28 if (quasi_static_physics.empty())
31 for (
const auto *
const physics : quasi_static_physics)
33 const bool has_locking_param = physics->
isParamSetByUser(
"volumetric_locking_correction");
34 if (!has_locking_param)
37 if (physics->getParam<
bool>(
"volumetric_locking_correction"))
45hasOverlap(
const std::vector<BoundaryName> & lhs,
const std::vector<BoundaryName> & rhs)
47 for (
const auto & left : lhs)
48 if (
std::
find(rhs.begin(), rhs.end(), left) != rhs.end())
55producesProperty(
const NEML2Action & action,
const MaterialPropertyName & property_name)
57 const auto & outputs = action.
getParam<std::vector<std::string>>(
"moose_outputs");
58 if (std::find(outputs.begin(), outputs.end(), property_name) != outputs.end())
61 const auto & derivatives = action.
getParam<std::vector<std::string>>(
"moose_derivatives");
62 return std::find(derivatives.begin(), derivatives.end(), property_name) != derivatives.end();
66resolveTransferredProperty(
ActionWarehouse & awh,
const MaterialPropertyName & property_name)
70 if (material_action->getMooseObjectType() !=
"ComputeLagrangianCauchyCustomStress")
73 const auto & params = material_action->getObjectParams();
74 if (property_name ==
"pk1_stress" || property_name ==
"stress")
75 return params.get<MaterialPropertyName>(
"custom_cauchy_stress");
77 if (property_name ==
"pk1_jacobian" || property_name ==
"Jacobian_mult")
78 return params.get<MaterialPropertyName>(
"custom_cauchy_jacobian");
92 "add_master_action_material");
98 "validate_coordinate_systems");
105 "for non-interface-fitted meshes.");
109 "UserObject that provides signed distance and normal vector calculations.");
111 "generate_sbm_distance",
113 "Automatically create surface mesh builders, distance functions, and the boundary distance "
114 "user object from the supplied boundaries.");
115 params.
addParam<std::vector<MeshGeneratorName>>(
117 "Names of saved surface meshes corresponding one-to-one with boundary. If omitted, the "
118 "boundary names are used.");
119 params.
addParam<
bool>(
"check_surface_watertightness",
121 "Whether generated surface mesh builders check mesh watertightness.");
123 "complete_interface_mesh",
124 "Saved surface mesh containing the complete boundary of each subdomain. Setting this "
125 "parameter automatically creates one interface manager and distance user object.");
126 params.
addParam<std::vector<std::vector<SubdomainID>>>(
127 "interface_subdomain_pairs",
129 "Ordered subdomain pair for each boundary when it cannot be inferred from boundary names.");
130 params.
addParam<Real>(
"interface_matching_tolerance",
132 "Relative face-matching tolerance for the single-mesh interface manager.");
134 params.
addParam<
bool>(
"no_shifted",
false,
"Disable shifted terms.");
135 params.
addParam<
bool>(
"directional_correction",
true,
"Add the directional correction terms.");
136 params.
addParam<MaterialPropertyName>(
137 "stress",
"stress",
"Name of the stress tensor material property for small strain SCZM.");
138 params.
addParam<MaterialPropertyName>(
"tangent",
140 "Name of the material Jacobian tensor property for small "
143 "tangent_definition",
144 MooseEnum(
"auto stress_wrt_strain pk1_wrt_deformation_gradient",
"auto"),
145 "Mathematical definition of the tangent material property. 'auto' recognizes the standard "
146 "Jacobian_mult property as d(stress)/d(strain) and pk1_jacobian as d(PK1)/d(F). Select "
147 "'stress_wrt_strain' or 'pk1_wrt_deformation_gradient' explicitly for a custom tangent "
148 "property; use the latter only when the property is known to be d(PK1)/d(F).");
150 "volumetric_locking_correction",
152 "Whether to apply volumetric locking correction to the directional correction Jacobian "
153 "term in SCZM. If not specified, this value is automatically inherited from the solid "
154 "mechanics physics block.");
162 const bool generate_distance = getParam<bool>(
"generate_sbm_distance");
164 const bool has_complete_interface_mesh =
isParamSetByUser(
"complete_interface_mesh");
165 if (
static_cast<unsigned int>(generate_distance) +
static_cast<unsigned int>(has_distance_uo) +
166 static_cast<unsigned int>(has_complete_interface_mesh) >
169 "Specify only one of 'sbm_distance_uo', 'generate_sbm_distance', and "
170 "'complete_interface_mesh'.");
173 paramError(
"surface_meshes",
"This parameter is only valid with 'generate_sbm_distance=true'.");
176 "This parameter is only valid with 'generate_sbm_distance=true'.");
177 if (!has_complete_interface_mesh &&
isParamSetByUser(
"interface_matching_tolerance"))
179 "This parameter is only valid with 'complete_interface_mesh'.");
181 if (generate_distance)
184 if (surface_meshes.size() !=
_boundary.size())
185 paramError(
"surface_meshes",
"The number of surface meshes must match the boundaries.");
186 if (std::set<MeshGeneratorName>(surface_meshes.begin(), surface_meshes.end()).size() !=
187 surface_meshes.size())
188 paramError(
"surface_meshes",
"Each saved surface mesh may only be used once.");
191 if (!has_complete_interface_mesh &&
isParamSetByUser(
"interface_subdomain_pairs"))
193 "This parameter is only valid with 'complete_interface_mesh'.");
194 if (has_complete_interface_mesh &&
isParamSetByUser(
"interface_subdomain_pairs") &&
195 getParam<std::vector<std::vector<SubdomainID>>>(
"interface_subdomain_pairs").size() !=
197 paramError(
"interface_subdomain_pairs",
"Provide exactly one subdomain pair per boundary.");
200 paramError(
"tangent",
"This parameter applies only to the non-AD SCZM interface kernel.");
203 "This parameter applies only to the non-AD SCZM interface kernel. The AD kernel "
204 "differentiates the residual automatically.");
211 _use_AD ?
"ADSCZMInterfaceKernelSmallStrain" :
"SCZMInterfaceKernelSmallStrain";
215 :
"SCZMComputeDisplacementJumpSmallStrain";
217 _use_AD ?
"ADCZMComputeGlobalTractionSmallStrain" :
"CZMComputeGlobalTractionSmallStrain";
221 paramError(
"strain",
"Shifted cohesive zone models currently support only small strain.");
224 "ShiftedCohesiveZoneAction Error: Invalid kinematic parameter. Allowed values are: "
225 "SmallStrain or TotalLagrangian");
234 paramError(
"displacements",
"Number of displacements must match problem dimension.");
236 if (
_current_task ==
"add_interface_kernel" && getParam<bool>(
"directional_correction"))
238 std::vector<MaterialPropertyName> stress_names;
239 std::vector<MaterialPropertyName> tangent_names;
242 stress_names.push_back(getParam<MaterialPropertyName>(
"stress"));
244 stress_names.push_back(
"pk1_stress");
249 stress_names.push_back(
"stress");
250 stress_names.push_back(
"pk1_stress");
254 tangent_names.push_back(getParam<MaterialPropertyName>(
"tangent"));
256 tangent_names.push_back(
"pk1_jacobian");
259 tangent_names.push_back(
"Jacobian_mult");
260 tangent_names.push_back(
"pk1_jacobian");
263 std::vector<MaterialPropertyName> validated_neml2_properties;
265 const auto validate_neml2_interface =
266 [
this, &validated_neml2_properties](
const MaterialPropertyName & property_name)
268 const auto neml2_property_name = resolveTransferredProperty(
_awh, property_name);
270 if (std::find(validated_neml2_properties.begin(),
271 validated_neml2_properties.end(),
272 neml2_property_name) != validated_neml2_properties.end())
275 validated_neml2_properties.push_back(neml2_property_name);
279 if (!producesProperty(*neml2_action, neml2_property_name))
282 const bool interface_set = neml2_action->isParamSetByUser(
"interface");
283 const auto & interfaces = neml2_action->getParam<std::vector<BoundaryName>>(
"interface");
285 if (!interface_set || interfaces.empty())
286 neml2_action->paramError(
288 "This NEML2 block provides the material property '",
290 "' used by [Physics/SolidMechanics/ShiftedCohesiveZone] with "
291 "directional_correction = true. Set 'interface' to the SCZM boundary (for example, "
292 "interface = ${boundary}) or set "
293 "'directional_correction = false' in the ShiftedCohesiveZone block.");
296 neml2_action->paramError(
298 "This NEML2 block provides the material property '",
301 "[Physics/SolidMechanics/ShiftedCohesiveZone] with directional_correction = true, "
303 "its 'interface' setting does not overlap the SCZM boundary. Make the NEML2 "
304 "'interface' include the SCZM boundary or set 'directional_correction = false'.");
310 for (
const auto & stress_name : stress_names)
311 validate_neml2_interface(stress_name);
313 for (
const auto & tangent_name : tangent_names)
314 validate_neml2_interface(tangent_name);
321 if (
_current_task ==
"add_function" && getParam<bool>(
"generate_sbm_distance"))
324 (getParam<bool>(
"generate_sbm_distance") ||
isParamSetByUser(
"complete_interface_mesh")))
335std::vector<MeshGeneratorName>
339 return getParam<std::vector<MeshGeneratorName>>(
"surface_meshes");
341 std::vector<MeshGeneratorName> surface_meshes;
342 surface_meshes.reserve(
_boundary.size());
344 surface_meshes.push_back(boundary);
345 return surface_meshes;
351 return name() +
"_" + boundary +
"_builder";
357 return name() +
"_dist_" + boundary;
363 return name() +
"_sbm_distance";
369 return name() +
"_interface_manager";
388 distance_params.
set<std::vector<BoundaryName>>(
"boundary") =
_boundary;
389 distance_params.set<
int>(
"execution_order_group") = 0;
395 manager_params.
set<MeshGeneratorName>(
"complete_interface_mesh") =
396 getParam<MeshGeneratorName>(
"complete_interface_mesh");
397 manager_params.set<Real>(
"tolerance") = getParam<Real>(
"interface_matching_tolerance");
401 distance_params.set<std::vector<std::vector<SubdomainID>>>(
"interface_subdomain_pairs") =
402 getParam<std::vector<std::vector<SubdomainID>>>(
"interface_subdomain_pairs");
407 std::vector<FunctionName> distance_functions;
408 distance_functions.reserve(
_boundary.size());
409 for (
const auto i : index_range(
_boundary))
412 params.
set<MeshGeneratorName>(
"interface_mesh") = surface_meshes[i];
413 params.set<
bool>(
"check_watertightness") = getParam<bool>(
"check_surface_watertightness");
418 distance_params.set<std::vector<FunctionName>>(
"surfaces") = distance_functions;
428 if (getParam<bool>(
"generate_sbm_distance") ||
isParamSetByUser(
"complete_interface_mesh"))
431 params.
set<UserObjectName>(
"sbm_distance_uo") = getParam<UserObjectName>(
"sbm_distance_uo");
433 params.
set<
bool>(
"no_shifted") = getParam<bool>(
"no_shifted");
435 params.
set<
bool>(
"directional_correction") = getParam<bool>(
"directional_correction");
437 params.
set<MaterialPropertyName>(
"stress") = getParam<MaterialPropertyName>(
"stress");
439 params.
set<MaterialPropertyName>(
"tangent") = getParam<MaterialPropertyName>(
"tangent");
441 params.
set<
MooseEnum>(
"tangent_definition") = getParam<MooseEnum>(
"tangent_definition");
443 if (params.
isParamValid(
"volumetric_locking_correction"))
445 const bool inherited_correction = getInheritedVolumetricLockingCorrection(
_awh);
448 params.
set<
bool>(
"volumetric_locking_correction") =
449 getParam<bool>(
"volumetric_locking_correction");
450 if (getParam<bool>(
"volumetric_locking_correction") != inherited_correction)
452 "ShiftedCohesiveZoneAction: 'volumetric_locking_correction' value in "
453 "ShiftedCohesiveZone block is different from that in the physics block(s). Make sure "
454 "this is intended.");
457 params.
set<
bool>(
"volumetric_locking_correction") = inherited_correction;
465 if (getParam<bool>(
"generate_sbm_distance") ||
isParamSetByUser(
"complete_interface_mesh"))
468 params.
set<UserObjectName>(
"sbm_distance_uo") = getParam<UserObjectName>(
"sbm_distance_uo");
470 params.
set<
bool>(
"no_shifted") = getParam<bool>(
"no_shifted");
const ExecFlagType EXEC_INITIAL
registerMooseAction("ShiftedBoundaryMethodApp", ShiftedCohesiveZoneAction, "add_interface_kernel")
std::vector< const T * > getActions()
std::shared_ptr< MooseMesh > & _mesh
std::shared_ptr< FEProblemBase > & _problem
const std::string & _current_task
void actOutputGeneration()
const unsigned int _ndisp
number of displacement components
const bool _use_AD
whether to use AD kernels and materials
std::string _equilibrium_traction_calculator_name
void addRequiredCZMInterfaceMaterials()
adds the required interface materials based on the selected strain formulation
void chekMultipleActionParameters()
method checking multiple CohesiveZoneAction block inputs
static InputParameters validParams()
std::string _disp_jump_provider_name
enum CohesiveZoneAction::Strain _strain
void addRequiredCZMInterfaceKernels()
adds the required interfacekernels based on the selected strain formulation
std::string _czm_kernel_name
kernel's and materials's names
const std::vector< BoundaryName > _boundary
Base name of the material system.
InputParameters getValidParams(const std::string &name) const
const std::string & name() const
void paramError(const std::string ¶m, Args... args) const
bool isParamSetByUser(const std::string &name) const
void mooseError(Args &&... args) const
void mooseWarning(Args &&... args) const
const T & getParam(const std::string &name) const
bool isParamValid(const std::string &name) const
Action class for the Shifted Cohesive Zone Method (SCZM).
void addSBMDistanceUserObjects()
Adds the generated surface geometry and aggregate boundary distance user objects.
FunctionName surfaceDistanceFunctionName(const BoundaryName &boundary) const
Returns the generated distance function name for a boundary.
static InputParameters validParams()
UserObjectName interfaceManagerName() const
Returns the generated single-mesh interface manager name.
virtual void act() override
Main execution point for the Action.
void customizeCZMInterfaceKernelParameters(InputParameters ¶ms) const override
Sets SCZM-specific parameters on each generated interface kernel.
UserObjectName surfaceMeshBuilderName(const BoundaryName &boundary) const
Returns the generated builder name for a boundary.
UserObjectName sbmDistanceUserObjectName() const
Returns the generated aggregate distance user object name.
void customizeCZMDisplacementJumpMaterialParameters(InputParameters ¶ms) const override
Sets SCZM-specific parameters on the generated displacement jump material.
ShiftedCohesiveZoneAction(const InputParameters ¶ms)
void addSBMDistanceFunctions()
Adds the surface distance functions used by the generated distance user object.
std::vector< MeshGeneratorName > surfaceMeshNames() const
Returns the saved surface mesh names, defaulting to the boundary names.
KOKKOS_INLINE_FUNCTION const T * find(const T &target, const T *const begin, const T *const end)
static constexpr Real TOLERANCE