Gasdynamic library
Eilmerâ€™s gasdynamic library is accessible from your Lua scripts and is also available as a loadable library for Python and Ruby. It provides access to functions for the thermochemical gas model and, built on top of that, a number of functions for simple statetostate and streamtube flow analysis. This is the reference manual for the Python and Lua flavours of the library.
Lets start with a small example to set up a gas model and do a normal shock calculation. From within your Python script, you might try the following:
# Python
from eilmer.gas import GasModel, GasState, GasFlow
gmodel = GasModel('ceaair5speciesgasmodel.lua')
state1 = GasState(gmodel)
state1.p = 125.0e3 # Pa
state1.T = 300.0 # K
state1.update_thermo_from_pT()
state1.update_sound_speed()
print("# Initial test gas:")
print("# state1: %s" % state1)
print("# Normal shock, given shock speed")
vs = 2414.0
print("# vs=%g" % vs)
state2 = GasState(gmodel)
flow = GasFlow(gmodel)
v2, vg = flow.normal_shock(state1, vs, state2)
print("# v2=%g vg=%g" % (v2, vg))
print("# state2: %s" % state2)
The same functions are available to a Lua script given to the gascalc
program.
 Lua
gmodel = GasModel:new{'ceaair5speciesgasmodel.lua'}
state1 = GasState:new{gmodel}
state1.p = 125.0e3; state1.T = 300.0
gmodel:updateThermoFromPT(state1)
print("state1:"); printValues(state1)
print("normal shock, given shock speed")
Vs = 2414.0
state2, V2, Vg = gasflow.normal_shock(state1, Vs)
print(" V2=", V2, "Vg=", Vg)
print(" state2:"); printValues(state2)
Note that there are small but significant differences in calling the functions from Lua, compared with Python3. If you have not yet read the Gas Models User Guide, this is a good time to do so.
1. Installing the library
The gas models library for is part of a larger gasdynamics toolkit and general getting started notes can be found at https://gdtk.uqcloud.net/docs/gettingstarted/prerequisites . There, you will see how to get a copy of the source code, and a list of what other software you will need to build and install the tool kit, and a collection of environment variables that need to be set.
To install the library and the gascalc program,
move to the gas source directory and use the make
utility.
cd dgd/src/gas make install
Note that the loadable library needs to be built with the DMD64 compiler and that
you need the ForeignFunctionInterface extensions for your Python and Ruby interpreters.
On a LinuxMint system this package is pythoncffi
.
So that the Python interpreter can find the installed library, set your environment variables with something like:
export DGD=$HOME/dgdinst export PYTHONPATH=${PYTHONPATH}:${DGD}/lib export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:${DGD}/lib
2. Gas model and state objects
A number of gas models are encoded in Dlanguage modules and are available via a generic interface.
2.1. GasModel
# Python
gmodel = GasModel(file_name)
 Lua
gmodel = GasModel:new{file_name}
file_name

string, no default
Specifies the name of the detailed gas model configuration file. This is a Lua format file, constructed as described in the Gas Models User Guide.
2.1.1. Properties
# Python
gmodel.id
The index to the underlying Dlanguage gas model that is initialized during construction of the Python GasModel object.
# Python
gmodel.n_species
 Lua
gmodel:nSpecies()
Is the number of chemical species in the gas model.
# Python
gmodel.species_names
 Lua
gmodel:speciesName(isp)
In Python we get the list of the chemical species names in the gas model as a list of strings. In Lua, we specify the index for each species and get its name. The indices of the particular species may be useful for some of the method calls below.
# Python
gmodel.n_modes
 Lua
gmodel.nModes()
Is the number of internal energy modes (separate to the thermal internal energy) in the gas model.
# Python
gmodel.mol_masses
 Lua
gmodel:molMasses()
Is a list of molecular masses in units of kg/m^3.
2.1.2. Methods
# Python
gmodel.update_thermo_from_pT(gstate)
 Lua
gmodel:updateThermoFromPT(gstate)
Given a GasState object, and assuming that its pressure,
temperature and mass fractions are set,
compute the other thermodynamic properties of the gas state.
The Python function returns None
.
# Python
gmodel.update_thermo_from_rhou(gstate)
 Lua
gmodel:updateThermoFromRHOU(gstate)
Given a GasState object, and assuming that its density,
internal energy and mass fractions are set,
compute the other thermodynamic properties of the gas state.
The Python function returns None
.
# Python
gmodel.update_thermo_from_rhoT(gstate)
 Lua
gmodel:updateThermoFromRHOT(gstate)
Given a GasState object, and assuming that its density,
temperature and mass fractions are set,
compute the other thermodynamic properties of the gas state.
The Python function returns None
.
# Python
gmodel.update_thermo_from_rhop(gstate)
 Lua
gmodel:updateThermoFromRHOP(gstate)
Given a GasState object, and assuming that its density,
pressure and mass fractions are set,
compute the other thermodynamic properties of the gas state.
The Python function returns None
.
# Python
gmodel.update_thermo_from_ps(gstate, s)
 Lua
gmodel:updateThermoFromPS(gstate, s)
Given a GasState object and a value of entropy,
and assuming that gas state pressure and mass fractions are set,
compute the other thermodynamic properties of the gas state.
The units of entropy, s
, are J/kg.K.
The Python function returns None
.
# Python
gmodel.update_thermo_from_hs(gstate, h, s)
 Lua
gmodel:updateThermoFromHS(gstate, h, s)
Given a GasState object and values of enthalpy and entropy,
and assuming that gas state mass fractions are set,
compute the other thermodynamic properties of the gas state.
The units of enthalpy, h
, are J/kg and the units of entropy, s
, are J/kg.K.
The Python function returns None
.
# Python
gmodel.update_sound_speed(gstate)
 Lua
