Skip to content

Commit 501a7eb

Browse files
authored
Merge pull request #32419 from lynnmunday/xfem_autoMeshNodes
automatically determine 3D mesh cutter crack front nodes
2 parents bcd5a39 + 2a38c83 commit 501a7eb

54 files changed

Lines changed: 171 additions & 115 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

modules/solid_mechanics/doc/content/source/actions/DomainIntegralAction.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,8 @@ Details on the theory behind the computation of the various fracture integrals a
3131
| [DomainIntegralQFunction](DomainIntegralQFunction.md) | AuxKernel | Optionally populates AuxVariables with values of the geometry-based q function when `output_q=true` |
3232
| [DomainIntegralTopologicalQFunction](DomainIntegralTopologicalQFunction.md) | AuxKernel | Optionally populates AuxVariables with values of the topology-based q function when `output_q=true` |
3333

34+
### Output with `crack_front_points_provider`
35+
36+
The [!param](/DomainIntegral/DomainIntegralAction/crack_front_points_provider) parameter references a UserObject that defines a set of surface points at the edge of a cutting plane used by the XFEM module to define the crack. One of its primary purposes is to define the discrete locations where fracture integrals are computed when XFEM is used to define the crack. In XFEM, a crack can be described purely by geometric primitives or by a lower-dimensional mesh. When [!param](/DomainIntegral/DomainIntegralAction/crack_front_points_provider) is specified, the `DomainIntegral` action can create output at the crack front points, which are not at node locations. By default (`output_vpp=true`), the vectorpostprocessors will always be created and will be dynamically sized as the number of crack front points changes throughout the simulation. The Postprocessor and AuxKernel output will only be created if [!param](/DomainIntegral/DomainIntegralAction/number_points_from_provider) is specified.
37+
3438
!syntax parameters /DomainIntegral/DomainIntegralAction

modules/solid_mechanics/include/userobjects/CrackFrontDefinition.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,6 @@ namespace libMesh
2323
class QBase;
2424
}
2525

26-
// fixme lynn this needs to be removed from the globalname space in a seperate commit after Grizzly
27-
// is fixed to use includeCrackFrontDefinitionParams
28-
void addCrackFrontDefinitionParams(InputParameters & params);
2926
/**
3027
* Class used in fracture integrals to define geometric characteristics of the crack front
3128
*/

modules/solid_mechanics/include/userobjects/CrackFrontPointsProvider.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ class CrackFrontPointsProvider : public ElementUserObject
2121

2222
CrackFrontPointsProvider(const InputParameters & parameters, const bool uses_mesh = false);
2323

24+
/** Get the current number of crack front points
25+
* @return The current number of crack front points
26+
*/
27+
virtual unsigned int getNumberOfCrackFrontPoints() const = 0;
28+
2429
/** get a set of points along a crack front from a XFEM GeometricCutUserObject
2530
* @return A vector which contains all crack front points
2631
*/

modules/solid_mechanics/src/actions/DomainIntegralAction.C

