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