DUBeat  1.0.1
High-order discontinuous Galerkin methods and applications to cardiac electrophysiology
model_DG_t.hpp
Go to the documentation of this file.
1 /********************************************************************************
2  Copyright (C) 2024 by the DUBeat authors.
3 
4  This file is part of DUBeat.
5 
6  DUBeat is free software; you can redistribute it and/or modify
7  it under the terms of the GNU Lesser General Public License as published by
8  the Free Software Foundation, either version 3 of the License, or
9  (at your option) any later version.
10 
11  DUBeat is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  Lesser General Public License for more details.
15 
16  You should have received a copy of the GNU Lesser General Public License
17  along with DUBeat. If not, see <http://www.gnu.org/licenses/>.
18 ********************************************************************************/
19 
27 #ifndef MODEL_DG_T_HPP_
28 #define MODEL_DG_T_HPP_
29 
30 #include <deal.II/base/parameter_handler.h>
31 
32 #include <deal.II/fe/mapping_q1_eulerian.h>
33 
34 #include <deal.II/lac/full_matrix.h>
35 
36 #include <memory>
37 #include <string>
38 #include <vector>
39 
40 #include "DUBValues.hpp"
41 #include "DUB_FEM_handler.hpp"
42 #include "assemble_DG.hpp"
43 #include "face_handler_DG.hpp"
44 #include "model_DG.hpp"
45 #include "source/core_model.hpp"
46 #include "source/geometry/mesh_handler.hpp"
47 #include "source/init.hpp"
48 #include "source/io/data_writer.hpp"
49 #include "source/numerics/bc_handler.hpp"
50 #include "source/numerics/linear_solver_handler.hpp"
51 #include "source/numerics/preconditioner_handler.hpp"
52 #include "source/numerics/time_handler.hpp"
53 #include "source/numerics/tools.hpp"
54 #include "volume_handler_DG.hpp"
55 
60 template <class basis>
61 class ModelDG_t : public ModelDG<basis>
62 {
63 public:
65  ModelDG_t(std::string model_name)
66  : ModelDG<basis>(model_name)
68  , timestep_number(0)
69  {}
70 
73 
76 
79 
81  virtual ~ModelDG_t() = default;
82 
83 protected:
85  virtual void
86  declare_parameters(lifex::ParamHandler &params) const override;
87 
89  virtual void
90  parse_parameters(lifex::ParamHandler &params) override;
91 
93  virtual void
95 
97  virtual void
98  update_time();
99 
101  virtual void
103  const lifex::LinAlg::MPI::Vector &solution_owned,
104  const lifex::LinAlg::MPI::Vector &solution_ex_owned,
105  const std::shared_ptr<dealii::Function<lifex::dim>> &u_ex,
106  const char *solution_name = (char *)"u");
107 
109  void
110  run() override;
111 
119  unsigned int prm_bdf_order;
121  double time;
123  unsigned int timestep_number;
125  lifex::utils::BDFHandler<lifex::LinAlg::MPI::Vector> bdf_handler;
127  lifex::LinAlg::MPI::Vector solution_bdf;
129  lifex::LinAlg::MPI::Vector solution_ext;
130 };
131 
132 template <class basis>
133 void
134 ModelDG_t<basis>::declare_parameters(lifex::ParamHandler &params) const
135 {
136  // Default parameters.
137  this->linear_solver.declare_parameters(params);
138  this->preconditioner.declare_parameters(params);
139 
140  // Extra parameters.
141  params.enter_subsection("Mesh and space discretization");
142  {
143  params.declare_entry(
144  "Number of refinements",
145  "2",
146  dealii::Patterns::Integer(0),
147  "Number of global mesh refinement steps applied to initial grid.");
148  params.declare_entry("FE space degree",
149  "1",
150  dealii::Patterns::Integer(1),
151  "Degree of the FE space.");
152  }
153  params.leave_subsection();
154 
155  params.enter_subsection("Discontinuous Galerkin");
156  {
157  params.declare_entry(
158  "Penalty coefficient",
159  "1",
160  dealii::Patterns::Double(-1, 1),
161  "Penalty coefficient in the Discontinuous Galerkin formulation.");
162  params.declare_entry(
163  "Stability coefficient",
164  "10",
165  dealii::Patterns::Double(0),
166  "Stabilization term in the Discontinuous Galerkin formulation.");
167  }
168  params.leave_subsection();
169 
170  params.enter_subsection("Time solver");
171  {
172  params.declare_entry("Initial time",
173  "0",
174  dealii::Patterns::Double(0),
175  "Initial time.");
176  params.declare_entry("Final time",
177  "0.001",
178  dealii::Patterns::Double(0),
179  "Final time.");
180  params.declare_entry("Time step",
181  "0.0001",
182  dealii::Patterns::Double(0),
183  "Time step.");
184  params.declare_entry("BDF order",
185  "1",
186  dealii::Patterns::Integer(1, 3),
187  "BDF order: 1, 2, 3.");
188  }
189  params.leave_subsection();
190 }
191 
192 template <class basis>
193 void
194 ModelDG_t<basis>::parse_parameters(lifex::ParamHandler &params)
195 {
196  // Parse input file.
197  params.parse();
198  // Read input parameters.
199  this->linear_solver.parse_parameters(params);
200  this->preconditioner.parse_parameters(params);
201 
202  // Extra parameters.
203  params.enter_subsection("Mesh and space discretization");
204  this->prm_n_refinements = params.get_integer("Number of refinements");
205  this->prm_fe_degree = params.get_integer("FE space degree");
206  params.leave_subsection();
207 
208  params.enter_subsection("Discontinuous Galerkin");
209  this->prm_penalty_coeff = params.get_double("Penalty coefficient");
210  AssertThrow(this->prm_penalty_coeff == 1. || this->prm_penalty_coeff == 0. ||
211  this->prm_penalty_coeff == -1.,
212  dealii::StandardExceptions::ExcMessage(
213  "Penalty coefficient must be 1 (SIP method) or 0 (IIP method) "
214  "or -1 (NIP method)."));
215 
216  this->prm_stability_coeff = params.get_double("Stability coefficient");
217  params.leave_subsection();
218 
219  params.enter_subsection("Time solver");
220  this->prm_time_init = params.get_double("Initial time");
221  this->prm_time_final = params.get_double("Final time");
222  AssertThrow(this->prm_time_final > this->prm_time_init,
223  dealii::StandardExceptions::ExcMessage(
224  "Final time must be greater than initial time."));
225 
226  this->prm_time_step = params.get_double("Time step");
227  this->prm_bdf_order = params.get_integer("BDF order");
228  params.leave_subsection();
229 }
230 
231 template <class basis>
232 void
234 {
235  // Set initial time to the exact analytical solution.
236  this->u_ex->set_time(prm_time_init);
237 
238  // Solution_owned and solution_ex_owned at the initial time are the
239  // discretization of the analytical u_ex.
240  this->discretize_analytical_solution(this->u_ex, this->solution_owned);
241  this->solution_ex_owned = this->solution_owned;
242  this->solution = this->solution_owned;
243 
244  // Initialization of the initial solution.
245  const std::vector<lifex::LinAlg::MPI::Vector> sol_init(this->prm_bdf_order,
246  this->solution_owned);
247 
248  // Initialization of the BDFHandler
249  bdf_handler.initialize(this->prm_bdf_order, sol_init);
250 
251  solution_bdf = bdf_handler.get_sol_bdf();
252 }
253 
254 template <class basis>
255 void
257  const lifex::LinAlg::MPI::Vector &solution_owned,
258  const lifex::LinAlg::MPI::Vector &solution_ex_owned,
259  const std::shared_ptr<dealii::Function<lifex::dim>> &u_ex,
260  const char *solution_name)
261 {
262  AssertThrow(u_ex != nullptr,
263  dealii::StandardExceptions::ExcMessage(
264  "Not valid pointer to the exact solution."));
265 
266  AssertThrow(solution_owned.size() == solution_ex_owned.size(),
267  dealii::StandardExceptions::ExcMessage(
268  "The exact solution vector and the approximate solution vector "
269  "must have the same length."));
270 
271  lifex::LinAlg::MPI::Vector error_owned =
272  this->conversion_to_fem(solution_owned);
273  error_owned -= this->conversion_to_fem(solution_ex_owned);
274 
275  pcerr << solution_name << ":"
276  << "\tL-inf error norm: " << error_owned.linfty_norm() << std::endl;
277 }
278 
279 template <class basis>
280 void
282 {
283  // Update time for all the known analytical functions.
284  this->u_ex->set_time(this->time);
285  this->f_ex->set_time(this->time);
286  this->g_n->set_time(this->time);
287  this->grad_u_ex->set_time(this->time);
288 
289  bdf_handler.time_advance(this->solution_owned, true);
290  this->solution_bdf = bdf_handler.get_sol_bdf();
291 
292  // Update solution_ex_owned from the updated u_ex.
293  this->discretize_analytical_solution(this->u_ex, this->solution_ex_owned);
294 }
295 
296 template <class basis>
297 void
299 {
300  this->create_mesh();
301  this->setup_system();
302  this->initialize_solution(this->solution_owned, this->solution);
303  this->initialize_solution(this->solution_ex_owned, this->solution_ex);
304  this->time_initialization();
305 
306  while (this->time < this->prm_time_final)
307  {
308  time += prm_time_step;
309  ++timestep_number;
310 
311  pcout << "Time step " << std::setw(6) << timestep_number
312  << " at t = " << std::setw(8) << std::fixed << std::setprecision(6)
313  << time << std::endl;
314 
315  this->update_time();
316  this->solution_ext = bdf_handler.get_sol_extrapolation();
317 
318  this->assemble_system();
319 
320  // Initial guess.
321  this->solution_owned = this->solution_ext;
322  this->solve_system();
323 
324  this->intermediate_error_print(this->solution_owned,
325  this->solution_ex_owned,
326  this->u_ex);
327  }
328 
329  this->compute_errors(this->solution_owned,
330  this->solution_ex_owned,
331  this->u_ex,
332  this->grad_u_ex);
333 
334 
335  // Generation of the graphical output.
336  this->solution_ex = this->solution_ex_owned;
337  this->conversion_to_fem(this->solution_ex);
338  this->solution = this->solution_owned;
339  this->conversion_to_fem(this->solution);
340  this->output_results();
341 }
342 
343 #endif /* MODEL_DG_T_HPP_*/
Class representing the resolution of time-dependent problems using discontinuous Galerkin methods.
Definition: model_DG_t.hpp:62
virtual void declare_parameters(lifex::ParamHandler &params) const override
Override for declaration of additional parameters.
Definition: model_DG_t.hpp:134
double prm_time_step
Time-step amplitude.
Definition: model_DG_t.hpp:117
double time
Current time.
Definition: model_DG_t.hpp:121
lifex::LinAlg::MPI::Vector solution_bdf
BDF solution, with ghost entries.
Definition: model_DG_t.hpp:127
lifex::LinAlg::MPI::Vector solution_ext
BDF extrapolated solution, with ghost entries.
Definition: model_DG_t.hpp:129
lifex::utils::BDFHandler< lifex::LinAlg::MPI::Vector > bdf_handler
BDF time advancing handler.
Definition: model_DG_t.hpp:125
double prm_time_init
Initial time.
Definition: model_DG_t.hpp:113
virtual void parse_parameters(lifex::ParamHandler &params) override
Override to parse additional parameters.
Definition: model_DG_t.hpp:194
void run() override
Override for the simulation run.
Definition: model_DG_t.hpp:298
unsigned int prm_bdf_order
BDF order.
Definition: model_DG_t.hpp:119
double prm_time_final
Final time.
Definition: model_DG_t.hpp:115
virtual void intermediate_error_print(const lifex::LinAlg::MPI::Vector &solution_owned, const lifex::LinAlg::MPI::Vector &solution_ex_owned, const std::shared_ptr< dealii::Function< lifex::dim >> &u_ex, const char *solution_name=(char *)"u")
Computation of the error at an intermediate time-step.
Definition: model_DG_t.hpp:256
unsigned int timestep_number
Current time-step number.
Definition: model_DG_t.hpp:123
virtual void update_time()
To perform the time increment.
Definition: model_DG_t.hpp:281
virtual void time_initialization()
Setup for the time-dependent problems at the initial time-step.
Definition: model_DG_t.hpp:233
ModelDG_t(std::string model_name)
Constructor.
Definition: model_DG_t.hpp:65
virtual ~ModelDG_t()=default
Destructor.
Class representing the resolution of problems using discontinuous Galerkin methods.
Definition: model_DG.hpp:63
const std::string model_name
Name of the class/problem.
Definition: model_DG.hpp:212
lifex::LinAlg::MPI::Vector solution_owned
Distributed solution vector, without ghost entries.
Definition: model_DG.hpp:243
std::shared_ptr< lifex::utils::FunctionDirichlet > u_ex
Pointer to exact solution function.
Definition: model_DG.hpp:251
lifex::LinAlg::MPI::Vector solution_ex_owned
Distributed exact solution vector, without ghost entries.
Definition: model_DG.hpp:247