https://mooseframework.inl.gov
Loading...
Searching...
No Matches
SteffensenSolve.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 "SteffensenSolve.h"
11
12#include "Executioner.h"
13#include "FEProblemBase.h"
14#include "NonlinearSystem.h"
16#include "Console.h"
18
26
28
29void
31{
32 findTransformedSystem(primary);
33
34 TagID fxn_m1_tagid;
35 TagID xn_m1_tagid;
36 const std::vector<PostprocessorName> * transformed_pps;
37 std::vector<std::vector<PostprocessorValue>> * transformed_pps_values;
38 if (primary)
39 {
40 xn_m1_tagid = _problem.addVectorTag("xn_m1", Moose::VECTOR_TAG_SOLUTION);
41 fxn_m1_tagid = _problem.addVectorTag("fxn_m1", Moose::VECTOR_TAG_SOLUTION);
42 transformed_pps = &_transformed_pps;
43 transformed_pps_values = &_transformed_pps_values;
44 _xn_m1_tagid = xn_m1_tagid;
45 _fxn_m1_tagid = fxn_m1_tagid;
46 }
47 else
48 {
49 xn_m1_tagid = _problem.addVectorTag("secondary_xn_m1", Moose::VECTOR_TAG_SOLUTION);
50 fxn_m1_tagid = _problem.addVectorTag("secondary_fxn_m1", Moose::VECTOR_TAG_SOLUTION);
51 transformed_pps = &_secondary_transformed_pps;
52 transformed_pps_values = &_secondary_transformed_pps_values;
53 _secondary_xn_m1_tagid = xn_m1_tagid;
54 _secondary_fxn_m1_tagid = fxn_m1_tagid;
55 }
56
57 // Store a copy of the previous solution here
58 // If we don't have a transformed system, we are not accelerating variables
60 {
61 _transformed_sys->addVector(xn_m1_tagid, false, PARALLEL);
62 _transformed_sys->addVector(fxn_m1_tagid, false, PARALLEL);
63 }
64
65 // Allocate storage for the previous postprocessor values
66 (*transformed_pps_values).resize((*transformed_pps).size());
67 for (size_t i = 0; i < (*transformed_pps).size(); i++)
68 (*transformed_pps_values)[i].resize(2);
69}
70
71void
73{
75
77 if (!dynamic_cast<DefaultMultiAppFixedPointConvergence *>(&convergence))
79 "Only DefaultMultiAppFixedPointConvergence objects may be used for "
80 "'multiapp_fixed_point_convergence' when using the Steffensen fixed point algorithm.");
81}
82
83void
85{
86 unsigned int iteration;
87 TagID fxn_m1_tagid;
88 TagID xn_m1_tagid;
89 if (primary)
90 {
91 iteration = _fixed_point_it;
92 fxn_m1_tagid = _fxn_m1_tagid;
93 xn_m1_tagid = _xn_m1_tagid;
94 }
95 else
96 {
97 iteration = _main_fixed_point_it;
98 fxn_m1_tagid = _secondary_fxn_m1_tagid;
99 xn_m1_tagid = _secondary_xn_m1_tagid;
100 }
101
102 // Check to make sure allocateStorage has been called
103 mooseAssert(fxn_m1_tagid != Moose::INVALID_TAG_ID,
104 "allocateStorage has not been called with primary = " + Moose::stringify(primary));
105 mooseAssert(xn_m1_tagid != Moose::INVALID_TAG_ID,
106 "allocateStorage has not been called with primary = " + Moose::stringify(primary));
107
108 // Save previous variable values
109 NumericVector<Number> & solution = _transformed_sys->solution();
110 NumericVector<Number> & fxn_m1 = _transformed_sys->getVector(fxn_m1_tagid);
111 NumericVector<Number> & xn_m1 = _transformed_sys->getVector(xn_m1_tagid);
112
113 // What 'solution' is with regards to the Steffensen solve depends on the step
114 if (iteration % 2 == 1)
115 xn_m1 = solution;
116 else
117 fxn_m1 = solution;
118}
119
120void
122{
123 unsigned int iteration;
124 const std::vector<PostprocessorName> * transformed_pps;
125 std::vector<std::vector<PostprocessorValue>> * transformed_pps_values;
126 if (primary)
127 {
128 iteration = _fixed_point_it;
129 transformed_pps = &_transformed_pps;
130 transformed_pps_values = &_transformed_pps_values;
131 }
132 else
133 {
134 iteration = _main_fixed_point_it;
135 transformed_pps = &_secondary_transformed_pps;
136 transformed_pps_values = &_secondary_transformed_pps_values;
137 }
138
139 // Save previous postprocessor values
140 for (size_t i = 0; i < (*transformed_pps).size(); i++)
141 {
142 if (iteration % 2 == 0)
143 (*transformed_pps_values)[i][1] = getPostprocessorValueByName((*transformed_pps)[i]);
144 else
145 (*transformed_pps_values)[i][0] = getPostprocessorValueByName((*transformed_pps)[i]);
146 }
147}
148
149bool
151{
152 // Need at least two values to compute the Steffensen update, and the update is only performed
153 // every other iteration as two evaluations of the coupled problem are necessary
154 if (primary)
155 return _fixed_point_it > 1 && (_fixed_point_it % 2 == 0);
156 else
157 return _main_fixed_point_it > 1 && (_main_fixed_point_it % 2 == 0);
158}
159
160void
162{
163 Real relaxation_factor;
164 const std::vector<PostprocessorName> * transformed_pps;
165 std::vector<std::vector<PostprocessorValue>> * transformed_pps_values;
166 if (primary)
167 {
168 relaxation_factor = _relax_factor;
169 transformed_pps = &_transformed_pps;
170 transformed_pps_values = &_transformed_pps_values;
171 }
172 else
173 {
174 relaxation_factor = _secondary_relaxation_factor;
175 transformed_pps = &_secondary_transformed_pps;
176 transformed_pps_values = &_secondary_transformed_pps_values;
177 }
178
179 // Relax postprocessors for the main application
180 for (size_t i = 0; i < (*transformed_pps).size(); i++)
181 {
182 // Get new postprocessor value
183 const Real current_value = getPostprocessorValueByName((*transformed_pps)[i]);
184 const Real fxn_m1 = (*transformed_pps_values)[i][0];
185 const Real xn_m1 = (*transformed_pps_values)[i][1];
186
187 // Compute and set relaxed value
188 Real new_value = current_value;
189 if (!MooseUtils::absoluteFuzzyEqual(current_value + xn_m1 - 2 * fxn_m1, 0))
190 new_value =
191 xn_m1 - (fxn_m1 - xn_m1) * (fxn_m1 - xn_m1) / (current_value + xn_m1 - 2 * fxn_m1);
192
193 // Relax update
194 new_value = relaxation_factor * new_value + (1 - relaxation_factor) * fxn_m1;
195
196 _problem.setPostprocessorValueByName((*transformed_pps)[i], new_value);
197 }
198}
199
200void
201SteffensenSolve::transformVariables(const std::set<dof_id_type> & transformed_dofs,
202 const bool primary)
203{
204 Real relaxation_factor;
205 TagID fxn_m1_tagid;
206 TagID xn_m1_tagid;
207 if (primary)
208 {
209 relaxation_factor = _relax_factor;
210 fxn_m1_tagid = _fxn_m1_tagid;
211 xn_m1_tagid = _xn_m1_tagid;
212 }
213 else
214 {
215 relaxation_factor = _secondary_relaxation_factor;
216 fxn_m1_tagid = _secondary_fxn_m1_tagid;
217 xn_m1_tagid = _secondary_xn_m1_tagid;
218 }
219
220 NumericVector<Number> & solution = _transformed_sys->solution();
221 NumericVector<Number> & fxn_m1 = _transformed_sys->getVector(fxn_m1_tagid);
222 NumericVector<Number> & xn_m1 = _transformed_sys->getVector(xn_m1_tagid);
223
224 for (const auto & dof : transformed_dofs)
225 {
226 // Avoid 0 denominator issue
227 Real new_value = solution(dof);
228 if (!MooseUtils::absoluteFuzzyEqual(solution(dof) + xn_m1(dof) - 2 * fxn_m1(dof), 0))
229 new_value = xn_m1(dof) - (fxn_m1(dof) - xn_m1(dof)) * (fxn_m1(dof) - xn_m1(dof)) /
230 (solution(dof) + xn_m1(dof) - 2 * fxn_m1(dof));
231
232 // Relax update
233 new_value = relaxation_factor * new_value + (1 - relaxation_factor) * fxn_m1(dof);
234
235 solution.set(dof, new_value);
236 }
237 solution.close();
239}
240
241void
243 const Real initial_norm,
244 const std::vector<Real> & timestep_begin_norms,
245 const std::vector<Real> & timestep_end_norms) const
246{
247 _console << "\n 0 Steffensen initialization |R| = "
248 << Console::outputNorm(std::numeric_limits<Real>::max(), initial_norm) << '\n';
249
250 Real max_norm_old = initial_norm;
251 for (unsigned int i = 0; i <= _fixed_point_it; ++i)
252 {
253 Real max_norm = std::max(timestep_begin_norms[i], timestep_end_norms[i]);
254 std::stringstream steffensen_prefix;
255 if (i == 0)
256 steffensen_prefix << " Steffensen initialization |R| = ";
257 else if (i % 2 == 0)
258 steffensen_prefix << " Steffensen half-step |R| = ";
259 else
260 steffensen_prefix << " Steffensen step |R| = ";
261
262 _console << std::setw(2) << i + 1 << steffensen_prefix.str()
263 << Console::outputNorm(max_norm_old, max_norm) << '\n';
264
265 max_norm_old = max_norm;
266 }
267}
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application.
Definition MooseError.h:311
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
Default fixed point convergence criteria.
Executioners are objects that do the actual work of solving your problem.
Definition Executioner.h:37
virtual Convergence & getConvergence(const std::string &name, const THREAD_ID tid=0) const
Gets a Convergence object.
void setPostprocessorValueByName(const PostprocessorName &name, const PostprocessorValue &value, std::size_t t_index=0)
Set the value of a PostprocessorValue.
const ConvergenceName & getMultiAppFixedPointConvergenceName() const
Gets the MultiApp fixed point convergence object name.
virtual void initialSetup() override
Method that should be executed once, before any solve calls.
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.
FEProblemBase & _problem
Reference to FEProblem.
Definition SolveObject.h:47
virtual void transformPostprocessors(const bool primary) override final
Use the fixed point algorithm to transform the postprocessors.
virtual void savePostprocessorValues(const bool primary) override final
Saves the current values of the postprocessors, and update the old(er) vectors.
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.
TagID _fxn_m1_tagid
Vector tag id for the most recent solution variable, pre-Steffensen transform, as a main app.
TagID _secondary_xn_m1_tagid
Vector tag id for the solution variable before the latest solve, as a sub app.
TagID _secondary_fxn_m1_tagid
Vector tag id for the most recent solution variable, pre-Steffensen transform, as a sub app.
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.
TagID _xn_m1_tagid
Vector tag id for the solution variable before the latest solve, as a main app.
SteffensenSolve(Executioner &ex)
virtual bool useFixedPointAlgorithmUpdateInsteadOfPicard(const bool primary) override final
Use the fixed point algorithm transform instead of simply using the Picard update.
virtual void allocateStorage(const bool primary) override final
Allocate storage for the fixed point algorithm.
static InputParameters validParams()
virtual void initialSetup() override
Method that should be executed once, before any solve calls.
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
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
std::string stringify(const T &t)
conversion to string
Definition Conversion.h:64