Lines changed: 48 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ DomainIntegralAction::validParams()
113113
"equivalent_k",
114114
false,
115115
"Calculate an equivalent K from KI, KII and KIII, assuming self-similar crack growth.");
116-
params.addParam<bool>("output_q", true, "Output q");
116+
params.addParam<bool>("output_q", false, "Output q");
117117
params.addRequiredParam<bool>(
118118
"incremental", "Flag to indicate whether an incremental or total model is being used.");
119119
params.addParam<std::vector<MaterialPropertyName>>(
@@ -229,10 +229,6 @@ DomainIntegralAction::DomainIntegralAction(const InputParameters & params)
229229

230230
if (isParamValid("crack_front_points_provider"))
231231
{
232-
if (!isParamValid("number_points_from_provider"))
233-
paramError("number_points_from_provider",
234-
"DomainIntegral error: when crack_front_points_provider is used, "
235-
"number_points_from_provider must be provided.");
236232
_use_crack_front_points_provider = true;
237233
_crack_front_points_provider = getParam<UserObjectName>("crack_front_points_provider");
238234
}
@@ -370,12 +366,10 @@ DomainIntegralAction::act()
370366
const std::string uo_type_name("CrackFrontDefinition");
371367

372368
InputParameters params = _factory.getValidParams(uo_type_name);
369+
// The CrackFrontDefinition updates the vpps and MUST execute before them
370+
params.set<int>("execution_order_group") = -1;
373371
if (_use_crack_front_points_provider)
374-
{
375-
// The CrackFrontDefinition updates the vpps and MUST execute before them
376-
params.set<int>("execution_order_group") = -1;
377372
params.set<ExecFlagEnum>("execute_on") = xfem_exec_flags;
378-
}
379373
else
380374
params.set<ExecFlagEnum>("execute_on") = {EXEC_INITIAL, EXEC_TIMESTEP_END};
381375

@@ -400,8 +394,12 @@ DomainIntegralAction::act()
400394
if (_crack_front_points.size() != 0)
401395
params.set<std::vector<Point>>("crack_front_points") = _crack_front_points;
402396
if (_use_crack_front_points_provider)
403-
params.applyParameters(parameters(),
404-
{"crack_front_points_provider, number_points_from_provider"});
397+
{
398+
params.set<UserObjectName>("crack_front_points_provider") = _crack_front_points_provider;
399+
if (isParamValid("number_points_from_provider"))
400+
params.set<unsigned int>("number_points_from_provider") =
401+
getParam<unsigned int>("number_points_from_provider");
402+
}
405403
if (_closed_loop)
406404
params.set<bool>("closed_loop") = _closed_loop;
407405
params.set<bool>("use_displaced_mesh") = _use_displaced_mesh;
@@ -436,6 +434,14 @@ DomainIntegralAction::act()
436434
}
437435
else if (_current_task == "add_aux_variable" && _output_q)
438436
{
437+
if (isParamValid("number_points_from_provider") && num_crack_front_points == 0)
438+
{
439+
paramError("output_q",
440+
"Requesting AuxVariable output of q functions but the number of crack fronts for "
441+
"output is zero. AuxVariable output for XFEM cutter objects requires "
442+
"number_points_from_provider to be set.");
443+
}
444+
439445
for (unsigned int ring_index = 0; ring_index < _ring_vec.size(); ++ring_index)
440446
{
441447
std::string aux_var_type;
@@ -530,6 +536,26 @@ DomainIntegralAction::act()
530536

531537
else if (_current_task == "add_postprocessor")
532538
{
539+
// Check that the number specified by the XFEM cutter object matches the number of points
540+
// specified in the DomainIntegralAction block. This is being done in teh add_postprocessor
541+
// block because it must be done after all userObjects have been created.
542+
if (_use_crack_front_points_provider && isParamValid("number_points_from_provider"))
543+
{
544+
auto crack_front_points_provider = &_problem->getUserObject<CrackFrontPointsProvider>(
545+
getParam<UserObjectName>("crack_front_points_provider"));
546+
if (crack_front_points_provider->usesMesh())
547+
{
548+
auto xfem_cutter_points = crack_front_points_provider->getNumberOfCrackFrontPoints();
549+
if (xfem_cutter_points != num_crack_front_points)
550+
paramError("number_points_from_provider",
551+
"This must match the number of points provided by the XFEM mesh cutter "
552+
"object."
553+
"\n number_points_from_provider:",
554+
num_crack_front_points,
555+
"\n XFEM Crack Front Points: ",
556+
xfem_cutter_points);
557+
}
558+
}
533559
for (std::set<INTEGRAL>::iterator sit = _integrals.begin(); sit != _integrals.end(); ++sit)
534560
{
535561
std::string pp_base_name;
@@ -1007,7 +1033,17 @@ DomainIntegralAction::calcNumCrackFrontPoints()
10071033
else if (_crack_front_points.size() != 0)
10081034
num_points = _crack_front_points.size();
10091035
else if (_use_crack_front_points_provider)
1010-
num_points = getParam<unsigned int>("number_points_from_provider");
1036+
{
1037+
if (isParamValid("number_points_from_provider"))
1038+
num_points = getParam<unsigned int>("number_points_from_provider");
1039+
else
1040+
// Actual count determined at runtime by CrackFrontDefinition::initialSetup()
1041+
// which calls provider->getNumberOfCrackFrontPoints(). Use 0 here so the
1042+
// action does not create per-point objects that would access crack front data
1043+
// before it exists. The VectorPostprocessors (JIntegral, InteractionIntegral,
1044+
// etc.) dynamically size based on the runtime count.
1045+
num_points = 0;
1046+
}
10111047
else
10121048
mooseError("Must define either 'boundary' or 'crack_front_points'");
10131049
return num_points;

modules/solid_mechanics/src/userobjects/CrackFrontDefinition.C

Lines changed: 24 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,6 @@ CrackFrontDefinition::validParams()
3838
return params;
3939
}
4040

41-
void
42-
addCrackFrontDefinitionParams(InputParameters & params)
43-
{
44-
CrackFrontDefinition::includeCrackFrontDefinitionParams(params);
45-
}
46-
4741
void
4842
CrackFrontDefinition::includeCrackFrontDefinitionParams(InputParameters & params)
4943
{
@@ -108,9 +102,9 @@ CrackFrontDefinition::includeCrackFrontDefinitionParams(InputParameters & params
108102
"crack_front_points_provider",
109103
"The UserObject provides the crack front points from XFEM GeometricCutObject");
110104

111-
params.addParam<unsigned int>(
112-
"number_points_from_provider",
113-
"The number of crack front points, only needed if crack_front_points_provider is used.");
105+
params.addParam<unsigned int>("number_points_from_provider",
106+
"The number of crack front points, only needed for "
107+
"crack_front_points_provider that do not use a cut mesh.");
114108
params.addParam<Real>(
115109
"crack_front_node_tolerance",
116110
1e-10,
@@ -164,12 +158,7 @@ CrackFrontDefinition::CrackFrontDefinition(const InputParameters & parameters)
164158
paramError("crack_front_points_provider",
165159
"CrackFrontDefinition error: since boundary is defined, "
166160
"crack_front_points_provider should not be added.");
167-
if (!isParamValid("number_points_from_provider"))
168-
paramError("number_points_from_provider",
169-
"CrackFrontDefinition error: When crack_front_points_provider is used, the "
170-
"number_points_from_provider must be provided.");
171161

172-
_num_points_from_provider = getParam<unsigned int>("number_points_from_provider");
173162
_geom_definition_method = CRACK_GEOM_DEFINITION::CRACK_FRONT_POINTS;
174163
}
175164
else if (isParamValid("number_points_from_provider"))
@@ -302,6 +291,13 @@ CrackFrontDefinition::initialSetup()
302291
if (_crack_front_points_provider->usesMesh())
303292
{
304293
_use_mesh_cutter = true;
294+
295+
// Automatically get number of crack front points from mesh-based provider
296+
_num_points_from_provider = _crack_front_points_provider->getNumberOfCrackFrontPoints();
297+
mooseInfo("CrackFrontDefinition: Automatically detected ",
298+
_num_points_from_provider,
299+
" crack front points from mesh-based provider");
300+
305301
if (_direction_method != DIRECTION_METHOD::CURVED_CRACK_FRONT)
306302
paramError("crack_direction_method",
307303
"Using a `crack_front_points_provider` that uses an XFEM cutter mesh also "
@@ -311,6 +307,17 @@ CrackFrontDefinition::initialSetup()
311307
"'crack_mouth_boundary' cannot be set when using a "
312308
"'crack_front_points_provider' that uses an XFEM cutter mesh");
313309
}
310+
else if (isParamValid("number_points_from_provider"))
311+
{
312+
_num_points_from_provider = getParam<unsigned int>("number_points_from_provider");
313+
}
314+
else if (_num_points_from_provider == 0)
315+
{
316+
paramError(
317+
"number_points_from_provider",
318+
"CrackFrontDefinition error: When using a non-mesh-based crack_front_points_provider, "
319+
"the number_points_from_provider parameter must be provided.");
320+
}
314321
}
315322
if (_crack_front_points_provider != nullptr)
316323
{
@@ -365,6 +372,9 @@ CrackFrontDefinition::initialize()
365372
// cutter
366373
if (_use_mesh_cutter && _is_cutter_modified)
367374
{
375+
// Automatically update the number of crack front points as crack grows
376+
_num_points_from_provider = _crack_front_points_provider->getNumberOfCrackFrontPoints();
377+
368378
_crack_front_points =
369379
_crack_front_points_provider->getCrackFrontPoints(_num_points_from_provider);
370380
updateCrackFrontGeometry();

modules/solid_mechanics/test/tests/domain_integral_thermal/c_integral_2d.i

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
crack_direction_vector = '1 0 0'
102102
2d = true
103103
axis_2d = 2
104+
output_q = true
104105
radius_inner = '60.0 80.0 100.0 120.0'
105106
radius_outer = '80.0 100.0 120.0 140.0'
106107
incremental = true

modules/solid_mechanics/test/tests/domain_integral_thermal/interaction_integral_2d_c.i

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@
136136
radius_outer = '80.0 100.0 120.0 140.0'
137137
symmetry_plane = 1
138138
incremental = true
139+
output_q = true
139140

140141
# interaction integral parameters
141142
block = 1

modules/solid_mechanics/test/tests/domain_integral_thermal/j_integral_2d.i

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
crack_direction_vector = '1 0 0'
3535
2d = true
3636
axis_2d = 2
37+
output_q = true
3738
radius_inner = '60.0 80.0 100.0 120.0'
3839
radius_outer = '80.0 100.0 120.0 140.0'
3940
temperature = temp

modules/solid_mechanics/test/tests/interaction_integral/interaction_integral_2d.i

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
block = 1
3636
youngs_modulus = 207000
3737
poissons_ratio = 0.3
38-
output_q = false
3938
incremental = true
4039
equivalent_k = true
4140
[]

modules/solid_mechanics/test/tests/interaction_integral/interaction_integral_2d_rot.i

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
block = 1
3636
youngs_modulus = 207000
3737
poissons_ratio = 0.3
38-
output_q = false
3938
incremental = true
4039
equivalent_k = true
4140
[]

0 commit comments

Comments
 (0)