12 #include "libmesh/elem.h"
20 InputParameters params = validParams<MooseMesh>();
21 params.addClassDescription(
"Mesh class to store and return peridynamics specific mesh data");
23 params.addParam<Real>(
"horizon_radius",
"Value of horizon size in terms of radius");
24 params.addParam<Real>(
"horizon_number",
25 "The material points spacing number, i.e. ratio of horizon radius to the "
26 "effective average spacing");
27 params.addParam<Real>(
"bond_associated_horizon_ratio",
29 "Ratio of bond-associated horizon to nodal horizon. This is the only "
30 "parameters to control the size of bond-associated horizon");
31 params.addParam<std::vector<Point>>(
"cracks_start",
32 "Cartesian coordinates where predefined line cracks start");
33 params.addParam<std::vector<Point>>(
"cracks_end",
34 "Cartesian coordinates where predefined line cracks end");
35 params.addParam<std::vector<Real>>(
"cracks_width",
"Widths of predefined line cracks");
37 params.set<
bool>(
"_mesh_generator_mesh") =
true;
43 : MooseMesh(parameters),
44 _horiz_rad(isParamValid(
"horizon_radius") ? getParam<Real>(
"horizon_radius") : 0),
45 _has_horiz_num(isParamValid(
"horizon_number")),
46 _horiz_num(_has_horiz_num ? getParam<Real>(
"horizon_number") : 0),
47 _bah_ratio(getParam<Real>(
"bond_associated_horizon_ratio")),
48 _has_cracks(isParamValid(
"cracks_start") || isParamValid(
"cracks_end")),
49 _dim(declareRestartableData<unsigned int>(
"dim")),
50 _n_pdnodes(declareRestartableData<unsigned int>(
"n_pdnodes")),
51 _n_pdbonds(declareRestartableData<unsigned int>(
"n_pdbonds")),
52 _pdnode_avg_spacing(declareRestartableData<std::vector<Real>>(
"pdnode_avg_spacing")),
53 _pdnode_horiz_rad(declareRestartableData<std::vector<Real>>(
"pdnode_horiz_radius")),
54 _pdnode_vol(declareRestartableData<std::vector<Real>>(
"pdnode_vol")),
55 _pdnode_horiz_vol(declareRestartableData<std::vector<Real>>(
"pdnode_horiz_vol")),
56 _pdnode_blockID(declareRestartableData<std::vector<SubdomainID>>(
"pdnode_blockID")),
57 _pdnode_elemID(declareRestartableData<std::vector<dof_id_type>>(
"pdnode_elemID")),
59 declareRestartableData<std::vector<std::vector<dof_id_type>>>(
"pdnode_neighbors")),
60 _pdnode_bonds(declareRestartableData<std::vector<std::vector<dof_id_type>>>(
"pdnode_bonds")),
62 declareRestartableData<std::vector<std::vector<std::vector<dof_id_type>>>>(
"dg_neighbors")),
63 _dg_vol_frac(declareRestartableData<std::vector<std::vector<Real>>>(
"dg_vol_fraction")),
64 _boundary_node_offset(
65 declareRestartableData<std::map<dof_id_type, Real>>(
"boundary_node_offset"))
68 mooseError(
"Must specify either horizon_radius or horizon_number to determine horizon size in "
74 _cracks_end = getParam<std::vector<Point>>(
"cracks_end");
84 "Number of cracks starting points is NOT the same as number of cracks ending points!");
88 if (isParamValid(
"cracks_width"))
92 mooseError(
"Number of cracks width is NOT the same as number of cracks!");
104 std::unique_ptr<MooseMesh>
107 return libmesh_make_unique<PeridynamicsMesh>(*
this);
114 _mesh = _app.getMeshGeneratorMesh();
116 _mesh->prepare_for_use(
true);
140 std::set<dof_id_type> converted_elem_id,
141 std::multimap<SubdomainID, SubdomainID> connect_block_id_pairs,
142 std::multimap<SubdomainID, SubdomainID> non_connect_block_id_pairs)
144 _dim = fe_mesh.mesh_dimension();
162 for (
const auto & eid : converted_elem_id)
164 Elem * fe_elem = fe_mesh.elem_ptr(eid);
166 unsigned int n_fe_neighbors = 0;
168 for (
unsigned int j = 0; j < fe_elem->n_neighbors(); ++j)
169 if (fe_elem->neighbor_ptr(j) !=
nullptr)
171 dist_sum += (fe_elem->centroid() - fe_elem->neighbor_ptr(j)->centroid()).norm();
177 std::vector<unsigned int> nid = fe_elem->nodes_on_side(j);
178 Point p0 = fe_elem->centroid();
179 Point p1 = fe_elem->point(nid[0]);
180 if (fe_elem->dim() == 2)
182 Point p2 = fe_elem->point(nid.back());
183 Real area = 0.5 * std::abs(p0(0) * (p1(1) - p2(1)) + p1(0) * (p2(1) - p0(1)) +
184 p2(0) * (p0(1) - p1(1)));
185 dist = 2.0 * area / fe_elem->length(nid[0], nid[1]);
189 Point p2 = fe_elem->point(nid[1]);
190 Point p3 = fe_elem->point(nid.back());
191 Point vec0 = p1 - p2;
192 Point vec1 = p1 - p3;
193 Point normal = vec0.cross(vec1);
194 normal /= normal.norm();
195 dist = std::abs(normal(0) * (p0(0) - p1(0)) + normal(1) * (p0(1) - p1(1)) +
196 normal(2) * (p0(2) - p1(2)));
238 std::multimap<SubdomainID, SubdomainID> connect_block_id_pairs,
239 std::multimap<SubdomainID, SubdomainID> non_connect_block_id_pairs)
250 bool is_interface =
false;
251 if (!connect_block_id_pairs.empty())
255 if (!non_connect_block_id_pairs.empty())
263 bool intersect =
false;
306 SubdomainID pdnode_blockID_j,
307 std::multimap<SubdomainID, SubdomainID> blockID_pairs)
309 bool is_interface =
false;
310 std::pair<std::multimap<SubdomainID, SubdomainID>::iterator,
311 std::multimap<SubdomainID, SubdomainID>::iterator>
314 ret = blockID_pairs.equal_range(pdnode_blockID_i);
315 for (std::multimap<SubdomainID, SubdomainID>::iterator it = ret.first; it != ret.second; ++it)
316 if (pdnode_blockID_j == it->second)
320 ret = blockID_pairs.equal_range(pdnode_blockID_j);
321 for (std::multimap<SubdomainID, SubdomainID>::iterator it = ret.first; it != ret.second; ++it)
322 if (pdnode_blockID_i == it->second)
336 Real dg_vol_sum = 0.0;
337 std::vector<Real> dg_vol(n_pd_neighbors.size(), 0.0);
338 for (
unsigned int j = 0; j < n_pd_neighbors.size(); ++j)
339 for (
unsigned int k = j; k < n_pd_neighbors.size(); ++k)
356 for (
unsigned int j = 0; j < n_pd_neighbors.size(); ++j)
361 std::vector<dof_id_type>
371 auto it = std::find(n_pd_neighbors.begin(), n_pd_neighbors.end(), node_j);
372 if (it != n_pd_neighbors.end())
373 return it - n_pd_neighbors.begin();
376 "Material point ", node_j,
" is not in the neighbor list of material point ", node_i);
381 std::vector<dof_id_type>
385 mooseError(
"Querying node ID exceeds the available PD node IDs!");
390 std::vector<dof_id_type>
394 mooseError(
"Querying node ID exceeds the available PD node IDs!");
396 std::vector<dof_id_type> dg_neighbors =
_dg_neighbors[node_id][neighbor_id];
397 if (dg_neighbors.size() <
_dim)
398 mooseError(
"Not enough number of neighbors to calculate deformation gradient at PD node: ",
408 mooseError(
"Querying node ID exceeds the available PD node IDs!");
423 mooseError(
"Querying node ID exceeds the available PD node IDs!");
428 std::vector<dof_id_type>
438 mooseError(
"Querying node ID exceeds the available PD node IDs!");
447 mooseError(
"Querying node ID exceeds the available PD node IDs!");
456 mooseError(
"Querying node ID exceeds the available PD node IDs!");
465 mooseError(
"Querying node ID exceeds the available PD node IDs!");
474 mooseError(
"Querying node ID exceeds the available PD node IDs!");
490 Point point, Point rec_p1, Point rec_p2, Real rec_height, Real
tol)
492 Real crack_length = (rec_p2 - rec_p1).norm();
493 bool inside = crack_length;
497 Real a = rec_p2(1) - rec_p1(1);
498 Real b = rec_p1(0) - rec_p2(0);
499 Real c = rec_p2(0) * rec_p1(1) - rec_p2(1) * rec_p1(0);
500 inside *= std::abs(a * point(0) + b * point(1) + c) / crack_length < rec_height / 2.0;
502 a = rec_p2(0) - rec_p1(0);
503 b = rec_p2(1) - rec_p1(1);
504 c = 0.5 * (rec_p1(1) * rec_p1(1) - rec_p2(1) * rec_p2(1) - rec_p2(0) * rec_p2(0) +
505 rec_p1(0) * rec_p1(0));
506 inside *= std::abs(a * point(0) + b * point(1) + c) / crack_length < (
tol + crack_length) / 2.0;
514 Point crack_p1, Point crack_p2, Real crack_width, Point bond_p1, Point bond_p2)
516 bool intersect0 =
false;
517 bool intersect1 =
false;
518 bool intersect2 =
false;
519 if ((crack_p2 - crack_p1).norm())
522 if (crack_width != 0.)
524 Real crack_len = (crack_p1 - crack_p2).norm();
525 Real cos_crack = (crack_p2(0) - crack_p1(0)) / crack_len;
526 Real sin_crack = (crack_p2(1) - crack_p1(1)) / crack_len;
527 Real new_crack_p1x = crack_p1(0) - crack_width / 2.0 * sin_crack;
528 Real new_crack_p1y = crack_p1(1) + crack_width / 2.0 * cos_crack;
529 Real new_crack_p2x = crack_p2(0) - crack_width / 2.0 * sin_crack;
530 Real new_crack_p2y = crack_p2(1) + crack_width / 2.0 * cos_crack;
531 Point new_crack_p1 = Point(new_crack_p1x, new_crack_p1y, 0.);
532 Point new_crack_p2 = Point(new_crack_p2x, new_crack_p2y, 0.);
534 new_crack_p1x = crack_p1(0) + crack_width / 2.0 * sin_crack;
535 new_crack_p1y = crack_p1(1) - crack_width / 2.0 * cos_crack;
536 new_crack_p2x = crack_p2(0) + crack_width / 2.0 * sin_crack;
537 new_crack_p2y = crack_p2(1) - crack_width / 2.0 * cos_crack;
538 new_crack_p1 = Point(new_crack_p1x, new_crack_p1y, 0.);
539 new_crack_p2 = Point(new_crack_p2x, new_crack_p2y, 0.);
544 return intersect0 || intersect1 || intersect2;
554 if ((seg1_p1(0) == seg2_p1(0) && seg1_p1(1) == seg2_p1(1)) ||
555 (seg1_p2(0) == seg2_p1(0) && seg1_p2(1) == seg2_p1(1)) ||
556 (seg1_p1(0) == seg2_p2(0) && seg1_p1(1) == seg2_p2(1)) ||
557 (seg1_p2(0) == seg2_p2(0) && seg1_p2(1) == seg2_p2(1)))
563 if ((seg1_p1(1) - seg1_p2(1)) / (seg1_p1(0) - seg1_p2(0)) ==
564 (seg1_p1(1) - seg2_p1(1)) / (seg1_p1(0) - seg2_p1(0)) ||
565 (seg1_p1(1) - seg1_p2(1)) / (seg1_p1(0) - seg1_p2(0)) ==
566 (seg1_p1(1) - seg2_p2(1)) / (seg1_p1(0) - seg2_p2(0)) ||
567 (seg2_p1(1) - seg2_p2(1)) / (seg2_p1(0) - seg2_p2(0)) ==
568 (seg2_p1(1) - seg1_p1(1)) / (seg2_p1(0) - seg1_p1(0)) ||
569 (seg2_p1(1) - seg2_p2(1)) / (seg2_p1(0) - seg2_p2(0)) ==
570 (seg2_p1(1) - seg1_p2(1)) / (seg2_p1(0) - seg1_p2(0)))
572 Real COSseg1_seg2 = (seg1_p2 - seg1_p1) * (seg2_p2 - seg2_p1) /
573 ((seg1_p2 - seg1_p1).norm() * (seg2_p2 - seg2_p1).norm());
574 if (COSseg1_seg2 > -0.08715574 && COSseg1_seg2 < 0.08715574)
579 seg1_p2(0) -= seg1_p1(0);
580 seg1_p2(1) -= seg1_p1(1);
581 seg2_p1(0) -= seg1_p1(0);
582 seg2_p1(1) -= seg1_p1(1);
583 seg2_p2(0) -= seg1_p1(0);
584 seg2_p2(1) -= seg1_p1(1);
587 Real seg1_len = seg1_p2.norm();
590 Real cos_seg1 = seg1_p2(0) / seg1_len;
591 Real sin_seg1 = seg1_p2(1) / seg1_len;
592 Real newX = seg2_p1(0) * cos_seg1 + seg2_p1(1) * sin_seg1;
593 seg2_p1(1) = seg2_p1(1) * cos_seg1 - seg2_p1(0) * sin_seg1;
595 newX = seg2_p2(0) * cos_seg1 + seg2_p2(1) * sin_seg1;
596 seg2_p2(1) = seg2_p2(1) * cos_seg1 - seg2_p2(0) * sin_seg1;
600 if ((seg2_p1(1) < 0. && seg2_p2(1) < 0.) || (seg2_p1(1) >= 0. && seg2_p2(1) >= 0.))
605 Real seg1_pos = seg2_p2(0) + (seg2_p1(0) - seg2_p2(0)) * seg2_p2(1) / (seg2_p2(1) - seg2_p1(1));
606 if (seg1_pos < 0. || seg1_pos > seg1_len)