22 "ADLAROMANCEStressUpdate");
29 params.
addClassDescription(
"Base class to calculate the effective creep strain based on the " 30 "rates predicted by a material specific Los Alamos Reduced Order " 31 "Model derived from a Visco-Plastic Self Consistent calculations.");
34 params.
addParam<MaterialPropertyName>(
"environmental_factor",
35 "Optional coupled environmental factor");
37 MooseEnum error_lower_limit_behavior(
"ERROR EXCEPTION WARN IGNORE DONTHING USELIMIT",
40 MooseEnum error_upper_limit_behavior(
"ERROR EXCEPTION",
"EXCEPTION");
42 "cell_input_window_low_failure",
43 error_lower_limit_behavior,
44 "What to do if cell dislocation concentration is outside the lower global " 45 "window of applicability.");
47 "cell_input_window_high_failure",
48 error_upper_limit_behavior,
49 "What to do if cell dislocation concentration is outside the upper global " 50 "window of applicability.");
52 error_lower_limit_behavior,
53 "What to do if wall dislocation concentration is outside the " 54 "lower global window of applicability.");
56 error_upper_limit_behavior,
57 "What to do if wall dislocation concentration is outside the " 58 "upper global window of applicability.");
60 "old_strain_input_window_low_failure",
61 error_lower_limit_behavior,
62 "What to do if old strain is outside the lower global window of applicability.");
64 "old_strain_input_window_high_failure",
65 error_upper_limit_behavior,
66 "What to do if old strain is outside the upper global window of applicability.");
68 MooseEnum extrapolated_lower_limit_behavior(
69 "ERROR EXCEPTION WARN IGNORE DONOTHING USELIMIT EXTRAPOLATE",
"EXTRAPOLATE");
71 "stress_input_window_low_failure",
72 extrapolated_lower_limit_behavior,
73 "What to do if stress is outside the lower global window of applicability.");
75 "stress_input_window_high_failure",
76 error_upper_limit_behavior,
77 "What to do if stress is outside the upper global window of applicability.");
79 "temperature_input_window_low_failure",
80 extrapolated_lower_limit_behavior,
81 "What to do if temperature is outside the lower global window of applicability.");
83 "temperature_input_window_high_failure",
84 error_upper_limit_behavior,
85 "What to do if temperature is outside the upper global window of applicability.");
87 "environment_input_window_low_failure",
88 extrapolated_lower_limit_behavior,
89 "What to do if environmental factor is outside the lower global window of applicability.");
91 "environment_input_window_high_failure",
92 error_upper_limit_behavior,
93 "What to do if environmental factor is outside the upper global window of applicability.");
96 "initial_cell_dislocation_density",
97 "initial_cell_dislocation_density >= 0.0",
98 "Initial density of cell (glissile) dislocations (1/m^2)");
100 "cell_dislocations_normal_distribution_width",
102 "cell_dislocations_normal_distribution_width >= 0.0",
103 "Width of the normal distribution to assign to the initial cell dislocation value. This is " 104 "given as a fraction of the initial_cell_dislocation_density.");
106 "max_relative_cell_dislocation_increment",
108 "max_relative_cell_dislocation_increment > 0.0",
109 "Maximum increment of density of cell (glissile) dislocations.");
112 "initial_wall_dislocation_density",
113 "initial_wall_dislocation_density >= 0.0",
114 "wall (locked) dislocation density initial value (1/m^2).");
116 "wall_dislocations_normal_distribution_width",
118 "wall_dislocations_normal_distribution_width >= 0.0",
119 "Width of the normal distribution to assign to the initial wall dislocation value. This is " 120 "given as a fraction of the initial_wall_dislocation_density.");
122 "max_relative_wall_dislocation_increment",
124 "max_relative_wall_dislocation_increment > 0.0",
125 "Maximum increment of wall (locked) dislocation density initial value (1/m^2).");
127 params.
addParam<
bool>(
"verbose",
false,
"Flag to output verbose information.");
130 "cell_dislocation_density_forcing_function",
131 "Optional forcing function for wall dislocation. If provided, the wall dislocation " 132 "density will be reset to the function value at the beginning of the timestep. Used for " 133 "testing purposes only.");
135 "wall_dislocation_density_forcing_function",
136 "Optional forcing function for wall dislocation. If provided, the wall dislocation " 137 "density will be reset to the function value at the beginning of the timestep. Used for " 138 "testing purposes only.");
140 "old_creep_strain_forcing_function",
141 "Optional forcing function for the creep strain from the previous timestep. If provided, " 142 "the old creep strain will be reset to the function value at the beginning of the " 143 "timestep. Used for testing purposes only.");
145 "effective_stress_forcing_function",
146 "Optional forcing function for the effective stress. If provided, the effective stress will " 147 "be reset to the function value at the beginning of the timestep. Used for testing purposes " 150 params.
addParam<
unsigned int>(
"seed", 0,
"Random number generator seed");
151 params.
addParam<std::string>(
"stress_unit",
"Pa",
"unit of stress");
154 params.
addParam<DataFileName>(
"model",
"LaRomance model JSON datafile");
155 params.
addParam<FileName>(
"export_model",
"Write LaRomance model to JSON datafile");
158 "cell_dislocation_density_forcing_function wall_dislocation_density_forcing_function " 159 "old_creep_strain_forcing_function effective_stress_forcing_function seed stress_unit",
165 template <
bool is_ad>
169 _temperature(this->template coupledGenericValue<is_ad>(
"temperature")),
171 this->isParamValid(
"environmental_factor")
172 ? &this->template getGenericMaterialProperty<
Real, is_ad>(
"environmental_factor")
174 _window_failure(_environmental ? 6 : 5),
176 _verbose(this->template getParam<bool>(
"verbose")),
178 this->template declareGenericProperty<
Real, is_ad>(this->_base_name +
"cell_dislocations")),
179 _cell_dislocations_old(
180 this->template getMaterialPropertyOld<
Real>(this->_base_name +
"cell_dislocations")),
181 _max_cell_increment(this->template getParam<
Real>(
"max_relative_cell_dislocation_increment")),
182 _cell_function(this->isParamValid(
"cell_dislocation_density_forcing_function")
183 ? &this->getFunction(
"cell_dislocation_density_forcing_function")
185 _cell_dislocation_increment(0.0),
187 this->template declareGenericProperty<
Real, is_ad>(this->_base_name +
"wall_dislocations")),
188 _wall_dislocations_old(
189 this->template getMaterialPropertyOld<
Real>(this->_base_name +
"wall_dislocations")),
190 _max_wall_increment(this->template getParam<
Real>(
"max_relative_wall_dislocation_increment")),
191 _wall_function(this->isParamValid(
"wall_dislocation_density_forcing_function")
192 ? &this->getFunction(
"wall_dislocation_density_forcing_function")
194 _stress_function(this->isParamValid(
"effective_stress_forcing_function")
195 ? &this->getFunction(
"effective_stress_forcing_function")
197 _wall_dislocation_increment(0.0),
198 _cell_input_index(0),
199 _wall_input_index(1),
200 _stress_input_index(2),
201 _old_strain_input_index(3),
202 _temperature_input_index(4),
203 _environmental_input_index(5),
204 _cell_output_index(0),
205 _wall_output_index(1),
206 _strain_output_index(2),
208 _creep_strain_old_forcing_function(this->isParamValid(
"old_creep_strain_forcing_function")
209 ? &this->getFunction(
"old_creep_strain_forcing_function")
213 this->template declareGenericProperty<
Real, is_ad>(this->_base_name +
"creep_rate")),
214 _cell_rate(this->template declareGenericProperty<
Real, is_ad>(this->_base_name +
215 "cell_dislocation_rate")),
216 _wall_rate(this->template declareGenericProperty<
Real, is_ad>(this->_base_name +
217 "wall_dislocation_rate")),
218 _extrapolation(this->template declareProperty<
Real>(
"ROM_extrapolation")),
219 _second_partition_weight(
220 this->template declareGenericProperty<
Real, is_ad>(
"partition_weight")),
223 _old_input_values(3),
224 _wall_dislocations_step(this->template declareGenericProperty<
Real, is_ad>(
225 this->_base_name +
"wall_dislocations_step")),
226 _cell_dislocations_step(this->template declareGenericProperty<
Real, is_ad>(
227 this->_base_name +
"cell_dislocations_step")),
228 _plastic_strain_increment(),
230 this->template declareProperty<
Real>(this->_base_name +
"number_of_substeps")),
231 _index_name(_window_failure.size())
242 parameters.
get<
MooseEnum>(
"cell_input_window_low_failure").getEnum<WindowFailure>();
273 const auto model_file_name = this->
template getParam<DataFileName>(
"model");
274 std::ifstream model_file(model_file_name.c_str());
281 template <
bool is_ad>
285 _json[
"strain_cutoff"] = getStrainCutoff();
286 _json[
"transform"] = getTransform();
287 _json[
"transform_coefs"] = getTransformCoefs();
288 _json[
"input_limits"] = getInputLimits();
289 _json[
"normalization_limits"] = getNormalizationLimits();
290 _json[
"coefs"] = getCoefs();
291 _json[
"tiling"] = getTilings();
292 _json[
"cutoff"] = getStrainCutoff();
295 template <
bool is_ad>
302 template <
bool is_ad>
309 const MooseUnits stress_unit_from(parameters.
get<std::string>(
"stress_unit"));
310 _stress_ucf = stress_unit_to.
convert(1, stress_unit_from);
313 template <
bool is_ad>
318 if (this->isParamValid(
"export_model"))
321 std::ofstream
out(this->
template getParam<FileName>(
"export_model").c_str());
326 _transform = getTransform();
327 _transform_coefs = getTransformCoefs();
328 _input_limits = getInputLimits();
329 _normalization_limits = getNormalizationLimits();
331 _tiling = getTilings();
332 _cutoff = getStrainCutoff();
335 _num_partitions = _transform.size();
336 if (_num_partitions < 1 || _num_partitions > 2)
338 "In ", _name,
": First dimension of getTransform must be either size one or size two");
339 if (_transform[0].size() < 1)
340 mooseError(
"In ", _name,
": Transform is not the correct shape");
341 _num_outputs = _transform[0][0].size();
342 if (_num_outputs != 3)
347 " outputs detected. Three and only three outputs are currently supported.");
349 _num_inputs = _transform[0][0][0].size();
350 if (_num_inputs != 5 && _num_inputs != 6)
355 " inputs detected. Only five or six inputs currently supported.");
356 if (_num_inputs == 6 && !_environmental)
358 "environmental_factor",
359 "Number of ROM inputs indicate environmental factor is required to be coupled.");
360 if (_num_inputs != 6 && _environmental)
361 this->paramError(
"environmental_factor",
362 "Number of ROM inputs indicate environmental factor is not implemented, but " 363 "environmental factor coupled.");
364 _num_tiles.resize(_num_partitions);
365 _num_coefs.resize(_num_partitions);
366 _degree.resize(_num_partitions);
367 _precomputed_vals.resize(_num_partitions);
368 _rom_inputs.resize(_num_partitions);
369 _polynomial_inputs.resize(_num_partitions);
370 _non_stress_weights.resize(_num_partitions);
371 _weights.resize(_num_partitions);
372 _partition_weights.resize(_num_partitions);
373 _dpartition_weight_dstress.resize(_num_partitions);
374 _transformed_normalization_limits.resize(_num_partitions);
375 _makeframe_helper.resize(_num_partitions);
376 _global_limits.resize(_num_inputs);
378 for (
unsigned int i = 0; i < _num_inputs; ++i)
379 _global_limits[i] = {std::numeric_limits<Real>::max(), 0.0};
383 if (_transform.size() != _num_partitions || _transform_coefs.size() != _num_partitions ||
384 _input_limits.size() != _num_partitions || _normalization_limits.size() != _num_partitions ||
385 _coefs.size() != _num_partitions || _tiling.size() != _num_partitions ||
386 _cutoff.size() != _num_partitions)
388 "In ", _name,
": one of the ROM inputs does not have the correct number of partitions");
390 for (
unsigned int p = 0; p < _num_partitions; ++p)
392 _num_tiles[p] = _transform[p].size();
394 mooseError(
"In ", _name,
": No tiles detected. Double check your ROM input");
396 bool correct_shape =
true;
397 if (_transform[p].size() != _num_tiles[p] || _transform_coefs[p].size() != _num_tiles[p] ||
398 _input_limits[p].size() != _num_tiles[p] ||
399 _normalization_limits[p].size() != _num_tiles[p] || _coefs[p].size() != _num_tiles[p])
400 correct_shape =
false;
401 if (_tiling[p].size() != _num_inputs)
402 correct_shape =
false;
403 if (_coefs[p][0].size() == 0)
404 correct_shape =
false;
405 _num_coefs[p] = _coefs[p][0][0].size();
408 for (
unsigned int t = 0; t < _num_tiles[p]; ++t)
410 if (_transform[p][t].size() != _num_outputs ||
411 _transform_coefs[p][t].size() != _num_outputs || _coefs[p][t].size() != _num_outputs)
412 correct_shape =
false;
413 for (
unsigned int o = 0; o < _num_outputs; ++o)
414 if (_transform[p][t][o].size() != _num_inputs ||
415 _transform_coefs[p][t][o].size() != _num_inputs ||
416 _coefs[p][t][o].size() != _num_coefs[p])
417 correct_shape =
false;
418 if (_input_limits[p][t].size() != _num_inputs ||
419 _normalization_limits[p][t].size() != _num_inputs)
420 correct_shape =
false;
421 for (
unsigned int i = 0; i < _num_inputs; ++i)
422 if (_input_limits[p][t][i].size() != 2 || _normalization_limits[p][t][i].size() != 2)
423 correct_shape =
false;
427 mooseError(
"In ", _name,
": ROM data is not the right shape.");
429 _degree[p] =
std::pow(_num_coefs[p], 1.0 / _num_inputs);
430 if (!_degree[p] || _degree[p] > 4)
431 mooseError(
"In ", _name,
": degree must be 1, 2, 3 or 4.");
437 for (
unsigned int i = 0; i < _num_inputs; ++i)
439 for (
unsigned int t = 0; t < _num_tiles[p]; ++t)
441 if (_input_limits[p][t][i][0] >= _input_limits[p][t][i][1])
442 mooseError(
"In ", _name,
": Input limits are ordered incorrectly");
443 _global_limits[i].first = std::min(_global_limits[i].first, _input_limits[p][t][i][0]);
444 _global_limits[i].second = std::max(_global_limits[i].second, _input_limits[p][t][i][1]);
449 _transformed_normalization_limits[p] = getTransformedLimits(p, _normalization_limits[p]);
450 _makeframe_helper[p] = getMakeFrameHelper(p);
453 _precomputed_vals[p].resize(_num_tiles[p], std::vector<
GenericReal<is_ad>>(_num_coefs[p]));
455 _polynomial_inputs[p].resize(_num_tiles[p],
458 _non_stress_weights[p].resize(_num_tiles[p]);
459 _weights[p].resize(_num_tiles[p], 0);
462 _input_values.resize(_num_inputs);
466 Moose::err <<
"ROM model info: " << _name <<
"\n";
467 Moose::err <<
" number of tiles, partition 1: " << _num_tiles[0] <<
"\n";
468 if (_num_partitions > 1)
469 Moose::err <<
" number of tiles, partition 2: " << _num_tiles[1] <<
"\n";
470 Moose::err <<
" number of outputs: " << _num_outputs <<
"\n";
471 Moose::err <<
" number of inputs: " << _num_inputs <<
"\n";
472 Moose::err <<
" degree (max Legendre degree + constant), partition 1: " << _degree[0] <<
"\n";
473 if (_num_partitions > 1)
474 Moose::err <<
" degree (max Legendre degree + constant), partition 2: " << _degree[1] <<
"\n";
475 Moose::err <<
" number of coefficients, partition 1: " << _num_coefs[0] <<
"\n";
476 if (_num_partitions > 1)
477 Moose::err <<
" number of coefficients, partition 2: " << _num_coefs[1] <<
"\n";
478 Moose::err <<
" Global limits:\n cell dislocations (" 479 << _global_limits[_cell_input_index].first <<
" - " 480 << _global_limits[_cell_input_index].second <<
")\n";
481 Moose::err <<
" wall dislocations (" << _global_limits[_wall_input_index].first <<
" - " 482 << _global_limits[_wall_input_index].second <<
")\n";
483 Moose::err <<
" Stress (" << _global_limits[_stress_input_index].first <<
" - " 484 << _global_limits[_stress_input_index].second <<
")\n";
485 Moose::err <<
" Old strain (" << _global_limits[_old_strain_input_index].first <<
" - " 486 << _global_limits[_old_strain_input_index].second <<
")\n";
487 Moose::err <<
" Temperature (" << _global_limits[_temperature_input_index].first <<
" - " 488 << _global_limits[_temperature_input_index].second <<
")\n";
490 Moose::err <<
" Environmental factor (" << _global_limits[_environmental_input_index].first
491 <<
" - " << _global_limits[_environmental_input_index].second <<
")\n";
492 Moose::err << std::endl;
496 template <
bool is_ad>
501 rng.
seed(0, this->
template getParam<unsigned int>(
"seed"));
504 this->
template getParam<Real>(
"initial_cell_dislocation_density"),
505 this->
template getParam<Real>(
"initial_cell_dislocation_density") *
506 this->
template getParam<Real>(
"cell_dislocations_normal_distribution_width"));
508 this->
template getParam<Real>(
"initial_wall_dislocation_density"),
509 this->
template getParam<Real>(
"initial_wall_dislocation_density") *
510 this->
template getParam<Real>(
"wall_dislocations_normal_distribution_width"));
515 template <
bool is_ad>
522 return effective_trial_stress / this->_three_shear_modulus * 0.999999;
525 template <
bool is_ad>
529 _cell_dislocation_increment = 0.0;
530 _wall_dislocation_increment = 0.0;
532 _plastic_strain_increment.zero();
534 _wall_dislocations_step[_qp] = 0.0;
535 _cell_dislocations_step[_qp] = 0.0;
538 template <
bool is_ad>
541 const unsigned int total_number_of_substeps)
543 _wall_dislocations_step[_qp] += _wall_dislocation_increment;
544 _cell_dislocations_step[_qp] += _cell_dislocation_increment;
545 _number_of_substeps[_qp] = total_number_of_substeps;
548 template <
bool is_ad>
557 RankTwoTensor creep_strain_substep = this->_creep_strain_old[_qp] + _plastic_strain_increment;
560 _old_input_values[_cell_output_index] =
562 ? _cell_function->value(_t, _q_point[_qp])
564 _old_input_values[_wall_output_index] =
566 ? _wall_function->value(_t, _q_point[_qp])
568 _old_input_values[_strain_output_index] =
569 _creep_strain_old_forcing_function
570 ? _creep_strain_old_forcing_function->value(_t, _q_point[_qp])
572 std::sqrt((creep_strain_substep).doubleContraction(creep_strain_substep) / 1.5));
575 _input_values[_cell_input_index] = _old_input_values[_cell_output_index];
576 _input_values[_wall_input_index] = _old_input_values[_wall_output_index];
577 _input_values[_stress_input_index] = _stress_function ? _stress_function->value(_t, _q_point[_qp])
578 : effective_trial_stress * _stress_ucf;
579 _input_values[_old_strain_input_index] = _old_input_values[_strain_output_index];
580 _input_values[_temperature_input_index] = _temperature[_qp];
582 _input_values[_environmental_input_index] = (*_environmental)[_qp];
585 for (
unsigned int p = 0; p < _num_partitions; ++p)
586 std::fill(_non_stress_weights[p].begin(), _non_stress_weights[p].end(), 1.0);
587 for (
unsigned int i = 0; i < _num_inputs; i++)
588 if (i != _stress_input_index)
589 computeTileWeight(_non_stress_weights, _input_values[i], i);
592 precomputeROM(_strain_output_index);
595 template <
bool is_ad>
600 const unsigned int in_index,
601 const bool derivative)
604 "computeTileWeight input must be finite");
606 for (
unsigned int p = 0; p < _num_partitions; ++p)
608 for (
unsigned int t = 0; t < _num_tiles[p]; ++t)
611 if (input >= _input_limits[p][t][in_index][0] && input <= _input_limits[p][t][in_index][1])
615 if (_tiling[p][in_index] == 1)
623 bool overlap =
false;
624 for (
unsigned int tt = 0; tt < _num_tiles[p]; ++tt)
626 if (!overlap && t != tt)
631 if (areTilesNotIdentical(p, t, tt, in_index) && checkInTile(p, tt))
636 if (_input_limits[p][t][in_index][0] < _input_limits[p][tt][in_index][0] &&
637 _input_limits[p][t][in_index][1] > _input_limits[p][tt][in_index][0])
639 weights[p][t] *= sigmoid(_input_limits[p][tt][in_index][0],
640 _input_limits[p][t][in_index][1],
645 else if (_input_limits[p][t][in_index][0] > _input_limits[p][tt][in_index][0] &&
646 _input_limits[p][t][in_index][0] < _input_limits[p][tt][in_index][1])
649 weights[p][t] *= -sigmoid(_input_limits[p][t][in_index][0],
650 _input_limits[p][tt][in_index][1],
654 weights[p][t] *= (1.0 - sigmoid(_input_limits[p][t][in_index][0],
655 _input_limits[p][tt][in_index][1],
669 else if (input < _input_limits[p][t][in_index][0])
672 if (_input_limits[p][t][in_index][0] == _global_limits[in_index].first)
674 if (_window_failure[in_index].first == WindowFailure::EXTRAPOLATE)
677 weights[p][t] *= -sigmoid(0.0, _input_limits[p][t][in_index][0], input,
derivative);
679 weights[p][t] *= (1.0 - sigmoid(0.0, _input_limits[p][t][in_index][0], input));
680 input = _input_limits[p][t][in_index][0];
682 else if (_window_failure[in_index].first == WindowFailure::USELIMIT)
683 input = _input_limits[p][t][in_index][0];
687 std::stringstream msg;
688 msg <<
"In " << _name <<
": " << _index_name[in_index]
690 <<
") is out of lower global range (" << _input_limits[p][t][in_index][0] <<
")";
693 input = _input_limits[p][t][in_index][0];
695 if (_window_failure[in_index].first == WindowFailure::WARN)
697 else if (_window_failure[in_index].first == WindowFailure::ERROR)
699 else if (_window_failure[in_index].first == WindowFailure::EXCEPTION)
700 mooseException(msg.str());
709 else if (input > _input_limits[p][t][in_index][1])
711 if (_input_limits[p][t][in_index][1] == _global_limits[in_index].second)
713 if (_window_failure[in_index].second == WindowFailure::EXTRAPOLATE)
714 mooseError(
"Internal error. Extrapolate not appropriate for upper bound");
715 else if (_window_failure[in_index].second == WindowFailure::USELIMIT)
716 input = _input_limits[p][t][in_index][1];
720 std::stringstream msg;
721 msg <<
"In " << _name <<
": " << _index_name[in_index]
723 <<
") is out of upper global range (" << _input_limits[p][t][in_index][1] <<
")";
726 input = _input_limits[p][t][in_index][1];
728 if (_window_failure[in_index].second == WindowFailure::WARN)
730 else if (_window_failure[in_index].second == WindowFailure::ERROR)
732 else if (_window_failure[in_index].second == WindowFailure::EXCEPTION)
733 mooseException(msg.str());
743 mooseError(
"In ", _name,
": Internal error. Outside input limits, input=", input);
748 template <
bool is_ad>
752 for (
unsigned int i = 0; i < _num_inputs; ++i)
753 if (_input_values[i] < _input_limits[p][t][i][0] ||
754 _input_values[i] > _input_limits[p][t][i][1])
759 template <
bool is_ad>
762 const unsigned int t,
763 const unsigned int tt,
764 const unsigned int in_index)
766 if (_input_limits[p][t][in_index][0] != _input_limits[p][tt][in_index][0] &&
767 _input_limits[p][t][in_index][1] != _input_limits[p][tt][in_index][1])
773 template <
bool is_ad>
779 "computeResidual: effective_trial_stress must be finite");
781 "computeResidual: scalar must be finite!");
784 ? _stress_function->value(_t, _q_point[_qp])
785 : effective_trial_stress * _stress_ucf;
789 if (this->_apply_strain)
791 trial_stress_mpa -= this->_three_shear_modulus * scalar * _stress_ucf;
792 dtrial_stress_dscalar -= this->_three_shear_modulus * _stress_ucf;
794 _input_values[_stress_input_index] = trial_stress_mpa;
797 for (
unsigned int p = 0; p < _num_partitions; ++p)
798 _weights[p] = _non_stress_weights[p];
799 computeTileWeight(_weights, _input_values[_stress_input_index], _stress_input_index);
800 auto dweights_dstress = _non_stress_weights;
802 dweights_dstress, _input_values[_stress_input_index], _stress_input_index,
true);
804 computePartitionWeights(_partition_weights, _dpartition_weight_dstress);
807 _extrapolation[_qp] = 0.0;
808 for (
unsigned int p = 0; p < _num_partitions; ++p)
809 for (
unsigned int t = 0; t < _num_tiles[p]; ++t)
816 for (
unsigned int p = 0; p < _num_partitions; p++)
818 if (_partition_weights[p])
822 unsigned int number_of_active_tiles = 0;
823 for (
unsigned int t = 0; t < _num_tiles[p]; ++t)
826 number_of_active_tiles += checkInTile(p, t);
830 weight_normalizer += _weights[p][t];
835 if (number_of_active_tiles == 3)
836 for (
unsigned int t = 0; t < _num_tiles[p]; ++t)
838 _weights[p][t] /= weight_normalizer;
839 dweights_dstress[p][t] /= weight_normalizer;
842 for (
unsigned int t = 0; t < _num_tiles[p]; ++t)
846 if (rom == std::numeric_limits<float>::infinity())
847 mooseError(
"In ", _name,
": Output for strain increment reaches infinity: ", rom);
849 total_rom_effective_strain_inc += _partition_weights[p] * _weights[p][t] * rom;
851 dtotal_rom_effective_strain_inc_dstress +=
852 _partition_weights[p] * _weights[p][t] * computeROM(t, p, _strain_output_index,
true);
853 if (_dpartition_weight_dstress[p])
854 dtotal_rom_effective_strain_inc_dstress +=
855 _dpartition_weight_dstress[p] * _weights[p][t] * rom;
856 if (dweights_dstress[p][t])
857 dtotal_rom_effective_strain_inc_dstress +=
858 _partition_weights[p] * dweights_dstress[p][t] * rom;
865 Moose::err << std::setprecision(9);
868 environmental = (*_environmental)[_qp];
869 Moose::err <<
"Verbose information from " << _name <<
": \n";
870 Moose::err <<
" dt: " << _dt <<
"\n";
871 Moose::err <<
" old cell disl: " << _old_input_values[_cell_output_index] <<
"\n";
872 Moose::err <<
" old wall disl: " << _old_input_values[_wall_output_index] <<
"\n";
873 Moose::err <<
" initial stress (MPa): " 880 Moose::err <<
" old effective strain: " << _old_input_values[_strain_output_index] <<
"\n";
884 Moose::err <<
" weights by tile, partition 1: ";
885 for (
unsigned int t = 0; t < _num_tiles[0]; ++t)
888 if (_num_partitions > 1)
890 Moose::err <<
" weights by tile, partition 2: ";
891 for (
unsigned int t = 0; t < _num_tiles[1]; ++t)
895 Moose::err <<
" nonstress weights by tile, partition 1: ";
896 for (
unsigned int t = 0; t < _num_tiles[0]; ++t)
899 if (_num_partitions > 1)
901 Moose::err <<
" nonstress weights by tile, partition 2: ";
902 for (
unsigned int t = 0; t < _num_tiles[1]; ++t)
907 Moose::err <<
" effective strain increment: " 911 _creep_rate[_qp] = total_rom_effective_strain_inc / _dt;
912 _derivative = dtotal_rom_effective_strain_inc_dstress * dtrial_stress_dscalar - 1.0;
914 if (!this->_apply_strain)
917 Moose::err <<
" Strain not applied due to apply_strain input parameter!" << std::endl;
921 return total_rom_effective_strain_inc - scalar;
924 template <
bool is_ad>
928 for (
unsigned int p = 0; p < _num_partitions; ++p)
930 for (
unsigned int t = 0; t < _num_tiles[p]; ++t)
933 if (_non_stress_weights[p][t])
935 for (
unsigned int i = 0; i < _num_inputs; ++i)
937 if (i != _stress_input_index)
939 _rom_inputs[p][t][i] =
940 normalizeInput(_input_values[i],
941 _transform[p][t][out_index][i],
942 _transform_coefs[p][t][out_index][i],
943 _transformed_normalization_limits[p][t][out_index][i]);
944 buildPolynomials(p, _rom_inputs[p][t][i], _polynomial_inputs[p][t][i]);
948 p, _coefs[p][t][out_index], _polynomial_inputs[p][t], _precomputed_vals[p][t]);
954 template <
bool is_ad>
957 const unsigned int p,
958 const unsigned out_index,
959 const bool derivative)
962 _rom_inputs[p][t][_stress_input_index] =
963 normalizeInput(_input_values[_stress_input_index],
964 _transform[p][t][out_index][_stress_input_index],
965 _transform_coefs[p][t][out_index][_stress_input_index],
966 _transformed_normalization_limits[p][t][out_index][_stress_input_index]);
969 p, _rom_inputs[p][t][_stress_input_index], _polynomial_inputs[p][t][_stress_input_index]);
973 computeValues(p, _precomputed_vals[p][t], _polynomial_inputs[p][t]);
977 return convertOutput(p, _old_input_values, rom_output, out_index);
980 normalizeInput(_input_values[_stress_input_index],
981 _transform[p][t][out_index][_stress_input_index],
982 _transform_coefs[p][t][out_index][_stress_input_index],
983 _transformed_normalization_limits[p][t][out_index][_stress_input_index],
986 std::vector<GenericReal<is_ad>> dpolynomial_inputs(_degree[p], 0.0);
988 p, _rom_inputs[p][t][_stress_input_index], dpolynomial_inputs, drom_input,
derivative);
991 p, _precomputed_vals[p][t], _polynomial_inputs[p][t], dpolynomial_inputs,
derivative);
992 return convertOutput(p, _old_input_values, rom_output, out_index, drom_output,
derivative);
995 template <
bool is_ad>
999 const Real transform_coef,
1000 const std::vector<Real> & transformed_limits,
1001 const bool derivative)
1004 convertValue(
x, transform, transform_coef,
derivative);
1008 return x / transformed_limits[2];
1010 return (
x - transformed_limits[0]) / transformed_limits[2] - 1.0;
1013 template <
bool is_ad>
1016 const unsigned int p,
1020 const bool derivative)
1022 for (
unsigned int d = 0;
d < _degree[p]; ++
d)
1024 polynomial_inputs[
d] = computePolynomial(rom_input,
d);
1027 polynomial_inputs[
d] = drom_input * computePolynomial(rom_input,
d,
derivative);
1031 template <
bool is_ad>
1034 const unsigned int p,
1035 const std::vector<Real> & coefs,
1039 for (
unsigned int c = 0;
c < _num_coefs[p]; ++
c)
1041 precomputed[
c] = coefs[
c];
1042 for (
unsigned int i = 0; i < _num_inputs; ++i)
1043 if (i != _stress_input_index)
1044 precomputed[
c] *= polynomial_inputs[i][_makeframe_helper[p][
c + _num_coefs[p] * i]];
1048 template <
bool is_ad>
1051 const unsigned int p,
1055 const bool derivative)
1058 for (
unsigned int c = 0;
c < _num_coefs[p]; ++
c)
1063 polynomial_inputs[_stress_input_index]
1064 [_makeframe_helper[p][
c + _num_coefs[p] * _stress_input_index]];
1069 dpolynomial_inputs[_makeframe_helper[p][
c + _num_coefs[p] * _stress_input_index]];
1074 template <
bool is_ad>
1077 const std::vector<Real> & old_input_values,
1079 const unsigned out_index,
1081 const bool derivative)
1083 if (out_index == _strain_output_index)
1086 return std::exp(rom_output) * _dt * drom_output;
1088 return std::exp(rom_output) * _dt;
1095 mooseAssert(expout > 0.0,
"ROM calculated strain increment must be positive");
1097 if (expout > _cutoff[p])
1098 expout -= _cutoff[p];
1100 expout = -_cutoff[p] * _cutoff[p] / expout + _cutoff[p];
1102 return -expout * old_input_values[out_index] * _dt;
1105 template <
bool is_ad>
1108 const unsigned int degree,
1109 const bool derivative)
1117 else if (degree == 1)
1123 else if (degree == 2)
1127 return 1.5 * Utility::pow<2>(
value) - 0.5;
1132 return 7.5 * Utility::pow<2>(
value) - 1.5;
1133 return 2.5 * Utility::pow<3>(
value) - 1.5 *
value;
1137 template <
bool is_ad>
1138 std::vector<std::vector<std::vector<std::vector<Real>>>>
1140 const unsigned int p,
const std::vector<std::vector<std::vector<Real>>> limits)
1142 std::vector<std::vector<std::vector<std::vector<Real>>>> transformed_limits(
1144 std::vector<std::vector<std::vector<Real>>>(
1145 _num_outputs, std::vector<std::vector<Real>>(_num_inputs, std::vector<Real>(3))));
1146 for (
unsigned int t = 0; t < _num_tiles[p]; ++t)
1148 for (
unsigned int o = 0; o < _num_outputs; ++o)
1150 for (
unsigned int i = 0; i < _num_inputs; ++i)
1152 for (
unsigned int k = 0;
k < 2; ++
k)
1154 transformed_limits[t][o][i][
k] = limits[t][i][
k];
1156 transformed_limits[t][o][i][
k], _transform[p][t][o][i], _transform_coefs[p][t][o][i]);
1158 transformed_limits[t][o][i][2] =
1159 (transformed_limits[t][o][i][1] - transformed_limits[t][o][i][0]) / 2.0;
1163 return transformed_limits;
1166 template <
bool is_ad>
1167 std::vector<unsigned int>
1170 std::vector<unsigned int>
v(_num_coefs[p] * _num_inputs);
1172 for (
unsigned int numcoeffs = 0; numcoeffs < _num_coefs[p]; ++numcoeffs)
1173 for (
unsigned int invar = 0; invar < _num_inputs; ++invar)
1174 v[numcoeffs + _num_coefs[p] * invar] =
1180 template <
bool is_ad>
1185 _cell_dislocation_increment = 0.0;
1186 _wall_dislocation_increment = 0.0;
1187 if (_input_values[_stress_input_index])
1189 precomputeROM(_cell_output_index);
1190 for (
unsigned int p = 0; p < _num_partitions; ++p)
1191 if (_partition_weights[p])
1192 for (
unsigned int t = 0; t < _num_tiles[p]; ++t)
1194 _cell_dislocation_increment +=
1195 _partition_weights[p] * _weights[p][t] * computeROM(t, p, _cell_output_index);
1196 precomputeROM(_wall_output_index);
1197 for (
unsigned int p = 0; p < _num_partitions; ++p)
1198 if (_partition_weights[p])
1199 for (
unsigned int t = 0; t < _num_tiles[p]; ++t)
1201 _wall_dislocation_increment +=
1202 _partition_weights[p] * _weights[p][t] * computeROM(t, p, _wall_output_index);
1205 _cell_rate[_qp] = _cell_dislocation_increment / _dt;
1206 _wall_rate[_qp] = _wall_dislocation_increment / _dt;
1207 _cell_dislocations[_qp] = _old_input_values[_cell_output_index] + _cell_dislocation_increment;
1208 _wall_dislocations[_qp] = _old_input_values[_wall_output_index] + _wall_dislocation_increment;
1214 if (_apply_strain && (_cell_dislocations[_qp] < 0.0 || _wall_dislocations[_qp] < 0.0))
1215 mooseException(
"In ",
1217 ": Negative disclocation density calculated for cell (old : ",
1223 ") or wall (old : ",
1233 Moose::err <<
" Finalized ROM output\n";
1234 Moose::err <<
" effective creep strain increment: " 1235 << std::sqrt(2.0 / 3.0 *
1237 _plastic_strain_increment)))
1239 Moose::err <<
" total effective creep strain: " 1240 << std::sqrt(2.0 / 3.0 *
1242 this->_creep_strain[_qp])))
1258 template <
bool is_ad>
1265 if (cell_strain_inc && _old_input_values[_cell_output_index])
1266 limited_dt = std::min(limited_dt,
1267 _dt * _max_cell_increment * _old_input_values[_cell_output_index] /
1270 if (wall_strain_inc && _old_input_values[_wall_output_index])
1271 limited_dt = std::min(limited_dt,
1272 _dt * _max_wall_increment * _old_input_values[_wall_output_index] /
1278 template <
bool is_ad>
1283 const bool derivative)
1306 else if (x < 1.0 && x > -1.0)
1312 return 1.0 - plus / (plus + minus);
1317 return (plus * dminus_dx - dplus_dx * minus) / Utility::pow<2>(plus + minus) * 2.0 /
1321 mooseError(
"Internal error: Sigmoid, value: x is out of bounds. val=",
1329 template <
bool is_ad>
1332 const unsigned int total_it)
1336 *iter_output <<
"At element " << this->_current_elem->id() <<
" _qp=" << _qp <<
" Coordinates " 1337 << _q_point[_qp] <<
" block=" << this->_current_elem->subdomain_id() <<
'\n';
1338 *iter_output <<
" dt " << _dt <<
" old cell disl: " << _old_input_values[_cell_output_index]
1339 <<
" old wall disl: " << _old_input_values[_wall_output_index]
1340 <<
" old effective strain: " << _old_input_values[_strain_output_index] <<
"\n";
1344 <<
" trial stress into rom (MPa): " 1350 *iter_output <<
" partition 2 weight: " 1352 *iter_output <<
" weights by tile, partition 1: ";
1353 for (
unsigned int t = 0; t < _num_tiles[0]; ++t)
1355 *iter_output <<
"\n";
1356 *iter_output <<
" weights by tile, partition 2: ";
1357 for (
unsigned int t = 0; t < _num_tiles[1]; ++t)
1359 *iter_output <<
"\n";
1360 *iter_output <<
" nonstress weights by tile, partition 1: ";
1361 for (
unsigned int t = 0; t < _num_tiles[0]; ++t)
1364 *iter_output <<
"\n";
1365 *iter_output <<
" nonstress weights by tile, partition 2: ";
1366 for (
unsigned int t = 0; t < _num_tiles[1]; ++t)
1369 *iter_output <<
"\n";
1375 template <
bool is_ad>
1378 std::stringstream * iter_output,
1381 const Real reference_residual)
1384 iter_output, effective_trial_stress, scalar, reference_residual);
1386 *iter_output <<
" derivative: " 1391 template <
bool is_ad>
1395 if (!this->isParamValid(
"model"))
1396 this->paramError(
"model",
"Specify a JSON data filename.");
1398 const auto model_file_name = this->
template getParam<DataFileName>(
"model");
1400 this->paramError(
"model",
"The specified JSON data file '", model_file_name,
"' is empty.");
1401 if (!_json.contains(key))
1403 "model",
"The key '", key,
"' is missing from the JSON data file '", model_file_name,
"'.");
nlohmann::json _json
JSON object constructed from the datafile.
Moose::GenericType< Real, is_ad > GenericReal
void outputIterationSummary(std::stringstream *iter_output, const unsigned int total_it) override
Output summary information for the convergence history of the model.
GenericReal< is_ad > computePolynomial(const GenericReal< is_ad > &value, const unsigned int degree, const bool derivative=false)
Calculate the value or derivative of Legendre polynomial up to 3rd order.
virtual void outputIterationStep(std::stringstream *iter_output, const GenericReal< is_ad > &effective_trial_stress, const GenericReal< is_ad > &scalar, const Real reference_residual)
Output information for a single iteration step to build the convergence history of the model...
const unsigned int _old_strain_input_index
Index corresponding to the position for the old strain in the input vector.
void buildPolynomials(const unsigned int p, const GenericReal< is_ad > &rom_input, std::vector< GenericReal< is_ad >> &polynomial_inputs, const GenericReal< is_ad > &drom_input=0, const bool derivative=false)
Assemble the array of Legendre polynomials to be multiplied by the ROM coefficients.
LAROMANCEStressUpdateBaseTempl(const InputParameters ¶meters)
GenericReal< is_ad > normalizeInput(const GenericReal< is_ad > &input, const ROMInputTransform transform, const Real transform_coef, const std::vector< Real > &transformed_limits, const bool derivative=false)
Convert the input variables into the form expected by the ROM Legendre polynomials to have a normaliz...
virtual GenericReal< is_ad > maximumPermissibleValue(const GenericReal< is_ad > &effective_trial_stress) const override
Compute the maximum permissible value of the scalar.
const GenericMaterialProperty< Real, is_ad > * _environmental
Optionally coupled environmental factor.
void mooseError(Args &&... args)
virtual void initQpStatefulProperties() override
void mooseWarning(Args &&... args)
bool checkInTile(const unsigned int p, const unsigned int t) const
Checks if the input combination is in a specific tile.
virtual void computeStressInitialize(const GenericReal< is_ad > &effective_trial_stress, const GenericRankFourTensor< is_ad > &elasticity_tensor)
Perform any necessary initialization before return mapping iterations.
void seed(std::size_t i, unsigned int seed)
std::vector< unsigned int > getMakeFrameHelper(const unsigned int p) const
GenericReal< is_ad > sigmoid(const Real lower, const Real upper, const GenericReal< is_ad > &val, const bool derivative=false)
Calculate the sigmoid function weighting for the input based on the limits.
RadialReturnStressUpdate computes the radial return stress increment for an isotropic elastic-viscopl...
virtual void outputIterationStep(std::stringstream *iter_output, const GenericReal< is_ad > &effective_trial_stress, const GenericReal< is_ad > &scalar, const Real reference_residual) override
Output information for a single iteration step to build the convergence history of the model...
registerMooseObjectAliased("SolidMechanicsApp", LAROMANCEStressUpdateBase, "LAROMANCEStressUpdate")
virtual bool substeppingCapabilityEnabled() override
Does the model include the infrastructure for substep decomposition of the elastic strain initially u...
Moose::GenericType< RankFourTensor, is_ad > GenericRankFourTensor
const unsigned int _wall_input_index
Index corresponding to the position for the dislocations within the cell wall in the input vector...
Real randNormal(std::size_t i, Real mean, Real sigma)
const unsigned int _stress_input_index
Index corresponding to the position for the stress in the input vector.
void precomputeROM(const unsigned out_index)
Precompute the ROM strain rate information for all inputs except for strain.
bool isParamValid(const std::string &name) const
std::vector< std::pair< WindowFailure, WindowFailure > > _window_failure
Real elasticity_tensor(unsigned int i, unsigned int j, unsigned int k, unsigned int l)
void checkJSONKey(const std::string &key)
check if a JSON file was loaded and if the specified key exists
virtual void initialSetup() override
std::vector< std::vector< std::vector< std::vector< Real > > > > getTransformedLimits(const unsigned int p, const std::vector< std::vector< std::vector< Real >>> limits)
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
const std::vector< double > x
const unsigned int _temperature_input_index
Index corresponding to the position for the tempeature in the input vector.
GenericReal< is_ad > computeValues(const unsigned int p, const std::vector< GenericReal< is_ad >> &precomputed, const std::vector< std::vector< GenericReal< is_ad >>> &polynomial_inputs, const std::vector< GenericReal< is_ad >> &dpolynomial_inputs={}, const bool derivative=false)
Arranges the calculated Legendre polynomials into the proper oder and multiplies the Legendre polynom...
virtual void outputIterationSummary(std::stringstream *iter_output, const unsigned int total_it)
Output summary information for the convergence history of the model.
std::vector< std::string > _index_name
index names for error output
const unsigned int _environmental_input_index
Index corresponding to the position for the environmental factor in the input vector.
virtual Real computeTimeStepLimit() override
Compute the limiting value of the time step for this material.
virtual GenericReal< is_ad > computeResidual(const GenericReal< is_ad > &effective_trial_stress, const GenericReal< is_ad > &scalar) override
Compute the residual for a predicted value of the scalar.
virtual void setupUnitConversionFactors(const InputParameters ¶meters)
virtual Real computeTimeStepLimit() override
Compute the limiting value of the time step for this material.
virtual GenericReal< is_ad > convertOutput(const unsigned int p, const std::vector< Real > &old_input_values, const GenericReal< is_ad > &rom_output, const unsigned out_index, const GenericReal< is_ad > &drom_output=0.0, const bool derivative=false)
Computes the output variable increments from the ROM predictions by bringing out of the normalized ma...
GenericReal< is_ad > computeROM(const unsigned int tile, const unsigned int partition, const unsigned out_index, const bool derivative=false)
Computes the ROM calculated increment for a given output and tile.
This class provides baseline functionallity for creep models based on the stress update material in a...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
static const std::string v
virtual void computeStressInitialize(const GenericReal< is_ad > &effective_trial_stress, const GenericRankFourTensor< is_ad > &elasticity_tensor) override
Perform any necessary initialization before return mapping iterations.
Real convert(Real from_value, const MooseUnits &from_unit) const
const InputParameters & parameters() const
virtual void resetIncrementalMaterialProperties() override
Reset material properties.
virtual void computeStressFinalize(const GenericRankTwoTensor< is_ad > &plastic_strain_increment) override
Perform any necessary steps to finalize state after return mapping iterations.
const unsigned int _cell_input_index
Index corresponding to the position for the dislocations with in the cell in the input vector...
void computeTileWeight(std::vector< std::vector< GenericReal< is_ad >>> &weights, GenericReal< is_ad > &input, const unsigned int in_index, const bool derivative=false)
Compute the contribution (weight) of each tile in each partition, based on the input and tile boundar...
MooseUnits pow(const MooseUnits &, int)
virtual void storeIncrementalMaterialProperties(const unsigned int total_number_substeps) override
Properly set up the incremental calculation storage of the stateful material properties in the inheri...
bool _check_range
Whether to check to see whether iterative solution is within admissible range, and set within that ra...
static const std::string k
static InputParameters validParams()
static InputParameters validParams()
bool areTilesNotIdentical(const unsigned int p, const unsigned int t, const unsigned int tt, const unsigned int in_index)
Checks if two tile domains are equal.
virtual void exportJSON()
void precomputeValues(const unsigned int p, const std::vector< Real > &coefs, const std::vector< std::vector< GenericReal< is_ad >>> &polynomial_inputs, std::vector< GenericReal< is_ad >> &precomputed)
Arranges the calculated Legendre polynomials into the proper oder and multiplies the Legendre polynom...
virtual void initQpStatefulProperties() override
Moose::GenericType< RankTwoTensor, is_ad > GenericRankTwoTensor
virtual void computeStressFinalize(const GenericRankTwoTensor< is_ad > &plastic_strain_increment) override
Perform any necessary steps to finalize state after return mapping iterations.