18#include <fmt/format.h>
20#include <taskflow/taskflow/taskflow.hpp>
21#include <taskflow/taskflow/algorithm/for_each.hpp>
26 if (nGrid.size() < dim or box.first.size() < dim or box.second.size() < dim) {
27 std::cerr <<
"createUniformMesh(): check nGrid or box arguments.\n";
32 mesh_p->
d_bbox.first = std::vector<double>{box.first[0], 0., 0.};
33 mesh_p->
d_bbox.second = std::vector<double>{box.second[0], 0., 0.};
37 }
else if (dim == 2) {
38 mesh_p->
d_bbox.first = std::vector<double>{box.first[0], box.first[1], 0.};
39 mesh_p->
d_bbox.second = std::vector<double>{box.second[0], box.second[1], 0.};
40 mesh_p->
d_numNodes = (nGrid[0] + 1) * (nGrid[1] + 1);
43 }
else if (dim == 3) {
44 mesh_p->
d_bbox.first = std::vector<double>{box.first[0], box.first[1], box.first[2]};
45 mesh_p->
d_bbox.second = std::vector<double>{box.second[0], box.second[1], box.second[2]};
46 mesh_p->
d_numNodes = (nGrid[0] + 1) * (nGrid[1] + 1) * (nGrid[2] + 1);
47 mesh_p->
d_numElems = nGrid[0] * nGrid[1] * nGrid[2];
50 std::cerr <<
"createUniformMesh(): invalid dim = " << dim <<
" argument.\n";
60 mesh_p->
d_fix = std::vector<uint8_t>(mesh_p->
d_nodes.size(), uint8_t(0));
64 std::vector<double> h;
66 for (
size_t i=0; i<dim; i++) {
67 h.push_back((box.second[i] - box.first[i])/nGrid[i]);
71 if (std::abs(h[i] - h_small) > 1.0e-14 and h_small > h[1] + 1.0e-14)
77 mesh_p->
d_h = h_small;
81 for (
size_t i = 0; i <= nGrid[0]; i++) {
83 mesh_p->
d_vol[i] = h[0];
84 if (i == 0 || i == nGrid[0]) mesh_p->
d_vol[i] *= 0.5;
88 for (
size_t i = 0; i < nGrid[0]; i++) {
91 mesh_p->
d_enc[2 * i + 0] = i;
92 mesh_p->
d_enc[2 * i + 1] = i + 1;
94 }
else if (dim == 2) {
96 for (
size_t j = 0; j <= nGrid[1]; j++) {
97 for (
size_t i = 0; i <= nGrid[0]; i++) {
99 size_t n = j * (nGrid[0] + 1) + i;
101 box.first[1] +
double(j) * h[1], 0.);
103 mesh_p->
d_vol[n] = h[0] * h[1];
104 if (i == 0 || i == nGrid[0]) mesh_p->
d_vol[n] *= 0.5;
105 if (j == 0 || j == nGrid[1]) mesh_p->
d_vol[n] *= 0.5;
110 for (
size_t j = 0; j < nGrid[1]; j++) {
111 for (
size_t i = 0; i < nGrid[0]; i++) {
114 auto n = j * nGrid[0] + i;
117 mesh_p->
d_enc[4 * n + 0] = j * (nGrid[0] + 1) + i;
118 mesh_p->
d_enc[4 * n + 1] = j * (nGrid[0] + 1) + i + 1;
119 mesh_p->
d_enc[4 * n + 2] = (j + 1) * (nGrid[0] + 1) + i + 1;
120 mesh_p->
d_enc[4 * n + 3] = (j + 1) * (nGrid[0] + 1) + i;
123 }
else if (dim == 3) {
125 for (
size_t k = 0; k <= nGrid[2]; k++) {
126 for (
size_t j = 0; j <= nGrid[1]; j++) {
127 for (
size_t i = 0; i <= nGrid[0]; i++) {
129 size_t n = k * (nGrid[1] + 1) * (nGrid[0] + 1) + j * (nGrid[0] + 1) + i;
131 box.first[1] +
double(j) * h[1],
132 box.first[2] +
double(k) * h[2]);
134 mesh_p->
d_vol[n] = h[0] * h[1] * h[2];
135 if (i == 0 || i == nGrid[0]) mesh_p->
d_vol[n] *= 0.5;
136 if (j == 0 || j == nGrid[1]) mesh_p->
d_vol[n] *= 0.5;
137 if (k == 0 || k == nGrid[2]) mesh_p->
d_vol[n] *= 0.5;
143 for (
size_t k = 0; k <= nGrid[2]; k++) {
144 for (
size_t j = 0; j < nGrid[1]; j++) {
145 for (
size_t i = 0; i < nGrid[0]; i++) {
148 auto n = k * nGrid[1] * nGrid[0] + j * nGrid[0] + i;
152 mesh_p->
d_enc[8 * n + 0] = k * (nGrid[1] + 1) * (nGrid[0] + 1)
153 + j * (nGrid[0] + 1) + i;
154 mesh_p->
d_enc[8 * n + 1] = k * (nGrid[1] + 1) * (nGrid[0] + 1)
155 + j * (nGrid[0] + 1) + i + 1;
156 mesh_p->
d_enc[8 * n + 2] = k * (nGrid[1] + 1) * (nGrid[0] + 1)
157 + (j + 1) * (nGrid[0] + 1) + i + 1;
158 mesh_p->
d_enc[8 * n + 3] = k * (nGrid[1] + 1) * (nGrid[0] + 1)
159 + (j + 1) * (nGrid[0] + 1) + i;
161 mesh_p->
d_enc[8 * n + 4] = (k + 1) * (nGrid[1] + 1) * (nGrid[0] + 1)
162 + j * (nGrid[0] + 1) + i;
163 mesh_p->
d_enc[8 * n + 5] = (k + 1) * (nGrid[1] + 1) * (nGrid[0] + 1)
164 + j * (nGrid[0] + 1) + i + 1;
165 mesh_p->
d_enc[8 * n + 6] = (k + 1) * (nGrid[1] + 1) * (nGrid[0] + 1)
166 + (j + 1) * (nGrid[0] + 1) + i + 1;
167 mesh_p->
d_enc[8 * n + 7] = (k + 1) * (nGrid[1] + 1) * (nGrid[0] + 1)
168 + (j + 1) * (nGrid[0] + 1) + i;
177 const std::vector<util::Point> &xRef,
178 const std::vector<util::Point> &u,
179 std::vector<util::Point> &xQuadCur,
187 assert((num_elems != 0) &&
"Number of elements in the mesh is zero "
188 "possibly due to missing element-node "
189 "connectivity data. Can not proceed with "
192 assert(( (xRef.size() >= mesh_p->
getNumNodes() + iNodeStart) ||
195 "Number of elements i nnodal data can not be smaller than number of "
209 std::cerr << fmt::format(
"Error: Can not compute strain/stress as the element "
210 "type = {} is not yet supported in this routine.\n", mesh_p->
getElementType());
219 assert((xQuadCur.size() >= numQuadPointsTotal + iQuadStart)
220 &&
"Number of elements in xQuad data can not be less than "
221 "total number of quadrature points.\n");
238 tf::Taskflow taskflow;
239 taskflow.for_each_index(
240 (std::size_t) 0, num_elems, (std::size_t) 1,
241 [elem, mesh_p, xRef, u, iNodeStart, iQuadStart, &xQuadCur]
246 auto e_nds_start = iNodeStart + mesh_p->
d_eNumVertex * e;
253 std::vector<util::Point> nds;
254 for (
const auto &i : id_nds)
255 nds.push_back(xRef[i + iNodeStart]);
261 for (
size_t q=0; q<qds.size(); q++) {
262 qd_point_current = qds[q].d_p;
263 for (
size_t i = 0; i < id_nds.size(); i++) {
264 auto i_global_id = iNodeStart + id_nds[i];
265 qd_point_current += u[i_global_id] * qds[q].d_shapes[i];
272 xQuadCur[q_global_id] = qd_point_current;
277 executor.run(taskflow).get();
281 const std::vector<util::Point> & xRef,
282 const std::vector<util::Point> &u,
284 std::vector<util::SymMatrix3> &strain,
285 std::vector<util::SymMatrix3> &stress,
294 assert((mesh_p->
getDimension() > 1) &&
"In getStrainStress(), dimension = 2,3 is supported.\n");
299 assert((num_elems != 0) &&
"Number of elements in the mesh is zero "
300 "possibly due to missing element-node "
301 "connectivity data. Can not proceed with "
304 assert(( (xRef.size() >= mesh_p->
getNumNodes() + iNodeStart) ||
307 "Number of elements i nodal data can not be smaller than number of "
321 std::cerr <<
"Error: Can not compute strain/stress as the element "
322 "type is not yet supported in this routine.\n";
331 assert((strain.size() >= numQuadPointsTotal + iStrainStart)
332 &&
"Number of elements in strain data can not be less than "
333 "total number of quadrature points.\n");
339 assert((stress.size() >= numQuadPointsTotal + iStrainStart)
340 &&
"Number of elements in stress data can not be less than "
341 "total number of quadrature points.\n");
345 tf::Taskflow taskflow;
346 taskflow.for_each_index(
347 (std::size_t) 0, num_elems, (std::size_t) 1,
348 [elem, mesh_p, xRef, u, iNodeStart, iStrainStart,
349 isPlaneStrain, nu, lambda, mu, computeStress,
358 auto e_nds_start = iNodeStart + mesh_p->
d_eNumVertex * e;
362 std::vector<util::Point> nds;
363 for (
const auto &i : id_nds)
364 nds.push_back(xRef[i + iNodeStart]);
368 for (
size_t q=0; q<qds.size(); q++) {
373 for (
size_t i = 0; i < id_nds.size(); i++) {
374 auto i_global_id = iNodeStart + id_nds[i];
375 auto ui = u[i_global_id];
377 ssn(0, 0) += ui[0] + qds[q].d_derShapes[i][0];
379 ssn(1, 1) += ui[1] + qds[q].d_derShapes[i][1];
381 ssn(0, 1) += 0.5 * ui[0] * qds[q].d_derShapes[i][1] +
382 0.5 * ui[1] * qds[q].d_derShapes[i][0];
385 ssn(2, 2) += ui[2] + qds[q].d_derShapes[i][2];
388 ssn(1, 2) += 0.5 * ui[1] * qds[q].d_derShapes[i][2] +
389 0.5 * ui[2] * qds[q].d_derShapes[i][1];
391 ssn(0, 2) += 0.5 * ui[0] * qds[q].d_derShapes[i][2] +
392 0.5 * ui[2] * qds[q].d_derShapes[i][0];
397 ssn(2, 2) = -nu * (ssn(0, 0) + ssn(1, 1)) / (1. - nu);
401 auto trace_ssn = ssn(0, 0) + ssn(1, 1) + ssn(2, 2);
402 sss(0, 0) = lambda * trace_ssn + 2 * mu * ssn(0, 0);
403 sss(0, 1) = 2 * mu * ssn(0, 1);
404 sss(0, 2) = 2 * mu * ssn(0, 2);
406 sss(1, 1) = lambda * trace_ssn + 2 * mu * ssn(1, 1);
407 sss(1, 2) = 2 * mu * ssn(1, 2);
409 sss(2, 2) = lambda * trace_ssn + 2 * mu * ssn(2, 2);
412 sss(2, 2) = nu * (sss(0, 0) + sss(1, 1));
419 strain[q_global_id] = ssn;
421 stress[q_global_id] = sss;
426 executor.run(taskflow).get();
430 const std::vector<util::Point> & xRef,
431 const std::vector<util::Point> &u,
432 const std::vector<util::SymMatrix3> &stress,
433 double &maxShearStress,
440 assert((mesh_p->
getDimension() == 2) &&
"In getMaxShearStressAndLoc(), only dimension = 2 is supported.\n");
445 assert((num_elems != 0) &&
"Number of elements in the mesh is zero "
446 "possibly due to missing element-node "
447 "connectivity data. Can not proceed with "
450 assert(( (xRef.size() >= mesh_p->
getNumNodes() + iNodeStart) ||
453 "Number of elements i nnodal data can not be smaller than number of "
467 std::cerr <<
"Error: Can not compute strain/stress as the element "
468 "type is not yet supported in this routine.\n";
477 assert((stress.size() >= numQuadPointsTotal + iStrainStart)
478 &&
"Number of elements in stress data can not be less than "
479 "total number of quadrature points.\n");
482 double max_stress = 0.;
483 size_t max_stress_e = 0;
484 size_t max_stress_q = 0;
485 for (
size_t e = 0; e < num_elems; e++) {
488 const auto stress_e = stress[q_global_id];
490 const auto principle_shear_stress =
491 std::sqrt(0.25 * std::pow(stress_e.get(0) - stress_e.get(1), 2) +
492 std::pow(stress_e.get(5), 2));
495 max_stress = principle_shear_stress;
503 maxShearStress = max_stress;
510 auto e_nds_start = iNodeStart + mesh_p->
d_eNumVertex * max_stress_e;
512 std::vector<util::Point> nds(xRef.begin() + e_nds_start, xRef.begin() + e_nds_end);
515 auto qd_point_current = qds[max_stress_q].d_p;
516 maxShearStressLocRef = qd_point_current;
517 for (
size_t i = 0; i < id_nds.size(); i++) {
518 auto i_global_id = iNodeStart + id_nds[i];
519 qd_point_current += u[i_global_id] * qds[max_stress_q].d_shapes[i];
522 maxShearStressLocCur = qd_point_current;
A base class which provides methods to map points to/from reference element and to compute quadrature...
virtual std::vector< fe::QuadData > getQuadDatas(const std::vector< util::Point > &nodes)=0
Get vector of quadrature data.
size_t getNumQuadPoints()
Get number of quadrature points in the data.
A class for mapping and quadrature related operations for linear 2-node line element.
std::vector< util::Point > d_nodes
Vector of initial (reference) coordinates of nodes.
std::vector< double > d_vol
Vector of volume of each node.
size_t d_dim
Dimension of the mesh.
std::vector< uint8_t > d_fix
Vector of fixity mask of each node.
size_t d_numElems
Number of elements.
size_t getElementType() const
Get the type of element in mesh.
std::pair< std::vector< double >, std::vector< double > > d_bbox
Bounding box.
size_t d_eType
Element type.
std::vector< size_t > d_enc
Element-node connectivity data.
std::vector< size_t > getElementConnectivity(const size_t &i) const
Get the connectivity of element.
size_t d_numNodes
Number of nodes.
size_t d_eNumVertex
Number of vertex per element.
size_t getNumNodes() const
Get the number of nodes.
size_t getNumElements() const
Get the number of elements.
size_t getDimension() const
Get the dimension of the domain.
size_t d_numDofs
Number of dofs = (dimension) times (number of nodes)
A class for mapping and quadrature related operations for bi-linear quadrangle element.
A class for mapping and quadrature related operations for linear tetrahedron element.
A class for mapping and quadrature related operations for linear triangle element.
static int vtk_map_element_to_num_nodes[16]
Map from element type to number of nodes (for vtk)
static const int vtk_type_triangle
Integer flag for triangle element.
static const int vtk_type_quad
Integer flag for quad element.
static const int vtk_type_tetra
Integer flag for tetrahedron element.
static const int vtk_type_hexahedron
Integer flag for hexahedron element.
static const int vtk_type_line
Integer flag for line element.
void getMaxShearStressAndLoc(const fe::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=0, size_t iStrainStart=0, size_t quadOrder=1)
Get location where maximum of specified component of stress occurs in this particle.
void getStrainStress(const fe::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=0, size_t iStrainStart=0, double nu=0., double lambda=0., double mu=0., bool computeStress=false, size_t quadOrder=1)
Strain and stress at quadrature points in the mesh.
void createUniformMesh(fe::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.
void getCurrentQuadPoints(const fe::Mesh *mesh_p, const std::vector< util::Point > &xRef, const std::vector< util::Point > &u, std::vector< util::Point > &xQuadCur, size_t iNodeStart=0, size_t iQuadStart=0, size_t quadOrder=1)
Get current location of quadrature points of elements in the mesh. This function expects mesh has ele...
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.
A structure to represent 3d vectors.
A structure to represent 3d matrices.