diff --git a/src/mesa_pd/kernel/VBondModel/VBondContact.h b/src/mesa_pd/kernel/VBondModel/VBondContact.h new file mode 100644 index 0000000000000000000000000000000000000000..716fdc195b5382e0ce5820211e61d709963083e9 --- /dev/null +++ b/src/mesa_pd/kernel/VBondModel/VBondContact.h @@ -0,0 +1,164 @@ +//====================================================================================================================== +// +// 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 <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +//====================================================================================================================== +// +// THIS FILE IS GENERATED - PLEASE CHANGE THE TEMPLATE !!! +// +//====================================================================================================================== + +#pragma once + +#include <mesa_pd/common/ParticleFunctions.h> +#include <mesa_pd/data/DataTypes.h> +#include <mesa_pd/data/IAccessor.h> + +#include <core/math/Constants.h> +#include <core/logging/Logging.h> + +#include <vector> + +namespace walberla { +namespace mesa_pd { +namespace kernel { +namespace VBondModel { + +/** + * Advanced DEM kernel + */ +class VBondContact +{ +public: + template<typename Accessor> + void operator()(const size_t p_idx1, + const size_t p_idx2, + Accessor &ac); + + static constexpr real_t S = 142.7_r; // Area of the bond, + static constexpr real_t E = 1029_r * 0.006242_r; // Conversion from GPa to eV/A^3 + static constexpr real_t G = 459_r * 0.006242_r; + static constexpr real_t a = 2_r * 6.78_r; // (10,10) CNTS + static constexpr real_t J = 3480_r; + static constexpr real_t Jp = 2_r * J; + + // Stiffnesses, equilibrium length etc + static constexpr real_t B1 = E * S / a; // Need to calibrate + static constexpr real_t B2 = 12_r * E * J / a; + static constexpr real_t B3 = -2_r * E * J / a - G * Jp / (2_r * a); + static constexpr real_t B4 = G * Jp / a; + + Vector3<bool> isPeriodic_; + Vector3<int64_t> maxSegments_; + + + // Calibration through atomistic simulation + //constexpr real_t B1 = 60.1_r; + //constexpr real_t B2 = 17100_r; + //constexpr real_t B3 = 3610_r; + //constexpr real_t B4 = 1107_r; + + real_t U; + real_t U_1; + real_t U_2; + real_t U_3; + real_t U_4; +}; + +/** + * + * @tparam Accessor + * @param p_idx1 + * @param p_idx2 + * @param ac + * @return vdW adhesion energy + */ +template<typename Accessor> +inline +void VBondContact::operator()(const size_t p_idx1, + const size_t p_idx2, + Accessor &ac) +{ + Vec3 ri = ac.getPosition(p_idx1); + Vec3 rj = ac.getPosition(p_idx2); + + // Fix for the issue of segment's undefined sides + real_t sign = ac.getSegmentID(p_idx1) <= ac.getSegmentID(p_idx2) ? 1_r : -1_r; + if (((isPeriodic_[0]) && (std::abs(ac.getSegmentID(p_idx2) - ac.getSegmentID(p_idx1)) == maxSegments_[0] - 1)) or + ((isPeriodic_[1]) && (std::abs(ac.getSegmentID(p_idx2) - ac.getSegmentID(p_idx1)) == maxSegments_[1] - 1))) + sign = -sign; // special case for periodic fibers + + Vec3 ni1 = ac.getRotation(p_idx1).getMatrix() * Vec3(sign, 0_r, 0_r); + Vec3 ni2 = ac.getRotation(p_idx1).getMatrix() * Vec3(0_r, 1_r, 0_r); + Vec3 ni3 = ac.getRotation(p_idx1).getMatrix() * Vec3(0_r, 0_r, 1_r); + + Vec3 nj1 = ac.getRotation(p_idx2).getMatrix() * Vec3(-sign, 0_r, 0_r); + Vec3 nj2 = ac.getRotation(p_idx2).getMatrix() * Vec3(0_r, 1_r, 0_r); + Vec3 nj3 = ac.getRotation(p_idx2).getMatrix() * Vec3(0_r, 0_r, 1_r); + + // Vectors Dij and dij + Vec3 Dij = rj - ri; + real_t s = Dij.length(); + Vec3 dij = Dij * (1_r / s); + + real_t C = 1_r; + + /* + //srand(SID_1); + double AA = 0.2 + 0.2 * ((rand() % 1000)/1000); //strain of initiation of stress corrosion + //double BB = 0.01; // width of stress corrosion band + //double DD = 1. + AA/BB; + //double KK = 1 / BB; + //if (((std::fabs((s-a)/s))>AA)&&((std::fabs((s-a)/s))<=AA+BB)) C = DD - std::fabs((s-a)/s) * KK; + //if ((std::fabs((s-a)/s))>AA+BB) C = 0; + if ((std::fabs((s-a)/s))>AA) C = 0; + + // Potential energy + real_t U_1 = C * 0.5 * B1 * (s - a) * (s - a); + real_t U_2 = C * 0.5 * B2 * (nj1 - ni1) * dij + B2; + real_t U_3 = C * B3 * ni1 * nj1 + B3; + real_t U_4 = C * -0.5 * B4 * (ni2 * nj2 + ni3 * nj3) + B4; + real_t U = U_1 + U_2 + U_3 + U_4; + */ + U_1 = 0.5_r * B1 * (s - a) * (s - a); + U_2 = B2 * (0.5_r * (nj1 - ni1) * dij - 0.25_r * ni1 * nj1 + 0.75_r); + U_3 = (0.25_r * B2 + B3 + 0.5_r * B4) * (ni1 * nj1 + 1_r); + U_4 = -0.5_r * B4 * (ni1 * nj1 + ni2 * nj2 + ni3 * nj3 - 1_r); + U = U_1 + U_2 + U_3 + U_4; + + Vec3 rij = dij; + + Vec3 Fij = C * B1 * (s - a) * rij + B2 / (2_r * s) * ((nj1 - ni1) - ((nj1 - ni1) * dij) * dij); + Vec3 Fji = -Fij; + Vec3 M_TB = C * B3 * (nj1 % ni1) - 0.5_r * B4 * (nj2 % ni2 + nj3 % ni3); + Vec3 Mij = -C * 0.5_r * B2 * (dij % ni1) + M_TB; + Vec3 Mji = C * 0.5_r * B2 * (dij % nj1) - M_TB; + + addForceAtomic(p_idx1, ac, Fij); + addForceAtomic(p_idx2, ac, Fji); + addTorqueAtomic(p_idx1, ac, Mij); + addTorqueAtomic(p_idx2, ac, Mji); +} + +} //namespace VBondModel +} //namespace kernel +} //namespace mesa_pd +} //namespace walberla \ No newline at end of file diff --git a/tests/mesa_pd/CMakeLists.txt b/tests/mesa_pd/CMakeLists.txt index a70fa950fceca7f0436c010986e34ac9a28402a1..f68304f20998635dd73d1e213b2f8611d29f5d11 100644 --- a/tests/mesa_pd/CMakeLists.txt +++ b/tests/mesa_pd/CMakeLists.txt @@ -167,6 +167,9 @@ waLBerla_execute_test( NAME MESA_PD_Kernel_SyncNextNeighborsBlockForest PROCES waLBerla_compile_test( NAME MESA_PD_Kernel_TemperatureIntegration FILES kernel/TemperatureIntegration.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Kernel_TemperatureIntegration ) +waLBerla_compile_test( NAME MESA_PD_Kernel_VBondModel_VBondContact FILES kernel/VBondModel/VBondContact.test.cpp DEPENDS core ) +waLBerla_execute_test( NAME MESA_PD_Kernel_VBondModel_VBondContact ) + waLBerla_compile_test( NAME MESA_PD_Kernel_VBondModel_ViscousDamping FILES kernel/VBondModel/ViscousDamping.test.cpp DEPENDS core ) waLBerla_execute_test( NAME MESA_PD_Kernel_VBondModel_ViscousDamping ) diff --git a/tests/mesa_pd/kernel/VBondModel/VBondContact.test.cpp b/tests/mesa_pd/kernel/VBondModel/VBondContact.test.cpp new file mode 100644 index 0000000000000000000000000000000000000000..941b4c2856e21a877eb4553a2aeb9ef4ec07b3ca --- /dev/null +++ b/tests/mesa_pd/kernel/VBondModel/VBondContact.test.cpp @@ -0,0 +1,80 @@ +//====================================================================================================================== +// +// 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 <http://www.gnu.org/licenses/>. +// +//! \file +//! \author Igor Ostanin <i.ostanin@skoltech.ru> +//! \author Grigorii Drozdov <drozd013@umn.edu> +//! \author Sebastian Eibl <sebastian.eibl@fau.de> +// +//====================================================================================================================== + +#include <mesa_pd/data/ParticleAccessor.h> +#include <mesa_pd/data/ParticleStorage.h> + +#include <mesa_pd/kernel/VBondModel/VBondContact.h> + +#include <core/Environment.h> +#include <core/logging/Logging.h> + +#include <iostream> + +namespace walberla { +namespace mesa_pd { + +int main( int argc, char ** argv ) +{ + Environment env(argc, argv); + WALBERLA_UNUSED(env); + mpi::MPIManager::instance()->useWorldComm(); + + if (std::is_same<real_t, float>::value) + { + WALBERLA_LOG_WARNING("waLBerla build in sp mode: skipping test due to low precision"); + return EXIT_SUCCESS; + } + + //init data structures + auto ps = std::make_shared<data::ParticleStorage>(100); + + data::Particle&& p1 = *ps->create(); + p1.getPositionRef() = Vec3(0,0,0); + p1.getForceRef() = Vec3(0,0,0); + p1.getTypeRef() = 0; + + data::Particle&& p2 = *ps->create(); + p2.getPositionRef() = Vec3(0,0,0); + p2.getForceRef() = Vec3(0,0,0); + p2.getTypeRef() = 0; + + data::ParticleAccessor accessor(ps); + + //init kernels + kernel::VBondModel::VBondContact vbond; + + //check equilibrium distance + vbond(0, 1, accessor); + WALBERLA_CHECK_FLOAT_EQUAL( p1.getForce(), Vec3(0,0,0) ); + WALBERLA_CHECK_FLOAT_EQUAL( p2.getForce(), Vec3(0,0,0) ); + + return EXIT_SUCCESS; +} + +} //namespace mesa_pd +} //namespace walberla + +int main( int argc, char ** argv ) +{ + return walberla::mesa_pd::main(argc, argv); +}