/
helper_solid_solution.py
192 lines (153 loc) · 6.86 KB
/
helper_solid_solution.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
from __future__ import absolute_import
import os
import sys
# hack to allow scripts to be placed in subdirectories next to burnman:
if not os.path.exists("burnman") and os.path.exists("../../burnman"):
sys.path.insert(1, os.path.abspath("../.."))
import burnman
import burnman.minerals as minerals
class HelperSolidSolution(burnman.Mineral):
"""
This material is deprecated!
Class for coming up with a new mineral based based on a solid
solution between two or more end member minerals. It is not
completely clear how to do this, or how valid this approximation
is, but here we just do a weighted arithmetic average of the
thermoelastic properties of the end members according to their molar fractions
"""
def __init__(self, endmembers, molar_fractions):
"""
Takes a list of end member minerals, and a matching list of
molar fractions of those minerals for mixing them. Simply
comes up with a new mineral by doing a weighted arithmetic
average of the end member minerals
"""
burnman.Mineral.__init__(self)
self.endmembers = endmembers
self.molar_fractions = molar_fractions
assert len(endmembers) == len(molar_fractions)
assert sum(molar_fractions) > 0.9999
assert sum(molar_fractions) < 1.0001
self.method = endmembers[0].method
# does not make sense to do a solid solution with different number of
# atoms per formula unit or different equations of state, at least not
# simply...
for m in endmembers:
m.set_method(self.method)
if "n" in endmembers[0].params:
assert m.params["n"] == endmembers[0].params["n"]
self.params = {}
def debug_print(self, indent=""):
print("%sHelperSolidSolution(%s):" % (indent, self.to_string()))
indent += " "
for fraction, mat in zip(self.molar_fractions, self.endmembers):
print("%s%g of" % (indent, fraction))
mat.debug_print(indent + " ")
def set_method(self, method):
for mat in self.endmembers:
mat.set_method(method)
self.method = self.endmembers[0].method
def set_state(self, pressure, temperature):
for mat in self.endmembers:
mat.set_state(pressure, temperature)
itrange = range(0, len(self.endmembers))
self.params = {}
for prop in self.endmembers[0].params:
try:
self.params[prop] = sum(
[
self.endmembers[i].params[prop] * self.molar_fractions[i]
for i in itrange
]
)
except TypeError:
# if there is a type error, it is probably a string. Just go
# with the value of the first endmembers.
self.params[prop] = self.endmembers[0].params[prop]
burnman.Mineral.set_state(self, pressure, temperature)
class SLB_2005_ferropericlase(HelperSolidSolution):
def __init__(self, fe_num):
endmembers = [minerals.SLB_2005.periclase(), minerals.SLB_2005.wuestite()]
molar_fractions = [1.0 - fe_num, 0.0 + fe_num]
# keep the 0.0 +, otherwise it is an array sometimes
HelperSolidSolution.__init__(self, endmembers, molar_fractions)
class SLB_2005_mg_fe_perovskite(HelperSolidSolution):
def __init__(self, fe_num):
endmembers = [
minerals.SLB_2005.mg_perovskite(),
minerals.SLB_2005.fe_perovskite(),
]
molar_fractions = [1.0 - fe_num, 0.0 + fe_num]
# keep the 0.0 +, otherwise it is an array sometimes
HelperSolidSolution.__init__(self, endmembers, molar_fractions)
class Murakami_2013_ferropericlase(HelperSolidSolution):
def __init__(self, fe_num):
endmembers = [
minerals.Murakami_2013.periclase(),
minerals.Murakami_2013.wuestite(),
]
molar_fractions = [1.0 - fe_num, 0.0 + fe_num]
# keep the 0.0 +, otherwise it is an array sometimes
HelperSolidSolution.__init__(self, endmembers, molar_fractions)
class Murakami_2013_mg_fe_perovskite(HelperSolidSolution):
def __init__(self, fe_num):
endmembers = [
minerals.Murakami_2013.mg_perovskite(),
minerals.Murakami_2013.fe_perovskite(),
]
molar_fractions = [1.0 - fe_num, 0.0 + fe_num]
# keep the 0.0 +, otherwise it is an array sometimes
HelperSolidSolution.__init__(self, endmembers, molar_fractions)
# This is ferropericlase with the deprecated solid solution setup,
# only used for the scripts in this folder
class other_ferropericlase(HelperSolidSolution):
def __init__(self, fe_num):
endmembers = [minerals.other.periclase(), minerals.other.wuestite()]
molar_fractions = [1.0 - fe_num, 0.0 + fe_num]
# keep the 0.0 +, otherwise it is an array sometimes
HelperSolidSolution.__init__(self, endmembers, molar_fractions)
# this is mg_fe_perovskite with the depricated solid solution setup.
# Better not use...
class other_mg_fe_perovskite(HelperSolidSolution):
def __init__(self, fe_num):
endmembers = [minerals.other.mg_perovskite(), minerals.other.fe_perovskite()]
molar_fractions = [
1.0 - fe_num,
0.0 + fe_num,
] # keep the 0.0 +, otherwise it is an array sometimes
HelperSolidSolution.__init__(self, endmembers, molar_fractions)
# similar to ferropericlase, using the old solid solution setup. These
# values are based on Zhang, Stixrude and Brodholt 2013
class other_ZSB_2013_mg_fe_perovskite(HelperSolidSolution):
def __init__(self, fe_num):
endmembers = [
minerals.other.ZSB_2013_mg_perovskite(),
minerals.other.ZSB_2013_fe_perovskite(),
]
molar_fractions = [
1.0 - fe_num,
0.0 + fe_num,
] # keep the 0.0 +, otherwise it is an array sometimes
HelperSolidSolution.__init__(self, endmembers, molar_fractions)
class SLB_2011_ZSB_2013_ferropericlase(HelperSolidSolution):
def __init__(self, fe_num):
endmembers = [
minerals.SLB_2011_ZSB_2013.periclase(),
minerals.SLB_2011_ZSB_2013.wuestite(),
]
molar_fractions = [
1.0 - fe_num,
0.0 + fe_num,
] # keep the 0.0 +, otherwise it is an array sometimes
HelperSolidSolution.__init__(self, endmembers, molar_fractions)
class SLB_2011_ZSB_2013_mg_fe_perovskite(HelperSolidSolution):
def __init__(self, fe_num):
endmembers = [
minerals.SLB_2011_ZSB_2013.mg_perovskite(),
minerals.SLB_2011_ZSB_2013.fe_perovskite(),
]
molar_fractions = [
1.0 - fe_num,
0.0 + fe_num,
] # keep the 0.0 +, otherwise it is an array sometimes
HelperSolidSolution.__init__(self, endmembers, molar_fractions)