Gas-dynamic library
Eilmer’s gas-dynamic 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 state-to-state and stream-tube 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 gdtk.gas import GasModel, GasState, GasFlow
gmodel = GasModel('cea-air5species-gas-model.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 gas-calc
program.
-- Lua
gmodel = GasModel:new{'cea-air5species-gas-model.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 gas-dynamics toolkit and general getting started notes can be found at https://gdtk.uqcloud.net/docs/getting-started/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 gas-calc 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 Foreign-Function-Interface extensions for your Python and Ruby interpreters.
On a LinuxMint system this package is python-cffi
.
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 D-language 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 D-language 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 D-language gas model has the sound-speed 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 sound-speed 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 chemically-reacting 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 mass-fraction 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 mole-fraction 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 D-language 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 read-only.
# Python
gstate.k
-- Lua
gstate.k
Thermal conductivity, in W/m.K. This property is read-only.
# Python
gstate.mu
-- Lua
gstate.mu
Dynamic viscosity, Pa.s. This property is read-only.
# 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 non-zero 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 mass-fraction values.
It is a read-only 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 non-zero values.
In any case, the mole fractions should sum to 1.0
.
# Python
gstate.molef_as_dict
Is a dictionary of named mole-fraction values.
It is a read-only 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 read-only property.
# Python
gstate.conc_as_dict
Is a dictionary of named concentration values. It is a read-only property.
# Python
gstate.u_modes
-- Lua
gstate.u_modes
Is a list of internal-energy values for a multi-temperature 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 multi-temperature 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 multi-temperature gas. It is a read-only 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 mass-fraction 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 D-language gas model has the sound-speed 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 sound-speed 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 chemically-reacting 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 mole-fractions 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 of-1.0
indicates to the reactor that we have no good idea and that it should select something suitable.
Returns the last successful time-step size, so that the value may be used in subsequent calls.
4. State-to-state 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 gas-calc
program in a table called gasflow
.
4.1. Normal shock
For shock processing when we want to restrict the processing to the ideal-gas 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 post-shock gas speed, in m/s, relative to the shock front.
vg
-
Float The post-shock 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 chemically-frozen, 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 post-shock gas speed, in m/s, relative to the shock front.
vg
-
Float The post-shock 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 post-shock gas speed, in m/s, relative to the shock front.
vg
-
Float The post-shock 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 reflected-shock 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 reflected-shock processing.
The function returns vr
, the speed of the reflected shock (in m/s) in the lab frame.
In Python, the values within the user-provided 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 free-stream, 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 free-stream 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 free-stream 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 free-stream 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 free-stream 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 free-stream state.
4.4. Steady flow in a duct
Steady, isentropic flow through a variable-area duct. Internally, this function iterates guesses for the pressure ratio, in order to keep mass-flux equal.
# Python
v2 = flow.steady_flow_with_area_change(state1, v1, area2_over_area1, state2, tol=1.0e-4)
-- 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.0e-4
Tolerance on the mass-flux 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 larger-scale CFD codes.
Left and Right gas states are allowed to interact at their contact surface.
Processing of each initial state is via a left-running wave (into the Left state) and
a right-running 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 contact-surface 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 constact-surface 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 leading-edge wave speed of the left-moving wave. If the wave is a compression, this is the shock speed.
wR
-
Float The leading-edge wave speed of the right-moving 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 contact-surface.
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 contact-surface velocity as known and we need to compute just the gas pressure at the contact-surface.
# 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 strong-shock 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 thermochemically-frozen and thermochemical-equilibrium gases, there is a conical flow analysis for shock waves.
Given the free-stream 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 free-stream direction.
# Python
theta_c, v2_c = flow.theta_cone(state1, v1, beta, state_c)
Input:
state1
-
GasState object, no default.
The free-stream 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 free-stream 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 post-shock flow would be associated with a detached shock
and the flow field would not match the assumed conical arrangement.
5. State-to-state processes (ideal gas)
If the calorically-perfect ideal gas model is sufficient for your analysis needs,
there is simple set of ideal-gas 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 gdtk.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 gas-calc
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, quasi-one-dimensional 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 free-stream flow.
The value will have the same units as input p1
.
5.3. Flow with heat addition.
One-dimensional flow with heat addition is also known as
Rayleigh-line 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 Prandtl-Meyer function value, in radians.
# Python
igf.PM2(nu, g=1.4)
-- Lua
idealgasflow.PM2(nu, g)
Input:
nu
-
Float, no default. Prandtl-Meyer 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.0e-6)
-- 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 normal-velocity 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 flow-speed 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. Taylor-Maccoll cone flow
Compute the cone-surface angle and conditions given the shock wave angle.
The computation starts with the oblique-shock 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 cone-surface speed of gas, in m/s
p_c
-
the cone-surface pressure, in Pa
T_c
-
the cone-surface 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 free-stream 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 free-stream flow direction.