PeriDEM 0.3.0
PeriDEM -- Peridynamics-based high-fidelity model for granular media
Loading...
Searching...
No Matches
wallContact.cpp
Go to the documentation of this file.
1/*
2 * -------------------------------------------
3 * Copyright (c) 2021 - 2026 Prashant K. Jha
4 * -------------------------------------------
5 * PeriDEM https://github.com/prashjha/PeriDEM
6 *
7 * Distributed under the Boost Software License, Version 1.0. (See accompanying
8 * file LICENSE)
9 */
10
11#include "wallContact.h"
12
13#include "data/modelData.h"
14#include "geom/geomObjects.h"
15#include "inp/contactPairDeck.h"
17#include "util/function.h"
18#include "util/parallelUtil.h"
19
20#include <cmath>
21#include <stdexcept>
22#include <taskflow/taskflow/algorithm/for_each.hpp>
23#include <taskflow/taskflow/taskflow.hpp>
24
25namespace contact {
26
28
30 bool use_node_damping) const {
31 if (data.d_particlesListTypeWall.empty())
32 return;
33
34 const unsigned n_workers = util::parallel::getNThreads();
35 tf::Executor executor(n_workers);
36 tf::Taskflow taskflow;
37
38 taskflow.for_each_index(
39 (std::size_t)0, data.d_fContCompNodes.size(), (std::size_t)1,
40 [&data, use_node_damping](std::size_t II) {
41 const auto i = data.d_fContCompNodes[II];
42 const auto &ptIdi = data.getPtId(i);
43 auto &pi = data.getParticleFromAllList(ptIdi);
44 if (pi->isWall())
45 return;
46
47 const auto &yi = data.d_x[i];
48 const auto &vi = data.d_v[i];
49 const double voli = data.d_vol[i];
50 util::Point force_i;
51
52 for (auto *wall : data.d_particlesListTypeWall) {
53 if (!wall || !wall->d_geom_p)
54 continue;
55
56 geom::WallContactHit hit;
57 if (!wall->d_geom_p->wallContactQuery(yi, hit) || !hit.active)
58 continue;
59
60 const auto &contact =
61 data.d_particleDeck_p->d_contactDeck.getContact(
62 pi->getGroupId("contact_id"),
63 wall->getGroupId("contact_id"));
64
65 // Signed gap from geom (positive = free space). Contact when gap < Rc.
66 const double R = hit.signed_gap;
67 if (!util::isLess(R, contact.d_contactR))
68 continue;
69
70 // en points from grain toward wall (into the material).
71 const util::Point en = -1. * hit.outward_n;
72 auto scalar_f = contact.d_Kn * (R - contact.d_contactR) * voli;
73 if (scalar_f > 0.)
74 scalar_f = 0.;
75
76 util::Point f = scalar_f * en;
77
78 if (contact.d_frictionOn) {
79 const util::Point vji = -1. * vi; // wall velocity ~ 0
80 const double vn = vji * en;
81 util::Point et = vji - vn * en;
82 if (util::isGreater(et.length(), 0.))
83 et = et / et.length();
84 else
85 et = util::Point();
86 f += contact.d_mu * scalar_f * et;
87 }
88
89 if (use_node_damping && contact.d_dampingOn && voli > 0. &&
90 contact.d_K > 0. && contact.d_contactR > 0.) {
91 const util::Point vji = -1. * vi;
92 const double vn = vji * en;
93 if (util::isLess(vn, 0.)) {
94 const double meq =
95 util::equivalentMass(pi->getDensity() * voli,
96 wall->getDensity() * voli);
97 const double beta_n =
98 contact.d_betan *
99 std::sqrt(contact.d_K * contact.d_contactR * meq);
100 f += (beta_n * vn / voli) * en;
101 }
102 }
103
104 force_i += f;
105 }
106
107 data.d_f[i] += force_i;
108 });
109
110 executor.run(taskflow).get();
111}
112
113std::unique_ptr<WallContact> makeWallContact(const std::string &name) {
114 if (name == "meshed")
115 return std::make_unique<MeshedWallContact>();
116 if (name == "analytical_plane")
117 return std::make_unique<AnalyticalPlaneWallContact>();
118 throw std::runtime_error(
119 "Unknown Model.Wall_Contact '" + name +
120 "'. Supported: meshed, analytical_plane.");
121}
122
123} // namespace contact
void apply(data::ModelData &data, PairForce *pair, bool use_node_damping) const override
void apply(data::ModelData &data, PairForce *pair, bool use_node_damping) const override
A class to store model data.
Definition modelData.h:50
std::unique_ptr< WallContact > makeWallContact(const std::string &name)
Definition contact.h:20
unsigned int getNThreads()
Get number of threads to be used by taskflow.