https://mooseframework.inl.gov
Loading...
Searching...
No Matches
PeridynamicsMesh.C
Go to the documentation of this file.
1//* This file is part of the MOOSE framework
2//* https://mooseframework.inl.gov
3//*
4//* All rights reserved, see COPYRIGHT for full restrictions
5//* https://github.com/idaholab/moose/blob/master/COPYRIGHT
6//*
7//* Licensed under LGPL 2.1, please see LICENSE for details
8//* https://www.gnu.org/licenses/lgpl-2.1.html
9
10#include "PeridynamicsMesh.h"
11
12#include "libmesh/elem.h"
13
15
18{
20 params.addClassDescription("Mesh class to store and return peridynamics specific mesh data");
21
22 params.addParam<Real>("horizon_radius", "Value of horizon size in terms of radius");
23 params.addParam<Real>("horizon_number",
24 "The material points spacing number, i.e. ratio of horizon radius to the "
25 "effective average spacing");
26 params.addParam<Real>("bond_associated_horizon_ratio",
27 1.5,
28 "Ratio of bond-associated horizon to nodal horizon. This is the only "
29 "parameters to control the size of bond-associated horizon");
30 params.addParam<std::vector<Point>>("cracks_start",
31 "Cartesian coordinates where predefined line cracks start");
32 params.addParam<std::vector<Point>>("cracks_end",
33 "Cartesian coordinates where predefined line cracks end");
34 params.addParam<std::vector<Real>>("cracks_width", "Widths of predefined line cracks");
35
36 params.set<bool>("_mesh_generator_mesh") = true;
37
38 return params;
39}
40
42 : MooseMesh(parameters),
43 _horizon_radius(isParamValid("horizon_radius") ? getParam<Real>("horizon_radius") : 0),
44 _has_horizon_number(isParamValid("horizon_number")),
45 _horizon_number(_has_horizon_number ? getParam<Real>("horizon_number") : 0),
46 _bah_ratio(getParam<Real>("bond_associated_horizon_ratio")),
47 _has_cracks(isParamValid("cracks_start") || isParamValid("cracks_end")),
48 _dim(declareRestartableData<unsigned int>("dim")),
49 _n_pdnodes(declareRestartableData<unsigned int>("n_pdnodes")),
50 _n_pdbonds(declareRestartableData<unsigned int>("n_pdbonds")),
51 _pdnode_average_spacing(declareRestartableData<std::vector<Real>>("pdnode_average_spacing")),
52 _pdnode_horizon_radius(declareRestartableData<std::vector<Real>>("pdnode_horizon_radius")),
53 _pdnode_vol(declareRestartableData<std::vector<Real>>("pdnode_vol")),
54 _pdnode_horizon_vol(declareRestartableData<std::vector<Real>>("pdnode_horizon_vol")),
55 _pdnode_blockID(declareRestartableData<std::vector<SubdomainID>>("pdnode_blockID")),
56 _pdnode_elemID(declareRestartableData<std::vector<dof_id_type>>("pdnode_elemID")),
57 _pdnode_neighbors(
58 declareRestartableData<std::vector<std::vector<dof_id_type>>>("pdnode_neighbors")),
59 _pdnode_bonds(declareRestartableData<std::vector<std::vector<dof_id_type>>>("pdnode_bonds")),
60 _dg_neighbors(
61 declareRestartableData<std::vector<std::vector<std::vector<dof_id_type>>>>("dg_neighbors")),
62 _pdnode_sub_vol(declareRestartableData<std::vector<std::vector<Real>>>("pdnode_sub_vol")),
63 _pdnode_sub_vol_sum(declareRestartableData<std::vector<Real>>("pdnode_sub_vol_sum")),
64 _boundary_node_offset(
65 declareRestartableData<std::map<dof_id_type, Real>>("boundary_node_offset")),
66 _pdnode_weight_normalizer(declareRestartableData<std::vector<Real>>("pdnode_weight_normalizer"))
67{
68 if (!(isParamValid("horizon_radius") || _has_horizon_number))
69 mooseError("Must specify either horizon_radius or horizon_number to determine horizon size in "
70 "the mesh block!");
71
72 if (_has_cracks)
73 {
74 _cracks_start = getParam<std::vector<Point>>("cracks_start");
75 _cracks_end = getParam<std::vector<Point>>("cracks_end");
76 }
77 else
78 {
79 _cracks_start.push_back(Point(0., 0., 0.));
80 _cracks_end.push_back(Point(0., 0., 0.));
81 }
82
83 if (_cracks_start.size() != _cracks_end.size())
85 "Number of cracks starting points is NOT the same as number of cracks ending points!");
86
87 if (_has_cracks)
88 {
89 if (isParamValid("cracks_width"))
90 {
91 _cracks_width = getParam<std::vector<Real>>("cracks_width");
92 if (_cracks_width.size() != _cracks_start.size())
93 mooseError("Number of cracks width is NOT the same as number of cracks!");
94 }
95 else
96 {
97 for (unsigned int i = 0; i < _cracks_start.size(); ++i)
98 _cracks_width.push_back(0);
99 }
100 }
101 else
102 _cracks_width.push_back(0);
103}
104
105std::unique_ptr<MooseMesh>
107{
108 return _app.getFactory().copyConstruct(*this);
109}
110
111void
113{
114 if (!hasMeshBase())
115 {
116 auto & entry = _app.getMeshGeneratorSystem();
117 _mesh = entry.getSavedMesh(entry.mainMeshGeneratorName());
118 }
119 _mesh->allow_renumbering(false);
120 _mesh->prepare_for_use();
121 _mesh->allow_renumbering(true);
122}
123
124unsigned int
126{
127 return _dim;
128}
129
130dof_id_type
132{
133 return _n_pdnodes;
134}
135
136dof_id_type
138{
139 return _n_pdbonds;
140}
141
142void
144 MeshBase & fe_mesh,
145 std::set<dof_id_type> converted_elem_id,
146 std::multimap<SubdomainID, SubdomainID> bonding_block_pairs,
147 std::multimap<SubdomainID, SubdomainID> non_bonding_block_pairs)
148{
149 _dim = fe_mesh.mesh_dimension();
150 _n_pdnodes = converted_elem_id.size();
151
152 // initialize data size
156 _pdnode_vol.resize(_n_pdnodes);
157 _pdnode_horizon_vol.resize(_n_pdnodes, 0.0);
164 _pdnode_sub_vol_sum.resize(_n_pdnodes, 0.0);
166
167 // loop through converted fe elements to generate PD nodes structure
168 unsigned int id = 0; // make pd nodes start at 0 in the new mesh
169 for (const auto & eid : converted_elem_id)
170 {
171 Elem * fe_elem = fe_mesh.elem_ptr(eid);
172 // calculate the nodes spacing as average distance between fe element with its neighbors
173 unsigned int n_fe_neighbors = 0;
174 Real dist_sum = 0.0;
175 for (unsigned int j = 0; j < fe_elem->n_neighbors(); ++j)
176 if (fe_elem->neighbor_ptr(j) != nullptr)
177 {
178 dist_sum += (fe_elem->vertex_average() - fe_elem->neighbor_ptr(j)->vertex_average()).norm();
179 n_fe_neighbors++;
180 }
181 else // this side is on boundary and calculate the distance to the centroid
182 {
183 Real dist = 0.0;
184 std::vector<unsigned int> nid = fe_elem->nodes_on_side(j);
185 Point p0 = fe_elem->vertex_average();
186 Point p1 = fe_elem->point(nid[0]);
187 if (fe_elem->dim() == 2) // 2D elems
188 {
189 Point p2 = fe_elem->point(nid.back());
190 Real area = 0.5 * std::abs(p0(0) * (p1(1) - p2(1)) + p1(0) * (p2(1) - p0(1)) +
191 p2(0) * (p0(1) - p1(1)));
192 dist = 2.0 * area / fe_elem->length(nid[0], nid[1]);
193 }
194 else // 3D elems
195 {
196 Point p2 = fe_elem->point(nid[1]);
197 Point p3 = fe_elem->point(nid.back());
198 Point vec0 = p1 - p2;
199 Point vec1 = p1 - p3;
200 Point normal = vec0.cross(vec1);
201 normal /= normal.norm();
202 dist = std::abs(normal(0) * (p0(0) - p1(0)) + normal(1) * (p0(1) - p1(1)) +
203 normal(2) * (p0(2) - p1(2)));
204 }
205 _boundary_node_offset.insert(std::make_pair(id, -dist));
206 }
207
208 _pdnode_coord[id] = fe_elem->vertex_average();
209 _pdnode_average_spacing[id] = dist_sum / n_fe_neighbors;
211 (_has_horizon_number ? _horizon_number * dist_sum / n_fe_neighbors : _horizon_radius);
212 // NOTE: PeridynamicsMesh does not support RZ/RSpherical so using volume from libmesh elem is
213 // fine
214 _pdnode_vol[id] = fe_elem->volume();
215 _pdnode_blockID[id] = fe_elem->subdomain_id() + 1000; // set new subdomain id for PD mesh in
216 // case FE mesh is retained
217 _pdnode_elemID[id] = fe_elem->id();
218
219 ++id;
220 }
221
222 // search node neighbors and create other nodal data
223 createNodeHorizBasedData(bonding_block_pairs, non_bonding_block_pairs);
224
225 createNeighborHorizonBasedData(); // applies to non-ordinary state-based model only.
226
227 // total number of peridynamic bonds
228 _n_pdbonds = 0;
229 for (unsigned int i = 0; i < _n_pdnodes; ++i)
230 _n_pdbonds += _pdnode_neighbors[i].size();
231 _n_pdbonds /= 2;
232
233 unsigned int k = 0;
234 for (unsigned int i = 0; i < _n_pdnodes; ++i)
235 for (unsigned int j = 0; j < _pdnode_neighbors[i].size(); ++j)
236 if (_pdnode_neighbors[i][j] > i)
237 {
238 // build the bond list for each node
239 _pdnode_bonds[i].push_back(k);
240 _pdnode_bonds[_pdnode_neighbors[i][j]].push_back(k);
241 ++k;
242 }
243}
244
245void
247 std::multimap<SubdomainID, SubdomainID> bonding_block_pairs,
248 std::multimap<SubdomainID, SubdomainID> non_bonding_block_pairs)
249{
250 // search neighbors
251 for (unsigned int i = 0; i < _n_pdnodes; ++i)
252 {
253 Real dis = 0.0;
254 for (unsigned int j = 0; j < _n_pdnodes; ++j)
255 {
256 dis = (_pdnode_coord[i] - _pdnode_coord[j]).norm();
257 if (dis <= 1.0001 * _pdnode_horizon_radius[i] && j != i)
258 {
259 bool is_interface = false;
260 if (!bonding_block_pairs.empty())
261 is_interface =
262 checkInterface(_pdnode_blockID[i], _pdnode_blockID[j], bonding_block_pairs);
263
264 if (!non_bonding_block_pairs.empty())
265 is_interface =
266 !checkInterface(_pdnode_blockID[i], _pdnode_blockID[j], non_bonding_block_pairs);
267
268 if (_pdnode_blockID[i] == _pdnode_blockID[j] || is_interface)
269 {
270 // check whether pdnode i falls in the region whose bonds may need to be removed due to
271 // the pre-existing cracks
272 bool intersect = false;
273 for (unsigned int k = 0; k < _cracks_start.size(); ++k)
274 {
276 _cracks_start[k],
277 _cracks_end[k],
279 4.0 * _pdnode_horizon_radius[i]))
280 intersect = intersect || checkCrackIntersectBond(_cracks_start[k],
281 _cracks_end[k],
282 _cracks_width[k],
283 _pdnode_coord[i],
284 _pdnode_coord[j]);
285 }
286 // remove bonds cross the crack to form crack surface
287 if (!intersect)
288 {
289 // Use the addition balance scheme to remove unbalanced interactions
290 // check whether j was already considered as a neighbor of i, if not, add j to i's
291 // neighborlist
292 if (std::find(_pdnode_neighbors[i].begin(), _pdnode_neighbors[i].end(), j) ==
293 _pdnode_neighbors[i].end())
294 {
295 _pdnode_neighbors[i].push_back(j);
298 }
299 // check whether i was also considered as a neighbor of j, if not, add i to j's
300 // neighborlist
301 if (std::find(_pdnode_neighbors[j].begin(), _pdnode_neighbors[j].end(), i) ==
302 _pdnode_neighbors[j].end())
303 {
304 _pdnode_neighbors[j].push_back(i);
307 }
308 }
309 }
310 }
311 }
312 }
313}
314
315bool
317 SubdomainID pdnode_blockID_j,
318 std::multimap<SubdomainID, SubdomainID> blockID_pairs)
319{
320 bool is_interface = false;
321 std::pair<std::multimap<SubdomainID, SubdomainID>::iterator,
322 std::multimap<SubdomainID, SubdomainID>::iterator>
323 ret;
324 // check existence of the case when i is the key and j is the value
325 ret = blockID_pairs.equal_range(pdnode_blockID_i);
326 for (std::multimap<SubdomainID, SubdomainID>::iterator it = ret.first; it != ret.second; ++it)
327 if (pdnode_blockID_j == it->second)
328 is_interface = true;
329
330 // check existence of the case when j is the key and i is the value
331 ret = blockID_pairs.equal_range(pdnode_blockID_j);
332 for (std::multimap<SubdomainID, SubdomainID>::iterator it = ret.first; it != ret.second; ++it)
333 if (pdnode_blockID_i == it->second)
334 is_interface = true;
335
336 return is_interface;
337}
338
339void
341{
342 for (unsigned int i = 0; i < _n_pdnodes; ++i)
343 {
344 std::vector<dof_id_type> n_pd_neighbors = _pdnode_neighbors[i];
345 _dg_neighbors[i].resize(n_pd_neighbors.size());
346 _pdnode_sub_vol[i].resize(n_pd_neighbors.size(), 0.0);
347
348 for (unsigned int j = 0; j < n_pd_neighbors.size(); ++j)
349 for (unsigned int k = j; k < n_pd_neighbors.size(); ++k) // only search greater number index
350 if ((_pdnode_coord[n_pd_neighbors[j]] - _pdnode_coord[n_pd_neighbors[k]]).norm() <=
352 {
353 // only save the corresponding index in neighbor list, rather than the actual node id
354 // for neighbor j
355 _dg_neighbors[i][j].push_back(k);
356 _pdnode_sub_vol[i][j] += _pdnode_vol[n_pd_neighbors[k]];
357 _pdnode_sub_vol_sum[i] += _pdnode_vol[n_pd_neighbors[k]];
358 // for neighbor k
359 if (k > j)
360 {
361 _dg_neighbors[i][k].push_back(j);
362 _pdnode_sub_vol[i][k] += _pdnode_vol[n_pd_neighbors[j]];
363 _pdnode_sub_vol_sum[i] += _pdnode_vol[n_pd_neighbors[j]];
364 }
365 }
366 }
367}
368
369std::vector<dof_id_type>
371{
372 return _pdnode_neighbors[node_id];
373}
374
375dof_id_type
376PeridynamicsMesh::getNeighborIndex(dof_id_type node_i, dof_id_type node_j)
377{
378 std::vector<dof_id_type> n_pd_neighbors = _pdnode_neighbors[node_i];
379 auto it = std::find(n_pd_neighbors.begin(), n_pd_neighbors.end(), node_j);
380 if (it != n_pd_neighbors.end())
381 return it - n_pd_neighbors.begin();
382 else
384 "Material point ", node_j, " is not in the neighbor list of material point ", node_i);
385
386 return -1;
387}
388
389std::vector<dof_id_type>
390PeridynamicsMesh::getBonds(dof_id_type node_id)
391{
392 if (node_id > _n_pdnodes)
393 mooseError("Querying node ID exceeds the available PD node IDs!");
394
395 return _pdnode_bonds[node_id];
396}
397
398std::vector<dof_id_type>
399PeridynamicsMesh::getBondDeformationGradientNeighbors(dof_id_type node_id, dof_id_type neighbor_id)
400{
401 if (node_id > _n_pdnodes)
402 mooseError("Querying node ID exceeds the available PD node IDs!");
403
404 if (neighbor_id > _pdnode_neighbors[node_id].size() - 1)
405 mooseError("Querying neighbor index exceeds the available neighbors!");
406
407 std::vector<dof_id_type> dg_neighbors = _dg_neighbors[node_id][neighbor_id];
408 if (dg_neighbors.size() < _dim)
409 mooseError("Not enough number of neighbors to calculate deformation gradient at PD node: ",
410 node_id);
411
412 return dg_neighbors;
413}
414
417{
418 if (node_id > _n_pdnodes)
419 mooseError("Querying node ID exceeds the available PD node IDs!");
420
421 return _pdnode_blockID[node_id];
422}
423
424void
429
430Point
432{
433 if (node_id > _n_pdnodes)
434 mooseError("Querying node ID exceeds the available PD node IDs!");
435
436 return _pdnode_coord[node_id];
437}
438
439std::vector<dof_id_type>
444
445Real
447{
448 if (node_id > _n_pdnodes)
449 mooseError("Querying node ID exceeds the available PD node IDs!");
450
451 return _pdnode_vol[node_id];
452}
453
454Real
456{
457 if (node_id > _n_pdnodes)
458 mooseError("Querying node ID exceeds the available PD node IDs!");
459
460 return _pdnode_horizon_vol[node_id];
461}
462
463Real
464PeridynamicsMesh::getHorizonSubsetVolume(dof_id_type node_id, dof_id_type neighbor_id)
465{
466 if (node_id > _n_pdnodes)
467 mooseError("Querying node ID exceeds the available PD node IDs!");
468
469 if (neighbor_id > _pdnode_neighbors[node_id].size() - 1)
470 mooseError("Querying neighbor index exceeds the available neighbors!");
471
472 return _pdnode_sub_vol[node_id][neighbor_id];
473}
474
475Real
477{
478 if (node_id > _n_pdnodes)
479 mooseError("Querying node ID exceeds the available PD node IDs!");
480
481 return _pdnode_sub_vol_sum[node_id];
482}
483
484Real
485PeridynamicsMesh::getHorizonSubsetVolumeFraction(dof_id_type node_id, dof_id_type neighbor_id)
486{
487 if (node_id > _n_pdnodes)
488 mooseError("Querying node ID exceeds the available PD node IDs!");
489
490 if (neighbor_id > _pdnode_neighbors[node_id].size() - 1)
491 mooseError("Querying neighbor index exceeds the available neighbors!");
492
493 return _pdnode_sub_vol[node_id][neighbor_id] / _pdnode_sub_vol_sum[node_id];
494}
495
496Real
498{
499 if (node_id > _n_pdnodes)
500 mooseError("Querying node ID exceeds the available PD node IDs!");
501
502 return _pdnode_average_spacing[node_id];
503}
504
505Real
507{
508 if (node_id > _n_pdnodes)
509 mooseError("Querying node ID exceeds the available PD node IDs!");
510
511 return _pdnode_horizon_radius[node_id];
512}
513
514Real
516{
517 if (_boundary_node_offset.count(node_id))
518 return _boundary_node_offset[node_id];
519 else
520 return 0.0;
521}
522
523Real
524PeridynamicsMesh::getNeighborWeight(dof_id_type node_id, dof_id_type neighbor_id)
525{
526 if (node_id > _n_pdnodes)
527 mooseError("Querying node ID exceeds the available PD node IDs!");
528
529 if (neighbor_id > _pdnode_neighbors[node_id].size() - 1)
530 mooseError("Querying neighbor index exceeds the available neighbors!");
531
532 Real dis =
533 (_pdnode_coord[node_id] - _pdnode_coord[_pdnode_neighbors[node_id][neighbor_id]]).norm();
534 Real result = _pdnode_horizon_radius[node_id] / dis / _pdnode_weight_normalizer[node_id];
535
536 return result;
537}
538
539bool
541 Point point, Point rec_p1, Point rec_p2, Real rec_height, Real tol)
542{
543 Real crack_length = (rec_p2 - rec_p1).norm();
544 bool inside = crack_length;
545
546 if (inside)
547 {
548 Real a = rec_p2(1) - rec_p1(1);
549 Real b = rec_p1(0) - rec_p2(0);
550 Real c = rec_p2(0) * rec_p1(1) - rec_p2(1) * rec_p1(0);
551 inside =
552 inside && (std::abs(a * point(0) + b * point(1) + c) / crack_length < rec_height / 2.0);
553
554 a = rec_p2(0) - rec_p1(0);
555 b = rec_p2(1) - rec_p1(1);
556 c = 0.5 * (rec_p1(1) * rec_p1(1) - rec_p2(1) * rec_p2(1) - rec_p2(0) * rec_p2(0) +
557 rec_p1(0) * rec_p1(0));
558 inside = inside && (std::abs(a * point(0) + b * point(1) + c) / crack_length <
559 (tol + crack_length) / 2.0);
560 }
561
562 return inside;
563}
564
565bool
567 Point crack_p1, Point crack_p2, Real crack_width, Point bond_p1, Point bond_p2)
568{
569 bool intersect0 = false;
570 bool intersect1 = false;
571 bool intersect2 = false;
572 if ((crack_p2 - crack_p1).norm())
573 {
574 intersect0 = checkSegmentIntersectSegment(crack_p1, crack_p2, bond_p1, bond_p2);
575 if (crack_width != 0.)
576 {
577 Real crack_len = (crack_p1 - crack_p2).norm();
578 Real cos_crack = (crack_p2(0) - crack_p1(0)) / crack_len;
579 Real sin_crack = (crack_p2(1) - crack_p1(1)) / crack_len;
580 Real new_crack_p1x = crack_p1(0) - crack_width / 2.0 * sin_crack;
581 Real new_crack_p1y = crack_p1(1) + crack_width / 2.0 * cos_crack;
582 Real new_crack_p2x = crack_p2(0) - crack_width / 2.0 * sin_crack;
583 Real new_crack_p2y = crack_p2(1) + crack_width / 2.0 * cos_crack;
584 Point new_crack_p1 = Point(new_crack_p1x, new_crack_p1y, 0.);
585 Point new_crack_p2 = Point(new_crack_p2x, new_crack_p2y, 0.);
586 intersect1 = checkSegmentIntersectSegment(new_crack_p1, new_crack_p2, bond_p1, bond_p2);
587 new_crack_p1x = crack_p1(0) + crack_width / 2.0 * sin_crack;
588 new_crack_p1y = crack_p1(1) - crack_width / 2.0 * cos_crack;
589 new_crack_p2x = crack_p2(0) + crack_width / 2.0 * sin_crack;
590 new_crack_p2y = crack_p2(1) - crack_width / 2.0 * cos_crack;
591 new_crack_p1 = Point(new_crack_p1x, new_crack_p1y, 0.);
592 new_crack_p2 = Point(new_crack_p2x, new_crack_p2y, 0.);
593 intersect2 = checkSegmentIntersectSegment(new_crack_p1, new_crack_p2, bond_p1, bond_p2);
594 }
595 }
596
597 return intersect0 || intersect1 || intersect2;
598}
599
600bool
602 Point seg1_p2,
603 Point seg2_p1,
604 Point seg2_p2)
605{
606 // Fail if the segments share an end-point
607 if ((seg1_p1(0) == seg2_p1(0) && seg1_p1(1) == seg2_p1(1)) ||
608 (seg1_p2(0) == seg2_p1(0) && seg1_p2(1) == seg2_p1(1)) ||
609 (seg1_p1(0) == seg2_p2(0) && seg1_p1(1) == seg2_p2(1)) ||
610 (seg1_p2(0) == seg2_p2(0) && seg1_p2(1) == seg2_p2(1)))
611 {
612 return false;
613 }
614
615 // Fail if the segments intersect at a given end-point but not normal to the crack
616 if ((seg1_p1(1) - seg1_p2(1)) / (seg1_p1(0) - seg1_p2(0)) ==
617 (seg1_p1(1) - seg2_p1(1)) / (seg1_p1(0) - seg2_p1(0)) ||
618 (seg1_p1(1) - seg1_p2(1)) / (seg1_p1(0) - seg1_p2(0)) ==
619 (seg1_p1(1) - seg2_p2(1)) / (seg1_p1(0) - seg2_p2(0)) ||
620 (seg2_p1(1) - seg2_p2(1)) / (seg2_p1(0) - seg2_p2(0)) ==
621 (seg2_p1(1) - seg1_p1(1)) / (seg2_p1(0) - seg1_p1(0)) ||
622 (seg2_p1(1) - seg2_p2(1)) / (seg2_p1(0) - seg2_p2(0)) ==
623 (seg2_p1(1) - seg1_p2(1)) / (seg2_p1(0) - seg1_p2(0)))
624 {
625 Real COSseg1_seg2 = (seg1_p2 - seg1_p1) * (seg2_p2 - seg2_p1) /
626 ((seg1_p2 - seg1_p1).norm() * (seg2_p2 - seg2_p1).norm());
627 if (COSseg1_seg2 > -0.08715574 && COSseg1_seg2 < 0.08715574)
628 return false;
629 }
630
631 // Translate the system so that point seg1_p1 is on the origin
632 seg1_p2(0) -= seg1_p1(0);
633 seg1_p2(1) -= seg1_p1(1);
634 seg2_p1(0) -= seg1_p1(0);
635 seg2_p1(1) -= seg1_p1(1);
636 seg2_p2(0) -= seg1_p1(0);
637 seg2_p2(1) -= seg1_p1(1);
638
639 // Length of segment seg1_p1-seg1_p2
640 Real seg1_len = seg1_p2.norm();
641
642 // Rotate the system so that point seg1_p2 is on the positive X axis
643 Real cos_seg1 = seg1_p2(0) / seg1_len;
644 Real sin_seg1 = seg1_p2(1) / seg1_len;
645 Real newX = seg2_p1(0) * cos_seg1 + seg2_p1(1) * sin_seg1;
646 seg2_p1(1) = seg2_p1(1) * cos_seg1 - seg2_p1(0) * sin_seg1;
647 seg2_p1(0) = newX;
648 newX = seg2_p2(0) * cos_seg1 + seg2_p2(1) * sin_seg1;
649 seg2_p2(1) = seg2_p2(1) * cos_seg1 - seg2_p2(0) * sin_seg1;
650 seg2_p2(0) = newX;
651
652 // Fail if segment seg2_p1-seg2_p2 doesn't cross segment seg1_p1-seg1_p2
653 if ((seg2_p1(1) < 0. && seg2_p2(1) < 0.) || (seg2_p1(1) >= 0. && seg2_p2(1) >= 0.))
654 return false;
655
656 // Fail if segment seg2_p1-seg2_p2 crosses segment seg1_p1-seg1_p2 outside of segment
657 // seg1_p1-seg1_p2
658 Real seg1_pos = seg2_p2(0) + (seg2_p1(0) - seg2_p2(0)) * seg2_p2(1) / (seg2_p2(1) - seg2_p1(1));
659 if (seg1_pos < 0. || seg1_pos > seg1_len)
660 return false;
661
662 return true;
663}
const double tol
registerMooseObject("PeridynamicsApp", PeridynamicsMesh)
void ErrorVector unsigned int
std::unique_ptr< T > copyConstruct(const T &object)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
void addClassDescription(const std::string &doc_string)
T & set(const std::string &name, bool quiet_mode=false)
std::unique_ptr< libMesh::MeshBase > getSavedMesh(const std::string &name)
Factory & getFactory()
MeshGeneratorSystem & getMeshGeneratorSystem()
void mooseError(Args &&... args) const
bool isParamValid(const std::string &name) const
std::unique_ptr< libMesh::MeshBase > _mesh
static InputParameters validParams()
bool hasMeshBase() const
MooseApp & _app
Peridynamics mesh class.
std::vector< Point > _cracks_start
std::map< dof_id_type, Real > & _boundary_node_offset
Offset of each boundary node to its original FE element boundary edge or face.
std::vector< std::vector< dof_id_type > > & _pdnode_neighbors
Neighbor lists for each material point determined using the horizon.
Real getHorizonSubsetVolumeSum(dof_id_type node_id)
Function to return the summation of all horizon subset volumes for node node_id.
dof_id_type nPDNodes() const
Function to return number of PD nodes.
Real getNodeVolume(dof_id_type node_id)
Function to return nodal volume for node node_id.
Real getHorizonSubsetVolumeFraction(dof_id_type node_id, dof_id_type neighbor_id)
Function to return the volume fraction of a horizon subset used for bond-associated deformation gradi...
bool checkSegmentIntersectSegment(Point seg1_p1, Point seg1_p2, Point seg2_p1, Point seg2_p2)
Function to check whether a segment crosses another segment.
const Real _horizon_number
Real getHorizon(dof_id_type node_id)
Function to return horizon size.
Point getNodeCoord(dof_id_type node_id)
Function to return coordinates for node node_id.
std::vector< SubdomainID > & _pdnode_blockID
unsigned int & _n_pdnodes
Number of total material points.
std::vector< dof_id_type > getBondDeformationGradientNeighbors(dof_id_type node_id, dof_id_type neighbor_id)
Function to return indices of neighbors used in formulation of bond-associated deformation gradient f...
std::vector< Point > _pdnode_coord
Data associated with each peridynamics node.
std::vector< Real > & _pdnode_horizon_vol
unsigned int & _n_pdbonds
Number of total bonds.
Real getNodeAverageSpacing(dof_id_type node_id)
Function to return the average spacing between node node_id with its most adjacent neighbors.
std::vector< dof_id_type > getBonds(dof_id_type node_id)
Function to return the bond number connected with node node_id.
Real getNeighborWeight(dof_id_type node_id, dof_id_type neighbor_id)
Function to return normalized weight for neighbor neighbor_id of node node_id based on predefined wei...
void setNodeBlockID(SubdomainID id)
Function to set block ID for all PD nodes.
const bool _has_horizon_number
std::vector< Real > & _pdnode_weight_normalizer
normalizer for calculating weighted values at a node from elemental values within its horizon
std::vector< Real > & _pdnode_average_spacing
void createNeighborHorizonBasedData()
Function to create node neighbors and other data for each material point based on NEIGHBOR_HORIZON ba...
unsigned int & _dim
Mesh dimension.
std::vector< Real > & _pdnode_horizon_radius
bool checkCrackIntersectBond(Point crack_p1, Point crack_p2, Real crack_width, Point bond_p1, Point bond_p2)
Function to check whether a bond crosses crack surface.
Real getBoundaryOffset(dof_id_type node_id)
Function to return offset for boundary nodes.
std::vector< Point > _cracks_end
const bool _has_cracks
Information for crack generation.
std::vector< std::vector< std::vector< dof_id_type > > > & _dg_neighbors
Neighbor lists for deformation gradient calculation using bond-associated horizon.
std::vector< Real > & _pdnode_sub_vol_sum
Summation of volumes of all horizon subsets at a node.
virtual std::unique_ptr< MooseMesh > safeClone() const override
Real getHorizonSubsetVolume(dof_id_type node_id, dof_id_type neighbor_id)
Function to return the volume of a horizon subset for bond-associated deformation gradient calculatio...
dof_id_type nPDBonds() const
Function to return number of PD Edge elements.
std::vector< dof_id_type > & _pdnode_elemID
bool checkInterface(SubdomainID pdnode_blockID_i, SubdomainID pdnode_blockID_j, std::multimap< SubdomainID, SubdomainID > blockID_pairs)
Function to check existence of interface between two blocks.
std::vector< dof_id_type > getPDNodeIDToFEElemIDMap()
Function to return the correspondence between PD node IDs and FE element IDs.
PeridynamicsMesh(const InputParameters &parameters)
std::vector< std::vector< Real > > & _pdnode_sub_vol
Volume of horizon subsets for bond-associated deformation gradients at a node.
SubdomainID getNodeBlockID(dof_id_type node_id)
Function to return block ID for node node_id.
virtual unsigned int dimension() const override
static InputParameters validParams()
std::vector< std::vector< dof_id_type > > & _pdnode_bonds
Bond lists associated with material points.
void createPeridynamicsMeshData(MeshBase &fe_mesh, std::set< dof_id_type > converted_elem_id, std::multimap< SubdomainID, SubdomainID > bonding_block_pairs, std::multimap< SubdomainID, SubdomainID > non_bonding_block_pairs)
Function to assign values to member variables (PD mesh data) of this class this function will be call...
std::vector< Real > & _pdnode_vol
bool checkPointInsideRectangle(Point point, Point rec_p1, Point rec_p2, Real rec_height, Real tol=0)
Function to check whether a material point falls within a given rectangular crack geometry.
dof_id_type getNeighborIndex(dof_id_type node_i, dof_id_type node_j)
Function to return the local neighbor index of node_j from node_i's neighbor list.
void createNodeHorizBasedData(std::multimap< SubdomainID, SubdomainID > bonding_block_pairs, std::multimap< SubdomainID, SubdomainID > non_bonding_block_pairs)
Function to create neighbors and other data for each material point with given horizon.
const Real _horizon_radius
Horizon size control parameters.
virtual void buildMesh() override
std::vector< Real > _cracks_width
Real getHorizonVolume(dof_id_type node_id)
Function to return summation of neighbor nodal volumes for node node_id.
std::vector< dof_id_type > getNeighbors(dof_id_type node_id)
Function to return neighbor nodes indices for node node_id.