Riemann Solvers

GadJet.jl provides a number of exact riemann solvers. So far these are for

  • Sod shock, pure hydro
  • Sod shock, with CR acceleration

Setup

To get the exact solution to a Sod shock you first need to set up the inital conditions. You can do this with the helper function RiemannParameters that contains all parameters for all possible configurations:

RiemannParameters(;rhol::Float64=1.0, rhor::Float64=0.125,      # density left and right (L&R)
                   Pl::Float64=0.0,   Pr::Float64=0.0,          # pressure L&R
                   Ul::Float64=0.0,   Ur::Float64=0.0,          # internal energy L&R
                   P_cr_l::Float64=0.0, P_cr_r::Float64=0.0,    # CR pressure L&R
                   E_cr_l::Float64=0.0, E_cr_r::Float64=0.0,    # CR energy L&R
                   Bl::Array{Float64,1} = zeros(3),             # B-field left
                   Br::Array{Float64,1} = zeros(3),             # B-field right
                   Mach::Float64=0.0,                           # target Mach number
                   t::Float64,                                  # time of the solution
                   x_contact::Float64=70.0,                     # position of the contact discontinuity along the tube
                   γ_th::Float64=5.0/3.0,                       # adiabatic index of the gas               
                   γ_cr::Float64=4.0/3.0,                       # adiabatic index of CRs
                   Pe_ratio::Float64=0.01,                      # ratio of proton to electron energy in acceleration
                   thetaB::Float64=0.0,                         # angle between magnetic field and shock normal
                   theta_crit::Float64=(π/4.0),                 # critical angle for B/Shock angle efficiency
                   dsa_model::Int64=-1,                         # diffuse shock acceleration model
                   xs_first_guess::Float64=4.7)                 # first guess of the resulting shock compression

To set up a standard Sod shock you need to supply it with pressure/energy values for left and right state, or with pressure/energy values for the left state and a target Mach number.

A minimal working version would be, for a shock with Mach 10, at time = 1.5:

par = RiemannParameters(Ul=100.0, Mach=10.0, t=1.5)

This returns a parameter object for a pure hydro Sod shock:

mutable struct SodParameters

    rhol::Float64           # denisty left
    rhor::Float64           # density right
    Pl::Float64             # pressure left
    Pr::Float64             # pressure right
    Ul::Float64             # internal energy left
    Ur::Float64             # internal energy right
    cl::Float64             # soundspeed left
    cr::Float64             # soundspeed right
    M::Float64              # Mach number
    t::Float64              # time
    x_contact::Float64      # position of the contact discontinuity along the tube
    γ_th::Float64           # adiabatic index of the gas
    γ_exp::Float64          # helper variable
    η2::Float64             # helper variable

end

A minimal working version for the solution of the CR shock discussed in Pfrommer+16 (doi:10.1093/mnras/stw2941) would be:

par = RiemannParameters(Pl=63.499, Pr=0.1, t=1.5, dsa_model=4)

This also returns a parameter object: SodCRParameters_noCRs which can be found in cr_sod_shock_noprepopulation.jl .

Solving the shock

To solve the shock with the given initial condition you just need to call

sol = solve(x, par)

with par being either of the above mentioned parameter objects, multiple dispatch will take care of the rest.

x has to be an array with either sample positions along the tube, or your actual particle positions, to make calculating errors easier. You can also just pass it an array with a single position, if you’re only interested in that specific part of the shock ( e.g. x = [86.0] for the center of the postshock region.)

This will return a solution object depending on which shock you’re solving.

For the pure hydro case this is:

mutable struct SodHydroSolution
    x::Array{Float64,1}         # array of given positions
    rho::Array{Float64,1}       # array of densities along the tube
    rho4::Float64               # density in postshock region
    rho3::Float64               # density between contact disc. and rarefaction wave
    P::Array{Float64,1}         # array of pressures along the tube
    P34::Float64                # pressure between shock and rarefaction wave
    U::Array{Float64,1}         # array of internal energies along the tube
    v::Array{Float64,1}         # array of velocities along the tube
    v34::Float64                # velocity between shock and rarefaction wave
    vt::Float64                 # velocity of rarefaction wave
    vs::Float64                 # shock velocity
    Mach::Float64               # Mach number
end

Utility

A common issue is running into the error DomainError when solving a CR Sod shock. This is due to the definition of the incomplete beta function. You can avoid this by supplying a value for xs_first_guess, which is a first guess for the value of the shock compression ratio. In case you don’t know the target xs (which is the usual case) and are tired of trying different values there’s a helper function for that:

function find_xs_first_guess(Ul::Float64, Mach::Float64;
                             xs_start::Float64=3.8, delta_xs::Float64=1.e-4,
                             eff_model::Int64=2, thetaB::Float64=0.0)

    [...]
end