https://mooseframework.inl.gov
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 
14 registerMooseObject("PeridynamicsApp", PeridynamicsMesh);
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())
84  mooseError(
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 
105 std::unique_ptr<MooseMesh>
107 {
108  return _app.getFactory().copyConstruct(*this);
109 }
110 
111 void
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 
124 unsigned int
126 {
127  return _dim;
128 }
129 
132 {
133  return _n_pdnodes;
134 }
135 
138 {
139  return _n_pdbonds;
140 }
141 
142 void
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
153  _pdnode_coord.resize(_n_pdnodes);
156  _pdnode_vol.resize(_n_pdnodes);
157  _pdnode_horizon_vol.resize(_n_pdnodes, 0.0);
158  _pdnode_blockID.resize(_n_pdnodes);
159  _pdnode_elemID.resize(_n_pdnodes);
161  _pdnode_bonds.resize(_n_pdnodes);
162  _dg_neighbors.resize(_n_pdnodes);
163  _pdnode_sub_vol.resize(_n_pdnodes);
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 
245 void
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 
315 bool
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 
339 void
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 
369 std::vector<dof_id_type>
371 {
372  return _pdnode_neighbors[node_id];
373 }
374 
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
383  mooseError(
384  "Material point ", node_j, " is not in the neighbor list of material point ", node_i);
385 
386  return -1;
387 }
388 
389 std::vector<dof_id_type>
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 
398 std::vector<dof_id_type>
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 
424 void
426 {
427  _pdnode_blockID.assign(_n_pdnodes, id);
428 }
429 
430 Point
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 
439 std::vector<dof_id_type>
441 {
442  return _pdnode_elemID;
443 }
444 
445 Real
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 
454 Real
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 
463 Real
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 
475 Real
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 
484 Real
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 
496 Real
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 
505 Real
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 
514 Real
516 {
517  if (_boundary_node_offset.count(node_id))
518  return _boundary_node_offset[node_id];
519  else
520  return 0.0;
521 }
522 
523 Real
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 
539 bool
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 
565 bool
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 
600 bool
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 }
std::vector< std::vector< dof_id_type > > & _pdnode_neighbors
Neighbor lists for each material point determined using the horizon.
static InputParameters validParams()
std::vector< SubdomainID > & _pdnode_blockID
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.
static InputParameters validParams()
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...
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...
dof_id_type nPDBonds() const
Function to return number of PD Edge elements.
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...
bool checkSegmentIntersectSegment(Point seg1_p1, Point seg1_p2, Point seg2_p1, Point seg2_p2)
Function to check whether a segment crosses another segment.
Real getBoundaryOffset(dof_id_type node_id)
Function to return offset for boundary nodes.
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
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.
std::vector< Point > _cracks_end
std::vector< dof_id_type > getNeighbors(dof_id_type node_id)
Function to return neighbor nodes indices for node node_id.
const double tol
Peridynamics mesh class.
std::vector< std::vector< Real > > & _pdnode_sub_vol
Volume of horizon subsets for bond-associated deformation gradients at a node.
T & set(const std::string &name, bool quiet_mode=false)
unsigned int & _n_pdnodes
Number of total material points.
Real getHorizonSubsetVolumeSum(dof_id_type node_id)
Function to return the summation of all horizon subset volumes for node node_id.
std::vector< Real > & _pdnode_vol
std::vector< Real > & _pdnode_sub_vol_sum
Summation of volumes of all horizon subsets at a node.
std::vector< Real > & _pdnode_average_spacing
std::map< dof_id_type, Real > & _boundary_node_offset
Offset of each boundary node to its original FE element boundary edge or face.
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 > getPDNodeIDToFEElemIDMap()
Function to return the correspondence between PD node IDs and FE element IDs.
std::vector< dof_id_type > & _pdnode_elemID
std::vector< Point > _pdnode_coord
Data associated with each peridynamics node.
PeridynamicsMesh(const InputParameters &parameters)
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&#39;s neighbor list.
std::unique_ptr< T > copyConstruct(const T &object)
Factory & getFactory()
virtual void buildMesh() override
bool isParamValid(const std::string &name) const
void createNeighborHorizonBasedData()
Function to create node neighbors and other data for each material point based on NEIGHBOR_HORIZON ba...
const Real _horizon_number
const Real _horizon_radius
Horizon size control parameters.
const bool _has_cracks
Information for crack generation.
Real getHorizonVolume(dof_id_type node_id)
Function to return summation of neighbor nodal volumes for node node_id.
virtual std::unique_ptr< MooseMesh > safeClone() const override
unsigned int & _dim
Mesh dimension.
std::vector< Real > & _pdnode_horizon_vol
SubdomainID getNodeBlockID(dof_id_type node_id)
Function to return block ID for node node_id.
dof_id_type nPDNodes() const
Function to return number of PD nodes.
auto norm(const T &a) -> decltype(std::abs(a))
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...
std::vector< Real > & _pdnode_horizon_radius
std::vector< Real > & _pdnode_weight_normalizer
normalizer for calculating weighted values at a node from elemental values within its horizon ...
Real getNodeVolume(dof_id_type node_id)
Function to return nodal volume for node node_id.
std::vector< Real > _cracks_width
std::vector< std::vector< dof_id_type > > & _pdnode_bonds
Bond lists associated with material points.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Point getNodeCoord(dof_id_type node_id)
Function to return coordinates for node node_id.
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...
MooseApp & _app
bool hasMeshBase() const
std::unique_ptr< libMesh::MeshBase > _mesh
const bool _has_horizon_number
std::vector< std::vector< std::vector< dof_id_type > > > & _dg_neighbors
Neighbor lists for deformation gradient calculation using bond-associated horizon.
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
virtual unsigned int dimension() const override
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
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.
MeshGeneratorSystem & getMeshGeneratorSystem()
std::vector< dof_id_type > getBonds(dof_id_type node_id)
Function to return the bond number connected with node node_id.
registerMooseObject("PeridynamicsApp", PeridynamicsMesh)
std::vector< Point > _cracks_start
static const std::string k
Definition: NS.h:130
void ErrorVector unsigned int
unsigned int & _n_pdbonds
Number of total bonds.
void setNodeBlockID(SubdomainID id)
Function to set block ID for all PD nodes.
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...
uint8_t dof_id_type
Real getHorizon(dof_id_type node_id)
Function to return horizon size.