Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
trixi-framework
GitHub Repository: trixi-framework/Trixi.jl
Path: blob/main/src/equations/ideal_glm_mhd_multicomponent_1d.jl
2055 views
1
# By default, Julia/LLVM does not use fused multiply-add operations (FMAs).
2
# Since these FMAs can increase the performance of many numerical algorithms,
3
# we need to opt-in explicitly.
4
# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details.
5
@muladd begin
6
#! format: noindent
7
8
@doc raw"""
9
IdealGlmMhdMulticomponentEquations1D
10
11
The ideal compressible multicomponent GLM-MHD equations in one space dimension.
12
"""
13
struct IdealGlmMhdMulticomponentEquations1D{NVARS, NCOMP, RealT <: Real} <:
14
AbstractIdealGlmMhdMulticomponentEquations{1, NVARS, NCOMP}
15
gammas::SVector{NCOMP, RealT}
16
gas_constants::SVector{NCOMP, RealT}
17
cv::SVector{NCOMP, RealT}
18
cp::SVector{NCOMP, RealT}
19
20
function IdealGlmMhdMulticomponentEquations1D{NVARS, NCOMP, RealT}(gammas::SVector{NCOMP,
21
RealT},
22
gas_constants::SVector{NCOMP,
23
RealT}) where {
24
NVARS,
25
NCOMP,
26
RealT <:
27
Real
28
}
29
NCOMP >= 1 ||
30
throw(DimensionMismatch("`gammas` and `gas_constants` have to be filled with at least one value"))
31
32
cv = gas_constants ./ (gammas .- 1)
33
cp = gas_constants + gas_constants ./ (gammas .- 1)
34
35
new(gammas, gas_constants, cv, cp)
36
end
37
end
38
39
function IdealGlmMhdMulticomponentEquations1D(; gammas, gas_constants)
40
_gammas = promote(gammas...)
41
_gas_constants = promote(gas_constants...)
42
RealT = promote_type(eltype(_gammas), eltype(_gas_constants))
43
44
__gammas = SVector(map(RealT, _gammas))
45
__gas_constants = SVector(map(RealT, _gas_constants))
46
47
NVARS = length(_gammas) + 7
48
NCOMP = length(_gammas)
49
50
return IdealGlmMhdMulticomponentEquations1D{NVARS, NCOMP, RealT}(__gammas,
51
__gas_constants)
52
end
53
54
# Outer constructor for `@reset` works correctly
55
function IdealGlmMhdMulticomponentEquations1D(gammas, gas_constants, cv, cp, c_h)
56
IdealGlmMhdMulticomponentEquations1D(gammas = gammas, gas_constants = gas_constants)
57
end
58
59
@inline function Base.real(::IdealGlmMhdMulticomponentEquations1D{NVARS, NCOMP, RealT}) where {
60
NVARS,
61
NCOMP,
62
RealT
63
}
64
RealT
65
end
66
67
have_nonconservative_terms(::IdealGlmMhdMulticomponentEquations1D) = False()
68
69
function varnames(::typeof(cons2cons), equations::IdealGlmMhdMulticomponentEquations1D)
70
cons = ("rho_v1", "rho_v2", "rho_v3", "rho_e", "B1", "B2", "B3")
71
rhos = ntuple(n -> "rho" * string(n), Val(ncomponents(equations)))
72
return (cons..., rhos...)
73
end
74
75
function varnames(::typeof(cons2prim), equations::IdealGlmMhdMulticomponentEquations1D)
76
prim = ("v1", "v2", "v3", "p", "B1", "B2", "B3")
77
rhos = ntuple(n -> "rho" * string(n), Val(ncomponents(equations)))
78
return (prim..., rhos...)
79
end
80
81
"""
82
initial_condition_convergence_test(x, t, equations::IdealGlmMhdMulticomponentEquations1D)
83
84
An Alfvén wave as smooth initial condition used for convergence tests.
85
"""
86
function initial_condition_convergence_test(x, t,
87
equations::IdealGlmMhdMulticomponentEquations1D)
88
# smooth Alfvén wave test from Derigs et al. FLASH (2016)
89
# domain must be set to [0, 1], γ = 5/3
90
91
RealT = eltype(x)
92
rho = one(RealT)
93
prim_rho = SVector{ncomponents(equations), real(equations)}(2^(i - 1) * (1 - 2) *
94
rho / (1 -
95
2^ncomponents(equations))
96
for i in eachcomponent(equations))
97
v1 = 0
98
si, co = sincospi(2 * x[1])
99
v2 = convert(RealT, 0.1) * si
100
v3 = convert(RealT, 0.1) * co
101
p = convert(RealT, 0.1)
102
B1 = 1
103
B2 = v2
104
B3 = v3
105
prim_other = SVector(v1, v2, v3, p, B1, B2, B3)
106
107
return prim2cons(vcat(prim_other, prim_rho), equations)
108
end
109
110
"""
111
initial_condition_weak_blast_wave(x, t, equations::IdealGlmMhdMulticomponentEquations1D)
112
113
A weak blast wave adapted from
114
- Sebastian Hennemann, Gregor J. Gassner (2020)
115
A provably entropy stable subcell shock capturing approach for high order split form DG
116
[arXiv: 2008.12044](https://arxiv.org/abs/2008.12044)
117
"""
118
function initial_condition_weak_blast_wave(x, t,
119
equations::IdealGlmMhdMulticomponentEquations1D)
120
# Adapted MHD version of the weak blast wave from Hennemann & Gassner JCP paper 2020 (Sec. 6.3)
121
# Same discontinuity in the velocities but with magnetic fields
122
# Set up polar coordinates
123
RealT = eltype(x)
124
inicenter = (0)
125
x_norm = x[1] - inicenter[1]
126
r = sqrt(x_norm^2)
127
phi = atan(x_norm)
128
129
# Calculate primitive variables
130
# We initialize each species with a fraction of the total density `rho`, such
131
# that the sum of the densities is `rho := density(prim, equations)`. The density of
132
# a species is double the density of the next species.
133
if r > 0.5f0
134
rho = one(RealT)
135
prim_rho = SVector{ncomponents(equations), real(equations)}(2^(i - 1) *
136
(1 - 2) * rho /
137
(1 -
138
2^ncomponents(equations))
139
for i in eachcomponent(equations))
140
else
141
rho = convert(RealT, 1.1691)
142
prim_rho = SVector{ncomponents(equations), real(equations)}(2^(i - 1) *
143
(1 - 2) * rho /
144
(1 -
145
2^ncomponents(equations))
146
for i in eachcomponent(equations))
147
end
148
v1 = r > 0.5f0 ? zero(RealT) : convert(RealT, 0.1882) * cos(phi)
149
p = r > 0.5f0 ? one(RealT) : convert(RealT, 1.245)
150
151
prim_other = SVector(v1, 0, 0, p, 1, 1, 1)
152
153
return prim2cons(vcat(prim_other, prim_rho), equations)
154
end
155
156
# Calculate 1D flux for a single point
157
@inline function flux(u, orientation::Integer,
158
equations::IdealGlmMhdMulticomponentEquations1D)
159
rho_v1, rho_v2, rho_v3, rho_e, B1, B2, B3 = u
160
161
rho = density(u, equations)
162
163
v1 = rho_v1 / rho
164
v2 = rho_v2 / rho
165
v3 = rho_v3 / rho
166
kin_en = 0.5f0 * rho * (v1^2 + v2^2 + v3^2)
167
mag_en = 0.5f0 * (B1^2 + B2^2 + B3^2)
168
gamma = totalgamma(u, equations)
169
p = (gamma - 1) * (rho_e - kin_en - mag_en)
170
171
f_rho = densities(u, v1, equations)
172
f1 = rho_v1 * v1 + p + mag_en - B1^2
173
f2 = rho_v1 * v2 - B1 * B2
174
f3 = rho_v1 * v3 - B1 * B3
175
f4 = (kin_en + gamma * p / (gamma - 1) + 2 * mag_en) * v1 -
176
B1 * (v1 * B1 + v2 * B2 + v3 * B3)
177
f5 = 0
178
f6 = v1 * B2 - v2 * B1
179
f7 = v1 * B3 - v3 * B1
180
181
f_other = SVector(f1, f2, f3, f4, f5, f6, f7)
182
183
return vcat(f_other, f_rho)
184
end
185
186
"""
187
flux_derigs_etal(u_ll, u_rr, orientation, equations::IdealGlmMhdEquations1D)
188
189
Entropy conserving two-point flux adapted by
190
- Derigs et al. (2018)
191
Ideal GLM-MHD: About the entropy consistent nine-wave magnetic field
192
divergence diminishing ideal magnetohydrodynamics equations for multicomponent
193
[DOI: 10.1016/j.jcp.2018.03.002](https://doi.org/10.1016/j.jcp.2018.03.002)
194
"""
195
function flux_derigs_etal(u_ll, u_rr, orientation::Integer,
196
equations::IdealGlmMhdMulticomponentEquations1D)
197
# Unpack left and right states to get velocities, pressure, and inverse temperature (called beta)
198
rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll = u_ll
199
rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_rr, B1_rr, B2_rr, B3_rr = u_rr
200
@unpack gammas, gas_constants, cv = equations
201
202
rho_ll = density(u_ll, equations)
203
rho_rr = density(u_rr, equations)
204
205
gamma_ll = totalgamma(u_ll, equations)
206
gamma_rr = totalgamma(u_rr, equations)
207
208
rhok_mean = SVector{ncomponents(equations), real(equations)}(ln_mean(u_ll[i + 7],
209
u_rr[i + 7])
210
for i in eachcomponent(equations))
211
rhok_avg = SVector{ncomponents(equations), real(equations)}(0.5f0 * (u_ll[i + 7] +
212
u_rr[i + 7])
213
for i in eachcomponent(equations))
214
215
v1_ll = rho_v1_ll / rho_ll
216
v2_ll = rho_v2_ll / rho_ll
217
v3_ll = rho_v3_ll / rho_ll
218
v1_rr = rho_v1_rr / rho_rr
219
v2_rr = rho_v2_rr / rho_rr
220
v3_rr = rho_v3_rr / rho_rr
221
vel_norm_ll = v1_ll^2 + v2_ll^2 + v3_ll^2
222
vel_norm_rr = v1_rr^2 + v2_rr^2 + v3_rr^2
223
mag_norm_ll = B1_ll^2 + B2_ll^2 + B3_ll^2
224
mag_norm_rr = B1_rr^2 + B2_rr^2 + B3_rr^2
225
# for convenience store v⋅B
226
vel_dot_mag_ll = v1_ll * B1_ll + v2_ll * B2_ll + v3_ll * B3_ll
227
vel_dot_mag_rr = v1_rr * B1_rr + v2_rr * B2_rr + v3_rr * B3_rr
228
229
# Compute the necessary mean values needed for either direction
230
v1_avg = 0.5f0 * (v1_ll + v1_rr)
231
v2_avg = 0.5f0 * (v2_ll + v2_rr)
232
v3_avg = 0.5f0 * (v3_ll + v3_rr)
233
v_sum = v1_avg + v2_avg + v3_avg
234
B1_avg = 0.5f0 * (B1_ll + B1_rr)
235
B2_avg = 0.5f0 * (B2_ll + B2_rr)
236
B3_avg = 0.5f0 * (B3_ll + B3_rr)
237
vel_norm_avg = 0.5f0 * (vel_norm_ll + vel_norm_rr)
238
mag_norm_avg = 0.5f0 * (mag_norm_ll + mag_norm_rr)
239
vel_dot_mag_avg = 0.5f0 * (vel_dot_mag_ll + vel_dot_mag_rr)
240
241
RealT = eltype(u_ll)
242
enth = zero(RealT)
243
help1_ll = zero(RealT)
244
help1_rr = zero(RealT)
245
246
for i in eachcomponent(equations)
247
enth += rhok_avg[i] * gas_constants[i]
248
help1_ll += u_ll[i + 7] * cv[i]
249
help1_rr += u_rr[i + 7] * cv[i]
250
end
251
252
T_ll = (rho_e_ll - 0.5f0 * rho_ll * (vel_norm_ll) - 0.5f0 * mag_norm_ll) / help1_ll
253
T_rr = (rho_e_rr - 0.5f0 * rho_rr * (vel_norm_rr) - 0.5f0 * mag_norm_rr) / help1_rr
254
T = 0.5f0 * (1 / T_ll + 1 / T_rr)
255
T_log = ln_mean(1 / T_ll, 1 / T_rr)
256
257
# Calculate fluxes depending on orientation with specific direction averages
258
help1 = zero(RealT)
259
help2 = zero(RealT)
260
261
f_rho = SVector{ncomponents(equations), real(equations)}(rhok_mean[i] * v1_avg
262
for i in eachcomponent(equations))
263
for i in eachcomponent(equations)
264
help1 += f_rho[i] * cv[i]
265
help2 += f_rho[i]
266
end
267
f1 = help2 * v1_avg + enth / T + 0.5f0 * mag_norm_avg - B1_avg * B1_avg
268
f2 = help2 * v2_avg - B1_avg * B2_avg
269
f3 = help2 * v3_avg - B1_avg * B3_avg
270
f5 = 0
271
f6 = v1_avg * B2_avg - v2_avg * B1_avg
272
f7 = v1_avg * B3_avg - v3_avg * B1_avg
273
274
# total energy flux is complicated and involves the previous eight components
275
v1_mag_avg = 0.5f0 * (v1_ll * mag_norm_ll + v1_rr * mag_norm_rr)
276
277
f4 = (help1 / T_log) - 0.5f0 * (vel_norm_avg) * (help2) + f1 * v1_avg +
278
f2 * v2_avg +
279
f3 * v3_avg +
280
f5 * B1_avg + f6 * B2_avg + f7 * B3_avg - 0.5f0 * v1_mag_avg +
281
B1_avg * vel_dot_mag_avg
282
283
f_other = SVector(f1, f2, f3, f4, f5, f6, f7)
284
285
return vcat(f_other, f_rho)
286
end
287
288
"""
289
flux_hindenlang_gassner(u_ll, u_rr, orientation_or_normal_direction,
290
equations::IdealGlmMhdMulticomponentEquations1D)
291
292
Adaption of the entropy conserving and kinetic energy preserving two-point flux of
293
Hindenlang (2019), extending [`flux_ranocha`](@ref) to the MHD equations.
294
## References
295
- Florian Hindenlang, Gregor Gassner (2019)
296
A new entropy conservative two-point flux for ideal MHD equations derived from
297
first principles.
298
Presented at HONOM 2019: European workshop on high order numerical methods
299
for evolutionary PDEs, theory and applications
300
- Hendrik Ranocha (2018)
301
Generalised Summation-by-Parts Operators and Entropy Stability of Numerical Methods
302
for Hyperbolic Balance Laws
303
[PhD thesis, TU Braunschweig](https://cuvillier.de/en/shop/publications/7743)
304
- Hendrik Ranocha (2020)
305
Entropy Conserving and Kinetic Energy Preserving Numerical Methods for
306
the Euler Equations Using Summation-by-Parts Operators
307
[Proceedings of ICOSAHOM 2018](https://doi.org/10.1007/978-3-030-39647-3_42)
308
"""
309
@inline function flux_hindenlang_gassner(u_ll, u_rr, orientation::Integer,
310
equations::IdealGlmMhdMulticomponentEquations1D)
311
# Unpack left and right states
312
v1_ll, v2_ll, v3_ll, p_ll, B1_ll, B2_ll, B3_ll = cons2prim(u_ll, equations)
313
v1_rr, v2_rr, v3_rr, p_rr, B1_rr, B2_rr, B3_rr = cons2prim(u_rr, equations)
314
315
rho_ll = density(u_ll, equations)
316
rho_rr = density(u_rr, equations)
317
318
# Compute the necessary mean values needed for either direction
319
# Algebraically equivalent to `inv_ln_mean(rho_ll / p_ll, rho_rr / p_rr)`
320
# in exact arithmetic since
321
# log((ϱₗ/pₗ) / (ϱᵣ/pᵣ)) / (ϱₗ/pₗ - ϱᵣ/pᵣ)
322
# = pₗ pᵣ log((ϱₗ pᵣ) / (ϱᵣ pₗ)) / (ϱₗ pᵣ - ϱᵣ pₗ)
323
inv_rho_p_mean = p_ll * p_rr * inv_ln_mean(rho_ll * p_rr, rho_rr * p_ll)
324
v1_avg = 0.5f0 * (v1_ll + v1_rr)
325
v2_avg = 0.5f0 * (v2_ll + v2_rr)
326
v3_avg = 0.5f0 * (v3_ll + v3_rr)
327
p_avg = 0.5f0 * (p_ll + p_rr)
328
velocity_square_avg = 0.5f0 * (v1_ll * v1_rr + v2_ll * v2_rr + v3_ll * v3_rr)
329
magnetic_square_avg = 0.5f0 * (B1_ll * B1_rr + B2_ll * B2_rr + B3_ll * B3_rr)
330
331
inv_gamma_minus_one = 1 / (totalgamma(0.5f0 * (u_ll + u_rr), equations) - 1)
332
333
rhok_mean = SVector{ncomponents(equations), real(equations)}(ln_mean(u_ll[i + 7],
334
u_rr[i + 7])
335
for i in eachcomponent(equations))
336
rhok_avg = SVector{ncomponents(equations), real(equations)}(0.5f0 * (u_ll[i + 7] +
337
u_rr[i + 7])
338
for i in eachcomponent(equations))
339
340
RealT = eltype(u_ll)
341
f1 = zero(RealT)
342
f_rho = SVector{ncomponents(equations), real(equations)}(rhok_mean[i] * v1_avg
343
for i in eachcomponent(equations))
344
for i in eachcomponent(equations)
345
f1 += f_rho[i]
346
end
347
348
# Calculate fluxes depending on orientation with specific direction averages
349
f2 = f1 * v1_avg + p_avg + magnetic_square_avg -
350
0.5f0 * (B1_ll * B1_rr + B1_rr * B1_ll)
351
f3 = f1 * v2_avg - 0.5f0 * (B1_ll * B2_rr + B1_rr * B2_ll)
352
f4 = f1 * v3_avg - 0.5f0 * (B1_ll * B3_rr + B1_rr * B3_ll)
353
# f5 below
354
f6 = 0
355
f7 = 0.5f0 * (v1_ll * B2_ll - v2_ll * B1_ll + v1_rr * B2_rr - v2_rr * B1_rr)
356
f8 = 0.5f0 * (v1_ll * B3_ll - v3_ll * B1_ll + v1_rr * B3_rr - v3_rr * B1_rr)
357
# total energy flux is complicated and involves the previous components
358
f5 = (f1 * (velocity_square_avg + inv_rho_p_mean * inv_gamma_minus_one)
359
+
360
0.5f0 * (+p_ll * v1_rr + p_rr * v1_ll
361
+ (v1_ll * B2_ll * B2_rr + v1_rr * B2_rr * B2_ll)
362
+ (v1_ll * B3_ll * B3_rr + v1_rr * B3_rr * B3_ll)
363
-
364
(v2_ll * B1_ll * B2_rr + v2_rr * B1_rr * B2_ll)
365
-
366
(v3_ll * B1_ll * B3_rr + v3_rr * B1_rr * B3_ll)))
367
368
f_other = SVector(f2, f3, f4, f5, f6, f7, f8)
369
370
return vcat(f_other, f_rho)
371
end
372
373
# Calculate maximum wave speed for local Lax-Friedrichs-type dissipation
374
@inline function max_abs_speed_naive(u_ll, u_rr, orientation::Integer,
375
equations::IdealGlmMhdMulticomponentEquations1D)
376
rho_v1_ll, _ = u_ll
377
rho_v1_rr, _ = u_rr
378
379
rho_ll = density(u_ll, equations)
380
rho_rr = density(u_rr, equations)
381
382
# Calculate velocities (ignore orientation since it is always "1" in 1D)
383
# and fast magnetoacoustic wave speeds
384
# left
385
v_ll = rho_v1_ll / rho_ll
386
cf_ll = calc_fast_wavespeed(u_ll, orientation, equations)
387
# right
388
v_rr = rho_v1_rr / rho_rr
389
cf_rr = calc_fast_wavespeed(u_rr, orientation, equations)
390
391
return max(abs(v_ll), abs(v_rr)) + max(cf_ll, cf_rr)
392
end
393
394
# Less "cautious", i.e., less overestimating `λ_max` compared to `max_abs_speed_naive`
395
@inline function max_abs_speed(u_ll, u_rr, orientation::Integer,
396
equations::IdealGlmMhdMulticomponentEquations1D)
397
rho_v1_ll, _ = u_ll
398
rho_v1_rr, _ = u_rr
399
400
rho_ll = density(u_ll, equations)
401
rho_rr = density(u_rr, equations)
402
403
# Calculate velocities (ignore orientation since it is always "1" in 1D)
404
# and fast magnetoacoustic wave speeds
405
# left
406
v_ll = rho_v1_ll / rho_ll
407
cf_ll = calc_fast_wavespeed(u_ll, orientation, equations)
408
# right
409
v_rr = rho_v1_rr / rho_rr
410
cf_rr = calc_fast_wavespeed(u_rr, orientation, equations)
411
412
return max(abs(v_ll) + cf_ll, abs(v_rr) + cf_rr)
413
end
414
415
@inline function max_abs_speeds(u, equations::IdealGlmMhdMulticomponentEquations1D)
416
rho_v1, _ = u
417
418
rho = density(u, equations)
419
420
v1 = rho_v1 / rho
421
422
cf_x_direction = calc_fast_wavespeed(u, 1, equations)
423
424
return (abs(v1) + cf_x_direction,)
425
end
426
427
# Convert conservative variables to primitive
428
function cons2prim(u, equations::IdealGlmMhdMulticomponentEquations1D)
429
rho_v1, rho_v2, rho_v3, rho_e, B1, B2, B3 = u
430
431
prim_rho = SVector{ncomponents(equations), real(equations)}(u[i + 7]
432
for i in eachcomponent(equations))
433
rho = density(u, equations)
434
435
v1 = rho_v1 / rho
436
v2 = rho_v2 / rho
437
v3 = rho_v3 / rho
438
439
gamma = totalgamma(u, equations)
440
441
p = (gamma - 1) *
442
(rho_e - 0.5f0 * rho * (v1^2 + v2^2 + v3^2) - 0.5f0 * (B1^2 + B2^2 + B3^2))
443
prim_other = SVector(v1, v2, v3, p, B1, B2, B3)
444
445
return vcat(prim_other, prim_rho)
446
end
447
448
# Convert conservative variables to entropy
449
@inline function cons2entropy(u, equations::IdealGlmMhdMulticomponentEquations1D)
450
rho_v1, rho_v2, rho_v3, rho_e, B1, B2, B3 = u
451
@unpack cv, gammas, gas_constants = equations
452
453
rho = density(u, equations)
454
455
v1 = rho_v1 / rho
456
v2 = rho_v2 / rho
457
v3 = rho_v3 / rho
458
v_square = v1^2 + v2^2 + v3^2
459
gamma = totalgamma(u, equations)
460
p = (gamma - 1) * (rho_e - 0.5f0 * rho * v_square - 0.5f0 * (B1^2 + B2^2 + B3^2))
461
s = log(p) - gamma * log(rho)
462
rho_p = rho / p
463
464
# Multicomponent stuff
465
RealT = eltype(u)
466
help1 = zero(RealT)
467
468
for i in eachcomponent(equations)
469
help1 += u[i + 7] * cv[i]
470
end
471
472
T = (rho_e - 0.5f0 * rho * v_square - 0.5f0 * (B1^2 + B2^2 + B3^2)) / (help1)
473
474
entrop_rho = SVector{ncomponents(equations), real(equations)}(-1 *
475
(cv[i] * log(T) -
476
gas_constants[i] *
477
log(u[i + 7])) +
478
gas_constants[i] +
479
cv[i] -
480
(v_square / (2 * T))
481
for i in eachcomponent(equations))
482
483
w1 = v1 / T
484
w2 = v2 / T
485
w3 = v3 / T
486
w4 = -1 / T
487
w5 = B1 / T
488
w6 = B2 / T
489
w7 = B3 / T
490
491
entrop_other = SVector(w1, w2, w3, w4, w5, w6, w7)
492
493
return vcat(entrop_other, entrop_rho)
494
end
495
496
# Convert primitive to conservative variables
497
@inline function prim2cons(prim, equations::IdealGlmMhdMulticomponentEquations1D)
498
v1, v2, v3, p, B1, B2, B3 = prim
499
500
cons_rho = SVector{ncomponents(equations), real(equations)}(prim[i + 7]
501
for i in eachcomponent(equations))
502
rho = density(prim, equations)
503
504
rho_v1 = rho * v1
505
rho_v2 = rho * v2
506
rho_v3 = rho * v3
507
508
gamma = totalgamma(prim, equations)
509
rho_e = p / (gamma - 1) + 0.5f0 * (rho_v1 * v1 + rho_v2 * v2 + rho_v3 * v3) +
510
0.5f0 * (B1^2 + B2^2 + B3^2)
511
512
cons_other = SVector(rho_v1, rho_v2, rho_v3, rho_e, B1, B2, B3)
513
514
return vcat(cons_other, cons_rho)
515
end
516
517
@inline function density_pressure(u, equations::IdealGlmMhdMulticomponentEquations1D)
518
rho_v1, rho_v2, rho_v3, rho_e, B1, B2, B3 = u
519
rho = density(u, equations)
520
gamma = totalgamma(u, equations)
521
p = (gamma - 1) * (rho_e - 0.5f0 * (rho_v1^2 + rho_v2^2 + rho_v3^2) / rho
522
-
523
0.5f0 * (B1^2 + B2^2 + B3^2))
524
return rho * p
525
end
526
527
# Compute the fastest wave speed for ideal MHD equations: c_f, the fast magnetoacoustic eigenvalue
528
@inline function calc_fast_wavespeed(cons, direction,
529
equations::IdealGlmMhdMulticomponentEquations1D)
530
rho_v1, rho_v2, rho_v3, rho_e, B1, B2, B3 = cons
531
rho = density(cons, equations)
532
v1 = rho_v1 / rho
533
v2 = rho_v2 / rho
534
v3 = rho_v3 / rho
535
v_mag = sqrt(v1^2 + v2^2 + v3^2)
536
gamma = totalgamma(cons, equations)
537
p = (gamma - 1) * (rho_e - 0.5f0 * rho * v_mag^2 - 0.5f0 * (B1^2 + B2^2 + B3^2))
538
a_square = gamma * p / rho
539
sqrt_rho = sqrt(rho)
540
b1 = B1 / sqrt_rho
541
b2 = B2 / sqrt_rho
542
b3 = B3 / sqrt_rho
543
b_square = b1^2 + b2^2 + b3^2
544
545
c_f = sqrt(0.5f0 * (a_square + b_square) +
546
0.5f0 * sqrt((a_square + b_square)^2 - 4 * a_square * b1^2))
547
548
return c_f
549
end
550
551
@inline function density(u, equations::IdealGlmMhdMulticomponentEquations1D)
552
RealT = eltype(u)
553
rho = zero(RealT)
554
555
for i in eachcomponent(equations)
556
rho += u[i + 7]
557
end
558
559
return rho
560
end
561
562
@inline function totalgamma(u, equations::IdealGlmMhdMulticomponentEquations1D)
563
@unpack cv, gammas = equations
564
565
RealT = eltype(u)
566
help1 = zero(RealT)
567
help2 = zero(RealT)
568
569
for i in eachcomponent(equations)
570
help1 += u[i + 7] * cv[i] * gammas[i]
571
help2 += u[i + 7] * cv[i]
572
end
573
574
return help1 / help2
575
end
576
577
@inline function densities(u, v, equations::IdealGlmMhdMulticomponentEquations1D)
578
return SVector{ncomponents(equations), real(equations)}(u[i + 7] * v
579
for i in eachcomponent(equations))
580
end
581
end # @muladd
582
583