PyEospac: exemples of use

In [1]:
import eospac as eos
import numpy as np

I. Avalable Tables, Information and Options

are automatically generated from eos_Interface.h at install time

In [2]:
print eos.tables.keys()
['T_DUt', 'T_Als', 'Uic_DSic', 'Siz_DAiz', 'St_DPt', 'Sic_DUic', 'Pic_DSic', 'Uls_T', 'Uv_Av', 'T_DUe', 'Zfc_DT', 'Dv_Uv', 'Pe_DAe', 'Am_Pm', 'Uv_Pv', 'Dls_Als', 'Uls_Uv', 'Piz_DT', 'Kr_DT', 'Als_Av', 'Am_D', 'Dv_T', 'Aic_DPic', 'Aic_DT', 'Gs_D', 'Tf_Pf', 'Zfo_DT', 'Dv_Dls', 'Dv_Uls', 'Af_D', 'Kp_DT', 'T_Av', 'Uf_Af', 'Ae_DT', 'T_Pv', 'Tm_Um', 'Pf_Af', 'Dv_Als', 'Pv_Uls', 'T_DPic', 'Um_Pm', 'Sic_DAic', 'Af_Uf', 'Ktc_DT', 'Tf_Af', 'Ae_DUe', 'T_DPiz', 'T_DAic', 'Um_D', 'Kc_DT', 'B_DT', 'Uic_DT', 'T_DSiz', 'Kec_DT', 'Sic_DPic', 'T_Uv', 'D_Am', 'Uls_Pv', 'T_DSt', 'Tf_Uf', 'Tm_Pm', 'Am_Um', 'Pv_Dv', 'T_DSe', 'Se_DPe', 'Uiz_DPiz', 'Af_Pf', 'Pv_Uv', 'Av_T', 'Piz_DAiz', 'Pm_Tm', 'D_Tm', 'At_DT', 'At_DUt', 'Pv_Dls', 'Aiz_DSiz', 'Dls_Uls', 'Info', 'D_Tf', 'Av_Pv', 'Dls_Uv', 'Siz_DT', 'Siz_DUiz', 'T_Dls', 'Als_Pv', 'Piz_DUiz', 'T_DUic', 'Dls_Dv', 'Aic_DUic', 'Pf_D', 'Uf_Tf', 'Pt_DSt', 'Uiz_DAiz', 'Comment', 'T_Uls', 'D_Uf', 'Se_DAe', 'Ut_DT', 'D_Um', 'Als_Dv', 'Uls_Av', 'Am_Tm', 'Uf_D', 'St_DAt', 'Als_T', 'Av_Dls', 'Uv_Uls', 'Pic_DT', 'Dv_Av', 'Pe_DUe', 'Av_Uls', 'Pt_DAt', 'Dls_Pv', 'Uiz_DSiz', 'Uv_T', 'Als_Uv', 'Uls_Dls', 'T_DAt', 'Uic_DAic', 'Ae_DPe', 'Uv_Dls', 'T_DAe', 'Tf_D', 'At_DSt', 'Pic_DAic', 'Ut_DSt', 'Ogb', 'Siz_DPiz', 'Tm_D', 'Uls_Als', 'Ut_DPt', 'D_Gs', 'Ue_DAe', 'M_DT', 'T_DAiz', 'Aiz_DT', 'Pm_Am', 'Um_Tm', 'T_DUiz', 'Pf_Tf', 'Uv_Dv', 'Pv_Als', 'Als_Dls', 'Ue_DT', 'T_Dv', 'Pv_T', 'Uv_Als', 'D_PtT', 'Ue_DSe', 'Um_Am', 'Av_Uv', 'Pm_Um', 'Uic_DPic', 'Pm_D', 'T_DSic', 'Aic_DSic', 'Keo_DT', 'Dls_T', 'T_DPe', 'Uf_Pf', 'Dls_Av', 'Als_Uls', 'Af_Tf', 'Pc_D', 'T_DPt', 'Pe_DSe', 'Av_Als', 'Aiz_DUiz', 'Pe_DT', 'Se_DT', 'Pv_Av', 'St_DUt', 'Ut_DAt', 'Uls_Dv', 'Uc_D', 'D_Af', 'Ut_PtT', 'Se_DUe', 'D_Pm', 'Tm_Am', 'NullTable', 'St_DT', 'D_Pf', 'Pic_DUic', 'Pf_Uf', 'Aiz_DPiz', 'Piz_DSiz', 'Pt_DT', 'Ae_DSe', 'Sic_DT', 'Uiz_DT', 'V_PtT', 'At_DPt', 'Pt_DUt', 'Dv_Pv', 'Ue_DPe', 'Ac_D', 'Av_Dv']

