Pyrrhenius Quickstart

Basic Usage

The basic workflow of using pyrrhenius is structured like so:

  1. Import necessary modules

import pyrrhenius.database as phsd
  1. Create a pyrrhenius database object

ecdatabase = phsd.Database()

3. Create a pyrrhenius.model.Model object corresponding to the desired model_id. In this case the model id corresponding to the SEO3 model of olivine (insert citation) is loaded

model = ecdatabase.get_model('SEO3_ol')
  1. Call the get_conductivity(*args,**kwargs) method on the model with the relevant parameters.

conductivity = model.get_conductivity(T=1000, P=1.0, logfo2=10**-11)
print('*'*20)
print('Calculated conductivity (S/m) at T=1000 K, P=1 GPa,and fO2=10^-11 bars:')
print(conductivity)
********************
Calculated conductivity (S/m) at T=1000 K, P=1 GPa,and fO2=10^-11 bars:
2.7380861532827377e-05

Keywords can be of type float or numpy.ndarray’s. The latter functionality is especially useful for computing conductivities across a vectorized grid. In this case, using meshgrid on a dummy variable (zz) and a temperature array T creates a temperature array of size (10x10).

import numpy as np

T = np.linspace(500,1500,num=11)
z = np.arange(0,11,1) # dummy variable for demonstration purposes only
tt, xx = np.meshgrid(T,z)
print(tt.shape)
tt
(11, 11)
array([[ 500.,  600.,  700., ..., 1300., 1400., 1500.],
       [ 500.,  600.,  700., ..., 1300., 1400., 1500.],
       [ 500.,  600.,  700., ..., 1300., 1400., 1500.],
       ...,
       [ 500.,  600.,  700., ..., 1300., 1400., 1500.],
       [ 500.,  600.,  700., ..., 1300., 1400., 1500.],
       [ 500.,  600.,  700., ..., 1300., 1400., 1500.]])

As long as the input keyword-arguments are directly broadcastable, pyrrhenius can use mixed float and numpy.ndarray objects, vectorizing them as needed.

model.get_conductivity(T=tt, P=1.0, logfo2=10**-11)
array([[1.06820389e-10, 6.71262242e-09, 1.29536636e-07, ...,
        5.52272174e-04, 1.26077070e-03, 2.93431687e-03],
       [1.06820389e-10, 6.71262242e-09, 1.29536636e-07, ...,
        5.52272174e-04, 1.26077070e-03, 2.93431687e-03],
       [1.06820389e-10, 6.71262242e-09, 1.29536636e-07, ...,
        5.52272174e-04, 1.26077070e-03, 2.93431687e-03],
       ...,
       [1.06820389e-10, 6.71262242e-09, 1.29536636e-07, ...,
        5.52272174e-04, 1.26077070e-03, 2.93431687e-03],
       [1.06820389e-10, 6.71262242e-09, 1.29536636e-07, ...,
        5.52272174e-04, 1.26077070e-03, 2.93431687e-03],
       [1.06820389e-10, 6.71262242e-09, 1.29536636e-07, ...,
        5.52272174e-04, 1.26077070e-03, 2.93431687e-03]])

Accessing Database Options

Pyrrhenius currently ships with a .csv database which is loaded by default.

import pyrrhenius.database as phsd

ecdatabase = phsd.Database()

Once the database object has been created, you can use the get_phases(), get_model_list_for_phase(), and the get_model() methods to specify which model to load.

ecdatabase.get_phases()
['basalt',
 'basaltic melt',
 'brine',
 'clinopyroxene',
 'gabbro',
 'garnet',
 'granite',
 'granulite',
 'olivine',
 'omphacite',
 'orthopyroxene',
 'peridotite',
 'pervoskite',
 'phlogopite',
 'plagioclase',
 'schist',
 'wadsleyite',
 'silicate melt']
ecdatabase.get_model_list_for_phase('granite')
['ks_83_granite',
 'han_23_HD_granite',
 'han_23_QD_low_granite',
 'han_23_QD_high_granite',
 'han_23_QP_low_granite',
 'han_23_QP_high_granite']
