# Multicomponent Precipitation

## The Ni-Cr-Al system #

In the Ni-Cr-Al system, $Ni_3(Al,Cr)$ can precipitate into an $\gamma$-Ni (FCC) matrix. As with binary precipitatation, the Thermodynamics module provides some functions to interface with pyCalphad in defining the driving force, growth rate and interfacial composition. Similarly, it is also possible to use user-defined functions for the driving force and nucleation as long as the function parameters and return values are consistent with the ones provides by the Thermodynamics module. Calphad models for the Ni-Cr-Al system was obtained from the STGE database and Dupin et al [1,2]. Mobility data for the Ni-Cr-Al system was obtained from Engstrom and Agren [3].

from kawin.Thermodynamics import MulticomponentThermodynamics
from kawin.KWNEuler import PrecipitateModel
import numpy as np

elements = ['NI', 'AL', 'CR', 'VA']
phases = ['FCC_A1', 'FCC_L12']

therm = MulticomponentThermodynamics('NiCrAl.tdb', elements, phases)

t0, tf, steps = 1e-1, 1e6, 2e4
model = PrecipitateModel(t0, tf, steps, elements=['Al', 'Cr'])


## Model Inputs #

Setting up model parameters is the same as for binary systems. The only difference is that the initial composition needs to be set as an array where the elements in the array will correspond to the same order of elements when the model was defined. In this case, [0.10, 0.085] corresponds to Ni-10Al-8.5Cr (at.%).

model.setInitialComposition([0.10, 0.085])
model.setInterfacialEnergy(0.023)

T = 1073
model.setTemperature(T)

a = 0.352e-9        #Lattice parameter
Va = a**3           #Atomic volume of FCC-Ni
Vb = Va             #Assume Ni3Al has same unit volume as FCC-Ni
atomsPerCell = 4    #Atoms in an FCC unit cell
model.setVaAlpha(Va, atomsPerCell)
model.setVaBeta(Vb, atomsPerCell)

#Set nucleation sites to dislocations and use defualt value of 5e12 m/m3
model.setNucleationSite('dislocations')
model.setNucleationDensity(dislocationDensity=5e12)


## Surrogate Modeling #

For efficiency, a surrogate model can be made on the driving force and interfacial composition. The surrogate models uses radial-basis function (RBF) interpolation and the scale and basis function can be defined (using RBF interpolation from Scipy).

For multicomponent systems, a surrogate on the driving force and the various terms derived from the curvature of the free energy surface to calculate growth rate and interfacial composition (which will be referred to as “curvature factors”) can be made. Both surrogates will need a set of compositions and temperatures to be trained on.

from kawin.Surrogate import MulticomponentSurrogate, generateTrainingPoints

surr = MulticomponentSurrogate(therm)

#Train driving force surrogate
xAl = np.linspace(0.05, 0.11, 8)
xCr = np.linspace(0.05, 0.1, 8)
xTrain = generateTrainingPoints(xAl, xCr)
surr.trainDrivingForce(xTrain, T)

#Train curvature factors surrogate
xAl = np.linspace(0.1, 0.23, 16)
xCr = np.linspace(0, 0.1, 16)
xTrain = generateTrainingPoints(xAl, xCr)
surr.trainCurvature(xTrain, T)

model.setSurrogate(surr)


## Solving the Model #

Solving the model is the same as for binary precipitation.

model.solve(verbose=True, vIt = 5000)

N	Time (s)	Temperature (K)Al	Cr
5000	5.6e+00		1073	9.9932	8.5016

Phase	Prec Density (#/m3)	Volume Frac	Avg Radius (m)
beta	1.888e+21	0.0938		4.8541e-09

N	Time (s)	Temperature (K)Al	Cr
10000	3.2e+02		1073	8.7199	8.8756

Phase	Prec Density (#/m3)	Volume Frac	Avg Radius (m)
beta	1.889e+21	15.0704		2.6600e-08

N	Time (s)	Temperature (K)Al	Cr
15000	1.8e+04		1073	8.7111	8.8775

Phase	Prec Density (#/m3)	Volume Frac	Avg Radius (m)
beta	6.607e+20	15.1921		3.5948e-08

N	Time (s)	Temperature (K)Al	Cr
20000	9.9e+05		1073	8.6933	8.8822

Phase	Prec Density (#/m3)	Volume Frac	Avg Radius (m)
beta	1.181e+19	15.4082		1.3802e-07

Finished in 34.489 seconds.


## Plotting #

Plotting is also the same as with binary precipitation. Note that plotting composition will plot all components.

%matplotlib inline
import matplotlib.pyplot as plt

fig, axes = plt.subplots(2, 2, figsize=(12, 10))

model.plot(axes[0,0], 'Precipitate Density')
model.plot(axes[0,1], 'Composition')
model.plot(axes[1,0], 'Average Radius', color='C0', label='Avg. R')