@@ -30,95 +30,222 @@ namespace cadet
30
30
{
31
31
/* *
32
32
* @brief Implements the subcell FV slope limited reconstruction
33
+ * @detail Defines the 2nd order (linear) subcell FV reconstruction by implementing its limiter.
33
34
*/
34
35
// todo active types required in reconstruction?
35
36
class SlopeLimiterFV {
36
37
public:
38
+ enum class SlopeLimiterID : int
39
+ {
40
+ NoLimiter1stOrder = 0 , // !< 1st order (constant) reconstruction, i.e. no reconstruction
41
+ Minmod = 1 , // !< Minmod slope limiter
42
+ Superbee = 2 , // !< Superbee slope limiter
43
+ vanLeer = 3 , // !< van Leer slope limiter
44
+ vanAlbada = 4 , // !< van Alaba slope limiter
45
+ RelaxedVanAlbada = 6 , // !< relaxed van Alaba slope limiter
46
+ NoLimiterForward = -1 , // !< unlimited forward FD reconstruction
47
+ NoLimiterBackward = -2 , // !< unlimited backward FD reconstruction
48
+ };
49
+
37
50
virtual ~SlopeLimiterFV () {}
38
- virtual double call (double slope0, double slope1) = 0;
39
- virtual active call (active slope0, active slope1) = 0;
51
+ virtual double call (double fwdSlope, double bwdSlope) = 0;
52
+ virtual active call (active fwdSlope, active bwdSlope) = 0;
53
+ virtual SlopeLimiterID getID () = 0;
40
54
};
41
55
42
56
/* *
43
- * @brief Implements unlimited forward slope reconstruction
57
+ * @brief 1st order (constant) reconstruction
44
58
*/
45
- class NoLimiterForward : public SlopeLimiterFV {
59
+ class NoLimiter1stOrder : public SlopeLimiterFV {
46
60
47
61
public:
48
- NoLimiterForward () {}
49
- double call (double slope0 , double slope1 ) override {
50
- return slope1 ;
62
+ NoLimiter1stOrder () {}
63
+ double call (double fwdSlope , double bwdSlope ) override {
64
+ return 0.0 ;
51
65
}
52
- active call (active slope0 , active slope1 ) override {
53
- return slope1 ;
66
+ active call (active fwdSlope , active bwdSlope ) override {
67
+ return 0.0 ;
54
68
}
69
+ SlopeLimiterID getID () override { return SlopeLimiterID::NoLimiter1stOrder; }
55
70
};
56
71
57
72
/* *
58
- * @brief Implements unlimited backward slope reconstruction
73
+ * @brief MINMOD reconstruction slope limiter
59
74
*/
60
- class NoLimiterBackward : public SlopeLimiterFV {
75
+ class Minmod : public SlopeLimiterFV {
61
76
62
77
public:
63
- NoLimiterBackward () {}
64
- double call (double slope0, double slope1) override {
65
- return slope0;
78
+ Minmod () {}
79
+ double call (double fwdSlope, double bwdSlope) override {
80
+ if (std::signbit (fwdSlope) == std::signbit (bwdSlope))
81
+ return std::copysign (std::min (std::abs (fwdSlope), std::abs (bwdSlope)), fwdSlope);
82
+ else
83
+ return 0.0 ;
66
84
}
67
- active call (active slope0, active slope1) override {
68
- return slope0;
85
+ active call (active fwdSlope, active bwdSlope) override {
86
+
87
+ if (std::signbit (static_cast <double >(fwdSlope)) == std::signbit (static_cast <double >(bwdSlope)))
88
+ return abs (static_cast <double >(fwdSlope)) < abs (static_cast <double >(bwdSlope)) ? fwdSlope : bwdSlope;
89
+ else
90
+ return active (0.0 );
69
91
}
92
+ SlopeLimiterID getID () override { return SlopeLimiterID::Minmod; }
70
93
};
71
-
94
+
72
95
/* *
73
- * @brief Disables reconstruction
96
+ * @brief Superbee slope limiter for reconstruction
74
97
*/
75
- class NoLimiter1stOrder : public SlopeLimiterFV {
98
+ class Superbee : public SlopeLimiterFV {
76
99
77
100
public:
78
- NoLimiter1stOrder () {}
79
- double call (double slope0, double slope1) override {
80
- return 0.0 ;
101
+ Superbee () {}
102
+
103
+ double maxmod (double fwdSlope, double bwdSlope) {
104
+ if (std::signbit (fwdSlope) == std::signbit (bwdSlope))
105
+ return std::copysign (std::max (std::abs (fwdSlope), std::abs (bwdSlope)), fwdSlope);
106
+ else
107
+ return 0.0 ;
81
108
}
82
- active call (active slope0, active slope1) override {
83
- return 0.0 ;
109
+ active maxmod (active fwdSlope, active bwdSlope) {
110
+
111
+ if (std::signbit (static_cast <double >(fwdSlope)) == std::signbit (static_cast <double >(bwdSlope)))
112
+ return abs (static_cast <double >(fwdSlope)) < abs (static_cast <double >(bwdSlope)) ? bwdSlope : fwdSlope;
113
+ else
114
+ return active (0.0 );
115
+ }
116
+
117
+ double call (double fwdSlope, double bwdSlope) override {
118
+ return maxmod (minmod.call (2 * fwdSlope, bwdSlope), minmod.call (fwdSlope, 2 * bwdSlope));
119
+ }
120
+ active call (active fwdSlope, active bwdSlope) override {
121
+ return maxmod (minmod.call (2 * fwdSlope, bwdSlope), minmod.call (fwdSlope, 2 * bwdSlope));
84
122
}
123
+ SlopeLimiterID getID () override { return SlopeLimiterID::Superbee; }
124
+
125
+ private:
126
+ Minmod minmod;
85
127
};
86
128
87
- // /**
88
- // * @brief Implements unlimited central slope reconstruction
89
- // */
90
- // class NoLimiterCentral : public SlopeLimiterFV {
91
-
92
- // public:
93
- // NoLimiterCentral() {}
94
- // double call(double slope0, double slope1) override {
95
- // return slope0;
96
- // }
97
- // active call(active slope0, active slope1) override {
98
- // return slope0;
99
- // }
100
- // };
129
+ /* *
130
+ * @brief van Leer slope limiter for reconstruction
131
+ */
132
+ class vanLeer : public SlopeLimiterFV {
133
+
134
+ public:
135
+ vanLeer () {}
101
136
102
- class Minmod : public SlopeLimiterFV {
137
+ double call (double fwdSlope, double bwdSlope) override {
138
+ if (std::signbit (fwdSlope) == std::signbit (bwdSlope))
139
+ {
140
+ if (std::abs (fwdSlope) < eps && std::abs (bwdSlope) < eps) // catch zero-division problem
141
+ return 0.0 ;
142
+ else
143
+ return (2.0 * fwdSlope * bwdSlope) / (fwdSlope + bwdSlope);
144
+ }
145
+ else
146
+ return 0.0 ;
147
+ }
148
+ active call (active fwdSlope, active bwdSlope) override {
149
+ if (std::signbit (static_cast <double >(fwdSlope)) == std::signbit (static_cast <double >(bwdSlope)))
150
+ {
151
+ if (abs (fwdSlope) < eps && abs (bwdSlope) < eps) // catch zero-division problem
152
+ return 0.0 ;
153
+ else
154
+ return (2.0 * fwdSlope * bwdSlope) / (fwdSlope + bwdSlope);
155
+ }
156
+ else
157
+ return 0.0 ;
158
+ }
159
+ SlopeLimiterID getID () override { return SlopeLimiterID::vanLeer; }
160
+
161
+ private:
162
+ const double eps = 1e-8 ;
163
+ };
164
+
165
+ /* *
166
+ * @brief van Albada slope limiter for reconstruction
167
+ */
168
+ class vanAlbada : public SlopeLimiterFV {
103
169
104
170
public:
105
- Minmod () {}
106
- double call (double slope0, double slope1) override {
107
- if (std::signbit (slope0) == std::signbit (slope1))
108
- return std::copysign (std::min (std::abs (slope0), std::abs (slope1)), slope0);
171
+ vanAlbada () {}
172
+
173
+ double call (double fwdSlope, double bwdSlope) override {
174
+ if (std::signbit (fwdSlope) == std::signbit (bwdSlope))
175
+ return ((fwdSlope * fwdSlope + eps) * bwdSlope + ((bwdSlope * bwdSlope + eps) * fwdSlope)) / (fwdSlope * fwdSlope + bwdSlope * bwdSlope + 2.0 * eps);
109
176
else
110
177
return 0.0 ;
111
178
}
112
- active call (active slope0, active slope1) override {
179
+ active call (active fwdSlope, active bwdSlope) override {
180
+ if (std::signbit (static_cast <double >(fwdSlope)) == std::signbit (static_cast <double >(bwdSlope)))
181
+ return ((fwdSlope * fwdSlope + eps) * bwdSlope + ((bwdSlope * bwdSlope + eps) * fwdSlope)) / (fwdSlope * fwdSlope + bwdSlope * bwdSlope + 2.0 * eps);
182
+ else
183
+ return 0.0 ;
184
+ }
185
+ SlopeLimiterID getID () override { return SlopeLimiterID::vanAlbada; }
113
186
114
- if (std::signbit (static_cast <double >(slope0)) == std::signbit (static_cast <double >(slope1)))
115
- return abs (static_cast <double >(slope0)) < abs (static_cast <double >(slope1)) ? slope0 : slope1;
187
+ private:
188
+ const double eps = 1e-6 ; // constant chosen according to https://doi.org/10.2514/3.9465
189
+ };
190
+
191
+ /* *
192
+ * @brief relaxed van Albada slope limiter for reconstruction
193
+ * @detail relaxed w.r.t. required arithmetic operations, according to https://doi.org/10.1007/978-981-15-9011-5_5
194
+ */
195
+ class RelaxedVanAlbada : public SlopeLimiterFV {
196
+
197
+ public:
198
+ RelaxedVanAlbada () {}
199
+
200
+ double call (double fwdSlope, double bwdSlope) override {
201
+ if (std::signbit (fwdSlope) == std::signbit (bwdSlope))
202
+ return fwdSlope * (2.0 * fwdSlope * bwdSlope + eps) / (fwdSlope * fwdSlope + bwdSlope * bwdSlope + eps);
116
203
else
117
- return active ( 0.0 ) ;
204
+ return 0.0 ;
118
205
}
206
+ active call (active fwdSlope, active bwdSlope) override {
207
+ if (std::signbit (static_cast <double >(fwdSlope)) == std::signbit (static_cast <double >(bwdSlope)))
208
+ return fwdSlope * (2.0 * fwdSlope * bwdSlope + eps) / (fwdSlope * fwdSlope + bwdSlope * bwdSlope + eps);
209
+ else
210
+ return 0.0 ;
211
+ }
212
+ SlopeLimiterID getID () override { return SlopeLimiterID::RelaxedVanAlbada; }
213
+
214
+ private:
215
+ const double eps = 1e-6 ; // constant chosen according to https://doi.org/10.2514/3.9465
119
216
};
120
217
121
- // todo, note: if more slope limiters are added, note that they have to be symmetrical in the current implementation (i.e. in reconstruction function reconstructedUpwindValue)
218
+ /* *
219
+ * @brief Implements unlimited forward slope for reconstruction
220
+ */
221
+ class NoLimiterForward : public SlopeLimiterFV {
222
+
223
+ public:
224
+ NoLimiterForward () {}
225
+ double call (double fwdSlope, double bwdSlope) override {
226
+ return bwdSlope;
227
+ }
228
+ active call (active fwdSlope, active bwdSlope) override {
229
+ return bwdSlope;
230
+ }
231
+ SlopeLimiterID getID () override { return SlopeLimiterID::NoLimiterForward; }
232
+ };
233
+
234
+ /* *
235
+ * @brief Implements unlimited backward slope for reconstruction
236
+ */
237
+ class NoLimiterBackward : public SlopeLimiterFV {
238
+
239
+ public:
240
+ NoLimiterBackward () {}
241
+ double call (double fwdSlope, double bwdSlope) override {
242
+ return fwdSlope;
243
+ }
244
+ active call (active fwdSlope, active bwdSlope) override {
245
+ return fwdSlope;
246
+ }
247
+ SlopeLimiterID getID () override { return SlopeLimiterID::NoLimiterBackward; }
248
+ };
122
249
123
250
/* *
124
251
* @brief Implements the subcell FV limiting scheme for convection
@@ -169,16 +296,22 @@ namespace cadet
169
296
_subcellGrid[subcell] = _subcellGrid[subcell - 1 ] + _LGLweights[subcell - 1 ];
170
297
171
298
_FVorder = FVorder;
299
+ _slope_limiter = std::make_unique<NoLimiter1stOrder>();
300
+
172
301
if (_FVorder == 2 ) {
173
302
if (limiter == " MINMOD" )
174
303
_slope_limiter = std::make_unique<Minmod>();
175
304
else if (limiter == " UNLIMITED_FORWARD_RECONSTRUCTION" )
176
305
_slope_limiter = std::make_unique<NoLimiterForward>();
177
- else if (limiter == " UNLIMITED_BACKWARD_RECONSTRUCTION" )
178
- _slope_limiter = std::make_unique<NoLimiterBackward>();
179
- else if (limiter == " NONE" )
180
- _slope_limiter = std::make_unique<NoLimiter1stOrder>();
181
- else
306
+ else if (limiter == " SUPERBEE" )
307
+ _slope_limiter = std::make_unique<Superbee>();
308
+ else if (limiter == " VANLEER" )
309
+ _slope_limiter = std::make_unique<vanLeer>();
310
+ else if (limiter == " VANALBADA" )
311
+ _slope_limiter = std::make_unique<vanAlbada>();
312
+ else if (limiter == " RELAXED_VANALBADA" )
313
+ _slope_limiter = std::make_unique<RelaxedVanAlbada>();
314
+ else if (limiter != " NONE" )
182
315
throw InvalidParameterException (" Subcell FV slope limiter " + limiter + " unknown." );
183
316
184
317
switch (boundaryTreatment)
@@ -200,6 +333,17 @@ namespace cadet
200
333
throw InvalidParameterException (" Subcell FV order must be 1 or 2, but was specified as " + std::to_string (_FVorder));
201
334
}
202
335
336
+ void notifyDiscontinuousSectionTransition (int direction) {
337
+
338
+ // Forward FD slope reconstruction depends on flow direction // todo: Koren limiter which is also non-symmetrical
339
+ if (_slope_limiter->getID () == SlopeLimiterFV::SlopeLimiterID::NoLimiterForward && direction == -1 )
340
+ _slope_limiter = std::make_unique<NoLimiterBackward>();
341
+
342
+ else if (_slope_limiter->getID () == SlopeLimiterFV::SlopeLimiterID::NoLimiterBackward && direction == 1 )
343
+ _slope_limiter = std::make_unique<NoLimiterForward>();
344
+
345
+ }
346
+
203
347
/* *
204
348
* @brief Implements FV (limited) reconstruction
205
349
* @details TODO
0 commit comments