Multicomponent Precipitation
This example will use a ternary system (Ni-Cr-Al); however, the setup for any multicomponent system is mostly the same.
Example - 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].
1 from kawin.thermo import MulticomponentThermodynamics
2
3 elements = ['NI', 'AL', 'CR', 'VA']
4 phases = ['FCC_A1', 'FCC_L12']
5 therm = MulticomponentThermodynamics('NiCrAl.tdb', elements, phases)
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.%).
6 from kawin.precipitation import MatrixParameters, PrecipitateParameters, TemperatureParameters
7
8 a = 0.352e-9 #Lattice parameter
9 Va = a**3 #Atomic volume of FCC-Ni
10 Vb = Va #Assume Ni3Al has same unit volume as FCC-Ni
11 atomsPerCell = 4 #Atoms in an FCC unit cell
12
13 matrix = MatrixParameters(['AL', 'CR'])
14 matrix.initComposition = [0.098, 0.083]
15 matrix.volume.setVolume(Va, 'VA', 4)
16 matrix.nucleationSites.setBulkDensity(1e30)
17
18 precipitate = PrecipitateParameters('FCC_L12')
19 precipitate.gamma = 0.023
20 precipitate.volume.setVolume(Va, 'VA', 4)
21 precipitate.nucleation.setNucleationType('bulk')
22
23 T = 1073
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. When defining the range to train the surrogate model on, it is recommended to extend the range beyond what is expected to occur during the precipitate simulation.
24 import numpy as np
25 from kawin.thermo import MulticomponentSurrogate, generateTrainingPoints
26
27 surr = MulticomponentSurrogate(therm)
28
29 #Train driving force surrogate
30 xAl = np.linspace(0.02, 0.12, 8)
31 xCr = np.linspace(0.02, 0.12, 8)
32 xTrain = generateTrainingPoints(xAl, xCr)
33 surr.trainDrivingForce(xTrain, T)
34
35 #Train curvature factors surrogate
36 xAl = np.linspace(0.05, 0.23, 16)
37 xCr = np.linspace(0, 0.12, 16)
38 xTrain = generateTrainingPoints(xAl, xCr)
39 surr.trainCurvature(xTrain, T)
Solving the Model
Solving the model is the same as for binary precipitation.
40 from kawin.precipitation import PrecipitateModel
41
42 model = PrecipitateModel(matrix, precipitate, thermodynamics=surr, temperature=T)
43 model.solve(1e6, verbose=True, vIt = 5000)
N Time (s) Sim Time (s) Temperature (K) AL CR
0 0.0e+00 0.0 1073 9.8000 8.3000
Phase Prec Density (#/m3) Volume Frac Avg Radius (m) Driving Force (J/mol)
FCC_L12 0.000e+00 0.0000 0.0000e+00 2.4244e+02
N Time (s) Sim Time (s) Temperature (K) AL CR
5000 1.3e+04 16.0 1073 8.8453 8.5602
Phase Prec Density (#/m3) Volume Frac Avg Radius (m) Driving Force (J/mol)
FCC_L12 6.195e+20 11.2809 3.2945e-08 9.0477e+00
N Time (s) Sim Time (s) Temperature (K) AL CR
7690 1.0e+06 24.7 1073 8.8170 8.5673
Phase Prec Density (#/m3) Volume Frac Avg Radius (m) Driving Force (J/mol)
FCC_L12 8.595e+18 11.6264 1.3858e-07 2.1507e+00
Plotting
Plotting is also the same as with binary precipitation. Note that plotting composition will plot all components.
44 %matplotlib inline
45 import matplotlib.pyplot as plt
46 from kawin.precipitation.Plot import plotPrecipitateDensity, plotVolumeFraction, plotAverageRadius, plotCriticalRadius, plotComposition, plotEqMatrixComposition
47
48 fig, axes = plt.subplots(2, 2, figsize=(10, 8))
49
50 plotPrecipitateDensity(model, ax=axes[0,0])
51 plotVolumeFraction(model, ax=axes[0,1])
52 plotAverageRadius(model, ax=axes[1,0], label=r'$R_{avg}$')
53 plotCriticalRadius(model, ax=axes[1,0], label=r'$R_{crit}$')
54 plotComposition(model, ax=axes[1,1])
55 plotEqMatrixComposition(model, ax=axes[1,1], linestyle='--', color={'AL': 'C0', 'CR': 'C1'}, label={'AL': r'AL$_{eq}$', 'CR': r'CR$_{eq}$'})
56
57 axes[0,0].set_xlim([1e-1, 1e6])
58 axes[0,1].set_xlim([1e-1, 1e6])
59 axes[1,0].set_xlim([1e-1, 1e6])
60 axes[1,1].set_xlim([1e-1, 1e6])
61 axes[1,1].set_ylim([0.08, 0.1])
62
63 fig.tight_layout()

The other way is to account for the time-dependent history of the surface composition. So as the precipitate grows, only the volume that is added to the precipitate has the surface composition. We can simulate this by the setInfinitePrecipitateDiffusivity function, which can be applied to all precipitates or a specified one.
64 precipitate.infinitePrecipitateDiffusion = False
65
66 model_nodiff = PrecipitateModel(matrix, precipitate, thermodynamics=surr, temperature=T)
67 model_nodiff.solve(1e6, verbose=True, vIt = 5000)
N Time (s) Sim Time (s) Temperature (K) AL CR
0 0.0e+00 0.0 1073 9.8000 8.3000
Phase Prec Density (#/m3) Volume Frac Avg Radius (m) Driving Force (J/mol)
FCC_L12 0.000e+00 0.0000 0.0000e+00 2.4244e+02
N Time (s) Sim Time (s) Temperature (K) AL CR
5000 1.3e+04 16.3 1073 8.8605 8.5201
Phase Prec Density (#/m3) Volume Frac Avg Radius (m) Driving Force (J/mol)
FCC_L12 6.242e+20 11.4620 3.3041e-08 9.0234e+00
N Time (s) Sim Time (s) Temperature (K) AL CR
7688 1.0e+06 24.6 1073 8.8334 8.5245
Phase Prec Density (#/m3) Volume Frac Avg Radius (m) Driving Force (J/mol)
FCC_L12 8.687e+18 11.8163 1.3895e-07 2.1485e+00
When plotting the matrix composition under these two assumptions shows that the matrix composition under the no diffusion assumption will never reach the equilibrium matrix composition. This is due to how the precipitates will never homogenize to the equilibrium precipitate composition.
68 fig, axes = plt.subplots(figsize=(5, 4))
69
70 plotEqMatrixComposition(model, ax=axes, color='k', linewidth=0.5, label={'AL': r'AL$_{eq}$', 'CR': r'CR$_{eq}$'})
71 plotComposition(model, ax=axes, color={'AL': 'C0', 'CR': 'C1'}, label={'AL': r'AL$_{inf}$', 'CR': r'CR$_{inf}$'})
72 plotComposition(model_nodiff, ax=axes, linestyle='--', color={'AL': 'C0', 'CR': 'C1'}, label={'AL': r'AL$_{nodiff}$', 'CR': r'CR$_{nodiff}$'})
73
74 axes.legend(loc='upper right')
75 axes.set_xlim([1e-1, 1e6])
76 axes.set_ylim([0.0825, 0.1])
77
78 fig.tight_layout()

References
- A. T. Dinsdale, “SGTE Data for Pure Elements” Calphad 15 (1991) p. 317
- N. Dupin, I. Ansara and B. Sundman, “Thermodynamic Re-assessment of the Ternary System Al-Cr-Ni” Calphad 25 (2001) p. 279
- A. Engstrom and J. Agren, “Assessment of Diffusional Mobilities in Face-centered Cubic Ni-Cr-Al Alloys” Z. Metallkd. 87 (1996) p. 92