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