gmodel:updateSoundSpeed(gstate)
The underlying Dlanguage gas model has the soundspeed calculation
separate to the other calculations for other thermodynamic properties.
This function reflects that separation, hovever, the other Python
methods mentioned above actually do update the soundspeed along with
the other thermodynamic properties of the gas state; the Lua methods do not.
The Python function returns None
.
# Python
gmodel.update_trans_coeffs(gstate)
 Lua
gmodel:updateTransCoeffs(gstate)
Update the transport coefficients of viscosity and thermal conductivity.
The Python function returns None
.
# Python
gmodel.Cv(gstate)
 Lua
gmodel:Cv(gstate)
Returns the specific heat capacity for a constant volume process, J/kg.K.
# Python
gmodel.Cp(gstate)
 Lua
gmodel:Cp(gstate)
Returns the specific heat capacity for a constant pressure process, J/kg.K.
# Python
gmodel.dpdrho_const_T(gstate)
 Lua
gmodel:dpdrhoConstT(gstate)
Returns the derivative. Equivalent to RT
for a thermally perfect gas.
# Python
gmodel.R(gstate)
 Lua
gmodel:R(gstate)
Returns the gas constant for the gas state. Units are J/kg.K.
# Python
gmodel.gamma(gstate)
 Lua
gmodel:gamma(gstate)
Returns the ratio of specific heats for the gas state. Nondimensional.
# Python
gmodel.Prandtl(gstate)
 Lua
gmodel:Prandtl(gstate)
Returns the ratio of momentum diffusivity to thermal diffusivity. Nondimensional.
# Python
gmodel.internal_energy(gstate)
 Lua
gmodel:intEnergy(gstate)
Returns the full internal energy of the gas state. This is the sum of thermal internal energy and any other internal energy modes of the gas model. Units are J/kg.
# Python
gmodel.enthalpy(gstate)
 Lua
gmodel:enthalpy(gstate)
Returns the specific enthalpy of the gas state, in J/kg.
# Python
gmodel.entropy(gstate)
 Lua
gmodel:entropy(gstate)
Returns the specific entropy of the gas state, in J/kg.K.
# Python
gmodel.molecular_mass(gstate)
 Lua
gmodel:molMass(gstate)
Returns the molecular mass of the gas state, in kg/m^3. This is most useful for chemicallyreacting gases where the value will change with mixture fractions of the species.
# Python
gmodel.enthalpy_isp(gstate, isp)
 Lua
gmodel:enthalpy(gstate, isp)
Returns the specific enthalpy for a particular chemical species,
at index isp
, of the gas state.
Units are J/kg.
# Python
gmodel.entropy_isp(gstate, isp)
 Lua
gmodel:entropy(gstate, isp)
Returns the specific entropy for a particular chemical species,
at index isp
, of the gas state.
Units are J/kg.K.
# Python
gmodel.gibbs_free_energy_isp(gstate, isp)
 Lua
gmodel:gibbsFreeEnergy(gstate, isp)
Returns the Gibbs Free Energy value for a particular chemical species,
at index isp
, of the gas state.
Units are J/kg.
# Python
gmodel.massf2molef(massf)
 Lua
gmodel:massf2molef(gstate)
Given the mass fractions of a gas mixture, returns the list of equivalent mole fractions. In Python, the massfraction values may be supplied in a dictionary. In Lua, the mass fractions are taken from the GasState object.
# Python
gmodel.molef2massf(molef)
 Lua
gmodel:molef2massf(molef, gstate)
Given the mole fractions of a gas mixture, returns the list of equivalent mass fractions. The molefraction values may be supplied in a dictionary. In the Lua call, the table of mass fractions in the GasState object is also updated.
2.2. GasState
Any number of GasState objects may be constructed in the context of a GasModel object.
# Python
gstate = GasState(gmodel)
 Lua
gstate = GasState:new{gmodel}
In Python, the GasState object retains a reference to the gas model used in its construction. In Lua, the GasState object is a Lua table with named entries.
2.2.1. Properties
# Python
gstate.id
The index to the underlying Dlanguage gas state that is initialized during the construction of the Python GasState object.
# Python
gstate.rho
 Lua
gstate.rho
Gas density, in kg/m^3. This property may be used in an expression or a new value may be assigned.
# Python
gstate.p
 Lua
gstate.p
Gas pressure, in Pa. This property may be used in an expression or a new value may be assigned.
# Python
gstate.T
 Lua
gstate.T
Gas temperature, in K. This property may be used in an expression or a new value may be assigned.
# Python
gstate.u
 Lua
gstate.u
Thermal internal energy, in J/kg. This property may be used in an expression or a new value may be assigned.
# Python
gstate.a
 Lua
gstate.a
Sound speed, m/s. This property is readonly.
# Python
gstate.k
 Lua
gstate.k
Thermal conductivity, in W/m.K. This property is readonly.
# Python
gstate.mu
 Lua
gstate.mu
Dynamic viscosity, Pa.s. This property is readonly.
# Python
gstate.massf
 Lua
gstate.massf
In Python, this a list of the mass fractions of the chemical species.
It may be assigned a list with all of the species mass fraction values in order.
It may also be assigned a dictionary, with named entries.
In the dictionary form, you need provide only the nonzero values.
In any case, the mass fractions should sum to 1.0
.
In Lua, it is a table with named entries.
# Python
gstate.massf_as_dict
Is a dictionary of named massfraction values.
It is a readonly property. You may, however, assign to the massf
property.
# Python
gstate.molef
Is a list of the mole fractions of the chemical species.
It may be assigned a list with all of the species mass fraction values in order.
It may also be assigned a dictionary, with named entries.
In the dictionary form, you need provide only the nonzero values.
In any case, the mole fractions should sum to 1.0
.
# Python
gstate.molef_as_dict
Is a dictionary of named molefraction values.
It is a readonly property. You may, however, assign to the molef
property.
# Python
gstate.conc
Is a list of the concentrations, in mole/m^3, of the chemical species. It is a readonly property.
# Python
gstate.conc_as_dict
Is a dictionary of named concentration values. It is a readonly property.
# Python
gstate.u_modes
 Lua
