https://mooseframework.inl.gov
MaternHalfIntCovariance.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 #ifdef MOOSE_LIBTORCH_ENABLED
10 
12 #include "LibtorchUtils.h"
13 #include <cmath>
14 
15 registerMooseObject("StochasticToolsApp", MaternHalfIntCovariance);
16 
19 {
21  params.addClassDescription("Matern half-integer covariance function.");
22  params.addRequiredParam<std::vector<Real>>("length_factor",
23  "Length factors to use for Covariance Kernel");
24  params.addRequiredParam<Real>("signal_variance",
25  "Signal Variance ($\\sigma_f^2$) to use for kernel calculation.");
26  params.addParam<Real>(
27  "noise_variance", 0.0, "Noise Variance ($\\sigma_n^2$) to use for kernel calculation.");
28  params.addRequiredParam<unsigned int>(
29  "p", "Integer p to use for Matern Half Integer Covariance Kernel");
30  return params;
31 }
32 
34  : CovarianceFunctionBase(parameters),
35  _length_factor(addVectorRealHyperParameter(
36  "length_factor", getParam<std::vector<Real>>("length_factor"), true)),
37  _sigma_f_squared(
38  addRealHyperParameter("signal_variance", getParam<Real>("signal_variance"), true)),
39  _sigma_n_squared(
40  addRealHyperParameter("noise_variance", getParam<Real>("noise_variance"), true)),
41  _p(addRealHyperParameter("p", getParam<unsigned int>("p"), false))
42 {
43 }
44 
45 void
47  const torch::Tensor & x,
48  const torch::Tensor & xp,
49  const bool is_self_covariance) const
50 {
51  if ((unsigned)x.sizes()[1] != _length_factor.numel())
52  mooseError("length_factor size does not match dimension of trainer input.");
53 
55  K, x, xp, _length_factor, _sigma_f_squared, _sigma_n_squared, _p, is_self_covariance);
56 }
57 
58 void
60  const torch::Tensor & x,
61  const torch::Tensor & xp,
62  const torch::Tensor & length_factor,
63  const torch::Tensor & sigma_f_squared,
64  const torch::Tensor & sigma_n_squared,
65  const torch::Tensor & p,
66  const bool is_self_covariance)
67 {
68  const auto p_value = cast_int<unsigned int>(LibtorchUtils::toCPUContiguous(p).item<Real>());
69  mooseAssert(x.sizes()[1] == xp.sizes()[1],
70  "Number of parameters do not match in covariance kernel calculation");
71 
72  const auto l_factor = length_factor.unsqueeze(0);
73  K = torch::cdist(torch::div(x, l_factor), torch::div(xp, l_factor), 2.0);
74  const Real factor = std::sqrt(2 * p_value + 1);
75  const Real normalization = std::tgamma(p_value + 1) / std::tgamma(2 * p_value + 1);
76 
77  auto summation = torch::zeros_like(K);
78  for (const auto tt : make_range(p_value + 1))
79  {
80  const Real coefficient =
81  std::tgamma(p_value + tt + 1) / (std::tgamma(tt + 1) * std::tgamma(p_value - tt + 1));
82  summation = summation + coefficient * torch::pow(2.0 * factor * K, Real(p_value - tt));
83  }
84 
85  K = sigma_f_squared * torch::exp(-factor * K) * normalization * summation;
86  if (is_self_covariance)
87  K.diagonal().add_(sigma_n_squared);
88 }
89 
90 bool
92  const torch::Tensor & x,
93  const std::string & hyper_param_name,
94  unsigned int ind) const
95 {
96  if (name().length() + 1 > hyper_param_name.length())
97  return false;
98 
99  const std::string name_without_prefix = hyper_param_name.substr(name().length() + 1);
100 
101  if (name_without_prefix == "noise_variance")
102  {
103  const auto options = x.options().dtype(at::kDouble);
104  maternHalfIntFunction(dKdhp,
105  x,
106  x,
108  torch::tensor(0.0, options),
109  torch::tensor(1.0, options),
110  _p,
111  true);
112  return true;
113  }
114 
115  if (name_without_prefix == "signal_variance")
116  {
117  const auto options = x.options().dtype(at::kDouble);
118  maternHalfIntFunction(dKdhp,
119  x,
120  x,
122  torch::tensor(1.0, options),
123  torch::tensor(0.0, options),
124  _p,
125  false);
126  return true;
127  }
128 
129  if (name_without_prefix == "length_factor")
130  {
132  return true;
133  }
134 
135  return false;
136 }
137 
138 void
140  const torch::Tensor & x,
141  const torch::Tensor & length_factor,
142  const torch::Tensor & sigma_f_squared,
143  const torch::Tensor & p,
144  const int ind)
145 {
146  const auto p_value = cast_int<unsigned int>(LibtorchUtils::toCPUContiguous(p).item<Real>());
147 
148  mooseAssert(ind < x.sizes()[1], "Incorrect length factor index");
149 
150  const auto l_factor = length_factor.unsqueeze(0);
151  const auto scaled_distance = torch::cdist(torch::div(x, l_factor), torch::div(x, l_factor), 2.0);
152  const auto nonzero_distance = scaled_distance > 0;
153  const auto safe_scaled_distance =
154  torch::where(nonzero_distance, scaled_distance, torch::ones_like(scaled_distance));
155  const Real factor = std::sqrt(2 * p_value + 1);
156  const Real normalization = std::tgamma(p_value + 1) / std::tgamma(2 * p_value + 1);
157 
158  auto summation = torch::zeros_like(safe_scaled_distance);
159  for (const auto tt : make_range(p_value + 1))
160  {
161  const Real coefficient =
162  std::tgamma(p_value + tt + 1) / (std::tgamma(tt + 1) * std::tgamma(p_value - tt + 1));
163  summation = summation +
164  coefficient * torch::pow(2.0 * factor * safe_scaled_distance, Real(p_value - tt));
165  }
166 
167  auto summation_derivative = torch::zeros_like(safe_scaled_distance);
168  for (const auto tt : make_range(p_value))
169  {
170  const Real coefficient =
171  std::tgamma(p_value + tt + 1) / (std::tgamma(tt + 1) * std::tgamma(p_value - tt + 1));
172  summation_derivative =
173  summation_derivative +
174  coefficient * 2.0 * factor * (p_value - tt) *
175  torch::pow(2.0 * factor * safe_scaled_distance, Real(p_value - tt - 1));
176  }
177 
178  const auto coordinate = x.select(1, ind);
179  const auto coordinate_distance_squared =
180  torch::pow(coordinate.unsqueeze(1) - coordinate.unsqueeze(0), 2);
181  const auto length_factor_ind = length_factor.select(0, ind);
182  const auto dr_dlength_factor =
183  -coordinate_distance_squared / (torch::pow(length_factor_ind, 3) * safe_scaled_distance);
184  const auto dK_dlength_factor = sigma_f_squared * normalization *
185  torch::exp(-factor * safe_scaled_distance) *
186  (summation_derivative - factor * summation) * dr_dlength_factor;
187 
188  K = torch::where(nonzero_distance, dK_dlength_factor, torch::zeros_like(dK_dlength_factor));
189 }
190 
191 #endif
const torch::Tensor & _sigma_f_squared
signal variance (^2)
void addParam(const std::string &name, const std::initializer_list< typename T::value_type > &value, const std::string &doc_string)
static const std::string K
Definition: NS.h:174
torch::Tensor toCPUContiguous(const torch::Tensor &tensor)
Base class for covariance functions that are used in Gaussian Processes.
static InputParameters validParams()
void addRequiredParam(const std::string &name, const std::string &doc_string)
registerMooseObject("StochasticToolsApp", MaternHalfIntCovariance)
const std::string & name() const
const std::vector< double > x
static InputParameters validParams()
const torch::Tensor & _length_factor
lengh factor () for the kernel, in vector form for multiple parameters
const torch::Tensor & _p
non-negative p factor for use in Matern half-int. = p+(1/2) in terms of general Matern ...
static void maternHalfIntFunction(torch::Tensor &K, const torch::Tensor &x, const torch::Tensor &xp, const torch::Tensor &length_factor, const torch::Tensor &sigma_f_squared, const torch::Tensor &sigma_n_squared, const torch::Tensor &p, const bool is_self_covariance)
ExpressionBuilder::EBTerm pow(const ExpressionBuilder::EBTerm &left, T exponent)
static void computedKdlf(torch::Tensor &K, const torch::Tensor &x, const torch::Tensor &length_factor, const torch::Tensor &sigma_f_squared, const torch::Tensor &p, const int ind)
Computes dK/dlf for individual length factors.
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
const Real p
IntRange< T > make_range(T beg, T end)
void mooseError(Args &&... args) const
void addClassDescription(const std::string &doc_string)
const torch::Tensor & _sigma_n_squared
noise variance (^2)
MaternHalfIntCovariance(const InputParameters &parameters)
void ErrorVector unsigned int
bool computedKdhyper(torch::Tensor &dKdhp, const torch::Tensor &x, const std::string &hyper_param_name, unsigned int ind) const override
Redirect dK/dhp for hyperparameter "hp".
void computeCovarianceMatrix(torch::Tensor &K, const torch::Tensor &x, const torch::Tensor &xp, const bool is_self_covariance) const override
Generates the Covariance Matrix given two points in the parameter space.