MAIA bb96820c
Multiphysics at AIA
Loading...
Searching...
No Matches
dgcartesiansyseqnlinearscalaradv.h
Go to the documentation of this file.
1// Copyright (C) 2024 The m-AIA AUTHORS
2//
3// This file is part of m-AIA (https://git.rwth-aachen.de/aia/m-AIA/m-AIA)
4//
5// SPDX-License-Identifier: LGPL-3.0-only
6
7#ifndef DGSYSEQNLINEARSCALARADV_H_
8#define DGSYSEQNLINEARSCALARADV_H_
9
10#include <algorithm>
11#include <limits>
12#include <numeric>
14#include "INCLUDE/maiatypes.h"
15#include "UTIL/tensor.h"
16#include "dgcartesiansyseqn.h"
17
18template <MInt nDim>
19class DgSysEqnLinearScalarAdv : public DgSysEqn<nDim, DgSysEqnLinearScalarAdv<nDim>> {
20 // Declare parent a friend so that CRTP can access this class's private
21 // methods/members
22 friend class DgSysEqn<nDim, DgSysEqnLinearScalarAdv>;
23
24 // Member functions
25 public:
26 explicit DgSysEqnLinearScalarAdv(MInt solverId);
27 void calcInitialCondition(const MFloat t, const MFloat* x, MFloat* nodeVars, MFloat* u) const;
28 void calcFlux(const MFloat* nodeVars, const MFloat* u, const MInt noNodes1D, MFloat* flux) const;
29 void calcSource(const MFloat* nodeVars, const MFloat* u, const MInt noNodes1D, const MFloat t, const MFloat* x,
30 MFloat* src) const;
31 void calcSpongeSource(const MFloat* nodeVars, const MFloat* u, const MInt noNodes1D, const MFloat* eta,
32 MFloat* src) const;
33 MFloat getTimeStep(const MFloat* nodeVars, const MFloat* u, const MInt noNodes1D, const MFloat invJacobian,
34 const MInt sbpMode) const;
35 void calcRiemann(const MFloat* nodeVarsL, const MFloat* nodeVarsR, const MFloat* stateL, const MFloat* stateR,
36 const MInt noNodes1D, const MInt dirId, MFloat* flux) const;
37 void primToCons(const MFloat* prim, MFloat* cons) const;
38 void consToPrim(const MFloat* cons, MFloat* prim) const;
39
40 MFloat cflFactor(const MInt polyDeg) const;
41
42 void getDefaultNodeVars(MFloat* const NotUsed(nodeVars)) const {};
43 MBool extendNodeVar(const MInt NotUsed(varId)) const { return true; };
44
45 // Member variables
46 private:
47 static const MString s_sysEqnName;
48
49 static const MInt s_noVariables = 1;
52
53 static const MInt s_noNodeVars = 0;
54 static const MBool s_hasTimeDependentNodeVars = false;
55 static constexpr const MString* s_nodeVarNames = nullptr;
56
58
61 static const MInt s_maxPolyDeg = 31;
62 std::array<std::array<MFloat, s_maxPolyDeg + 1>, 2> m_cflFactor;
63};
64
65// Initialize static member variables
66template <MInt nDim>
67const MString DgSysEqnLinearScalarAdv<nDim>::s_sysEqnName = "DG_SYSEQN_LINEARSCALARADV";
68
69template <MInt nDim>
71
72template <MInt nDim>
74
75
85template <MInt nDim>
87 : DgSysEqn<nDim, DgSysEqnLinearScalarAdv>(solverId) {
88 // Read and set advection velocity
89 for(MInt i = 0; i < nDim; i++) {
90 m_advectionVelocity[i] = F1;
100 Context::getSolverProperty<MFloat>("advectionVelocity", this->m_solverId, AT_, &m_advectionVelocity[i], i);
101 }
102
103 // Get the quadrature method being used
104 MString dgIntegrationMethod = "DG_INTEGRATE_GAUSS";
106 Context::getSolverProperty<MString>("dgIntegrationMethod", this->m_solverId, AT_, &dgIntegrationMethod);
107
108 // Get the time integration scheme being used
109 MString dgTimeIntegrationScheme = "DG_TIMEINTEGRATION_CARPENTER_4_5";
111 Context::getSolverProperty<MString>("dgTimeIntegrationScheme", this->m_solverId, AT_, &dgTimeIntegrationScheme));
112
113
114 // cfl correction factor table - Obtained by running different test cases
115 // to get the maximum stable CFL number solution for polynomial degrees
116 // varying from 0 to 15. 1st row -> 2D cases & 2nd row -> 3D cases.
117 // Note: The cfl factors are not calibrated and thus not suitable to be used
118 // with RiemannRoe's Flux.
121 default:
122 if(m_dgIntegrationMethod == "DG_INTEGRATE_GAUSS") {
123 // Legendre-Gauss nodes
124 m_cflFactor = {{{{2.448730, 2.420654, 2.171631, 1.834717, 1.652832, 1.497803, 1.369629, 1.246338, 1.151123,
125 1.071777, 1.015625, 0.959473, 0.904541, 0.856934, 0.814209, 0.783691}},
126 {{2.891846, 2.716064, 2.454112, 2.081513, 1.877617, 1.702831, 1.523950, 1.382303, 1.281892,
127 1.203783, 1.132922, 1.060420, 1.002581, 0.960691, 0.912857, 0.868814}}}};
128 } else {
129 // Legendre-Gauss-Lobatto nodes
130 m_cflFactor = {{{{5.277100, 5.277100, 3.908691, 3.056641, 2.852783, 2.486572, 2.232660, 2.036133, 1.865234,
131 1.748047, 1.624756, 1.542969, 1.455078, 1.365967, 1.307373, 1.243896}},
132 {{5.848389, 5.848389, 3.948975, 3.621826, 3.244629, 2.897949, 2.618408, 2.298584, 2.114258,
133 1.972656, 1.834717, 1.741943, 1.669922, 1.539307, 1.470947, 1.406250}}}};
134 }
135 break;
136 }
138 // Using CFL factors used for CARPENTER 4/5
139 if(m_dgIntegrationMethod == "DG_INTEGRATE_GAUSS") {
140 // Legendre-Gauss nodes
141 m_cflFactor = {{{{2.448730, 2.420654, 2.171631, 1.834717, 1.652832, 1.497803, 1.369629, 1.246338, 1.151123,
142 1.071777, 1.015625, 0.959473, 0.904541, 0.856934, 0.814209, 0.783691}},
143 {{2.891846, 2.716064, 2.454112, 2.081513, 1.877617, 1.702831, 1.523950, 1.382303, 1.281892,
144 1.203783, 1.132922, 1.060420, 1.002581, 0.960691, 0.912857, 0.868814}}}};
145 } else {
146 // Legendre-Gauss-Lobatto nodes
147 m_cflFactor = {{{{5.277100, 5.277100, 3.908691, 3.056641, 2.852783, 2.486572, 2.232660, 2.036133, 1.865234,
148 1.748047, 1.624756, 1.542969, 1.455078, 1.365967, 1.307373, 1.243896}},
149 {{5.848389, 5.848389, 3.948975, 3.621826, 3.244629, 2.897949, 2.618408, 2.298584, 2.114258,
150 1.972656, 1.834717, 1.741943, 1.669922, 1.539307, 1.470947, 1.406250}}}};
151 }
152 break;
153 }
155 if(m_dgIntegrationMethod == "DG_INTEGRATE_GAUSS") {
156 // Legendre-Gauss nodes
157 m_cflFactor = {{{{9.878051, 7.782532, 6.381652, 5.689331, 5.249816, 4.883361, 4.852050, 4.584167, 4.302368,
158 4.062316, 3.855896, 3.674987, 3.481323, 3.322448, 3.161255, 3.032532}},
159 {{11.289367, 10.013732, 7.770935, 7.036865, 6.197266, 5.667297, 5.417968, 5.106018, 4.787108,
160 4.493713, 4.266418, 4.072753, 3.840820, 3.692383, 3.507995, 3.385070}}}};
161 } else {
162 // Legendre-Gauss-Lobatto nodes
163 m_cflFactor = {{{{16.500915, 16.500915, 10.074035, 8.384399, 7.637573, 6.993957, 6.730712, 6.372375, 6.059265,
164 5.831970, 5.558288, 5.319396, 5.126892, 4.957580, 4.782471, 4.585327}},
165 {{18.998840, 18.998840, 11.339233, 9.595093, 8.869141, 8.107239, 7.406799, 6.981201, 6.632140,
166 6.465149, 6.123046, 5.956054, 5.783263, 5.485229, 5.329834, 5.112976}}}};
167 }
168 break;
169 }
171 // Using CFL factors used for CARPENTER 4/5
172 if(m_dgIntegrationMethod == "DG_INTEGRATE_GAUSS") {
173 // Legendre-Gauss nodes
174 m_cflFactor = {{{{2.448730, 2.420654, 2.171631, 1.834717, 1.652832, 1.497803, 1.369629, 1.246338, 1.151123,
175 1.071777, 1.015625, 0.959473, 0.904541, 0.856934, 0.814209, 0.783691}},
176 {{2.891846, 2.716064, 2.454112, 2.081513, 1.877617, 1.702831, 1.523950, 1.382303, 1.281892,
177 1.203783, 1.132922, 1.060420, 1.002581, 0.960691, 0.912857, 0.868814}}}};
178 } else {
179 // Legendre-Gauss-Lobatto nodes
180 m_cflFactor = {{{{5.277100, 5.277100, 3.908691, 3.056641, 2.852783, 2.486572, 2.232660, 2.036133, 1.865234,
181 1.748047, 1.624756, 1.542969, 1.455078, 1.365967, 1.307373, 1.243896}},
182 {{5.848389, 5.848389, 3.948975, 3.621826, 3.244629, 2.897949, 2.618408, 2.298584, 2.114258,
183 1.972656, 1.834717, 1.741943, 1.669922, 1.539307, 1.470947, 1.406250}}}};
184 }
185 break;
186 }
188 // Using CFL factors used for CARPENTER 4/5
189 if(m_dgIntegrationMethod == "DG_INTEGRATE_GAUSS") {
190 // Legendre-Gauss nodes
191 m_cflFactor = {{{{2.448730, 2.420654, 2.171631, 1.834717, 1.652832, 1.497803, 1.369629, 1.246338, 1.151123,
192 1.071777, 1.015625, 0.959473, 0.904541, 0.856934, 0.814209, 0.783691}},
193 {{2.891846, 2.716064, 2.454112, 2.081513, 1.877617, 1.702831, 1.523950, 1.382303, 1.281892,
194 1.203783, 1.132922, 1.060420, 1.002581, 0.960691, 0.912857, 0.868814}}}};
195 } else {
196 // Legendre-Gauss-Lobatto nodes
197 m_cflFactor = {{{{5.277100, 5.277100, 3.908691, 3.056641, 2.852783, 2.486572, 2.232660, 2.036133, 1.865234,
198 1.748047, 1.624756, 1.542969, 1.455078, 1.365967, 1.307373, 1.243896}},
199 {{5.848389, 5.848389, 3.948975, 3.621826, 3.244629, 2.897949, 2.618408, 2.298584, 2.114258,
200 1.972656, 1.834717, 1.741943, 1.669922, 1.539307, 1.470947, 1.406250}}}};
201 }
202 break;
203 }
205 // Using CFL factors used for CARPENTER 4/5
206 if(m_dgIntegrationMethod == "DG_INTEGRATE_GAUSS") {
207 // Legendre-Gauss nodes
208 m_cflFactor = {{{{2.448730, 2.420654, 2.171631, 1.834717, 1.652832, 1.497803, 1.369629, 1.246338, 1.151123,
209 1.071777, 1.015625, 0.959473, 0.904541, 0.856934, 0.814209, 0.783691}},
210 {{2.891846, 2.716064, 2.454112, 2.081513, 1.877617, 1.702831, 1.523950, 1.382303, 1.281892,
211 1.203783, 1.132922, 1.060420, 1.002581, 0.960691, 0.912857, 0.868814}}}};
212 } else {
213 // Legendre-Gauss-Lobatto nodes
214 m_cflFactor = {{{{5.277100, 5.277100, 3.908691, 3.056641, 2.852783, 2.486572, 2.232660, 2.036133, 1.865234,
215 1.748047, 1.624756, 1.542969, 1.455078, 1.365967, 1.307373, 1.243896}},
216 {{5.848389, 5.848389, 3.948975, 3.621826, 3.244629, 2.897949, 2.618408, 2.298584, 2.114258,
217 1.972656, 1.834717, 1.741943, 1.669922, 1.539307, 1.470947, 1.406250}}}};
218 }
219 break;
220 }
221 }
222}
223
234template <MInt nDim>
235void DgSysEqnLinearScalarAdv<nDim>::calcInitialCondition(const MFloat t, const MFloat* x, MFloat* NotUsed(nodeVars),
236 MFloat* u) const {
241 switch(this->m_initialCondition) {
242 case 1: {
247
248 // Set domain-specific values and user-defined properties
249 const MFloat frequency = this->m_initialNumberWaves; // = no. full oscillations in the domain
250 const MFloat A = F1B5; // = max. amplitude of the i.c.
251 const MFloat length = F2; // = side length of square/cube domain
252 const MFloat origin[] = {-F1, -F1, -F1}; // lower left corner
253
254 // Calculate initialization value
255 const MFloat omega = F2 * PI * frequency / length;
256 MFloat compound = sin(omega * (x[0] - origin[0] - m_advectionVelocity[0] * t));
257 for(MInt i = 1; i < nDim; i++) {
258 compound *= cos(omega * (x[i] - origin[i] - F1B4 * length / frequency - m_advectionVelocity[i] * t));
259 }
260 const MFloat init = F2 + A * compound;
261
262 // Set to init
263 u[0] = init;
264 break;
265 }
266 case 2: {
268 u[0] = F2;
269 break;
270 }
271 case 4: {
274
275 u[0] = F2;
276 u[0] += x[0] - m_advectionVelocity[0] * t;
277 break;
278 }
279 case 5: {
284
285 const MFloat origin[] = {F0, F0, F0}; // center of the Gauss pulse
286 MFloat xNormalized = F0;
287 for(MInt i = 0; i < nDim; i++) {
288 xNormalized += pow(x[i] - origin[i] - m_advectionVelocity[i] * t, F2);
289 }
290 u[0] = pow(F2, -25.0 * xNormalized);
291 break;
292 }
293 default:
294 mTerm(1, AT_, "The specified initial condition (" + std::to_string(this->m_initialCondition) + ")is not valid!");
295 }
296}
297
298
310template <MInt nDim>
311void DgSysEqnLinearScalarAdv<nDim>::calcFlux(const MFloat* NotUsed(nodeVars), const MFloat* u, const MInt noNodes1D,
312 MFloat* flux) const {
313 const MInt noNodes1D3 = (nDim == 3) ? noNodes1D : 1;
314 const MFloatTensor U(const_cast<MFloat*>(u), noNodes1D, noNodes1D, noNodes1D3);
315 MFloatTensor f(flux, noNodes1D, noNodes1D, noNodes1D3, nDim);
316
317 for(MInt i = 0; i < noNodes1D; i++) {
318 for(MInt j = 0; j < noNodes1D; j++) {
319 for(MInt k = 0; k < noNodes1D3; k++) {
320 for(MInt l = 0; l < nDim; l++) {
321 f(i, j, k, l) = U(i, j, k) * m_advectionVelocity[l];
322 }
323 }
324 }
325 }
326}
327
328
340template <MInt nDim>
342 if(polyDeg > s_maxPolyDeg) {
343 TERMM(1, "Polynomial degree exceeds maximum supported (" + std::to_string(s_maxPolyDeg) + ")!");
344 }
345 // Note: The factor "0.95" is used to avoid numerical instabilities when using the full
346 // cfl factor value.
347 const MFloat factor = 0.95 * m_cflFactor[nDim - 2][polyDeg];
348
349 return factor;
350}
351
352
366template <MInt nDim>
367void DgSysEqnLinearScalarAdv<nDim>::calcSource(const MFloat* NotUsed(nodeVars), const MFloat* NotUsed(u),
368 const MInt noNodes1D, const MFloat NotUsed(t), const MFloat* NotUsed(x),
369 MFloat* src) const {
370 const MInt noNodes1D3 = (nDim == 3) ? noNodes1D : 1;
371 MFloatTensor sourceTerms(src, noNodes1D, noNodes1D, noNodes1D3);
372
376 switch(this->m_sourceTerm) {
377 case 0: {
379 sourceTerms.set(F0);
380 break;
381 }
382 default:
383 mTerm(1, AT_, "The specified source term is not valid!");
384 }
385}
386
401template <MInt nDim>
403 const MFloat* NotUsed(u),
404 const MInt NotUsed(noNodes1D),
405 const MFloat* NotUsed(eta),
406 MFloat* NotUsed(src)) const {
407 mTerm(1, AT_, "Sponge: Implementation for linear scalar adv. is missing");
408}
409
422template <MInt nDim>
423MFloat DgSysEqnLinearScalarAdv<nDim>::getTimeStep(const MFloat* NotUsed(nodeVars), const MFloat* const NotUsed(u),
424 const MInt noNodes1D, const MFloat invJacobian,
425 const MInt sbpMode) const {
426 // Calculate maximum propagation speed (lambda)
427 MFloat maxLambda = 0;
428 for(MInt n = 0; n < nDim; n++) {
429 maxLambda += fabs(m_advectionVelocity[n]);
430 }
431
432 // Calculate time step for current element
433 MFloat dt;
434 if(sbpMode) {
435 dt = this->cfl() * F2 / (invJacobian * maxLambda * (noNodes1D - 1));
436 } else {
437 const MInt polyDeg = noNodes1D - 1;
438 dt = this->cflScaled(polyDeg) * cflFactor(polyDeg) * F2 / (invJacobian * maxLambda);
439 }
440 return dt;
441}
442
443
460template <MInt nDim>
461inline void DgSysEqnLinearScalarAdv<nDim>::calcRiemann(const MFloat* NotUsed(nodeVarsL),
462 const MFloat* NotUsed(nodeVarsR),
463 const MFloat* stateL,
464 const MFloat* stateR,
465 const MInt noNodes1D,
466 const MInt dirId,
467 MFloat* flux) const {
468 const MInt noNodes1D3 = (nDim == 3) ? noNodes1D : 1;
469 const MFloatTensor uL(const_cast<MFloat*>(stateL), noNodes1D, noNodes1D3);
470 const MFloatTensor uR(const_cast<MFloat*>(stateR), noNodes1D, noNodes1D3);
471
472 // Calculate maximum eigenvalue
473 const MFloat maxLambda = m_advectionVelocity[dirId];
474
475 // Classical upwind flux...
476 MFloatTensor riemann(flux, noNodes1D, noNodes1D3);
477 for(MInt i = 0; i < noNodes1D; i++) {
478 for(MInt j = 0; j < noNodes1D3; j++) {
479 riemann(i, j) = F1B2 * ((maxLambda + fabs(maxLambda)) * uL(i, j) + (maxLambda - fabs(maxLambda)) * uR(i, j));
480 }
481 }
482}
483
484
495template <MInt nDim>
496inline void DgSysEqnLinearScalarAdv<nDim>::consToPrim(const MFloat* cons, MFloat* prim) const {
497 // Very easy...
498 std::copy(cons, cons + 1, prim);
499}
500
501
512template <MInt nDim>
513inline void DgSysEqnLinearScalarAdv<nDim>::primToCons(const MFloat* prim, MFloat* cons) const {
514 // Very easy...
515 std::copy(prim, prim + 1, cons);
516}
517
518#endif // DGSYSEQNLINEARSCALARADV_H_
Base class for concrete system-of-equations classes (CRTP).
MFloat cflScaled(const MInt polyDeg) const
MInt m_initialCondition
MFloat m_initialNumberWaves
MFloat cfl() const
MFloat cflFactor(const MInt polyDeg) const
static const MString s_consVarNames[s_noVariables]
void primToCons(const MFloat *prim, MFloat *cons) const
Calculates a set of conservative variables from a set of primitive variables.
static constexpr const MString * s_nodeVarNames
MBool extendNodeVar(const MInt NotUsed(varId)) const
std::array< std::array< MFloat, s_maxPolyDeg+1 >, 2 > m_cflFactor
void calcRiemann(const MFloat *nodeVarsL, const MFloat *nodeVarsR, const MFloat *stateL, const MFloat *stateR, const MInt noNodes1D, const MInt dirId, MFloat *flux) const
Calculates the numerical flux at a surface given two states (left and right).
void consToPrim(const MFloat *cons, MFloat *prim) const
Calculates a set of primitive variables from a set of conservative variables.
void getDefaultNodeVars(MFloat *const NotUsed(nodeVars)) const
void calcSpongeSource(const MFloat *nodeVars, const MFloat *u, const MInt noNodes1D, const MFloat *eta, MFloat *src) const
Calculates the sponge source terms for all integration points within a cell.
void calcSource(const MFloat *nodeVars, const MFloat *u, const MInt noNodes1D, const MFloat t, const MFloat *x, MFloat *src) const
Calculates the source terms for all integration points within a cell.
static const MString s_primVarNames[s_noVariables]
void calcFlux(const MFloat *nodeVars, const MFloat *u, const MInt noNodes1D, MFloat *flux) const
Calculates the physical fluxes in all dimensions for all integrations points within a cell.
MFloat getTimeStep(const MFloat *nodeVars, const MFloat *u, const MInt noNodes1D, const MFloat invJacobian, const MInt sbpMode) const
Calculate the time step for an explicit time stepping scheme for a given element.
DgSysEqnLinearScalarAdv(MInt solverId)
Constructor calls parent constructor & loads all necessary properties for this equation.
void calcInitialCondition(const MFloat t, const MFloat *x, MFloat *nodeVars, MFloat *u) const
Calculate the initial condition for a certain point in space.
MInt string2enum(MString theString)
This global function translates strings in their corresponding enum values (integer values)....
Definition: enums.cpp:20
@ DG_TIMEINTEGRATION_CARPENTER_4_5
Definition: enums.h:321
@ DG_TIMEINTEGRATION_TOULORGEC_3_7
Definition: enums.h:325
@ DG_TIMEINTEGRATION_TOULORGEC_4_8
Definition: enums.h:322
@ DG_TIMEINTEGRATION_TOULORGEF_4_8
Definition: enums.h:326
@ DG_TIMEINTEGRATION_NIEGEMANN_4_13
Definition: enums.h:324
@ DG_TIMEINTEGRATION_NIEGEMANN_4_14
Definition: enums.h:323
void mTerm(const MInt errorCode, const MString &location, const MString &message)
Definition: functions.cpp:29
int32_t MInt
Definition: maiatypes.h:62
std::basic_string< char > MString
Definition: maiatypes.h:55
double MFloat
Definition: maiatypes.h:52
bool MBool
Definition: maiatypes.h:58
T cos(const T a, const T b, const T x)
Cosine slope filter.
Definition: filter.h:125