Reference documentation for deal.II version 9.0.0
solver_fire.h
1 // ---------------------------------------------------------------------
2 //
3 // Copyright (C) 1998 - 2017 by the deal.II authors
4 //
5 // This file is part of the deal.II library.
6 //
7 // The deal.II library is free software; you can use it, redistribute
8 // it, and/or modify it under the terms of the GNU Lesser General
9 // Public License as published by the Free Software Foundation; either
10 // version 2.1 of the License, or (at your option) any later version.
11 // The full text of the license can be found in the file LICENSE at
12 // the top level of the deal.II distribution.
13 //
14 // ---------------------------------------------------------------------
15 
16 #ifndef dealii_solver_fire_h
17 #define dealii_solver_fire_h
18 
19 
20 #include <deal.II/base/config.h>
21 #include <deal.II/base/logstream.h>
22 #include <deal.II/lac/diagonal_matrix.h>
23 #include <deal.II/lac/solver.h>
24 
25 #include <functional>
26 
27 
28 DEAL_II_NAMESPACE_OPEN
29 
30 
33 
88 template <typename VectorType = Vector<double> >
89 class SolverFIRE : public Solver<VectorType>
90 {
91 
92 public:
93 
98  {
104  explicit
105  AdditionalData (const double initial_timestep = 0.1,
106  const double maximum_timestep = 1,
107  const double maximum_linfty_norm = 1);
108 
112  const double initial_timestep;
113 
117  const double maximum_timestep;
118 
122  const double maximum_linfty_norm;
123 
124  };
125 
129  SolverFIRE (SolverControl &solver_control,
130  VectorMemory<VectorType> &vector_memory,
131  const AdditionalData &data = AdditionalData());
132 
137  SolverFIRE (SolverControl &solver_control,
138  const AdditionalData &data );
139 
143  virtual ~SolverFIRE();
144 
154  template <typename PreconditionerType = DiagonalMatrix<VectorType>>
155  void solve
156  (const std::function<double(VectorType &, const VectorType &)> &compute,
157  VectorType &x,
158  const PreconditionerType &inverse_mass_matrix);
159 
165  template <typename MatrixType, typename PreconditionerType>
166  void solve (const MatrixType &A,
167  VectorType &x,
168  const VectorType &b,
169  const PreconditionerType &preconditioner);
170 
171 protected:
172 
179  virtual void print_vectors (const unsigned int,
180  const VectorType &x,
181  const VectorType &v,
182  const VectorType &g) const;
183 
188 
189 };
190 
193 /*------------------------- Implementation ----------------------------*/
194 
195 #ifndef DOXYGEN
196 
197 template <typename VectorType>
199 AdditionalData (const double initial_timestep,
200  const double maximum_timestep,
201  const double maximum_linfty_norm)
202  :
203  initial_timestep(initial_timestep),
204  maximum_timestep(maximum_timestep),
205  maximum_linfty_norm(maximum_linfty_norm)
206 {
207  AssertThrow (initial_timestep > 0. &&
208  maximum_timestep > 0. &&
209  maximum_linfty_norm > 0.,
210  ExcMessage("Expected positive values for initial_timestep, "
211  "maximum_timestep and maximum_linfty_norm but one "
212  "or more of the these values are not positive."));
213 }
214 
215 
216 
217 template <typename VectorType>
219 SolverFIRE (SolverControl &solver_control,
220  VectorMemory<VectorType> &vector_memory,
221  const AdditionalData &data )
222  :
223  Solver<VectorType>(solver_control, vector_memory),
224  additional_data(data)
225 {}
226 
227 
228 
229 template <typename VectorType>
231 SolverFIRE (SolverControl &solver_control,
232  const AdditionalData &data )
233  :
234  Solver<VectorType>(solver_control),
235  additional_data(data)
236 {}
237 
238 
239 
240 template <typename VectorType>
242 {}
243 
244 
245 
246 template <typename VectorType>
247 template <typename PreconditionerType>
248 void
250 (const std::function<double(VectorType &, const VectorType &)> &compute,
251  VectorType &x,
252  const PreconditionerType &inverse_mass_matrix)
253 {
254  LogStream::Prefix prefix("FIRE");
255 
256  // FIRE algorithm constants
257  const double DELAYSTEP = 5;
258  const double TIMESTEP_GROW = 1.1;
259  const double TIMESTEP_SHRINK = 0.5;
260  const double ALPHA_0 = 0.1;
261  const double ALPHA_SHRINK = 0.99;
262 
263  using real_type = typename VectorType::real_type;
264 
265  typename VectorMemory<VectorType>::Pointer v(this->memory);
266  typename VectorMemory<VectorType>::Pointer g(this->memory);
267 
268  // Set velocities to zero but not gradients
269  // as we are going to compute them soon.
270  v->reinit(x,false);
271  g->reinit(x,true);
272 
273  // Refer to v and g with some readable names.
274  VectorType &velocities = *v;
275  VectorType &gradients = *g;
276 
277  // Update gradients for the new x.
278  compute(gradients, x);
279 
280  unsigned int iter = 0;
281 
283  conv = this->iteration_status (iter, gradients * gradients, x);
284  if (conv != SolverControl::iterate)
285  return;
286 
287  // Refer to additional data members with some readable names.
288  const auto &maximum_timestep = additional_data.maximum_timestep;
289  double timestep = additional_data.initial_timestep;
290 
291  // First scaling factor.
292  double alpha = ALPHA_0;
293 
294  unsigned int previous_iter_with_positive_v_dot_g = 0;
295 
296  while (conv == SolverControl::iterate)
297  {
298  ++iter;
299  // Euler integration step.
300  x.add (timestep, velocities); // x += dt * v
301  inverse_mass_matrix.vmult(gradients, gradients); // g = M^{-1} * g
302  velocities.add (-timestep, gradients); // v -= dt * h
303 
304  // Compute gradients for the new x.
305  compute(gradients, x);
306 
307  const real_type gradient_norm_squared = gradients * gradients;
308  conv = this->iteration_status(iter, gradient_norm_squared, x);
309  if (conv != SolverControl::iterate)
310  break;
311 
312  // v_dot_g = V * G
313  const real_type v_dot_g = velocities * gradients;
314 
315  if (v_dot_g < 0.)
316  {
317  const real_type velocities_norm_squared =
318  velocities * velocities;
319 
320  // Check if we divide by zero in DEBUG mode.
321  Assert (gradient_norm_squared > 0., ExcInternalError());
322 
323  // beta = - alpha |V|/|G|
324  const real_type beta = -alpha *
325  std::sqrt (velocities_norm_squared
326  /
327  gradient_norm_squared);
328 
329  // V = (1-alpha) V + beta G.
330  velocities.sadd (1. - alpha, beta, gradients);
331 
332  if (iter - previous_iter_with_positive_v_dot_g > DELAYSTEP)
333  {
334  // Increase timestep and decrease alpha.
335  timestep = std::min (timestep*TIMESTEP_GROW, maximum_timestep);
336  alpha *= ALPHA_SHRINK;
337  }
338  }
339  else
340  {
341  // Decrease timestep, reset alpha and set V = 0.
342  previous_iter_with_positive_v_dot_g = iter;
343  timestep *= TIMESTEP_SHRINK;
344  alpha = ALPHA_0;
345  velocities = 0.;
346  }
347 
348  real_type vmax = velocities.linfty_norm();
349 
350  // Change timestep if any dof would move more than maximum_linfty_norm.
351  if (vmax > 0.)
352  {
353  const double minimal_timestep = additional_data.maximum_linfty_norm
354  /
355  vmax;
356  if (minimal_timestep < timestep)
357  timestep = minimal_timestep;
358  }
359 
360  print_vectors(iter, x, velocities, gradients);
361 
362  } // While we need to iterate.
363 
364  // In the case of failure: throw exception.
365  if (conv != SolverControl::success)
366  AssertThrow (false,
367  SolverControl::NoConvergence (iter, gradients * gradients));
368 
369 }
370 
371 
372 
373 template <typename VectorType>
374 template <typename MatrixType, typename PreconditionerType>
375 void SolverFIRE<VectorType>::solve (const MatrixType &A,
376  VectorType &x,
377  const VectorType &b,
378  const PreconditionerType &preconditioner)
379 {
380 
381  std::function<double(VectorType &, const VectorType &)> compute_func =
382  [&] (VectorType &g, const VectorType &x) -> double
383  {
384  // Residual of the quadratic form @f$ \frac{1}{2} xAx - xb @f$.
385  // G = b - Ax
386  A.residual(g, x, b);
387 
388  // Gradient G = Ax -b.
389  g *= -1.;
390 
391  // The quadratic form @f$\frac{1}{2} xAx - xb @f$.
392  return 0.5*A.matrix_norm_square(x) - x*b;
393  };
394 
395  this->solve (compute_func, x, preconditioner);
396 }
397 
398 
399 
400 template <typename VectorType>
401 void
402 SolverFIRE<VectorType>::print_vectors (const unsigned int,
403  const VectorType &,
404  const VectorType &,
405  const VectorType &) const
406 {}
407 
408 
409 
410 #endif // DOXYGEN
411 
412 DEAL_II_NAMESPACE_CLOSE
413 
414 #endif
virtual void print_vectors(const unsigned int, const VectorType &x, const VectorType &v, const VectorType &g) const
Continue iteration.
AdditionalData(const double initial_timestep=0.1, const double maximum_timestep=1, const double maximum_linfty_norm=1)
const AdditionalData additional_data
Definition: solver_fire.h:187
#define AssertThrow(cond, exc)
Definition: exceptions.h:1221
static ::ExceptionBase & ExcMessage(std::string arg1)
Stop iteration, goal reached.
const double maximum_timestep
Definition: solver_fire.h:117
#define Assert(cond, exc)
Definition: exceptions.h:1142
void solve(const std::function< double(VectorType &, const VectorType &)> &compute, VectorType &x, const PreconditionerType &inverse_mass_matrix)
SymmetricTensor< 2, dim, Number > b(const Tensor< 2, dim, Number > &F)
const double initial_timestep
Definition: solver_fire.h:112
Definition: solver.h:322
const double maximum_linfty_norm
Definition: solver_fire.h:122
SolverFIRE(SolverControl &solver_control, VectorMemory< VectorType > &vector_memory, const AdditionalData &data=AdditionalData())
virtual ~SolverFIRE()
static ::ExceptionBase & ExcInternalError()