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 : #pragma once
11 :
12 : #include <string>
13 :
14 : #ifdef NEML2_ENABLED
15 :
16 : #include "neml2/tensors/tensors.h"
17 : #include "neml2/base/Factory.h"
18 : #include "neml2/models/Model.h"
19 : #include "RankTwoTensor.h"
20 : #include "RankFourTensor.h"
21 : #include "SymmetricRankTwoTensor.h"
22 : #include "SymmetricRankFourTensor.h"
23 : #include "MaterialProperty.h"
24 :
25 : #endif
26 :
27 : class MooseObject;
28 : class Action;
29 : class SubProblem;
30 :
31 : namespace NEML2Utils
32 : {
33 : #ifdef NEML2_ENABLED
34 :
35 : enum class MOOSEIOType
36 : {
37 : // unbatched
38 : TIME,
39 : SCALAR,
40 : // batched
41 : FUNCTION,
42 : VARIABLE,
43 : MATERIAL
44 : };
45 :
46 : std::string stringify(MOOSEIOType type);
47 :
48 : /**
49 : * @brief Get the NEML2 Model
50 : *
51 : * This is mostly the same as the plain neml2::get_model() method, but it also guards the default
52 : * dtype and sends the model to the target device.
53 : * @return neml2::Model&
54 : */
55 : std::shared_ptr<neml2::Model>
56 : getModel(neml2::Factory & factory, const std::string & name, neml2::Dtype dtype = neml2::kFloat64);
57 :
58 : template <typename T>
59 : struct Layout
60 : {
61 : };
62 : template <>
63 : struct Layout<Real>
64 : {
65 : static constexpr std::array<neml2::Size, 0> shape{};
66 : static constexpr std::array<neml2::Size, 1> strides{1};
67 : };
68 : template <>
69 : struct Layout<RealVectorValue>
70 : {
71 : static constexpr std::array<neml2::Size, 1> shape{3};
72 : static constexpr std::array<neml2::Size, 2> strides{3, 1};
73 : };
74 : template <>
75 : struct Layout<RankTwoTensor>
76 : {
77 : static constexpr std::array<neml2::Size, 2> shape{3, 3};
78 : static constexpr std::array<neml2::Size, 3> strides{9, 3, 1};
79 : };
80 : template <>
81 : struct Layout<SymmetricRankTwoTensor>
82 : {
83 : static constexpr std::array<neml2::Size, 1> shape{6};
84 : static constexpr std::array<neml2::Size, 2> strides{6, 1};
85 : };
86 : template <>
87 : struct Layout<RankFourTensor>
88 : {
89 : static constexpr std::array<neml2::Size, 4> shape{3, 3, 3, 3};
90 : static constexpr std::array<neml2::Size, 5> strides{81, 27, 9, 3, 1};
91 : };
92 : template <>
93 : struct Layout<SymmetricRankFourTensor>
94 : {
95 : static constexpr std::array<neml2::Size, 2> shape{6, 6};
96 : static constexpr std::array<neml2::Size, 3> strides{36, 6, 1};
97 : };
98 :
99 : /**
100 : * @brief Map from std::vector<T> to neml2::Tensor without copying the data
101 : *
102 : * This method is used in gatherers which gather data from MOOSE as input variables to the NEML2
103 : * material model. So in theory, we only need to provide Layout specializations for MOOSE types that
104 : * can potentially be used as NEML2 input variables.
105 : *
106 : * For this method to work, the underlying data in \p data must be reinterpretable as Real
107 : * (neml2::kFloat64). The data class T must also be aligned and follow the striding implied by
108 : * Layout<T>::shape. The data class T must also have no padding or overhead.
109 : */
110 : template <typename T>
111 : neml2::Tensor
112 1825 : fromBlob(const std::vector<T> & data)
113 : {
114 : // The const_cast is fine because torch works with non-const ptr so that it can optionally handle
115 : // deallocation. But we are not going to let torch do that.
116 1825 : const auto torch_tensor = at::from_blob(const_cast<T *>(data.data()),
117 1825 : neml2::utils::add_shapes(data.size(), Layout<T>::shape),
118 1825 : at::TensorOptions().dtype(neml2::kFloat64));
119 3650 : return neml2::Tensor(torch_tensor, 1);
120 1825 : }
121 :
122 : /**
123 : * @brief Directly copy a contiguous chunk of memory of a at::Tensor to a MOOSE data of type T
124 : *
125 : * This assumes the at::Tensor and T have the same layout, for example both row-major
126 : * with T = RankTwoTensor. If the layouts are different, we may need to reshape/reorder/transpose
127 : * the at::Tensor before copying.
128 : *
129 : * For this method to work,
130 : * 1. the address of \p dest must align with the first element of the data,
131 : * 2. the number of elements in \p dest must match the number of elements in \p src,
132 : * 3. the \p src tensor must be of type neml2::kFloat64, and
133 : * 4. data in \p dest must be reinterpretable as Real.
134 : */
135 : template <typename T>
136 : void
137 180886 : copyTensorToMOOSEData(const at::Tensor & src, T & dest)
138 : {
139 180886 : if (src.dtype() != neml2::kFloat64)
140 0 : mooseError(
141 0 : "Cannot copy at::Tensor with dtype ", src.dtype(), " into ", demangle(typeid(T).name()));
142 180886 : if (src.numel() != Layout<T>::strides[0])
143 0 : mooseError("Cannot copy at::Tensor with shape ",
144 0 : src.sizes(),
145 : " into ",
146 : demangle(typeid(T).name()),
147 : " with different number of elements.");
148 180886 : auto dest_tensor = at::from_blob(reinterpret_cast<Real *>(&dest),
149 : Layout<T>::shape,
150 180886 : at::TensorOptions().dtype(neml2::kFloat64));
151 180886 : dest_tensor.copy_(src.reshape(Layout<T>::shape));
152 180886 : }
153 :
154 : static std::string NEML2_help_message = R""""(
155 : ==============================================================================
156 : To debug NEML2 related issues:
157 : 1. Build and run MOOSE in dbg mode.
158 : 2. Re-run the simulation using the dbg executable, and often times
159 : NEML2 will provide a more helpful error message.
160 : 3. If the error message is not helpful, or if there is still no error message,
161 : run the simulation through a debugger: See
162 : https://mooseframework.inl.gov/application_development/debugging.html
163 : 4. If the issue is due to a NEML2 bug, feel free to report it at
164 : https://github.com/applied-material-modeling/neml2/issues
165 : ==============================================================================
166 : )"""";
167 :
168 : #endif // NEML2_ENABLED
169 :
170 : /// Determine whether the NEML2 material model should be evaluated
171 : bool shouldCompute(const SubProblem &);
172 :
173 : /**
174 : * Augment docstring if NEML2 is not enabled
175 : */
176 : std::string docstring(const std::string & desc);
177 :
178 : /**
179 : * Assert that NEML2 is enabled. A MooseError is raised if NEML2 is not enabled.
180 : */
181 : void assertNEML2Enabled();
182 :
183 : } // namespace NEML2Utils
|