30 bool use_node_damping)
const {
31 if (
data.d_particlesListTypeWall.empty())
35 tf::Executor executor(n_workers);
36 tf::Taskflow taskflow;
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);
47 const auto &yi = data.d_x[i];
48 const auto &vi = data.d_v[i];
49 const double voli = data.d_vol[i];
52 for (auto *wall : data.d_particlesListTypeWall) {
53 if (!wall || !wall->d_geom_p)
56 geom::WallContactHit hit;
57 if (!wall->d_geom_p->wallContactQuery(yi, hit) || !hit.active)
61 data.d_particleDeck_p->d_contactDeck.getContact(
62 pi->getGroupId(
"contact_id"),
63 wall->getGroupId(
"contact_id"));
66 const double R = hit.signed_gap;
67 if (!util::isLess(R, contact.d_contactR))
71 const util::Point en = -1. * hit.outward_n;
72 auto scalar_f = contact.d_Kn * (R - contact.d_contactR) * voli;
76 util::Point f = scalar_f * en;
78 if (contact.d_frictionOn) {
79 const util::Point vji = -1. * vi;
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();
86 f += contact.d_mu * scalar_f * et;
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.)) {
95 util::equivalentMass(pi->getDensity() * voli,
96 wall->getDensity() * voli);
99 std::sqrt(contact.d_K * contact.d_contactR * meq);
100 f += (beta_n * vn / voli) * en;
107 data.d_f[i] += force_i;
110 executor.run(taskflow).get();