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 "ParsedConvergence.h"
11 : #include "MooseUtils.h"
12 : #include "Function.h"
13 : #include "FEProblemBase.h"
14 :
15 : registerMooseObject("MooseApp", ParsedConvergence);
16 :
17 : InputParameters
18 3206 : ParsedConvergence::validParams()
19 : {
20 3206 : InputParameters params = Convergence::validParams();
21 3206 : params += FunctionParserUtils<false>::validParams();
22 :
23 6412 : params.addClassDescription("Evaluates convergence from a parsed expression.");
24 :
25 19236 : params.addRequiredCustomTypeParam<std::string>(
26 : "convergence_expression", "FunctionExpression", "Expression to parse for convergence");
27 19236 : params.addCustomTypeParam<std::string>(
28 : "divergence_expression", "FunctionExpression", "Expression to parse for divergence");
29 12824 : params.addParam<std::vector<std::string>>(
30 : "symbol_names", {}, "Symbol names to use in the parsed expressions");
31 9618 : params.addParam<std::vector<std::string>>(
32 : "symbol_values",
33 : {},
34 : "Values (Convergence names, Postprocessor names, Function names, and constants) "
35 : "corresponding to each entry in 'symbol_names'");
36 :
37 3206 : return params;
38 0 : }
39 :
40 77 : ParsedConvergence::ParsedConvergence(const InputParameters & parameters)
41 : : Convergence(parameters),
42 : FunctionParserUtils<false>(parameters),
43 231 : _fe_problem(*getCheckedPointerParam<FEProblemBase *>("_fe_problem_base")),
44 154 : _symbol_names(getParam<std::vector<std::string>>("symbol_names")),
45 154 : _symbol_values(getParam<std::vector<std::string>>("symbol_values")),
46 154 : _convergence_function_params(_symbol_names.size(), 0.0),
47 308 : _divergence_function_params(_symbol_names.size(), 0.0)
48 : {
49 77 : if (_symbol_names.size() != _symbol_values.size())
50 3 : mooseError("The parameters 'symbol_names' and 'symbol_values' must have the same size.");
51 74 : }
52 :
53 : void
54 74 : ParsedConvergence::initialSetup()
55 : {
56 74 : Convergence::initialSetup();
57 :
58 74 : initializeSymbols();
59 :
60 148 : const auto convergence_expression = getParam<std::string>("convergence_expression");
61 74 : _convergence_function = makeParsedFunction(convergence_expression);
62 :
63 148 : const auto divergence_expression = isParamValid("divergence_expression")
64 74 : ? getParam<std::string>("divergence_expression")
65 222 : : MooseUtils::join(_convergence_symbol_names, "|");
66 74 : if (divergence_expression.size())
67 74 : _divergence_function = makeParsedFunction(divergence_expression);
68 74 : }
69 :
70 : void
71 74 : ParsedConvergence::initializeSymbols()
72 : {
73 333 : for (const auto i : index_range(_symbol_values))
74 : {
75 259 : ReporterName reporter_name(_symbol_values[i], "value");
76 259 : if (_fe_problem.getReporterData().hasReporterValue<PostprocessorValue>(reporter_name))
77 61 : initializePostprocessorSymbol(i);
78 198 : else if (_fe_problem.hasFunction(_symbol_values[i]))
79 50 : initializeFunctionSymbol(i);
80 148 : else if (_fe_problem.hasConvergence(_symbol_values[i]))
81 98 : initializeConvergenceSymbol(i);
82 : else
83 50 : initializeConstantSymbol(i);
84 259 : }
85 74 : }
86 :
87 : void
88 61 : ParsedConvergence::initializePostprocessorSymbol(unsigned int i)
89 : {
90 61 : const PostprocessorValue & pp_value = _fe_problem.getPostprocessorValueByName(_symbol_values[i]);
91 61 : _pp_values.push_back(&pp_value);
92 61 : _pp_indices.push_back(i);
93 61 : }
94 :
95 : void
96 50 : ParsedConvergence::initializeFunctionSymbol(unsigned int i)
97 : {
98 50 : Function & function = _fe_problem.getFunction(_symbol_values[i], _tid);
99 50 : _functions.push_back(&function);
100 50 : _function_indices.push_back(i);
101 50 : }
102 :
103 : void
104 98 : ParsedConvergence::initializeConvergenceSymbol(unsigned int i)
105 : {
106 98 : Convergence & convergence = _fe_problem.getConvergence(_symbol_values[i], _tid);
107 98 : _convergences.push_back(&convergence);
108 98 : _convergence_symbol_names.push_back(_symbol_names[i]);
109 98 : _convergence_indices.push_back(i);
110 98 : }
111 :
112 : void
113 50 : ParsedConvergence::initializeConstantSymbol(unsigned int i)
114 : {
115 : try
116 : {
117 50 : const Real value = MooseUtils::convert<Real>(_symbol_values[i], true);
118 50 : _convergence_function_params[i] = value;
119 50 : _divergence_function_params[i] = value;
120 : }
121 0 : catch (const std::invalid_argument & e)
122 : {
123 0 : mooseError(
124 : "The 'symbol_values' entry '",
125 0 : _symbol_values[i],
126 : "' is not a constant value or the name of a Convergence, Postprocessor, or Function.",
127 0 : e.what());
128 0 : }
129 50 : }
130 :
131 : ParsedConvergence::SymFunctionPtr
132 148 : ParsedConvergence::makeParsedFunction(const std::string & expression)
133 : {
134 : // Create parsed function
135 148 : auto sym_function = std::make_shared<SymFunction>();
136 1184 : parsedFunctionSetup(sym_function,
137 : expression,
138 740 : Moose::stringify(_symbol_names),
139 : {"pi", "e"},
140 : {std::to_string(libMesh::pi), std::to_string(std::exp(Real(1)))},
141 : comm());
142 :
143 148 : return sym_function;
144 148 : }
145 :
146 : Convergence::MooseConvergenceStatus
147 918 : ParsedConvergence::checkConvergence(unsigned int iter)
148 : {
149 918 : updateSymbolValues(iter);
150 :
151 918 : const Real converged_real = evaluate(_convergence_function, _convergence_function_params, name());
152 : const Real diverged_real =
153 918 : _divergence_function ? evaluate(_divergence_function, _divergence_function_params, name())
154 918 : : 0;
155 :
156 1833 : if (convertRealToBool(diverged_real, "divergence_expression"))
157 18 : return MooseConvergenceStatus::DIVERGED;
158 1794 : else if (convertRealToBool(converged_real, "convergence_expression"))
159 114 : return MooseConvergenceStatus::CONVERGED;
160 : else
161 783 : return MooseConvergenceStatus::ITERATING;
162 : }
163 :
164 : void
165 918 : ParsedConvergence::updateSymbolValues(unsigned int iter)
166 : {
167 918 : updatePostprocessorSymbolValues();
168 918 : updateFunctionSymbolValues();
169 918 : updateConvergenceSymbolValues(iter);
170 918 : }
171 :
172 : void
173 918 : ParsedConvergence::updatePostprocessorSymbolValues()
174 : {
175 1802 : for (const auto i : index_range(_pp_indices))
176 : {
177 884 : _convergence_function_params[_pp_indices[i]] = (*_pp_values[i]);
178 884 : _divergence_function_params[_pp_indices[i]] = (*_pp_values[i]);
179 : }
180 918 : }
181 :
182 : void
183 918 : ParsedConvergence::updateFunctionSymbolValues()
184 : {
185 1028 : for (const auto i : index_range(_function_indices))
186 : {
187 110 : const Real function_value = _functions[i]->value(_t, Point(0, 0, 0));
188 110 : _convergence_function_params[_function_indices[i]] = function_value;
189 110 : _divergence_function_params[_function_indices[i]] = function_value;
190 : }
191 918 : }
192 :
193 : void
194 918 : ParsedConvergence::updateConvergenceSymbolValues(unsigned int iter)
195 : {
196 2644 : for (const auto i : index_range(_convergence_indices))
197 : {
198 1726 : const auto status = _convergences[i]->checkConvergence(iter);
199 1726 : _convergence_function_params[_convergence_indices[i]] =
200 : status == MooseConvergenceStatus::CONVERGED;
201 1726 : _divergence_function_params[_convergence_indices[i]] =
202 : status == MooseConvergenceStatus::DIVERGED;
203 : }
204 918 : }
205 :
206 : bool
207 1815 : ParsedConvergence::convertRealToBool(Real value, const std::string & param) const
208 : {
209 1815 : if (MooseUtils::absoluteFuzzyEqual(value, 1.0))
210 132 : return true;
211 1683 : else if (MooseUtils::absoluteFuzzyEqual(value, 0.0))
212 1680 : return false;
213 : else
214 3 : mooseError("The expression parameter '",
215 : param,
216 : "' evaluated to the value ",
217 : value,
218 : ", but it must only evaluate to either 0 or 1.");
219 : }
|