//====================================================================================================================== // // This file is part of waLBerla. waLBerla is free software: you can // redistribute it and/or modify it under the terms of the GNU General Public // License as published by the Free Software Foundation, either version 3 of // the License, or (at your option) any later version. // // waLBerla is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License // for more details. // // You should have received a copy of the GNU General Public License along // with waLBerla (see COPYING.txt). If not, see . // //! \file //! \author Sebastian Eibl // //====================================================================================================================== //====================================================================================================================== // // THIS FILE IS GENERATED - PLEASE CHANGE THE TEMPLATE !!! // //====================================================================================================================== #pragma once #include #include #include #include namespace walberla { namespace mesa_pd { namespace kernel { /** * Kernel which calculates the Lennard Jones force between two particles. * * This kernel uses the type property of a particle to decide on the material parameters. * * This kernel requires the following particle accessor interface * \code {%- for prop in interface %} {%- if 'g' in prop.access %} * const {{prop.type}}& get{{prop.name | capFirst}}(const size_t p_idx) const; {%- endif %} {%- if 's' in prop.access %} * void set{{prop.name | capFirst}}(const size_t p_idx, const {{prop.type}}& v); {%- endif %} {%- if 'r' in prop.access %} * {{prop.type}}& get{{prop.name | capFirst}}Ref(const size_t p_idx); {%- endif %} * {%- endfor %} * \endcode * \ingroup mesa_pd_kernel */ class ForceLJ { public: ForceLJ(const uint_t numParticleTypes); ForceLJ(const ForceLJ& other) = default; ForceLJ(ForceLJ&& other) = default; ForceLJ& operator=(const ForceLJ& other) = default; ForceLJ& operator=(ForceLJ&& other) = default; template void operator()(const size_t p_idx, const size_t np_idx, Accessor& ac) const; {% for param in parameters %} /// assumes this parameter is symmetric void set{{param | capFirst}}(const size_t type1, const size_t type2, const real_t& val); {%- endfor %} {% for param in parameters %} real_t get{{param | capFirst}}(const size_t type1, const size_t type2) const; {%- endfor %} private: uint_t numParticleTypes_; {% for param in parameters %} std::vector {{param}} {}; {%- endfor %} }; ForceLJ::ForceLJ(const uint_t numParticleTypes) { numParticleTypes_ = numParticleTypes; {% for param in parameters %} {{param}}.resize(numParticleTypes * numParticleTypes, real_t(0)); {%- endfor %} } {% for param in parameters %} inline void ForceLJ::set{{param | capFirst}}(const size_t type1, const size_t type2, const real_t& val) { WALBERLA_ASSERT_LESS( type1, numParticleTypes_ ); WALBERLA_ASSERT_LESS( type2, numParticleTypes_ ); {{param}}[numParticleTypes_*type1 + type2] = val; {{param}}[numParticleTypes_*type2 + type1] = val; } {%- endfor %} {% for param in parameters %} inline real_t ForceLJ::get{{param | capFirst}}(const size_t type1, const size_t type2) const { WALBERLA_ASSERT_LESS( type1, numParticleTypes_ ); WALBERLA_ASSERT_LESS( type2, numParticleTypes_ ); WALBERLA_ASSERT_FLOAT_EQUAL( {{param}}[numParticleTypes_*type1 + type2], {{param}}[numParticleTypes_*type2 + type1], "parameter matrix for {{param}} not symmetric!"); return {{param}}[numParticleTypes_*type1 + type2]; } {%- endfor %} template inline void ForceLJ::operator()(const size_t p_idx, const size_t np_idx, Accessor& ac) const { static_assert(std::is_base_of::value, "please provide a valid accessor"); if (p_idx != np_idx) { Vec3 dir = ac.getPosition(p_idx) - ac.getPosition(np_idx); const real_t rsq = sqrLength(dir); const real_t sr2 = real_t(1.0) / rsq; const real_t sr2sigma = sr2 * getSigma(ac.getType(p_idx), ac.getType(np_idx)) * getSigma(ac.getType(p_idx), ac.getType(np_idx)); const real_t sr6 = sr2sigma * sr2sigma * sr2sigma; const real_t force = real_t(48) * sr6 * ( sr6 - real_t(0.5) ) * sr2 * getEpsilon(ac.getType(p_idx), ac.getType(np_idx)); const Vec3 f = force * dir; // Add normal force at contact point addForceAtomic( p_idx, ac, f ); addForceAtomic( np_idx, ac, -f ); } } } //namespace kernel } //namespace mesa_pd } //namespace walberla