https://mooseframework.inl.gov
Loading...
Searching...
No Matches
NEML2ToMOOSEMaterialProperty.C
Go to the documentation of this file.
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
11#include "NEML2ModelExecutor.h"
12
13#define registerNEML2ToMOOSEMaterialProperty(alias) \
14 registerMooseObject("MooseApp", NEML2ToMOOSE##alias##MaterialProperty)
15
22
23template <typename T>
26{
27 auto params = Material::validParams();
28 params.addClassDescription("Provide an output (or its derivative) from a NEML2 model as a MOOSE "
29 "material property of type " +
30 demangle(typeid(T).name()) + ".");
31
32 params.addRequiredParam<UserObjectName>("neml2_executor",
33 "User object managing the execution of the NEML2 model.");
34 params.addRequiredParam<MaterialPropertyName>(
35 "to_moose",
36 "MOOSE material property used to store the NEML2 output variable (or its derivative)");
37 params.addRequiredParam<std::string>("from_neml2", "NEML2 output variable to read from");
38 params.addParam<std::string>(
39 "neml2_input_derivative",
40
41 "If supplied return the derivative of the NEML2 output variable with respect to this");
42 params.addParam<std::string>(
43 "neml2_parameter_derivative",
44 "If supplied return the derivative of the NEML2 output variable with respect to this NEML2 "
45 "model parameter");
46 // provide an optional initialization of the moose property (because we don't really know if it is
47 // going to become stateful or not)
48 params.addParam<MaterialPropertyName>("moose_material_property_init",
49 "Optional material property as the initial condition");
50
51 return params;
52}
53
54template <typename T>
56 : Material(params)
57#ifdef NEML2_ENABLED
58 ,
59 _execute_neml2_model(getUserObject<NEML2ModelExecutor>("neml2_executor")),
60 _prop(declareProperty<T>(getParam<MaterialPropertyName>("to_moose"))),
61 _prop0(isParamValid("moose_material_property_init")
62 ? &getMaterialProperty<T>("moose_material_property_init")
63 : nullptr),
64 _value(isParamValid("neml2_input_derivative")
65 ? _execute_neml2_model.getOutputDerivative(
66 getParam<std::string>("from_neml2"),
67 getParam<std::string>("neml2_input_derivative"))
68 : (isParamValid("neml2_parameter_derivative")
69 ? _execute_neml2_model.getOutputParameterDerivative(
70 getParam<std::string>("from_neml2"),
71 getParam<std::string>("neml2_parameter_derivative"))
72 : _execute_neml2_model.getOutput(getParam<std::string>("from_neml2"))))
73#endif
74{
76}
77
78#ifdef NEML2_ENABLED
79template <typename T>
80void
82{
83 // See issue #28971: Using _prop0 to set initial condition for this possibly stateful property may
84 // not work. As a workaround, we set the initial condition here when _t_step == 0.
85 if (_t_step == 0 && _prop0)
86 {
87 _prop.set() = _prop0->get();
88 return;
89 }
90
91 if (!_execute_neml2_model.outputReady())
92 return;
93
94 // A derivative retriever's tensor is produced only on passes that compute the derivative (see
95 // NEML2ModelExecutor::solve). If it has not been computed (e.g. an input derivative on a step
96 // where no Jacobian was assembled), report the derivative as zero.
97 if (!_value.defined())
98 {
99 for (_qp = 0; _qp < _qrule->n_points(); ++_qp)
100 MathUtils::mooseSetToZero(_prop[_qp]);
101 return;
102 }
103
104 // look up start index for current element
105 const auto i = _execute_neml2_model.getBatchIndex(_current_elem->id());
106 // The NEML2 output/derivative tensor is (batch, *base_shape) when batched; a leading batch
107 // axis is present iff the tensor has more dims than the base shape of the MOOSE type T.
108 const auto base_ndim = static_cast<int64_t>(NEML2Utils::Layout<T>::shape.size());
109 const bool batched = _value.dim() > base_ndim;
110
111 // Fast path: the retrieved output lives on the host (the default output_device) as a contiguous
112 // double buffer (see NEML2ModelExecutor::extractOutputs), so copy each element's data with a
113 // plain memcpy off data_ptr() rather than allocating an at::Tensor view per quadrature point.
114 // Fall back to the generic tensor copy only when the output was kept on an accelerator.
115 if (_value.is_cpu())
116 {
117 const Real * data = _value.template data_ptr<Real>();
118 const auto base_size = NEML2Utils::Layout<T>::strides[0];
119 for (_qp = 0; _qp < _qrule->n_points(); ++_qp)
120 {
121 // The batch-index map can outrun a not-yet-recomputed output/derivative tensor when the set
122 // of elements handled by the model grows mid-run (e.g. a moving subdomain adds elements
123 // before the next model evaluation). The generic tensor copy below relies on
124 // at::Tensor::operator[]'s bounds check throwing here; MOOSE catches that as a recoverable
125 // failure and cuts the time step, after which the model re-evaluates on the enlarged batch.
126 // The raw memcpy would instead read past the buffer, so guard it: on an out-of-range index
127 // fall back to the throwing copy to preserve that cut-back signal.
128 if (batched && static_cast<int64_t>(i + _qp) >= _value.size(0))
129 NEML2Utils::copyTensorToMOOSEData(_value[static_cast<int64_t>(i + _qp)], _prop[_qp]);
130 else
131 NEML2Utils::copyBlobToMOOSEData<T>(
132 batched ? data + static_cast<std::ptrdiff_t>(i + _qp) * base_size : data, _prop[_qp]);
133 }
134 }
135 else
136 for (_qp = 0; _qp < _qrule->n_points(); ++_qp)
137 NEML2Utils::copyTensorToMOOSEData(batched ? _value[static_cast<int64_t>(i + _qp)] : _value,
138 _prop[_qp]);
139}
140#endif
141
142#define instantiateNEML2ToMOOSEMaterialProperty(T) template class NEML2ToMOOSEMaterialProperty<T>
143
registerNEML2ToMOOSEMaterialProperty(Real)
instantiateNEML2ToMOOSEMaterialProperty(Real)
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
Materials compute MaterialProperties.
Definition Material.h:36
static InputParameters validParams()
Definition Material.C:14
NEML2ModelExecutor executes a NEML2 model.
NEML2ToMOOSEMaterialProperty(const InputParameters &params)
void computeProperties() override
Performs the quadrature point loop, calling computeQpProperties.
RankFourTensorTempl is designed to handle any N-dimensional fourth order tensor, C.
SymmetricRankFourTensorTempl is designed to handle an N-dimensional fourth order tensor with minor sy...
void mooseSetToZero(T &v)
Helper function templates to set a variable to zero.
Definition MathUtils.h:433
void copyTensorToMOOSEData(const at::Tensor &src, T &dest)
Directly copy a contiguous chunk of memory of a at::Tensor to a MOOSE data of type T.
Definition NEML2Utils.h:166
void assertNEML2Enabled()
Assert that NEML2 is enabled.
Definition NEML2Utils.C:90
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real