|
28 | 28 |
|
29 | 29 | """
|
30 | 30 |
|
| 31 | +from functools import partial |
| 32 | + |
31 | 33 | import numpy as np
|
| 34 | +import pandas as pd |
| 35 | +from scipy.optimize import curve_fit |
32 | 36 |
|
33 | 37 | from ..util.log import Handle
|
34 | 38 | from ..util.meta import sphinx_doi_link, update_docstring_references
|
@@ -104,7 +108,7 @@ def strain_coefficient(ri, rx, r0=None, E=None, T=298.15, z=None, **kwargs):
|
104 | 108 | """
|
105 | 109 | n = 6.023 * 10**23
|
106 | 110 | if r0 is None:
|
107 |
| - logger.warn("Use fictive ideal cation radii where possible.") |
| 111 | + logger.warning("Use fictive ideal cation radii where possible.") |
108 | 112 | r0 = ri
|
109 | 113 | ri, rx, r0 = ri / 10**10, rx / 10**10, r0 / 10**10 # convert to meters
|
110 | 114 | E = E or youngs_modulus_approximation(z, r0) # use E if defined, else try to calc
|
@@ -182,6 +186,60 @@ def youngs_modulus_approximation(z, r):
|
182 | 186 | return E
|
183 | 187 |
|
184 | 188 |
|
| 189 | +def _lattice_opt_function(xs, ri, Tk, D, z=3, E=None): |
| 190 | + return D * strain_coefficient( |
| 191 | + ri, xs, r0=ri, E=E or youngs_modulus_approximation(z, ri), T=Tk |
| 192 | + ) |
| 193 | + |
| 194 | + |
| 195 | +def fit_lattice_strain( |
| 196 | + radii, |
| 197 | + ys, |
| 198 | + E=None, |
| 199 | + z=3, |
| 200 | + bounds=[(0.1, 2.2), (273.15, 273.15 + 2700), (0, np.inf)], |
| 201 | + r0=None, |
| 202 | + t0=273.15 + 500, |
| 203 | + d0=1.0, |
| 204 | + **kwargs, |
| 205 | +): |
| 206 | + """ |
| 207 | + Fit a lattice strain model to a given set of abundances. |
| 208 | +
|
| 209 | + Parameters |
| 210 | + ---------- |
| 211 | + radii : :class:`numpy.ndarray` |
| 212 | + Radii to fit against. |
| 213 | + ys : :class:`numpy.ndarray` |
| 214 | + Partition coefficients for given elemental data. |
| 215 | + E : :class:`float`, :code:`None` |
| 216 | + Young's modulus (stiffness) for the site, in pascals (Pa). Will be estimated using |
| 217 | + :func:`youngs_modulus_approximation` if none is given. |
| 218 | + z : :class:`int` |
| 219 | + Optional specification of cationic valence, for calcuation of approximate |
| 220 | + Young's modulus using :func:`youngs_modulus_approximation`, |
| 221 | + where the modulus is not specified. |
| 222 | + bounds : :class:`list` |
| 223 | + List of tuples specifying bounds on parameters `ri`, `T` and `D`. |
| 224 | +
|
| 225 | + Returns |
| 226 | + ------- |
| 227 | + ri, tk, D : :class:`float` |
| 228 | + Radius, temperature and partition coefficeint describing the |
| 229 | + lattice strain fit. |
| 230 | + """ |
| 231 | + |
| 232 | + popt, pcov = curve_fit( |
| 233 | + partial(_lattice_opt_function, z=z, E=E), |
| 234 | + radii, |
| 235 | + ys, |
| 236 | + p0=[r0 if r0 is not None else radii.mean(), t0, d0], |
| 237 | + bounds=pd.DataFrame(bounds).T.values, |
| 238 | + **kwargs, |
| 239 | + ) |
| 240 | + return popt |
| 241 | + |
| 242 | + |
185 | 243 | __doc__ = __doc__.format(
|
186 | 244 | brice1975=sphinx_doi_link("10.1016/0022-0248(75)90241-9"),
|
187 | 245 | blundy1994=sphinx_doi_link("10.1038/372452a0"),
|
|
0 commit comments