gstate.u_modes
Is a list of internalenergy values for a multitemperature gas. Units are J/kg. When assigning a list, the full list must be supplied.
# Python
gstate.T_modes
 Lua
gstate.T_modes
Is a list of temperature values, in K, for a multitemperature gas. When assigning a list, the full list must be supplied.
# Python
gstate.k_modes
 Lua
gstate.k_modes
Is a list of thermal diffusivity coefficient values, in W/m.K, for a multitemperature gas. It is a readonly property.
# Python
gstate.ceaSavedData
 Lua
gstate.ceaSavedData
Is a dictionary of the data saved from the call out to the CEA2 program that was made when updating the thermodynamic properties for the gas state of the equilibrium mixture. This property is specific to the CEAgas model. If it exists, it contains the entries:
"p"

static pressure, Pa
"rho"

density, kg/m^3
"u"

specific internal energy, J/kg
"h"

specific enthalpy, J/kg
"T"

temperature, K
"a"

sound speed, m/s
"Mmass"

average molecular mass of the equilibrium mixture, kg/mole
"Rgas"

effective gas constant, J/kg/K
"gamma"

effective ratio of specific heats
"Cp"

effective specific heat, constant pressure, J/kg
"s"

specific entropy, J/kg.K
"mu"

effective viscosity coefficient, Pa.s
"mass"

dictionary of massfraction values for the species in the equilibrium mixture.
2.2.2. Methods
# Python
gstate.copy_values(other_gstate)
Copy property values from the other_gstate
object.
It is assumed that the GasModel is the same for east of the GasState objects.
# Python
gstate.update_thermo_from_pT()
Assuming that its pressure, temperature and mass fractions are set,
compute the other thermodynamic properties of the gas state.
Returns None
.
# Python
gstate.update_thermo_from_rhou()
Assuming that its density, internal energy and mass fractions are set,
compute the other thermodynamic properties of the gas state.
Returns None
.
# Python
gstate.update_thermo_from_rhoT()
Assuming that its density, temperature and mass fractions are set,
compute the other thermodynamic properties of the gas state.
Returns None
.
# Python
gstate.update_thermo_from_rhop()
Assuming that its density, pressure and mass fractions are set,
compute the other thermodynamic properties of the gas state.
Returns None
.
# Python
gstate.update_thermo_from_ps(s)
Given a value of entropy, and
assuming that gas state pressure and mass fractions are set,
compute the other thermodynamic properties of the gas state.
The units of entropy, s
, are J/kg.K.
Returns None
.
# Python
gstate.update_thermo_from_hs(h, s)
Given values of enthalpy and entropy,
and assuming that gas state mass fractions are set,
compute the other thermodynamic properties of the gas state.
The units of enthalpy, h
, are J/kg and the units of entropy, s
, are J/kg.K.
Returns None
.
# Python
gstate.update_sound_speed()
The underlying Dlanguage gas model has the soundspeed calculation
separate to the other calculations for other thermodynamic properties.
This function reflects that separation, hovever, the other Python
methods mentiond above actually do update the soundspeed along with
the other thermodynamic properties of the gas state.
Returns None
.
# Python
gstate.update_trans_coeffs()
Update the transport coefficients of viscosity and thermal conductivity.
Returns None
.
2.2.3. Other properties
These are for the Python library.
In Lua, you can access the same data via the GasModel
methods.
# Python
gstate.Cv
Returns the specific heat capacity for a constant volume process, J/kg.K.
# Python
gstate.Cp
Returns the specific heat capacity for a constant pressure process, J/kg.K.
# Python
gstate.dpdrho_const_T
Returns the derivative. Equivalent to RT
for a thermally perfect gas.
# Python
gstate.R
Returns the gas constant for the gas state. Units are J/kg.K.
# Python
gstate.gamma
Returns the ratio of specific heats for the gas state. Nondimensional.
# Python
gmodel.Prandtl(gstate)
Returns the ratio of momentum diffusivity to thermal diffusivity. Nondimensional.
# Python
gstate.internal_energy
Returns the full internal energy of the gas state. This is the sum of thermal internal energy and any other internal energy modes of the gas model. Units are J/kg.
# Python
gstate.enthalpy
Returns the specific enthalpy of the gas state, in J/kg.
# Python
gstate.entropy
Returns the specific entropy of the gas state, in J/kg.K.
# Python
gstate.molecular_mass
Returns the molecular mass of the gas state, in kg/m^3. This is most useful for chemicallyreacting gases where the value will change with mixture fractions of the species.
# Python
gstate.enthalpy_isp(isp)
Returns the specific enthalpy for a particular chemical species,
at index isp
, of the gas state.
Units are J/kg.
# Python
gstate.entropy_isp(isp)
Returns the specific entropy for a particular chemical species,
at index isp
, of the gas state.
Units are J/kg.K.
# Python
gstate.gibbs_free_energy_isp(isp)
Returns the Gibbs Free Energy value for a particular chemical species,
at index isp
, of the gas state.
Units are J/kg.
3. Thermochemical kinetics
If you have a gas model with several chemical species and/or with more than one temperature you may be interested in allowing the thermochemical processes to change the gas state in an otherwise isolated blob of gas.
Before trying the following functions, you should read the Reacting Gas Guide.
3.1. ThermochemicalReactor objects
# Python
reactor = ThermochemicalReactor(gmodel, filename1, filename2="")
 Lua
reactor = ThermochemicalReactor:new{gasmodel=gmodel, filename1='fname1', filename2=''}
gmodel

GasModel object, no default
is a reference to a suitable gas model. Not all gas models will have associated reactors but some, such as the ThermallyPerfectGas model do. filename1

string, no default.
File name for the detailed chemistry configuration file. filename2

string, default: ""
File name for the second detailed thermochemical configuration file. Only a few files will require a second configuration file.
3.2. Methods
To update the gas state over a finite interval of time, call
# Python
reactor.update_state(gstate, t_interval, dt_suggest)
 Lua
reactor:update_state(gstate, t_interval, dt_suggest)
gstate