ecmodel = ecdatabase.get_model('han_23_HD_granite')
ecmodel
han_23_HD_granite:{9.906(nan) exp( -1.22(0.063)/kT)}

Isotropic Models

The default database comes with a number of anisotropic models, visible as model_id’s with “[xxx]” strings appended to the end. To get an isotropic model, first tell the database to generate isotropic models via create_isotropic_models(), then examine the available models

before_isotropic_calculation = ecdatabase.get_model_list_for_phase('plagioclase')
ecdatabase.create_isotropic_models()
after_isotropic_calculation = ecdatabase.get_model_list_for_phase('plagioclase')
print('*'*20)
print('Before Isotropic Calculation')
print('*'*20)
print(*before_isotropic_calculation,sep='\n')
print('*'*20)
print('After Isotropic Calculation')
print('*'*20)
print(*after_isotropic_calculation,sep='\n')
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
withers (2012) withers (2012)
ppm ppm
nan nan
withers (2012) withers (2012)
ppm ppm
nan nan
withers (2012) withers (2012)
ppm ppm
nan nan
withers (2012) withers (2012)
ppm ppm
nan nan
withers (2012) withers (2012)
ppm ppm
nan nan
withers (2012) withers (2012)
ppm ppm
nan nan
withers (2012) withers (2012)
ppm ppm
nan nan
withers (2012) withers (2012)
ppm ppm
nan nan
withers (2012) withers (2012)
ppm ppm
nan nan
withers (2012) withers (2012)
ppm ppm
nan nan
withers (2012) withers (2012)
ppm ppm
nan nan
withers (2012) withers (2012)
ppm ppm
nan nan
withers (2012) withers (2012)
ppm ppm
nan nan
withers (2012) withers (2012)
ppm ppm
nan nan
withers (2012) withers (2012)
ppm ppm
nan nan
withers (2012) withers (2012)
ppm ppm
nan nan
withers (2012) withers (2012)
ppm ppm
nan nan
withers (2012) withers (2012)
ppm ppm
nan nan
withers (2012) withers (2012)
ppm ppm
nan nan
withers (2012) withers (2012)
ppm ppm
nan nan
withers (2012) withers (2012)
ppm ppm
nan nan
withers (2012) withers (2012)
ppm ppm
nan nan
withers (2012) withers (2012)
ppm ppm
nan nan
withers (2012) withers (2012)
ppm ppm
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
bell (2003) bell (2003)
ppm ppm
nan nan
bell (2003) bell (2003)
ppm ppm
nan nan
bell (2003) bell (2003)
ppm ppm
nan nan
bell (2003) bell (2003)
ppm ppm
nan nan
bell (2003) bell (2003)
ppm ppm
nan nan
bell (2003) bell (2003)
ppm ppm
nan nan
paterson (1982) paterson (1982)
wtpct wtpct
nan nan
paterson (1982) paterson (1982)
wtpct wtpct
nan nan
paterson (1982) paterson (1982)
wtpct wtpct
nan nan
paterson (1982) paterson (1982)
wtpct wtpct
nan nan
paterson (1982) paterson (1982)
wtpct wtpct
nan nan
paterson (1982) paterson (1982)
wtpct wtpct
nan nan
paterson (1982) paterson (1982)
ppm ppm
nan nan
paterson (1982) paterson (1982)
ppm ppm
nan nan
paterson (1982) paterson (1982)
ppm ppm
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
Libowitzky and rossman (1996) Libowitzky and rossman (1996)
wtpct wtpct
nan nan
Libowitzky and rossman (1996) Libowitzky and rossman (1996)
wtpct wtpct
nan nan
Libowitzky and rossman (1996) Libowitzky and rossman (1996)
wtpct wtpct
nan nan
Libowitzky and rossman (1996) Libowitzky and rossman (1996)
wtpct wtpct
nan nan
Libowitzky and rossman (1996) Libowitzky and rossman (1996)
wtpct wtpct
nan nan
Libowitzky and rossman (1996) Libowitzky and rossman (1996)
wtpct wtpct
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
nan nan
bell (1995) bell (1995)
ppm ppm
nan nan
bell (1995) bell (1995)
ppm ppm
nan nan
bell (1995) bell (1995)
ppm ppm
nan nan
bell (1995) bell (1995)
ppm ppm
nan nan
bell (1995) bell (1995)
ppm ppm
nan nan
bell (1995) bell (1995)
ppm ppm
nan nan
bell (2003) bell (2003)
ppm ppm
nan nan
bell (2003) bell (2003)
ppm ppm
nan nan
bell (2003) bell (2003)
ppm ppm
nan nan
bell (2003) bell (2003)
ppm ppm
nan nan
bell (2003) bell (2003)
ppm ppm
nan nan
bell (2003) bell (2003)
ppm ppm
nan nan
Johnson and Rossman (2003) Johnson and Rossman (2003)
ppm ppm
nan nan
Johnson and Rossman (2003) Johnson and Rossman (2003)
ppm ppm
nan nan
Johnson and Rossman (2003) Johnson and Rossman (2003)
ppm ppm
nan nan
Johnson and Rossman (2003) Johnson and Rossman (2003)
ppm ppm
nan nan
Johnson and Rossman (2003) Johnson and Rossman (2003)
ppm ppm
nan nan
Johnson and Rossman (2003) Johnson and Rossman (2003)
ppm ppm
nan nan
********************
Before Isotropic Calculation
********************
yang_11a_plag
yang_12b_plag[100]
yang_12b_plag[010]
yang_12b_plag[001]
Li_18_dry_plag
Li_18_wet_plag
********************
After Isotropic Calculation
********************
yang_11a_plag
yang_12b_plag[100]
yang_12b_plag[010]
yang_12b_plag[001]
Li_18_dry_plag
Li_18_wet_plag
isotropic_model:yang_12b_plag[100]+yang_12b_plag[010]+yang_12b_plag[001]

