From 97b9451a8bf8f9a8e2ad079f50a3af603d9e599b Mon Sep 17 00:00:00 2001 From: Zachary Prince Date: Thu, 29 Jul 2021 00:34:03 -0600 Subject: [PATCH] Reporter that accumulates values over time #18469 --- .../source/reporters/AccumulateReporter.md | 25 + .../include/reporters/AccumulateReporter.h | 111 +++ .../include/reporters/ConstantReporter.h | 13 - framework/src/reporters/AccumulateReporter.C | 60 ++ framework/src/reporters/ConstantReporter.C | 15 +- .../accumulate_reporter.i | 69 ++ .../gold/accumulate_reporter_out.json | 745 ++++++++++++++++++ .../reporters/accumulated_reporter/tests | 12 + 8 files changed, 1029 insertions(+), 21 deletions(-) create mode 100644 framework/doc/content/source/reporters/AccumulateReporter.md create mode 100644 framework/include/reporters/AccumulateReporter.h create mode 100644 framework/src/reporters/AccumulateReporter.C create mode 100644 test/tests/reporters/accumulated_reporter/accumulate_reporter.i create mode 100644 test/tests/reporters/accumulated_reporter/gold/accumulate_reporter_out.json create mode 100644 test/tests/reporters/accumulated_reporter/tests diff --git a/framework/doc/content/source/reporters/AccumulateReporter.md b/framework/doc/content/source/reporters/AccumulateReporter.md new file mode 100644 index 000000000000..af0bd9d28dd1 --- /dev/null +++ b/framework/doc/content/source/reporters/AccumulateReporter.md @@ -0,0 +1,25 @@ +# AccumulateReporter + +!syntax description /Reporters/AccumulateReporter + +## Overview + +AccumulateReporter gives the ability to accumulate reporter values over time and assigns it to a vector reporter value. Currently supported reporter value types: + +- `int` +- `Real` (this covers postprocessors) +- `std::string` +- `std::vector` +- `std::vector` (this covers vectorpostprocessors) +- `std::vector` + +If more types need to be supported, they can easily be added by adding a line in the `if` statement in `AccumulateReporter::initialSetup()`: + +!listing framework/src/reporters/AccumulateReporter.C + re=void\nAccumulateReporter::initialSetup.*?^} + +!syntax parameters /Reporters/AccumulateReporter + +!syntax inputs /Reporters/AccumulateReporter + +!syntax children /Reporters/AccumulateReporter diff --git a/framework/include/reporters/AccumulateReporter.h b/framework/include/reporters/AccumulateReporter.h new file mode 100644 index 000000000000..7ca2715b4af8 --- /dev/null +++ b/framework/include/reporters/AccumulateReporter.h @@ -0,0 +1,111 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +#pragma once + +#include "GeneralReporter.h" + +class AccumulatedValueBase; +template +class AccumulatedValue; + +class AccumulateReporter : public GeneralReporter +{ +public: + static InputParameters validParams(); + AccumulateReporter(const InputParameters & parameters); + virtual void initialSetup() override; + virtual void initialize() override {} + virtual void execute() override; + virtual void finalize() override {} + +protected: + /** + * Helper for declaring an accumalative reporter value + * This will fill in _accumulated_values if the reporter value is found + */ + template + bool declareAccumulateHelper(const ReporterName & rname); + + /// Vector of accumulated value objects + std::vector> _accumulated_values; +}; + +template +bool +AccumulateReporter::declareAccumulateHelper(const ReporterName & rname) +{ + const ReporterData & rdata = _fe_problem.getReporterData(); + + if (!rdata.hasReporterValue(rname)) + return false; + + const auto & pmode = rdata.getReporterMode(rname); + ReporterMode rmode = REPORTER_MODE_UNSET; + if (pmode == REPORTER_MODE_ROOT) + rmode = REPORTER_MODE_ROOT; + else if (pmode == REPORTER_MODE_REPLICATED) + rmode = REPORTER_MODE_REPLICATED; + else if (pmode == REPORTER_MODE_DISTRIBUTED) + rmode = REPORTER_MODE_DISTRIBUTED; + const T & val = getReporterValueByName(rname); + std::vector & acc_val = + declareValueByName>(rname.getObjectName() + ":" + rname.getValueName(), rmode); + + _accumulated_values.push_back(libmesh_make_unique>(val, acc_val)); + return true; +} + +class AccumulatedValueBase +{ +public: + AccumulatedValueBase() = default; + virtual ~AccumulatedValueBase() = default; + + virtual void accumulate(Real acc_id) + { + auto it = std::find(_acc_index.begin(), _acc_index.end(), acc_id); + unsigned int ind; + if (it == _acc_index.end()) + { + _acc_index.push_back(acc_id); + ind = _acc_index.size() - 1; + } + else + ind = std::distance(_acc_index.begin(), it); + accumulateInternal(ind); + } + +protected: + virtual void accumulateInternal(unsigned int index) = 0; + std::vector _acc_index; +}; + +template +class AccumulatedValue : public AccumulatedValueBase +{ +public: + AccumulatedValue(const T & val, std::vector & acc_val) + : AccumulatedValueBase(), _val(val), _acc_val(acc_val) + { + } + +protected: + virtual void accumulateInternal(unsigned int index) override + { + if (_acc_val.size() <= index) + _acc_val.resize(index + 1, _val); + else + _acc_val[index] = _val; + } + +private: + const T & _val; + std::vector & _acc_val; +}; diff --git a/framework/include/reporters/ConstantReporter.h b/framework/include/reporters/ConstantReporter.h index 8d859942bc8e..9192ffa97459 100644 --- a/framework/include/reporters/ConstantReporter.h +++ b/framework/include/reporters/ConstantReporter.h @@ -32,19 +32,6 @@ class ConstantReporter : public GeneralReporter template std::vector *> declareConstantVectorReporterValues(const std::string & prefix); ///@} - - /// Integer reporter data - std::vector _int; - /// Real reporter data - std::vector _real; - /// String reporter data - std::vector _string; - /// Vector of integers reporter data - std::vector *> _int_vec; - /// Vector of reals reporter data - std::vector *> _real_vec; - /// Vector of strings reporter data - std::vector *> _string_vec; }; template diff --git a/framework/src/reporters/AccumulateReporter.C b/framework/src/reporters/AccumulateReporter.C new file mode 100644 index 000000000000..f51f4215ca0f --- /dev/null +++ b/framework/src/reporters/AccumulateReporter.C @@ -0,0 +1,60 @@ +//* This file is part of the MOOSE framework +//* https://www.mooseframework.org +//* +//* All rights reserved, see COPYRIGHT for full restrictions +//* https://github.com/idaholab/moose/blob/master/COPYRIGHT +//* +//* Licensed under LGPL 2.1, please see LICENSE for details +//* https://www.gnu.org/licenses/lgpl-2.1.html + +#include "AccumulateReporter.h" + +registerMooseObject("MooseApp", AccumulateReporter); + +InputParameters +AccumulateReporter::validParams() +{ + InputParameters params = GeneralReporter::validParams(); + params.addClassDescription("Reporter the accumulates the value of a inputted reporter value over " + "time into a vector reporter value of the same type."); + params.addRequiredParam>("reporters", "The reporters to accumulate."); + + params.set("execute_on") = {EXEC_INITIAL, EXEC_TIMESTEP_END}; + params.suppressParameter("execute_on"); + return params; +} + +AccumulateReporter::AccumulateReporter(const InputParameters & parameters) + : GeneralReporter(parameters) +{ +} + +void +AccumulateReporter::initialSetup() +{ + const ReporterData & rdata = _fe_problem.getReporterData(); + for (const auto & rname : getParam>("reporters")) + { + if (!rdata.hasReporterValue(rname)) + paramError("reporters", "Reporter ", rname, " does not exist."); + + if (!declareAccumulateHelper(rname) && !declareAccumulateHelper(rname) && + !declareAccumulateHelper(rname) && + !declareAccumulateHelper>(rname) && + !declareAccumulateHelper>(rname) && + !declareAccumulateHelper>(rname)) + paramError("reporters", + "Reporter value ", + rname, + " is of unsupported type ", + rdata.getReporterContextBase(rname).type(), + "."); + } +} + +void +AccumulateReporter::execute() +{ + for (auto & val : _accumulated_values) + val->accumulate(_t); +} diff --git a/framework/src/reporters/ConstantReporter.C b/framework/src/reporters/ConstantReporter.C index 2ec632d81ad2..e864b31a1786 100644 --- a/framework/src/reporters/ConstantReporter.C +++ b/framework/src/reporters/ConstantReporter.C @@ -25,13 +25,12 @@ ConstantReporter::validParams() return params; } -ConstantReporter::ConstantReporter(const InputParameters & parameters) - : GeneralReporter(parameters), - _int(declareConstantReporterValues("integer")), - _real(declareConstantReporterValues("real")), - _string(declareConstantReporterValues("string")), - _int_vec(declareConstantVectorReporterValues("integer")), - _real_vec(declareConstantVectorReporterValues("real")), - _string_vec(declareConstantVectorReporterValues("string")) +ConstantReporter::ConstantReporter(const InputParameters & parameters) : GeneralReporter(parameters) { + declareConstantReporterValues("integer"); + declareConstantReporterValues("real"); + declareConstantReporterValues("string"); + declareConstantVectorReporterValues("integer"); + declareConstantVectorReporterValues("real"); + declareConstantVectorReporterValues("string"); } diff --git a/test/tests/reporters/accumulated_reporter/accumulate_reporter.i b/test/tests/reporters/accumulated_reporter/accumulate_reporter.i new file mode 100644 index 000000000000..4383aa78cfbe --- /dev/null +++ b/test/tests/reporters/accumulated_reporter/accumulate_reporter.i @@ -0,0 +1,69 @@ +[Mesh/mesh] + type = GeneratedMeshGenerator + dim = 1 +[] + +[Problem] + kernel_coverage_check = false + solve = false +[] + +[Functions/fun] + type = ParsedFunction + value = 't * x' +[] + +[Postprocessors/pp] + type = FunctionValuePostprocessor + function = fun + point = '1 0 0' + execute_on = 'initial timestep_end' +[] + +[VectorPostprocessors/vpp] + type = LineFunctionSampler + functions = fun + start_point = '0 0 0' + end_point = '1 0 0' + num_points = 6 + sort_by = x + execute_on = 'initial timestep_end' +[] + +[Reporters] + [rep] + type = ConstantReporter + integer_names = 'int' + integer_values = '1' + string_names = 'str' + string_values = 'two' + integer_vector_names = 'int_vec' + integer_vector_values = '3 4' + string_vector_names = 'str_vec' + string_vector_values = 'five six seven eight' + outputs = none + [] + [accumulate] + type = AccumulateReporter + reporters = 'pp/value vpp/fun rep/int rep/str rep/int_vec rep/str_vec' + [] +[] + +[Executioner] + type = Transient + num_steps = 5 + + # This is just testing that AccumulateReporter doesn't accumulate picard iterations + fixed_point_max_its = 3 + custom_pp = pp + direct_pp_value = true + disable_fixed_point_residual_norm_check = true + accept_on_max_fixed_point_iteration = true +[] + +[Outputs] + [out] + type = JSON + execute_system_information_on = none + [] +[] diff --git a/test/tests/reporters/accumulated_reporter/gold/accumulate_reporter_out.json b/test/tests/reporters/accumulated_reporter/gold/accumulate_reporter_out.json new file mode 100644 index 000000000000..be26cca1f277 --- /dev/null +++ b/test/tests/reporters/accumulated_reporter/gold/accumulate_reporter_out.json @@ -0,0 +1,745 @@ +{ + "time_steps": [ + { + "reporters": { + "accumulate": { + "info": { + "name": "accumulate", + "type": "AccumulateReporter" + }, + "values": [ + { + "name": "pp:value", + "type": "std::vector", + "value": [ + 0.0 + ] + }, + { + "name": "rep:int", + "type": "std::vector", + "value": [ + 1 + ] + }, + { + "name": "rep:int_vec", + "type": "std::vector>", + "value": [ + [ + 3, + 4 + ] + ] + }, + { + "name": "rep:str", + "type": "std::vector", + "value": [ + "two" + ] + }, + { + "name": "rep:str_vec", + "type": "std::vector>", + "value": [ + [ + "five", + "six", + "seven", + "eight" + ] + ] + }, + { + "name": "vpp:fun", + "type": "std::vector>", + "value": [ + [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ] + ] + } + ] + } + }, + "time": 0.0, + "time_step": 0 + }, + { + "reporters": { + "accumulate": { + "info": { + "name": "accumulate", + "type": "AccumulateReporter" + }, + "values": [ + { + "name": "pp:value", + "type": "std::vector", + "value": [ + 0.0, + 1.0 + ] + }, + { + "name": "rep:int", + "type": "std::vector", + "value": [ + 1, + 1 + ] + }, + { + "name": "rep:int_vec", + "type": "std::vector>", + "value": [ + [ + 3, + 4 + ], + [ + 3, + 4 + ] + ] + }, + { + "name": "rep:str", + "type": "std::vector", + "value": [ + "two", + "two" + ] + }, + { + "name": "rep:str_vec", + "type": "std::vector>", + "value": [ + [ + "five", + "six", + "seven", + "eight" + ], + [ + "five", + "six", + "seven", + "eight" + ] + ] + }, + { + "name": "vpp:fun", + "type": "std::vector>", + "value": [ + [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 0.0, + 0.2, + 0.4, + 0.6000000000000001, + 0.8, + 1.0 + ] + ] + } + ] + } + }, + "time": 1.0, + "time_step": 1 + }, + { + "reporters": { + "accumulate": { + "info": { + "name": "accumulate", + "type": "AccumulateReporter" + }, + "values": [ + { + "name": "pp:value", + "type": "std::vector", + "value": [ + 0.0, + 1.0, + 2.0 + ] + }, + { + "name": "rep:int", + "type": "std::vector", + "value": [ + 1, + 1, + 1 + ] + }, + { + "name": "rep:int_vec", + "type": "std::vector>", + "value": [ + [ + 3, + 4 + ], + [ + 3, + 4 + ], + [ + 3, + 4 + ] + ] + }, + { + "name": "rep:str", + "type": "std::vector", + "value": [ + "two", + "two", + "two" + ] + }, + { + "name": "rep:str_vec", + "type": "std::vector>", + "value": [ + [ + "five", + "six", + "seven", + "eight" + ], + [ + "five", + "six", + "seven", + "eight" + ], + [ + "five", + "six", + "seven", + "eight" + ] + ] + }, + { + "name": "vpp:fun", + "type": "std::vector>", + "value": [ + [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 0.0, + 0.2, + 0.4, + 0.6000000000000001, + 0.8, + 1.0 + ], + [ + 0.0, + 0.4, + 0.8, + 1.2000000000000002, + 1.6, + 2.0 + ] + ] + } + ] + } + }, + "time": 2.0, + "time_step": 2 + }, + { + "reporters": { + "accumulate": { + "info": { + "name": "accumulate", + "type": "AccumulateReporter" + }, + "values": [ + { + "name": "pp:value", + "type": "std::vector", + "value": [ + 0.0, + 1.0, + 2.0, + 3.0 + ] + }, + { + "name": "rep:int", + "type": "std::vector", + "value": [ + 1, + 1, + 1, + 1 + ] + }, + { + "name": "rep:int_vec", + "type": "std::vector>", + "value": [ + [ + 3, + 4 + ], + [ + 3, + 4 + ], + [ + 3, + 4 + ], + [ + 3, + 4 + ] + ] + }, + { + "name": "rep:str", + "type": "std::vector", + "value": [ + "two", + "two", + "two", + "two" + ] + }, + { + "name": "rep:str_vec", + "type": "std::vector>", + "value": [ + [ + "five", + "six", + "seven", + "eight" + ], + [ + "five", + "six", + "seven", + "eight" + ], + [ + "five", + "six", + "seven", + "eight" + ], + [ + "five", + "six", + "seven", + "eight" + ] + ] + }, + { + "name": "vpp:fun", + "type": "std::vector>", + "value": [ + [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 0.0, + 0.2, + 0.4, + 0.6000000000000001, + 0.8, + 1.0 + ], + [ + 0.0, + 0.4, + 0.8, + 1.2000000000000002, + 1.6, + 2.0 + ], + [ + 0.0, + 0.6000000000000001, + 1.2000000000000002, + 1.8000000000000003, + 2.4000000000000004, + 3.0 + ] + ] + } + ] + } + }, + "time": 3.0, + "time_step": 3 + }, + { + "reporters": { + "accumulate": { + "info": { + "name": "accumulate", + "type": "AccumulateReporter" + }, + "values": [ + { + "name": "pp:value", + "type": "std::vector", + "value": [ + 0.0, + 1.0, + 2.0, + 3.0, + 4.0 + ] + }, + { + "name": "rep:int", + "type": "std::vector", + "value": [ + 1, + 1, + 1, + 1, + 1 + ] + }, + { + "name": "rep:int_vec", + "type": "std::vector>", + "value": [ + [ + 3, + 4 + ], + [ + 3, + 4 + ], + [ + 3, + 4 + ], + [ + 3, + 4 + ], + [ + 3, + 4 + ] + ] + }, + { + "name": "rep:str", + "type": "std::vector", + "value": [ + "two", + "two", + "two", + "two", + "two" + ] + }, + { + "name": "rep:str_vec", + "type": "std::vector>", + "value": [ + [ + "five", + "six", + "seven", + "eight" + ], + [ + "five", + "six", + "seven", + "eight" + ], + [ + "five", + "six", + "seven", + "eight" + ], + [ + "five", + "six", + "seven", + "eight" + ], + [ + "five", + "six", + "seven", + "eight" + ] + ] + }, + { + "name": "vpp:fun", + "type": "std::vector>", + "value": [ + [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 0.0, + 0.2, + 0.4, + 0.6000000000000001, + 0.8, + 1.0 + ], + [ + 0.0, + 0.4, + 0.8, + 1.2000000000000002, + 1.6, + 2.0 + ], + [ + 0.0, + 0.6000000000000001, + 1.2000000000000002, + 1.8000000000000003, + 2.4000000000000004, + 3.0 + ], + [ + 0.0, + 0.8, + 1.6, + 2.4000000000000004, + 3.2, + 4.0 + ] + ] + } + ] + } + }, + "time": 4.0, + "time_step": 4 + }, + { + "reporters": { + "accumulate": { + "info": { + "name": "accumulate", + "type": "AccumulateReporter" + }, + "values": [ + { + "name": "pp:value", + "type": "std::vector", + "value": [ + 0.0, + 1.0, + 2.0, + 3.0, + 4.0, + 5.0 + ] + }, + { + "name": "rep:int", + "type": "std::vector", + "value": [ + 1, + 1, + 1, + 1, + 1, + 1 + ] + }, + { + "name": "rep:int_vec", + "type": "std::vector>", + "value": [ + [ + 3, + 4 + ], + [ + 3, + 4 + ], + [ + 3, + 4 + ], + [ + 3, + 4 + ], + [ + 3, + 4 + ], + [ + 3, + 4 + ] + ] + }, + { + "name": "rep:str", + "type": "std::vector", + "value": [ + "two", + "two", + "two", + "two", + "two", + "two" + ] + }, + { + "name": "rep:str_vec", + "type": "std::vector>", + "value": [ + [ + "five", + "six", + "seven", + "eight" + ], + [ + "five", + "six", + "seven", + "eight" + ], + [ + "five", + "six", + "seven", + "eight" + ], + [ + "five", + "six", + "seven", + "eight" + ], + [ + "five", + "six", + "seven", + "eight" + ], + [ + "five", + "six", + "seven", + "eight" + ] + ] + }, + { + "name": "vpp:fun", + "type": "std::vector>", + "value": [ + [ + 0.0, + 0.0, + 0.0, + 0.0, + 0.0, + 0.0 + ], + [ + 0.0, + 0.2, + 0.4, + 0.6000000000000001, + 0.8, + 1.0 + ], + [ + 0.0, + 0.4, + 0.8, + 1.2000000000000002, + 1.6, + 2.0 + ], + [ + 0.0, + 0.6000000000000001, + 1.2000000000000002, + 1.8000000000000003, + 2.4000000000000004, + 3.0 + ], + [ + 0.0, + 0.8, + 1.6, + 2.4000000000000004, + 3.2, + 4.0 + ], + [ + 0.0, + 1.0, + 2.0, + 3.0000000000000004, + 4.0, + 5.0 + ] + ] + } + ] + } + }, + "time": 5.0, + "time_step": 5 + } + ] +} diff --git a/test/tests/reporters/accumulated_reporter/tests b/test/tests/reporters/accumulated_reporter/tests new file mode 100644 index 000000000000..2e1a09905545 --- /dev/null +++ b/test/tests/reporters/accumulated_reporter/tests @@ -0,0 +1,12 @@ +[Tests] + design = 'AccumulateReporter.md' + issues = '#18469' + + [accumulate_reporter] + type = 'JSONDiff' + input = 'accumulate_reporter.i' + jsondiff = 'accumulate_reporter_out.json' + + requirement = 'The system shall be able to accumulate reporter values over time steps into a vector reporter value.' + [] +[]