Line data Source code
1 : //* This file is part of the MOOSE framework
2 : //* https://www.mooseframework.org
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("TensorMechanicsApp", CohesiveZoneAction, "add_interface_kernel");
17 : registerMooseAction("TensorMechanicsApp", CohesiveZoneAction, "add_material");
18 : registerMooseAction("TensorMechanicsApp", CohesiveZoneAction, "add_master_action_material");
19 : registerMooseAction("TensorMechanicsApp", CohesiveZoneAction, "add_aux_variable");
20 : registerMooseAction("TensorMechanicsApp", CohesiveZoneAction, "add_aux_kernel");
21 : registerMooseAction("TensorMechanicsApp", CohesiveZoneAction, "add_kernel");
22 : registerMooseAction("TensorMechanicsApp", CohesiveZoneAction, "validate_coordinate_systems");
23 :
24 : InputParameters
25 103 : CohesiveZoneAction::validParams()
26 : {
27 103 : InputParameters params = CohesiveZoneActionBase::validParams();
28 103 : params.addClassDescription("Action to create an instance of the cohesive zone model kernel for "
29 : "each displacement component");
30 206 : params.addRequiredParam<std::vector<BoundaryName>>(
31 : "boundary", "The list of boundary IDs from the mesh where the cohesive zone will be applied");
32 103 : return params;
33 0 : }
34 :
35 103 : CohesiveZoneAction::CohesiveZoneAction(const InputParameters & params)
36 : : CohesiveZoneActionBase(params),
37 206 : _displacements(getParam<std::vector<VariableName>>("displacements")),
38 103 : _ndisp(_displacements.size()),
39 206 : _use_AD(getParam<bool>("use_automatic_differentiation")),
40 318 : _base_name(isParamValid("base_name") && !getParam<std::string>("base_name").empty()
41 103 : ? getParam<std::string>("base_name")
42 : : ""),
43 206 : _boundary(getParam<std::vector<BoundaryName>>("boundary")),
44 206 : _strain(getParam<MooseEnum>("strain").getEnum<Strain>()),
45 206 : _save_in_master(getParam<std::vector<AuxVariableName>>("save_in_master")),
46 206 : _diag_save_in_master(getParam<std::vector<AuxVariableName>>("diag_save_in_master")),
47 206 : _save_in_slave(getParam<std::vector<AuxVariableName>>("save_in_slave")),
48 206 : _diag_save_in_slave(getParam<std::vector<AuxVariableName>>("diag_save_in_slave")),
49 206 : _material_output_order(getParam<MultiMooseEnum>("material_output_order")),
50 309 : _material_output_family(getParam<MultiMooseEnum>("material_output_family")),
51 412 : _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 103 : if (_ndisp > 3 || _ndisp < 1)
56 0 : mooseError("the CZM Action requires 1, 2 or 3 displacement variables.");
57 :
58 103 : switch (_strain)
59 : {
60 69 : case Strain::Small:
61 : {
62 : _czm_kernel_name =
63 69 : _use_AD ? "ADCZMInterfaceKernelSmallStrain" : "CZMInterfaceKernelSmallStrain";
64 69 : _disp_jump_provider_name = _use_AD ? "ADCZMComputeDisplacementJumpSmallStrain"
65 69 : : "CZMComputeDisplacementJumpSmallStrain";
66 : _equilibrium_traction_calculator_name =
67 69 : _use_AD ? "ADCZMComputeGlobalTractionSmallStrain" : "CZMComputeGlobalTractionSmallStrain";
68 : break;
69 : }
70 34 : case Strain::Finite:
71 : {
72 : _czm_kernel_name =
73 34 : _use_AD ? "ADCZMInterfaceKernelTotalLagrangian" : "CZMInterfaceKernelTotalLagrangian";
74 34 : _disp_jump_provider_name = _use_AD ? "ADCZMComputeDisplacementJumpTotalLagrangian"
75 34 : : "CZMComputeDisplacementJumpTotalLagrangian";
76 34 : _equilibrium_traction_calculator_name = _use_AD ? "ADCZMComputeGlobalTractionTotalLagrangian"
77 34 : : "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 103 : 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 103 : 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 103 : 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 103 : 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 788 : 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 582 : _generate_output.push_back(lower);
109 : }
110 :
111 103 : if (!_generate_output.empty())
112 60 : verifyOrderAndFamilyOutputs();
113 103 : }
114 :
115 : void
116 99 : CohesiveZoneAction::addRequiredCZMInterfaceKernels()
117 : {
118 363 : for (unsigned int i = 0; i < _ndisp; ++i)
119 : {
120 : // Create unique kernel name for each displacement component
121 792 : std::string unique_kernel_name = _czm_kernel_name + "_" + _name + "_" + Moose::stringify(i);
122 :
123 264 : InputParameters paramsk = _factory.getValidParams(_czm_kernel_name);
124 :
125 264 : paramsk.set<unsigned int>("component") = i;
126 528 : paramsk.set<NonlinearVariableName>("variable") = _displacements[i];
127 792 : paramsk.set<std::vector<VariableName>>("neighbor_var") = {_displacements[i]};
128 264 : paramsk.set<std::vector<VariableName>>("displacements") = _displacements;
129 264 : paramsk.set<std::vector<BoundaryName>>("boundary") = _boundary;
130 528 : paramsk.set<std::string>("base_name") = _base_name;
131 :
132 : std::string save_in_side;
133 : std::vector<AuxVariableName> save_in_var_names;
134 264 : 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 264 : 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 264 : _problem->addInterfaceKernel(_czm_kernel_name, unique_kernel_name, paramsk);
148 528 : }
149 99 : }
150 :
151 : void
152 99 : CohesiveZoneAction::addRequiredCZMInterfaceMaterials()
153 : {
154 : // Create unique material name for the "CZMComputeDisplacementJump" object
155 99 : std::string unique_material_name = _disp_jump_provider_name + "_" + _name;
156 99 : InputParameters paramsm = _factory.getValidParams(_disp_jump_provider_name);
157 99 : paramsm.set<std::vector<BoundaryName>>("boundary") = _boundary;
158 : ;
159 99 : paramsm.set<std::vector<VariableName>>("displacements") = _displacements;
160 99 : paramsm.set<std::string>("base_name") = _base_name;
161 99 : _problem->addInterfaceMaterial(_disp_jump_provider_name, unique_material_name, paramsm);
162 :
163 : // Create unique material name for the "CZMComputeGlobalTraction" object
164 99 : unique_material_name = _equilibrium_traction_calculator_name + "_" + _name;
165 99 : paramsm = _factory.getValidParams(_equilibrium_traction_calculator_name);
166 99 : paramsm.set<std::vector<BoundaryName>>("boundary") = _boundary;
167 : ;
168 99 : paramsm.set<std::string>("base_name") = _base_name;
169 99 : _problem->addInterfaceMaterial(
170 : _equilibrium_traction_calculator_name, unique_material_name, paramsm);
171 198 : }
172 :
173 : void
174 695 : CohesiveZoneAction::act()
175 : {
176 : // Enforce consistency
177 695 : if (_ndisp != _mesh->dimension())
178 0 : paramError("displacements", "Number of displacements must match problem dimension.");
179 :
180 695 : chekMultipleActionParameters();
181 :
182 693 : if (_current_task == "add_interface_kernel")
183 99 : addRequiredCZMInterfaceKernels();
184 594 : else if (_current_task == "add_master_action_material")
185 99 : addRequiredCZMInterfaceMaterials();
186 :
187 : // optional, add required outputs
188 693 : actOutputGeneration();
189 693 : }
190 :
191 : void
192 301 : CohesiveZoneAction::addRelationshipManagers(Moose::RelationshipManagerType input_rm_type)
193 : {
194 301 : InputParameters ips = _factory.getValidParams(_czm_kernel_name);
195 301 : addRelationshipManagers(input_rm_type, ips);
196 301 : }
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 60 : 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 60 : 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 60 : 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 60 : if (_material_output_order.size() == 0)
242 108 : _material_output_order.push_back("CONSTANT");
243 :
244 : // For only one order, make all orders the same magnitude
245 60 : if (_material_output_order.size() == 1)
246 : _material_output_order =
247 60 : std::vector<std::string>(_generate_output.size(), _material_output_order[0]);
248 :
249 60 : 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 60 : if (_material_output_family.size() == 0)
257 120 : _material_output_family.push_back("MONOMIAL");
258 :
259 : // For only one family, make all families that value
260 60 : if (_material_output_family.size() == 1)
261 : _material_output_family =
262 60 : std::vector<std::string>(_generate_output.size(), _material_output_family[0]);
263 :
264 60 : 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 60 : }
270 :
271 : void
272 693 : CohesiveZoneAction::actOutputGeneration()
273 : {
274 693 : if (_current_task == "add_material")
275 99 : actOutputMatProp();
276 :
277 : // Add variables (optional)
278 693 : if (_current_task == "add_aux_variable")
279 : {
280 : unsigned int index = 0;
281 681 : for (auto out : _generate_output)
282 : {
283 582 : const auto & order = _material_output_order[index];
284 582 : const auto & family = _material_output_family[index];
285 :
286 522 : std::string type = (order == "CONSTANT" && family == "MONOMIAL")
287 : ? "MooseVariableConstMonomial"
288 1164 : : "MooseVariable";
289 :
290 : // Create output helper aux variables
291 582 : auto params = _factory.getValidParams(type);
292 582 : params.set<MooseEnum>("order") = order;
293 1164 : params.set<MooseEnum>("family") = family;
294 582 : if (family == "MONOMIAL")
295 1164 : _problem->addAuxVariable(type, addBaseName(out), params);
296 : else
297 0 : _problem->addVariable(type, addBaseName(out), params);
298 :
299 582 : index++;
300 582 : }
301 : }
302 :
303 : // Add output AuxKernels
304 594 : else if (_current_task == "add_aux_kernel")
305 : {
306 192 : const std::string material_output_aux_name = _use_AD ? "ADMaterialRealAux" : "MaterialRealAux";
307 : // Loop through output aux variables
308 : unsigned int index = 0;
309 681 : for (auto out : _generate_output)
310 : {
311 1164 : if (_material_output_family[index] == "MONOMIAL")
312 : {
313 582 : InputParameters params = _factory.getValidParams(material_output_aux_name);
314 1746 : params.set<MaterialPropertyName>("property") = addBaseName(out);
315 1746 : params.set<AuxVariableName>("variable") = addBaseName(out);
316 582 : params.set<ExecFlagEnum>("execute_on") = EXEC_TIMESTEP_END;
317 582 : params.set<std::vector<BoundaryName>>("boundary") = _boundary;
318 582 : params.set<bool>("check_boundary_restricted") = false;
319 582 : _problem->addAuxKernel(material_output_aux_name, addBaseName(out) + '_' + name(), params);
320 582 : }
321 582 : index++;
322 : }
323 : }
324 693 : }
325 :
326 : void
327 99 : CohesiveZoneAction::actOutputMatProp()
328 : {
329 99 : if (_current_task == "add_material")
330 : {
331 : // Add output Materials
332 681 : for (auto out : _generate_output)
333 : {
334 582 : InputParameters params = emptyInputParameters();
335 :
336 : // RealVectorCartesianComponent
337 936 : if (
338 1164 : [&]()
339 : {
340 1620 : for (const auto & vq : _real_vector_cartesian_component_table)
341 4848 : for (unsigned int a = 0; a < 3; ++a)
342 7620 : if (vq.first + '_' + _component_table[a] == out)
343 : {
344 354 : auto type = _use_AD ? "ADCZMRealVectorCartesianComponent"
345 : : "CZMRealVectorCartesianComponent";
346 708 : params = _factory.getValidParams(type);
347 354 : params.set<std::string>("real_vector_value") = vq.second;
348 354 : params.set<unsigned int>("index") = a;
349 354 : params.set<std::vector<BoundaryName>>("boundary") = _boundary;
350 1062 : params.set<MaterialPropertyName>("property_name") = addBaseName(out);
351 354 : params.set<std::string>("base_name") = _base_name;
352 1062 : _problem->addInterfaceMaterial(type, addBaseName(out) + '_' + name(), params);
353 : return true;
354 : }
355 : return false;
356 582 : }())
357 354 : continue;
358 :
359 : // CZMRealVectorScalar
360 456 : if (setupOutput(out,
361 : _vector_direction_table,
362 228 : [&](std::string prop_name, std::string direction)
363 : {
364 228 : auto type = _use_AD ? "ADCZMRealVectorScalar" : "CZMRealVectorScalar";
365 228 : params = _factory.getValidParams(type);
366 228 : params.set<std::string>("real_vector_value") = prop_name;
367 228 : params.set<MooseEnum>("direction") = direction;
368 684 : params.set<MaterialPropertyName>("property_name") = addBaseName(out);
369 228 : params.set<std::vector<BoundaryName>>("boundary") = _boundary;
370 228 : params.set<std::string>("base_name") = _base_name;
371 684 : _problem->addInterfaceMaterial(
372 228 : type, addBaseName(out) + '_' + name(), params);
373 228 : }))
374 228 : continue;
375 :
376 0 : mooseError("CZM Master: unable to add output Material");
377 582 : }
378 : }
379 99 : }
380 :
381 : void
382 695 : CohesiveZoneAction::chekMultipleActionParameters()
383 : {
384 :
385 : // Gather info about all other master actions when we add variables
386 695 : if (_current_task == "validate_coordinate_systems")
387 : {
388 101 : auto actions = _awh.getActions<CohesiveZoneAction>();
389 227 : for (const auto & action : actions)
390 : {
391 : const auto size_before = _boundary_name_union.size();
392 127 : const auto added_size = action->_boundary.size();
393 127 : _boundary_name_union.insert(action->_boundary.begin(), action->_boundary.end());
394 : const auto size_after = _boundary_name_union.size();
395 127 : if (size_after != size_before + added_size)
396 1 : mooseError("The boundary restrictions in the CohesiveZoneAction actions must be "
397 : "non-overlapping.");
398 : }
399 :
400 224 : for (const auto & action : actions)
401 : {
402 : // check for different strain definitions
403 125 : _strain_formulation_union.insert(action->_strain);
404 : const auto size_after = _strain_formulation_union.size();
405 :
406 125 : if (size_after != 1)
407 1 : mooseError("All blocks of the CohesiveZoneAction should have the same strain formulation");
408 : }
409 : }
410 693 : }
|