Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added the Vinet EOS #158

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Binary file added burnman/data/input_figures/Ahmad.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added burnman/data/input_figures/Dewaele.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 2 additions & 0 deletions burnman/eos/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
from .modified_tait import MT
from .hp import HP_TMT
from .cork import CORK
from .vinet import Vinet
from .birch_murnaghan_4th import BM4

from .property_modifiers import calculate_property_modifications

Expand Down
18 changes: 9 additions & 9 deletions burnman/eos/birch_murnaghan.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def birch_murnaghan(x, params):
"""

return 3.*params['K_0']/2. * (pow(x, 7./3.) - pow(x, 5./3.)) \
* (1 - .75*(4-params['Kprime_0'] )*(pow(x, 2./3.) - 1)) + params['P_0']
* (1. - .75*(4.-params['Kprime_0'] )*(pow(x, 2./3.) - 1.)) + params['P_0']


def volume(pressure, params):
Expand Down Expand Up @@ -68,14 +68,14 @@ def shear_modulus_third_order(volume, params):

x = params['V_0']/volume
f = 0.5*(pow(x, 2./3.) - 1.0)
G = pow((1. + 2*f), 5./2.)*(params['G_0']+(3.*params['K_0']*params['Gprime_0'] - 5.*params['G_0'])*f + (6.*params['K_0']*params['Gprime_0']-24.*params['K_0']-14.*params['G_0']+9./2. * params['K_0']*params['Kprime_0'])*f*f)
G = pow((1. + 2.*f), 5./2.)*(params['G_0']+(3.*params['K_0']*params['Gprime_0'] - 5.*params['G_0'])*f + (6.*params['K_0']*params['Gprime_0']-24.*params['K_0']-14.*params['G_0']+9./2. * params['K_0']*params['Kprime_0'])*f*f)
return G


class BirchMurnaghanBase(eos.EquationOfState):
"""
Base class for the isothermal Birch Murnaghan equation of state. This is third order in strain, and
has no temperature dependence. However, the shear modulus is sometimes fit to a second order
has no temperature dependence. However, the shear modulus is sometimes fit to a second order
function, so if this is the case, you should use that. For more see :class:`burnman.birch_murnaghan.BM2` and :class:`burnman.birch_murnaghan.BM3`.
"""
def volume(self,pressure, temperature, params):
Expand All @@ -90,7 +90,7 @@ def pressure(self, temperature, volume, params):
def isothermal_bulk_modulus(self,pressure,temperature, volume, params):
"""
Returns isothermal bulk modulus :math:`K_T` :math:`[Pa]` as a function of pressure :math:`[Pa]`,
temperature :math:`[K]` and volume :math:`[m^3]`.
temperature :math:`[K]` and volume :math:`[m^3]`.
"""
return bulk_modulus(volume, params)

Expand Down Expand Up @@ -137,7 +137,7 @@ def validate_parameters(self, params):
"""
Check for existence and validity of the parameters
"""

if 'P_0' not in params:
params['P_0'] = 0.

Expand All @@ -148,13 +148,13 @@ def validate_parameters(self, params):
params['G_0'] = float('nan')
if 'Gprime_0' not in params:
params['Gprime_0'] = float('nan')

# Check that all the required keys are in the dictionary
expected_keys = ['V_0', 'K_0', 'Kprime_0', 'G_0', 'Gprime_0']
for k in expected_keys:
if k not in params:
raise KeyError('params object missing parameter : ' + k)

# Finally, check that the values are reasonable.
if params['P_0'] < 0.:
warnings.warn( 'Unusual value for P_0', stacklevel=2 )
Expand All @@ -173,7 +173,7 @@ def validate_parameters(self, params):

class BM3(BirchMurnaghanBase):
"""
Third order Birch Murnaghan isothermal equation of state.
Third order Birch Murnaghan isothermal equation of state.
This uses the third order expansion for shear modulus.
"""
def __init__(self):
Expand All @@ -182,7 +182,7 @@ def __init__(self):

class BM2(BirchMurnaghanBase):
"""
Third order Birch Murnaghan isothermal equation of state.
Third order Birch Murnaghan isothermal equation of state.
This uses the third order expansion for shear modulus.
"""
def __init__(self):
Expand Down
142 changes: 142 additions & 0 deletions burnman/eos/birch_murnaghan_4th.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
from __future__ import absolute_import
# This file is part of BurnMan - a thermoelastic and thermodynamic toolkit for the Earth and Planetary Sciences
# Copyright (C) 2012 - 2015 by the BurnMan team, released under the GNU GPL v2 or later.


import scipy.optimize as opt
from . import equation_of_state as eos
from ..tools import bracket
import warnings

def bulk_modulus_fourth(volume, params):
"""
compute the bulk modulus as per the fourth order
birch-murnaghan equation of state. Returns bulk
modulus in the same units as the reference bulk
modulus. Pressure must be in :math:`[Pa]`.
"""

x = params['V_0']/volume
f = 0.5*(pow(x, 2./3.) - 1.0)

Xi = (3./4.)*(4.-params['Kprime_0'])
Zeta = (3./8.)*((params['K_0']*params['Kprime_prime_0'])+params['Kprime_0']*(params['Kprime_0']-7.)+143./9.)

K = (5.*f*pow((1.+2.*f),5./2.)*params['K_0']*(1.-(2.*Xi*f)+(4.*Zeta*pow(f,2.)))) + \
(pow(1.+(2.*f),7./2.)*params['K_0']*(1.-(4.*Xi*f)+(12.*Zeta*pow(f,2.))))


return K

def volume_fourth_order(pressure,params):
func = lambda x: birch_murnaghan_fourth(params['V_0']/x, params) - pressure
try:
sol = bracket(func, params['V_0'], 1.e-2*params['V_0'])
except:
raise ValueError('Cannot find a volume, perhaps you are outside of the range of validity for the equation of state?')
return opt.brentq(func, sol[0], sol[1])

def birch_murnaghan_fourth(x, params):
"""
equation for the fourth order birch-murnaghan equation of state, returns
pressure in the same units that are supplied for the reference bulk
modulus (params['K_0'])
"""

f = 0.5*(pow(x, 2./3.) - 1.0)
Xi = (3./4.)*(4.-params['Kprime_0'])
Zeta = (3./8.)*((params['K_0']*params['Kprime_prime_0'])+params['Kprime_0']*(params['Kprime_0']-7.)+143./9.)

return 3.*f*pow(1.+2.*f,5./2.)*params['K_0']*(1.-(2.*Xi*f)+(4.*Zeta*pow(f,2.)))


class BM4(eos.EquationOfState):
"""
Base class for the isothermal Birch Murnaghan equation of state. This is fourth order in strain, and
has no temperature dependence.
"""
def volume(self,pressure, temperature, params):
"""
Returns volume :math:`[m^3]` as a function of pressure :math:`[Pa]`.
"""
return volume_fourth_order(pressure,params)


def pressure(self, temperature, volume, params):
return birch_murnaghan_fourth(volume/params['V_0'], params)


def isothermal_bulk_modulus(self,pressure,temperature, volume, params):
"""
Returns isothermal bulk modulus :math:`K_T` :math:`[Pa]` as a function of pressure :math:`[Pa]`,
temperature :math:`[K]` and volume :math:`[m^3]`.
"""
return bulk_modulus_fourth(volume,params)
def adiabatic_bulk_modulus(self,pressure, temperature, volume, params):
"""
Returns adiabatic bulk modulus :math:`K_s` of the mineral. :math:`[Pa]`.
"""
return bulk_modulus_fourth(volume,params)

def shear_modulus(self,pressure, temperature, volume, params):
"""
Returns shear modulus :math:`G` of the mineral. :math:`[Pa]`
"""
return 0.
def heat_capacity_v(self,pressure, temperature, volume, params):
"""
Since this equation of state does not contain temperature effects, simply return a very large number. :math:`[J/K/mol]`
"""
return 1.e99

def heat_capacity_p(self,pressure, temperature, volume, params):
"""
Since this equation of state does not contain temperature effects, simply return a very large number. :math:`[J/K/mol]`
"""
return 1.e99

def thermal_expansivity(self,pressure, temperature, volume, params):
"""
Since this equation of state does not contain temperature effects, simply return zero. :math:`[1/K]`
"""
return 0.

def grueneisen_parameter(self,pressure,temperature,volume,params):
"""
Since this equation of state does not contain temperature effects, simply return zero. :math:`[unitless]`
"""
return 0.

def validate_parameters(self, params):
"""
Check for existence and validity of the parameters
"""

if 'P_0' not in params:
params['P_0'] = 0.

# If G and Gprime are not included this is presumably deliberate,
# as we can model density and bulk modulus just fine without them,
# so just add them to the dictionary as nans
if 'G_0' not in params:
params['G_0'] = float('nan')
if 'Gprime_0' not in params:
params['Gprime_0'] = float('nan')

# Check that all the required keys are in the dictionary
expected_keys = ['V_0', 'K_0', 'Kprime_0']
for k in expected_keys:
if k not in params:
raise KeyError('params object missing parameter : ' + k)

# Finally, check that the values are reasonable.
if params['P_0'] < 0.:
warnings.warn( 'Unusual value for P_0', stacklevel=2 )
if params['V_0'] < 1.e-7 or params['V_0'] > 1.e-3:
warnings.warn( 'Unusual value for V_0', stacklevel=2 )
if params['K_0'] < 1.e9 or params['K_0'] > 1.e13:
warnings.warn( 'Unusual value for K_0' , stacklevel=2)
if params['Kprime_0'] < 0. or params['Kprime_0'] > 10.:
warnings.warn( 'Unusual value for Kprime_0', stacklevel=2 )
if params['Kprime_prime_0'] > 0. or params['Kprime_prime_0'] < -10.:
warnings.warn( 'Unusual value for Kprime_prime_0', stacklevel=2 )
6 changes: 6 additions & 0 deletions burnman/eos/helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
from . import slb
from . import mie_grueneisen_debye as mgd
from . import birch_murnaghan as bm
from . import birch_murnaghan_4th as bm4
from . import modified_tait as mt
from . import hp
from . import cork
from . import vinet
from .equation_of_state import EquationOfState


Expand All @@ -21,6 +23,8 @@ def create(method):
if isinstance(method, str):
if method == "slb2":
return slb.SLB2()
elif method == "vinet":
return vinet.Vinet()
elif method == "mgd2":
return mgd.MGD2()
elif method == "mgd3":
Expand All @@ -31,6 +35,8 @@ def create(method):
return bm.BM2()
elif method == "bm3":
return bm.BM3()
elif method == "bm4":
return bm4.BM4()
elif method == "mt":
return mt.MT()
elif method == "hp_tmt":
Expand Down
127 changes: 127 additions & 0 deletions burnman/eos/vinet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
# This file is part of BurnMan - a thermoelastic and thermodynamic toolkit for the Earth and Planetary Sciences
# Copyright (C) 2012 - 2015 by the BurnMan team, released under the GNU GPL v2 or later.


import scipy.optimize as opt
from . import equation_of_state as eos
import warnings
from math import exp

def bulk_modulus(volume, params):
"""
compute the bulk modulus as per the third order
Vinet equation of state. Returns bulk
modulus in the same units as the reference bulk
modulus. Pressure must be in :math:`[Pa]`.
"""

x = volume/params['V_0']
eta = (3./2.)*(params['Kprime_0']-1.)

K = (params['K_0']*pow(x,-2./3.))*(1+((eta*pow(x,1./3.)+1.)*(1.-pow(x,1./3.))))*exp(eta*(1.-pow(x,1./3.)))
return K

def vinet(x, params):
"""
equation for the third order Vinet equation of state, returns
pressure in the same units that are supplied for the reference bulk
modulus (params['K_0'])
"""
eta = (3./2.)*(params['Kprime_0']-1.)
return 3.*params['K_0'] * (pow(x, -2./3.))*(1.-(pow(x,1./3.))) \
* exp(eta*(1.-pow(x,1./3.)))

def volume(pressure, params):
"""
Get the Vinet volume at a reference temperature for a given
pressure :math:`[Pa]`. Returns molar volume in :math:`[m^3]`
"""

func = lambda x: vinet(x/params['V_0'], params) - pressure
V = opt.brentq(func, 0.1*params['V_0'], 1.5*params['V_0'])
return V

class Vinet(eos.EquationOfState):
"""
Base class for the isothermal Vinet equation of state. This is third order in strain, and
has no temperature dependence.
"""
def volume(self,pressure, temperature, params):
"""
Returns volume :math:`[m^3]` as a function of pressure :math:`[Pa]`.
"""
return volume(pressure,params)

def pressure(self, temperature, volume, params):
return vinet(volume/params['V_0'], params)

def isothermal_bulk_modulus(self,pressure,temperature, volume, params):
"""
Returns isothermal bulk modulus :math:`K_T` :math:`[Pa]` as a function of pressure :math:`[Pa]`,
temperature :math:`[K]` and volume :math:`[m^3]`.
"""
return bulk_modulus(volume, params)

def adiabatic_bulk_modulus(self,pressure, temperature, volume, params):
"""
Returns adiabatic bulk modulus :math:`K_s` of the mineral. :math:`[Pa]`.
"""
return bulk_modulus(volume,params)

def shear_modulus(self,pressure, temperature, volume, params):
"""
Returns shear modulus :math:`G` of the mineral. :math:`[Pa]`
Currently not included in the Vinet EOS, so omitted.
"""
return 0.

def heat_capacity_v(self,pressure, temperature, volume, params):
"""
Since this equation of state does not contain temperature effects, simply return a very large number. :math:`[J/K/mol]`
"""
return 1.e99

def heat_capacity_p(self,pressure, temperature, volume, params):
"""
Since this equation of state does not contain temperature effects, simply return a very large number. :math:`[J/K/mol]`
"""
return 1.e99

def thermal_expansivity(self,pressure, temperature, volume, params):
"""
Since this equation of state does not contain temperature effects, simply return zero. :math:`[1/K]`
"""
return 0.

def grueneisen_parameter(self,pressure,temperature,volume,params):
"""
Since this equation of state does not contain temperature effects, simply return zero. :math:`[unitless]`
"""
return 0.

def validate_parameters(self, params):
"""
Check for existence and validity of the parameters
"""

#G is not included in the Vinet EOS so we shall set them to NaN's
if 'G_0' not in params:
params['G_0'] = float('nan')
if 'Gprime_0' not in params:
params['Gprime_0'] = float('nan')

#check that all the required keys are in the dictionary
expected_keys = ['V_0', 'K_0', 'Kprime_0']
for k in expected_keys:
if k not in params:
raise KeyError('params object missing parameter : ' + k)

#now check that the values are reasonable. I mostly just
#made up these values from experience, and we are only
#raising a warning. Better way to do this? [IR]
if params['V_0'] < 1.e-7 or params['V_0'] > 1.e-3:
warnings.warn( 'Unusual value for V_0', stacklevel=2 )
if params['K_0'] < 1.e9 or params['K_0'] > 1.e13:
warnings.warn( 'Unusual value for K_0' , stacklevel=2)
if params['Kprime_0'] < -5. or params['Kprime_0'] > 10.:
warnings.warn( 'Unusual value for Kprime_0', stacklevel=2 )