[cig-commits] [commit] inversion, master, validate_MT_params: Rejigged SolidSolution class (8e7ba31)
cig_noreply at geodynamics.org
cig_noreply at geodynamics.org
Fri Dec 12 18:25:09 PST 2014
Repository : https://github.com/geodynamics/burnman
On branches: inversion,master,validate_MT_params
Link : https://github.com/geodynamics/burnman/compare/80c2a295c42dfdb38f83f6c1334bf7d8f97a8463...409647ff05dfad6a686198cac1481bd46b5e2e62
>---------------------------------------------------------------
commit 8e7ba3109e7deb244b919a6773a2898254e23617
Author: Bob Myhill <myhill.bob at gmail.com>
Date: Sun Aug 31 12:19:42 2014 +0200
Rejigged SolidSolution class
>---------------------------------------------------------------
8e7ba3109e7deb244b919a6773a2898254e23617
burnman/processchemistry.py | 67 +++++++++++++++++++++++++++++++++--
burnman/solidsolution.py | 81 ++++++++++---------------------------------
burnman/test_solidsolution.py | 4 +--
3 files changed, 86 insertions(+), 66 deletions(-)
diff --git a/burnman/processchemistry.py b/burnman/processchemistry.py
index 41a4bbd..8736b74 100644
--- a/burnman/processchemistry.py
+++ b/burnman/processchemistry.py
@@ -1,10 +1,14 @@
# BurnMan - a lower mantle toolkit
-# Copyright (C) 2012, 2013, Myhill, R., Heister, T., Unterborn, C., Rose, I. and Cottaar, S.
+# Copyright (C) 2012-2014, Myhill, R., Heister, T., Unterborn, C., Rose, I. and Cottaar, S.
# Released under GPL v2 or later.
-# This is a function which returns the number of atoms and molar mass of a compound given its unit formula as an argument.
+# This module provides the functions required to process the standard burnman formula compositions
+# ProcessChemistry returns the number of atoms and molar mass of a compound given its unit formula as an argument.
+# ProcessSolidSolutionChemistry returns information required to calculate solid solution properties from a set of endmember formulae
import re
+import numpy as np
+from fractions import Fraction
def ProcessChemistry(formula):
filename="data/input_masses/atomic_masses.dat"
@@ -37,3 +41,62 @@ def ProcessChemistry(formula):
molar_mass=molar_mass+nel*el_mass[el_name.index(list[0])]
return n, molar_mass
+
+
+def ProcessSolidSolutionChemistry(formula):
+ n_sites=formula[0].count('[')
+ n_endmembers=len(formula)
+ # Check the number of sites is the same for each endmember
+ for i in range(n_endmembers):
+ assert(formula[i].count('[') == n_sites)
+
+ # Number of unique site occupancies (e.g.. Mg on X etc.)
+ sites=[[] for i in range(n_sites)]
+ list_occupancies=[]
+ list_multiplicity=np.empty(shape=(n_sites))
+ n_occupancies=0
+ for endmember in range(n_endmembers):
+ list_occupancies.append([[0]*len(sites[site]) for site in range(n_sites)])
+ s=re.split(r'\[', formula[endmember])[1:]
+ for site in range(n_sites):
+ site_occupancy=re.split(r'\]', s[site])[0]
+ mult=re.split('[A-Z][^A-Z]*',re.split(r'\]', s[site])[1])[0]
+ if mult == '':
+ list_multiplicity[site]=1.0
+ else:
+ list_multiplicity[site]=mult
+ elements=re.findall('[A-Z][^A-Z]*',site_occupancy)
+ for i in range(len(elements)):
+ element_on_site=re.split('[0-9][^A-Z]*',elements[i])[0]
+ proportion_element_on_site=re.findall('[0-9][^A-Z]*',elements[i])
+ if len(proportion_element_on_site) == 0:
+ proportion_element_on_site=Fraction(1.0)
+ else:
+ proportion_element_on_site=Fraction(proportion_element_on_site[0])
+
+ if element_on_site not in sites[site]:
+ n_occupancies=n_occupancies+1
+ sites[site].append(element_on_site)
+ element_index=sites[site].index(element_on_site)
+ for parsed_mbr in range(len(list_occupancies)):
+ list_occupancies[parsed_mbr][site].append(0)
+ else:
+ element_index=sites[site].index(element_on_site)
+ list_occupancies[endmember][site][element_index]=proportion_element_on_site
+
+ # Site occupancies and multiplicities
+ endmember_occupancies=np.empty(shape=(n_endmembers,n_occupancies))
+ site_multiplicities=np.empty(shape=(n_occupancies))
+ for endmember in range(n_endmembers):
+ n_element=0
+ for site in range(n_sites):
+ for element in range(len(list_occupancies[endmember][site])):
+ endmember_occupancies[endmember][n_element]=list_occupancies[endmember][site][element]
+ site_multiplicities[n_element]=list_multiplicity[site]
+ n_element=n_element+1
+
+ return n_sites, sites, n_occupancies, endmember_occupancies, site_multiplicities
+
+# WARNING: Currently not implemented
+def CompositionEquality(endmember_formula, solution_formula):
+ return True
diff --git a/burnman/solidsolution.py b/burnman/solidsolution.py
index 375057d..c6fa56b 100644
--- a/burnman/solidsolution.py
+++ b/burnman/solidsolution.py
@@ -2,13 +2,12 @@
# Copyright (C) 2012-2014, Myhill, R., Heister, T., Unterborn, C., Rose, I. and Cottaar, S.
# Released under GPL v2 or later.
+import numpy as np
from burnman.mineral import Mineral
+from burnman.processchemistry import ProcessSolidSolutionChemistry
+from burnman.processchemistry import CompositionEquality
import warnings
-import re
-import numpy as np
-from fractions import Fraction
-
R = 8.3145 # J/K/mol
kd = lambda x,y : 1 if x==y else 0
@@ -57,63 +56,21 @@ class SolidSolution(Mineral):
self.excess_entropy=interaction_parameter[1]
self.excess_volume=interaction_parameter[2]
- # Number of sites
- self.n_sites=base_material[0][1].count('[')
-
- # Check the number of sites is the same for each endmember
- for i in range(self.n_endmembers):
- assert(base_material[i][1].count('[') == self.n_sites)
-
# Check the chemical composition of each endmember is consistent with the dataset
- # NOT IMPLEMENTED YET
+ for i in range(self.n_endmembers):
+ endmember_formula=base_material[i][0].params['formula']
+ solution_formula=base_material[i][1]
+ if CompositionEquality(endmember_formula, solution_formula) != True:
+ print 'Formula of endmember', base_material[i][0].params['name'], 'does not agree with formula in the', self.name, 'SolidSolution model'
+ exit()
- # Number of unique site occupancies (e.g.. Mg on X etc.)
- self.sites=[[] for i in range(self.n_sites)]
- list_occupancies=[]
- list_multiplicity=np.empty(shape=(self.n_sites))
- self.n_occupancies=0
- for endmember in range(self.n_endmembers):
- list_occupancies.append([[0]*len(self.sites[site]) for site in range(self.n_sites)])
- s=re.split(r'\[', base_material[endmember][1])[1:]
- for site in range(self.n_sites):
- site_occupancy=re.split(r'\]', s[site])[0]
- mult=re.split('[A-Z][^A-Z]*',re.split(r'\]', s[site])[1])[0]
- if mult == '':
- list_multiplicity[site]=1.0
- else:
- list_multiplicity[site]=mult
- elements=re.findall('[A-Z][^A-Z]*',site_occupancy)
- for i in range(len(elements)):
- element_on_site=re.split('[0-9][^A-Z]*',elements[i])[0]
- proportion_element_on_site=re.findall('[0-9][^A-Z]*',elements[i])
- if len(proportion_element_on_site) == 0:
- proportion_element_on_site=Fraction(1.0)
- else:
- proportion_element_on_site=Fraction(proportion_element_on_site[0])
-
- if element_on_site not in self.sites[site]:
- self.n_occupancies=self.n_occupancies+1
- self.sites[site].append(element_on_site)
- element_index=self.sites[site].index(element_on_site)
- for parsed_mbr in range(len(list_occupancies)):
- list_occupancies[parsed_mbr][site].append(0)
- else:
- element_index=self.sites[site].index(element_on_site)
- list_occupancies[endmember][site][element_index]=proportion_element_on_site
-
- # Site occupancies and multiplicities
- self.site_occupancies=np.empty(shape=(self.n_endmembers,self.n_occupancies))
- self.site_multiplicities=np.empty(shape=(self.n_occupancies))
- for endmember in range(self.n_endmembers):
- n_element=0
- for site in range(self.n_sites):
- for element in range(len(list_occupancies[endmember][site])):
- self.site_occupancies[endmember][n_element]=list_occupancies[endmember][site][element]
- self.site_multiplicities[n_element]=list_multiplicity[site]
- n_element=n_element+1
+ # Process solid solution chemistry
+ self.n_sites, self.sites, self.n_occupancies, self.endmember_occupancies, self.site_multiplicities = ProcessSolidSolutionChemistry([base_material[i][1] for i in range(self.n_endmembers)])
+ # Create array of van Laar parameters
self.alpha=np.array([base_material[i][2] for i in range(self.n_endmembers)])
+ # Create 2D arrays of interaction parameters
self.Wh=np.zeros(shape=(self.n_endmembers,self.n_endmembers))
self.Ws=np.zeros(shape=(self.n_endmembers,self.n_endmembers))
self.Wv=np.zeros(shape=(self.n_endmembers,self.n_endmembers))
@@ -127,22 +84,24 @@ class SolidSolution(Mineral):
def set_composition(self, molar_fraction):
+ # Check that the composition declared is consistent with the solution model
assert(len(self.base_material) == len(molar_fraction))
assert(sum(molar_fraction) > 0.9999)
assert(sum(molar_fraction) < 1.0001)
+ # Make molar fraction an attribute of the solid solution
self.molar_fraction=molar_fraction
# Ideal activities
- self.occupancies=np.dot(self.molar_fraction, self.site_occupancies)
+ self.site_occupancies=np.dot(self.molar_fraction, self.endmember_occupancies)
self.ideal_activity=np.empty(shape=(self.n_endmembers))
for endmember in range(self.n_endmembers):
self.ideal_activity[endmember]=1.0
normalisation_constant=1.0
for element in range(self.n_occupancies):
- if self.site_occupancies[endmember][element] != 0:
- self.ideal_activity[endmember]=self.ideal_activity[endmember]*pow(self.occupancies[element],self.site_multiplicities[element])
- normalisation_constant=normalisation_constant/pow(self.site_occupancies[endmember][element],self.site_multiplicities[element])
+ if self.endmember_occupancies[endmember][element] != 0:
+ self.ideal_activity[endmember]=self.ideal_activity[endmember]*pow(self.site_occupancies[element],self.site_multiplicities[element])
+ normalisation_constant=normalisation_constant/pow(self.endmember_occupancies[endmember][element],self.site_multiplicities[element])
self.ideal_activity[endmember]=normalisation_constant*self.ideal_activity[endmember]
# Nonideal contributions
@@ -188,5 +147,3 @@ class SolidSolution(Mineral):
self.params[prop] = self.base_materials[0].params[prop]
Mineral.set_state(self, pressure, temperature)
'''
-
-
diff --git a/burnman/test_solidsolution.py b/burnman/test_solidsolution.py
index 09e9056..6159d4a 100644
--- a/burnman/test_solidsolution.py
+++ b/burnman/test_solidsolution.py
@@ -20,13 +20,13 @@ print garnet.molar_fraction
print ''
print 'Site occupancies'
print garnet.sites
-print garnet.occupancies
+print garnet.site_occupancies
print ''
print 'Ideal activities'
print garnet.ideal_activity
print ''
print 'Volume excess'
-print garnet.V_excess
+print garnet.V_excess, 'm^3/mol'
print ''
# Excess volumes for the pyrope-grossular join
More information about the CIG-COMMITS
mailing list