https://mooseframework.inl.gov
Loading...
Searching...
No Matches
NEML2Utils.h
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
10#pragma once
11
12#include <string>
13#include <vector>
14#include <utility>
15#include <algorithm>
16#include <cstring>
17#include <map>
18
19#ifdef NEML2_ENABLED
20
21// NEML2 v3's C++ API exchanges plain at::Tensor (libtorch/ATen); the rich neml2::Tensor /
22// typed-tensor library is no longer shipped, so we work with ATen directly here.
23#include <ATen/ATen.h>
24#include <ATen/Parallel.h> // at::get_num_threads / at::set_num_threads
25#include "RankTwoTensor.h"
26#include "RankFourTensor.h"
29#include "MaterialProperty.h"
30
31#endif
32
33class MooseObject;
34class Action;
35class ConsoleStream;
36
37namespace NEML2Utils
38{
39#ifdef NEML2_ENABLED
40
41enum class MOOSEIOType
42{
43 // unbatched
44 TIME,
45 SCALAR,
46 // batched
50};
51
52std::string stringify(MOOSEIOType type);
53
57inline std::pair<std::string, int>
58parseLag(const std::string & name)
59{
60 const auto pos = name.rfind('~');
61 if (pos == std::string::npos)
62 return {name, 0};
63 const auto suffix = name.substr(pos + 1);
64 if (suffix.empty() || suffix.find_first_not_of("0123456789") != std::string::npos)
65 return {name, 0};
66 return {name.substr(0, pos), std::stoi(suffix)};
67}
68
70inline std::string
71lagName(const std::string & base, int lag)
72{
73 return lag == 0 ? base : base + "~" + std::to_string(lag);
74}
75
77inline bool
78contains(const std::vector<std::string> & v, const std::string & s)
79{
80 return std::find(v.begin(), v.end(), s) != v.end();
81}
82
83template <typename T>
84struct Layout
85{
86};
87template <>
88struct Layout<Real>
89{
90 static constexpr std::array<int64_t, 0> shape{};
91 static constexpr std::array<int64_t, 1> strides{1};
92};
93template <>
94struct Layout<RealVectorValue>
95{
96 static constexpr std::array<int64_t, 1> shape{3};
97 static constexpr std::array<int64_t, 2> strides{3, 1};
98};
99template <>
101{
102 static constexpr std::array<int64_t, 2> shape{3, 3};
103 static constexpr std::array<int64_t, 3> strides{9, 3, 1};
104};
105template <>
107{
108 static constexpr std::array<int64_t, 1> shape{6};
109 static constexpr std::array<int64_t, 2> strides{6, 1};
110};
111template <>
113{
114 static constexpr std::array<int64_t, 4> shape{3, 3, 3, 3};
115 static constexpr std::array<int64_t, 5> strides{81, 27, 9, 3, 1};
116};
117template <>
119{
120 static constexpr std::array<int64_t, 2> shape{6, 6};
121 static constexpr std::array<int64_t, 3> strides{36, 6, 1};
122};
123
137template <typename T>
138at::Tensor
139fromBlob(const std::vector<T> & data)
140{
141 // Full shape: leading batch dim followed by the base shape.
142 std::vector<int64_t> shape;
143 shape.reserve(1 + Layout<T>::shape.size());
144 shape.push_back(static_cast<int64_t>(data.size()));
145 shape.insert(shape.end(), Layout<T>::shape.begin(), Layout<T>::shape.end());
146 // The const_cast is fine because torch works with non-const ptr so that it can optionally handle
147 // deallocation. But we are not going to let torch do that.
148 return at::from_blob(const_cast<T *>(data.data()), shape, at::TensorOptions().dtype(at::kDouble));
149}
150
164template <typename T>
165void
166copyTensorToMOOSEData(const at::Tensor & src, T & dest)
167{
168 if (src.dtype() != at::kDouble)
170 "Cannot copy at::Tensor with dtype ", src.dtype(), " into ", demangle(typeid(T).name()));
171 if (src.numel() != Layout<T>::strides[0])
172 mooseError("Cannot copy at::Tensor with shape ",
173 src.sizes(),
174 " into ",
175 demangle(typeid(T).name()),
176 " with different number of elements.");
177 auto dest_tensor = at::from_blob(
178 reinterpret_cast<Real *>(&dest), Layout<T>::shape, at::TensorOptions().dtype(at::kDouble));
179 dest_tensor.copy_(src.reshape(Layout<T>::shape));
180}
181
193template <typename T>
194void
195copyBlobToMOOSEData(const Real * src, T & dest)
196{
197 std::memcpy(reinterpret_cast<Real *>(&dest), src, Layout<T>::strides[0] * sizeof(Real));
198}
199
215{
216public:
217 explicit ScopedNumThreads(int n) : _saved(at::get_num_threads()), _changed(n > 0 && n != _saved)
218 {
219 if (_changed)
220 at::set_num_threads(n);
221 }
223 {
224 if (_changed)
225 at::set_num_threads(_saved);
226 }
229
230private:
231 const int _saved;
232 const bool _changed;
233};
234
249{
250public:
251 ScopedDefaultDtype() : _saved(at::get_default_dtype())
252 {
253 at::set_default_dtype(caffe2::TypeMeta::Make<double>());
254 }
255 ~ScopedDefaultDtype() { at::set_default_dtype(_saved); }
258
259private:
260 const caffe2::TypeMeta _saved;
261};
262
263static std::string NEML2_help_message = R""""(
264==============================================================================
265To debug NEML2 related issues:
2661. Build and run MOOSE in dbg mode.
2672. Re-run the simulation using the dbg executable, and often times
268 NEML2 will provide a more helpful error message.
2693. If the error message is not helpful, or if there is still no error message,
270 run the simulation through a debugger: See
271 https://mooseframework.inl.gov/application_development/debugging.html
2724. If the issue is due to a NEML2 bug, feel free to report it at
273 https://github.com/applied-material-modeling/neml2/issues
274==============================================================================
275)"""";
276
287void redirectLogsToConsole(const ConsoleStream & console);
288
297void dumpInputsToTorchScript(const std::map<std::string, at::Tensor> & inputs,
298 const std::string & filename);
299
300#endif // NEML2_ENABLED
301
305std::string docstring(const std::string & desc);
306
310void assertNEML2Enabled();
311
312} // namespace NEML2Utils
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
Base class for actions.
Definition Action.h:38
A helper class for re-directing output streams to Console output objects form MooseObjects.
Every object that can be built by the factory should be derived from this class.
Definition MooseObject.h:31
RAII guard forcing libtorch's default scalar type to Float64 for its lifetime, restoring the previous...
Definition NEML2Utils.h:249
ScopedDefaultDtype(const ScopedDefaultDtype &)=delete
ScopedDefaultDtype & operator=(const ScopedDefaultDtype &)=delete
const caffe2::TypeMeta _saved
Definition NEML2Utils.h:260
RAII guard that pins libtorch's intra-op thread count for the current scope and restores the previous...
Definition NEML2Utils.h:215
ScopedNumThreads(const ScopedNumThreads &)=delete
ScopedNumThreads & operator=(const ScopedNumThreads &)=delete
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 dumpInputsToTorchScript(const std::map< std::string, at::Tensor > &inputs, const std::string &filename)
Serialize a set of named NEML2 input tensors to a TorchScript archive at filename (a torch::jit::Modu...
Definition NEML2Utils.C:25
std::pair< std::string, int > parseLag(const std::string &name)
Parse NEML2 v3 lag notation: "var~N" is the N-th old value of a variable (var~1 == old var,...
Definition NEML2Utils.h:58
at::Tensor fromBlob(const std::vector< T > &data)
Map from std::vector<T> to an at::Tensor without copying the data.
Definition NEML2Utils.h:139
std::string docstring(const std::string &desc)
Augment docstring if NEML2 is not enabled.
Definition NEML2Utils.C:80
void redirectLogsToConsole(const ConsoleStream &console)
Route NEML2's log output into MOOSE's console.
Definition NEML2Utils.C:45
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 copyBlobToMOOSEData(const Real *src, T &dest)
Copy one element's worth of doubles from a contiguous host buffer into a MOOSE datum of type T.
Definition NEML2Utils.h:195
std::string lagName(const std::string &base, int lag)
Inverse of parseLag: build the variable name for a base name + lag.
Definition NEML2Utils.h:71
void assertNEML2Enabled()
Assert that NEML2 is enabled.
Definition NEML2Utils.C:90
std::string stringify(MOOSEIOType type)
Definition NEML2Utils.C:56
static std::string NEML2_help_message
Definition NEML2Utils.h:263