LCOV - code coverage report
Current view: top level - src/surrogates - GaussianProcessSurrogate.C (source / functions) Hit Total Coverage
Test: idaholab/moose stochastic_tools: #33416 (b10b36) with base 9fbd27 Lines: 50 55 90.9 %
Date: 2026-07-23 16:21:17 Functions: 6 7 85.7 %
Legend: Lines: hit not hit

          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             : #ifdef MOOSE_LIBTORCH_ENABLED
      10             : 
      11             : #include "GaussianProcessSurrogate.h"
      12             : #include "Sampler.h"
      13             : 
      14             : #include "CovarianceFunctionBase.h"
      15             : 
      16             : registerMooseObject("StochasticToolsApp", GaussianProcessSurrogate);
      17             : 
      18             : InputParameters
      19         466 : GaussianProcessSurrogate::validParams()
      20             : {
      21         466 :   InputParameters params = SurrogateModel::validParams();
      22         466 :   params.addClassDescription("Computes and evaluates Gaussian Process surrogate model.");
      23         466 :   return params;
      24           0 : }
      25             : 
      26         232 : GaussianProcessSurrogate::GaussianProcessSurrogate(const InputParameters & parameters)
      27             :   : SurrogateModel(parameters),
      28             :     CovarianceInterface(parameters),
      29         232 :     _gp(declareModelData<StochasticTools::GaussianProcess>("_gp")),
      30         696 :     _training_params(getModelData<torch::Tensor>("_training_params"))
      31             : {
      32         232 : }
      33             : 
      34             : void
      35          16 : GaussianProcessSurrogate::setupCovariance(UserObjectName covar_name)
      36             : {
      37          16 :   if (_gp.getCovarFunctionPtr() != nullptr)
      38           0 :     ::mooseError("Attempting to redefine covariance function using setupCovariance.");
      39          16 :   _gp.linkCovarianceFunction(getCovarianceFunctionByName(covar_name));
      40          16 : }
      41             : 
      42             : Real
      43         375 : GaussianProcessSurrogate::evaluate(const std::vector<Real> & x) const
      44             : {
      45             :   // Overlaod for evaluate to maintain general compatibility. Only returns mean
      46         375 :   Real dummy = 0;
      47         375 :   return this->evaluate(x, dummy);
      48             : }
      49             : 
      50             : Real
      51      133926 : GaussianProcessSurrogate::evaluate(const std::vector<Real> & x, Real & std_dev) const
      52             : {
      53             :   std::vector<Real> y;
      54             :   std::vector<Real> std;
      55      133926 :   this->evaluate(x, y, std);
      56      133926 :   std_dev = std[0];
      57      133926 :   return y[0];
      58      133926 : }
      59             : 
      60             : void
      61           0 : GaussianProcessSurrogate::evaluate(const std::vector<Real> & x, std::vector<Real> & y) const
      62             : {
      63             :   // Overlaod for evaluate to maintain general compatibility. Only returns mean
      64             :   std::vector<Real> std_dummy;
      65           0 :   this->evaluate(x, y, std_dummy);
      66           0 : }
      67             : 
      68             : void
      69      134001 : GaussianProcessSurrogate::evaluate(const std::vector<Real> & x,
      70             :                                    std::vector<Real> & y,
      71             :                                    std::vector<Real> & std) const
      72             : {
      73      134001 :   const unsigned int n_dims = _training_params.sizes()[1];
      74             : 
      75             :   mooseAssert(x.size() == n_dims,
      76             :               "Number of parameters provided for evaluation does not match number of parameters "
      77             :               "used for training.");
      78      134001 :   const unsigned int n_outputs = _gp.getCovarFunction().numOutputs();
      79             : 
      80      268002 :   y = std::vector<Real>(n_outputs, 0.0);
      81      268002 :   std = std::vector<Real>(n_outputs, 0.0);
      82             : 
      83      134001 :   const auto options = _training_params.options().dtype(at::kDouble);
      84             : 
      85      134001 :   torch::Tensor test_points = torch::empty({1, n_dims}, at::kDouble);
      86      134001 :   auto points_accessor = test_points.accessor<Real, 2>();
      87      402256 :   for (unsigned int ii = 0; ii < n_dims; ++ii)
      88      268255 :     points_accessor[0][ii] = x[ii];
      89      134001 :   test_points = test_points.to(options.device());
      90             : 
      91      134001 :   _gp.getParamStandardizer().getStandardized(test_points);
      92             : 
      93             :   torch::Tensor K_train_test =
      94      134001 :       torch::empty({_training_params.sizes()[0] * n_outputs, n_outputs}, options);
      95             : 
      96      134001 :   _gp.getCovarFunction().computeCovarianceMatrix(
      97             :       K_train_test, _training_params, test_points, false);
      98      134001 :   torch::Tensor K_test = torch::empty({n_outputs, n_outputs}, options);
      99      134001 :   _gp.getCovarFunction().computeCovarianceMatrix(K_test, test_points, test_points, true);
     100             : 
     101             :   //  Compute the predicted mean value (centered)
     102             :   torch::Tensor pred_value = torch::transpose(
     103      134001 :       torch::mm(torch::transpose(K_train_test, 0, 1), _gp.getKResultsSolve()), 0, 1);
     104             : 
     105             :   //   De-center/scale the value and store for return
     106      134001 :   _gp.getDataStandardizer().getDestandardized(pred_value);
     107             : 
     108             :   torch::Tensor pred_var =
     109      134001 :       K_test - torch::mm(torch::transpose(K_train_test, 0, 1),
     110      402003 :                          torch::cholesky_solve(K_train_test, _gp.getKCholeskyDecomp()));
     111             : 
     112             :   // Only the marginal variances are returned. Clamp tiny negative roundoff before sqrt.
     113             :   torch::Tensor std_dev_vec =
     114      134001 :       torch::sqrt(torch::clamp_min(torch::diagonal(pred_var), 0.0)).unsqueeze(0);
     115      134001 :   _gp.getDataStandardizer().getDescaled(std_dev_vec);
     116      134001 :   const auto std_dev_cpu = LibtorchUtils::toCPUContiguous(std_dev_vec);
     117      134001 :   const auto pred_value_cpu = LibtorchUtils::toCPUContiguous(pred_value);
     118      134001 :   auto std_accessor = std_dev_cpu.accessor<Real, 2>();
     119      134001 :   auto pred_value_accessor = pred_value_cpu.accessor<Real, 2>();
     120             : 
     121      268077 :   for (const auto output_i : make_range(n_outputs))
     122             :   {
     123      134076 :     y[output_i] = pred_value_accessor[0][output_i];
     124      134076 :     std[output_i] = std_accessor[0][output_i];
     125             :   }
     126      134001 : }
     127             : 
     128             : #endif

Generated by: LCOV version 1.14