https://mooseframework.inl.gov
Loading...
Searching...
No Matches
LibtorchUtils.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
10#ifdef MOOSE_LIBTORCH_ENABLED
11
12#include "LibtorchUtils.h"
13
14#include <algorithm>
15#include <functional>
16#include <numeric>
17
18namespace LibtorchUtils
19{
20
21namespace
22{
23
24template <typename DataType>
25torch::TensorOptions
26tensorOptions()
27{
28 if constexpr (std::is_same<DataType, double>::value)
29 return torch::TensorOptions().dtype(at::kDouble);
30 else if constexpr (std::is_same<DataType, float>::value)
31 return torch::TensorOptions().dtype(at::kFloat);
32 else
33 static_assert(Moose::always_false<DataType>,
34 "Tensor conversion is not implemented for the given data type!");
35}
36
37template <typename DataType>
38void
39checkTensorShape(const std::vector<DataType> & vector, c10::IntArrayRef sizes)
40{
41 const auto expected_numel =
42 std::accumulate(sizes.begin(), sizes.end(), int64_t{1}, std::multiplies<int64_t>());
43
44 if (expected_numel != cast_int<int64_t>(vector.size()))
45 mooseError("The requested tensor shape is incompatible with the vector size.");
46}
47
48} // namespace
49
50template <typename DataType>
51torch::Tensor
52vectorToTensorCopy(const std::vector<DataType> & vector, c10::IntArrayRef sizes)
53{
54 checkTensorShape(vector, sizes);
55
56 const auto options = tensorOptions<DataType>();
57 auto tensor = torch::empty(sizes, options);
58
59 if (!vector.empty())
60 std::copy(vector.begin(), vector.end(), tensor.template data_ptr<DataType>());
61
62 return tensor;
63}
64
65// Explicitly instantiate for DataType=Real
66template torch::Tensor vectorToTensorCopy<Real>(const std::vector<Real> & vector,
67 c10::IntArrayRef sizes);
68
69template <typename DataType>
70void
71vectorToTensor(const std::vector<DataType> & vector, torch::Tensor & tensor, const bool detach)
72{
73 tensor = vectorToTensorCopy(vector, {long(vector.size()), 1});
74
75 if (detach)
76 tensor = tensor.detach();
77}
78
79// Explicitly instantiate for DataType=Real
80template void
81vectorToTensor<Real>(const std::vector<Real> & vector, torch::Tensor & tensor, const bool detach);
82
83template <typename DataType>
84torch::Tensor
85vectorToTensorView(std::vector<DataType> & vector, c10::IntArrayRef sizes)
86{
87 checkTensorShape(vector, sizes);
88
89 const auto options = tensorOptions<DataType>();
90 if (vector.empty())
91 return torch::empty(sizes, options);
92
93 return torch::from_blob(vector.data(), sizes, options);
94}
95
96// Explicitly instantiate for DataType=Real
97template torch::Tensor vectorToTensorView<Real>(std::vector<Real> & vector, c10::IntArrayRef sizes);
98
99void
100moveToLibtorchDevice(torch::Tensor & tensor, const torch::DeviceType device_type)
101{
102 tensor = tensor.to(device_type);
103}
104
105torch::Tensor
106toCPUContiguous(const torch::Tensor & tensor)
107{
108 // CPU accessors can handle strides, but data_ptr()-based reads require dense logical order.
109 return tensor.detach().to(tensor.options().device(at::kCPU)).contiguous();
110}
111
112template <typename DataType>
113void
114tensorToVector(torch::Tensor & tensor, std::vector<DataType> & vector)
115{
116 try
117 {
118 tensor.data_ptr<DataType>();
119 }
120 catch (const c10::Error & e)
121 {
123 "Cannot cast tensor values to", MooseUtils::prettyCppType<DataType>(), "!\n", e.msg());
124 }
125
126 const auto & sizes = tensor.sizes();
127
128 long int max_size = 0;
129 for (const auto & dim_size : sizes)
130 // We do this comparison because XCode complains if we use std::max
131 max_size = dim_size > max_size ? dim_size : max_size;
132
133 mooseAssert(max_size == tensor.numel(), "The given tensor should be one-dimensional!");
134 vector = {tensor.data_ptr<DataType>(), tensor.data_ptr<DataType>() + tensor.numel()};
135}
136
137// Explicitly instantiate for DataType=Real
138template void tensorToVector<Real>(torch::Tensor & tensor, std::vector<Real> & vector);
139
140} // LibtorchUtils namespace
141
142#endif
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
torch::Tensor toCPUContiguous(const torch::Tensor &tensor)
Return a detached contiguous CPU copy of a tensor.
void moveToLibtorchDevice(torch::Tensor &tensor, const torch::DeviceType device_type)
Move a tensor to the configured libtorch device.
template void vectorToTensor< Real >(const std::vector< Real > &vector, torch::Tensor &tensor, const bool detach)
template void tensorToVector< Real >(torch::Tensor &tensor, std::vector< Real > &vector)
void vectorToTensor(const std::vector< DataType > &vector, torch::Tensor &tensor, const bool detach=false)
Utility function that converts a standard vector to a torch::Tensor.
template torch::Tensor vectorToTensorCopy< Real >(const std::vector< Real > &vector, c10::IntArrayRef sizes)
template torch::Tensor vectorToTensorView< Real >(std::vector< Real > &vector, c10::IntArrayRef sizes)
torch::Tensor vectorToTensorCopy(const std::vector< DataType > &vector, c10::IntArrayRef sizes)
Utility function that creates an owning tensor copy of a standard vector.
void tensorToVector(torch::Tensor &tensor, std::vector< DataType > &vector)
Utility function that converts a torch::Tensor to a standard vector.
torch::Tensor vectorToTensorView(std::vector< DataType > &vector, c10::IntArrayRef sizes)
Utility function that creates a non-owning tensor view of a standard vector.