In [3]:
print eos.info.keys()
['Rmin', 'Exchange_Coeff', 'Cmnt_Len', 'R_Array', 'F_Convert_Factor', 'NUM_PHASES', 'dFy_Species_Data', 'T401', 'Material_ID', 'T_Array', 'F_Array', 'Modulus', 'EL401', 'Tmin', 'Fmax', 'Mean_Atomic_Num', 'Rmax', 'NR', 'RG401', 'AG401', 'Log_Val', 'P401', 'nXYPairs', 'AL401', 'Mean_Atomic_Mass', 'X_Species_Data', 'Table_Type', 'Tmax', 'dFx_Species_Data', 'RL401', 'F_Species_Data', 'X_Convert_Factor', 'Fmin', 'Y_Convert_Factor', 'EG401', 'NT', 'Y_Species_Data', 'NT401', 'Normal_Density']

In [4]:
print eos.options.keys()
['insert_data', 'use_custom_interp', 'split_forced', 'linear', 'calc_free_energy', 'check_args', 'monotonic_in_x', 'monotonic_in_y', 'use_maxwell_table', 'create_tzero', 'f_convert', 'save_species_data', 'split_ideal_gas', 'adjust_vap_pres', 'pt_smoothing', 'smooth', 'y_convert', 'x_convert', 'rational', 'dump_data', 'split_num_prop', 'use_taylor_fit', 'append_data', 'split_cowan']

II. Single material interpolations

In [5]:
# Load some tables for the material no 3720 (Aluminium)
# options keys accepts regular expressions. For instance
#    - '.*' would match any table
#    - '[PU]t_DT' matches 'Pt_DT', 'Ut_DT'
#    - etc..
mat = eos.EosMaterial(3720, ['Pt_DT', 'Ut_DT','St_DT', 'Pt_DSt'],
                      options={'.*': {'create_tzero': True},
                               '[PU]t_DT': {'x_convert': 1.0},
                               'St_DT': {'linear': True},
                                })

# see what options are applied
for table_name in mat.tables:
    print table_name, mat.get_table(table_name).options
Pt_DSt {'create_tzero': True}
Ut_DT {'x_convert': 1.0, 'create_tzero': True}
St_DT {'linear': True, 'create_tzero': True}
Pt_DT {'x_convert': 1.0, 'create_tzero': True}

In [6]:
# Separate tables can be accessed as parameters of the 'mat' object for instance 'm.Pt_DT'
# this is a shortcut from m.get_table('Pt_DT')
# Info values can be acessed as attributes of the EosMaterial class
print mat.Pt_DT['Normal_Density'], mat.Pt_DT['Mean_Atomic_Num']
2.7 13.0

In [7]:
# The list of all avalables info parameters for a given table can be obtained with
print mat.Pt_DT
================================================================================
                              Table summary: Pt_DT
================================================================================

Parameters
---------------
Rmin                 : 0.0
Exchange_Coeff       : 0.0
R_Array              : [  0.000e+00   2.700e-06 ...,   2.700e+04   5.400e+04]
F_Convert_Factor     : 1.0
Material_ID          : 3720
T_Array              : [  0.000e+00   7.253e+01 ...,   5.802e+08   1.160e+09]
F_Array              : [[  0.000e+00   0.000e+00 ...,   0.000e+00   0.000e+00]
 [ -1.238e-07  -6.345e-08 ...,   6.759e+00   1.352e+01]
 ..., 
 [  6.197e+09   6.197e+09 ...,   6.799e+10   1.352e+11]
 [  2.033e+10   2.033e+10 ...,   1.381e+11   2.718e+11]]