GasState object, no default.
The gas state which will be altered. Because the hypothetical reactor is isolated, the density and internal energy of the blob of gas will remain fixed, while other thermochemical properties, including mass and molefractions change. t_interval

Float, no default.
The time interval, in seconds, over which to evolve the gas state. dt_suggest

Float, default 1.0
The suggested time step size for the thermochemical update. The default value of1.0
indicates to the reactor that we have no good idea and that it should select something suitable.
Returns the last successful timestep size, so that the value may be used in subsequent calls.
4. Statetostate flow processes
These functions are for computing simple processes involving the general gas models. In Python, the flow analysis functions are collected as methods of the GasFlow class. An object of this class needs to be constructed in the context of a particular gas model.
# Python
flow = GasFlow(gmodel)
In Lua, the functions are already available in the gascalc
program in a table called gasflow
.
4.1. Normal shock
For shock processing when we want to restrict the processing to the idealgas behaviour, use the following function.
# Python
v2, vg = flow.ideal_shock(state1, vs, state2)
 Lua
state2, v2, vg = gasflow.ideal_shock(state1, vs)
Parameters:
state1

GasState object, no default.
The initial gas state, before passing through the shock. vs

Float, no default.
Speed of gas, in m/s, coming into the shock (in a shock stationary frame), or the speed of the shock into quiescent gas (lab frame). state2

GasState object, no default.
The state of the gas after shock processing. In Python, you need to constructstate2
first, then pass it into the function to have its values mutated. v2

Float The postshock gas speed, in m/s, relative to the shock front.
vg

Float The postshock gas speed, in m/s, in the lab frame, for the case where the shock in moving into a quiescent gas.
For shock processing with more general, but still chemicallyfrozen, gas behaviour, use the following function.
# Python
v2, vg = flow.normal_shock(state1, vs, state2)
 Lua
state2, v2, vg = gasflow.normal_shock(state1, vs)
Parameters:
state1

GasState object, no default.
The initial gas state, before passing through the shock. vs

Float, no default.
Speed of gas, in m/s, coming into the shock (in a shock stationary frame), or the speed of the shock into quiescent gas (lab frame). state2

GasState object, no default.
The state of the gas after shock processing. In Python, you need to constructstate2
first, then pass it into the function to have its values mutated. v2

Float The postshock gas speed, in m/s, relative to the shock front.
vg

Float The postshock gas speed, in m/s, in the lab frame, for the case where the shock in moving into a quiescent gas.
For the case where the pressure ratio is provided, use the function:
# Python
vs, v2, vg = flow.normal_shock_p2p1(state1, p2p1, state2)
 Lua
vs, v2, vg = gasflow.normal_shock_p2p1(state1, p2p1)
Parameters:
state1

GasState object, no default.
The initial gas state, before passing through the shock. p2p1

Float, no default.
Ratio of pressures p2/p1 across the shock. state2

GasState object, no default for Python but not needed in Lua.
The state of the gas after shock processing. vs

Float The incident shock speed, in m/s.
v2

Float The postshock gas speed, in m/s, relative to the shock front.
vg

Float The postshock gas speed, in m/s, in the lab frame, for the case where the shock in moving into a quiescent gas.
For a reflected shock, as would be observed in a shock tunnel, we have the function:
# Python
vr = flow.reflected_shock(state2, vg, state5)
 Lua
state5, vr = gasflow.reflected_shock(state2, vg)
Parameters:
state1

GasState object, no default.
The state of the gas approaching the reflectedshock front. vg

Float The speed of the incoming gas (in m/s) in the lab frame.
state5

GasState object, no default in Python.
The state of the gas after reflectedshock processing.
The function returns vr
, the speed of the reflected shock (in m/s) in the lab frame.
In Python, the values within the userprovided state5
are altered.
4.2. Reversible steady flow
Allow a gas to expand through a steady isentropic process, from stagnation to a lower pressure.
# Python
v = flow.expand_from_stagnation(state0, p_over_p0, state1)
 Lua
state1, v = gasflow.expand_from_stagnation(state0, p_over_p0)
Parameters:
state0

GasState object, no default.
The initial stagnation state. p_over_p0

Float, no default.
The pressure of the expanded gas divided by the stagnation pressure. state1

GasState object, no default in Python.
The state of the gas after expansion. In Python, you need to constructstate1
first and pass it into the function to have its values mutated. v

The velocity (in m/s) of the expanded gas.
Allow a gas to expand through a steady isentropic process, from stagnation to a particular Mach number.
# Python
v = flow.expand_to_mach(state0, mach, state1)
 Lua
state1, v = gasflow.expand_to_mach(state0, mach)
Parameters:
state0

GasState object, no default.
The initial stagnation state. mach

Float, no default.
The Mach number of the expanded gas. state1

GasState object, no default.
The state of the gas after expansion. Although you might expectstate1
as output, in Python, you need to construct it first and pass it into the function to have its values mutated.
The function returns v
. the velocity (in m/s) of the expanded gas.
The Lua flavour also returns state1
.
Given a freestream, compute the corresponding stagnation condition.
# Python
flow.total_condition(state1, v1, state0)
 Lua
state0 = gasflow.total_condition(state1, v1)
Parameters:
state1

GasState object, no default.
The freestream state. v1

Float, no default.
The velocity (in m/s) of the free stream. state0

GasState object, no default in Python.
The stagnation state, following an isentropic compression from the freestream state. In Python, you need to constructstate0
first and pass it into the function to have its values mutated.
4.3. Pitot probe flow
Compute the state of gas at the stagnation point on a Pitot probe. For a subsonic freestream flow, this will be the same as for an isentropic compression. For a supersonic flow, there will be a normal shock, followed by an isentropic compression.
# Python
flow.pitot_condition(state1, v1, state2pitot)
 Lua
state2pitot = gasflow.pitot_condition(state1, v1)
Parameters:
state1

GasState object, no default.
The freestream state. v1

