DUBeat  1.0.1
High-order discontinuous Galerkin methods and applications to cardiac electrophysiology
laplace_dg.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 LAPLACE_DG_HPP_
28 #define LAPLACE_DG_HPP_
29 
30 #include <memory>
31 #include <vector>
32 
33 #include "../source/DUBValues.hpp"
34 #include "../source/DUB_FEM_handler.hpp"
35 #include "../source/assemble_DG.hpp"
36 #include "../source/face_handler_DG.hpp"
37 #include "../source/model_DG.hpp"
38 #include "../source/volume_handler_DG.hpp"
39 #include "source/core_model.hpp"
40 #include "source/geometry/mesh_handler.hpp"
41 #include "source/init.hpp"
42 #include "source/io/data_writer.hpp"
43 #include "source/numerics/bc_handler.hpp"
44 #include "source/numerics/linear_solver_handler.hpp"
45 #include "source/numerics/preconditioner_handler.hpp"
46 #include "source/numerics/tools.hpp"
47 
48 namespace DUBeat::models
49 {
50  namespace laplace_DG
51  {
55  class ExactSolution : public lifex::utils::FunctionDirichlet
56  {
57  public:
60  : lifex::utils::FunctionDirichlet()
61  {}
62 
64  virtual double
65  value(const dealii::Point<lifex::dim> &p,
66  const unsigned int /*component*/ = 0) const override
67  {
68  if (lifex::dim == 2)
69  return std::exp(p[0] + p[1]);
70  else
71  return std::exp(p[0] + p[1] + p[2]);
72  }
73  };
74 
78  class RightHandSide : public lifex::Function<lifex::dim>
79  {
80  public:
83  : Function<lifex::dim>()
84  {}
85 
87  virtual double
88  value(const dealii::Point<lifex::dim> &p,
89  const unsigned int /*component*/ = 0) const override
90  {
91  if (lifex::dim == 2)
92  return -2 * std::exp(p[0] + p[1]);
93  else
94  return -3 * std::exp(p[0] + p[1] + p[2]);
95  }
96  };
97 
101  class GradExactSolution : public lifex::Function<lifex::dim>
102  {
103  public:
106  : Function<lifex::dim>()
107  {}
108 
110  virtual double
111  value(const dealii::Point<lifex::dim> &p,
112  const unsigned int component = 0) const override
113  {
114  if (lifex::dim == 2)
115  {
116  if (component == 0) // x
117  return std::exp(p[0] + p[1]);
118  else // y
119  return std::exp(p[0] + p[1]);
120  }
121  else // dim=3
122  {
123  if (component == 0) // x
124  return std::exp(p[0] + p[1] + p[2]);
125  if (component == 1) // y
126  return std::exp(p[0] + p[1] + p[2]);
127  else // z
128  return std::exp(p[0] + p[1] + p[2]);
129  }
130  }
131  };
132  } // namespace laplace_DG
133 
160  template <class basis>
161  class LaplaceDG : public ModelDG<basis>
162  {
163  public:
166  : ModelDG<basis>("Laplace")
167  {
168  this->u_ex = std::make_shared<laplace_DG::ExactSolution>();
169  this->grad_u_ex = std::make_shared<laplace_DG::GradExactSolution>();
170  this->f_ex = std::make_shared<laplace_DG::RightHandSide>();
171  }
172 
173  private:
174  void
175  assemble_system() override;
176  };
177 
179  template <class basis>
180  void
182  {
183  this->matrix = 0;
184  this->rhs = 0;
185 
186  // The method is needed to define how the system matrix and rhs term are
187  // defined for the Laplace problem with Dirichlet boundary conditions. The
188  // full matrix is composed by different sub-matrices that are called with
189  // simple capital letters. We refer here to the DG_Assemble methods for
190  // their definition.
191 
192  // See DG_Assemble::local_V().
193  dealii::FullMatrix<double> V(this->dofs_per_cell, this->dofs_per_cell);
194  // See DG_Assemble::local_SC().
195  dealii::FullMatrix<double> SC(this->dofs_per_cell, this->dofs_per_cell);
196  // See DG_Assemble::local_IC().
197  dealii::FullMatrix<double> IC(this->dofs_per_cell, this->dofs_per_cell);
198  // Transpose of IC.
199  dealii::FullMatrix<double> IC_t(this->dofs_per_cell, this->dofs_per_cell);
200  // See DG_Assemble::local_IB().
201  dealii::FullMatrix<double> IB(this->dofs_per_cell, this->dofs_per_cell);
202  // Transpose of IB.
203  dealii::FullMatrix<double> IB_t(this->dofs_per_cell, this->dofs_per_cell);
204  // See DG_Assemble::local_IN().
205  dealii::FullMatrix<double> IN(this->dofs_per_cell, this->dofs_per_cell);
206  // Transpose of IN.
207  dealii::FullMatrix<double> IN_t(this->dofs_per_cell, this->dofs_per_cell);
208  // See DG_Assemble::local_SN().
209  dealii::FullMatrix<double> SN(this->dofs_per_cell, this->dofs_per_cell);
210 
211  // See DG_Assemble::local_rhs().
212  dealii::Vector<double> cell_rhs(this->dofs_per_cell);
213  // See DG_Assemble::local_rhs_edge_dirichlet().
214  dealii::Vector<double> cell_rhs_edge(this->dofs_per_cell);
215 
216  std::vector<lifex::types::global_dof_index> dof_indices(
217  this->dofs_per_cell);
218 
219  for (const auto &cell : this->dof_handler.active_cell_iterators())
220  {
221  if (cell->is_locally_owned())
222  {
223  this->assemble->reinit(cell);
224  dof_indices = this->dof_handler.get_dof_indices(cell);
225 
226  V = this->assemble->local_V();
227  cell_rhs = this->assemble->local_rhs(this->f_ex);
228 
229  this->matrix.add(dof_indices, V);
230  this->rhs.add(dof_indices, cell_rhs);
231 
232  for (const auto &edge : cell->face_indices())
233  {
234  this->assemble->reinit(cell, edge);
235  std::vector<lifex::types::global_dof_index> dof_indices_neigh(
236  this->dofs_per_cell);
237 
238  SC = this->assemble->local_SC(this->prm_stability_coeff);
239  this->matrix.add(dof_indices, SC);
240 
241  if (!cell->at_boundary(edge))
242  {
243  std::tie(IC, IC_t) =
244  this->assemble->local_IC(this->prm_penalty_coeff);
245  this->matrix.add(dof_indices, IC);
246  this->matrix.add(dof_indices, IC_t);
247 
248  const auto neighcell = cell->neighbor(edge);
249  dof_indices_neigh =
250  this->dof_handler.get_dof_indices(neighcell);
251 
252  std::tie(IN, IN_t) =
253  this->assemble->local_IN(this->prm_penalty_coeff);
254  SN = this->assemble->local_SN(this->prm_stability_coeff);
255 
256  this->matrix.add(dof_indices, dof_indices_neigh, IN);
257  this->matrix.add(dof_indices_neigh, dof_indices, IN_t);
258  this->matrix.add(dof_indices, dof_indices_neigh, SN);
259  }
260  else
261  {
262  std::tie(IB, IB_t) =
263  this->assemble->local_IB(this->prm_penalty_coeff);
264  cell_rhs_edge = this->assemble->local_rhs_edge_dirichlet(
265  this->prm_stability_coeff,
266  this->prm_penalty_coeff,
267  this->u_ex);
268  this->matrix.add(dof_indices, IB);
269  this->matrix.add(dof_indices, IB_t);
270  this->rhs.add(dof_indices, cell_rhs_edge);
271  }
272  }
273  }
274  }
275 
276  this->matrix.compress(dealii::VectorOperation::add);
277  this->rhs.compress(dealii::VectorOperation::add);
278  }
279 } // namespace DUBeat::models
280 
281 #endif /* LAPLACE_DG_HPP_*/
Class to solve the Laplace equation using the Discontinuous Galerkin method.
Definition: laplace_dg.hpp:162
void assemble_system() override
Assembly of the linear system.
Definition: laplace_dg.hpp:181
virtual double value(const dealii::Point< lifex::dim > &p, const unsigned int=0) const override
Evaluate the exact solution in a point.
Definition: laplace_dg.hpp:65
Gradient of the exact solution.
Definition: laplace_dg.hpp:102
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.
Definition: laplace_dg.hpp:111
virtual double value(const dealii::Point< lifex::dim > &p, const unsigned int=0) const override
Evaluate the source term in a point.
Definition: laplace_dg.hpp:88
Class representing the resolution of problems using discontinuous Galerkin methods.
Definition: model_DG.hpp:63
std::shared_ptr< dealii::Function< lifex::dim > > f_ex
Known forcing term.
Definition: model_DG.hpp:255
std::shared_ptr< dealii::Function< lifex::dim > > grad_u_ex
Pointer to exact gradient solution Function.
Definition: model_DG.hpp:253
std::shared_ptr< lifex::utils::FunctionDirichlet > u_ex
Pointer to exact solution function.
Definition: model_DG.hpp:251