From de0056ff2ee7243f3f855f6aca0159a3c82d0bc5 Mon Sep 17 00:00:00 2001 From: Samuel Kemmler <samuel.kemmler@fau.de> Date: Wed, 12 Apr 2023 17:10:35 +0200 Subject: [PATCH] Add cohesion to PipingErosion.cpp --- .../showcases/PipingErosion/PipingErosion.cpp | 118 +++++++++++++++--- 1 file changed, 101 insertions(+), 17 deletions(-) diff --git a/apps/showcases/PipingErosion/PipingErosion.cpp b/apps/showcases/PipingErosion/PipingErosion.cpp index b2cd6b4fe..0821ff370 100644 --- a/apps/showcases/PipingErosion/PipingErosion.cpp +++ b/apps/showcases/PipingErosion/PipingErosion.cpp @@ -70,6 +70,8 @@ #include "mesa_pd/data/shape/Sphere.h" #include "mesa_pd/domain/BlockForestDataHandling.h" #include "mesa_pd/domain/BlockForestDomain.h" +#include "mesa_pd/kernel/Cohesion.h" +#include "mesa_pd/kernel/CohesionInitialization.h" #include "mesa_pd/kernel/DoubleCast.h" #include "mesa_pd/kernel/LinearSpringDashpot.h" #include "mesa_pd/kernel/ParticleSelector.h" @@ -86,6 +88,8 @@ #include "vtk/all.h" +#include "../apps/bam/Utility.h" + namespace fluidized_bed { @@ -347,7 +351,7 @@ void initSpheresFromFile(const std::string& filename, walberla::mesa_pd::data::P pIt->getBaseShapeRef()->updateMassAndInertia(density);*/ pIt->setInteractionRadius(diameter / 2); pIt->setOwner(rank); - pIt->setType(1); + pIt->setType(0); numParticles++; @@ -555,7 +559,7 @@ int main( int argc, char **argv ) // in simulation units: dt = 1, dx = 1, densityFluid = 1 const real_t dt_SI = uOutflow / uOutflow_SI * dx_SI; - const real_t diameter = 10; // average diameter from bed generation TODO: remove hard coded diameter + const real_t diameter = 15; // average diameter from bed generation TODO: remove hard coded diameter const real_t viscosity = kinematicViscosityFluid_SI * dt_SI / ( dx_SI * dx_SI ); const real_t omega = lbm::collision_model::omegaFromViscosity(viscosity); const real_t gravitationalAcceleration = gravitationalAcceleration_SI * dt_SI * dt_SI / dx_SI; @@ -725,6 +729,78 @@ int main( int argc, char **argv ) return ac.getShapeID(particleIdx) == boxShape; }, *accessor, particleMappingKernel, *accessor, NoSlip_Flag); + // cohesion init + mesa_pd::kernel::CohesionInitialization cohesionInitKernel; + mesa_pd::kernel::Cohesion cohesionKernel(2); + + real_t densityFluid_SI = real_t(1000); + real_t diameter_SI = real_t(0.0029); // m + real_t densityParticle_SI = real_t(2550); + real_t y_n_SI = 200_r; // N = tensile force, where bond breaks + real_t frictionCoefficient = real_t(0.3); + + real_t sphereRadius_SI = diameter_SI / 2_r; + real_t sphereVolume_SI = 4_r / 3_r * math::pi * sphereRadius_SI * sphereRadius_SI * sphereRadius_SI; + real_t sphereMass_SI = densityParticle_SI * sphereVolume_SI; + real_t E_SI = 1e3_r; // kg / (m * s^2) + real_t en = 0.2_r; // coefficient of restitution + real_t kn_SI = 2_r * E_SI * (sphereRadius_SI * sphereRadius_SI / (sphereRadius_SI + sphereRadius_SI)); + real_t meff_SI = sphereMass_SI * sphereMass_SI / (sphereMass_SI + sphereMass_SI); + real_t damping = -std::log(en) / std::sqrt((std::log(en) * std::log(en) + math::pi * math::pi)); + real_t nun_SI = 2_r * std::sqrt(kn_SI * meff_SI) * damping; + + real_t kn = kn_SI / (densityFluid_SI * dx_SI * dx_SI * dx_SI / (dt_SI * dt_SI)); + real_t nun = nun_SI / (densityFluid_SI * dx_SI * dx_SI * dx_SI / (dt_SI)); + real_t y_n = y_n_SI / (densityFluid_SI * dx_SI * dx_SI * dx_SI * dx_SI / (dt_SI * dt_SI)); + + real_t ksFactors = 0.5_r; // - + real_t krFactors = 0.1_r; // - + real_t koFactors = 0.1_r; // - + + real_t nusFactor = 0_r; // - + real_t nurFactor = 0_r; // - + real_t nuoFactor = 0_r; // - + + real_t y_s = 0.5_r * y_n; + real_t y_r = 0.1_r * y_n / dx_SI; // TODO check -> torsion = N m + real_t y_o = 0.1_r * y_n / dx_SI; // TODO check -> torsion = N m + + WALBERLA_LOG_INFO_ON_ROOT("kn = " << kn << ", nun = " << nun << ", yn = " << y_n); + WALBERLA_LOG_INFO_ON_ROOT("Estimated maximum surface distance for rupture / radius= " << (y_n / kn) / + (diameter / 2)); + cohesionKernel.setKn(0,0,kn); + cohesionKernel.setKsFactor(0,0,ksFactors); + cohesionKernel.setKrFactor(0,0,krFactors); + cohesionKernel.setKoFactor(0,0,koFactors); + + cohesionKernel.setNun(0,0,nun); + cohesionKernel.setNusFactor(0,0,nusFactor); + cohesionKernel.setNurFactor(0,0,nurFactor); + cohesionKernel.setNuoFactor(0,0,nuoFactor); + + cohesionKernel.setFrictionCoefficient(0,0,frictionCoefficient); + + cohesionKernel.setYn(0,0,y_n); + cohesionKernel.setYs(0,0,y_s); + cohesionKernel.setYr(0,0,y_r); + cohesionKernel.setYo(0,0,y_o); + + mesa_pd::SelectSphere sphereSelector; + ps->forEachParticlePairHalf(false, sphereSelector, *accessor, [&](const size_t idx1, const size_t idx2) { + mesa_pd::collision_detection::AnalyticContactDetection acd; + mesa_pd::kernel::DoubleCast double_cast; + mesa_pd::mpi::ContactFilter contact_filter; + if (double_cast(idx1, idx2, *accessor, acd, *accessor)) + { + // particles overlap + if (contact_filter(acd.getIdx1(), acd.getIdx2(), *accessor, acd.getContactPoint(), *rpdDomain)) + { + cohesionInitKernel(acd.getIdx1(), acd.getIdx2(), *accessor, acd.getPenetrationDepth()); + } + } + }); + reduceAndSwapContactHistory(*ps); + // setup of the LBM communication for synchronizing the pdf field between neighboring blocks blockforest::communication::UniformBufferedScheme< Stencil_T > optimizedPDFCommunicationScheme( blocks ); optimizedPDFCommunicationScheme.addPackInfo( make_shared< lbm::PdfFieldPackInfo< LatticeModel_T > >( pdfFieldID ) ); // optimized sync @@ -869,26 +945,34 @@ int main( int argc, char **argv ) // collision response - ps->forEachParticlePairHalf(useOpenMP, ExcludeGlobalGlobal(), *accessor, - [&collisionResponse, &rpdDomain, timeStepSizeRPD, coefficientOfRestitution, particleCollisionTime, kappa, particleVolume, particleDensityRatio] - (const size_t idx1, const size_t idx2, auto& ac) + ps->forEachParticlePairHalf(false, ExcludeGlobalGlobal(), *accessor, [&](size_t idx1, size_t idx2) { + mesa_pd::collision_detection::AnalyticContactDetection acd; + mesa_pd::kernel::DoubleCast double_cast; + mesa_pd::mpi::ContactFilter contact_filter; + bool contactExists = double_cast(idx1, idx2, *accessor, acd, *accessor); + + Vector3< real_t > filteringPoint; + if (contactExists) { filteringPoint = acd.getContactPoint();} + else { filteringPoint = (accessor->getPosition(idx1) + accessor->getPosition(idx2)) / real_t(2); } + + if (contact_filter(idx1, idx2, *accessor, filteringPoint, *rpdDomain)) { - mesa_pd::collision_detection::AnalyticContactDetection acd; - mesa_pd::kernel::DoubleCast double_cast; - mesa_pd::mpi::ContactFilter contact_filter; - if (double_cast(idx1, idx2, ac, acd, ac )) + bool contactTreatedByCohesionKernel = false; + if (sphereSelector(idx1, idx2, *accessor)) { - if (contact_filter(acd.getIdx1(), acd.getIdx2(), ac, acd.getContactPoint(), *rpdDomain)) + if (cohesionKernel.isCohesiveBondActive(idx1, idx2, *accessor)) { - auto meff_sphere_wall = particleVolume * particleDensityRatio; - auto meff_sphere_sphere = real_t(1) / (ac.getInvMass(idx1) + ac.getInvMass(idx2)); - collisionResponse.setStiffnessAndDamping(0,1,coefficientOfRestitution, particleCollisionTime, kappa, meff_sphere_wall); - collisionResponse.setStiffnessAndDamping(1,1,coefficientOfRestitution, particleCollisionTime, kappa, meff_sphere_sphere); - collisionResponse(acd.getIdx1(), acd.getIdx2(), ac, acd.getContactPoint(), acd.getContactNormal(), acd.getPenetrationDepth(), timeStepSizeRPD); + contactTreatedByCohesionKernel = cohesionKernel(idx1, idx2, *accessor, timeStepSizeRPD); } } - }, - *accessor ); + if (contactExists && !contactTreatedByCohesionKernel) + { + cohesionKernel.nonCohesiveInteraction(acd.getIdx1(), acd.getIdx2(), *accessor, acd.getContactPoint(), + acd.getContactNormal(), acd.getPenetrationDepth(), + timeStepSizeRPD); + } + } + }); reduceAndSwapContactHistory(*ps); -- GitLab