Path: blob/main/src/equations/ideal_glm_mhd_1d.jl
2055 views
# By default, Julia/LLVM does not use fused multiply-add operations (FMAs).1# Since these FMAs can increase the performance of many numerical algorithms,2# we need to opt-in explicitly.3# See https://ranocha.de/blog/Optimizing_EC_Trixi for further details.4@muladd begin5#! format: noindent67@doc raw"""8IdealGlmMhdEquations1D(gamma)910The ideal compressible GLM-MHD equations for an ideal gas with ratio of11specific heats `gamma` in one space dimension.1213!!! note14There is no divergence cleaning variable `psi` because the divergence-free constraint15is satisfied trivially in one spatial dimension.16"""17struct IdealGlmMhdEquations1D{RealT <: Real} <: AbstractIdealGlmMhdEquations{1, 8}18gamma::RealT # ratio of specific heats19inv_gamma_minus_one::RealT # = inv(gamma - 1); can be used to write slow divisions as fast multiplications2021function IdealGlmMhdEquations1D(gamma)22γ, inv_gamma_minus_one = promote(gamma, inv(gamma - 1))23new{typeof(γ)}(γ, inv_gamma_minus_one)24end25end2627have_nonconservative_terms(::IdealGlmMhdEquations1D) = False()28function varnames(::typeof(cons2cons), ::IdealGlmMhdEquations1D)29("rho", "rho_v1", "rho_v2", "rho_v3", "rho_e", "B1", "B2", "B3")30end31function varnames(::typeof(cons2prim), ::IdealGlmMhdEquations1D)32("rho", "v1", "v2", "v3", "p", "B1", "B2", "B3")33end34function default_analysis_integrals(::IdealGlmMhdEquations1D)35(entropy_timederivative, Val(:l2_divb), Val(:linf_divb))36end3738"""39initial_condition_constant(x, t, equations::IdealGlmMhdEquations1D)4041A constant initial condition to test free-stream preservation.42"""43function initial_condition_constant(x, t, equations::IdealGlmMhdEquations1D)44RealT = eltype(x)45rho = 146rho_v1 = convert(RealT, 0.1)47rho_v2 = -convert(RealT, 0.2)48rho_v3 = -0.5f049rho_e = 5050B1 = 351B2 = -convert(RealT, 1.2)52B3 = 0.5f053return SVector(rho, rho_v1, rho_v2, rho_v3, rho_e, B1, B2, B3)54end5556"""57initial_condition_convergence_test(x, t, equations::IdealGlmMhdEquations1D)5859An Alfvén wave as smooth initial condition used for convergence tests.60See for reference section 4.2 in61- Dominik Derigs, Andrew R. Winters, Gregor J. Gassner, and Stefanie Walch (2016)62A novel high-order, entropy stable, 3D AMR MHD solver with guaranteed positive pressure63[DOI: 10.1016/j.jcp.2016.04.048](https://doi.org/10.1016/j.jcp.2016.04.048)64"""65function initial_condition_convergence_test(x, t, equations::IdealGlmMhdEquations1D)66# smooth Alfvén wave test from Derigs et al. (2016)67# domain must be set to [0, 1], γ = 5/368RealT = eltype(x)69rho = 170v1 = 071si, co = sincospi(2 * (x[1] + t)) # Adding `t` makes non-integer time valid72v2 = convert(RealT, 0.1) * si73v3 = convert(RealT, 0.1) * co74p = convert(RealT, 0.1)75B1 = 176B2 = v277B3 = v378return prim2cons(SVector(rho, v1, v2, v3, p, B1, B2, B3), equations)79end8081"""82initial_condition_weak_blast_wave(x, t, equations::IdealGlmMhdEquations1D)8384A weak blast wave adapted from85- Sebastian Hennemann, Gregor J. Gassner (2020)86A provably entropy stable subcell shock capturing approach for high order split form DG87[arXiv: 2008.12044](https://arxiv.org/abs/2008.12044)88"""89function initial_condition_weak_blast_wave(x, t, equations::IdealGlmMhdEquations1D)90# Adapted MHD version of the weak blast wave from Hennemann & Gassner JCP paper 2020 (Sec. 6.3)91# Same discontinuity in the velocities but with magnetic fields92# Set up polar coordinates93RealT = eltype(x)94inicenter = (0,)95x_norm = x[1] - inicenter[1]96r = sqrt(x_norm^2)97phi = atan(x_norm)9899# Calculate primitive variables100rho = r > 0.5f0 ? one(RealT) : convert(RealT, 1.1691)101v1 = r > 0.5f0 ? zero(RealT) : convert(RealT, 0.1882) * cos(phi)102p = r > 0.5f0 ? one(RealT) : convert(RealT, 1.245)103104return prim2cons(SVector(rho, v1, 0, 0, p, 1, 1, 1, 0), equations)105end106107# Calculate 1D flux for a single point108@inline function flux(u, orientation::Integer, equations::IdealGlmMhdEquations1D)109rho, rho_v1, rho_v2, rho_v3, rho_e, B1, B2, B3 = u110v1 = rho_v1 / rho111v2 = rho_v2 / rho112v3 = rho_v3 / rho113kin_en = 0.5f0 * (rho_v1 * v1 + rho_v2 * v2 + rho_v3 * v3)114mag_en = 0.5f0 * (B1 * B1 + B2 * B2 + B3 * B3)115p_over_gamma_minus_one = (rho_e - kin_en - mag_en)116p = (equations.gamma - 1) * p_over_gamma_minus_one117118# Ignore orientation since it is always "1" in 1D119f1 = rho_v1120f2 = rho_v1 * v1 + p + mag_en - B1^2121f3 = rho_v1 * v2 - B1 * B2122f4 = rho_v1 * v3 - B1 * B3123f5 = (kin_en + equations.gamma * p_over_gamma_minus_one + 2 * mag_en) * v1 -124B1 * (v1 * B1 + v2 * B2 + v3 * B3)125f6 = 0126f7 = v1 * B2 - v2 * B1127f8 = v1 * B3 - v3 * B1128129return SVector(f1, f2, f3, f4, f5, f6, f7, f8)130end131132"""133flux_derigs_etal(u_ll, u_rr, orientation, equations::IdealGlmMhdEquations1D)134135Entropy conserving two-point flux by136- Derigs et al. (2018)137Ideal GLM-MHD: About the entropy consistent nine-wave magnetic field138divergence diminishing ideal magnetohydrodynamics equations139[DOI: 10.1016/j.jcp.2018.03.002](https://doi.org/10.1016/j.jcp.2018.03.002)140"""141function flux_derigs_etal(u_ll, u_rr, orientation::Integer,142equations::IdealGlmMhdEquations1D)143# Unpack left and right states to get velocities, pressure, and inverse temperature (called beta)144rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll = u_ll145rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_rr, B1_rr, B2_rr, B3_rr = u_rr146147v1_ll = rho_v1_ll / rho_ll148v2_ll = rho_v2_ll / rho_ll149v3_ll = rho_v3_ll / rho_ll150v1_rr = rho_v1_rr / rho_rr151v2_rr = rho_v2_rr / rho_rr152v3_rr = rho_v3_rr / rho_rr153vel_norm_ll = v1_ll^2 + v2_ll^2 + v3_ll^2154vel_norm_rr = v1_rr^2 + v2_rr^2 + v3_rr^2155mag_norm_ll = B1_ll^2 + B2_ll^2 + B3_ll^2156mag_norm_rr = B1_rr^2 + B2_rr^2 + B3_rr^2157p_ll = (equations.gamma - 1) *158(rho_e_ll - 0.5f0 * rho_ll * vel_norm_ll - 0.5f0 * mag_norm_ll)159p_rr = (equations.gamma - 1) *160(rho_e_rr - 0.5f0 * rho_rr * vel_norm_rr - 0.5f0 * mag_norm_rr)161beta_ll = 0.5f0 * rho_ll / p_ll162beta_rr = 0.5f0 * rho_rr / p_rr163# for convenience store v⋅B164vel_dot_mag_ll = v1_ll * B1_ll + v2_ll * B2_ll + v3_ll * B3_ll165vel_dot_mag_rr = v1_rr * B1_rr + v2_rr * B2_rr + v3_rr * B3_rr166167# Compute the necessary mean values needed for either direction168rho_avg = 0.5f0 * (rho_ll + rho_rr)169rho_mean = ln_mean(rho_ll, rho_rr)170beta_mean = ln_mean(beta_ll, beta_rr)171beta_avg = 0.5f0 * (beta_ll + beta_rr)172v1_avg = 0.5f0 * (v1_ll + v1_rr)173v2_avg = 0.5f0 * (v2_ll + v2_rr)174v3_avg = 0.5f0 * (v3_ll + v3_rr)175p_mean = 0.5f0 * rho_avg / beta_avg176B1_avg = 0.5f0 * (B1_ll + B1_rr)177B2_avg = 0.5f0 * (B2_ll + B2_rr)178B3_avg = 0.5f0 * (B3_ll + B3_rr)179vel_norm_avg = 0.5f0 * (vel_norm_ll + vel_norm_rr)180mag_norm_avg = 0.5f0 * (mag_norm_ll + mag_norm_rr)181vel_dot_mag_avg = 0.5f0 * (vel_dot_mag_ll + vel_dot_mag_rr)182183# Ignore orientation since it is always "1" in 1D184f1 = rho_mean * v1_avg185f2 = f1 * v1_avg + p_mean + 0.5f0 * mag_norm_avg - B1_avg * B1_avg186f3 = f1 * v2_avg - B1_avg * B2_avg187f4 = f1 * v3_avg - B1_avg * B3_avg188f6 = 0189f7 = v1_avg * B2_avg - v2_avg * B1_avg190f8 = v1_avg * B3_avg - v3_avg * B1_avg191# total energy flux is complicated and involves the previous eight components192v1_mag_avg = 0.5f0 * (v1_ll * mag_norm_ll + v1_rr * mag_norm_rr)193f5 = (f1 * 0.5f0 * (1 / (equations.gamma - 1) / beta_mean - vel_norm_avg) +194f2 * v1_avg + f3 * v2_avg +195f4 * v3_avg + f6 * B1_avg + f7 * B2_avg + f8 * B3_avg - 0.5f0 * v1_mag_avg +196B1_avg * vel_dot_mag_avg)197198return SVector(f1, f2, f3, f4, f5, f6, f7, f8)199end200201"""202flux_hindenlang_gassner(u_ll, u_rr, orientation_or_normal_direction,203equations::IdealGlmMhdEquations1D)204205Entropy conserving and kinetic energy preserving two-point flux of206Hindenlang and Gassner (2019), extending [`flux_ranocha`](@ref) to the MHD equations.207208## References209- Florian Hindenlang, Gregor Gassner (2019)210A new entropy conservative two-point flux for ideal MHD equations derived from211first principles.212Presented at HONOM 2019: European workshop on high order numerical methods213for evolutionary PDEs, theory and applications214- Hendrik Ranocha (2018)215Generalised Summation-by-Parts Operators and Entropy Stability of Numerical Methods216for Hyperbolic Balance Laws217[PhD thesis, TU Braunschweig](https://cuvillier.de/en/shop/publications/7743)218- Hendrik Ranocha (2020)219Entropy Conserving and Kinetic Energy Preserving Numerical Methods for220the Euler Equations Using Summation-by-Parts Operators221[Proceedings of ICOSAHOM 2018](https://doi.org/10.1007/978-3-030-39647-3_42)222"""223@inline function flux_hindenlang_gassner(u_ll, u_rr, orientation::Integer,224equations::IdealGlmMhdEquations1D)225# Unpack left and right states226rho_ll, v1_ll, v2_ll, v3_ll, p_ll, B1_ll, B2_ll, B3_ll = cons2prim(u_ll, equations)227rho_rr, v1_rr, v2_rr, v3_rr, p_rr, B1_rr, B2_rr, B3_rr = cons2prim(u_rr, equations)228229# Compute the necessary mean values needed for either direction230rho_mean = ln_mean(rho_ll, rho_rr)231# Algebraically equivalent to `inv_ln_mean(rho_ll / p_ll, rho_rr / p_rr)`232# in exact arithmetic since233# log((ϱₗ/pₗ) / (ϱᵣ/pᵣ)) / (ϱₗ/pₗ - ϱᵣ/pᵣ)234# = pₗ pᵣ log((ϱₗ pᵣ) / (ϱᵣ pₗ)) / (ϱₗ pᵣ - ϱᵣ pₗ)235inv_rho_p_mean = p_ll * p_rr * inv_ln_mean(rho_ll * p_rr, rho_rr * p_ll)236v1_avg = 0.5f0 * (v1_ll + v1_rr)237v2_avg = 0.5f0 * (v2_ll + v2_rr)238v3_avg = 0.5f0 * (v3_ll + v3_rr)239p_avg = 0.5f0 * (p_ll + p_rr)240velocity_square_avg = 0.5f0 * (v1_ll * v1_rr + v2_ll * v2_rr + v3_ll * v3_rr)241magnetic_square_avg = 0.5f0 * (B1_ll * B1_rr + B2_ll * B2_rr + B3_ll * B3_rr)242243# Calculate fluxes depending on orientation with specific direction averages244f1 = rho_mean * v1_avg245f2 = f1 * v1_avg + p_avg + magnetic_square_avg -2460.5f0 * (B1_ll * B1_rr + B1_rr * B1_ll)247f3 = f1 * v2_avg - 0.5f0 * (B1_ll * B2_rr + B1_rr * B2_ll)248f4 = f1 * v3_avg - 0.5f0 * (B1_ll * B3_rr + B1_rr * B3_ll)249#f5 below250f6 = 0251f7 = 0.5f0 * (v1_ll * B2_ll - v2_ll * B1_ll + v1_rr * B2_rr - v2_rr * B1_rr)252f8 = 0.5f0 * (v1_ll * B3_ll - v3_ll * B1_ll + v1_rr * B3_rr - v3_rr * B1_rr)253# total energy flux is complicated and involves the previous components254f5 = (f1 * (velocity_square_avg + inv_rho_p_mean * equations.inv_gamma_minus_one)255+2560.5f0 * (+p_ll * v1_rr + p_rr * v1_ll257+ (v1_ll * B2_ll * B2_rr + v1_rr * B2_rr * B2_ll)258+ (v1_ll * B3_ll * B3_rr + v1_rr * B3_rr * B3_ll)259-260(v2_ll * B1_ll * B2_rr + v2_rr * B1_rr * B2_ll)261-262(v3_ll * B1_ll * B3_rr + v3_rr * B1_rr * B3_ll)))263264return SVector(f1, f2, f3, f4, f5, f6, f7, f8)265end266267"""268flux_hllc(u_ll, u_rr, orientation, equations::IdealGlmMhdEquations1D)269270- Li (2005)271An HLLC Riemann solver for magneto-hydrodynamics272[DOI: 10.1016/j.jcp.2004.08.020](https://doi.org/10.1016/j.jcp.2004.08.020).273"""274function flux_hllc(u_ll, u_rr, orientation::Integer,275equations::IdealGlmMhdEquations1D)276# Unpack left and right states277rho_ll, v1_ll, v2_ll, v3_ll, p_ll, B1_ll, B2_ll, B3_ll = cons2prim(u_ll, equations)278rho_rr, v1_rr, v2_rr, v3_rr, p_rr, B1_rr, B2_rr, B3_rr = cons2prim(u_rr, equations)279280# Total pressure, i.e., thermal + magnetic pressures (eq. (12))281p_tot_ll = p_ll + 0.5f0 * (B1_ll^2 + B2_ll^2 + B3_ll^2)282p_tot_rr = p_rr + 0.5f0 * (B1_rr^2 + B2_rr^2 + B3_rr^2)283284# Conserved variables285rho_v1_ll = u_ll[2]286rho_v2_ll = u_ll[3]287rho_v3_ll = u_ll[4]288289rho_v1_rr = u_rr[2]290rho_v2_rr = u_rr[3]291rho_v3_rr = u_rr[4]292293# Obtain left and right fluxes294f_ll = flux(u_ll, orientation, equations)295f_rr = flux(u_rr, orientation, equations)296297SsL, SsR = min_max_speed_einfeldt(u_ll, u_rr, orientation, equations)298sMu_L = SsL - v1_ll299sMu_R = SsR - v1_rr300if SsL >= 0301f1 = f_ll[1]302f2 = f_ll[2]303f3 = f_ll[3]304f4 = f_ll[4]305f5 = f_ll[5]306f6 = f_ll[6]307f7 = f_ll[7]308f8 = f_ll[8]309elseif SsR <= 0310f1 = f_rr[1]311f2 = f_rr[2]312f3 = f_rr[3]313f4 = f_rr[4]314f5 = f_rr[5]315f6 = f_rr[6]316f7 = f_rr[7]317f8 = f_rr[8]318else319# Compute the "HLLC-speed", eq. (14) from paper mentioned above320#=321SStar = (rho_rr * v1_rr * sMu_R - rho_ll * v1_ll * sMu_L + p_tot_ll - p_tot_rr - B1_ll^2 + B1_rr^2 ) /322(rho_rr * sMu_R - rho_ll * sMu_L)323=#324# Simplification for 1D: B1 is constant325SStar = (rho_rr * v1_rr * sMu_R - rho_ll * v1_ll * sMu_L + p_tot_ll - p_tot_rr) /326(rho_rr * sMu_R - rho_ll * sMu_L)327328Sdiff = SsR - SsL329330# Compute HLL values for vStar, BStar331# These correspond to eq. (28) and (30) from the referenced paper332# and the classic HLL intermediate state given by (2)333rho_HLL = (SsR * rho_rr - SsL * rho_ll - (f_rr[1] - f_ll[1])) / Sdiff334335v1Star = (SsR * rho_v1_rr - SsL * rho_v1_ll - (f_rr[2] - f_ll[2])) /336(Sdiff * rho_HLL)337v2Star = (SsR * rho_v2_rr - SsL * rho_v2_ll - (f_rr[3] - f_ll[3])) /338(Sdiff * rho_HLL)339v3Star = (SsR * rho_v3_rr - SsL * rho_v3_ll - (f_rr[4] - f_ll[4])) /340(Sdiff * rho_HLL)341342#B1Star = (SsR * B1_rr - SsL * B1_ll - (f_rr[6] - f_ll[6])) / Sdiff343# 1D B1 = constant => B1_ll = B1_rr = B1Star344B1Star = B1_ll345346B2Star = (SsR * B2_rr - SsL * B2_ll - (f_rr[7] - f_ll[7])) / Sdiff347B3Star = (SsR * B3_rr - SsL * B3_ll - (f_rr[8] - f_ll[8])) / Sdiff348if SsL <= SStar349SdiffStar = SsL - SStar350351densStar = rho_ll * sMu_L / SdiffStar # (19)352353mom_1_Star = densStar * SStar # (20)354mom_2_Star = densStar * v2_ll -355(B1Star * B2Star - B1_ll * B2_ll) / SdiffStar # (21)356mom_3_Star = densStar * v3_ll -357(B1Star * B3Star - B1_ll * B3_ll) / SdiffStar # (22)358359#p_tot_Star = rho_ll * sMu_L * (SStar - v1_ll) + p_tot_ll - B1_ll^2 + B1Star^2 # (17)360# 1D B1 = constant => B1_ll = B1_rr = B1Star361p_tot_Star = rho_ll * sMu_L * (SStar - v1_ll) + p_tot_ll # (17)362363enerStar = u_ll[5] * sMu_L / SdiffStar +364(p_tot_Star * SStar - p_tot_ll * v1_ll - (B1Star *365(B1Star * v1Star + B2Star * v2Star + B3Star * v3Star) -366B1_ll * (B1_ll * v1_ll + B2_ll * v2_ll + B3_ll * v3_ll))) /367SdiffStar # (23)368369# Classic HLLC update (32)370f1 = f_ll[1] + SsL * (densStar - u_ll[1])371f2 = f_ll[2] + SsL * (mom_1_Star - u_ll[2])372f3 = f_ll[3] + SsL * (mom_2_Star - u_ll[3])373f4 = f_ll[4] + SsL * (mom_3_Star - u_ll[4])374f5 = f_ll[5] + SsL * (enerStar - u_ll[5])375f6 = f_ll[6] + SsL * (B1Star - u_ll[6])376f7 = f_ll[7] + SsL * (B2Star - u_ll[7])377f8 = f_ll[8] + SsL * (B3Star - u_ll[8])378else # SStar <= Ssr379SdiffStar = SsR - SStar380381densStar = rho_rr * sMu_R / SdiffStar # (19)382383mom_1_Star = densStar * SStar # (20)384mom_2_Star = densStar * v2_rr -385(B1Star * B2Star - B1_rr * B2_rr) / SdiffStar # (21)386mom_3_Star = densStar * v3_rr -387(B1Star * B3Star - B1_rr * B3_rr) / SdiffStar # (22)388389#p_tot_Star = rho_rr * sMu_R * (SStar - v1_rr) + p_tot_rr - B1_rr^2 + B1Star^2 # (17)390# 1D B1 = constant => B1_ll = B1_rr = B1Star391p_tot_Star = rho_rr * sMu_R * (SStar - v1_rr) + p_tot_rr # (17)392393enerStar = u_rr[5] * sMu_R / SdiffStar +394(p_tot_Star * SStar - p_tot_rr * v1_rr - (B1Star *395(B1Star * v1Star + B2Star * v2Star + B3Star * v3Star) -396B1_rr * (B1_rr * v1_rr + B2_rr * v2_rr + B3_rr * v3_rr))) /397SdiffStar # (23)398399# Classic HLLC update (32)400f1 = f_rr[1] + SsR * (densStar - u_rr[1])401f2 = f_rr[2] + SsR * (mom_1_Star - u_rr[2])402f3 = f_rr[3] + SsR * (mom_2_Star - u_rr[3])403f4 = f_rr[4] + SsR * (mom_3_Star - u_rr[4])404f5 = f_rr[5] + SsR * (enerStar - u_rr[5])405f6 = f_rr[6] + SsR * (B1Star - u_rr[6])406f7 = f_rr[7] + SsR * (B2Star - u_rr[7])407f8 = f_rr[8] + SsR * (B3Star - u_rr[8])408end409end410return SVector(f1, f2, f3, f4, f5, f6, f7, f8)411end412413# Calculate maximum wave speed for local Lax-Friedrichs-type dissipation414@inline function max_abs_speed_naive(u_ll, u_rr, orientation::Integer,415equations::IdealGlmMhdEquations1D)416rho_ll, rho_v1_ll, _ = u_ll417rho_rr, rho_v1_rr, _ = u_rr418419# Calculate velocities (ignore orientation since it is always "1" in 1D)420# and fast magnetoacoustic wave speeds421# left422v_ll = rho_v1_ll / rho_ll423cf_ll = calc_fast_wavespeed(u_ll, orientation, equations)424# right425v_rr = rho_v1_rr / rho_rr426cf_rr = calc_fast_wavespeed(u_rr, orientation, equations)427428return max(abs(v_ll), abs(v_rr)) + max(cf_ll, cf_rr)429end430431# Less "cautious", i.e., less overestimating `λ_max` compared to `max_abs_speed_naive`432@inline function max_abs_speed(u_ll, u_rr, orientation::Integer,433equations::IdealGlmMhdEquations1D)434rho_ll, rho_v1_ll, _ = u_ll435rho_rr, rho_v1_rr, _ = u_rr436437# Calculate velocities (ignore orientation since it is always "1" in 1D)438# and fast magnetoacoustic wave speeds439# left440v_ll = rho_v1_ll / rho_ll441cf_ll = calc_fast_wavespeed(u_ll, orientation, equations)442# right443v_rr = rho_v1_rr / rho_rr444cf_rr = calc_fast_wavespeed(u_rr, orientation, equations)445446return max(abs(v_ll) + cf_ll, abs(v_rr) + cf_rr)447end448449# Calculate estimates for minimum and maximum wave speeds for HLL-type fluxes450@inline function min_max_speed_naive(u_ll, u_rr, orientation::Integer,451equations::IdealGlmMhdEquations1D)452rho_ll, rho_v1_ll, _ = u_ll453rho_rr, rho_v1_rr, _ = u_rr454455# Calculate primitive variables456v1_ll = rho_v1_ll / rho_ll457v1_rr = rho_v1_rr / rho_rr458459λ_min = v1_ll - calc_fast_wavespeed(u_ll, orientation, equations)460λ_max = v1_rr + calc_fast_wavespeed(u_rr, orientation, equations)461462return λ_min, λ_max463end464465# More refined estimates for minimum and maximum wave speeds for HLL-type fluxes466@inline function min_max_speed_davis(u_ll, u_rr, orientation::Integer,467equations::IdealGlmMhdEquations1D)468rho_ll, rho_v1_ll, _ = u_ll469rho_rr, rho_v1_rr, _ = u_rr470471# Calculate primitive variables472v1_ll = rho_v1_ll / rho_ll473v1_rr = rho_v1_rr / rho_rr474475# Approximate the left-most and right-most eigenvalues in the Riemann fan476c_f_ll = calc_fast_wavespeed(u_ll, orientation, equations)477c_f_rr = calc_fast_wavespeed(u_rr, orientation, equations)478479λ_min = min(v1_ll - c_f_ll, v1_rr - c_f_rr)480λ_max = max(v1_ll + c_f_ll, v1_rr + c_f_rr)481482return λ_min, λ_max483end484485"""486min_max_speed_einfeldt(u_ll, u_rr, orientation::Integer, equations::IdealGlmMhdEquations1D)487488Calculate minimum and maximum wave speeds for HLL-type fluxes as in489- Li (2005)490An HLLC Riemann solver for magneto-hydrodynamics491[DOI: 10.1016/j.jcp.2004.08.020](https://doi.org/10.1016/j.jcp.2004.08.020).492"""493@inline function min_max_speed_einfeldt(u_ll, u_rr, orientation::Integer,494equations::IdealGlmMhdEquations1D)495rho_ll, rho_v1_ll, _ = u_ll496rho_rr, rho_v1_rr, _ = u_rr497498# Calculate primitive variables499v1_ll = rho_v1_ll / rho_ll500v1_rr = rho_v1_rr / rho_rr501502# Approximate the left-most and right-most eigenvalues in the Riemann fan503c_f_ll = calc_fast_wavespeed(u_ll, orientation, equations)504c_f_rr = calc_fast_wavespeed(u_rr, orientation, equations)505vel_roe, c_f_roe = calc_fast_wavespeed_roe(u_ll, u_rr, orientation, equations)506λ_min = min(v1_ll - c_f_ll, vel_roe - c_f_roe)507λ_max = max(v1_rr + c_f_rr, vel_roe + c_f_roe)508509return λ_min, λ_max510end511512@inline function max_abs_speeds(u, equations::IdealGlmMhdEquations1D)513rho, rho_v1, _ = u514v1 = rho_v1 / rho515cf_x_direction = calc_fast_wavespeed(u, 1, equations)516517return abs(v1) + cf_x_direction518end519520# Convert conservative variables to primitive521@inline function cons2prim(u, equations::IdealGlmMhdEquations1D)522rho, rho_v1, rho_v2, rho_v3, rho_e, B1, B2, B3 = u523524v1 = rho_v1 / rho525v2 = rho_v2 / rho526v3 = rho_v3 / rho527p = (equations.gamma - 1) * (rho_e -5280.5f0 * (rho_v1 * v1 + rho_v2 * v2 + rho_v3 * v3529+ B1 * B1 + B2 * B2 + B3 * B3))530531return SVector(rho, v1, v2, v3, p, B1, B2, B3)532end533534# Convert conservative variables to entropy535@inline function cons2entropy(u, equations::IdealGlmMhdEquations1D)536rho, rho_v1, rho_v2, rho_v3, rho_e, B1, B2, B3 = u537538v1 = rho_v1 / rho539v2 = rho_v2 / rho540v3 = rho_v3 / rho541v_square = v1^2 + v2^2 + v3^2542p = (equations.gamma - 1) *543(rho_e - 0.5f0 * rho * v_square - 0.5f0 * (B1^2 + B2^2 + B3^2))544s = log(p) - equations.gamma * log(rho)545rho_p = rho / p546547w1 = (equations.gamma - s) / (equations.gamma - 1) - 0.5f0 * rho_p * v_square548w2 = rho_p * v1549w3 = rho_p * v2550w4 = rho_p * v3551w5 = -rho_p552w6 = rho_p * B1553w7 = rho_p * B2554w8 = rho_p * B3555556return SVector(w1, w2, w3, w4, w5, w6, w7, w8)557end558559# Convert primitive to conservative variables560@inline function prim2cons(prim, equations::IdealGlmMhdEquations1D)561rho, v1, v2, v3, p, B1, B2, B3 = prim562563rho_v1 = rho * v1564rho_v2 = rho * v2565rho_v3 = rho * v3566rho_e = p / (equations.gamma - 1) +5670.5f0 * (rho_v1 * v1 + rho_v2 * v2 + rho_v3 * v3) +5680.5f0 * (B1^2 + B2^2 + B3^2)569570return SVector(rho, rho_v1, rho_v2, rho_v3, rho_e, B1, B2, B3)571end572573@inline function density(u, equations::IdealGlmMhdEquations1D)574rho, rho_v1, rho_v2, rho_v3, rho_e, B1, B2, B3 = u575return rho576end577578@inline function velocity(u, equations::IdealGlmMhdEquations1D)579rho = u[1]580v1 = u[2] / rho581v2 = u[3] / rho582v3 = u[4] / rho583return SVector(v1, v2, v3)584end585586@inline function velocity(u, orientation::Int, equations::IdealGlmMhdEquations1D)587rho = u[1]588v = u[orientation + 1] / rho589return v590end591592@inline function pressure(u, equations::IdealGlmMhdEquations1D)593rho, rho_v1, rho_v2, rho_v3, rho_e, B1, B2, B3 = u594p = (equations.gamma - 1) * (rho_e - 0.5f0 * (rho_v1^2 + rho_v2^2 + rho_v3^2) / rho595-5960.5f0 * (B1^2 + B2^2 + B3^2))597return p598end599600@inline function density_pressure(u, equations::IdealGlmMhdEquations1D)601rho, rho_v1, rho_v2, rho_v3, rho_e, B1, B2, B3 = u602p = (equations.gamma - 1) * (rho_e - 0.5f0 * (rho_v1^2 + rho_v2^2 + rho_v3^2) / rho603-6040.5f0 * (B1^2 + B2^2 + B3^2))605return rho * p606end607608# Compute the fastest wave speed for ideal MHD equations: c_f, the fast magnetoacoustic eigenvalue609@inline function calc_fast_wavespeed(cons, direction, equations::IdealGlmMhdEquations1D)610rho, rho_v1, rho_v2, rho_v3, rho_e, B1, B2, B3 = cons611v1 = rho_v1 / rho612v2 = rho_v2 / rho613v3 = rho_v3 / rho614v_mag = sqrt(v1^2 + v2^2 + v3^2)615p = (equations.gamma - 1) *616(rho_e - 0.5f0 * rho * v_mag^2 - 0.5f0 * (B1^2 + B2^2 + B3^2))617a_square = equations.gamma * p / rho618sqrt_rho = sqrt(rho)619b1 = B1 / sqrt_rho620b2 = B2 / sqrt_rho621b3 = B3 / sqrt_rho622b_square = b1^2 + b2^2 + b3^2623624c_f = sqrt(0.5f0 * (a_square + b_square) +6250.5f0 * sqrt((a_square + b_square)^2 - 4 * a_square * b1^2))626return c_f627end628629"""630calc_fast_wavespeed_roe(u_ll, u_rr, direction, equations::IdealGlmMhdEquations1D)631632Compute the fast magnetoacoustic wave speed using Roe averages633as given by634- Cargo and Gallice (1997)635Roe Matrices for Ideal MHD and Systematic Construction636of Roe Matrices for Systems of Conservation Laws637[DOI: 10.1006/jcph.1997.5773](https://doi.org/10.1006/jcph.1997.5773)638"""639@inline function calc_fast_wavespeed_roe(u_ll, u_rr, direction,640equations::IdealGlmMhdEquations1D)641rho_ll, rho_v1_ll, rho_v2_ll, rho_v3_ll, rho_e_ll, B1_ll, B2_ll, B3_ll = u_ll642rho_rr, rho_v1_rr, rho_v2_rr, rho_v3_rr, rho_e_rr, B1_rr, B2_rr, B3_rr = u_rr643644# Calculate primitive variables645v1_ll = rho_v1_ll / rho_ll646v2_ll = rho_v2_ll / rho_ll647v3_ll = rho_v3_ll / rho_ll648vel_norm_ll = v1_ll^2 + v2_ll^2 + v3_ll^2649mag_norm_ll = B1_ll^2 + B2_ll^2 + B3_ll^2650p_ll = (equations.gamma - 1) *651(rho_e_ll - 0.5f0 * rho_ll * vel_norm_ll - 0.5f0 * mag_norm_ll)652653v1_rr = rho_v1_rr / rho_rr654v2_rr = rho_v2_rr / rho_rr655v3_rr = rho_v3_rr / rho_rr656vel_norm_rr = v1_rr^2 + v2_rr^2 + v3_rr^2657mag_norm_rr = B1_rr^2 + B2_rr^2 + B3_rr^2658p_rr = (equations.gamma - 1) *659(rho_e_rr - 0.5f0 * rho_rr * vel_norm_rr - 0.5f0 * mag_norm_rr)660661# compute total pressure which is thermal + magnetic pressures662p_total_ll = p_ll + 0.5f0 * mag_norm_ll663p_total_rr = p_rr + 0.5f0 * mag_norm_rr664665# compute the Roe density averages666sqrt_rho_ll = sqrt(rho_ll)667sqrt_rho_rr = sqrt(rho_rr)668inv_sqrt_rho_add = 1 / (sqrt_rho_ll + sqrt_rho_rr)669inv_sqrt_rho_prod = 1 / (sqrt_rho_ll * sqrt_rho_rr)670rho_ll_roe = sqrt_rho_ll * inv_sqrt_rho_add671rho_rr_roe = sqrt_rho_rr * inv_sqrt_rho_add672# Roe averages673# velocities and magnetic fields674v1_roe = v1_ll * rho_ll_roe + v1_rr * rho_rr_roe675v2_roe = v2_ll * rho_ll_roe + v2_rr * rho_rr_roe676v3_roe = v3_ll * rho_ll_roe + v3_rr * rho_rr_roe677B1_roe = B1_ll * rho_ll_roe + B1_rr * rho_rr_roe678B2_roe = B2_ll * rho_ll_roe + B2_rr * rho_rr_roe679B3_roe = B3_ll * rho_ll_roe + B3_rr * rho_rr_roe680# enthalpy681H_ll = (rho_e_ll + p_total_ll) / rho_ll682H_rr = (rho_e_rr + p_total_rr) / rho_rr683H_roe = H_ll * rho_ll_roe + H_rr * rho_rr_roe684# temporary variable see equations (4.12) in Cargo and Gallice685X = 0.5f0 * ((B1_ll - B1_rr)^2 + (B2_ll - B2_rr)^2 + (B3_ll - B3_rr)^2) *686inv_sqrt_rho_add^2687# averaged components needed to compute c_f, the fast magnetoacoustic wave speed688b_square_roe = (B1_roe^2 + B2_roe^2 + B3_roe^2) * inv_sqrt_rho_prod # scaled magnectic sum689a_square_roe = ((2 - equations.gamma) * X +690(equations.gamma - 1) *691(H_roe - 0.5f0 * (v1_roe^2 + v2_roe^2 + v3_roe^2) -692b_square_roe)) # acoustic speed693# finally compute the average wave speed and set the output velocity694# Ignore orientation since it is always "1" in 1D695c_a_roe = B1_roe^2 * inv_sqrt_rho_prod # (squared) Alfvén wave speed696a_star_roe = sqrt((a_square_roe + b_square_roe)^2 - 4 * a_square_roe * c_a_roe)697c_f_roe = sqrt(0.5f0 * (a_square_roe + b_square_roe + a_star_roe))698699return v1_roe, c_f_roe700end701702# Calculate thermodynamic entropy for a conservative state `cons`703@inline function entropy_thermodynamic(cons, equations::IdealGlmMhdEquations1D)704# Pressure705p = (equations.gamma - 1) *706(cons[5] - 0.5f0 * (cons[2]^2 + cons[3]^2 + cons[4]^2) / cons[1]707-7080.5f0 * (cons[6]^2 + cons[7]^2 + cons[8]^2))709710# Thermodynamic entropy711s = log(p) - equations.gamma * log(cons[1])712713return s714end715716# Calculate mathematical entropy for a conservative state `cons`717@inline function entropy_math(cons, equations::IdealGlmMhdEquations1D)718S = -entropy_thermodynamic(cons, equations) * cons[1] / (equations.gamma - 1)719720return S721end722723# Default entropy is the mathematical entropy724@inline entropy(cons, equations::IdealGlmMhdEquations1D) = entropy_math(cons, equations)725726# Calculate total energy for a conservative state `cons`727@inline energy_total(cons, ::IdealGlmMhdEquations1D) = cons[5]728729# Calculate kinetic energy for a conservative state `cons`730@inline function energy_kinetic(cons, equations::IdealGlmMhdEquations1D)731return 0.5f0 * (cons[2]^2 + cons[3]^2 + cons[4]^2) / cons[1]732end733734# Calculate the magnetic energy for a conservative state `cons'.735# OBS! For non-dinmensional form of the ideal MHD magnetic pressure ≡ magnetic energy736@inline function energy_magnetic(cons, ::IdealGlmMhdEquations1D)737return 0.5f0 * (cons[6]^2 + cons[7]^2 + cons[8]^2)738end739740# Calculate internal energy for a conservative state `cons`741@inline function energy_internal(cons, equations::IdealGlmMhdEquations1D)742return (energy_total(cons, equations)743-744energy_kinetic(cons, equations)745-746energy_magnetic(cons, equations))747end748749# Calculate the cross helicity (\vec{v}⋅\vec{B}) for a conservative state `cons'750@inline function cross_helicity(cons, ::IdealGlmMhdEquations1D)751return (cons[2] * cons[6] + cons[3] * cons[7] + cons[4] * cons[8]) / cons[1]752end753end # @muladd754755756