PeriDEM 0.3.0
PeriDEM -- Peridynamics-based high-fidelity model for granular media
Loading...
Searching...
No Matches
meshUtil.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 "meshUtil.h"
12#include "util/io.h"
13#include <stdexcept>
14#include "mesh.h"
15#include "fe/elemIncludes.h"
16#include "fe/bMatrix.h"
17#include "util/feElementDefs.h"
18#include "util/parallelUtil.h"
19#include "util/function.h"
20
21#include <format>
22#include <memory>
23
24#include <taskflow/taskflow/taskflow.hpp>
25#include <taskflow/taskflow/algorithm/for_each.hpp>
26#include <cstdlib>
27#include <iostream>
28
29namespace {
30
32 const std::vector<util::Point> &u) {
33 std::vector<double> uflat(B.nDof());
34 const int dim = B.dim();
35 for (size_t a = 0; a < u.size(); a++) {
36 uflat[dim * static_cast<int>(a)] = u[a][0];
37 if (dim > 1)
38 uflat[dim * static_cast<int>(a) + 1] = u[a][1];
39 if (dim > 2)
40 uflat[dim * static_cast<int>(a) + 2] = u[a][2];
41 }
42 std::vector<double> e(B.nStrain(), 0.);
43 for (int i = 0; i < B.nStrain(); i++)
44 for (int j = 0; j < B.nDof(); j++)
45 e[i] += B(i, j) * uflat[j];
47 s(0, 0) = e[0];
48 if (dim > 1) {
49 s(1, 1) = e[1];
50 s(0, 1) = (dim == 2) ? e[2] : e[5];
51 }
52 if (dim > 2) {
53 s(2, 2) = e[2];
54 s(1, 2) = e[3];
55 s(0, 2) = e[4];
56 }
57 return s;
58}
59
60} // namespace
61
62namespace mesh {
63
64void createUniformMesh(mesh::Mesh *mesh_p, size_t dim, std::pair<std::vector<double>, std::vector<double>> box, std::vector<size_t> nGrid) {
65
66 mesh_p->d_dim = dim;
67 if (nGrid.size() < dim or box.first.size() < dim or box.second.size() < dim) {
68 throw std::runtime_error(
70 << "createUniformMesh(): check nGrid or box arguments.\n");
71 }
72
73 if (dim == 1) {
74 mesh_p->d_bbox.first = std::vector<double>{box.first[0], 0., 0.};
75 mesh_p->d_bbox.second = std::vector<double>{box.second[0], 0., 0.};
76 mesh_p->d_numNodes = (nGrid[0] + 1);
77 mesh_p->d_numElems = nGrid[0];
79 } else if (dim == 2) {
80 mesh_p->d_bbox.first = std::vector<double>{box.first[0], box.first[1], 0.};
81 mesh_p->d_bbox.second = std::vector<double>{box.second[0], box.second[1], 0.};
82 mesh_p->d_numNodes = (nGrid[0] + 1) * (nGrid[1] + 1);
83 mesh_p->d_numElems = nGrid[0] * nGrid[1];
85 } else if (dim == 3) {
86 mesh_p->d_bbox.first = std::vector<double>{box.first[0], box.first[1], box.first[2]};
87 mesh_p->d_bbox.second = std::vector<double>{box.second[0], box.second[1], box.second[2]};
88 mesh_p->d_numNodes = (nGrid[0] + 1) * (nGrid[1] + 1) * (nGrid[2] + 1);
89 mesh_p->d_numElems = nGrid[0] * nGrid[1] * nGrid[2];
91 } else {
92 throw std::runtime_error(
94 << "createUniformMesh(): invalid dim = " << dim << " argument.\n");
95 }
96
98 mesh_p->d_numDofs = mesh_p->d_numNodes * mesh_p->d_dim;
99
100 // local nodal data
101 mesh_p->d_nodes.resize(mesh_p->d_numNodes);
102 mesh_p->d_enc.resize(mesh_p->d_numElems * mesh_p->d_eNumVertex);
103 mesh_p->d_fix = std::vector<uint8_t>(mesh_p->d_nodes.size(), uint8_t(0));
104 mesh_p->d_vol.resize(mesh_p->d_numNodes);
105
106 // create mesh data
107 std::vector<double> h;
108 double h_small = 0.;
109 for (size_t i=0; i<dim; i++) {
110 h.push_back((box.second[i] - box.first[i])/nGrid[i]);
111 if (i == 0)
112 h_small = h[0];
113 else
114 h_small = std::min(h_small, h[i]);
115 }
116
117 // set smallest h as mesh size
118 mesh_p->d_h = h_small;
119
120 if (dim == 1) {
121 // compute node positions
122 for (size_t i = 0; i <= nGrid[0]; i++) {
123 mesh_p->d_nodes[i] = util::Point(box.first[0] + double(i) * h[0], 0., 0.);
124 mesh_p->d_vol[i] = h[0];
125 if (i == 0 || i == nGrid[0]) mesh_p->d_vol[i] *= 0.5;
126 } // loop over i
127
128 // compute element-node connectivity
129 for (size_t i = 0; i < nGrid[0]; i++) {
130 // element node connectivity, in the VTK line order
131 mesh_p->d_enc[2 * i + 0] = i;
132 mesh_p->d_enc[2 * i + 1] = i + 1;
133 } // loop over i
134 } else if (dim == 2) {
135 // compute node positions
136 for (size_t j = 0; j <= nGrid[1]; j++) {
137 for (size_t i = 0; i <= nGrid[0]; i++) {
138 // node number
139 size_t n = j * (nGrid[0] + 1) + i;
140 mesh_p->d_nodes[n] = util::Point(box.first[0] + double(i) * h[0],
141 box.first[1] + double(j) * h[1], 0.);
142
143 mesh_p->d_vol[n] = h[0] * h[1];
144 if (i == 0 || i == nGrid[0]) mesh_p->d_vol[n] *= 0.5;
145 if (j == 0 || j == nGrid[1]) mesh_p->d_vol[n] *= 0.5;
146 } // loop over i
147 } // loop over j
148
149 // compute element-node connectivity
150 for (size_t j = 0; j < nGrid[1]; j++) {
151 for (size_t i = 0; i < nGrid[0]; i++) {
152
153 // element number
154 auto n = j * nGrid[0] + i;
155
156 // element node connectivity (put it in anti clockwise order)
157 mesh_p->d_enc[4 * n + 0] = j * (nGrid[0] + 1) + i;
158 mesh_p->d_enc[4 * n + 1] = j * (nGrid[0] + 1) + i + 1;
159 mesh_p->d_enc[4 * n + 2] = (j + 1) * (nGrid[0] + 1) + i + 1;
160 mesh_p->d_enc[4 * n + 3] = (j + 1) * (nGrid[0] + 1) + i;
161 } // loop over i
162 } // loop over j
163 } else if (dim == 3) {
164 // compute node positions
165 for (size_t k = 0; k <= nGrid[2]; k++) {
166 for (size_t j = 0; j <= nGrid[1]; j++) {
167 for (size_t i = 0; i <= nGrid[0]; i++) {
168 // node number
169 size_t n = k * (nGrid[1] + 1) * (nGrid[0] + 1) + j * (nGrid[0] + 1) + i;
170 mesh_p->d_nodes[n] = util::Point(box.first[0] + double(i) * h[0],
171 box.first[1] + double(j) * h[1],
172 box.first[2] + double(k) * h[2]);
173
174 mesh_p->d_vol[n] = h[0] * h[1] * h[2];
175 if (i == 0 || i == nGrid[0]) mesh_p->d_vol[n] *= 0.5;
176 if (j == 0 || j == nGrid[1]) mesh_p->d_vol[n] *= 0.5;
177 if (k == 0 || k == nGrid[2]) mesh_p->d_vol[n] *= 0.5;
178 } // loop over i
179 } // loop over j
180 } // loop over k
181
182 // compute element-node connectivity
183 // (k < nGrid[2]: there are nGrid[2] cells through the thickness, not
184 // nGrid[2]+1. Using <= overran d_enc and corrupted the heap.)
185 for (size_t k = 0; k < nGrid[2]; k++) {
186 for (size_t j = 0; j < nGrid[1]; j++) {
187 for (size_t i = 0; i < nGrid[0]; i++) {
188
189 // element number
190 auto n = k * nGrid[1] * nGrid[0] + j * nGrid[0] + i;
191
192 // element node connectivity, in the VTK hexahedron order: the
193 // face at k counterclockwise, then the face at k+1 with node 4
194 // above node 0
195 mesh_p->d_enc[8 * n + 0] = k * (nGrid[1] + 1) * (nGrid[0] + 1)
196 + j * (nGrid[0] + 1) + i;
197 mesh_p->d_enc[8 * n + 1] = k * (nGrid[1] + 1) * (nGrid[0] + 1)
198 + j * (nGrid[0] + 1) + i + 1;
199 mesh_p->d_enc[8 * n + 2] = k * (nGrid[1] + 1) * (nGrid[0] + 1)
200 + (j + 1) * (nGrid[0] + 1) + i + 1;
201 mesh_p->d_enc[8 * n + 3] = k * (nGrid[1] + 1) * (nGrid[0] + 1)
202 + (j + 1) * (nGrid[0] + 1) + i;
203
204 mesh_p->d_enc[8 * n + 4] = (k + 1) * (nGrid[1] + 1) * (nGrid[0] + 1)
205 + j * (nGrid[0] + 1) + i;
206 mesh_p->d_enc[8 * n + 5] = (k + 1) * (nGrid[1] + 1) * (nGrid[0] + 1)
207 + j * (nGrid[0] + 1) + i + 1;
208 mesh_p->d_enc[8 * n + 6] = (k + 1) * (nGrid[1] + 1) * (nGrid[0] + 1)
209 + (j + 1) * (nGrid[0] + 1) + i + 1;
210 mesh_p->d_enc[8 * n + 7] = (k + 1) * (nGrid[1] + 1) * (nGrid[0] + 1)
211 + (j + 1) * (nGrid[0] + 1) + i;
212 } // loop over i
213 } // loop over j
214 } // loop over k
215 }
216}
217
219 const std::vector<std::vector<double>> &boxes) {
220 if (boxes.empty() || mesh_p->d_nodes.empty())
221 return;
222
223 auto inAnyBox = [&boxes](const util::Point &p) {
224 for (const auto &b : boxes) {
225 if (p.d_x >= b[0] && p.d_x <= b[3] && p.d_y >= b[1] && p.d_y <= b[4] &&
226 p.d_z >= b[2] && p.d_z <= b[5])
227 return true;
228 }
229 return false;
230 };
231
232 const size_t n_old = mesh_p->d_nodes.size();
233 std::vector<long> new_id(n_old, -1);
234 std::vector<util::Point> nodes;
235 std::vector<double> vol;
236 nodes.reserve(n_old);
237 vol.reserve(n_old);
238 for (size_t i = 0; i < n_old; ++i) {
239 if (inAnyBox(mesh_p->d_nodes[i]))
240 continue;
241 new_id[i] = static_cast<long>(nodes.size());
242 nodes.push_back(mesh_p->d_nodes[i]);
243 if (i < mesh_p->d_vol.size())
244 vol.push_back(mesh_p->d_vol[i]);
245 }
246
247 // Keep only elements all of whose nodes survived, renumbered.
248 std::vector<size_t> enc;
249 const size_t nv = mesh_p->d_eNumVertex;
250 if (nv > 0) {
251 enc.reserve(mesh_p->d_enc.size());
252 for (size_t e = 0; e + nv <= mesh_p->d_enc.size(); e += nv) {
253 bool keep = true;
254 for (size_t v = 0; v < nv; ++v) {
255 if (new_id[mesh_p->d_enc[e + v]] < 0) {
256 keep = false;
257 break;
258 }
259 }
260 if (!keep)
261 continue;
262 for (size_t v = 0; v < nv; ++v)
263 enc.push_back(static_cast<size_t>(new_id[mesh_p->d_enc[e + v]]));
264 }
265 }
266
267 // Nodes on faces newly opened by the void kept full cell volumes from
268 // createUniformMesh (only the outer box faces were halved). Mirror that
269 // rule: if a one-grid-step probe along ±e_i lands inside a carved box,
270 // apply the same ½ factor on that axis (corners get multiple halves).
271 const double h = mesh_p->d_h > 0. ? mesh_p->d_h : 1.0e-3;
272 auto probeInBox = [&boxes](double x, double y, double z) {
273 for (const auto &b : boxes) {
274 if (x >= b[0] && x <= b[3] && y >= b[1] && y <= b[4] && z >= b[2] &&
275 z <= b[5])
276 return true;
277 }
278 return false;
279 };
280 for (size_t i = 0; i < nodes.size(); ++i) {
281 const auto &p = nodes[i];
282 const bool hx = probeInBox(p.d_x - h, p.d_y, p.d_z) ||
283 probeInBox(p.d_x + h, p.d_y, p.d_z);
284 const bool hy = probeInBox(p.d_x, p.d_y - h, p.d_z) ||
285 probeInBox(p.d_x, p.d_y + h, p.d_z);
286 const bool hz = mesh_p->d_dim > 2 && (probeInBox(p.d_x, p.d_y, p.d_z - h) ||
287 probeInBox(p.d_x, p.d_y, p.d_z + h));
288 if (hx)
289 vol[i] *= 0.5;
290 if (hy)
291 vol[i] *= 0.5;
292 if (hz)
293 vol[i] *= 0.5;
294 }
295
296 mesh_p->d_nodes = std::move(nodes);
297 mesh_p->d_vol = std::move(vol);
298 mesh_p->d_enc = std::move(enc);
299 mesh_p->d_numNodes = mesh_p->d_nodes.size();
300 mesh_p->d_numElems = (nv > 0) ? mesh_p->d_enc.size() / nv : 0;
301 mesh_p->d_numDofs = mesh_p->d_numNodes * mesh_p->d_dim;
302 mesh_p->d_fix = std::vector<uint8_t>(mesh_p->d_nodes.size(), uint8_t(0));
303}
304
306 const std::vector<util::Point> &xRef,
307 const std::vector<util::Point> &u,
308 std::vector<util::Point> &xQuadCur,
309 size_t iNodeStart,
310 size_t iQuadStart,
311 size_t quadOrder) {
312
313 size_t num_elems = mesh_p->getNumElements();
314
315 // check data
316 assert((num_elems != 0) && "Number of elements in the mesh is zero "
317 "possibly due to missing element-node "
318 "connectivity data. Can not proceed with "
319 "computation.\n");
320
321 assert(( (xRef.size() >= mesh_p->getNumNodes() + iNodeStart) ||
322 (u.size() >= mesh_p->getNumNodes() + iNodeStart)
323 ) &&
324 "Number of elements i nnodal data can not be smaller than number of "
325 "nodes.\n");
326
327 auto elem = fe::elem(mesh_p->getElementType(), quadOrder);
328
329 // get total number of quadrature points by getting the number of quad
330 // points in one element times the number of elements
331 size_t numQuadPointsTotal = mesh_p->getNumElements() *
332 elem->getNumQuadPoints();
333
334 assert((xQuadCur.size() >= numQuadPointsTotal + iQuadStart)
335 && "Number of elements in xQuad data can not be less than "
336 "total number of quadrature points.\n");
337
338
339 // compute current position of quad points
340 auto *elem_p = elem.get();
341 tf::Executor executor(util::parallel::getNThreads());
342 tf::Taskflow taskflow;
343 taskflow.for_each_index(
344 (std::size_t) 0, num_elems, (std::size_t) 1,
345 [elem_p, mesh_p, xRef, u, iNodeStart, iQuadStart, &xQuadCur]
346 (std::size_t e) {
347
348 auto id_nds = mesh_p->getElementConnectivity(e);
349 std::vector<util::Point> nds;
350 for (const auto &i : id_nds)
351 nds.push_back(xRef[i + iNodeStart]);
352
353 auto qds = elem_p->getQuadDatas(nds);
354
355 auto qd_point_current = util::Point();
356
357 for (size_t q=0; q<qds.size(); q++) {
358 qd_point_current = qds[q].d_p;
359 for (size_t i = 0; i < id_nds.size(); i++) {
360 auto i_global_id = iNodeStart + id_nds[i];
361 qd_point_current += u[i_global_id] * qds[q].d_shapes[i];
362 }
363
364 auto q_global_id = iQuadStart + e * elem_p->getNumQuadPoints() + q;
365 xQuadCur[q_global_id] = qd_point_current;
366 }
367 }
368 ); // for_each
369
370 executor.run(taskflow).get();
371}
372
373void getStrainStress(const mesh::Mesh *mesh_p,
374 const std::vector<util::Point> & xRef,
375 const std::vector<util::Point> &u,
376 bool isPlaneStrain,
377 std::vector<util::SymMatrix3> &strain,
378 std::vector<util::SymMatrix3> &stress,
379 size_t iNodeStart,
380 size_t iStrainStart,
381 double nu,
382 double lambda,
383 double mu,
384 bool computeStress,
385 size_t quadOrder) {
386
387 assert((mesh_p->getDimension() > 1) && "In getStrainStress(), dimension = 2,3 is supported.\n");
388
389 size_t num_elems = mesh_p->getNumElements();
390
391 // check data
392 assert((num_elems != 0) && "Number of elements in the mesh is zero "
393 "possibly due to missing element-node "
394 "connectivity data. Can not proceed with "
395 "computation.\n");
396
397 assert(( (xRef.size() >= mesh_p->getNumNodes() + iNodeStart) ||
398 (u.size() >= mesh_p->getNumNodes() + iNodeStart)
399 ) &&
400 "Number of elements i nodal data can not be smaller than number of "
401 "nodes.\n");
402
403 auto elem = fe::elem(mesh_p->getElementType(), quadOrder);
404
405 // get total number of quadrature points by getting the number of quad
406 // points in one element times the number of elements
407 size_t numQuadPointsTotal = mesh_p->getNumElements() *
408 elem->getNumQuadPoints();
409
410 assert((strain.size() >= numQuadPointsTotal + iStrainStart)
411 && "Number of elements in strain data can not be less than "
412 "total number of quadrature points.\n");
413
414 // check if we can compute stress from given material data
415 computeStress = computeStress || util::isLess(mu, 1.e-16) || util::isLess(lambda, 1.e-16);
416
417 if (computeStress)
418 assert((stress.size() >= numQuadPointsTotal + iStrainStart)
419 && "Number of elements in stress data can not be less than "
420 "total number of quadrature points.\n");
421
422 // compute current position of quad points
423 auto *elem_p = elem.get();
424 const auto dim = mesh_p->getDimension();
425 tf::Executor executor(util::parallel::getNThreads());
426 tf::Taskflow taskflow;
427 taskflow.for_each_index(
428 (std::size_t) 0, num_elems, (std::size_t) 1,
429 [elem_p, mesh_p, xRef, u, iNodeStart, iStrainStart,
430 isPlaneStrain, nu, lambda, mu, computeStress, dim,
431 &strain, &stress]
432 (std::size_t e) {
433
434 auto id_nds = mesh_p->getElementConnectivity(e);
435 std::vector<util::Point> nds;
436 std::vector<util::Point> u_el;
437 for (const auto &i : id_nds) {
438 nds.push_back(xRef[i + iNodeStart]);
439 u_el.push_back(u[i + iNodeStart]);
440 }
441
442 auto qds = elem_p->getQuadDatas(nds);
443
444 for (size_t q=0; q<qds.size(); q++) {
445 auto ssn = strainFromB(fe::B(qds[q].d_derShapes, dim), u_el);
446 auto sss = util::SymMatrix3();
447
448 if (dim == 2 && isPlaneStrain)
449 ssn(2, 2) = -nu * (ssn(0, 0) + ssn(1, 1)) / (1. - nu);
450
451 if (computeStress) {
452 auto trace_ssn = ssn(0, 0) + ssn(1, 1) + ssn(2, 2);
453 sss(0, 0) = lambda * trace_ssn + 2 * mu * ssn(0, 0);
454 sss(0, 1) = 2 * mu * ssn(0, 1);
455 sss(0, 2) = 2 * mu * ssn(0, 2);
456
457 sss(1, 1) = lambda * trace_ssn + 2 * mu * ssn(1, 1);
458 sss(1, 2) = 2 * mu * ssn(1, 2);
459
460 sss(2, 2) = lambda * trace_ssn + 2 * mu * ssn(2, 2);
461
462 if (dim == 2 && !isPlaneStrain)
463 sss(2, 2) = nu * (sss(0, 0) + sss(1, 1));
464 }
465
466 auto q_global_id = iStrainStart + e * elem_p->getNumQuadPoints() + q;
467 strain[q_global_id] = ssn;
468 if (computeStress)
469 stress[q_global_id] = sss;
470 }
471 }
472 );
473
474 executor.run(taskflow).get();
475}
476
478 const std::vector<util::Point> & xRef,
479 const std::vector<util::Point> &u,
480 const std::vector<util::SymMatrix3> &stress,
481 double &maxShearStress,
482 util::Point &maxShearStressLocRef,
483 util::Point &maxShearStressLocCur,
484 size_t iNodeStart,
485 size_t iStrainStart,
486 size_t quadOrder) {
487
488 assert((mesh_p->getDimension() == 2) && "In getMaxShearStressAndLoc(), only dimension = 2 is supported.\n");
489
490 size_t num_elems = mesh_p->getNumElements();
491
492 // check data
493 assert((num_elems != 0) && "Number of elements in the mesh is zero "
494 "possibly due to missing element-node "
495 "connectivity data. Can not proceed with "
496 "computation.\n");
497
498 assert(( (xRef.size() >= mesh_p->getNumNodes() + iNodeStart) ||
499 (u.size() >= mesh_p->getNumNodes() + iNodeStart)
500 ) &&
501 "Number of elements i nnodal data can not be smaller than number of "
502 "nodes.\n");
503
504 auto elem = fe::elem(mesh_p->getElementType(), quadOrder);
505
506 // get total number of quadrature points by getting the number of quad
507 // points in one element times the number of elements
508 size_t numQuadPointsTotal = mesh_p->getNumElements() *
509 elem->getNumQuadPoints();
510
511 assert((stress.size() >= numQuadPointsTotal + iStrainStart)
512 && "Number of elements in stress data can not be less than "
513 "total number of quadrature points.\n");
514
515 // compute principal shear stress
516 double max_stress = 0.;
517 size_t max_stress_e = 0;
518 size_t max_stress_q = 0;
519 for (size_t e = 0; e < num_elems; e++) {
520 for (size_t q=0; q<elem->getNumQuadPoints(); q++) {
521 auto q_global_id = iStrainStart + e * elem->getNumQuadPoints() + q;
522 const auto stress_e = stress[q_global_id];
523
524 const auto principle_shear_stress =
525 std::sqrt(0.25 * std::pow(stress_e.get(0) - stress_e.get(1), 2) +
526 std::pow(stress_e.get(5), 2));
527
528 if (util::isLess(max_stress, principle_shear_stress)) {
529 max_stress = principle_shear_stress;
530 max_stress_e = e;
531 max_stress_q = q;
532 }
533 }
534 }
535
536 // set data
537 maxShearStress = max_stress;
538
539 // now compute current and reference location of the quadrature point at which
540 // stress is maximum
541 {
542 // get ids of nodes of element and reference coordinate of nodes
543 auto id_nds = mesh_p->getElementConnectivity(max_stress_e);
544 auto e_nds_start = iNodeStart + mesh_p->d_eNumVertex * max_stress_e;
545 auto e_nds_end = e_nds_start + mesh_p->d_eNumVertex;
546 std::vector<util::Point> nds(xRef.begin() + e_nds_start, xRef.begin() + e_nds_end);
547
548 auto qds = elem->getQuadDatas(nds);
549 auto qd_point_current = qds[max_stress_q].d_p;
550 maxShearStressLocRef = qd_point_current;
551 for (size_t i = 0; i < id_nds.size(); i++) {
552 auto i_global_id = iNodeStart + id_nds[i];
553 qd_point_current += u[i_global_id] * qds[max_stress_q].d_shapes[i];
554 }
555
556 maxShearStressLocCur = qd_point_current;
557 }
558}
559
560} // namespace mesh
561
int dim() const
Definition bMatrix.h:31
int nDof() const
Definition bMatrix.h:30
int nStrain() const
Definition bMatrix.h:29
A class for mesh data.
Definition mesh.h:53
std::vector< size_t > getElementConnectivity(const size_t &i) const
Get the connectivity of element.
Definition mesh.h:213
size_t getNumNodes() const
Get the number of nodes.
Definition mesh.h:91
std::vector< size_t > d_enc
Element-node connectivity data.
Definition mesh.h:443
std::pair< std::vector< double >, std::vector< double > > d_bbox
Bounding box.
Definition mesh.h:541
std::vector< util::Point > d_nodes
Vector of initial (reference) coordinates of nodes.
Definition mesh.h:435
size_t d_numElems
Number of elements.
Definition mesh.h:406
size_t d_eType
Element type.
Definition mesh.h:417
size_t d_numNodes
Number of nodes.
Definition mesh.h:403
size_t d_dim
Dimension of the mesh.
Definition mesh.h:496
size_t getDimension() const
Get the dimension of the domain.
Definition mesh.h:85
std::vector< uint8_t > d_fix
Vector of fixity mask of each node.
Definition mesh.h:459
size_t d_numDofs
Number of dofs = (dimension) times (number of nodes)
Definition mesh.h:518
size_t getElementType() const
Get the type of element in mesh.
Definition mesh.h:109
std::vector< double > d_vol
Vector of volume of each node.
Definition mesh.h:467
size_t d_eNumVertex
Number of vertex per element.
Definition mesh.h:432
size_t getNumElements() const
Get the number of elements.
Definition mesh.h:97
double d_h
Characteristic mesh spacing (minimum nodal distance); always from computeMeshSize() after nodes exist...
Definition mesh.h:544
Collects a message with stream syntax for use in an exception.
Definition io.h:52
static int vtk_map_element_to_num_nodes[16]
Map from element type to number of nodes (for vtk)
static const int vtk_type_quad
Integer flag for quad element.
static const int vtk_type_hexahedron
Integer flag for hexahedron element.
static const int vtk_type_line
Integer flag for line element.
util::SymMatrix3 strainFromB(const fe::B &B, const std::vector< util::Point > &u)
Definition meshUtil.cpp:31
std::unique_ptr< BaseElem > elem(size_t type, size_t order)
Collection of methods and data related to finite element and mesh.
Definition mesh.cpp:29
void getCurrentQuadPoints(const mesh::Mesh *mesh_p, const std::vector< util::Point > &xRef, const std::vector< util::Point > &u, std::vector< util::Point > &xQuadCur, size_t iNodeStart, size_t iQuadStart, size_t quadOrder)
Get current location of quadrature points of elements in the mesh. This function expects mesh has ele...
Definition meshUtil.cpp:305
void getMaxShearStressAndLoc(const mesh::Mesh *mesh_p, const std::vector< util::Point > &xRef, const std::vector< util::Point > &u, const std::vector< util::SymMatrix3 > &stress, double &maxShearStress, util::Point &maxShearStressLocRef, util::Point &maxShearStressLocCur, size_t iNodeStart, size_t iStrainStart, size_t quadOrder)
Get location where maximum of specified component of stress occurs in this particle.
Definition meshUtil.cpp:477
void createUniformMesh(mesh::Mesh *mesh_p, size_t dim, std::pair< std::vector< double >, std::vector< double > > box, std::vector< size_t > nGrid)
Creates uniform mesh for rectangle/cuboid domain.
Definition meshUtil.cpp:64
void getStrainStress(const mesh::Mesh *mesh_p, const std::vector< util::Point > &xRef, const std::vector< util::Point > &u, bool isPlaneStrain, std::vector< util::SymMatrix3 > &strain, std::vector< util::SymMatrix3 > &stress, size_t iNodeStart, size_t iStrainStart, double nu, double lambda, double mu, bool computeStress, size_t quadOrder)
Strain and stress at quadrature points in the mesh.
Definition meshUtil.cpp:373
void removeNodesInBoxes(mesh::Mesh *mesh_p, const std::vector< std::vector< double > > &boxes)
Removes nodes lying inside any of the given axis-aligned boxes.
Definition meshUtil.cpp:218
unsigned int getNThreads()
Get number of threads to be used by taskflow.
bool isLess(const double &a, const double &b)
Returns true if a < b.
Definition function.cpp:22
A structure to represent 3d vectors.
Definition point.h:30
A structure to represent 3d matrices.
Definition matrix.h:258