kawin.thermo (Surrogate)
kawin.kawin.thermo.Surrogate
def generateTrainingPoints(*arrays):
Creates all combinations of inputted arrays
Used for creating training points in composition space for
MulticomponentSurrogate
Parameters
----------
arrays - arrays along each dimension
Order of arrays should correspond to the order of elements when defining thermodynamic functions
def _filter_points(inputs, outputs, tol = 1e-3):
Filter set of input points such that the closest distance is above tolerance
This is to avoid non-positive definite training matrices when creating surrogate models
Parameters
----------
inputs : m x n matrix of floats
Input points of m observations in n-dimensional space
outputs : list of array of floats
Output points, each array must be m x n where
m is number of observations and n is dimensions of output
tol : float
Tolerance for distance between two input points
Outputs
-------
(filtered inputs, filtered outputs)
filtered inputs - array of input points
filtered outputs - array of output points
NumpyEncoder(json.JSONEncoder)
Converts all numpy arrays to list, to be used when serializing surrogate data
We don't need custom decoding, since the surrogate model should convert lists to numpy arrays if needed
def NumpyEncoder.default(self, data):
SurrogateKernel(ABC)
class SurrogateKernel(self, x, y, *args, **kwargs):
Abstract class for kernel
Attributes
__init__ - builds the surrogate model from x and y, and may use *args and **kwargs for hyperparameters
predict - returns a y-like output from an x-like input
def SurrogateKernel.predict(self, x):
RBFKernel(SurrogateKernel)
class RBFKernel(self, x, y, *args, **kwargs):
Surrogate kernel using scipy radial basis function (RBFInterpolator)
An additional parameter, 'normalize', can be used to normalize all dimensions of x from [0,1]
def RBFKernel.predict(self, x):
GeneralSurrogate
class GeneralSurrogate(self, thermodynamics: GeneralThermodynamics, kernel:SurrogateKernel=RBFKernel, kernelKwargs={‘kernel’:‘cubic’, ‘normalize’:True}):
By default, the untrained surrogate will use the thermodynamic functions
As we train a model, it will be added to the model and replace the underlying thermodynamics
Then any untrained model will still go back to the thermodynamic functions
The intent of this is that the surrogate models API will be similar to the
underlying thermodynamic modules
Driving force
Tracer diffusivity
Interdiffusivity
Interfacial composition - binary only
Curvature factor - multicomponent only
Impingement rate - multicomponent only
Parameters
----------
thermodynamics: GeneralThermodynamics, BinaryThermodynamics, MulticomponentThermodynamics
kernel: SurrogateKernel (optional)
Defaults to RBFKernel
kernelKwargs: dict (optional)
arguments for kernel
Defaults to {'kernel': 'cubic', 'normalize': True}
def GeneralSurrogate._processCompositionInput(self, x, T, broadcast = True):
Makes sure x and T are np arrays
If broadcasting, then x and T will be computed as a grid
Parameters
x : float, np.array
T : float, np.array
broadcast : bool (optional)
Defaults to True
If True, will create a grid over x and T
If False, x and T represents all points and must have the same length
def GeneralSurrogate._createInput(self, xs, singleXs):
Create input data for the surrogate model by validating number of unique points in each dimension
def GeneralSurrogate.trainDrivingForce(self, x, T, precPhase=None, logX = False, broadcast=True):
Creates surrogate model for driving force
Model will be in the form of (dg, x) = f(x, T) or (dg, x) = f(ln(x), T)
If only single x or T, then surrogate model will only be trained on
non-scalar axis
Parameters
----------
x : float, np.array
If binary, shape of x must be () or (N,)
If multicomponent, shape of x must be (e,) or (N,e)
T : float, np.array
precPhase : str (optional)
Defaults to None
If None, defaults to first precipitate phase
logX : bool (optional)
Defaults to False
If True, fits composition on a log scale
broadcast : bool (optional)
Defaults to True
If True, will create grid of points over x and T
def GeneralSurrogate._fitDrivingForce(self, phase):
Fits driving force data for phase
def GeneralSurrogate.getDrivingForce(self, x, T, precPhase=None, *args, **kwargs):
Computes driving force
If surrogate model for driving force has not been trained, this will use the underlying thermodynamics function
Parameters
----------
x : float, np.array
If binary, shape of x must be () or (N,)
If multicomponent, shape of x must be (e,) or (N,e)
T : float, np.array
precPhase : str (optional)
Defaults to None
If None, defaults to first precipitate phase
def GeneralSurrogate.trainDiffusivity(self, x, T, phase=None, logX=False, broadcast=True):
Creates surrogate model for diffusivity
Model will be in the form of (Dnkj^1/3, D*^1/3) = f(x, 1/T) or (Dnkj^1/3, D*^1/3) = f(ln(x), 1/T)
The cubic transformation is used since Dnkj may be negative due to chemical potential gradients
If only single x or T, then surrogate model will only be trained on
non-scalar axis
Parameters
----------
x : float, np.array
If binary, shape of x must be () or (N,)
If multicomponent, shape of x must be (e,) or (N,e)
T : float, np.array
precPhase : str (optional)
Defaults to None
If None, defaults to first precipitate phase
logX : bool (optional)
Defaults to False
If True, fits composition on a log scale
broadcast : bool (optional)
Defaults to True
If True, will create grid of points over x and T
def GeneralSurrogate._fitDiffusivity(self, phase):
Fits driving force data for phase
def GeneralSurrogate._getDiffusivity(self, x, T, phase):
Evaluates diffusivity from surrogate model
def GeneralSurrogate.getInterdiffusivity(self, x, T, phase=None, *args, **kwargs):
Computes interdiffusivity
If surrogate model for driving force has not been trained, this will use the underlying thermodynamics function
Parameters
----------
x : float, np.array
If binary, shape of x must be () or (N,)
If multicomponent, shape of x must be (e,) or (N,e)
T : float, np.array
precPhase : str (optional)
Defaults to None
If None, defaults to first precipitate phase
def GeneralSurrogate.getTracerDiffusivity(self, x, T, phase=None, *args, **kwargs):
Computes tracer diffusivity
If surrogate model for driving force has not been trained, this will use the underlying thermodynamics function
Parameters
----------
x : float, np.array
If binary, shape of x must be () or (N,)
If multicomponent, shape of x must be (e,) or (N,e)
T : float, np.array
precPhase : str (optional)
Defaults to None
If None, defaults to first precipitate phase
def GeneralSurrogate._collectSurrogateData(self):
Creates dictionary of surrogate training data
def GeneralSurrogate._processSurrogateData(self, data):
Stores surrogate training data from dict and trains models
def GeneralSurrogate.toJson(self, filename: str | Path):
Saves surrogate data to json
def GeneralSurrogate.fromJson(self, filename: str | Path):
Loads surrogate data from json
BinarySurrogate(GeneralSurrogate)
class BinarySurrogate(self, thermodynamics: BinaryThermodynamics, kernel:SurrogateKernel=RBFKernel, kernelKwargs={‘kernel’:‘cubic’, ‘normalize’:True}):
Same as GeneralSurrogate but implements models for interfacial composition
def BinarySurrogate._processGibbsThompsonInput(self, T, gExtra, broadcast = False):
Makes sure T and gExtra are np arrays
If broadcasting, then T and gExtra will be computed as a grid
def BinarySurrogate.trainInterfacialComposition(self, T, gExtra, precPhase=None, logY = False, broadcast=True):
Creates surrogate model for interfacial composition
Model will be in the form of (xa, xb) = f(T, 1/gExtra) or (ln(xa), xb) = f(T, 1/gExtra)
If only single T or gExtra, then surrogate model will only be trained on
non-scalar axis
Parameters
----------
T : float, np.array
gExtra : float, np.array
precPhase : str (optional)
Defaults to None
If None, defaults to first precipitate phase
logY : bool (optional)
If True, will fit interfacial composition on a log scale
broadcast : bool (optional)
If True, will create grid of points from T and gExtra
def BinarySurrogate._fitInterfacialComposition(self, phase):
Fits driving force data for phase
def BinarySurrogate.getInterfacialComposition(self, T, gExtra=0, precPhase=None):
Computes interfacial composition
Parameters
----------
T : float, np.array
gExtra : float, np.array (optional)
Defaults to 0
precPhase : str (optional)
Defaults to None
If None, defaults to first precipitate phase
def BinarySurrogate._collectSurrogateData(self):
Adds interfacial composition data to GeneralSurrogate surrogate data
def BinarySurrogate._processSurrogateData(self, data):
Stores interfacial composition data and fits models along with models from GeneralSurrogate
MulticomponentSurrogate(GeneralSurrogate)
class MulticomponentSurrogate(self, thermodynamics: MulticomponentThermodynamics, kernel:SurrogateKernel=RBFKernel, kernelKwargs={‘kernel’:‘cubic’, ‘normalize’:True}):
Same as GeneralSurrogate but implements models for curvature factors
Curvature factor can then be used for growth rate, interfacial composition and impingement rate
def MulticomponentSurrogate.trainCurvature(self, x, T, precPhase=None, logX = False, broadcast=True):
Trains curvature factors
Parameters
----------
x : np.array
Shape of (e,) of (N,e)
T : float, np.array
precPhase : str (optional)
Defaults to None, which is first precipitate phase
logX : bool (optional)
Defaults to False
If True, then x and matrix interfacial composition will be fitted on a log scale
broadcast : bool (optional)
Defaults to True
If True, then a grid a points will be generated over x and T
def MulticomponentSurrogate._fitCurvature(self, phase):
Fits cuvature data for phase
def MulticomponentSurrogate._surrogateOutputToCurvature(self, output, numEle, logX):
Converts surrogate output to CurvatureOutput
def MulticomponentSurrogate.curvatureFactor(self, x, T, precPhase = None, *args, **kwargs):
Computes curvature factors
Parameters
----------
x : np.array
Shape of (e,)
T : float
precPhase : str (optional)
Defaults to None, which is first precipitate phase
def MulticomponentSurrogate.getGrowthAndInterfacialComposition(self, x, T, dG, R, gExtra, precPhase = None, *args, **kwargs):
Computes growth rate and interfacial composition
Parameters
----------
x : np.array
Shape of (e,)
T : float
dG : float
Driving force at x,T
R : float, np.array
Precipitate radius
gExtra : float, np.array
Gibbs-Thomson contribution corresponding to R
precPhase : str (optional)
Defaults to None, which is first precipitate phase
def MulticomponentSurrogate.impingementFactor(self, x, T, precPhase = None, *args, **kwargs):
Computes impingement factor
Parameters
----------
x : np.array
Shape of (e,)
T : float
precPhase : str (optional)
Defaults to None, which is first precipitate phase
def MulticomponentSurrogate._collectSurrogateData(self):
Adds interfacial composition data to GeneralSurrogate surrogate data
def MulticomponentSurrogate._processSurrogateData(self, data):
Stores interfacial composition data and fits models along with models from GeneralSurrogate