You should see that calling create_isotropic_models() on the database procedurally creates new model_id’s where multiple crystal directions are present for the same base id. These procedurally generated new models are identified by a prepended isotropic: string. They can now be accessed in the same way as default models

ecmodel = ecdatabase.get_model('isotropic_model:yang_12b_plag[100]+yang_12b_plag[010]+yang_12b_plag[001]')
conductivity = ecmodel.get_conductivity(T=1000, P=1.0)
conductivity
array([0.00061567])

Mixing Models

Pyrrhenius provides several N phase mixing models which are accessed via the mixing module. Since the interfaces for these mixing models can be different, consult the documentation prior to using them.

import pyrrhenius.mixing as pyhmix

brine_id = 'Li_18_1%plg_brine'
plag_id = 'isotropic_model:yang_12b_plag[100]+yang_12b_plag[010]+yang_12b_plag[001]'

brine_model = ecdatabase.get_model(brine_id)
plag_model  = ecdatabase.get_model(plag_id)
phase_fractions=[0.05,0.95]

# The HashinStrikman mixing model needs to be initialized with a matrix and inclusion ecmodel
hashinshtrikman_matrix = pyhmix.HashinStrickmanBound([brine_model,plag_model])

# The Geometric Average model requires intitialization with a phase and phase fraction list.
geometric_mixed_matrix = pyhmix.GeomAverage([brine_model,plag_model])

# Only the HS model in this example requires a provided phase fraction (0.05), positional argument.
hs_conductivity = hashinshtrikman_matrix.get_conductivity(phase_fractions,T=1000)
gm_conductivity = geometric_mixed_matrix.get_conductivity(phase_fractions,T=1000)

# Also calculate endmember phase conductivities for comparison
plagioclase_conductivity = plag_model.get_conductivity(T=1000)
brine_conductivity        = brine_model.get_conductivity(T=1000)

print(f'HS: {hs_conductivity} GM:{gm_conductivity}')
print(f'Plag: {plagioclase_conductivity} Brine:{brine_conductivity}')
HS: [0.01280826] GM:[0.00084664]
Plag: [0.00061567] Brine:[0.36]

Metadata Access

Most pyrrhenius objects come equipped with a metadata object which describes the source publication, experimental conditions, and calibration settings used to create the model

