10 #ifdef LIBTORCH_ENABLED 19 const std::string name,
20 const unsigned int num_inputs,
21 const unsigned int num_outputs,
22 const std::vector<unsigned int> & num_neurons_per_layer,
23 const std::vector<std::string> & activation_function,
24 const torch::DeviceType device_type,
27 _num_inputs(num_inputs),
28 _num_outputs(num_outputs),
29 _num_neurons_per_layer(num_neurons_per_layer),
30 _activation_function(
MultiMooseEnum(
"relu sigmoid elu gelu linear",
"relu")),
31 _device_type(device_type),
39 mooseError(
"The number of activation functions should be either one or the same as the number " 46 : torch::nn::Module(),
48 _num_inputs(nn.numInputs()),
49 _num_outputs(nn.numOutputs()),
50 _num_neurons_per_layer(nn.numNeuronsPerLayer()),
51 _activation_function(nn.activationFunctions()),
52 _device_type(nn.deviceType()),
53 _data_type(nn.dataType())
59 const auto & from_params = nn.named_parameters();
60 auto to_params = this->named_parameters();
61 for (
unsigned int param_i :
make_range(from_params.size()))
62 to_params[param_i].value().data() = from_params[param_i].value().data().clone();
72 std::unordered_map<std::string, unsigned int> parameters = {
74 addLayer(
"hidden_layer_" + std::to_string(i + 1), parameters);
81 std::unordered_map<std::string, unsigned int> parameters = {{
"inp_neurons", inp_neurons},
83 addLayer(
"output_layer_", parameters);
90 torch::Tensor output(x);
96 for (
unsigned int i = 0; i <
_weights.size() - 1; ++i)
98 std::string activation =
100 if (activation ==
"relu")
102 else if (activation ==
"sigmoid")
104 else if (activation ==
"elu")
106 else if (activation ==
"gelu")
108 else if (activation ==
"linear")
109 output =
_weights[i]->forward(output);
119 const std::string & layer_name,
120 const std::unordered_map<std::string, unsigned int> & parameters)
122 auto it = parameters.find(
"inp_neurons");
123 if (it == parameters.end())
124 ::
mooseError(
"Number of input neurons not found during the construction of " 125 "LibtorchArtificialNeuralNet!");
126 unsigned int inp_neurons = it->second;
128 it = parameters.find(
"out_neurons");
129 if (it == parameters.end())
130 ::
mooseError(
"Number of output neurons not found during the construction of " 131 "LibtorchArtificialNeuralNet!");
132 unsigned int out_neurons = it->second;
134 _weights.push_back(register_module(layer_name, torch::nn::Linear(inp_neurons, out_neurons)));
140 const auto & named_params = this->named_parameters();
141 for (
const auto & param_i :
make_range(named_params.size()))
144 json[named_params[param_i].key()] = std::vector<Real>(
145 named_params[param_i].value().data_ptr<
Real>(),
146 named_params[param_i].
value().data_ptr<
Real>() + named_params[param_i].
value().numel());
154 network->
store(json);
161 dataStore<Moose::LibtorchArtificialNeuralNet>(
162 std::ostream & stream, std::shared_ptr<Moose::LibtorchArtificialNeuralNet> & nn,
void * context)
164 std::string n(nn->name());
167 unsigned int ni(nn->numInputs());
170 unsigned int no(nn->numOutputs());
173 unsigned int nhl(nn->numHiddenLayers());
176 std::vector<unsigned int> nnpl(nn->numNeuronsPerLayer());
179 unsigned int afs(nn->activationFunctions().size());
182 std::vector<std::string> items(afs);
183 for (
unsigned int i = 0; i < afs; ++i)
184 items[i] = nn->activationFunctions()[i];
188 auto device_type =
static_cast<std::underlying_type<torch::DeviceType>::type
>(nn->deviceType());
191 auto data_type =
static_cast<std::underlying_type<torch::ScalarType>::type
>(nn->dataType());
194 torch::save(nn, nn->name());
199 dataLoad<Moose::LibtorchArtificialNeuralNet>(
200 std::istream & stream, std::shared_ptr<Moose::LibtorchArtificialNeuralNet> & nn,
void * context)
205 unsigned int num_inputs;
206 dataLoad(stream, num_inputs, context);
208 unsigned int num_outputs;
209 dataLoad(stream, num_outputs, context);
211 unsigned int num_hidden_layers;
212 dataLoad(stream, num_hidden_layers, context);
214 std::vector<unsigned int> num_neurons_per_layer;
215 num_neurons_per_layer.resize(num_hidden_layers);
216 dataLoad(stream, num_neurons_per_layer, context);
218 unsigned int num_activation_items;
219 dataLoad(stream, num_activation_items, context);
221 std::vector<std::string> activation_functions;
222 activation_functions.resize(num_activation_items);
223 dataLoad(stream, activation_functions, context);
225 std::underlying_type<torch::DeviceType>::type device_type;
226 dataLoad(stream, device_type, context);
227 const torch::DeviceType divt(static_cast<torch::DeviceType>(device_type));
229 std::underlying_type<torch::ScalarType>::type
data_type;
231 const torch::ScalarType datt(static_cast<torch::ScalarType>(
data_type));
233 nn = std::make_shared<Moose::LibtorchArtificialNeuralNet>(
234 name, num_inputs, num_outputs, num_neurons_per_layer, activation_functions, divt, datt);
236 torch::load(nn,
name);
241 dataStore<Moose::LibtorchArtificialNeuralNet const>(
250 dataLoad<Moose::LibtorchArtificialNeuralNet const>(
std::string name(const ElemQuality q)
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
unsigned int size() const
Return the number of active items in the MultiMooseEnum.
void dataLoad(std::istream &stream, PenetrationInfo *&pinfo, void *context)
MultiMooseEnum _activation_function
Activation functions (either one for all hidden layers or one for every layer separately) ...
const torch::DeviceType _device_type
The device type used for this neural network.
unsigned int numHiddenLayers() const
Return the number of hidden layers.
const std::vector< unsigned int > _num_neurons_per_layer
Hidden layer architecture.
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
std::vector< torch::nn::Linear > _weights
Submodules that hold linear operations and the corresponding weights and biases (y = W * x + b) ...
void constructNeuralNetwork()
Construct the neural network.
virtual void addLayer(const std::string &layer_name, const std::unordered_map< std::string, unsigned int > ¶meters)
Add layers to the neural network.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
IntRange< T > make_range(T beg, T end)
void store(nlohmann::json &json) const
Store the network architecture in a json file (for debugging, visualization)
void to_json(nlohmann::json &json, const Moose::LibtorchArtificialNeuralNet *const &network)
const unsigned int _num_outputs
Number of neurons on the output layer.
const torch::ScalarType _data_type
The data type used in this neural network.
MOOSE now contains C++17 code, so give a reasonable error message stating what the user can do to add...
This is a "smart" enum class intended to replace many of the shortcomings in the C++ enum type...
void dataStore(std::ostream &stream, PenetrationInfo *&pinfo, void *context)
LibtorchArtificialNeuralNet(const std::string name, const unsigned int num_inputs, const unsigned int num_outputs, const std::vector< unsigned int > &num_neurons_per_layer, const std::vector< std::string > &activation_function={"relu"}, const torch::DeviceType device_type=torch::kCPU, const torch::ScalarType scalar_type=torch::kDouble)
Construct using input parameters.
const unsigned int _num_inputs
virtual torch::Tensor forward(const torch::Tensor &x) override
Overriding the forward substitution function for the neural network, unfortunately this cannot be con...