27#ifndef MONODOMAIN_FHN_DG_HPP_
28#define MONODOMAIN_FHN_DG_HPP_
35#include "../source/DUBValues.hpp"
36#include "../source/DUB_FEM_handler.hpp"
37#include "../source/assemble_DG.hpp"
38#include "../source/face_handler_DG.hpp"
39#include "../source/model_DG.hpp"
40#include "../source/model_DG_t.hpp"
41#include "../source/volume_handler_DG.hpp"
42#include "source/core_model.hpp"
43#include "source/geometry/mesh_handler.hpp"
44#include "source/init.hpp"
45#include "source/io/data_writer.hpp"
46#include "source/numerics/bc_handler.hpp"
47#include "source/numerics/linear_solver_handler.hpp"
48#include "source/numerics/preconditioner_handler.hpp"
49#include "source/numerics/tools.hpp"
53 namespace monodomain_fhn_DG
63 : lifex::utils::FunctionDirichlet()
68 value(
const dealii::Point<lifex::dim> &
p,
69 const unsigned int = 0)
const override
72 return std::sin(2 *
M_PI *
p[0]) * std::sin(2 *
M_PI *
p[1]) *
75 return std::sin(2 *
M_PI *
p[0] +
M_PI / 4) *
118 : lifex::Function<lifex::
dim>()
130 value(
const dealii::Point<lifex::dim> &
p,
131 const unsigned int = 0)
const override
134 return std::sin(2 *
M_PI *
p[0]) * std::sin(2 *
M_PI *
p[1]) *
138 (std::sin(2 *
M_PI *
p[0]) * std::sin(2 *
M_PI *
p[1]) *
141 (std::sin(2 *
M_PI *
p[0]) * std::sin(2 *
M_PI *
p[1]) *
146 return std::sin(2 *
M_PI *
p[0] +
M_PI / 4) *
178 : lifex::Function<lifex::
dim>()
184 value(
const dealii::Point<lifex::dim> &
p,
185 const unsigned int = 0)
const override
190 std::cos(2 *
M_PI *
p[1]) *
191 std::exp(-5 * this->
get_time()) * (std::abs(
p[1]) < 1
e-10) +
193 std::sin(2 *
M_PI *
p[1]) *
195 (std::abs(
p[0] - 1) < 1
e-10) +
197 std::cos(2 *
M_PI *
p[1]) *
199 (std::abs(
p[1] - 1) < 1
e-10) -
201 std::sin(2 *
M_PI *
p[1]) *
202 std::exp(-5 * this->
get_time()) * (std::abs(
p[0]) < 1
e-10));
209 (std::abs(
p[0] - 1) < 1
e-10) -
213 std::exp(-5 * this->
get_time()) * (std::abs(
p[0]) < 1
e-10) +
218 (std::abs(
p[1] - 1) < 1
e-10) -
222 std::exp(-5 * this->
get_time()) * (std::abs(
p[1]) < 1
e-10) +
227 (std::abs(
p[2] - 1) < 1
e-10) -
231 std::exp(-5 * this->
get_time()) * (std::abs(
p[2]) < 1
e-10));
243 : lifex::Function<lifex::
dim>()
248 value(
const dealii::Point<lifex::dim> &
p,
249 const unsigned int component = 0)
const override
254 return 2 *
M_PI * std::cos(2 *
M_PI *
p[0]) *
255 std::sin(2 *
M_PI *
p[1]) *
258 return 2 *
M_PI * std::sin(2 *
M_PI *
p[0]) *
259 std::cos(2 *
M_PI *
p[1]) *
298 : lifex::utils::FunctionDirichlet()
305 value(
const dealii::Point<lifex::dim> &
p,
306 const unsigned int = 0)
const override
313 std::sin(2 *
M_PI *
p[1]) * std::sin(2 *
M_PI *
p[2]) *
333 : lifex::Function<lifex::
dim>()
340 value(
const dealii::Point<lifex::dim> &
p,
341 const unsigned int component = 0)
const override
347 std::cos(2 *
M_PI *
p[0]) * std::sin(2 *
M_PI *
p[1]) *
351 std::sin(2 *
M_PI *
p[0]) * std::cos(2 *
M_PI *
p[1]) *
358 std::cos(2 *
M_PI *
p[0]) * std::sin(2 *
M_PI *
p[1]) *
359 std::sin(2 *
M_PI *
p[2]) *
363 std::sin(2 *
M_PI *
p[0]) * std::cos(2 *
M_PI *
p[1]) *
364 std::sin(2 *
M_PI *
p[2]) *
368 std::sin(2 *
M_PI *
p[0]) * std::sin(2 *
M_PI *
p[1]) *
369 std::cos(2 *
M_PI *
p[2]) *
445 template <
class basis>
478 std::shared_ptr<lifex::utils::FunctionDirichlet>
w_ex;
480 std::shared_ptr<dealii::Function<lifex::dim>>
grad_w_ex;
516 template <
class basis>
525 params.enter_subsection(
"Mesh and space discretization");
528 "Number of refinements",
530 dealii::Patterns::Integer(0),
531 "Number of global mesh refinement steps applied to initial grid.");
532 params.declare_entry(
"FE space degree",
534 dealii::Patterns::Integer(1),
535 "Degree of the FE space.");
537 params.leave_subsection();
539 params.enter_subsection(
"Discontinuous Galerkin");
542 "Penalty coefficient",
544 dealii::Patterns::Double(-1, 1),
545 "Penalty coefficient in the Discontinuous Galerkin formulation.");
547 "Stability coefficient",
549 dealii::Patterns::Double(0),
550 "Stabilization term in the Discontinuous Galerkin formulation.");
552 params.leave_subsection();
554 params.enter_subsection(
"Time solver");
556 params.declare_entry(
"Initial time",
558 dealii::Patterns::Double(0),
560 params.declare_entry(
"Final time",
562 dealii::Patterns::Double(0),
564 params.declare_entry(
"Time step",
566 dealii::Patterns::Double(0),
568 params.declare_entry(
"BDF order",
570 dealii::Patterns::Integer(1, 3),
571 "BDF order: 1, 2, 3.");
573 params.leave_subsection();
575 params.enter_subsection(
"Parameters of the model");
577 params.declare_entry(
"ChiM",
579 dealii::Patterns::Double(0),
580 "Surface-to-volume ratio of cells parameter.");
581 params.declare_entry(
"Cm",
583 dealii::Patterns::Double(0),
584 "Membrane capacity.");
585 params.declare_entry(
"Sigma",
587 dealii::Patterns::Double(0),
588 "Diffusion parameter in the principal directions.");
592 dealii::Patterns::Double(0),
593 "Factor for the nonlinear reaction in Fitzhugh Nagumo model.");
594 params.declare_entry(
"epsilon",
596 dealii::Patterns::Double(0),
597 "Parameter for Fitzhugh Nagumo model.");
598 params.declare_entry(
"gamma",
600 dealii::Patterns::Double(0),
601 "Parameter for Fitzhugh Nagumo model.");
604 dealii::Patterns::Double(0),
605 "Parameter for Fitzhugh Nagumo model.");
607 params.leave_subsection();
610 template <
class basis>
621 params.enter_subsection(
"Mesh and space discretization");
624 params.leave_subsection();
626 params.enter_subsection(
"Discontinuous Galerkin");
631 dealii::StandardExceptions::ExcMessage(
632 "Penalty coefficient must be 1 (SIP method) or 0 (IIP method) "
633 "or -1 (NIP method)."));
636 params.leave_subsection();
638 params.enter_subsection(
"Time solver");
642 dealii::StandardExceptions::ExcMessage(
643 "Final time must be greater than initial time."));
647 params.leave_subsection();
649 params.enter_subsection(
"Parameters of the model");
650 ChiM =
params.get_double(
"ChiM");
651 Cm =
params.get_double(
"Cm");
652 Sigma =
params.get_double(
"Sigma");
653 kappa =
params.get_double(
"kappa");
654 epsilon =
params.get_double(
"epsilon");
655 gamma =
params.get_double(
"gamma");
656 a =
params.get_double(
"a");
657 params.leave_subsection();
660 template <
class basis>
680 <<
" at t = " << std::setw(8) << std::fixed
681 << std::setprecision(6) << this->
time << std::endl;
697 this->solution_ex_owned_w,
709 this->solution_ex_owned_w,
722 template <
class basis>
728 this->
g_n->set_time(this->
time);
731 w_ex->set_time(this->
time);
732 grad_w_ex->set_time(this->
time);
736 bdf_handler_w.time_advance(solution_owned_w,
true);
737 solution_bdf_w = this->bdf_handler_w.get_sol_bdf();
744 template <
class basis>
748 this->
u_ex = std::make_shared<monodomain_fhn_DG::ExactSolution>();
749 this->
grad_u_ex = std::make_shared<monodomain_fhn_DG::GradExactSolution>();
750 this->
f_ex = std::make_shared<monodomain_fhn_DG::RightHandSide>(
751 ChiM, Sigma, Cm, kappa, epsilon, gamma, a);
752 this->
g_n = std::make_shared<monodomain_fhn_DG::BCNeumann>(Sigma);
753 w_ex = std::make_shared<monodomain_fhn_DG::ExactSolution_w>(epsilon, gamma);
755 std::make_shared<monodomain_fhn_DG::GradExactSolution_w>(epsilon, gamma);
764 solution_ex_w = solution_ex_owned_w;
765 solution_w = solution_owned_w = solution_ex_owned_w;
767 const std::vector<lifex::LinAlg::MPI::Vector>
sol_init(
772 const std::vector<lifex::LinAlg::MPI::Vector>
sol_init_w(
778 template <
class basis>
784 solution_owned_w *= -gamma;
786 solution_owned_w *= epsilon;
787 solution_owned_w.add(1 / this->
prm_time_step, this->solution_bdf_w);
790 solution_w = solution_owned_w;
807 std::vector<lifex::types::global_dof_index>
dof_indices(
817 this->matrix_t0.reinit(this->
matrix);
838 for (
const auto &cell : this->
dof_handler.active_cell_iterators())
840 if (cell->is_locally_owned())
856 for (
const auto &edge : cell->face_indices())
859 std::vector<lifex::types::global_dof_index>
862 if (!cell->at_boundary(edge))
875 const auto neighcell = cell->neighbor(edge);
896 this->matrix_t0.compress(lifex::VectorOperation::add);
901 this->
matrix.copy_from(this->matrix_t0);
903 for (
const auto &cell : this->
dof_handler.active_cell_iterators())
905 if (cell->is_locally_owned())
925 if (cell->at_boundary())
927 for (
const auto &edge : cell->face_indices())
929 if (cell->at_boundary(edge))
939 this->
matrix.add(dof_indices,
C);
946 this->
matrix.compress(lifex::VectorOperation::add);
947 this->
rhs.compress(lifex::VectorOperation::add);
Class to solve the heat equation using the Discontinuous Galerkin method.
void assemble_system() override
Assembly of the linear system.
Class to solve the monodomain equation with Fitzhugh-Nagumo ionic model for the cardiac electrophysio...
lifex::LinAlg::MPI::Vector solution_bdf_w
BDF solution, with ghost entries.
lifex::LinAlg::MPI::Vector solution_ex_owned_w
Solution exact gating variable, without ghost entries.
double kappa
Factor for the nonlinear reaction in Fitzhugh Nagumo model.
double Cm
Membrane capacity.
std::shared_ptr< dealii::Function< lifex::dim > > grad_w_ex
dealii::Pointer to exact gradient solution Function gating variable
double gamma
ODE parameter.
std::shared_ptr< lifex::utils::FunctionDirichlet > w_ex
dealii::Pointer to exact solution function gating variable.
virtual void declare_parameters(lifex::ParamHandler ¶ms) const override
Override for declaration of additional parameters.
lifex::LinAlg::MPI::Vector solution_ex_w
Solution exact gating variable, without ghost entries.
void run() override
Override for the simulation run.
lifex::LinAlg::MPI::Vector solution_owned_w
Solution gating variable, without ghost entries.
void time_initialization() override
Override to initialize both u and w.
lifex::utils::BDFHandler< lifex::LinAlg::MPI::Vector > bdf_handler_w
BDF time advancing handler.
void update_time() override
Override to update time for both u and w.
lifex::LinAlg::MPI::Vector solution_w
Solution gating variable, with ghost entries.
lifex::LinAlg::MPI::Vector solution_ext_w
BDF extrapolated solution, with ghost entries.
double epsilon
ODE parameter.
double Sigma
Diffusion scalar parameter.
void assemble_system() override
Assembly of the Monodomain system.
double ChiM
Monodomain equation parameter.
virtual void parse_parameters(lifex::ParamHandler ¶ms) override
Override to parse additional parameters.
lifex::LinAlg::MPI::SparseMatrix matrix_t0
Component of the system matrix that does not depend on time.
Neumann boundary condition of the trans-membrane potential.
virtual double value(const dealii::Point< lifex::dim > &p, const unsigned int=0) const override
Evaluate the Neumann boundary condition function in a point.
BCNeumann(double Sigma)
Constrcutor.
double Sigma
Diffusion scalar parameter.
Exact solution of the gating variable.
double epsilon
Parameter ODE.
ExactSolution_w(double epsilon, double gamma)
Constructor.
double gamma
Parameter ODE.
virtual double value(const dealii::Point< lifex::dim > &p, const unsigned int=0) const override
Evaluate the exact solution in a point.
Exact solution of the trans-membrane potential.
ExactSolution()
Constructor.
virtual double value(const dealii::Point< lifex::dim > &p, const unsigned int=0) const override
Evaluate the exact solution in a point.
Gradient of the gating variable.
GradExactSolution_w(double epsilon, double gamma)
Constructor.
double gamma
Parameter ODE.
virtual double value(const dealii::Point< lifex::dim > &p, const unsigned int component=0) const override
Evaluate the gradient of the exact solution in a point.
double epsilon
Parameter ODE.
Gradient of the trans-membrane potential.
GradExactSolution()
Constructor.
virtual double value(const dealii::Point< lifex::dim > &p, const unsigned int component=0) const override
Evaluate the gradient of the exact solution in a point.
Source term: applied current.
double epsilon
Parameter ODE.
RightHandSide(double ChiM, double Sigma, double Cm, double kappa, double epsilon, double gamma, double a)
Constructor.
double gamma
Parameter ODE.
double Cm
Membrane capacity.
double kappa
Factor for the nonlinear reaction in Fitzhugh Nagumo model.
double ChiM
Parameter monodomain equation.
virtual double value(const dealii::Point< lifex::dim > &p, const unsigned int=0) const override
Evaluate the source term in a point.
double Sigma
Diffusion scalar parameter.
Class representing the resolution of time-dependent problems using discontinuous Galerkin methods.
virtual void declare_parameters(lifex::ParamHandler ¶ms) const override
Override for declaration of additional parameters.
double prm_time_step
Time-step amplitude.
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 ¶ms) override
Override to parse additional parameters.
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.
lifex::LinAlg::MPI::SparseMatrix matrix
Distributed matrix of the linear system.
std::shared_ptr< dealii::Function< lifex::dim > > g_n
Neumann boundary conditions.
unsigned int prm_n_refinements
Mesh refinement level (>=1).
void initialize_solution(lifex::LinAlg::MPI::Vector &solution_owned, lifex::LinAlg::MPI::Vector &solution)
To inizialize the solutions using the deal.II reinit.
unsigned int prm_fe_degree
Polynomials degree.
double prm_stability_coeff
DG stabilty coefficient.
lifex::LinAlg::MPI::Vector solution
Distributed solution vector, with ghost entries.
std::unique_ptr< AssembleDG< basis > > assemble
Matrix assembler.
lifex::LinAlg::MPI::Vector solution_ex
Distributed exact solution vector, without ghost entries.
DoFHandlerDG< basis > dof_handler
DoFHandler (internal use for useful already implemented methods).
virtual void conversion_to_fem(lifex::LinAlg::MPI::Vector &sol_owned)
To convert a discretized solution from modal to nodal basis (does nothing if problem is already in no...
void create_mesh()
Load the mesh from the default path.
lifex::LinAlg::MPI::Vector solution_owned
Distributed solution vector, without ghost entries.
std::shared_ptr< dealii::Function< lifex::dim > > f_ex
Known forcing term.
lifex::utils::PreconditionerHandler preconditioner
Preconditioner handler.
double prm_penalty_coeff
DG Penalty coefficient.
std::shared_ptr< dealii::Function< lifex::dim > > grad_u_ex
Pointer to exact gradient solution Function.
virtual void output_results(std::string output_name="solution") const
Output of results.
void compute_errors(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 std::shared_ptr< dealii::Function< lifex::dim > > &grad_u_ex, const char *solution_name=(char *)"u") const
To compute the error, the error, the error and the error at the end of system solving,...
unsigned int dofs_per_cell
Number of degrees of freedom per cell.
void solve_system()
System solving.
std::shared_ptr< lifex::utils::FunctionDirichlet > u_ex
Pointer to exact solution function.
lifex::LinAlg::MPI::Vector solution_ex_owned
Distributed exact solution vector, without ghost entries.
lifex::LinAlg::MPI::Vector rhs
Distributed right hand side vector of the linear system.
void discretize_analytical_solution(const std::shared_ptr< dealii::Function< lifex::dim > > &u_analytical, lifex::LinAlg::MPI::Vector &sol_owned)
Conversion of an analytical solution from FEM to basis coefficients.
lifex::utils::LinearSolverHandler< lifex::LinAlg::MPI::Vector > linear_solver
Linear solver handler.
virtual void setup_system()
Setup of the problem before the resolution.