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

Generated by: LCOV version 1.14