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 "Statistics.h"
11 :
12 : // MOOSE includes
13 : #include "MooseVariable.h"
14 : #include "ThreadedElementLoopBase.h"
15 : #include "ThreadedNodeLoop.h"
16 :
17 : #include "libmesh/quadrature.h"
18 :
19 : #include <numeric>
20 :
21 : registerADMooseObjectDeprecated("StochasticToolsApp", Statistics, "07/01/2021 12:00");
22 :
23 : InputParameters
24 348 : Statistics::validParams()
25 : {
26 348 : InputParameters params = GeneralVectorPostprocessor::validParams();
27 348 : params.addClassDescription(
28 : "Compute statistical values of a given VectorPostprocessor objects and vectors.");
29 :
30 696 : params.addRequiredParam<std::vector<VectorPostprocessorName>>(
31 : "vectorpostprocessors",
32 : "List of VectorPostprocessor(s) to utilized for statistic computations.");
33 :
34 348 : MultiMooseEnum stats = StochasticTools::makeCalculatorEnum();
35 696 : params.addRequiredParam<MultiMooseEnum>(
36 : "compute",
37 : stats,
38 : "The statistic(s) to compute for each of the supplied vector postprocessors.");
39 :
40 : // Confidence Levels
41 348 : MooseEnum ci = StochasticTools::makeBootstrapCalculatorEnum();
42 696 : params.addParam<MooseEnum>(
43 : "ci_method", ci, "The method to use for computing confidence level intervals.");
44 :
45 696 : params.addParam<std::vector<Real>>(
46 : "ci_levels", "A vector of confidence levels to consider, values must be in (0, 0.5].");
47 696 : params.addParam<unsigned int>(
48 : "ci_replicates",
49 696 : 10000,
50 : "The number of replicates to use when computing confidence level intervals.");
51 696 : params.addParam<unsigned int>("ci_seed",
52 696 : 1,
53 : "The random number generator seed used for creating replicates "
54 : "while computing confidence level intervals.");
55 :
56 : // Compute values are computed on rank 0 and broadcast
57 696 : params.set<MooseEnum>("parallel_type") = "REPLICATED";
58 348 : params.suppressParameter<MooseEnum>("parallel_type");
59 348 : params.set<bool>("_auto_boradcast") = true;
60 :
61 348 : return params;
62 348 : }
63 :
64 180 : Statistics::Statistics(const InputParameters & parameters)
65 : : GeneralVectorPostprocessor(parameters),
66 180 : _compute_stats(getParam<MultiMooseEnum>("compute")),
67 360 : _ci_method(getParam<MooseEnum>("ci_method")),
68 314 : _ci_levels(_ci_method.isValid() ? computeLevels(getParam<std::vector<Real>>("ci_levels"))
69 : : std::vector<Real>()),
70 336 : _replicates(getParam<unsigned int>("ci_replicates")),
71 336 : _seed(getParam<unsigned int>("ci_seed")),
72 348 : _stat_type_vector(declareVector("stat_type"))
73 : {
74 612 : for (const auto & item : _compute_stats)
75 : {
76 444 : _stat_type_vector.push_back(item.id());
77 1686 : for (const auto & level : _ci_levels)
78 1242 : _stat_type_vector.push_back(item.id() + level);
79 : }
80 168 : }
81 :
82 : void
83 168 : Statistics::initialSetup()
84 : {
85 336 : TIME_SECTION("initialSetup", 3, "Setting Up Statistics");
86 :
87 336 : const auto & vpp_names = getParam<std::vector<VectorPostprocessorName>>("vectorpostprocessors");
88 368 : for (const auto & vpp_name : vpp_names)
89 : {
90 : const VectorPostprocessor & vpp_object =
91 200 : _fe_problem.getVectorPostprocessorObjectByName(vpp_name);
92 200 : const std::set<std::string> & vpp_vectors = vpp_object.getVectorNames();
93 400 : for (const auto & vec_name : vpp_vectors)
94 : {
95 : // Store VectorPostprocessor name and vector name from which stats will be computed
96 200 : _compute_from_names.emplace_back(vpp_name, vec_name, vpp_object.isDistributed());
97 :
98 : // Create the vector where the statistics will be stored
99 200 : std::string name = vpp_name + "_" + vec_name;
100 200 : _stat_vectors.push_back(&declareVector(name));
101 : }
102 : }
103 168 : }
104 :
105 : void
106 168 : Statistics::initialize()
107 : {
108 168 : if (!containsCompleteHistory())
109 368 : for (const auto & vec : _stat_vectors)
110 200 : vec->clear();
111 168 : }
112 :
113 : void
114 168 : Statistics::execute()
115 : {
116 336 : TIME_SECTION("execute", 3, "Executing Statistics");
117 :
118 368 : for (std::size_t i = 0; i < _compute_from_names.size(); ++i)
119 : {
120 : const std::string & vpp_name = std::get<0>(_compute_from_names[i]);
121 : const std::string & vec_name = std::get<1>(_compute_from_names[i]);
122 200 : const bool is_distributed = std::get<2>(_compute_from_names[i]);
123 : const VectorPostprocessorValue & data =
124 200 : getVectorPostprocessorValueByName(vpp_name, vec_name, true);
125 :
126 200 : if (is_distributed || processor_id() == 0)
127 : {
128 510 : for (const auto & item : _compute_stats)
129 : {
130 : std::unique_ptr<StochasticTools::Calculator<std::vector<Real>, Real>> calc_ptr =
131 380 : StochasticTools::makeCalculator(item, *this);
132 380 : _stat_vectors[i]->emplace_back(calc_ptr->compute(data, is_distributed));
133 :
134 380 : if (_ci_method.isValid())
135 : {
136 : auto ci_calc_ptr = StochasticTools::makeBootstrapCalculator<std::vector<Real>, Real>(
137 110 : _ci_method, *this, _ci_levels, _replicates, _seed, *calc_ptr);
138 110 : std::vector<Real> ci = ci_calc_ptr->compute(data, is_distributed);
139 110 : _stat_vectors[i]->insert(_stat_vectors[i]->end(), ci.begin(), ci.end());
140 110 : }
141 380 : }
142 : }
143 : }
144 168 : }
145 :
146 : std::vector<Real>
147 134 : Statistics::computeLevels(const std::vector<Real> & levels_in) const
148 : {
149 134 : if (levels_in.empty())
150 4 : paramError("ci_levels",
151 : "If the 'ci_method' parameter is supplied then the 'ci_levels' must also be "
152 : "supplied with values in (0, 0.5].");
153 :
154 130 : else if (*std::min_element(levels_in.begin(), levels_in.end()) <= 0)
155 4 : paramError("ci_levels", "The supplied levels must be greater than zero.");
156 :
157 126 : else if (*std::max_element(levels_in.begin(), levels_in.end()) > 0.5)
158 4 : paramError("ci_levels", "The supplied levels must be less than or equal to 0.5");
159 :
160 : std::list<Real> levels_out;
161 732 : for (auto it = levels_in.rbegin(); it != levels_in.rend(); ++it)
162 : {
163 610 : if (*it == 0.5)
164 : levels_out.push_back(*it);
165 :
166 : else
167 : {
168 : levels_out.push_front(*it);
169 488 : levels_out.push_back(1 - *it);
170 : }
171 : }
172 122 : return std::vector<Real>(levels_out.begin(), levels_out.end());
173 : }
|