Float, no default.
The velocity (in m/s) of the free stream. state2pitot

GasState object, no default.
The stagnation state at the probe tip, after compression from the freestream state.
4.4. Steady flow in a duct
Steady, isentropic flow through a variablearea duct. Internally, this function iterates guesses for the pressure ratio, in order to keep massflux equal.
# Python
v2 = flow.steady_flow_with_area_change(state1, v1, area2_over_area1, state2, tol=1.0e4)
 Lua
state2, v2 = gasflow.steady_flow_with_area_change(state1, v1, area2_over_area1, tol)
Parameters:
state1

GasState object, no default.
The state at point 1 in the duct. v1

Float, no default.
The velocity (in m/s) at point 1. area2_over_area1

Float, no default.
The ratio of areas of the two points. state2

GasState object, no default.
The gas state at point 2. tol

Float, default
1.0e4
Tolerance on the massflux error.
4.5. Unsteady reversible flow
For compression and expansion processes that travel as a wave, the analysis steps along a characteristic trajectory that traverses the wave and integrates the effects numerically.
# Python
v2 = flow.finite_wave_dp(state1, v1, characteristic, p2, state2, steps=100)
 Lua
state2, v2 = gasflow.finite_wave_dp(state1, v1, characteristic, p2, steps)
Parameters:
state1

GasState object, no default.
The state before wave processing. v1

Float, no default.
The velocity (in m/s) before wave processing. Positive velocities are to the right. characteristic

string, no default.
Name of the characteristic trajectory that the integration process follows. Options are"cplus"
and"cminus"
. If the unsteady processing wave is moving left through the gas, the integration follows a "cplus" characteristic trajectory (from the left initial state to the right final state). p2

Float, no default.
The pressure (in Pa) after wave processing. state2

GasState object, no default.
The gas state after wave processing. steps

Int, default: 100
The pressure change is divided into a number of steps and the effects are integrated numerically. v2

Float:
the velocity of the gas following wave processing.
For the cases where we know the velocity of the expanded gas, we can take steps in velocity to get to the expanded state.
# Python
v2 = flow.finite_wave_dv(state1, v1, characteristic, v2_target, state2, steps=100, t_min=200.0)
 Lua
state2, v2 = gasflow.finite_wave_dv(state1, v1, characteristic, v2_target, steps, t_min)
Input:
state1

GasState object, no default.
The state before wave processing. v1

Float, no default.
The velocity (in m/s) before wave processing. characteristic

string, no default.
Name of the characteristic trajectory that the integration process follows. Options are"cplus"
and"cminus"
. If the unsteady processing wave is moving left through the gas, the integration follows a "cplus" characteristic trajectory (from the left initial state to the right final state). v2_target

Float, no default.
The expected velocity (in m/s) after wave processing. state2

GasState object, no default.
The gas state after wave processing. Although you might expectstate2
as output, you need to construct it first and pass it into the function to have its values mutated. steps

Int, default: 100
The velocity change is divided into a number of steps and the effects are integrated numerically. t_min

Float, default: 200.0
Minimum temperature (in degrees K) of the gas through the expansion. Because we are stepping in velocity, it is easy to demand a final velocity that can exceed the maximum velocity for a physically realizable expansion. A typical symptom of demanding too strong an expansion is a negative temperature for the expanded gas. v2

Float: the velocity of the gas following wave processing.
4.6. Riemann problem
The Riemann problem is at the core of our largerscale CFD codes.
Left and Right gas states are allowed to interact at their contact surface.
Processing of each initial state is via a leftrunning wave (into the Left state) and
a rightrunning wave (into the Right state).
The results of wave processing are two intermediate states (labelled star
)
that have a common pressure and velocity at the contact surface.
Osherâ€™s approximate Riemann solver assumes that both processing waves are isentropic.
# Python
pstar, wstar, wL, wR, velX0 = flow.osher_riemann(stateL, stateR, velL, velR, stateLstar, stateRstar, stateX0)
Input:
stateL

GasState object, no default.
The state on the left of the contact surface. stateR

GasState object, no default.
The state on the right of the contact surface. velL

Float, no default.
The velocity of the gas (in m/s) in the left initial state. velR

Float, no default.
The velocity of the gas (in m/s) in the right initial state. stateLstar

GasState object, no default.
The left intermediate state after wave processing. stateRstar

GasState object, no default.
The right intermediate state after wave processing. stateX0

GasState object, no default.
The interpolated state at the initial contactsurface location, after wave processing. As part of a flow simulation code, the details of this state may be used to compute the flux of mass, momentum and energy across the initial constactsurface location.
Although you might expect stateLstar
and statRstar
as output,
you need to construct them first and pass them into the function
to have their values mutated.
The function returns:
pstar

Float The common pressure at the contact surface between the intermediate states.
wstar

Float The common velocity at the contact surface between the intermediate states.
wL

Float The leadingedge wave speed of the leftmoving wave. If the wave is a compression, this is the shock speed.
wR

Float The leadingedge wave speed of the rightmoving wave. If the wave is a compression, this is the shock speed.
velX0

Float The velocity of the gas, interpolated at the initial location of the contactsurface.
4.7. Riemann subproblem for L1d
The Lagrangian flow solver has a specialized Riemann solver at its core.
# Python
pstar, wstar = flow.lrivp(stateL, stateR, velL, velR)
Input:
stateL

GasState object, no default.
The state on the left of the contact surface. stateR

GasState object, no default.
The state on the right of the contact surface. velL

Float, no default.
The velocity of the gas (in m/s) in the left initial state. velR

Float, no default.
The velocity of the gas (in m/s) in the right initial state.
The function returns:
pstar

Float The common pressure at the contact surface between the intermediate states.
wstar

Float The common velocity at the contact surface between the intermediate states.
When the gas is up against a solid face of a piston, we have the contactsurface velocity as known and we need to compute just the gas pressure at the contactsurface.
# Python
pstar = flow.piston_at_left(stateR, velR, wstar)
Input:
stateR