Modulus              : 0.0
Tmin                 : 0.0
Fmax                 : 2.71796080807e+11
Mean_Atomic_Num      : 13.0
Rmax                 : 54000.0
NR                   : 111
Log_Val              : 0.0
nXYPairs             : 0.0
Mean_Atomic_Mass     : 26.9815
Table_Type           : 3
Tmax                 : 1160485000.0
X_Convert_Factor     : 1.0
Fmin                 : -6.73824766288
Y_Convert_Factor     : 1.0
NT                   : 78
Normal_Density       : 2.7

Options
---------------
x_convert            : 1.0
create_tzero         : True
================================================================================

In [8]:
X = np.array([0.1, 0.2, 0.3]) # density array in g.cm⁻³
Y = np.array([1e5, 1e6, 1e8]) # temperature array in K
# interpolates the total pressure at given X,Y points
# X,Y could be arrrays of any dimension
print 'F', mat.Pt_DT(X,Y)

# ∂F/∂x  first order derivative as returned by EOSPAC6 (same thing for dFy)
print 'dFx', mat.Pt_DT.dFx(X,Y)

# ∂²F/∂x² second order derivative (finite differences over EOSPAC's first derivative)
print 'dFxx', mat.Pt_DT.dFxx(X,Y)

# ∂²F/∂x∂y second order derivative 
print 'dFxy', mat.Pt_DT.dFxy(X,Y)
print 'dFyx', mat.Pt_DT.dFyx(X,Y)
# checking that F is C² : ||dFxy - dFyx|| << 1
print 'max(dFxy - dFxy)', np.abs(mat.Pt_DT.dFxy(X,Y) - mat.Pt_DT.dFyx(X,Y)).max()
F [  8.937e+00   5.388e+02   1.292e+05]
dFx [  8.327e+01   2.489e+03   4.300e+05]
dFxx [ -23.119 -865.32   -96.02 ]
dFxy [ 0.001  0.004  0.004]
dFyx [ 0.001  0.004  0.004]
max(dFxy - dFxy) 1.75027344614e-09

III. Mixtures

In [9]:
# The EosMixture class allows to manipulate multiple matierial with a similar interface to EosMaterial's one
# The following loads tables Pt_DT, Ut_DT, St_DT and Pt_DSt for materials 3720 and 7593 using regular expressions.
# The setup options are very similar to EosMaterial class. An additional possibility is to provide a tuple as key
# in order to specify the material the option should be applied to, otherwise the corresponding option will be applyed
# to all materials
mix = eos.EosMixture([3720, 7593], ['[PUS]t_DT', 'Pt_DSt'],
                      options={'.*': {'create_tzero': True},
                               '[PU]t_DT': {'x_convert': 1.0},
                               (7593, 'St_DT'): {'linear': False},
                                })
print 'Loaded tables:', mix.tables
Loaded tables: ['Pt_DSt', 'Ut_DT', 'St_DT', 'Pt_DT']

In [10]:
# It is possible access to different loaded materials separately 
print "object:", mix.m3720

# See previous section to all possibilities of EosMaterial class. For instance:
print 'interpolating :', mix.m3720.Pt_DT(X,Y) 
object: <eospac.interface.EosMaterial instance at 0x35d9a28>
interpolating : [  8.937e+00   5.388e+02   1.292e+05]

In [11]:
# Multi-material properties can be accessed by specifying the table name as attribute. For instance:
print mix.Pt_DT['Material_ID']
print mix.Pt_DT['Normal_Density']
[3720 7593]
[ 2.7    1.044]

