ExaDG
Loading...
Searching...
No Matches
divergence_penalty_operator.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 EXADG_INCOMPRESSIBLE_NAVIER_STOKES_SPATIAL_DISCRETIZATION_OPERATORS_DIVERGENCE_PENALTY_OPERATOR_H_
23#define EXADG_INCOMPRESSIBLE_NAVIER_STOKES_SPATIAL_DISCRETIZATION_OPERATORS_DIVERGENCE_PENALTY_OPERATOR_H_
24
25// ExaDG
26#include <exadg/grid/calculate_characteristic_element_length.h>
27#include <exadg/incompressible_navier_stokes/user_interface/parameters.h>
28#include <exadg/matrix_free/integrators.h>
29#include <exadg/operators/integrator_flags.h>
30#include <exadg/operators/mapping_flags.h>
31
32namespace ExaDG
33{
34namespace IncNS
35{
36/*
37 * Divergence penalty operator:
38 *
39 * ( div(v_h) , tau_div * div(u_h) )_Omega^e
40 *
41 * where
42 *
43 * v_h : test function
44 * u_h : solution
45 * tau_div: divergence penalty factor
46 *
47 * use convective term: tau_div_conv = K * ||U||_mean * h_eff
48 *
49 * where h_eff = h / (k_u+1) with a characteristic
50 * element length h derived from the element volume V_e
51 *
52 * use viscous term: tau_div_viscous = K * nu
53 *
54 * use both terms: tau_div = tau_div_conv + tau_div_viscous
55 *
56 */
57
58namespace Operators
59{
60struct DivergencePenaltyKernelData
61{
62 DivergencePenaltyKernelData()
63 : type_penalty_parameter(TypePenaltyParameter::ConvectiveTerm),
64 viscosity(0.0),
65 degree(1),
66 penalty_factor(1.0)
67 {
68 }
69
70 // type of penalty parameter (viscous and/or convective terms)
71 TypePenaltyParameter type_penalty_parameter;
72
73 // viscosity, needed for computation of penalty factor
74 double viscosity;
75
76 // degree of finite element shape functions
77 unsigned int degree;
78
79 // the penalty term can be scaled by 'penalty_factor'
80 double penalty_factor;
81};
82
83template<int dim, typename Number>
84class DivergencePenaltyKernel
85{
86private:
87 typedef CellIntegrator<dim, dim, Number> IntegratorCell;
88
89 typedef dealii::LinearAlgebra::distributed::Vector<Number> VectorType;
90
91 typedef dealii::VectorizedArray<Number> scalar;
92
93public:
94 DivergencePenaltyKernel()
95 : matrix_free(nullptr), dof_index(0), quad_index(0), array_penalty_parameter(0)
96 {
97 }
98
99 void
100 reinit(dealii::MatrixFree<dim, Number> const & matrix_free,
101 unsigned int const dof_index,
102 unsigned int const quad_index,
103 DivergencePenaltyKernelData const & data)
104 {
105 this->matrix_free = &matrix_free;
106
107 this->dof_index = dof_index;
108 this->quad_index = quad_index;
109
110 this->data = data;
111
112 unsigned int n_cells = matrix_free.n_cell_batches() + matrix_free.n_ghost_cell_batches();
113 array_penalty_parameter.resize(n_cells);
114 }
115
117 get_data()
118 {
119 return this->data;
120 }
121
123 get_integrator_flags() const
124 {
125 IntegratorFlags flags;
126
127 flags.cell_evaluate = dealii::EvaluationFlags::gradients;
128 flags.cell_integrate = dealii::EvaluationFlags::gradients;
129
130 // no face integrals
131
132 return flags;
133 }
134
135 static MappingFlags
136 get_mapping_flags()
137 {
138 MappingFlags flags;
139
140 flags.cells = dealii::update_JxW_values | dealii::update_gradients;
141
142 // no face integrals
143
144 return flags;
145 }
146
147 void
148 calculate_penalty_parameter(VectorType const & velocity)
149 {
150 velocity.update_ghost_values();
151
152 IntegratorCell integrator(*matrix_free, dof_index, quad_index);
153
154 dealii::AlignedVector<scalar> JxW_values(integrator.n_q_points);
155
156 ElementType const element_type =
157 get_element_type(matrix_free->get_dof_handler(dof_index).get_triangulation());
158
159 unsigned int n_cells = matrix_free->n_cell_batches() + matrix_free->n_ghost_cell_batches();
160 for(unsigned int cell = 0; cell < n_cells; ++cell)
161 {
162 scalar tau_convective = dealii::make_vectorized_array<Number>(0.0);
163 scalar tau_viscous = dealii::make_vectorized_array<Number>(data.viscosity);
164
165 if(data.type_penalty_parameter == TypePenaltyParameter::ConvectiveTerm or
166 data.type_penalty_parameter == TypePenaltyParameter::ViscousAndConvectiveTerms)
167 {
168 integrator.reinit(cell);
169 integrator.read_dof_values(velocity);
170 integrator.evaluate(dealii::EvaluationFlags::values);
171
172 scalar volume = dealii::make_vectorized_array<Number>(0.0);
173 scalar norm_U_mean = dealii::make_vectorized_array<Number>(0.0);
174 for(unsigned int q = 0; q < integrator.n_q_points; ++q)
175 {
176 volume += integrator.JxW(q);
177 norm_U_mean += integrator.JxW(q) * integrator.get_value(q).norm();
178 }
179 norm_U_mean /= volume;
180
181 scalar h = calculate_characteristic_element_length(volume, dim, element_type);
182 scalar h_eff = calculate_high_order_element_length(h, data.degree, true);
183
184 tau_convective = norm_U_mean * h_eff;
185 }
186
187 if(data.type_penalty_parameter == TypePenaltyParameter::ConvectiveTerm)
188 {
189 array_penalty_parameter[cell] = data.penalty_factor * tau_convective;
190 }
191 else if(data.type_penalty_parameter == TypePenaltyParameter::ViscousTerm)
192 {
193 array_penalty_parameter[cell] = data.penalty_factor * tau_viscous;
194 }
195 else if(data.type_penalty_parameter == TypePenaltyParameter::ViscousAndConvectiveTerms)
196 {
197 array_penalty_parameter[cell] = data.penalty_factor * (tau_convective + tau_viscous);
198 }
199 }
200 }
201
202 void
203 reinit_cell(IntegratorCell & integrator) const
204 {
205 tau = integrator.read_cell_data(array_penalty_parameter);
206 }
207
208 /*
209 * Volume flux, i.e., the term occurring in the volume integral
210 */
211 inline DEAL_II_ALWAYS_INLINE //
212 scalar
213 get_volume_flux(IntegratorCell const & integrator, unsigned int const q) const
214 {
215 return tau * integrator.get_divergence(q);
216 }
217
218private:
219 dealii::MatrixFree<dim, Number> const * matrix_free;
220
221 unsigned int dof_index;
222 unsigned int quad_index;
223
225
226 dealii::AlignedVector<scalar> array_penalty_parameter;
227
228 mutable scalar tau;
229};
230
231} // namespace Operators
232
233struct DivergencePenaltyData
234{
235 DivergencePenaltyData() : dof_index(0), quad_index(0)
236 {
237 }
238
239 unsigned int dof_index;
240 unsigned int quad_index;
241};
242
243template<int dim, typename Number>
244class DivergencePenaltyOperator
245{
246private:
247 typedef DivergencePenaltyOperator<dim, Number> This;
248
249 typedef dealii::LinearAlgebra::distributed::Vector<Number> VectorType;
250
251 typedef std::pair<unsigned int, unsigned int> Range;
252
253 typedef CellIntegrator<dim, dim, Number> IntegratorCell;
254
256
257public:
258 DivergencePenaltyOperator();
259
260 void
261 initialize(dealii::MatrixFree<dim, Number> const & matrix_free,
262 DivergencePenaltyData const & data,
263 std::shared_ptr<Kernel> const kernel);
264
265 void
266 update(VectorType const & velocity);
267
268 void
269 apply(VectorType & dst, VectorType const & src) const;
270
271 void
272 apply_add(VectorType & dst, VectorType const & src) const;
273
274private:
275 void
276 cell_loop(dealii::MatrixFree<dim, Number> const & matrix_free,
277 VectorType & dst,
278 VectorType const & src,
279 Range const & range) const;
280
281 void
282 do_cell_integral(IntegratorCell & integrator) const;
283
284 dealii::MatrixFree<dim, Number> const * matrix_free;
285
287
288 std::shared_ptr<Operators::DivergencePenaltyKernel<dim, Number>> kernel;
289};
290
291} // namespace IncNS
292} // namespace ExaDG
293
294#endif /* EXADG_INCOMPRESSIBLE_NAVIER_STOKES_SPATIAL_DISCRETIZATION_OPERATORS_DIVERGENCE_PENALTY_OPERATOR_H_ \
295 */
Definition divergence_penalty_operator.h:85
Definition driver.cpp:33
ElementType get_element_type(dealii::Triangulation< dim > const &tria)
Definition grid_data.h:70
Number calculate_high_order_element_length(Number const element_length, unsigned int const fe_degree, bool const is_dg)
Definition calculate_characteristic_element_length.h:108
Number calculate_characteristic_element_length(Number const element_volume, unsigned int const dim, ElementType const &element_type)
Definition calculate_characteristic_element_length.h:68
Definition divergence_penalty_operator.h:234
Definition divergence_penalty_operator.h:61
Definition integrator_flags.h:31
Definition mapping_flags.h:31