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