DUBeat 1.0.1
High-order discontinuous Galerkin methods and applications to cardiac electrophysiology
Loading...
Searching...
No Matches
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
60template <class basis>
61class ModelDG_t : public ModelDG<basis>
62{
63public:
65 ModelDG_t(std::string model_name)
66 : ModelDG<basis>(model_name)
69 {}
70
73
76
79
81 virtual ~ModelDG_t() = default;
82
83protected:
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
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
132template <class basis>
133void
134ModelDG_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
192template <class basis>
193void
194ModelDG_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
231template <class basis>
232void
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
254template <class basis>
255void
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
279template <class basis>
280void
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
296template <class basis>
297void
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.
virtual void declare_parameters(lifex::ParamHandler &params) const override
Override for declaration of additional parameters.
double prm_time_step
Time-step amplitude.
double time
Current time.
lifex::LinAlg::MPI::Vector solution_bdf
BDF solution, with ghost entries.
lifex::LinAlg::MPI::Vector solution_ext
BDF extrapolated solution, with ghost entries.
lifex::utils::BDFHandler< lifex::LinAlg::MPI::Vector > bdf_handler
BDF time advancing handler.
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.
double prm_time_init
Initial time.
virtual void parse_parameters(lifex::ParamHandler &params) override
Override to parse additional parameters.
void run() override
Override for the simulation run.
unsigned int prm_bdf_order
BDF order.
double prm_time_final
Final time.
unsigned int timestep_number
Current time-step number.
virtual void update_time()
To perform the time increment.
virtual void time_initialization()
Setup for the time-dependent problems at the initial time-step.
ModelDG_t(std::string model_name)
Constructor.
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