Line data Source code
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 : #include "ExponentialCovariance.h"
11 : #include <cmath>
12 :
13 : registerMooseObject("StochasticToolsApp", ExponentialCovariance);
14 :
15 : InputParameters
16 68 : ExponentialCovariance::validParams()
17 : {
18 68 : InputParameters params = CovarianceFunctionBase::validParams();
19 68 : params.addClassDescription("Exponential covariance function.");
20 136 : params.addRequiredParam<std::vector<Real>>("length_factor",
21 : "Length factors to use for Covariance Kernel");
22 136 : params.addRequiredParam<Real>("signal_variance",
23 : "Signal Variance ($\\sigma_f^2$) to use for kernel calculation.");
24 136 : params.addParam<Real>(
25 136 : "noise_variance", 0.0, "Noise Variance ($\\sigma_n^2$) to use for kernel calculation.");
26 136 : params.addRequiredParam<Real>("gamma", "Gamma to use for Exponential Covariance Kernel");
27 68 : return params;
28 0 : }
29 :
30 34 : ExponentialCovariance::ExponentialCovariance(const InputParameters & parameters)
31 : : CovarianceFunctionBase(parameters),
32 34 : _length_factor(addVectorRealHyperParameter(
33 : "length_factor", getParam<std::vector<Real>>("length_factor"), true)),
34 34 : _sigma_f_squared(
35 102 : addRealHyperParameter("signal_variance", getParam<Real>("signal_variance"), true)),
36 34 : _sigma_n_squared(
37 102 : addRealHyperParameter("noise_variance", getParam<Real>("noise_variance"), true)),
38 102 : _gamma(addRealHyperParameter("gamma", getParam<Real>("gamma"), false))
39 : {
40 34 : }
41 :
42 : void
43 22094 : ExponentialCovariance::computeCovarianceMatrix(RealEigenMatrix & K,
44 : const RealEigenMatrix & x,
45 : const RealEigenMatrix & xp,
46 : const bool is_self_covariance) const
47 : {
48 22094 : if ((unsigned)x.cols() != _length_factor.size())
49 0 : mooseError("length_factor size does not match dimension of trainer input.");
50 :
51 22094 : ExponentialFunction(
52 22094 : K, x, xp, _length_factor, _sigma_f_squared, _sigma_n_squared, _gamma, is_self_covariance);
53 22094 : }
54 :
55 : void
56 39094 : ExponentialCovariance::ExponentialFunction(RealEigenMatrix & K,
57 : const RealEigenMatrix & x,
58 : const RealEigenMatrix & xp,
59 : const std::vector<Real> & length_factor,
60 : const Real sigma_f_squared,
61 : const Real sigma_n_squared,
62 : const Real gamma,
63 : const bool is_self_covariance)
64 : {
65 39094 : unsigned int num_samples_x = x.rows();
66 39094 : unsigned int num_samples_xp = xp.rows();
67 39094 : unsigned int num_params_x = x.cols();
68 :
69 : mooseAssert(num_params_x == xp.cols(),
70 : "Number of parameters do not match in covariance kernel calculation");
71 :
72 760634 : for (unsigned int ii = 0; ii < num_samples_x; ++ii)
73 : {
74 14371070 : for (unsigned int jj = 0; jj < num_samples_xp; ++jj)
75 : {
76 : // Compute distance per parameter, scaled by length factor
77 : Real r_scaled = 0;
78 40948590 : for (unsigned int kk = 0; kk < num_params_x; ++kk)
79 27299060 : r_scaled += pow((x(ii, kk) - xp(jj, kk)) / length_factor[kk], 2);
80 13649530 : r_scaled = sqrt(r_scaled);
81 13649530 : K(ii, jj) = sigma_f_squared * std::exp(-pow(r_scaled, gamma));
82 : }
83 721540 : if (is_self_covariance)
84 343040 : K(ii, ii) += sigma_n_squared;
85 : }
86 39094 : }
87 :
88 : bool
89 51000 : ExponentialCovariance::computedKdhyper(RealEigenMatrix & dKdhp,
90 : const RealEigenMatrix & x,
91 : const std::string & hyper_param_name,
92 : unsigned int ind) const
93 : {
94 51000 : if (name().length() + 1 > hyper_param_name.length())
95 : return false;
96 :
97 51000 : const std::string name_without_prefix = hyper_param_name.substr(name().length() + 1);
98 :
99 51000 : if (name_without_prefix == "noise_variance")
100 : {
101 0 : ExponentialFunction(dKdhp, x, x, _length_factor, 0, 1, _gamma, true);
102 : return true;
103 : }
104 :
105 51000 : if (name_without_prefix == "signal_variance")
106 : {
107 17000 : ExponentialFunction(dKdhp, x, x, _length_factor, 1, 0, _gamma, false);
108 : return true;
109 : }
110 :
111 34000 : if (name_without_prefix == "length_factor")
112 : {
113 34000 : computedKdlf(dKdhp, x, _length_factor, _sigma_f_squared, _gamma, ind);
114 : return true;
115 : }
116 :
117 : return false;
118 : }
119 :
120 : void
121 34000 : ExponentialCovariance::computedKdlf(RealEigenMatrix & K,
122 : const RealEigenMatrix & x,
123 : const std::vector<Real> & length_factor,
124 : const Real sigma_f_squared,
125 : const Real gamma,
126 : const int ind)
127 : {
128 34000 : unsigned int num_samples_x = x.rows();
129 34000 : unsigned int num_params_x = x.cols();
130 :
131 : mooseAssert(ind < x.cols(), "Incorrect length factor index");
132 :
133 714000 : for (unsigned int ii = 0; ii < num_samples_x; ++ii)
134 : {
135 14280000 : for (unsigned int jj = 0; jj < num_samples_x; ++jj)
136 : {
137 : // Compute distance per parameter, scaled by length factor
138 : Real r_scaled = 0;
139 40800000 : for (unsigned int kk = 0; kk < num_params_x; ++kk)
140 27200000 : r_scaled += pow((x(ii, kk) - x(jj, kk)) / length_factor[kk], 2);
141 13600000 : r_scaled = sqrt(r_scaled);
142 13600000 : if (r_scaled != 0)
143 : {
144 12920000 : K(ii, jj) = gamma * std::pow(r_scaled, gamma - 2) * sigma_f_squared *
145 12920000 : std::exp(-pow(r_scaled, gamma));
146 12920000 : K(ii, jj) =
147 12920000 : std::pow(x(ii, ind) - x(jj, ind), 2) / std::pow(length_factor[ind], 3) * K(ii, jj);
148 : }
149 : else // avoid div by 0. 0/0=0 scenario.
150 680000 : K(ii, jj) = 0;
151 : }
152 : }
153 34000 : }
|