PeriDEM 0.3.0
PeriDEM -- Peridynamics-based high-fidelity model for granular media
Loading...
Searching...
No Matches
contact::Damping Class Reference

#include <damping.h>

Collaboration diagram for contact::Damping:

Public Member Functions

virtual ~Damping ()=default
 
virtual void apply (data::ModelData &data)
 

Detailed Description

Center-center and particle-wall damping. Not part of the node-node pair law. Contact applies this after pair assembly if d_damping is set. Subclass to change or add damping; pass nullptr to skip.

Selected by Contact.Damping_Law:

  • com_and_node (default): this COM path + node damping in the pair law
  • com: this COM path only
  • node: node damping only (no COM object)
  • off: neither

Definition at line 31 of file damping.h.

Constructor & Destructor Documentation

◆ ~Damping()

virtual contact::Damping::~Damping ( )
virtualdefault

Member Function Documentation

◆ apply()

void contact::Damping::apply ( data::ModelData data)
virtual

Definition at line 25 of file damping.cpp.

25 {
26 util::io::log(3, " Computing normal damping force \n");
27 const int mpi_rank = util::parallel::mpiRank();
28 for (auto &pi : data.d_particlesListTypeParticle) {
29
30 if (!pi->d_computeForce)
31 continue;
32 // Particle-MPI: one rank owns each grain. DOF-MPI: every rank may own
33 // some nodes of any grain — compute here, deposit only on owned nodes.
34 if (!data.d_pdDofMpi && !particle::isLocallyOwned(*pi))
35 continue;
36
37 auto pi_id = pi->getId();
38
39 double Ri = pi->d_geom_p->boundingRadius();
40 double vol_pi = M_PI * Ri * Ri;
41 auto pi_xc = pi->getXCenter();
42 auto pi_vc = pi->getVCenter();
43 auto rhoi = pi->getDensity();
44 util::Point force_i = util::Point();
45
46 for (auto &pj : data.d_particlesListTypeParticle) {
47 if (pj->getId() != pi->getId()) {
48 auto Rj = pj->d_geom_p->boundingRadius();
49 auto xc_ji = pj->getXCenter() - pi_xc;
50 auto dist_xcji = xc_ji.length();
51
52 const auto &contact = data.d_particleDeck_p->d_contactDeck.getContact(pi->getGroupId("contact_id"), pj->getGroupId("contact_id"));
53
54 if (!contact.d_dampingOn)
55 continue;
56
57 if (util::isLess(dist_xcji, Rj + Ri + 1.01 * contact.d_contactR)) {
58
59 auto vol_pj = M_PI * Rj * Rj;
60 auto rhoj = pj->getDensity();
61 auto meq = util::equivalentMass(rhoi * vol_pi, rhoj * vol_pj);
62
63 auto beta_n = contact.d_betan *
64 std::sqrt(contact.d_K * contact.d_contactR * meq);
65
66 auto hat_xc_ji = util::Point();
67 if (util::isGreater(dist_xcji, 0.))
68 hat_xc_ji = xc_ji / dist_xcji;
69 else
70 hat_xc_ji = util::Point();
71
72 auto vc_ji = pj->getVCenter() - pi_vc;
73 auto vc_mag = vc_ji * hat_xc_ji;
74 if (vc_mag > 0.)
75 vc_mag = 0.;
76
77 force_i += beta_n * vc_mag * hat_xc_ji / vol_pi;
78 }
79 }
80 }
81
82 data.d_neighWallNodesCondensed[pi->getId()].clear();
83 {
84 for (size_t j=0; j<data.d_neighWallNodes[pi_id].size(); j++) {
85
86 const auto &j_id = pi->getNodeId(j);
87 const auto &yj = data.d_x[j_id];
88
89 for (size_t k=0; k<data.d_neighWallNodes[pi_id][j].size(); k++) {
90
91 const auto &k_id = data.d_neighWallNodes[pi_id][j][k];
92 const auto &pk = data.d_particlesListTypeAll[data.d_ptId[k_id]];
93
94 double Rjk = (data.d_x[k_id] - yj).length();
95
96 const auto &contact =
97 data.d_particleDeck_p->d_contactDeck.getContact(pi->getGroupId("contact_id"), pk->getGroupId("contact_id"));
98
99 if (util::isLess(Rjk, contact.d_contactR))
100 util::methods::addToList(k_id, data.d_neighWallNodesCondensed[pi_id]);
101
102 }
103 }
104 }
105
106 for (auto &j : data.d_neighWallNodesCondensed[pi_id]) {
107
108 auto &ptIdj = data.d_ptId[j];
109 auto &pj = data.d_particlesListTypeAll[ptIdj];
110 auto meq = rhoi * vol_pi;
111
112 const auto &contact
113 = data.d_particleDeck_p->d_contactDeck.getContact(pi->getGroupId("contact_id"), pj->getGroupId("contact_id"));
114
115 if (!contact.d_dampingOn)
116 continue;
117
118 auto beta_n = contact.d_betan *
119 std::sqrt(contact.d_K * contact.d_contactR * meq);
120
121 auto xc_ji = data.d_x[j] - pi_xc;
122 auto hat_xc_ji = util::Point();
123 if (util::isGreater(xc_ji.length(), 0.))
124 hat_xc_ji = xc_ji / xc_ji.length();
125
126 auto vc_ji = data.d_v[j] - pi_vc;
127 auto vc_mag = vc_ji * hat_xc_ji;
128 if (vc_mag > 0.)
129 vc_mag = 0.;
130
131 force_i += beta_n * vc_mag * hat_xc_ji / vol_pi;
132 }
133
134 for (size_t i = 0; i < pi->getNumNodes(); i++) {
135 const size_t g = pi->getNodeId(i);
136 if (data.d_pdDofMpi &&
137 (data.d_pdNodePartition.size() != data.d_x.size() ||
138 static_cast<int>(data.d_pdNodePartition[g]) != mpi_rank))
139 continue;
140 data.d_f[g] += force_i;
141 }
142 }
143}
Definition contact.h:20
bool isLocallyOwned(const BaseParticle &p)
True if this rank updates / assembles forces for the particle. Walls are replicated on every rank....
void log(std::ostringstream &oss, bool screen_out=false, int printMpiRank=print_default_mpi_rank)
Global method to log the message.
Definition io.cpp:41
void addToList(const T &i, std::vector< T > &list)
Add element to the list.
Definition vecMethods.h:289
int mpiRank()
get rank (id) of this processor
bool isGreater(const double &a, const double &b)
Returns true if a > b.
Definition function.cpp:15
double equivalentMass(const double &m1, const double &m2)
Compute harmonic mean of m1 and m2.
Definition function.cpp:127
bool isLess(const double &a, const double &b)
Returns true if a < b.
Definition function.cpp:20
A structure to represent 3d vectors.
Definition point.h:30

References util::methods::addToList(), util::equivalentMass(), util::isGreater(), util::isLess(), particle::isLocallyOwned(), util::io::log(), and util::parallel::mpiRank().

Here is the call graph for this function:

The documentation for this class was generated from the following files: