ExaDG
Loading...
Searching...
No Matches
constraints.h
1/* ______________________________________________________________________
2 *
3 * ExaDG - High-Order Discontinuous Galerkin for the Exa-Scale
4 *
5 * Copyright (C) 2021 by the ExaDG authors
6 *
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 * ______________________________________________________________________
20 */
21
22#ifndef OPERATOR_CONSTRAINTS_H
23#define OPERATOR_CONSTRAINTS_H
24
25#include <deal.II/multigrid/mg_constrained_dofs.h>
26
27namespace ExaDG
28{
29namespace ConstraintUtil
30{
31namespace // anonymous namespace
32{
33template<int dim, typename Number>
34void
35add_periodicity_constraints(unsigned int const level,
36 unsigned int const target_level,
37 typename dealii::DoFHandler<dim>::face_iterator const face1,
38 typename dealii::DoFHandler<dim>::face_iterator const face2,
39 dealii::AffineConstraints<Number> & constraints)
40{
41 if(level == 0)
42 {
43 // level of interest has been reached
44 unsigned int const dofs_per_face = face1->get_fe(0).dofs_per_face;
45
46 std::vector<dealii::types::global_dof_index> dofs_1(dofs_per_face);
47 std::vector<dealii::types::global_dof_index> dofs_2(dofs_per_face);
48
49 face1->get_mg_dof_indices(target_level, dofs_1, 0);
50 face2->get_mg_dof_indices(target_level, dofs_2, 0);
51
52 for(unsigned int i = 0; i < dofs_per_face; ++i)
53 {
54 if(constraints.can_store_line(dofs_2[i]) and constraints.can_store_line(dofs_1[i]) and
55 not(constraints.is_constrained(dofs_2[i])))
56 {
57 // constraint dof and ...
58 constraints.add_line(dofs_2[i]);
59 // specify type of constraint: equality (dof_2[i]=dof_1[j]*1.0)
60 constraints.add_entry(dofs_2[i], dofs_1[i], 1.);
61 }
62 }
63 }
64 else if(face1->has_children() and face2->has_children())
65 {
66 // recursively visit all subfaces
67 for(unsigned int c = 0; c < face1->n_children(); ++c)
68 {
69 add_periodicity_constraints<dim>(
70 level - 1, target_level, face1->child(c), face2->child(c), constraints);
71 }
72 }
73}
74
75
76template<int dim, typename Number>
77void
78add_periodicity_constraints(
79 dealii::DoFHandler<dim> const & dof_handler,
80 unsigned int const level,
81 std::vector<typename dealii::GridTools::PeriodicFacePair<
82 typename dealii::Triangulation<dim>::cell_iterator>> const & periodic_face_pairs_level0,
83 dealii::AffineConstraints<Number> & affine_constraints_own)
84{
85 // loop over all periodic face pairs of level 0
86 for(auto & it : periodic_face_pairs_level0)
87 {
88 // get reference to the cells on level 0 sharing the periodic face
89 typename dealii::DoFHandler<dim>::cell_iterator cell1(&dof_handler.get_triangulation(),
90 0,
91 it.cell[1]->index(),
92 &dof_handler);
93 typename dealii::DoFHandler<dim>::cell_iterator cell0(&dof_handler.get_triangulation(),
94 0,
95 it.cell[0]->index(),
96 &dof_handler);
97
98 // get reference to periodic faces on level and add recursively their
99 // subfaces on the given level
100 add_periodicity_constraints<dim, Number>(level,
101 level,
102 cell1->face(it.face_idx[1]),
103 cell0->face(it.face_idx[0]),
104 affine_constraints_own);
105 }
106}
107
108template<int dim, typename Number>
109void
110add_constraints(bool is_dg,
111 bool operator_is_singular,
112 dealii::DoFHandler<dim> const & dof_handler,
113 dealii::AffineConstraints<Number> & affine_constraints_own,
114 dealii::MGConstrainedDoFs const & mg_constrained_dofs,
115 std::vector<dealii::GridTools::PeriodicFacePair<
116 typename dealii::Triangulation<dim>::cell_iterator>> const & periodic_face_pairs,
117 unsigned int const level)
118{
119 if(is_dg)
120 {
121 // for DG: nothing to do
122 affine_constraints_own.close();
123 return;
124 }
125 // 0) clear old content (to be on the safe side)
126 affine_constraints_own.clear();
127
128 // ... and set local dofs
129 dealii::IndexSet relevant_dofs;
130 if(level != dealii::numbers::invalid_unsigned_int)
131 dealii::DoFTools::extract_locally_relevant_level_dofs(dof_handler, level, relevant_dofs);
132 else
133 dealii::DoFTools::extract_locally_relevant_dofs(dof_handler, relevant_dofs);
134 affine_constraints_own.reinit(relevant_dofs);
135
136 // 1) add periodic BCs
137 add_periodicity_constraints<dim, Number>(dof_handler,
138 level,
139 periodic_face_pairs,
140 affine_constraints_own);
141
142 // 2) add Dirichlet BCs
143 if(mg_constrained_dofs.have_boundary_indices())
144 affine_constraints_own.add_lines(mg_constrained_dofs.get_boundary_indices(level));
145
146 // constrain zeroth DoF in continuous case (the mean value constraint will
147 // be applied in the DG case). In case we have interface matrices, there are
148 // Dirichlet constraints on parts of the boundary and no such transformation
149 // is required.
150 if(operator_is_singular and affine_constraints_own.can_store_line(0))
151 {
152 // if dof 0 is constrained, it must be a periodic dof, so we take the
153 // value on the other side
154 dealii::types::global_dof_index line_index = 0;
155 while(true)
156 {
157 auto const * lines = affine_constraints_own.get_constraint_entries(line_index);
158
159 if(lines == 0)
160 {
161 affine_constraints_own.add_line(line_index);
162 // add the constraint back to the dealii::MGConstrainedDoFs field. This
163 // is potentially dangerous but we know what we are doing... ;-)
164 if(mg_constrained_dofs.have_boundary_indices() &&
165 level != dealii::numbers::invalid_unsigned_int)
166 {
167 if(mg_constrained_dofs.get_boundary_indices(level).size() != dof_handler.n_dofs(level))
168 const_cast<dealii::IndexSet &>(mg_constrained_dofs.get_boundary_indices(level))
169 .set_size(dof_handler.n_dofs(level));
170 const_cast<dealii::IndexSet &>(mg_constrained_dofs.get_boundary_indices(level))
171 .add_index(line_index);
172 }
173
174 break;
175 }
176 else
177 {
178 Assert(lines->size() == 1 and std::abs((*lines)[0].second - 1.) < 1e-15,
179 dealii::ExcMessage("Periodic index expected, bailing out"));
180
181 line_index = (*lines)[0].first;
182 }
183 }
184 }
185
186 affine_constraints_own.close();
187}
188
189
190} // namespace
191} // namespace ConstraintUtil
192} // namespace ExaDG
193
194#endif
Definition driver.cpp:33