deal.II version GIT relicensing-6842-g793a97d2aa 2026-10-02 14:00:01+00:00
\(\newcommand{\dealvcentcolon}{\mathrel{\mathop{:}}}\) \(\newcommand{\dealcoloneq}{\dealvcentcolon\mathrel{\mkern-1.2mu}=}\) \(\newcommand{\jump}[1]{\left[\!\left[ #1 \right]\!\right]}\) \(\newcommand{\average}[1]{\left\{\!\left\{ #1 \right\}\!\right\}}\)
Loading...
Searching...
No Matches
solver_fire.h
Go to the documentation of this file.
1// -----------------------------------------------------------------------------
2//
3// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception OR LGPL-2.1-or-later
4// Copyright (C) 2017 - 2026 by the deal.II authors
5//
6// This file is part of the deal.II library.
7//
8// Detailed license information governing the source code and contributions
9// can be found in LICENSE.md and CONTRIBUTING.md at the top level directory.
10//
11// -----------------------------------------------------------------------------
12
13#ifndef dealii_solver_fire_h
14#define dealii_solver_fire_h
15
16
17#include <deal.II/base/config.h>
18
21
23#include <deal.II/lac/solver.h>
24
25#include <functional>
26
27
29
30
88template <typename VectorType = Vector<double>>
90class SolverFIRE : public SolverBase<VectorType>
91{
92public:
97 {
103 explicit AdditionalData(const double initial_timestep = 0.1,
104 const double maximum_timestep = 1,
105 const double maximum_linfty_norm = 1);
106
110 const double initial_timestep;
111
115 const double maximum_timestep;
116
121 };
122
126 SolverFIRE(SolverControl &solver_control,
127 VectorMemory<VectorType> &vector_memory,
129
134 SolverFIRE(SolverControl &solver_control,
136
146 template <typename PreconditionerType = DiagonalMatrix<VectorType>>
147 void
148 solve(const std::function<double(VectorType &, const VectorType &)> &compute,
149 VectorType &x,
150 const PreconditionerType &inverse_mass_matrix);
151
157 template <typename MatrixType, typename PreconditionerType>
161 void solve(const MatrixType &A,
162 VectorType &x,
163 const VectorType &b,
164 const PreconditionerType &preconditioner);
165
166protected:
173 virtual void
174 print_vectors(const unsigned int,
175 const VectorType &x,
176 const VectorType &v,
177 const VectorType &g) const;
178
182 const AdditionalData additional_data;
183};
184
187/*------------------------- Implementation ----------------------------*/
188
189#ifndef DOXYGEN
190
191template <typename VectorType>
194 const double initial_timestep,
195 const double maximum_timestep,
196 const double maximum_linfty_norm)
197 : initial_timestep(initial_timestep)
198 , maximum_timestep(maximum_timestep)
199 , maximum_linfty_norm(maximum_linfty_norm)
200{
201 AssertThrow(initial_timestep > 0. && maximum_timestep > 0. &&
202 maximum_linfty_norm > 0.,
203 ExcMessage("Expected positive values for initial_timestep, "
204 "maximum_timestep and maximum_linfty_norm but one "
205 "or more of the these values are not positive."));
206}
207
208
209
210template <typename VectorType>
213 VectorMemory<VectorType> &vector_memory,
214 const AdditionalData &data)
215 : SolverBase<VectorType>(solver_control, vector_memory)
216 , additional_data(data)
217{}
218
219
220
221template <typename VectorType>
224 const AdditionalData &data)
225 : SolverBase<VectorType>(solver_control)
226 , additional_data(data)
227{}
228
229
230
231template <typename VectorType>
233template <typename PreconditionerType>
235 const std::function<double(VectorType &, const VectorType &)> &compute,
236 VectorType &x,
237 const PreconditionerType &inverse_mass_matrix)
238{
239 LogStream::Prefix prefix("FIRE");
240
241 // FIRE algorithm constants
242 const double DELAYSTEP = 5;
243 const double TIMESTEP_GROW = 1.1;
244 const double TIMESTEP_SHRINK = 0.5;
245 const double ALPHA_0 = 0.1;
246 const double ALPHA_SHRINK = 0.99;
247
248 using real_type = typename VectorType::real_type;
249
250 typename VectorMemory<VectorType>::Pointer v(this->memory);
251 typename VectorMemory<VectorType>::Pointer g(this->memory);
252
253 // Set velocities to zero but not gradients
254 // as we are going to compute them soon.
255 v->reinit(x, false);
256 g->reinit(x, true);
257
258 // Refer to v and g with some readable names.
259 VectorType &velocities = *v;
260 VectorType &gradients = *g;
261
262 // Update gradients for the new x.
263 compute(gradients, x);
264
265 unsigned int iter = 0;
266
268 conv = this->iteration_status(iter, gradients * gradients, x);
269 if (conv != SolverControl::iterate)
270 return;
271
272 // Refer to additional data members with some readable names.
273 const auto &maximum_timestep = additional_data.maximum_timestep;
274 double timestep = additional_data.initial_timestep;
275
276 // First scaling factor.
277 double alpha = ALPHA_0;
278
279 unsigned int previous_iter_with_positive_v_dot_g = 0;
280
281 while (conv == SolverControl::iterate)
282 {
283 ++iter;
284 // Euler integration step.
285 x.add(timestep, velocities); // x += dt * v
286 inverse_mass_matrix.vmult(gradients, gradients); // g = M^{-1} * g
287 velocities.add(-timestep, gradients); // v -= dt * h
288
289 // Compute gradients for the new x.
290 compute(gradients, x);
291
292 const real_type gradient_norm_squared = gradients * gradients;
293 conv = this->iteration_status(iter, gradient_norm_squared, x);
294 if (conv != SolverControl::iterate)
295 break;
296
297 // v_dot_g = V * G
298 const real_type v_dot_g = velocities * gradients;
299
300 if (v_dot_g < 0.)
301 {
302 const real_type velocities_norm_squared = velocities * velocities;
303
304 // Check if we divide by zero in DEBUG mode.
305 Assert(gradient_norm_squared > 0., ExcInternalError());
306
307 // beta = - alpha |V|/|G|
308 const real_type beta =
309 -alpha * std::sqrt(velocities_norm_squared / gradient_norm_squared);
310
311 // V = (1-alpha) V + beta G.
312 velocities.sadd(1. - alpha, beta, gradients);
313
314 if (iter - previous_iter_with_positive_v_dot_g > DELAYSTEP)
315 {
316 // Increase timestep and decrease alpha.
317 timestep = std::min(timestep * TIMESTEP_GROW, maximum_timestep);
318 alpha *= ALPHA_SHRINK;
319 }
320 }
321 else
322 {
323 // Decrease timestep, reset alpha and set V = 0.
324 previous_iter_with_positive_v_dot_g = iter;
325 timestep *= TIMESTEP_SHRINK;
326 alpha = ALPHA_0;
327 velocities = 0.;
328 }
329
330 real_type vmax = velocities.linfty_norm();
331
332 // Change timestep if any dof would move more than maximum_linfty_norm.
333 if (vmax > 0.)
334 {
335 const double minimal_timestep =
336 additional_data.maximum_linfty_norm / vmax;
337 if (minimal_timestep < timestep)
338 timestep = minimal_timestep;
339 }
340
341 print_vectors(iter, x, velocities, gradients);
342
343 } // While we need to iterate.
344
345 // In the case of failure: throw exception.
346 if (conv != SolverControl::success)
347 AssertThrow(false,
348 SolverControl::NoConvergence(iter, gradients * gradients));
349}
350
351
352
353template <typename VectorType>
355template <typename MatrixType, typename PreconditionerType>
359void SolverFIRE<VectorType>::solve(const MatrixType &A,
360 VectorType &x,
361 const VectorType &b,
362 const PreconditionerType &preconditioner)
363{
364 std::function<double(VectorType &, const VectorType &)> compute_func =
365 [&](VectorType &g, const VectorType &x) -> double {
366 // The residual of the quadratic form @f$ \frac{1}{2} xAx - xb @f$ is
367 // g = b - Ax, but at the end of the day we need g = Ax -b:
368 A.vmult(g, x);
369 g -= b;
370
371 // The quadratic form @f$\frac{1}{2} xAx - xb @f$.
372 return 0.5 * A.matrix_norm_square(x) - x * b;
373 };
374
375 this->solve(compute_func, x, preconditioner);
376}
377
378
379
380template <typename VectorType>
382void SolverFIRE<VectorType>::print_vectors(const unsigned int,
383 const VectorType &,
384 const VectorType &,
385 const VectorType &) const
386{}
387
388
389
390#endif // DOXYGEN
391
393
394#endif
@ iterate
Continue iteration.
@ success
Stop iteration, goal reached.
SolverFIRE(SolverControl &solver_control, VectorMemory< VectorType > &vector_memory, const AdditionalData &data=AdditionalData())
virtual void print_vectors(const unsigned int, const VectorType &x, const VectorType &v, const VectorType &g) const
SolverFIRE(SolverControl &solver_control, const AdditionalData &data=AdditionalData())
void solve(const std::function< double(VectorType &, const VectorType &)> &compute, VectorType &x, const PreconditionerType &inverse_mass_matrix)
#define DEAL_II_NAMESPACE_OPEN
Definition config.h:38
#define DEAL_II_CXX20_REQUIRES(condition)
Definition config.h:249
#define DEAL_II_NAMESPACE_CLOSE
Definition config.h:39
#define Assert(cond, exc)
static ::ExceptionBase & ExcInternalError()
static ::ExceptionBase & ExcMessage(std::string arg1)
#define AssertThrow(cond, exc)
std::vector< index_type > data
Definition mpi.cc:734
constexpr char A
Tpetra::Vector< Number, LO, GO, NodeType< MemorySpace > > VectorType
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
::VectorizedArray< Number, width > min(const ::VectorizedArray< Number, width > &, const ::VectorizedArray< Number, width > &)
::VectorizedArray< Number, width > sqrt(const ::VectorizedArray< Number, width > &)
const double maximum_linfty_norm
AdditionalData(const double initial_timestep=0.1, const double maximum_timestep=1, const double maximum_linfty_norm=1)