LCOV - code coverage report
Current view: top level - src/reporters - ActiveLearningGPDecision.C (source / functions) Hit Total Coverage
Test: idaholab/moose stochastic_tools: #31405 (292dce) with base fef103 Lines: 70 72 97.2 %
Date: 2025-09-04 07:57:52 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         246 : ActiveLearningGPDecision::validParams()
      20             : {
      21         246 :   InputParameters params = ActiveLearningReporterTempl<Real>::validParams();
      22         246 :   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         492 :   MooseEnum learning_function("Ufunction COV");
      26         492 :   params.addRequiredParam<MooseEnum>(
      27             :       "learning_function", learning_function, "The learning function for active learning.");
      28         492 :   params.addRequiredParam<Real>("learning_function_threshold", "The learning function threshold.");
      29         492 :   params.addParam<Real>("learning_function_parameter",
      30         492 :                         std::numeric_limits<Real>::max(),
      31             :                         "The learning function parameter.");
      32         492 :   params.addRequiredParam<UserObjectName>("al_gp", "Active learning GP trainer.");
      33         492 :   params.addRequiredParam<UserObjectName>("gp_evaluator", "Evaluate the trained GP.");
      34         492 :   params.addRequiredParam<SamplerName>("sampler", "The sampler object.");
      35         492 :   params.addParam<ReporterValueName>("flag_sample", "flag_sample", "Flag samples.");
      36         492 :   params.addRequiredParam<int>("n_train", "Number of training steps.");
      37         492 :   params.addParam<ReporterValueName>("inputs", "inputs", "The inputs.");
      38         492 :   params.addParam<ReporterValueName>("gp_mean", "gp_mean", "The GP mean prediction.");
      39         492 :   params.addParam<ReporterValueName>("gp_std", "gp_std", "The GP standard deviation.");
      40         246 :   return params;
      41         246 : }
      42             : 
      43         123 : ActiveLearningGPDecision::ActiveLearningGPDecision(const InputParameters & parameters)
      44             :   : ActiveLearningReporterTempl<Real>(parameters),
      45             :     SurrogateModelInterface(this),
      46         123 :     _learning_function(getParam<MooseEnum>("learning_function")),
      47         246 :     _learning_function_threshold(getParam<Real>("learning_function_threshold")),
      48         246 :     _learning_function_parameter(getParam<Real>("learning_function_parameter")),
      49         123 :     _al_gp(getUserObject<ActiveLearningGaussianProcess>("al_gp")),
      50         123 :     _gp_eval(getSurrogateModel<GaussianProcessSurrogate>("gp_evaluator")),
      51         123 :     _flag_sample(declareValue<std::vector<bool>>(
      52         123 :         "flag_sample", std::vector<bool>(sampler().getNumberOfRows(), false))),
      53         246 :     _n_train(getParam<int>("n_train")),
      54         123 :     _inputs(declareValue<std::vector<std::vector<Real>>>(
      55             :         "inputs",
      56         246 :         std::vector<std::vector<Real>>(sampler().getNumberOfRows(),
      57         246 :                                        std::vector<Real>(sampler().getNumberOfCols())))),
      58         123 :     _gp_mean(
      59         246 :         declareValue<std::vector<Real>>("gp_mean", std::vector<Real>(sampler().getNumberOfRows()))),
      60         123 :     _gp_std(
      61         246 :         declareValue<std::vector<Real>>("gp_std", std::vector<Real>(sampler().getNumberOfRows()))),
      62         123 :     _decision(true),
      63         123 :     _inputs_global(getGlobalInputData()),
      64         123 :     _outputs_global(getGlobalOutputData())
      65             : {
      66         229 :   if (_learning_function == "Ufunction" &&
      67         335 :       !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         123 : }
      72             : 
      73             : bool
      74        2485 : ActiveLearningGPDecision::learningFunction(const Real & gp_mean, const Real & gp_std) const
      75             : {
      76        2485 :   if (_learning_function == "Ufunction")
      77        2230 :     return (std::abs(gp_mean - _learning_function_parameter) / gp_std) >
      78        2230 :            _learning_function_threshold;
      79         255 :   else if (_learning_function == "COV")
      80         255 :     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         939 : ActiveLearningGPDecision::setupData(const std::vector<std::vector<Real>> & inputs,
      88             :                                     const std::vector<Real> & outputs)
      89             : {
      90         939 :   _inputs_batch.insert(_inputs_batch.end(), inputs.begin(), inputs.end());
      91         939 :   _outputs_batch.insert(_outputs_batch.end(), outputs.begin(), outputs.end());
      92         939 : }
      93             : 
      94             : bool
      95        1418 : ActiveLearningGPDecision::facilitateDecision()
      96             : {
      97        3166 :   for (dof_id_type i = 0; i < _inputs.size(); ++i)
      98             :   {
      99        1748 :     _gp_mean[i] = _gp_eval.evaluate(_inputs[i], _gp_std[i]);
     100        1748 :     _flag_sample[i] = !learningFunction(_gp_mean[i], _gp_std[i]);
     101             :   }
     102             : 
     103        1559 :   for (const auto & fs : _flag_sample)
     104        1440 :     if (!fs)
     105             :       return false;
     106         119 :   return true;
     107             : }
     108             : 
     109             : void
     110        1958 : ActiveLearningGPDecision::preNeedSample()
     111             : {
     112             :   // Accumulate inputs and outputs if we previously decided we needed a sample
     113        1958 :   if (_t_step > 1 && _decision)
     114             :   {
     115             :     // Accumulate data into _batch members
     116         642 :     setupData(_inputs, _outputs_global);
     117             : 
     118             :     // Retrain if we are outside the training phase
     119         642 :     if (_t_step > _n_train)
     120         209 :       _al_gp.reTrain(_inputs_batch, _outputs_batch);
     121             :   }
     122             : 
     123             :   // Gather inputs for the current step
     124        1958 :   _inputs = _inputs_global;
     125             : 
     126             :   // Evaluate GP and decide if we need more data if outside training phase
     127        1958 :   if (_t_step > _n_train)
     128        1418 :     _decision = facilitateDecision();
     129        1958 : }
     130             : 
     131             : bool
     132        1430 : ActiveLearningGPDecision::needSample(const std::vector<Real> &,
     133             :                                      dof_id_type,
     134             :                                      dof_id_type global_ind,
     135             :                                      Real & val)
     136             : {
     137        1430 :   if (!_decision)
     138         957 :     val = _gp_mean[global_ind];
     139        1430 :   return _decision;
     140             : }

Generated by: LCOV version 1.14