Line data Source code
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 "CohesiveZoneAction.h"
11 : #include "AddAuxVariableAction.h"
12 : #include "Factory.h"
13 : #include "FEProblem.h"
14 : #include "Conversion.h"
15 :
16 : registerMooseAction("SolidMechanicsApp", CohesiveZoneAction, "add_interface_kernel");
17 : registerMooseAction("SolidMechanicsApp", CohesiveZoneAction, "add_material");
18 : registerMooseAction("SolidMechanicsApp", CohesiveZoneAction, "add_master_action_material");
19 : registerMooseAction("SolidMechanicsApp", CohesiveZoneAction, "add_aux_variable");
20 : registerMooseAction("SolidMechanicsApp", CohesiveZoneAction, "add_aux_kernel");
21 : registerMooseAction("SolidMechanicsApp", CohesiveZoneAction, "add_kernel");
22 : registerMooseAction("SolidMechanicsApp", CohesiveZoneAction, "validate_coordinate_systems");
23 :
24 : InputParameters
25 138 : CohesiveZoneAction::validParams()
26 : {
27 138 : InputParameters params = CohesiveZoneActionBase::validParams();
28 138 : params.addClassDescription("Action to create an instance of the cohesive zone model kernel for "
29 : "each displacement component");
30 276 : params.addRequiredParam<std::vector<BoundaryName>>(
31 : "boundary", "The list of boundary IDs from the mesh where the cohesive zone will be applied");
32 138 : return params;
33 0 : }
34 :
35 138 : CohesiveZoneAction::CohesiveZoneAction(const InputParameters & params)
36 : : CohesiveZoneActionBase(params),
37 276 : _displacements(getParam<std::vector<VariableName>>("displacements")),
38 138 : _ndisp(_displacements.size()),
39 276 : _use_AD(getParam<bool>("use_automatic_differentiation")),
40 428 : _base_name(isParamValid("base_name") && !getParam<std::string>("base_name").empty()
41 138 : ? getParam<std::string>("base_name")
42 : : ""),
43 276 : _boundary(getParam<std::vector<BoundaryName>>("boundary")),
44 276 : _strain(getParam<MooseEnum>("strain").getEnum<Strain>()),
45 276 : _save_in_primary(getParam<std::vector<AuxVariableName>>("save_in_primary")),
46 276 : _diag_save_in_primary(getParam<std::vector<AuxVariableName>>("diag_save_in_primary")),
47 276 : _save_in_secondary(getParam<std::vector<AuxVariableName>>("save_in_secondary")),
48 414 : _diag_save_in_secondary(getParam<std::vector<AuxVariableName>>("diag_save_in_secondary")),
49 276 : _material_output_order(getParam<MultiMooseEnum>("material_output_order")),
50 414 : _material_output_family(getParam<MultiMooseEnum>("material_output_family")),
51 414 : _verbose(getParam<bool>("verbose"))
52 : {
53 : // We can't enforce consistency between the number of displacement variables and the mesh
54 : // dimension. Hence we only check we have a reasonable number of displacement variables
55 138 : if (_ndisp > 3 || _ndisp < 1)
56 0 : mooseError("the CZM Action requires 1, 2 or 3 displacement variables.");
57 :
58 138 : switch (_strain)
59 : {
60 93 : case Strain::Small:
61 : {
62 : _czm_kernel_name =
63 182 : _use_AD ? "ADCZMInterfaceKernelSmallStrain" : "CZMInterfaceKernelSmallStrain";
64 93 : _disp_jump_provider_name = _use_AD ? "ADCZMComputeDisplacementJumpSmallStrain"
65 182 : : "CZMComputeDisplacementJumpSmallStrain";
66 : _equilibrium_traction_calculator_name =
67 182 : _use_AD ? "ADCZMComputeGlobalTractionSmallStrain" : "CZMComputeGlobalTractionSmallStrain";
68 : break;
69 : }
70 45 : case Strain::Finite:
71 : {
72 : _czm_kernel_name =
73 86 : _use_AD ? "ADCZMInterfaceKernelTotalLagrangian" : "CZMInterfaceKernelTotalLagrangian";
74 45 : _disp_jump_provider_name = _use_AD ? "ADCZMComputeDisplacementJumpTotalLagrangian"
75 86 : : "CZMComputeDisplacementJumpTotalLagrangian";
76 45 : _equilibrium_traction_calculator_name = _use_AD ? "ADCZMComputeGlobalTractionTotalLagrangian"
77 86 : : "CZMComputeGlobalTractionTotalLagrangian";
78 : break;
79 : }
80 0 : default:
81 0 : mooseError("CohesiveZoneAction Error: Invalid kinematic parameter. Allowed values are: "
82 : "SmallStrain or TotalLagrangian");
83 : }
84 :
85 138 : if (_save_in_primary.size() != 0 && _save_in_primary.size() != _ndisp)
86 0 : mooseError(
87 : "Number of save_in_primary variables should equal to the number of displacement variables ",
88 0 : _ndisp);
89 138 : if (_diag_save_in_primary.size() != 0 && _diag_save_in_primary.size() != _ndisp)
90 0 : mooseError(
91 : "Number of diag_save_in_primary variables should equal to the number of displacement "
92 : "variables ",
93 0 : _ndisp);
94 138 : if (_save_in_secondary.size() != 0 && _save_in_secondary.size() != _ndisp)
95 0 : mooseError("Number of save_in_secondary variables should equal to the number of displacement "
96 : "variables ",
97 0 : _ndisp);
98 :
99 138 : if (_diag_save_in_secondary.size() != 0 && _diag_save_in_secondary.size() != _ndisp)
100 0 : mooseError(
101 : "Number of diag_save_in_secondary variables should equal to the number of displacement "
102 : "variables ",
103 0 : _ndisp);
104 :
105 : // convert output variable names to lower case
106 1052 : for (const auto & out : getParam<MultiMooseEnum>("generate_output"))
107 : {
108 : std::string lower(out);
109 : std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
110 776 : _generate_output.push_back(lower);
111 : }
112 :
113 138 : if (!_generate_output.empty())
114 80 : verifyOrderAndFamilyOutputs();
115 138 : }
116 :
117 : void
118 134 : CohesiveZoneAction::addRequiredCZMInterfaceKernels()
119 : {
120 492 : for (unsigned int i = 0; i < _ndisp; ++i)
121 : {
122 : // Create unique kernel name for each displacement component
123 1074 : std::string unique_kernel_name = _czm_kernel_name + "_" + _name + "_" + Moose::stringify(i);
124 :
125 358 : InputParameters paramsk = _factory.getValidParams(_czm_kernel_name);
126 :
127 358 : paramsk.set<unsigned int>("component") = i;
128 716 : paramsk.set<NonlinearVariableName>("variable") = _displacements[i];
129 1074 : paramsk.set<std::vector<VariableName>>("neighbor_var") = {_displacements[i]};
130 358 : paramsk.set<std::vector<VariableName>>("displacements") = _displacements;
131 358 : paramsk.set<std::vector<BoundaryName>>("boundary") = _boundary;
132 716 : paramsk.set<std::string>("base_name") = _base_name;
133 :
134 : std::string save_in_side;
135 : std::vector<AuxVariableName> save_in_var_names;
136 358 : if (_save_in_primary.size() == _ndisp || _save_in_secondary.size() == _ndisp)
137 : {
138 0 : prepareSaveInInputs(save_in_var_names, save_in_side, _save_in_primary, _save_in_secondary, i);
139 0 : paramsk.set<std::vector<AuxVariableName>>("save_in") = save_in_var_names;
140 0 : paramsk.set<MultiMooseEnum>("save_in_var_side") = save_in_side;
141 : }
142 358 : if (_diag_save_in_primary.size() == _ndisp || _diag_save_in_secondary.size() == _ndisp)
143 : {
144 0 : prepareSaveInInputs(
145 0 : save_in_var_names, save_in_side, _diag_save_in_primary, _diag_save_in_secondary, i);
146 0 : paramsk.set<std::vector<AuxVariableName>>("diag_save_in") = save_in_var_names;
147 0 : paramsk.set<MultiMooseEnum>("diag_save_in_var_side") = save_in_side;
148 : }
149 358 : _problem->addInterfaceKernel(_czm_kernel_name, unique_kernel_name, paramsk);
150 716 : }
151 134 : }
152 :
153 : void
154 134 : CohesiveZoneAction::addRequiredCZMInterfaceMaterials()
155 : {
156 : // Create unique material name for the "CZMComputeDisplacementJump" object
157 134 : std::string unique_material_name = _disp_jump_provider_name + "_" + _name;
158 134 : InputParameters paramsm = _factory.getValidParams(_disp_jump_provider_name);
159 134 : paramsm.set<std::vector<BoundaryName>>("boundary") = _boundary;
160 : ;
161 134 : paramsm.set<std::vector<VariableName>>("displacements") = _displacements;
162 134 : paramsm.set<std::string>("base_name") = _base_name;
163 134 : _problem->addInterfaceMaterial(_disp_jump_provider_name, unique_material_name, paramsm);
164 :
165 : // Create unique material name for the "CZMComputeGlobalTraction" object
166 134 : unique_material_name = _equilibrium_traction_calculator_name + "_" + _name;
167 134 : paramsm = _factory.getValidParams(_equilibrium_traction_calculator_name);
168 134 : paramsm.set<std::vector<BoundaryName>>("boundary") = _boundary;
169 : ;
170 134 : paramsm.set<std::string>("base_name") = _base_name;
171 134 : _problem->addInterfaceMaterial(
172 : _equilibrium_traction_calculator_name, unique_material_name, paramsm);
173 268 : }
174 :
175 : void
176 940 : CohesiveZoneAction::act()
177 : {
178 : // Enforce consistency
179 940 : if (_ndisp != _mesh->dimension())
180 0 : paramError("displacements", "Number of displacements must match problem dimension.");
181 :
182 940 : chekMultipleActionParameters();
183 :
184 938 : if (_current_task == "add_interface_kernel")
185 134 : addRequiredCZMInterfaceKernels();
186 804 : else if (_current_task == "add_master_action_material")
187 134 : addRequiredCZMInterfaceMaterials();
188 :
189 : // optional, add required outputs
190 938 : actOutputGeneration();
191 938 : }
192 :
193 : void
194 406 : CohesiveZoneAction::addRelationshipManagers(Moose::RelationshipManagerType input_rm_type)
195 : {
196 406 : InputParameters ips = _factory.getValidParams(_czm_kernel_name);
197 406 : addRelationshipManagers(input_rm_type, ips);
198 406 : }
199 :
200 : void
201 0 : CohesiveZoneAction::prepareSaveInInputs(std::vector<AuxVariableName> & save_in_names,
202 : std::string & save_in_side,
203 : const std::vector<AuxVariableName> & var_name_primary,
204 : const std::vector<AuxVariableName> & var_name_secondary,
205 : const int & i) const
206 : {
207 0 : save_in_names.clear();
208 : save_in_side.clear();
209 0 : if (var_name_primary.size() == _ndisp)
210 : {
211 0 : save_in_names.push_back(var_name_primary[i]);
212 : save_in_side += "m";
213 0 : if (var_name_secondary.size() == _ndisp)
214 : save_in_side += " ";
215 : }
216 0 : if (var_name_secondary.size() == _ndisp)
217 : {
218 0 : save_in_names.push_back(var_name_secondary[i]);
219 : save_in_side += "s";
220 : }
221 0 : }
222 :
223 : void
224 80 : CohesiveZoneAction::verifyOrderAndFamilyOutputs()
225 : {
226 : // Ensure material output order and family vectors are same size as generate output
227 :
228 : // check number of supplied orders and families
229 80 : if (_material_output_order.size() > 1 && _material_output_order.size() < _generate_output.size())
230 0 : paramError("material_output_order",
231 : "The number of orders assigned to material outputs must be: 0 to be assigned "
232 : "CONSTANT; 1 to assign all outputs the same value, or the same size as the number "
233 : "of generate outputs listed.");
234 :
235 80 : if (_material_output_family.size() > 1 &&
236 0 : _material_output_family.size() < _generate_output.size())
237 0 : paramError("material_output_family",
238 : "The number of families assigned to material outputs must be: 0 to be assigned "
239 : "MONOMIAL; 1 to assign all outputs the same value, or the same size as the number "
240 : "of generate outputs listed.");
241 :
242 : // if no value was provided, chose the default CONSTANT
243 80 : if (_material_output_order.size() == 0)
244 144 : _material_output_order.setAdditionalValue("CONSTANT");
245 :
246 : // For only one order, make all orders the same magnitude
247 80 : if (_material_output_order.size() == 1)
248 : _material_output_order =
249 80 : std::vector<std::string>(_generate_output.size(), _material_output_order[0]);
250 :
251 80 : if (_verbose)
252 0 : Moose::out << COLOR_CYAN << "*** Automatic applied material output orders ***"
253 : << "\n"
254 0 : << _name << ": " << Moose::stringify(_material_output_order) << "\n"
255 0 : << COLOR_DEFAULT;
256 :
257 : // if no value was provided, chose the default MONOMIAL
258 80 : if (_material_output_family.size() == 0)
259 160 : _material_output_family.setAdditionalValue("MONOMIAL");
260 :
261 : // For only one family, make all families that value
262 80 : if (_material_output_family.size() == 1)
263 : _material_output_family =
264 80 : std::vector<std::string>(_generate_output.size(), _material_output_family[0]);
265 :
266 80 : if (_verbose)
267 0 : Moose::out << COLOR_CYAN << "*** Automatic applied material output families ***"
268 : << "\n"
269 0 : << _name << ": " << Moose::stringify(_material_output_family) << "\n"
270 0 : << COLOR_DEFAULT;
271 80 : }
272 :
273 : void
274 938 : CohesiveZoneAction::actOutputGeneration()
275 : {
276 938 : if (_current_task == "add_material")
277 134 : actOutputMatProp();
278 :
279 : // Add variables (optional)
280 938 : if (_current_task == "add_aux_variable")
281 : {
282 : unsigned int index = 0;
283 910 : for (auto out : _generate_output)
284 : {
285 776 : const auto & order = _material_output_order[index];
286 776 : const auto & family = _material_output_family[index];
287 :
288 696 : std::string type = (order == "CONSTANT" && family == "MONOMIAL")
289 : ? "MooseVariableConstMonomial"
290 1552 : : "MooseVariable";
291 :
292 : // Create output helper aux variables
293 776 : auto params = _factory.getValidParams(type);
294 776 : params.set<MooseEnum>("order") = order;
295 776 : params.set<MooseEnum>("family") = family;
296 776 : if (family == "MONOMIAL")
297 1552 : _problem->addAuxVariable(type, addBaseName(out), params);
298 : else
299 0 : _problem->addVariable(type, addBaseName(out), params);
300 :
301 776 : index++;
302 776 : }
303 : }
304 :
305 : // Add output AuxKernels
306 804 : else if (_current_task == "add_aux_kernel")
307 : {
308 260 : const std::string material_output_aux_name = _use_AD ? "ADMaterialRealAux" : "MaterialRealAux";
309 : // Loop through output aux variables
310 : unsigned int index = 0;
311 910 : for (auto out : _generate_output)
312 : {
313 776 : if (_material_output_family[index] == "MONOMIAL")
314 : {
315 776 : InputParameters params = _factory.getValidParams(material_output_aux_name);
316 2328 : params.set<MaterialPropertyName>("property") = addBaseName(out);
317 2328 : params.set<AuxVariableName>("variable") = addBaseName(out);
318 776 : params.set<ExecFlagEnum>("execute_on") = EXEC_TIMESTEP_END;
319 776 : params.set<std::vector<BoundaryName>>("boundary") = _boundary;
320 776 : params.set<bool>("check_boundary_restricted") = false;
321 776 : _problem->addAuxKernel(material_output_aux_name, addBaseName(out) + '_' + name(), params);
322 776 : }
323 776 : index++;
324 : }
325 : }
326 938 : }
327 :
328 : void
329 134 : CohesiveZoneAction::actOutputMatProp()
330 : {
331 134 : if (_current_task == "add_material")
332 : {
333 : // Add output Materials
334 910 : for (auto out : _generate_output)
335 : {
336 776 : InputParameters params = emptyInputParameters();
337 :
338 : // RealVectorCartesianComponent
339 1248 : if (
340 1552 : [&]()
341 : {
342 2160 : for (const auto & vq : _real_vector_cartesian_component_table)
343 6464 : for (unsigned int a = 0; a < 3; ++a)
344 10160 : if (vq.first + '_' + _component_table[a] == out)
345 : {
346 472 : auto type = _use_AD ? "ADCZMRealVectorCartesianComponent"
347 : : "CZMRealVectorCartesianComponent";
348 472 : params = _factory.getValidParams(type);
349 472 : params.set<std::string>("real_vector_value") = vq.second;
350 472 : params.set<unsigned int>("index") = a;
351 472 : params.set<std::vector<BoundaryName>>("boundary") = _boundary;
352 1416 : params.set<MaterialPropertyName>("property_name") = addBaseName(out);
353 472 : params.set<std::string>("base_name") = _base_name;
354 1416 : _problem->addInterfaceMaterial(type, addBaseName(out) + '_' + name(), params);
355 : return true;
356 : }
357 : return false;
358 776 : }())
359 472 : continue;
360 :
361 : // CZMRealVectorScalar
362 608 : if (setupOutput(out,
363 : _vector_direction_table,
364 304 : [&](std::string prop_name, std::string direction)
365 : {
366 304 : auto type = _use_AD ? "ADCZMRealVectorScalar" : "CZMRealVectorScalar";
367 304 : params = _factory.getValidParams(type);
368 304 : params.set<std::string>("real_vector_value") = prop_name;
369 304 : params.set<MooseEnum>("direction") = direction;
370 912 : params.set<MaterialPropertyName>("property_name") = addBaseName(out);
371 304 : params.set<std::vector<BoundaryName>>("boundary") = _boundary;
372 304 : params.set<std::string>("base_name") = _base_name;
373 912 : _problem->addInterfaceMaterial(
374 304 : type, addBaseName(out) + '_' + name(), params);
375 304 : }))
376 304 : continue;
377 :
378 0 : mooseError("CZM Master: unable to add output Material");
379 776 : }
380 : }
381 134 : }
382 :
383 : void
384 940 : CohesiveZoneAction::chekMultipleActionParameters()
385 : {
386 :
387 : // Gather info about all other master actions when we add variables
388 940 : if (_current_task == "validate_coordinate_systems")
389 : {
390 136 : auto actions = _awh.getActions<CohesiveZoneAction>();
391 307 : for (const auto & action : actions)
392 : {
393 : const auto size_before = _boundary_name_union.size();
394 172 : const auto added_size = action->_boundary.size();
395 172 : _boundary_name_union.insert(action->_boundary.begin(), action->_boundary.end());
396 : const auto size_after = _boundary_name_union.size();
397 172 : if (size_after != size_before + added_size)
398 1 : mooseError("The boundary restrictions in the CohesiveZoneAction actions must be "
399 : "non-overlapping.");
400 : }
401 :
402 304 : for (const auto & action : actions)
403 : {
404 : // check for different strain definitions
405 170 : _strain_formulation_union.insert(action->_strain);
406 : const auto size_after = _strain_formulation_union.size();
407 :
408 170 : if (size_after != 1)
409 1 : mooseError("All blocks of the CohesiveZoneAction should have the same strain formulation");
410 : }
411 134 : }
412 938 : }
|