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 14394 : ParsedConvergence::validParams()
19 : {
20 14394 : InputParameters params = Convergence::validParams();
21 14394 : params += FunctionParserUtils<false>::validParams();
22 :
23 14394 : params.addClassDescription("Evaluates convergence from a parsed expression.");
24 :
25 14394 : params.addRequiredCustomTypeParam<std::string>(
26 : "convergence_expression", "FunctionExpression", "Expression to parse for convergence");
27 14394 : params.addCustomTypeParam<std::string>(
28 : "divergence_expression", "FunctionExpression", "Expression to parse for divergence");
29 14394 : params.addParam<std::vector<std::string>>(
30 : "symbol_names", {}, "Symbol names to use in the parsed expressions");
31 14394 : 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 14394 : return params;
38 0 : }
39 :
40 69 : ParsedConvergence::ParsedConvergence(const InputParameters & parameters)
41 : : Convergence(parameters),
42 : FunctionParserUtils<false>(parameters),
43 69 : _fe_problem(*getCheckedPointerParam<FEProblemBase *>("_fe_problem_base")),
44 69 : _symbol_names(getParam<std::vector<std::string>>("symbol_names")),
45 69 : _symbol_values(getParam<std::vector<std::string>>("symbol_values")),
46 69 : _convergence_function_params(_symbol_names.size(), 0.0),
47 207 : _divergence_function_params(_symbol_names.size(), 0.0)
48 : {
49 69 : if (_symbol_names.size() != _symbol_values.size())
50 4 : mooseError("The parameters 'symbol_names' and 'symbol_values' must have the same size.");
51 65 : }
52 :
53 : void
54 65 : ParsedConvergence::initialSetup()
55 : {
56 65 : Convergence::initialSetup();
57 :
58 65 : initializeSymbols();
59 :
60 65 : const auto convergence_expression = getParam<std::string>("convergence_expression");
61 65 : _convergence_function = makeParsedFunction(convergence_expression);
62 :
63 130 : const auto divergence_expression = isParamValid("divergence_expression")
64 65 : ? getParam<std::string>("divergence_expression")
65 65 : : MooseUtils::join(_convergence_symbol_names, "|");
66 65 : if (divergence_expression.size())
67 65 : _divergence_function = makeParsedFunction(divergence_expression);
68 65 : }
69 :
70 : void
71 65 : ParsedConvergence::initializeSymbols()
72 : {
73 313 : for (const auto i : index_range(_symbol_values))
74 : {
75 248 : ReporterName reporter_name(_symbol_values[i], "value");
76 248 : if (_fe_problem.getReporterData().hasReporterValue<PostprocessorValue>(reporter_name))
77 65 : initializePostprocessorSymbol(i);
78 183 : else if (_fe_problem.hasFunction(_symbol_values[i]))
79 53 : initializeFunctionSymbol(i);
80 130 : else if (_fe_problem.hasConvergence(_symbol_values[i]))
81 77 : initializeConvergenceSymbol(i);
82 : else
83 53 : initializeConstantSymbol(i);
84 248 : }
85 65 : }
86 :
87 : void
88 65 : ParsedConvergence::initializePostprocessorSymbol(unsigned int i)
89 : {
90 65 : const PostprocessorValue & pp_value = _fe_problem.getPostprocessorValueByName(_symbol_values[i]);
91 65 : _pp_values.push_back(&pp_value);
92 65 : _pp_indices.push_back(i);
93 65 : }
94 :
95 : void
96 53 : ParsedConvergence::initializeFunctionSymbol(unsigned int i)
97 : {
98 53 : Function & function = _fe_problem.getFunction(_symbol_values[i], _tid);
99 53 : _functions.push_back(&function);
100 53 : _function_indices.push_back(i);
101 53 : }
102 :
103 : void
104 77 : ParsedConvergence::initializeConvergenceSymbol(unsigned int i)
105 : {
106 77 : Convergence & convergence = _fe_problem.getConvergence(_symbol_values[i], _tid);
107 77 : _convergences.push_back(&convergence);
108 77 : _convergence_symbol_names.push_back(_symbol_names[i]);
109 77 : _convergence_indices.push_back(i);
110 77 : }
111 :
112 : void
113 53 : ParsedConvergence::initializeConstantSymbol(unsigned int i)
114 : {
115 : try
116 : {
117 53 : const Real value = MooseUtils::convert<Real>(_symbol_values[i], true);
118 53 : _convergence_function_params[i] = value;
119 53 : _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 53 : }
130 :
131 : ParsedConvergence::SymFunctionPtr
132 130 : ParsedConvergence::makeParsedFunction(const std::string & expression)
133 : {
134 : // Create parsed function
135 130 : auto sym_function = std::make_shared<SymFunction>();
136 1300 : parsedFunctionSetup(sym_function,
137 : expression,
138 260 : Moose::stringify(_symbol_names),
139 : {"pi", "e"},
140 : {std::to_string(libMesh::pi), std::to_string(std::exp(Real(1)))},
141 : comm());
142 :
143 130 : return sym_function;
144 390 : }
145 :
146 : Convergence::MooseConvergenceStatus
147 954 : ParsedConvergence::checkConvergence(unsigned int iter)
148 : {
149 954 : updateSymbolValues(iter);
150 :
151 954 : const Real converged_real = evaluate(_convergence_function, _convergence_function_params, name());
152 : const Real diverged_real =
153 954 : _divergence_function ? evaluate(_divergence_function, _divergence_function_params, name())
154 954 : : 0;
155 :
156 954 : if (convertRealToBool(diverged_real, "divergence_expression"))
157 20 : return MooseConvergenceStatus::DIVERGED;
158 930 : else if (convertRealToBool(converged_real, "convergence_expression"))
159 110 : return MooseConvergenceStatus::CONVERGED;
160 : else
161 820 : return MooseConvergenceStatus::ITERATING;
162 : }
163 :
164 : void
165 954 : ParsedConvergence::updateSymbolValues(unsigned int iter)
166 : {
167 954 : updatePostprocessorSymbolValues();
168 954 : updateFunctionSymbolValues();
169 954 : updateConvergenceSymbolValues(iter);
170 954 : }
171 :
172 : void
173 954 : ParsedConvergence::updatePostprocessorSymbolValues()
174 : {
175 1908 : for (const auto i : index_range(_pp_indices))
176 : {
177 954 : _convergence_function_params[_pp_indices[i]] = (*_pp_values[i]);
178 954 : _divergence_function_params[_pp_indices[i]] = (*_pp_values[i]);
179 : }
180 954 : }
181 :
182 : void
183 954 : ParsedConvergence::updateFunctionSymbolValues()
184 : {
185 1072 : for (const auto i : index_range(_function_indices))
186 : {
187 118 : const Real function_value = _functions[i]->value(_t, Point(0, 0, 0));
188 118 : _convergence_function_params[_function_indices[i]] = function_value;
189 118 : _divergence_function_params[_function_indices[i]] = function_value;
190 : }
191 954 : }
192 :
193 : void
194 954 : ParsedConvergence::updateConvergenceSymbolValues(unsigned int iter)
195 : {
196 2744 : for (const auto i : index_range(_convergence_indices))
197 : {
198 1790 : const auto status = _convergences[i]->checkConvergence(iter);
199 1790 : _convergence_function_params[_convergence_indices[i]] =
200 : status == MooseConvergenceStatus::CONVERGED;
201 1790 : _divergence_function_params[_convergence_indices[i]] =
202 : status == MooseConvergenceStatus::DIVERGED;
203 : }
204 954 : }
205 :
206 : bool
207 1884 : ParsedConvergence::convertRealToBool(Real value, const std::string & param) const
208 : {
209 1884 : if (MooseUtils::absoluteFuzzyEqual(value, 1.0))
210 130 : return true;
211 1754 : else if (MooseUtils::absoluteFuzzyEqual(value, 0.0))
212 1750 : return false;
213 : else
214 4 : 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 : }
|