15 #include <initializer_list> 16 #include <torch/torch.h> 18 #include "neml2/tensors/functions/sign.h" 19 #include "neml2/tensors/functions/abs.h" 20 #include "neml2/tensors/functions/pow.h" 21 #include "neml2/tensors/functions/log10.h" 22 #include "neml2/tensors/functions/clamp.h" 23 #include "neml2/tensors/functions/stack.h" 32 auto options = Model::expected_options();
34 "Multilinear interpolation over six dimensions (von_mises_stress, temperature, " 35 "equivalent_plastic_strain, cell_dislocation_density, wall_dislocation_density, env_factor)";
37 options.set<VariableName>(
"equivalent_plastic_strain");
38 options.set<VariableName>(
"von_mises_stress");
40 options.set<VariableName>(
"cell_dislocation_density");
41 options.set<VariableName>(
"wall_dislocation_density");
43 options.set<VariableName>(
"temperature");
44 options.set<VariableName>(
"env_factor");
46 options.set_output(
"output_rate");
48 options.set<std::string>(
"model_file_name");
49 options.set<std::string>(
"model_file_variable_name");
51 options.set<
bool>(
"jit") =
false;
52 options.set(
"jit").suppressed() =
true;
58 _vm_stress(declare_input_variable<Scalar>(
"von_mises_stress")),
59 _temperature(declare_input_variable<Scalar>(
"temperature")),
60 _ep_strain(declare_input_variable<Scalar>(
"equivalent_plastic_strain")),
61 _cell_dd(declare_input_variable<Scalar>(
"cell_dislocation_density")),
62 _wall_dd(declare_input_variable<Scalar>(
"wall_dislocation_density")),
63 _env_fac(declare_input_variable<Scalar>(
"env_factor")),
64 _output_rate(declare_output_variable<Scalar>(
"output_rate"))
66 std::string filename = options.get<std::string>(
"model_file_name");
67 std::ifstream model_file(filename.c_str());
119 throw NEMLException(
"This ouput variable is not implemented, model_file_variable_name: " +
130 std::vector<const VariableBase *> inputs = {&
_vm_stress};
145 if (
name ==
"COMPRESS")
147 else if (
name ==
"DECOMPRESS")
149 else if (
name ==
"LOG10BOUNDED")
151 else if (
name ==
"EXP10BOUNDED")
153 else if (
name ==
"MINMAX")
156 throw NEMLException(
"Unrecognized transform: " + std::string(
name));
159 std::pair<Scalar, Scalar>
161 const Scalar & interp_points)
const 165 auto left_idx = Scalar(torch::searchsorted(grid, interp_points) - 1);
168 left_idx = Scalar(torch::clamp(left_idx, 0, grid.sizes()[0] - 2));
170 auto left_coord = grid.batch_index({left_idx});
172 grid.batch_index({left_idx + torch::tensor(1, default_integer_tensor_options())});
173 auto left_fraction = (right_coord - interp_points) / (right_coord - left_coord);
175 return {left_idx, neml2::batch_stack({left_fraction, 1 - left_fraction}, -1)};
180 const std::vector<std::pair<Scalar, Scalar>> index_and_fraction,
const Scalar grid_values)
const 183 for (
const auto i : {0, 1})
184 for (
const auto j : {0, 1})
185 for (
const auto k : {0, 1})
186 for (
const auto l : {0, 1})
187 for (
const auto m : {0, 1})
188 for (
const auto n : {0, 1})
191 grid_values.index({(index_and_fraction[0].first +
192 torch::tensor(i, default_integer_tensor_options())),
193 (index_and_fraction[1].first +
194 torch::tensor(
j, default_integer_tensor_options())),
195 (index_and_fraction[2].first +
196 torch::tensor(
k, default_integer_tensor_options())),
197 (index_and_fraction[3].first +
198 torch::tensor(l, default_integer_tensor_options())),
199 (index_and_fraction[4].first +
200 torch::tensor(m, default_integer_tensor_options())),
201 (index_and_fraction[5].first +
202 torch::tensor(n, default_integer_tensor_options()))});
203 auto weight = index_and_fraction[0].second.select(-1, i) *
204 index_and_fraction[1].second.select(-1,
j) *
205 index_and_fraction[2].second.select(-1,
k) *
206 index_and_fraction[3].second.select(-1, l) *
207 index_and_fraction[4].second.select(-1, m) *
208 index_and_fraction[5].second.select(-1, n);
209 result += vertex_value *
weight;
219 const auto cell_dd_transformed =
221 const auto wall_dd_transformed =
223 const auto vm_stress_transformed =
225 const auto ep_strain_transformed =
227 const auto temperature_transformed =
229 const auto env_fac_transformed =
232 std::vector<std::pair<Scalar, Scalar>> left_index_weight;
235 left_index_weight.push_back(
241 Scalar transformed_result =
243 return transformed_result;
248 const std::vector<double> & param,
251 switch (transform_type)
275 const std::vector<double> & param)
const 277 double factor = param[0];
278 double compressor = param[1];
279 double original_min = param[2];
280 auto d1 = neml2::sign(data) *
neml2::pow(neml2::abs(data * factor), compressor);
281 auto transformed_data = neml2::log10(1.0 + d1 - original_min);
282 return transformed_data;
287 const std::vector<double> & param)
const 289 double factor = param[0];
290 double compressor = param[1];
291 double original_min = param[2];
292 auto d1 =
neml2::pow(10.0, data) - 1.0 + original_min;
293 auto transformed_data = neml2::sign(d1) *
neml2::pow(neml2::abs(d1), 1.0 / compressor) / factor;
294 return transformed_data;
299 const std::vector<double> & param)
const 302 double factor = param[0];
303 double lowerbound = param[1];
304 double upperbound = param[2];
305 double logmin = param[3];
306 double logmax = param[4];
307 double range = upperbound - lowerbound;
308 auto transformed_data =
309 range * (neml2::log10(data + factor) - logmin) / (logmax - logmin) + lowerbound;
310 return transformed_data;
315 const std::vector<double> & param)
const 317 double factor = param[0];
318 double lowerbound = param[1];
319 double upperbound = param[2];
320 double logmin = param[3];
321 double logmax = param[4];
322 double range = upperbound - lowerbound;
323 auto transformed_data =
324 (
neml2::pow(10.0, ((data - lowerbound) * (logmax - logmin) / range) + logmin) - factor);
325 return transformed_data;
330 const std::vector<double> & param)
const 332 double data_min = param[0];
333 double data_max = param[1];
334 double scaled_min = param[2];
335 double scaled_max = param[3];
336 auto transformed_data =
337 ((data - data_min) / (data_max - data_min)) * (scaled_max - scaled_min) + scaled_min;
338 return transformed_data;
344 if (!
_json.contains(key))
345 throw NEMLException(
"The key '" + std::string(key) +
"' is missing from the JSON data file.");
347 std::string
name =
_json[key].get<std::string>();
354 if (!
_json.contains(key))
355 throw NEMLException(
"The key '" + std::string(key) +
"' is missing from the JSON data file.");
357 std::vector<double> data_vec =
_json[key].get<std::vector<double>>();
364 if (!
_json.contains(key))
365 throw NEMLException(
"The key '" + std::string(key) +
"' is missing from the JSON data file.");
367 std::vector<double> in_data =
_json[key].get<std::vector<double>>();
368 return Scalar::create(in_data).clone();
375 if (!
_json.contains(key))
376 throw NEMLException(
"The key '" + std::string(key) +
"' is missing from the JSON data file.");
378 vector<vector<vector<vector<vector<vector<double>>>>>> out_data =
379 _json[key].get<vector<vector<vector<vector<vector<vector<double>>>>>>>();
381 const int64_t sz_l0 = out_data.size();
382 const int64_t sz_l1 = out_data[0].size();
383 const int64_t sz_l2 = out_data[0][0].size();
384 const int64_t sz_l3 = out_data[0][0][0].size();
385 const int64_t sz_l4 = out_data[0][0][0][0].size();
386 const int64_t sz_l5 = out_data[0][0][0][0][0].size();
388 auto check_level_size =
389 [](
const int64_t current_vec_size,
const int64_t sz_level,
const std::string & key)
391 if (current_vec_size != sz_level)
392 throw NEMLException(
"Incorrect JSON interpolation grid size for '" + key +
"'.");
395 std::vector<double> linearize_values;
396 check_level_size(out_data.size(), sz_l0, key);
397 for (
auto && level1 : out_data)
399 check_level_size(level1.size(), sz_l1, key);
400 for (
auto && level2 : level1)
402 check_level_size(level2.size(), sz_l2, key);
403 for (
auto && level3 : level2)
405 check_level_size(level3.size(), sz_l3, key);
406 for (
auto && level4 : level3)
408 check_level_size(level4.size(), sz_l4, key);
409 for (
auto && level5 : level4)
411 check_level_size(level5.size(), sz_l5, key);
412 for (
auto &&
value : level5)
413 linearize_values.push_back(
value);
420 return Scalar::create(linearize_values)
421 .batch_reshape({sz_l0, sz_l1, sz_l2, sz_l3, sz_l4, sz_l5})
std::vector< double > _wall_transform_values
Scalar transform_data(const Scalar &data, const std::vector< double > ¶m, TransformEnum transform_type) const
transform data
TransformEnum _output_transform_enum
output transform enum
TransformEnum _temperature_transform_enum
const Variable< Scalar > & _temperature
Temperature.
std::string json_to_string(const std::string &key) const
read in json axes transform name
TransformEnum _cell_transform_enum
static OptionSet expected_options()
TransformEnum get_transform_enum(const std::string &name) const
const Variable< Scalar > & _wall_dd
wall dislocation density
TransformEnum _wall_transform_enum
std::vector< double > _cell_transform_values
const Variable< Scalar > & _cell_dd
cell dislocation density
TransformEnum _plastic_strain_transform_enum
std::vector< double > _plastic_strain_transform_values
register_NEML2_object(LibtorchModel)
const Variable< Scalar > & _env_fac
environmental factor
std::string _output_rate_name
output transform rate name
Scalar transform_exp10_bounded(const Scalar &data, const std::vector< double > ¶ms) const
std::vector< double > _stress_transform_values
input transform values
TransformEnum _env_transform_enum
std::pair< Scalar, Scalar > findLeftIndexAndFraction(const Scalar &grid, const Scalar &interp_points) const
find index of input point
TransformEnum _stress_transform_enum
input transform enums
Real value(unsigned n, unsigned alpha, unsigned beta, Real x)
Scalar compute_interpolation(const std::vector< std::pair< Scalar, Scalar >> index_and_fraction, const Scalar grid_values) const
compute interpolated value
Scalar json_6Dvector_to_torch(const std::string &key) const
read 6D grid date from json and store in Torch tensor
Scalar _grid_values
grid values being interpolated
const Variable< Scalar > & _vm_stress
Model input for interpolation.
void set_value(bool, bool, bool) override
Scalar _stress_grid
grid for interpolation
Scalar transform_decompress(const Scalar &data, const std::vector< double > ¶ms) const
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
Scalar transform_min_max(const Scalar &data, const std::vector< double > ¶ms) const
LAROMANCE6DInterpolation(const OptionSet &options)
std::vector< double > _env_transform_values
Scalar json_vector_to_torch(const std::string &key) const
read 1D vector of grid points from json and store in Torch tensor
nlohmann::json _json
JSON object containing interpolation grid and values.
Scalar transform_compress(const Scalar &data, const std::vector< double > ¶ms) const
LAROMANCE transforms for input axes and output axis.
std::vector< double > _output_transform_values
output transform values
std::vector< double > json_to_vector(const std::string &key) const
read in json axes transform constants
Scalar interpolate_and_transform() const
compute interpolated value and transform results
static const std::complex< double > j(0, 1)
Complex number "j" (also known as "i")
Scalar transform_log10_bounded(const Scalar &data, const std::vector< double > ¶ms) const
Variable< Scalar > & _output_rate
Model output.
std::vector< double > _temperature_transform_values
const Variable< Scalar > & _ep_strain
The creep strain.
static const std::string k
void request_AD() override
Scalar _plastic_strain_grid