In [12]:
# Assuming that X, Y used in interpolations are of shape (N1,N2,N3, etc..)
# the shape of the fraction array used by eos_Mix should be (number_of_materials, N1, N2, N3, etc..)
# Let's make a 25/75 mixture of materials 7320 and 7593
frac = np.zeros((2,) + X.shape)
frac[0] = 0.25
frac[1] = 1 - frac[0]
print 'frac.shape', frac.shape
print 'X.shape', X.shape
frac.shape (2, 3)
X.shape (3,)

In [13]:
# the interpolation within mixture is then done as follows:

print 'F', mix.Pt_DT(X,Y, frac)
print 'dFx', mix.Pt_DT.dFx(X,Y, frac)
F [  1.691e+01   7.348e+02   1.469e+05]
dFx [  1.616e+02   3.492e+03   4.892e+05]

IV. Derived quantities

A mecanism to access derived quanties is provided (inspired from yt toolkit). Most of the quantities described in EOSPAC's manual and a few additional ones are implemented.

In [14]:
# see eospac/quantities.py for more details
print eos.derived_quantities
List of derived quantities
------------------------------
   * Gamma           : t e ic : Gruneisen Coefficient
   * beta_s          : t e ic : Isentropic bulk modulus
   * G3              : t e ic : Fundemental derivative:
        $\textrm{C} = 1 + \frac{1}{2}\frac{1}{\gamma_s P V^2}\left.\frac{\partial^2 P}{\partial \rho^2}\right|_S$
   * beta_t          : t e ic : Isothermal bulk modulus
   * Ct2             : t e ic : Isothermal sound speed square
   * Cs2_check       : t      : Isentropic sound speed square: alternative method.
   * gruneisen_coef  : t e ic : Gruneisen Coefficient
   * Ks              : t e ic : Isentropic compressibility
   * g               : t e ic : Dimensionless specific heat:
        $\textrm{g} = \frac{P V}{C_V T}$
   * game            : t e ic : Polytropic index: $P= (\gamma_e - 1) E \rho $
   * gamc_t          : t e ic : Isothermal exponent:
        $\gamma_T = \frac{\rho}{P}\left.\frac{\partial P}{\partial \rho}\right|_T$
    
   * alpha_exp       : t e ic : Thermal expansion coefficient
   * Kt              : t e ic : Isothermal compressibility
   * gamc_s          : t e ic : Adiabatic exponent:
        $\gamma_S = \frac{\rho}{P}\left.\frac{\partial P}{\partial \rho}\right|_S$
   * therm_consistency : t e ic : Thermodynamic consistency: relative error
   * Cp              : t e ic : Constant pressure specific heat
   * gamc_s_bad      : t e ic : Adiabatic exponent
   * Cv              : t e ic : Constant volume specific heat
   * alpha_exp_check : t      : Thermal expansion coefficient: alternative method
       $\alpha_exp = \frac{1}{V} \left.\frac{\partial V}{\partial T}\right|_P$
    
   * Cs2             : t e ic : Isentropic sound speed square

In [15]:
# If a derived quantity is given to EosMaterial (or EosMixture), all the required tables to 
# compute the corresponding quantity will be pulled automatically
mat = eos.EosMaterial(3720, ['Pt_DT', 'gamc_s','gamc_t', 'Cp'], spec=['t', 'ic'])
print 'mat.tables', mat.tables
print 'Cp dependencies:', eos.derived_quantities['Cp']['dependencies']
print 'Cp required tables:', eos.derived_quantities.get_dependencies('Cp', spec=['t'])
mat.tables ['Pic_DT', 'Uic_DT', 'Pt_DT', 'Ut_DT', 'Sic_DT', 'St_DT', 'Pic_DSic', 'Pt_DSt']
Cp dependencies: ['Cs2', 'Cv', 'Ct2']
Cp required tables: ['Pt_DT', 'Ut_DT', 'St_DT', 'Pt_DSt']

In [16]:
# Now we can acess for instance the gamc_t quantity in a similar way to a table
print 'gamc_t total', mat.q['gamc_t','t'](X,Y)
print 'gamc_t ion+cc', mat.q['gamc_t','ic'](X,Y)