plag_model.metadata
isotropic_model:yang_12b_plag[100]+yang_12b_plag[010]+yang_12b_plag[001]
:title:None
	author:Xiaozhi Yang+Xiaozhi Yang+Xiaozhi Yang
	year:None
	doi:None
	phase_type:plagioclase
	description:None
	sample_type:None
	equation_form:None
	publication_id:Yang2012+Yang2012+Yang2012
	complete_or_partial_fit:None
	composite_or_single:None
	pressure_average:0.1
	pressure_min:None
	pressure_max:None
	temp_min:473.15
	temp_max:1073.15
	nacl_min:None
	nacl_max:None
	nacl_average:None
	na2o_min:None
	na2o_max:None
	na2o_average:None
	sio2_min:None
	sio2_max:None
	sio2_average:None
	co2_min:None
	co2_max:None
	co2_average:None
	water_min:95.0
	water_max:110.0
	water_average:102.5
	water_calibration:Johnson and Rossman (2003)
	water_units:ppm
	iron_min:None
	iron_max:None
	iron_average:None
	iron_units:nan
	crystal_direction:isotropic
	equation:mixture of:yang_12b_plag[100]*yang_12b_plag[010]*yang_12b_plag[001]
	ec_model:mixture of:yang_12b_plag[100]*yang_12b_plag[010]*yang_12b_plag[001]

metadata objects can be used by the parent model to produce input data representative of the experimental conditions

plag_model.generate_representative_conditions()
{'T': array([ 473.15, 1073.15])}

you can use the output from generate_representative_conditions() to construct your own input arrays, or directly evaluate the condition dictionary within the model itself

condition_dict = plag_model.generate_representative_conditions()
plag_model.get_conductivity(**condition_dict)
array([4.40250906e-11, 1.68569100e-03])

Plotting Utilities

Since most experimental petrologists conduct their parameter fitting in \(\log_{10}(\sigma), \frac{1}{T}\) space, pyrrhenius provides a convenience plotting method to format a matplotlib.Axis for a similar plotting space

import matplotlib.pyplot as plt
import numpy as np
import pyrrhenius.mixing as pyhmix
import pyrrhenius.database as phsd
import pyrrhenius.utils as pyhutils

ecdatabase = phsd.Database()

# endmember models
brine_id = 'Li_18_1%plg_brine'
plag_id = 'Li_18_wet_plag'

brine_model = ecdatabase.get_model(brine_id)
plag_model  = ecdatabase.get_model(plag_id)

# The HashinStrikman mixing model needs to be initialized with a matrix and inclusion ecmodel
hashinshtrikman_matrix = pyhmix.HashinStrickmanBound([brine_model,plag_model])

# provide a range of temperature conditions at which to evaluate the models
T = np.linspace(400,1200,num=120)

# Only the HS model in this example requires a provided phase fraction (0.05), positional argument.
hs_5pct = hashinshtrikman_matrix.get_conductivity(0.05,T=T)
hs_1pct = hashinshtrikman_matrix.get_conductivity(0.01,T=T)

# Also calculate endmember phase conductivities for comparison
plagioclase_conductivity = plag_model.get_conductivity(T=T)
brine_conductivity        = brine_model.get_conductivity(T=T)

# set up matplotlib plotting

fig, ax = plt.subplots()
linear_major_ticks = np.asarray([2000,1400,1100,900,800,700,600,500,400])
pyhutils.format_ax_arrhenian_space(ax,linear_major_ticks=linear_major_ticks)

ax.plot(1e4/T,plagioclase_conductivity,color='purple',label='Li et al., (2018) Plagioclase')
ax.plot(1e4/T,brine_conductivity,color='orange',label='Li et al., (2018) 1% NaCl Plagioclase-Equilibrated Brine')
ax.plot(1e4/T,hs_1pct,color='blue',label='Li et al., (2018) 1% NaCl, 1% Vol Plagioclase-Equilibrated Brine',linestyle=':')
ax.plot(1e4/T,hs_5pct,color='blue',label='Li et al., (2018) 1% NaCl, 5% Vol Plagioclase-Equilibrated Brine',linestyle='--')
ax.set_title('A Plagioclase, Brine, and two HS mixed Plag-Brine Models')
ax.legend()
fig.show()
_images/quickstart_17_1.png