https://mooseframework.inl.gov
Loading...
Searching...
No Matches
MeshCut2DRankTwoTensorNucleation.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
11
12#include "MooseError.h"
13#include "MooseTypes.h"
14#include "libmesh/quadrature.h"
15#include "RankTwoTensor.h"
16#include "RankTwoScalarTools.h"
17#include "Assembly.h"
18
20
23{
26 "Nucleate a crack in MeshCut2D UO based on a scalar extracted from a RankTwoTensor");
27 params.addRangeCheckedParam<Real>(
28 "edge_extension_factor",
29 1e-5,
30 "edge_extension_factor >= 0",
31 "Factor by which the length of cracks that have been adjusted to coincide with element edges "
32 "are increased to avoid missing an intersection with the edge due to numerical tolerance "
33 "issues.");
34 params.addRangeCheckedParam<Real>(
35 "nucleation_length",
36 "nucleation_length >= 0",
37 "Size of crack to nucleate. Must be larger than the length of the element in which the "
38 "crack is nucleated, unless 'nucleate_across_full_element' is set to 'true'.");
39 params.addParam<MooseEnum>(
40 "scalar_type",
42 "Scalar quantity to be computed from tensor and used as a failure criterion");
43 params.addRequiredParam<std::string>("tensor", "The material tensor name.");
45 "nucleation_threshold",
46 "Threshold for the scalar quantity of the RankTwoTensor to nucleate new cracks");
47 params.addParam<Point>(
48 "point1",
49 Point(0, 0, 0),
50 "Start point for axis used to calculate some cylindrical material tensor quantities");
51 params.addParam<Point>(
52 "point2",
53 Point(0, 1, 0),
54 "End point for axis used to calculate some cylindrical material tensor quantities");
55 params.addParam<bool>(
56 "nucleate_across_full_element",
57 false,
58 "Controls the behavior of nucleating cracks if 'nucleation_length' is smaller than the "
59 "length required to travserse an element with a nucleating crack. If this is set to 'false', "
60 "that condition will result in an error, but if set to 'true', a crack with the length "
61 "needed "
62 "to traverse the element will be inserted.");
63 return params;
64}
65
67 const InputParameters & parameters)
68 : MeshCut2DNucleationBase(parameters),
69 _edge_extension_factor(getParam<Real>("edge_extension_factor")),
70 _nucleate_across_full_element(getParam<bool>("nucleate_across_full_element")),
71 _is_nucleation_length_provided(isParamValid("nucleation_length")),
72 _nucleation_length(_is_nucleation_length_provided ? getParam<Real>("nucleation_length") : 0),
73 _tensor(getMaterialProperty<RankTwoTensor>(getParam<std::string>("tensor"))),
74 _nucleation_threshold(coupledValue("nucleation_threshold")),
75 _scalar_type(getParam<MooseEnum>("scalar_type")),
76 _point1(parameters.get<Point>("point1")),
77 _point2(parameters.get<Point>("point2")),
78 _JxW(_assembly.JxW()),
79 _coord(_assembly.coordTransformation())
80{
81}
82
83bool
85 std::pair<RealVectorValue, RealVectorValue> & cutterElemNodes)
86{
87 bool does_it_crack = false;
88 unsigned int numqp = _qrule->n_points();
89 Point zero; // Used for checking whether cutter Element is zero length
90
91 Real average_threshold = 0.0;
92 RankTwoTensor average_tensor;
93 Point average_point;
94 for (unsigned int qp = 0; qp < numqp; ++qp)
95 {
96 if (_nucleation_threshold[qp] <= 0.0)
97 mooseError("Threshold must be strictly positive in MeshCut2DRankTwoTensorNucleation");
98 average_threshold += _JxW[qp] * _coord[qp] * _nucleation_threshold[qp];
99 average_tensor += _JxW[qp] * _coord[qp] * _tensor[qp];
100 average_point += _JxW[qp] * _coord[qp] * _q_point[qp];
101 }
102 Point point_dir;
103 Real tensor_quantity = RankTwoScalarTools::getQuantity(
104 average_tensor, _scalar_type, _point1, _point2, average_point, point_dir);
105 if (point_dir.absolute_fuzzy_equals(zero))
106 mooseError("Cutter element has zero length in MeshCut2DRankTwoTensorNucleation");
107
108 if (tensor_quantity > average_threshold)
109 {
110 does_it_crack = true;
111
112 const Point elem_center(_current_elem->vertex_average());
113 Point crack_dir = point_dir.cross(Point(0, 0, 1));
114
115 // get max element length to use for ray length
116 std::unique_ptr<const Elem> edge;
117 Real circumference = 0;
118 for (const auto e : _current_elem->edge_index_range())
119 {
120 _current_elem->build_edge_ptr(edge, e);
121 circumference += edge->length(0, 1);
122 }
123
124 // Temporaries for doing things below
125 Real intersection_distance;
126
127 Point point_0;
128 Point point_1;
129 bool is_point_0_on_external_boundary = false;
130 bool is_point_1_on_external_boundary = false;
131 for (const auto e : _current_elem->edge_index_range())
132 {
133 _current_elem->build_edge_ptr(edge, e);
134 const auto & edge0 = edge->point(0);
135 const auto & edge1 = edge->point(1);
137 elem_center, -crack_dir, circumference, edge0, edge1, point_0, intersection_distance))
138 is_point_0_on_external_boundary = (_current_elem->neighbor_ptr(e) == nullptr);
139 else if (lineLineIntersect2D(elem_center,
140 crack_dir,
141 circumference,
142 edge0,
143 edge1,
144 point_1,
145 intersection_distance))
146 is_point_1_on_external_boundary = (_current_elem->neighbor_ptr(e) == nullptr);
147 }
148
149 // traverse_length is the length of a cut that goes across a single elment
150 // extend_length is the amount that needs to be added to each side of the traverse_length cut to
151 // make its length equal to the nucleation length
152 // We also add a small amount to the crack length to make sure it fully cuts the element edge.
153 // This factor is based on the element length.
154 Real traverse_length = (point_0 - point_1).norm();
155 Real extend_length = (_nucleation_length - traverse_length) / 2.0;
156 if (_nucleation_length < traverse_length)
157 {
160 "Trying to nucleate crack smaller than element length, increase nucleation_length.\n "
161 "Location of crack being nucleated: ",
162 point_0,
163 "\n nucleation_length: ",
165 "\n Length to traverse element: ",
166 traverse_length,
167 "\n This error can be suppressed by setting nucleate_across_full_element=True which "
168 "will nucleate a crack the size of the element.");
169 else
170 //_edge_extension_factor is used to make sure cut will cut both edges of the element.
171 extend_length = (traverse_length * _edge_extension_factor) / 2.0;
172 }
173
174 // First create a cut assuming bulk nucleation
175 point_0 = point_0 - extend_length * crack_dir.unit();
176 point_1 = point_1 + extend_length * crack_dir.unit();
177
178 // modify edges of cut to put them on the edge of the domain and have a length
179 // equal to nucleation_length
180 if (is_point_0_on_external_boundary)
181 {
182 // first move point back to edge
183 point_0 = point_0 + extend_length * crack_dir.unit();
184 // second move point a little bit over edge
185 point_0 = point_0 - (traverse_length * _edge_extension_factor) / 2.0 * crack_dir.unit();
186 // third, move point 1 so that crack equals nucleation length
187 point_1 = point_1 + extend_length * crack_dir.unit();
188 }
189 else if (is_point_1_on_external_boundary)
190 {
191 point_1 = point_1 - extend_length * crack_dir.unit();
192 point_1 = point_1 + (traverse_length * _edge_extension_factor) / 2.0 * crack_dir.unit();
193 point_0 = point_0 - extend_length * crack_dir.unit();
194 }
195 cutterElemNodes = {point_0, point_1};
196 }
197
198 return does_it_crack;
199}
200
201bool
203 const Point & direction,
204 const Real length,
205 const Point & v0,
206 const Point & v1,
207 Point & intersection_point,
208 Real & intersection_distance)
209{
211 const Real TRACE_TOLERANCE = 1e-5;
212
213 const auto r = direction * length;
214 const auto s = v1 - v0;
215 const auto rxs = r(0) * s(1) - r(1) * s(0);
216
217 // Lines are parallel or colinear
218 if (std::abs(rxs) < TRACE_TOLERANCE)
219 return false;
220
221 const auto v0mu0 = v0 - start;
222 const auto t = (v0mu0(0) * s(1) - v0mu0(1) * s(0)) / rxs;
223 if (0 >= t + TRACE_TOLERANCE || t - TRACE_TOLERANCE > 1.0)
224 {
225 return false;
226 }
227
228 const auto u = (v0mu0(0) * r(1) - v0mu0(1) * r(0)) / rxs;
229 if (0 < u + TRACE_TOLERANCE && u - TRACE_TOLERANCE <= 1.0)
230 {
231 intersection_point = start + r * t;
232 intersection_distance = t * length;
233 return true;
234 }
235
236 // Not parallel, but don't intersect
237 return false;
238}
registerMooseObject("XFEMApp", MeshCut2DRankTwoTensorNucleation)
const QBase *const & _qrule
const Elem *const & _current_elem
const MooseArray< Point > & _q_point
void addRequiredCoupledVar(const std::string &name, const std::string &doc_string)
void addRequiredParam(const std::string &name, const std::string &doc_string)
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)
void addRangeCheckedParam(const std::string &name, const T &value, const std::string &parsed_function, const std::string &doc_string)
static InputParameters validParams()
const Real _edge_extension_factor
scaling factor to extend the nucleated crack beyond the element edges.
const bool _is_nucleation_length_provided
is the nucleation length provided in the input file.
const VariableValue & _nucleation_threshold
Threshold at which a crack is nucleated if exceeded.
const bool _nucleate_across_full_element
should element be cut if the nucleation_length is smaller than the element length.
bool lineLineIntersect2D(const Point &start, const Point &direction, const Real length, const Point &v0, const Point &v1, Point &intersection_point, Real &intersection_distance)
MeshCut2DRankTwoTensorNucleation(const InputParameters &parameters)
virtual bool doesElementCrack(std::pair< RealVectorValue, RealVectorValue > &cutterElemNodes) override
Determine whether the current element should be cut by a new crack.
const MooseArray< Real > & _JxW
Transformed Jacobian weights.
const Point _point1
Points used to define an axis of rotation for some scalar quantities.
MooseEnum _scalar_type
The type of scalar to be extracted from the tensor.
const MaterialProperty< RankTwoTensor > & _tensor
The tensor from which the scalar quantity used as a nucleating criterion is extracted.
const Real _nucleation_length
Length of the nucleated cracks.
void mooseError(Args &&... args) const
MooseEnum scalarOptions()
This enum is left for legacy calls.
T getQuantity(const RankTwoTensorTempl< T > &tensor, const MooseEnum &scalar_type, const Point &point1, const Point &point2, const Point &curr_point, Point &direction)