# The derived quantities work with mixtures as well:
print 'gamc_t mixture total', mix.q['gamc_t','t'](X,Y, frac)
gamc_t total [ 0.932  0.924  0.999]
gamc_t ion+cc [ 0.985  0.998  1.   ]
gamc_t mixture total [ 0.956  0.95   0.999]

In [17]:
# It is very easy to define new derived quantities
# Let's define a quantity gamc_t_v0 which actually does the same thing as gamc_t

@eos.add_quantity(name='gamc_t_v0', args='DT', dependencies=['Pt_DT'])
def gamma_isothermal_v0(tab, spec, rho, temp):
    r"""Isothermal gamma exponent"""
    P =  tab.Pt_DT(rho, temp)
    return rho*tab.Pt_DT.dFx(rho, temp)/P

print 'gamc_t_v0 total', mat.q['gamc_t_v0','t'](X,Y)
gamc_t_v0 total [ 0.932  0.924  0.999]

In [18]:
# The previous definition is rather intuitive, however it is restrictive as it will only 
# work for total tables and a single material.
# A more general definition allow to take into account different species (total, electron, ion+cc, etc)
# as well as multi-material setups.
# In this case 'P{s}_DT' will be expanded to 'Pt_DT','Pe_DT', etc, according to the value of spec.
# spec could be 't', 'e', 'ie', etc..
# *XYf is a tuple containing:
#   - (X,Y) if applied to EosMaterial
#   - (X, Y, frac) if applied to EosMixture


@eos.add_quantity(name='gamc_t_v1', args='DT', dependencies=['P{s}_DT'])
def gamma_isothermal_v1(tab, spec, *XYf):
    r"""Isothermal gamma exponent """
    rho = XYf[0]
    P =  tab.get_table('P{s}_DT', spec)(*XYf)
    return rho*tab.get_table('P{s}_DT', spec).dFx(*XYf)/P

print 'gamc_t_v1 total', mat.q['gamc_t_v1','t'](X,Y)
print 'gamc_t_v1 mixture total', mix.q['gamc_t_v1','t'](X,Y, frac)
gamc_t_v1 total [ 0.932  0.924  0.999]
gamc_t_v1 mixture total [ 0.956  0.95   0.999]

V. Data visualization

a few examples of how to plot EoS data with matplotlib

In [19]:
rc= plt.rcParams
rc['figure.figsize'] = (12, 8)
rc['figure.dpi'] = 300
rc['font.size'] = 20
In [20]:
mat = eos.EosMaterial(3720, ['Pt_DT', 'Ut_DT','gamc_s', 'therm_consistency'], spec=['t'])
In [21]:
eos.eos_plot(mat, 'Pt_DT', ax=plt.subplot(111))
Out[21]:
<matplotlib.axes.AxesSubplot at 0x35d3790>
In [22]:
# the white contour corresponds to γ_T = 1
eos.eos_plot(mat, 'gamc_t', ax=plt.subplot(111))
/mnt/perso/src/pyeospac/eospac/quantities.py:189: RuntimeWarning: invalid value encountered in divide
  return rho*tab.get_table('P{s}_DT', spec).dFx(*XYf_DT)/P

Out[22]:
<matplotlib.axes.AxesSubplot at 0x3661e50>
In [23]:
# Checking that dE =  TdS - PdV
eos.eos_plot(mat, 'therm_consistency', ax=plt.subplot(111), vmax=1.0)
/mnt/perso/src/pyeospac/eospac/quantities.py:229: RuntimeWarning: divide by zero encountered in divide
  err1  = np.abs((dE_S - T))/T
/mnt/perso/src/pyeospac/eospac/quantities.py:232: RuntimeWarning: invalid value encountered in divide
  err2 = np.abs(dE_V - P)/np.abs(P)

Out[23]:
<matplotlib.axes.AxesSubplot at 0x430b510>