GasState object, no default.
The state on the right of the contact surface. velR

Float, no default.
The velocity of the gas (in m/s) in the right initial state. wstar

Float, no default.
The velocity (in m/s) of the gas at the contact (piston) surface.
The function returns pstar
(in Pa), the pressure at the contact surface.
# Python
pstar = flow.piston_at_right(stateL, velL, wstar)
Input:
stateL

GasState object, no default.
The state on the left of the contact surface. velL

Float, no default.
The velocity of the gas (in m/s) in the left initial state. wstar

Float, no default.
The velocity (in m/s) of the gas at the contact (piston) surface.
The function returns pstar
(in Pa), the pressure at the contact surface.
4.8. Oblique shock
Oblique straight shocks are analysed by splitting the velocity
into normal and tangential components.
The shock angle, with respect to the initial stream direction, is beta
.
The streamline deflection angle is theta
.
Given a shock angle, we can get the flow state after shock processing directly.
# Python
theta, v2 = flow.theta_oblique(state1, v1, beta, state2)
 Lua
state2, theta, v2 = gasflow.theta_oblique(state1, v1, beta)
Parameters:
state1

GasState object, no default.
The state before shock wave processing. v1

Float, no default.
The velocity of the gas (in m/s) before shock wave processing. beta

Float, no default.
Angle, in radians, of the shock with respect to the initial flow direction. state2

GasState object, no default.
The gas state after wave processing. Although you might expectstate2
as output, you need to construct it first and pass it into the function to have its values mutated. theta

Float the stream deflection angle (in radians)
v2

Float the speed of the gas in that deflected stream.
When you know the deflection angle and you want the shock angle, use the following function.
# Python
beta = flow.beta_oblique(state1, v1, theta)
 Lua
beta = gasflow.beta_oblique(state1, v1, theta)
Input:
state1

GasState object, no default.
The state before shock wave processing. v1

Float, no default.
The velocity of the gas (in m/s) before shock wave processing. theta

Float, no default.
Deflection angle, in radians, of the streamlines through the shock.
The function returns shock angle beta
for the weak shock solution
for the given streamline deflection angle.
The flow is assumed to remain supersonic following the shock.
The strongshock solution, resulting in subsonic downstream flow,
would be sensitive the (unspecified) details of whatever is downstream
and supporting the shock.
4.9. Conical shock
For the limits of thermochemicallyfrozen and thermochemicalequilibrium gases, there is a conical flow analysis for shock waves.
Given the freestream condition and a conical shock angle, the radial flow conditions can be integrated from just after the shock to the supporting conical body. The axis of the supporting cone is aligned with the freestream direction.
# Python
theta_c, v2_c = flow.theta_cone(state1, v1, beta, state_c)
Input:
state1

GasState object, no default.
The freestream state, before shock wave processing. v1

Float, no default.
The velocity of the gas (in m/s) in the free stream, before shock wave processing. beta

Float, no default.
Angle, in radians, of the conical shock with respect to the initial flow direction. state_c

GasState object, no default.
The gas state at the cone surface. Although you might expectstate_c
as output, you need to construct it first and pass it into the function to have its values mutated.
The function returns theta_c
the stream deflection angle (in radians) at the cone surface and
v2_c
, the speed of the gas in that deflected stream up the conical surface.
When you know the deflecting cone angle and you want the shock angle, use the following function.
# Python
beta = flow.beta_cone(state1, v1, theta)
Input:
state1

GasState object, no default.
The freestream state, before shock wave processing. v1

Float, no default.
The velocity of the gas (in m/s) in the free stream, before shock wave processing. theta

Float, no default.
Angle, in radians, of the deflecting cone.
The function returns shock angle beta
for the weak shock solution.
The flow is assumed to remain supersonic following the shock.
A subsonic postshock flow would be associated with a detached shock
and the flow field would not match the assumed conical arrangement.
5. Statetostate processes (ideal gas)
If the caloricallyperfect ideal gas model is sufficient for your analysis needs,
there is simple set of idealgas relations collected into the eilmer.ideal_gas
package.
The following functions do not use the generalized gas models but assume a gas bahaviour for fixed ratio of specific heats.
To get access to the functions, import the module into your Python script. For example:
# Python
import eilmer.ideal_gas_flow as igf
M = 2.0
print("Normal shock jump...")
print("Computed: M=%g: M2=%g, T2/T1=%g, p2/p1=%g, r2/r1=%g" %
(M, igf.m2_shock(M), igf.T2_T1(M), igf.p2_p1(M), igf.r2_r1(M)))
print("Expected: M1=2, M2=0.5774, T2/T1=1.687, p2/p1=4.50, r2/r1=2.667")
In a Lua script given to the gascalc
program, the functions are already available
in the table idealgasflow
.
5.1. Isentropic/adiabatic steady flow
# Python
igf.A_Astar(M, g=1.4)
 Lua
idealgasflow.A_Astar(M, g)
Input:
M

Float, no default. Mach number at area
A
, assuming sonic condition at areaAstar
g

Float, default: 1.4
Ratio of specific heats
Returns area ratio, A/Astar
, for an isentropic, quasionedimensional flow.
# Python
igf.T0_T(M, g=1.4)
 Lua
idealgasflow.T0_T(M, g)
Input:
M

Float, no default. Mach number.
g

Float, default: 1.4
Ratio of specific heats
Returns T0/T
, the ratio of total temperature over static temperature for adiabatic flow.
# Python
igf.p0_p(M, g=1.4)
 Lua
idealgasflow.p0_p(M, g)
Input:
M

Float, no default. Mach number.
g

Float, default: 1.4
Ratio of specific heats
Returns p0/p
, the ratio of total pressure over static pressure for isentropic flow.
# Python
igf.r0_r(M, g=1.4)
 Lua
idealgasflow.r0_r(M, g)
Input:
M

Float, no default. Mach number.
g

Float, default: 1.4
Ratio of specific heats
Returns rho0/rho
, the ratio of stagnation density over local for isentropic flow.
5.2. Normal shock
# Python
igf.m2_shock(M1, g=1.4)
 Lua
