LCOV - code coverage report
Current view: top level - src/reporters - ActiveLearningGPDecision.C (source / functions) Hit Total Coverage
Test: idaholab/moose stochastic_tools: f45d79 Lines: 69 71 97.2 %
Date: 2025-07-25 05:00:46 Functions: 7 7 100.0 %
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             : 
      10             : #include "ActiveLearningGPDecision.h"
      11             : #include "Sampler.h"
      12             : #include "AdaptiveMonteCarloUtils.h"
      13             : 
      14             : #include <math.h>
      15             : 
      16             : registerMooseObject("StochasticToolsApp", ActiveLearningGPDecision);
      17             : 
      18             : InputParameters
      19         228 : ActiveLearningGPDecision::validParams()
      20             : {
      21         228 :   InputParameters params = ActiveLearningReporterTempl<Real>::validParams();
      22         228 :   params.addClassDescription(
      23             :       "Evaluates a GP surrogate model, determines its prediction quality, "
      24             :       "launches full model if GP prediction is inadequate, and retrains GP.");
      25         456 :   MooseEnum learning_function("Ufunction COV");
      26         456 :   params.addRequiredParam<MooseEnum>(
      27             :       "learning_function", learning_function, "The learning function for active learning.");
      28         456 :   params.addRequiredParam<Real>("learning_function_threshold", "The learning function threshold.");
      29         456 :   params.addParam<Real>("learning_function_parameter",
      30         456 :                         std::numeric_limits<Real>::max(),
      31             :                         "The learning function parameter.");
      32         456 :   params.addRequiredParam<UserObjectName>("al_gp", "Active learning GP trainer.");
      33         456 :   params.addRequiredParam<UserObjectName>("gp_evaluator", "Evaluate the trained GP.");
      34         456 :   params.addRequiredParam<SamplerName>("sampler", "The sampler object.");
      35         456 :   params.addParam<ReporterValueName>("flag_sample", "flag_sample", "Flag samples.");
      36         456 :   params.addRequiredParam<int>("n_train", "Number of training steps.");
      37         456 :   params.addParam<ReporterValueName>("inputs", "inputs", "The inputs.");
      38         456 :   params.addParam<ReporterValueName>("gp_mean", "gp_mean", "The GP mean prediction.");
      39         456 :   params.addParam<ReporterValueName>("gp_std", "gp_std", "The GP standard deviation.");
      40         228 :   return params;
      41         228 : }
      42             : 
      43         114 : ActiveLearningGPDecision::ActiveLearningGPDecision(const InputParameters & parameters)
      44             :   : ActiveLearningReporterTempl<Real>(parameters),
      45             :     SurrogateModelInterface(this),
      46         114 :     _learning_function(getParam<MooseEnum>("learning_function")),
      47         228 :     _learning_function_threshold(getParam<Real>("learning_function_threshold")),
      48         228 :     _learning_function_parameter(getParam<Real>("learning_function_parameter")),
      49         114 :     _al_gp(getUserObject<ActiveLearningGaussianProcess>("al_gp")),
      50         114 :     _gp_eval(getSurrogateModel<GaussianProcessSurrogate>("gp_evaluator")),
      51         114 :     _flag_sample(declareValue<std::vector<bool>>(
      52         114 :         "flag_sample", std::vector<bool>(sampler().getNumberOfRows(), false))),
      53         228 :     _n_train(getParam<int>("n_train")),
      54         114 :     _inputs(declareValue<std::vector<std::vector<Real>>>(
      55             :         "inputs",
      56         228 :         std::vector<std::vector<Real>>(sampler().getNumberOfRows(),
      57         228 :                                        std::vector<Real>(sampler().getNumberOfCols())))),
      58         114 :     _gp_mean(
      59         228 :         declareValue<std::vector<Real>>("gp_mean", std::vector<Real>(sampler().getNumberOfRows()))),
      60         114 :     _gp_std(
      61         228 :         declareValue<std::vector<Real>>("gp_std", std::vector<Real>(sampler().getNumberOfRows()))),
      62         114 :     _decision(true),
      63         114 :     _inputs_global(getGlobalInputData()),
      64         228 :     _outputs_global(getGlobalOutputData())
      65             : {
      66         212 :   if (_learning_function == "Ufunction" &&
      67         310 :       !parameters.isParamSetByUser("learning_function_parameter"))
      68           0 :     paramError("learning_function",
      69             :                "The Ufunction requires the model failure threshold ('learning_function_parameter') "
      70             :                "to be specified.");
      71         114 : }
      72             : 
      73             : bool
      74        2294 : ActiveLearningGPDecision::learningFunction(const Real & gp_mean, const Real & gp_std) const
      75             : {
      76        2294 :   if (_learning_function == "Ufunction")
      77        2054 :     return (std::abs(gp_mean - _learning_function_parameter) / gp_std) >
      78        2054 :            _learning_function_threshold;
      79         240 :   else if (_learning_function == "COV")
      80         240 :     return (gp_std / std::abs(gp_mean)) < _learning_function_threshold;
      81             :   else
      82           0 :     mooseError("Invalid learning function ", std::string(_learning_function));
      83             :   return false;
      84             : }
      85             : 
      86             : void
      87         870 : ActiveLearningGPDecision::setupData(const std::vector<std::vector<Real>> & inputs,
      88             :                                     const std::vector<Real> & outputs)
      89             : {
      90         870 :   _inputs_batch.insert(_inputs_batch.end(), inputs.begin(), inputs.end());
      91         870 :   _outputs_batch.insert(_outputs_batch.end(), outputs.begin(), outputs.end());
      92         870 : }
      93             : 
      94             : bool
      95        1324 : ActiveLearningGPDecision::facilitateDecision()
      96             : {
      97        2948 :   for (dof_id_type i = 0; i < _inputs.size(); ++i)
      98             :   {
      99        1624 :     _gp_mean[i] = _gp_eval.evaluate(_inputs[i], _gp_std[i]);
     100        1624 :     _flag_sample[i] = !learningFunction(_gp_mean[i], _gp_std[i]);
     101             :   }
     102             : 
     103        1324 :   for (const auto & fs : _flag_sample)
     104        1344 :     if (!fs)
     105             :       return false;
     106             :   return true;
     107             : }
     108             : 
     109             : void
     110        1828 : ActiveLearningGPDecision::preNeedSample()
     111             : {
     112             :   // Accumulate inputs and outputs if we previously decided we needed a sample
     113        1828 :   if (_t_step > 1 && _decision)
     114             :   {
     115             :     // Accumulate data into _batch members
     116         600 :     setupData(_inputs, _outputs_global);
     117             : 
     118             :     // Retrain if we are outside the training phase
     119         600 :     if (_t_step > _n_train)
     120         196 :       _al_gp.reTrain(_inputs_batch, _outputs_batch);
     121             :   }
     122             : 
     123             :   // Gather inputs for the current step
     124        1828 :   _inputs = _inputs_global;
     125             : 
     126             :   // Evaluate GP and decide if we need more data if outside training phase
     127        1828 :   if (_t_step > _n_train)
     128        1324 :     _decision = facilitateDecision();
     129        1828 : }
     130             : 
     131             : bool
     132        1300 : ActiveLearningGPDecision::needSample(const std::vector<Real> &,
     133             :                                      dof_id_type,
     134             :                                      dof_id_type global_ind,
     135             :                                      Real & val)
     136             : {
     137        1300 :   if (!_decision)
     138         870 :     val = _gp_mean[global_ind];
     139        1300 :   return _decision;
     140             : }

Generated by: LCOV version 1.14