PeriDEM 0.2.0
PeriDEM -- Peridynamics-based high-fidelity model for granular media
Loading...
Searching...
No Matches
materialUtil.cpp
Go to the documentation of this file.
1/*
2 * -------------------------------------------
3 * Copyright (c) 2021 - 2024 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 "materialUtil.h"
13#include "util/function.h"
14#include "util/parallelUtil.h"
15#include <iostream>
16#include <taskflow/taskflow/taskflow.hpp>
17#include <taskflow/taskflow/algorithm/for_each.hpp>
18
19namespace {
20
21double computeStateMxI(size_t i, const std::vector<util::Point> &nodes,
22 const std::vector<double> &nodal_vol,
23 const std::vector<std::vector<size_t>> &neighbors,
24 const std::vector<std::vector<float>> &neighbors_sq_dist,
25 const double &mesh_size,
27
28 double horizon = material->getHorizon();
29 const auto &xi = nodes[i];
30 double m = 0.;
31
32 // upper and lower bound for volume correction
33 auto check_up = horizon + 0.5 * mesh_size;
34 auto check_low = horizon - 0.5 * mesh_size;
35
36 size_t k = 0;
37 for (size_t j : neighbors[i]) {
38
39 const auto &xj = nodes[j];
40 double rji = (xj - xi).length();
41 //double rji = std::sqrt(neighbors_sq_dist[i][k]);
42
43 if (util::isGreater(rji, horizon)) // or j == i) <-- check! For weighted volume, we don't want to skip the node itself
44 continue;
45
46 // get corrected volume of node j
47 auto volj = nodal_vol[j];
48
49 if (util::isGreater(rji, check_low))
50 volj *= (check_up - rji) / mesh_size;
51
52 m += std::pow(rji, 2) * material->getInfFn(rji) * volj;
53
54 k++;
55 }
56
57 if (util::isLess(m, 1.0E-18)) {
58 std::ostringstream oss;
59 oss << "Error: Weighted nodal volume = " << m
60 << " should not be too close to zero.\n";
61
62 oss << "Mesh size = " << mesh_size << "\n";
63 oss << "J = " << material->getInfFn(0.5 * horizon) << "\n";
64 oss << "weighted volume (times 1.0e10) = " << m*1.e+10 << "\n";
65 oss << "nodal coord = " << xi.printStr() << "\n";
66 oss << material->printStr(0, 0);
67
68 std::cout << oss.str();
69
70 exit(1);
71 }
72 return m;
73}
74
75double computeStateThetaxI(size_t i, const std::vector<util::Point> &nodes,
76 const std::vector<util::Point> &nodes_disp,
77 const std::vector<double> &nodal_vol,
78 const std::vector<std::vector<size_t>> &neighbors,
79 const std::vector<std::vector<float>> &neighbors_sq_dist,
80 const double &mesh_size,
82 const geometry::Fracture *fracture,
83 const std::vector<double> &mx) {
84
85 double horizon = material->getHorizon();
86 const auto &xi = nodes[i];
87 const auto &ui = nodes_disp[i];
88 double m = mx[i];
89 double theta = 0.;
90
91 // upper and lower bound for volume correction
92 auto check_up = horizon + 0.5 * mesh_size;
93 auto check_low = horizon - 0.5 * mesh_size;
94
95 size_t k = 0;
96 for (size_t j : neighbors[i]) {
97
98 const auto &xj = nodes[j];
99 const auto &uj = nodes_disp[j];
100 double rji = (xj - xi).length();
101 //double rji = std::sqrt(neighbors_sq_dist[i][k]); // distance in
102 // reference configuration
103
104 if (util::isGreater(rji, horizon) or j == i)
105 continue;
106
107 // get corrected volume of node j
108 auto volj = nodal_vol[j];
109
110 if (util::isGreater(rji, check_low))
111 volj *= (check_up - rji) / mesh_size;
112
113 // get bond state
114 double bond_state = fracture->getBondState(i, k) ? 0. : 1.;
115
116 // get change in bond length
117 auto yi = xi + ui;
118 auto yj = xj + uj;
119 double change_length = (yj - yi).length() - rji;
120
121 theta += bond_state * rji * change_length *
122 material->getInfFn(rji) * volj;
123
124 k += 1;
125 }
126
127 return 3. * theta / m;
128}
129
130double computeHydrostaticStrainI(size_t i, const std::vector<util::Point> &nodes,
131 const std::vector<util::Point> &nodes_disp,
132 const std::vector<double> &nodal_vol,
133 const std::vector<std::vector<size_t>> &neighbors,
134 const std::vector<std::vector<float>> &neighbors_sq_dist,
135 const double &mesh_size,
137 const geometry::Fracture *fracture,
138 size_t dim) {
139
140 double horizon = material->getHorizon();
141 const auto &xi = nodes[i];
142 const auto &ui = nodes_disp[i];
143 double theta = 0.;
144
145 // upper and lower bound for volume correction
146 auto check_up = horizon + 0.5 * mesh_size;
147 auto check_low = horizon - 0.5 * mesh_size;
148
149 // get volume of ball
150 double vol_ball = std::pow(horizon, 2) * M_PI;
151 if (dim == 3)
152 vol_ball *= horizon * 4. / 3.;
153
154 size_t k = 0;
155 for (size_t j : neighbors[i]) {
156
157 const auto &xj = nodes[j];
158 const auto &uj = nodes_disp[j];
159 double rji = (xj - xi).length();
160 //double rji = std::sqrt(neighbors_sq_dist[i][k]);
161
162 if (util::isGreater(rji, horizon) or j == i)
163 continue;
164
165 // get corrected volume of node j
166 auto volj = nodal_vol[j];
167
168 if (util::isGreater(rji, check_low))
169 volj *= (check_up - rji) / mesh_size;
170
171 // get bond state
172 double bond_state = fracture->getBondState(i, k) ? 0. : 1.;
173
174 // get bond strain
175 double Sji = material->getS(xj - xi, uj - ui);
176
177 theta += bond_state * rji * Sji *
178 material->getInfFn(rji) * volj / vol_ball;
179
180 k += 1;
181 }
182
183 return theta;
184}
185
186void updateBondFractureDataI(size_t i, const std::vector<util::Point> &nodes,
187 const std::vector<std::vector<size_t>> &neighbors,
188 const std::vector<util::Point> &nodes_disp,
190 geometry::Fracture *fracture) {
191
192 size_t k = 0;
193 for (size_t j : neighbors[i]) {
194
195 double s = material->getS(nodes[j] - nodes[i], nodes_disp[j] -
196 nodes_disp[i]);
197 double sc = material->getSc((nodes[j] - nodes[i]).length());
198
199 // get fracture state, modify, and set
200 auto fs = fracture->getBondState(i, k);
201 if (!fs && util::isGreater(std::abs(s), sc + 1.0e-10))
202 fs = true;
203 fracture->setBondState(i, k, fs);
204
205 k += 1;
206 }
207}
208
209} // anonymous namespace
210
211void material::computeStateMx(model::ModelData *model, bool compute_in_parallel) {
212
213 model->d_mX.resize(model->d_x.size());
214 if (!compute_in_parallel) {
215 for (size_t i = 0; i < model->d_x.size(); i++) {
216 const auto &pti = model->getPtId(i);
217 const auto &particle = model->getParticleFromAllList(pti);
218 auto mx = computeStateMxI(i, model->d_xRef, model->d_vol,
219 model->d_neighPd, model->d_neighPdSqdDist,
220 particle->getMeshSize(),
221 particle->getMaterial());
222
223 model->setMx(i, mx);
224 }
225 } else {
226
227 tf::Executor executor(util::parallel::getNThreads());
228 tf::Taskflow taskflow;
229
230 taskflow.for_each_index(
231 (std::size_t) 0, model->d_x.size(), (std::size_t) 1, [model](std::size_t i) {
232 const auto &pti = model->getPtId(i);
233 const auto &particle = model->getParticleFromAllList(pti);
234 auto mx = computeStateMxI(i, model->d_xRef, model->d_vol,
235 model->d_neighPd, model->d_neighPdSqdDist,
236 particle->getMeshSize(),
237 particle->getMaterial());
238
239 model->setMx(i, mx);
240 }
241 ); // for_each
242
243 executor.run(taskflow).get();
244 }
245}
246
247void material::computeStateThetax(model::ModelData *model, bool compute_in_parallel) {
248
249 model->d_thetaX.resize(model->d_x.size());
250 if (!compute_in_parallel) {
251 for (size_t i = 0; i < model->d_x.size(); i++) {
252 const auto &pti = model->getPtId(i);
253 const auto &particle = model->getParticleFromAllList(pti);
254
255 auto thetax = computeStateThetaxI(i, model->d_xRef, model->d_u,
256 model->d_vol,
257 model->d_neighPd, model->d_neighPdSqdDist,
258 particle->getMeshSize(),
259 particle->getMaterial(),
260 model->d_fracture_p.get(),
261 model->d_mX);
262
263 model->setThetax(i, thetax);
264
265 }
266
267 } else {
268
269 tf::Executor executor(util::parallel::getNThreads());
270 tf::Taskflow taskflow;
271
272 taskflow.for_each_index(
273 (std::size_t) 0, model->d_x.size(), (std::size_t) 1, [model](std::size_t i) {
274 const auto &pti = model->getPtId(i);
275 const auto &particle = model->getParticleFromAllList(pti);
276
277 auto thetax = computeStateThetaxI(i, model->d_xRef, model->d_u,
278 model->d_vol,
279 model->d_neighPd, model->d_neighPdSqdDist,
280 particle->getMeshSize(),
281 particle->getMaterial(),
282 model->d_fracture_p.get(),
283 model->d_mX);
284
285 model->setThetax(i, thetax);
286 }
287 ); // for_each
288
289 executor.run(taskflow).get();
290 }
291}
292
294
295 model->d_thetaX.resize(model->d_x.size());
296 if (!compute_in_parallel) {
297 for (size_t i = 0; i < model->d_x.size(); i++) {
298 const auto &pti = model->getPtId(i);
299 const auto &particle = model->getParticleFromAllList(pti);
300
301 auto thetax = computeHydrostaticStrainI(i, model->d_xRef, model->d_u,
302 model->d_vol,
303 model->d_neighPd, model->d_neighPdSqdDist,
304 particle->getMeshSize(),
305 particle->getMaterial(),
306 model->d_fracture_p.get(),
307 particle->getDimension());
308
309 model->setThetax(i, thetax);
310 }
311 } else {
312
313 tf::Executor executor(util::parallel::getNThreads());
314 tf::Taskflow taskflow;
315
316 taskflow.for_each_index(
317 (std::size_t) 0, model->d_x.size(), (std::size_t) 1, [model](std::size_t i) {
318 const auto &pti = model->getPtId(i);
319 const auto &particle = model->getParticleFromAllList(pti);
320
321 auto thetax = computeHydrostaticStrainI(i,
322 model->d_xRef,
323 model->d_u,
324 model->d_vol,
325 model->d_neighPd, model->d_neighPdSqdDist,
326 particle->getMeshSize(),
327 particle->getMaterial(),
328 model->d_fracture_p.get(),
329 particle->getDimension());
330
331 model->setThetax(i, thetax);
332 }
333 ); // for_each
334
335 executor.run(taskflow).get();
336 }
337
338}
339
341
342 if (!compute_in_parallel) {
343 for (size_t i = 0; i < model->d_x.size(); i++) {
344 const auto &pti = model->getPtId(i);
345 const auto &particle = model->getParticleFromAllList(pti);
346
347 updateBondFractureDataI(i, model->d_xRef, model->d_neighPd, model->d_u,
348 particle->getMaterial(),
349 model->d_fracture_p.get());
350 }
351 } else {
352
353 tf::Executor executor(util::parallel::getNThreads());
354 tf::Taskflow taskflow;
355
356 taskflow.for_each_index(
357 (std::size_t) 0, model->d_x.size(), (std::size_t) 1, [model](std::size_t i) {
358 const auto &pti = model->getPtId(i);
359 const auto &particle = model->getParticleFromAllList(pti);
360
361 updateBondFractureDataI(i,
362 model->d_xRef,
363 model->d_neighPd,
364 model->d_u,
365 particle->getMaterial(),
366 model->d_fracture_p.get());
367 }
368 ); // for_each
369
370 executor.run(taskflow).get();
371 }
372}
A class for fracture state of bonds.
Definition fracture.h:26
void setBondState(const std::size_t &i, const std::size_t &j, const bool &state)
Sets the bond state.
Definition fracture.cpp:51
bool getBondState(const std::size_t &i, const std::size_t &j) const
Read bond state.
Definition fracture.cpp:64
Collection of methods and database related to peridynamic material.
Definition material.h:76
A class to store model data.
Definition modelData.h:47
void updateBondFractureDataI(size_t i, const std::vector< util::Point > &nodes, const std::vector< std::vector< size_t > > &neighbors, const std::vector< util::Point > &nodes_disp, const material::Material *material, geometry::Fracture *fracture)
double computeHydrostaticStrainI(size_t i, const std::vector< util::Point > &nodes, const std::vector< util::Point > &nodes_disp, const std::vector< double > &nodal_vol, const std::vector< std::vector< size_t > > &neighbors, const std::vector< std::vector< float > > &neighbors_sq_dist, const double &mesh_size, const material::Material *material, const geometry::Fracture *fracture, size_t dim)
double computeStateThetaxI(size_t i, const std::vector< util::Point > &nodes, const std::vector< util::Point > &nodes_disp, const std::vector< double > &nodal_vol, const std::vector< std::vector< size_t > > &neighbors, const std::vector< std::vector< float > > &neighbors_sq_dist, const double &mesh_size, const material::Material *material, const geometry::Fracture *fracture, const std::vector< double > &mx)
double computeStateMxI(size_t i, const std::vector< util::Point > &nodes, const std::vector< double > &nodal_vol, const std::vector< std::vector< size_t > > &neighbors, const std::vector< std::vector< float > > &neighbors_sq_dist, const double &mesh_size, const material::Material *material)
void computeStateThetax(model::ModelData *model, bool compute_in_parallel=false)
void computeStateMx(model::ModelData *model, bool compute_in_parallel=false)
Computes the moment term in state-based peridynamic formulation.
void computeHydrostaticStrain(model::ModelData *model, bool compute_in_parallel=false)
void updateBondFractureData(model::ModelData *model, bool compute_in_parallel=false)
Collection of methods and data related to particle object.
unsigned int getNThreads()
Get number of threads to be used by taskflow.
bool isGreater(const double &a, const double &b)
Returns true if a > b.
Definition function.cpp:15
bool isLess(const double &a, const double &b)
Returns true if a < b.
Definition function.cpp:20