DUBeat  1.0.1
High-order discontinuous Galerkin methods and applications to cardiac electrophysiology
dof_handler_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 DOF_HANDLER_DG_HPP_
28 #define DOF_HANDLER_DG_HPP_
29 
30 #include <deal.II/base/quadrature.h>
31 
32 #include <deal.II/dofs/dof_handler.h>
33 
34 #include <deal.II/fe/fe.h>
35 #include <deal.II/fe/mapping_q1_eulerian.h>
36 
37 #include <deal.II/lac/trilinos_vector.h>
38 
39 #include <cmath>
40 #include <map>
41 #include <vector>
42 
43 #include "DUBValues.hpp"
44 #include "source/init.hpp"
45 
46 
47 using ActiveSelector = dealii::internal::DoFHandlerImplementation::
48  Iterators<lifex::dim, lifex::dim, false>;
50 
64 template <class basis>
65 class DoFHandlerDG : public dealii::DoFHandler<lifex::dim>
66 {
67 private:
69  unsigned int degree;
70 
72  std::map<active_cell_iterator, std::vector<unsigned int>> dof_map;
73 
74 public:
77  : dealii::DoFHandler<lifex::dim>()
78  , degree(0)
79  {}
80 
83 
85  DoFHandlerDG<basis>(const DoFHandlerDG<basis> &DOFHandlerDG) = default;
86 
89 
91  unsigned int
92  n_dofs_per_cell() const;
93 
95  unsigned int
96  n_dofs() const;
97 
101  void
102  distribute_dofs(const dealii::FE_SimplexDGP<lifex::dim> &fe);
103 
106  void
107  distribute_dofs(const unsigned int degree);
108 
110  std::vector<lifex::types::global_dof_index>
112 
115  dealii::IndexSet
116  locally_owned_dofs() const;
117 };
118 
119 template <class basis>
120 unsigned int
122 {
123  AssertThrow(degree > 0,
124  dealii::StandardExceptions::ExcMessage(
125  "Dofs have not been distributed yet. Please, use "
126  "distribute_dofs before."));
127 
128  // The analytical formula is:
129  // n_dof_per_cell = (p+1)*(p+2)*...(p+d) / d!,
130  // where p is the space order and d the space dimension..
131 
132  unsigned int denominator = 1;
133  unsigned int nominator = 1;
134 
135  for (unsigned int i = 1; i <= lifex::dim; i++)
136  {
137  denominator *= i;
138  nominator *= degree + i;
139  }
140 
141  return (int)(nominator / denominator);
142 }
143 
144 template <class basis>
145 unsigned int
147 {
148  AssertThrow(degree > 0,
149  dealii::StandardExceptions::ExcMessage(
150  "Dofs have not been distributed yet. Please, use "
151  "distribute_dofs before."));
152 
153  unsigned int n_cells = 0;
154 
155  for (const auto &cell : this->active_cell_iterators())
156  n_cells++;
157 
158  // The global nuber of dofs is the number of dofs per cell times the total
159  // number of cells since every cell has the same number of dofs.
160  return n_cells * n_dofs_per_cell();
161 }
162 
163 
166 template <>
167 void
169  const dealii::FE_SimplexDGP<lifex::dim> &fe)
170 {
171  AssertThrow(fe.degree < 3,
172  dealii::StandardExceptions::ExcMessage(
173  "deal.II library does not provide yet FEM spaces with "
174  "polynomial order > 2."));
175  degree = fe.degree;
176  dealii::DoFHandler<lifex::dim>::distribute_dofs(fe);
177 }
178 
182 template <>
183 void
185  const dealii::FE_SimplexDGP<lifex::dim> &fe)
186 {
187  AssertThrow(fe.degree < 3,
188  dealii::StandardExceptions::ExcMessage(
189  "deal.II library does not provide yet FEM spaces with "
190  "polynomial order > 2."));
191  dealii::DoFHandler<lifex::dim>::distribute_dofs(fe);
192  degree = fe.degree;
193 
194  std::vector<lifex::types::global_dof_index> dof_indices(
195  this->n_dofs_per_cell());
196  dof_map.clear();
197 
198  for (const auto &cell : this->active_cell_iterators())
199  {
200  // In the dof_map, for every cell we assign the global dofs.
201  cell->get_dof_indices(dof_indices);
202  dof_map.emplace(cell, dof_indices);
203  }
204 }
205 
208 template <>
209 void
211  const unsigned int degree)
212 {
213  AssertThrow(
214  degree,
215  dealii::StandardExceptions::ExcMessage(
216  "deal.II library does not provide yet the Lagrangian DG basis with "
217  "polynomial order > 2."));
218  dealii::FE_SimplexDGP<lifex::dim> fe(degree);
219  this->distribute_dofs(fe);
220 }
221 
222 
227 template <>
228 void
229 DoFHandlerDG<DUBValues<lifex::dim>>::distribute_dofs(const unsigned int degree)
230 {
231  this->degree = degree;
232  unsigned int n_dofs_per_cell = this->n_dofs_per_cell();
233  dof_map.clear();
234  unsigned int n = 0;
235  for (const auto &cell : this->active_cell_iterators())
236  {
237  std::vector<unsigned int> local_dofs;
238 
239  for (unsigned int i = 0; i < n_dofs_per_cell; ++i)
240  local_dofs.push_back(n + i);
241 
242  dof_map.emplace(cell, local_dofs);
243 
244  n = n + n_dofs_per_cell;
245  }
246 }
247 
250 template <>
251 std::vector<lifex::types::global_dof_index>
253  active_cell_iterator cell) const
254 {
255  std::vector<lifex::types::global_dof_index> dof_indices(
256  this->n_dofs_per_cell());
257  cell->get_dof_indices(dof_indices);
258  return dof_indices;
259 }
260 
261 
264 template <>
265 std::vector<lifex::types::global_dof_index>
267  active_cell_iterator cell) const
268 {
269  std::vector<lifex::types::global_dof_index> dof_indices(
270  this->n_dofs_per_cell());
271  dof_indices = dof_map.at(cell);
272  return dof_indices;
273 }
274 
275 template <class basis>
276 dealii::IndexSet
278 {
279  dealii::IndexSet owned_dofs(this->n_dofs());
280  // For the time being, this function returns all the dofs.
281  owned_dofs.add_range(0, this->n_dofs());
282  return owned_dofs;
283 }
284 
285 
286 #endif /* DOF_HANDLER_DG_HPP_*/
Class to work with global and local degrees of freedom and their mapping.
void distribute_dofs(const dealii::FE_SimplexDGP< lifex::dim > &fe)
Distribute dofs through the elements.
void distribute_dofs(const unsigned int degree)
Same method but avoids to use FiniteElement classes that might be invalid with higher order polynomia...
unsigned int n_dofs() const
Return copy of n_dofs.
std::vector< lifex::types::global_dof_index > get_dof_indices(active_cell_iterator cell) const
Returns the global dofs referred to the input cell.
unsigned int n_dofs_per_cell() const
Return copy of n_dofs_per_cell.
unsigned int degree
Polynomial space degree.
std::map< active_cell_iterator, std::vector< unsigned int > > dof_map
Local to global dof map.
dealii::IndexSet locally_owned_dofs() const
Return a set of all the locally owned dofs (for the time being, it is equivalent to return all the do...
typename ActiveSelector::active_cell_iterator active_cell_iterator
dealii::internal::DoFHandlerImplementation::Iterators< lifex::dim, lifex::dim, false > ActiveSelector