https://mooseframework.inl.gov
Loading...
Searching...
No Matches
SecantSolve.C
Go to the documentation of this file.
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 "SecantSolve.h"
11
12#include "Executioner.h"
13#include "FEProblemBase.h"
14#include "NonlinearSystem.h"
16#include "Console.h"
17
20{
22
23 return params;
24}
25
27{
29 for (size_t i = 0; i < _transformed_pps.size(); i++)
30 _transformed_pps_values[i].resize(4);
32 for (size_t i = 0; i < _secondary_transformed_pps.size(); i++)
34}
35
36void
38{
39 findTransformedSystem(primary);
41 return;
42
43 // TODO: We would only need to store the solution for the degrees of freedom that
44 // will be transformed, not the entire solution.
45 // Store solution vectors for the two previous points and their evaluation
46 if (primary)
47 {
53
56 _transformed_sys->addVector(_fxn_m1_tagid, false, PARALLEL);
57 _transformed_sys->addVector(_xn_m2_tagid, false, PARALLEL);
58 _transformed_sys->addVector(_fxn_m2_tagid, false, PARALLEL);
59 }
60 else
61 {
66
71 }
72}
73
74void
76{
77 TagID fxn_m1_tagid;
78 TagID xn_m1_tagid;
79 TagID fxn_m2_tagid;
80 TagID xn_m2_tagid;
81 if (primary)
82 {
83 fxn_m1_tagid = _fxn_m1_tagid;
84 xn_m1_tagid = _xn_m1_tagid;
85 fxn_m2_tagid = _fxn_m2_tagid;
86 xn_m2_tagid = _xn_m2_tagid;
87 }
88 else
89 {
90 fxn_m1_tagid = _secondary_fxn_m1_tagid;
91 xn_m1_tagid = _secondary_xn_m1_tagid;
92 fxn_m2_tagid = _secondary_fxn_m2_tagid;
93 xn_m2_tagid = _secondary_xn_m2_tagid;
94 }
95
96 // Check to make sure allocateStorage has been called
97 mooseAssert(fxn_m1_tagid != Moose::INVALID_TAG_ID,
98 "allocateStorage has not been called with primary = " + Moose::stringify(primary));
99 mooseAssert(xn_m1_tagid != Moose::INVALID_TAG_ID,
100 "allocateStorage has not been called with primary = " + Moose::stringify(primary));
101 mooseAssert(fxn_m2_tagid != Moose::INVALID_TAG_ID,
102 "allocateStorage has not been called with primary = " + Moose::stringify(primary));
103 mooseAssert(xn_m2_tagid != Moose::INVALID_TAG_ID,
104 "allocateStorage has not been called with primary = " + Moose::stringify(primary));
105
106 // Save previous variable values
107 NumericVector<Number> & solution = _transformed_sys->solution();
108 NumericVector<Number> & fxn_m1 = _transformed_sys->getVector(fxn_m1_tagid);
109 NumericVector<Number> & xn_m1 = _transformed_sys->getVector(xn_m1_tagid);
110 NumericVector<Number> & fxn_m2 = _transformed_sys->getVector(fxn_m2_tagid);
111 NumericVector<Number> & xn_m2 = _transformed_sys->getVector(xn_m2_tagid);
112
113 // Advance one step
114 xn_m2 = xn_m1;
115
116 // Before a solve, solution is a sequence term, after a solve, solution is the evaluated term
117 // Primary is copied back by _transformed_sys->copyPreviousSolutions(MultiAppFixedPoint)
118 if (!primary)
119 xn_m1 = solution;
120
121 // Since we did not update on the 0th iteration, the solution is also the previous evaluated term
122 const unsigned int it = primary ? _fixed_point_it : _main_fixed_point_it;
123 if (it == 1)
124 fxn_m2 = solution;
125 // Otherwise we just advance
126 else
127 fxn_m2 = fxn_m1;
128}
129
130void
132{
133 const std::vector<PostprocessorName> * transformed_pps;
134 std::vector<std::vector<PostprocessorValue>> * transformed_pps_values;
135 if (primary)
136 {
137 transformed_pps = &_transformed_pps;
138 transformed_pps_values = &_transformed_pps_values;
139 }
140 else
141 {
142 transformed_pps = &_secondary_transformed_pps;
143 transformed_pps_values = &_secondary_transformed_pps_values;
144 }
145 const unsigned int it = primary ? _fixed_point_it : _main_fixed_point_it;
146
147 // Save previous postprocessor values
148 for (size_t i = 0; i < (*transformed_pps).size(); i++)
149 {
150 // Advance one step
151 (*transformed_pps_values)[i][3] = (*transformed_pps_values)[i][1];
152
153 // Save current value
154 // Primary: this is done before the timestep's solves and before timestep_begin transfers,
155 // so the value is the result of the previous Secant update (xn_m1)
156 // Secondary: this is done after the secondary solve, but before timestep_end postprocessors
157 // are computed, or timestep_end transfers are received.
158 // This value is the same as before the solve (xn_m1)
159 (*transformed_pps_values)[i][1] = getPostprocessorValueByName((*transformed_pps)[i]);
160
161 // Since we did not update on the 1st iteration, the pp is also the previous evaluated term
162 if (it == 2)
163 (*transformed_pps_values)[i][2] = (*transformed_pps_values)[i][1];
164 // Otherwise we just advance
165 else
166 (*transformed_pps_values)[i][2] = (*transformed_pps_values)[i][0];
167 }
168}
169
170bool
172{
173 // Need at least two evaluations to compute the Secant slope
174 if (primary)
175 return _fixed_point_it > 0;
176 else
177 return _main_fixed_point_it > 0;
178}
179
180void
182{
183 if ((primary ? _fixed_point_it : _main_fixed_point_it) < 2)
184 return;
185
186 Real relaxation_factor;
187 const std::vector<PostprocessorName> * transformed_pps;
188 std::vector<std::vector<PostprocessorValue>> * transformed_pps_values;
189 if (primary)
190 {
191 relaxation_factor = _relax_factor;
192 transformed_pps = &_transformed_pps;
193 transformed_pps_values = &_transformed_pps_values;
194 }
195 else
196 {
197 relaxation_factor = _secondary_relaxation_factor;
198 transformed_pps = &_secondary_transformed_pps;
199 transformed_pps_values = &_secondary_transformed_pps_values;
200 }
201
202 // Relax postprocessors for the main application
203 for (size_t i = 0; i < (*transformed_pps).size(); i++)
204 {
205 // Get new postprocessor value
206 const Real fxn_m1 = getPostprocessorValueByName((*transformed_pps)[i]);
207 const Real xn_m1 = (*transformed_pps_values)[i][1];
208 const Real fxn_m2 = (*transformed_pps_values)[i][2];
209 const Real xn_m2 = (*transformed_pps_values)[i][3];
210
211 // Save fxn_m1, received or computed before the solve
212 (*transformed_pps_values)[i][0] = fxn_m1;
213
214 // Compute and set relaxed value
215 Real new_value = fxn_m1;
216 if (!MooseUtils::absoluteFuzzyEqual(fxn_m1 - xn_m1 - fxn_m2 + xn_m2, 0))
217 new_value = xn_m1 - (fxn_m1 - xn_m1) * (xn_m1 - xn_m2) / (fxn_m1 - xn_m1 - fxn_m2 + xn_m2);
218
219 // Relax update if desired
220 new_value = relaxation_factor * new_value + (1 - relaxation_factor) * xn_m1;
221
222 _problem.setPostprocessorValueByName((*transformed_pps)[i], new_value);
223 }
224}
225
226void
227SecantSolve::transformVariables(const std::set<dof_id_type> & target_dofs, const bool primary)
228{
229 Real relaxation_factor;
230 TagID fxn_m1_tagid;
231 TagID xn_m1_tagid;
232 TagID fxn_m2_tagid;
233 TagID xn_m2_tagid;
234 if (primary)
235 {
236 relaxation_factor = _relax_factor;
237 fxn_m1_tagid = _fxn_m1_tagid;
238 xn_m1_tagid = _xn_m1_tagid;
239 fxn_m2_tagid = _fxn_m2_tagid;
240 xn_m2_tagid = _xn_m2_tagid;
241 }
242 else
243 {
244 relaxation_factor = _secondary_relaxation_factor;
245 fxn_m1_tagid = _secondary_fxn_m1_tagid;
246 xn_m1_tagid = _secondary_xn_m1_tagid;
247 fxn_m2_tagid = _secondary_fxn_m2_tagid;
248 xn_m2_tagid = _secondary_xn_m2_tagid;
249 }
250
251 NumericVector<Number> & solution = _transformed_sys->solution();
252 NumericVector<Number> & xn_m1 = _transformed_sys->getVector(xn_m1_tagid);
253 NumericVector<Number> & fxn_m2 = _transformed_sys->getVector(fxn_m2_tagid);
254 NumericVector<Number> & xn_m2 = _transformed_sys->getVector(xn_m2_tagid);
255
256 // Save the most recent evaluation of the coupled problem
257 NumericVector<Number> & fxn_m1 = _transformed_sys->getVector(fxn_m1_tagid);
258 fxn_m1 = solution;
259
260 for (const auto & dof : target_dofs)
261 {
262 // Avoid 0 denominator issue
263 Real new_value = fxn_m1(dof);
264 if (!MooseUtils::absoluteFuzzyEqual(solution(dof) - xn_m1(dof) - fxn_m2(dof) + xn_m2(dof), 0))
265 new_value = xn_m1(dof) - (solution(dof) - xn_m1(dof)) * (xn_m1(dof) - xn_m2(dof)) /
266 (solution(dof) - xn_m1(dof) - fxn_m2(dof) + xn_m2(dof));
267
268 // Relax update
269 new_value = relaxation_factor * new_value + (1 - relaxation_factor) * xn_m1(dof);
270
271 solution.set(dof, new_value);
272 }
273 solution.close();
275}
276
277void
279 const std::vector<Real> & timestep_begin_norms,
280 const std::vector<Real> & timestep_end_norms) const
281{
282 _console << "\n 0 Secant initialization |R| = "
283 << Console::outputNorm(std::numeric_limits<Real>::max(), initial_norm) << '\n';
284
285 Real max_norm_old = initial_norm;
286 for (unsigned int i = 0; i <= _fixed_point_it; ++i)
287 {
288 Real max_norm = std::max(timestep_begin_norms[i], timestep_end_norms[i]);
289 std::stringstream secant_prefix;
290 if (i < 1)
291 secant_prefix << " Secant initialization |R| = ";
292 else
293 secant_prefix << " Secant step |R| = ";
294
295 _console << std::setw(2) << i + 1 << secant_prefix.str()
296 << Console::outputNorm(max_norm_old, max_norm) << '\n';
297 max_norm_old = max_norm;
298 }
299}
unsigned int TagID
Definition MooseTypes.h:238
const ConsoleStream _console
An instance of helper class to write streams to the Console objects.
static std::string outputNorm(const Real &old_norm, const Real &norm, const unsigned int precision=6)
A helper function for outputting norms in color.
Definition Console.C:619
Executioners are objects that do the actual work of solving your problem.
Definition Executioner.h:37
void setPostprocessorValueByName(const PostprocessorName &name, const PostprocessorValue &value, std::size_t t_index=0)
Set the value of a PostprocessorValue.
unsigned int _main_fixed_point_it
Current fixed point iteration index for the main app; 0 for the first iteration.
Real _secondary_relaxation_factor
Relaxation factor outside of fixed point iteration (used as a subapp)
const Real _relax_factor
Relaxation factor for fixed point Iteration.
static InputParameters validParams()
std::vector< std::vector< PostprocessorValue > > _transformed_pps_values
Previous values of the relaxed postprocessors.
std::vector< std::vector< PostprocessorValue > > _secondary_transformed_pps_values
Previous values of the postprocessors relaxed outside of the fixed point iteration (used as a subapp)
const std::vector< PostprocessorName > _transformed_pps
The postprocessors (transferred or not) that are going to be relaxed.
std::vector< PostprocessorName > _secondary_transformed_pps
Postprocessors to be relaxed outside of fixed point iteration (used as a subapp)
unsigned int _fixed_point_it
void findTransformedSystem(const bool primary)
Find the system holding the variables to be transformed (accelerated or relaxed)
SystemBase * _transformed_sys
System holding the transformed variables.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system.
virtual const PostprocessorValue & getPostprocessorValueByName(const PostprocessorName &name) const
Retrieve the value of the Postprocessor.
virtual void savePostprocessorValues(const bool primary) override final
Saves the current values of the postprocessors, and update the old(er) vectors.
TagID _xn_m1_tagid
Vector tag id for the solution variable before the latest solve, as a main app.
Definition SecantSolve.h:88
TagID _secondary_xn_m1_tagid
Vector tag id for the solution variable before the latest solve, as a sub app.
virtual void transformPostprocessors(const bool primary) override final
Use the fixed point algorithm to transform the postprocessors.
TagID _xn_m2_tagid
Vector tag id for the solution variable two solves ago, as a main app.
Definition SecantSolve.h:94
virtual void allocateStorage(const bool primary) override final
Allocate storage for the fixed point algorithm.
Definition SecantSolve.C:37
TagID _secondary_fxn_m1_tagid
Vector tag id for the most recent solution variable, pre-Secant transform, as a sub app.
Definition SecantSolve.h:97
virtual void transformVariables(const std::set< dof_id_type > &transformed_dofs, const bool primary) override final
Use the fixed point algorithm to transform the variables.
virtual bool useFixedPointAlgorithmUpdateInsteadOfPicard(const bool primary) override final
Use the fixed point algorithm transform instead of simply using the Picard update.
TagID _fxn_m1_tagid
Vector tag id for the most recent solution variable, pre-Secant transform, as a main app.
Definition SecantSolve.h:85
static InputParameters validParams()
Definition SecantSolve.C:19
TagID _secondary_xn_m2_tagid
Vector tag id for the solution variable two primary solves ago, as a sub app.
SecantSolve(Executioner &ex)
Definition SecantSolve.C:26
TagID _fxn_m2_tagid
Vector tag id for the result of the last but one solve, as a main app.
Definition SecantSolve.h:91
virtual void printFixedPointConvergenceHistory(Real initial_norm, const std::vector< Real > &timestep_begin_norms, const std::vector< Real > &timestep_end_norms) const override final
Print the convergence history of the coupling, at every fixed point iteration.
virtual void saveVariableValues(const bool primary) override final
Saves the current values of the variables, and update the old(er) vectors.
Definition SecantSolve.C:75
TagID _secondary_fxn_m2_tagid
Vector tag id for the result of the last but one secondary solve, as a sub app.
FEProblemBase & _problem
Reference to FEProblem.
Definition SolveObject.h:47
virtual TagID addVectorTag(const TagName &tag_name, const Moose::VectorTagType type=Moose::VECTOR_TAG_RESIDUAL)
Create a Tag.
Definition SubProblem.C:93
virtual NumericVector< Number > & getVector(const std::string &name)
Get a raw NumericVector by name.
Definition SystemBase.C:932
virtual void needSolutionState(const unsigned int state, Moose::SolutionIterationType iteration_type=Moose::SolutionIterationType::Time, libMesh::ParallelType parallel_type=GHOSTED)
Registers that the solution state state is needed.
NumericVector< Number > & solution()
Definition SystemBase.h:203
NumericVector< Number > & addVector(const std::string &vector_name, const bool project, const libMesh::ParallelType type)
Adds a solution length vector to the system.
Definition SystemBase.C:607
void update()
Update the system (doing libMesh magic)
const TagID INVALID_TAG_ID
Definition MooseTypes.C:23
@ VECTOR_TAG_SOLUTION
const TagName PREVIOUS_MULTIAPP_FP_SOLUTION_TAG
Definition MooseTypes.C:29
std::string stringify(const T &t)
conversion to string
Definition Conversion.h:64