idealgasflow.m2_shock(M1, g)
Input:
M

Float, no default. Mach number.
g

Float, default: 1.4
Ratio of specific heats
Returns m2
, Mach number following the shock processing.
# Python
igf.r2_r1(M1, g=1.4)
 Lua
idealgasflow.r2_r1(M1, g)
Input:
M

Float, no default. Mach number.
g

Float, default: 1.4
Ratio of specific heats
Returns density ratio, r2/r1
, across a normal shock.
# Python
igf.v2_v1(M1, g=1.4)
 Lua
idealgasflow.u2_u1(M1, g)
Input:
M

Float, no default. Mach number.
g

Float, default: 1.4
Ratio of specific heats
Returns velocity ratio, v2/v1
, across a normal shock.
# Python
igf.p2_p1(M1, g=1.4)
 Lua
idealgasflow.p2_p1(M1, g)
Input:
M

Float, no default. Mach number.
g

Float, default: 1.4
Ratio of specific heats
Returns static pressure ratio, p2/p1
, across a normal shock.
# Python
igf.T2_T1(M1, g=1.4)
 Lua
idealgasflow.T2_T1(M1, g)
Input:
M

Float, no default. Mach number.
g

Float, default: 1.4
Ratio of specific heats
Returns static temperature ratio, T2/T1
, across a normal shock.
# Python
igf.p02_p01(M1, g=1.4)
 Lua
idealgasflow.p02_p01(M1, g)
Input:
M

Float, no default. Mach number.
g

Float, default: 1.4
Ratio of specific heats
Returns stagnation pressure ratio, p02/p01
, across a normal shock.
# Python
igf.ds_Cv(M1, g=1.4)
 Lua
idealgasflow.DS_Cv(M1, g)
Input:
M

Float, no default. Mach number.
g

Float, default: 1.4
Ratio of specific heats
Returns nondimensional entropy change, ds/Cv
, across a normal shock.
# Python
igf.pitot_p(p1, M1, g=1.4)
 Lua
idealgasflow.pitot_p(p1, M1, g)
Input:
M

Float, no default. Mach number.
g

Float, default: 1.4
Ratio of specific heats
Returns pitot pressure for a specified Mach number freestream flow.
The value will have the same units as input p1
.
5.3. Flow with heat addition.
Onedimensional flow with heat addition is also known as
Rayleighline flow.
The flow starts with local Mach number, M
, and (hypothetically) enough heat
is added for the flow to reach sonic (Mstar=1
) condition.
# Python
igf.T0_T0star(M, g=1.4)
 Lua
idealgasflow.T0_T0star(M, g)
Input:
M

Float, no default. initial Mach number.
g

Float, default: 1.4
Ratio of specific heats
Returns T0/T0star
where T0
is the total temperature of the initial flow
and T0star
is the total temperature that would be achieved if enough heat
is added to get to the sonic condition.
# Python
igf.M_Rayleigh(T0T0star, g=1.4)
 Lua
idealgasflow.M_Rayleigh(T0T0star, g)
Input:
T0T0star

Float, no default. T0/T0star where T0 is the total temperature of the initial flow and T0star is the total temperature that would be achieved if enough heat is added to get to the sonic condition.
g

Float, default: 1.4
Ratio of specific heats
Returns the initial Mach number, M
, of the flow.
# Python
igf.T_Tstar(M, g=1.4)
 Lua
idealgasflow.T_Tstar(M, g)
Input:
M

Float, no default. Mach number.
g

Float, default: 1.4
Ratio of specific heats
Returns T/Tstar
where T
is the static temperature of the initial flow
and Tstar
is the static temperature that would be achieved if enough heat
is added to get to sonic condition.
# Python
igf.p_pstar(M, g=1.4)
 Lua
idealgasflow.p_pstar(M, g)
Input:
M

Float, no default. Mach number.
g

Float, default: 1.4
Ratio of specific heats
Returns p/pstar
where p
is the static pressure of the initial flow
and pstar
is the static pressure that would be achieved if enough heat
is added to get to sonic conditions.
# Python
igf.r_rstar(M, g=1.4)
 Lua
idealgasflow.r_rstar(M, g)
Input:
M

Float, no default. Mach number.
g

Float, default: 1.4
Ratio of specific heats
Returns density ratio, rho/rhostar
, where rho
is the density
of the initial flow and rhostar
is the density that would be achieved
if enough heat is added to get to sonic conditions.
# Python
igf.p0_p0star(M, g=1.4)
 Lua
idealgasflow.p0_p0star(M, g)
Input:
M

Float, no default. Mach number.
g

Float, default: 1.4
Ratio of specific heats
Returns p0/p0star
where p0
is the total pressure of the initial flow
and p0star
is the total pressure that would be achieved
if enough heat is added to get to sonic conditions.
5.4. Supersonic turning
# Python
igf.PM1(M, g=1.4)
 Lua
idealgasflow.PM1(M, g)
Input:
M

Float, no default. Mach number.
g

Float, default: 1.4
Ratio of specific heats
Returns PrandtlMeyer function value, in radians.
# Python
igf.PM2(nu, g=1.4)
 Lua
idealgasflow.PM2(nu, g)
Input:
nu

Float, no default. PrandtlMeyer function value, in radians.
g

Float, default: 1.4
Ratio of specific heats
Returns corresponding Mach number.
 Lua
MachAngle(M)
Returns the Mach angle in radians.
5.5. Oblique shock
# Python
igf.beta_obl(M1, theta, g=1.4, tol=1.0e6)
 Lua
idealgasflow.beta_obl(M1, theta, g, tol)
Input:
M1

Float, no default. Mach number of gas before the shock.
theta

Float, no default. Steamline deflection angle, in radians.
g

Float, default: 1.4
Ratio of specific heats
Returns shock angle, beta
(in radians), with respect to the
original stream direction.
# Python
igf.beta_obl2(M1, p2_p1, g=1.4)
 Lua
