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 : #pragma once 11 : 12 : #include "StochasticReporter.h" 13 : 14 : template <typename T> 15 : class ActiveLearningReporterTempl; 16 : 17 : /** 18 : * This is a base class for performing active learning routines, meant to be used 19 : * in conjunction with Sampler multiapps and SamplerReporterTransfer. The purpose 20 : * is to determine if a sample needs to be evaluated by a multiphysics solve and 21 : * possibly replace quantities of interest with values computed by other means. 22 : */ 23 : template <typename T> 24 : class ActiveLearningReporterTempl : public StochasticReporter 25 : { 26 : public: 27 : static InputParameters validParams(); 28 : 29 : ActiveLearningReporterTempl(const InputParameters & parameters); 30 : 31 : /** 32 : * Here we loop through the samples and call the needSample function to determine 33 : * if the sample needs to be run and define a value in its place. 34 : */ 35 : virtual void execute() override; 36 : 37 : protected: 38 : /** 39 : * This is overriden for the following reasons: 40 : * 1) Only one vector can be declared and must match the type of this class. 41 : * 2) Check that the inputted sampler matches the one given in the parameters. 42 : * 3) We actually get a pointer to the declared value so we can replace it 43 : * (if necessary) in the needSample routine. 44 : * 4) Declare the "need_sample" value which can be used to evaluate the sample 45 : * or not. 46 : */ 47 : virtual ReporterName declareStochasticReporterClone(const Sampler & sampler, 48 : const ReporterData & from_data, 49 : const ReporterName & from_reporter, 50 : std::string prefix = "") override; 51 : 52 : /** 53 : * Get a const reference to the sampler from the parameters. This is preferred 54 : * over having _sampler being a protected member since we don't want derived classes 55 : * changing the state of the sampler during the loop in execute. 56 : */ 57 714 : const Sampler & sampler() const { return _sampler; } 58 : 59 : const std::vector<std::vector<Real>> & getGlobalInputData() const 60 : { 61 114 : _input_data_requested = true; 62 114 : return _input_data; 63 : } 64 : 65 : /** 66 : * Get a const reference to the output data 67 : */ 68 : const std::vector<T> & getGlobalOutputData() const 69 : { 70 114 : _output_data_requested = true; 71 114 : return _output_data; 72 : } 73 : 74 : /** 75 : * Optional virtual function that is called before the sampler loop calling needSample 76 : */ 77 80 : virtual void preNeedSample() {} 78 : 79 : /** 80 : * This routine is called during the sampler loop in execute() and is meant to fill 81 : * in the "need_sample" reporter value and modify the data declared by the transfer. 82 : * 83 : * @param row The row of data from the sampler 84 : * @param local_ind The local index of the sampler row 85 : * @param global_ind The global index of the sampler row 86 : * @param val Reference to the value associated with the row of data. 87 : * @return Filled in value of "need_sample", meant to determine if a sample needs 88 : * to be run by a multiapp or other means. 89 : */ 90 0 : virtual bool needSample(const std::vector<Real> & /*row*/, 91 : dof_id_type /*local_ind*/, 92 : dof_id_type /*global_ind*/, 93 : T & /*val*/) 94 : { 95 0 : return true; 96 : } 97 : 98 : /// Sampler given in the parameters, must match the one used to declare the 99 : /// transferred values. 100 : Sampler & _sampler; 101 : 102 : private: 103 : /// Reporter value determining whether we need to evaluate the sample through 104 : /// a multiapp or other means. 105 : std::vector<bool> & _need_sample; 106 : /// Reporter value declared with the transfer 107 : std::vector<T> * _data = nullptr; 108 : 109 : /// Whether or not to gather global input data 110 : mutable bool _input_data_requested = false; 111 : /// Whether or not to gather global output data 112 : mutable bool _output_data_requested = false; 113 : /// Global input data from sampler 114 : std::vector<std::vector<Real>> _input_data; 115 : /// Global output data from sampler 116 : std::vector<T> _output_data; 117 : }; 118 : 119 : template <typename T> 120 : InputParameters 121 264 : ActiveLearningReporterTempl<T>::validParams() 122 : { 123 264 : InputParameters params = StochasticReporter::validParams(); 124 528 : params.addRequiredParam<SamplerName>("sampler", "The sampler used to produce data."); 125 264 : return params; 126 0 : } 127 : 128 : template <typename T> 129 130 : ActiveLearningReporterTempl<T>::ActiveLearningReporterTempl(const InputParameters & parameters) 130 : : StochasticReporter(parameters), 131 130 : _sampler(this->template getSampler<Sampler>("sampler")), 132 260 : _need_sample(this->template declareStochasticReporter<bool>("need_sample", _sampler)) 133 : { 134 130 : } 135 : 136 : template <typename T> 137 : void 138 2468 : ActiveLearningReporterTempl<T>::execute() 139 : { 140 : // If requesting global data, fill it in 141 2468 : if (_input_data_requested) 142 : { 143 : // Gather inputs for the current step 144 2388 : _input_data.assign(_sampler.getNumberOfRows(), 145 2388 : std::vector<Real>(_sampler.getNumberOfCols(), 0.0)); 146 4248 : for (dof_id_type i = _sampler.getLocalRowBegin(); i < _sampler.getLocalRowEnd(); ++i) 147 3720 : _input_data[i] = _sampler.getNextLocalRow(); 148 5656 : for (auto & inp : _input_data) 149 : gatherSum(inp); 150 : } 151 2468 : if (_output_data_requested) 152 : { 153 2388 : if (!_data) 154 0 : mooseError("Output data has been requested, but none was declared in this object."); 155 2388 : _output_data = *_data; 156 2388 : _communicator.allgather(_output_data); 157 : } 158 : 159 : // Optional call for before sampler loop 160 2468 : preNeedSample(); 161 : 162 : // Dummy value in case _data has not been declared yet 163 : T dummy; 164 : // Loop over samples to determine if sample is needed. Replace value in _data 165 : // (typically only if a sample is not needed). We insert a dummy value in case 166 : // _data has not been declared. 167 4778 : for (const auto & i : make_range(_sampler.getNumberOfLocalRows())) 168 2310 : _need_sample[i] = needSample(_sampler.getNextLocalRow(), 169 : i, 170 2310 : i + _sampler.getLocalRowBegin(), 171 2310 : (_data ? (*_data)[i] : dummy)); 172 2468 : } 173 : 174 : template <typename T> 175 : ReporterName 176 130 : ActiveLearningReporterTempl<T>::declareStochasticReporterClone(const Sampler & sampler, 177 : const ReporterData & from_data, 178 : const ReporterName & from_reporter, 179 : std::string prefix) 180 : { 181 : // Only one value is allowed to be declared 182 130 : if (_data) 183 0 : this->mooseError(type(), " can only declare a single reporter value."); 184 : // Make sure the inputted sampler is the same one in the parameters 185 130 : else if (sampler.name() != _sampler.name()) 186 0 : this->paramError("sampler", 187 : "Inputted sampler, ", 188 0 : _sampler.name(), 189 : ", is not the same as the one producing data, ", 190 0 : sampler.name(), 191 : "."); 192 : // Make sure reporter value exists 193 130 : else if (!from_data.hasReporterValue(from_reporter)) 194 0 : this->mooseError("Reporter value ", from_reporter, " has not been declared."); 195 : // Make sure the reporter value is the right type 196 130 : else if (!from_data.hasReporterValue<T>(from_reporter)) 197 0 : this->mooseError( 198 : type(), " can only use reporter values of type ", MooseUtils::prettyCppType<T>(), "."); 199 : 200 260 : std::string value_name = (prefix.empty() ? "" : prefix + ":") + from_reporter.getObjectName() + 201 130 : ":" + from_reporter.getValueName(); 202 130 : _data = &this->declareStochasticReporter<T>(value_name, sampler); 203 260 : return {name(), value_name}; 204 : }