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 velocity.zero_out_ghost_values();
202 }
203
204 void
205 reinit_cell(IntegratorCell & integrator) const
206 {
207 tau = integrator.read_cell_data(array_penalty_parameter);
208 }
209
210 /*
211 * Volume flux, i.e., the term occurring in the volume integral
212 */
213 inline DEAL_II_ALWAYS_INLINE //
214 scalar
215 get_volume_flux(IntegratorCell const & integrator, unsigned int const q) const
216 {
217 return tau * integrator.get_divergence(q);
218 }
219
220private:
221 dealii::MatrixFree<dim, Number> const * matrix_free;
222
223 unsigned int dof_index;
224 unsigned int quad_index;
225
227
228 dealii::AlignedVector<scalar> array_penalty_parameter;
229
230 mutable scalar tau;
231};
232
233} // namespace Operators
234
235struct DivergencePenaltyData
236{
237 DivergencePenaltyData() : dof_index(0), quad_index(0)
238 {
239 }
240
241 unsigned int dof_index;
242 unsigned int quad_index;
243};
244
245template<int dim, typename Number>
246class DivergencePenaltyOperator
247{
248private:
249 typedef DivergencePenaltyOperator<dim, Number> This;
250
251 typedef dealii::LinearAlgebra::distributed::Vector<Number> VectorType;
252
253 typedef std::pair<unsigned int, unsigned int> Range;
254
255 typedef CellIntegrator<dim, dim, Number> IntegratorCell;
256
258
259public:
260 DivergencePenaltyOperator();
261
262 void
263 initialize(dealii::MatrixFree<dim, Number> const & matrix_free,
264 DivergencePenaltyData const & data,
265 std::shared_ptr<Kernel> const kernel);
266
267 void
268 update(VectorType const & velocity);
269
270 void
271 apply(VectorType & dst, VectorType const & src) const;
272
273 void
274 apply_add(VectorType & dst, VectorType const & src) const;
275
276private:
277 void
278 cell_loop(dealii::MatrixFree<dim, Number> const & matrix_free,
279 VectorType & dst,
280 VectorType const & src,
281 Range const & range) const;
282
283 void
284 do_cell_integral(IntegratorCell & integrator) const;
285
286 dealii::MatrixFree<dim, Number> const * matrix_free;
287
289
290 std::shared_ptr<Operators::DivergencePenaltyKernel<dim, Number>> kernel;
291};
292
293} // namespace IncNS
294} // namespace ExaDG
295
296#endif /* EXADG_INCOMPRESSIBLE_NAVIER_STOKES_SPATIAL_DISCRETIZATION_OPERATORS_DIVERGENCE_PENALTY_OPERATOR_H_ \
297 */
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:236
Definition divergence_penalty_operator.h:61
Definition integrator_flags.h:31
Definition mapping_flags.h:31