16 #ifndef dealii_solver_fire_h
17 #define dealii_solver_fire_h
90 template <
typename VectorType = Vector<
double>>
147 template <
typename PreconditionerType = DiagonalMatrix<VectorType>>
151 const PreconditionerType &inverse_mass_matrix);
158 template <
typename MatrixType,
typename PreconditionerType>
160 solve(
const MatrixType &
A,
163 const PreconditionerType &preconditioner);
190 template <
typename VectorType>
192 const double initial_timestep,
193 const double maximum_timestep,
194 const double maximum_linfty_norm)
195 : initial_timestep(initial_timestep)
196 , maximum_timestep(maximum_timestep)
197 , maximum_linfty_norm(maximum_linfty_norm)
199 AssertThrow(initial_timestep > 0. && maximum_timestep > 0. &&
200 maximum_linfty_norm > 0.,
201 ExcMessage(
"Expected positive values for initial_timestep, "
202 "maximum_timestep and maximum_linfty_norm but one "
203 "or more of the these values are not positive."));
208 template <
typename VectorType>
211 const AdditionalData & data)
213 , additional_data(data)
218 template <
typename VectorType>
220 const AdditionalData &data)
222 , additional_data(data)
227 template <
typename VectorType>
228 template <
typename PreconditionerType>
233 const PreconditionerType &inverse_mass_matrix)
238 const double DELAYSTEP = 5;
239 const double TIMESTEP_GROW = 1.1;
240 const double TIMESTEP_SHRINK = 0.5;
241 const double ALPHA_0 = 0.1;
242 const double ALPHA_SHRINK = 0.99;
244 using real_type =
typename VectorType::real_type;
259 compute(gradients, x);
261 unsigned int iter = 0;
264 conv = this->iteration_status(iter, gradients * gradients, x);
269 const auto &maximum_timestep = additional_data.maximum_timestep;
270 double timestep = additional_data.initial_timestep;
273 double alpha = ALPHA_0;
275 unsigned int previous_iter_with_positive_v_dot_g = 0;
281 x.add(timestep, velocities);
282 inverse_mass_matrix.vmult(gradients, gradients);
283 velocities.add(-timestep, gradients);
286 compute(gradients, x);
288 const real_type gradient_norm_squared = gradients * gradients;
289 conv = this->iteration_status(iter, gradient_norm_squared, x);
294 const real_type v_dot_g = velocities * gradients;
298 const real_type velocities_norm_squared = velocities * velocities;
304 const real_type beta =
305 -alpha *
std::sqrt(velocities_norm_squared / gradient_norm_squared);
308 velocities.sadd(1. - alpha, beta, gradients);
310 if (iter - previous_iter_with_positive_v_dot_g > DELAYSTEP)
313 timestep =
std::min(timestep * TIMESTEP_GROW, maximum_timestep);
314 alpha *= ALPHA_SHRINK;
320 previous_iter_with_positive_v_dot_g = iter;
321 timestep *= TIMESTEP_SHRINK;
326 real_type vmax = velocities.linfty_norm();
331 const double minimal_timestep =
332 additional_data.maximum_linfty_norm / vmax;
333 if (minimal_timestep < timestep)
334 timestep = minimal_timestep;
337 print_vectors(iter, x, velocities, gradients);
349 template <
typename VectorType>
350 template <
typename MatrixType,
typename PreconditionerType>
355 const PreconditionerType &preconditioner)
367 return 0.5 *
A.matrix_norm_square(x) - x *
b;
370 this->solve(compute_func, x, preconditioner);
375 template <
typename VectorType>