idealgasflow.beta_obl2(M1, p2_p1, g)
Input:
M1

Float, no default. Mach number of gas before the shock.
p2_p1

Float, no default.
Static pressure ratio,p2/p1
, across the shock. g

Float, default: 1.4
Ratio of specific heats
Returns shock angle, beta
(in radians), with respect to the
original stream direction.
# Python
igf.theta_obl(M1, beta, g=1.4)
 Lua
idealgasflow.theta_obl(M1, beta, g)
Input:
M1

Float, no default. Mach number of gas before the shock.
beta

Float, no default.
Shock angle, in radians, relative to the original stream direction. g

Float, default: 1.4
Ratio of specific heats
Returns deflection angle of the stream, theta
(in radians).
# Python
igf.M2_obl(M1, beta, theta, g=1.4)
 Lua
idealgasflow.M2_obl(M1, beta, theta, g)
Input:
M1

Float, no default. Mach number of gas before the shock.
beta

Float, no default.
Shock angle, in radians, relative to the original stream direction. theta

Float, no default. Steamline deflection angle, in radians.
g

Float, default: 1.4
Ratio of specific heats
Returns M2
, Mach number in flow after the shock.
# Python
igf.r2_r1_obl(M1, beta, g=1.4)
 Lua
idealgasflow.r2_r1_obl(M1, beta, g)
Input:
M1

Float, no default. Mach number of gas before the shock.
beta

Float, no default.
Shock angle, in radians, relative to the original stream direction. g

Float, default: 1.4
Ratio of specific heats
Returns density ratio, rho2/rho1
across an oblique shock.
# Python
igf.vn2_vn1_obl(M1, beta, g=1.4)
 Lua
idealgasflow.Vn2_Vn1_obl(M1, beta, g)
Input:
M1

Float, no default. Mach number of gas before the shock.
beta

Float, no default.
Shock angle, in radians, relative to the original stream direction. g

Float, default: 1.4
Ratio of specific heats
Returns normalvelocity ratio, vn1/vn2
, across an oblique shock.
# Python
igf.v2_v1_obl(M1, beta, g=1.4)
 Lua
idealgasflow.V2_V1_obl(M1, beta, g)
Input:
M1

Float, no default. Mach number of gas before the shock.
beta

Float, no default.
Shock angle, in radians, relative to the original stream direction. g

Float, default: 1.4
Ratio of specific heats
Returns flowspeed ratio, v2/v1
, across an oblique shock.
# Python
igf.p2_p1_obl(M1, beta, g=1.4)
 Lua
idealgasflow.p2_p1_obl(M1, beta, g)
Input:
M1

Float, no default. Mach number of gas before the shock.
beta

Float, no default.
Shock angle, in radians, relative to the original stream direction. g

Float, default: 1.4
Ratio of specific heats
Returns static pressure ratio, p2/p1
, across an oblique shock.
# Python
igf.T2_T1_obl(M1, beta, g=1.4)
 Lua
idealgasflow.T2_T1_obl(M1, beta, g)
Input:
M1

Float, no default. Mach number of gas before the shock.
beta

Float, no default.
Shock angle, in radians, relative to the original stream direction. g

Float, default: 1.4
Ratio of specific heats
Returns static temperature ratio, T2/T1
, across an oblique shock.
# Python
igf.p02_p01_obl(M1, beta, g=1.4)
 Lua
idealgasflow.p02_p01_obl(M1, beta, g)
Input:
M1

Float, no default. Mach number of gas before the shock.
beta

Float, no default.
Shock angle, in radians, relative to the original stream direction. g

Float, default: 1.4
Ratio of specific heats
Returns ratio of stagnation pressures, p02/p01
, across an oblique shock.
5.6. TaylorMaccoll cone flow
Compute the conesurface angle and conditions given the shock wave angle.
The computation starts with the obliqueshock jump and then integrates
across theta until V_theta goes through zero.
The cone surface corresponds to V_theta == 0
.
# Python
igf.theta_cone(V1, p1, T1, beta, R=287.1, g=1.4)
 Lua
idealgasflow.theta_cone(V1, p1, T1, beta, R, g)
Input:
V1

Float, no default. Speed of gas (in m/s) entering the shock.
p1

Float, no default. Static pressure of gas (in Pa) entering the shock.
T1

Float, no default. Static temperature of gas (in K) entering the shock.
beta

Float, no default.
Shock angle, in radians, relative to the original stream direction. R

Float, default: 287.1
Gas constant, inJ/kg.K
g

Float, default: 1.4
Ratio of specific heats
Returns tuple of (theta_c, V_c, p_c, T_c).
theta_c

stream deflection angle, in radians
V_c

the conesurface speed of gas, in m/s
p_c

the conesurface pressure, in Pa
T_c

the conesurface static temperature, in K
# Python
igf.beta_cone(V1, p1, T1, theta, R=287.1, g=1.4)
 Lua
idealgasflow.beta_cone(V1, p1, T1, theta, R, g)
Input:
V1

Float, no default. Speed of gas (in m/s) entering the shock.
p1

Float, no default. Static pressure of gas (in Pa) entering the shock.
T1

Float, no default. Static temperature of gas (in K) entering the shock.
theta

Float, no default.
Cone deflection angle, in radians. R

Float, default: 287.1
Gas constant, inJ/kg.K
g

Float, default: 1.4
Ratio of specific heats
Returns beta
, the shock wave angle (in radians) with respect to the freestream flow direction.
# Python
igf.beta_cone2(M1, theta, R=287.1, g=1.4)
 Lua
idealgasflow.beta_cone2(M1, theta, R, g)
Input:
M1

Float, no default. Mach number of gas entering the shock.
theta

Float, no default.
Cone deflection angle, in radians. R

Float, default: 287.1
Gas constant, inJ/kg.K
g

Float, default: 1.4
Ratio of specific heats
Returns beta
, the shock wave angle (in radians) with respect to the freestream flow direction.