Features and examples
The following features are currently available.
- Single condition equilibrium calculations
- Batch equilibrium calculations
- Scheil-Gulliver solidification
- Phase selection Examples of using each features are demonstraed here. The corresponding python script files are accessible in Examples.
Simple equilibrium (Single condition)
Equilibrium calculation based on the CALPHAD approach requires a thermochemical database and NTP ensemble (N: elemental composition, T: temperature, P: pressure). In general, calculating equilibrium by the CALPHAD approach is a four-step process. An example of calculating a single NTP condition is given in Example01.
Step 1: Parse thermochemical database
First, a thermochemical database must be provided. Currently, equilipy
only supports ChemSage data format .dat
, available from FactSage 7.3.
To read a .dat
database in a python script:
import equilipy as eq
# Step 1: Parse database
datafile=f'./Database/AlCuMgSi_ORNL'
DB=eq.read_dat(datafile+'.dat')
Step 2: Define NPT ensemble
Once providing a database, users should define a NTP condition for input variable. The input condition in equilipy
is defined as a python dictionary:
NTP = dict({
'T':700,
'P': 1,
'Al':0.060606061,
'Cu':0.42424242,
'Si':0.515151515})
Step 3: Calculate equilibrium
For a single NPT condition, equilib_sinlge()
function is used to calculate phase equilibria. Note that both a database DB
and NTP condition NTP
must be given as arguments:
res=eq.equilib_single(DB,NTP)
Step 4: Post process
The calculated results are than stored in a result object res
. Users can access to the information through class methods:
# 4.1: To print all stable phases
print(res.StablePhases['Name'])
print(res.StablePhases['Amount'])
# 4.2: To print all relevant phases
PhasesAll=list(res.Phases.keys())
for i,ph in enumerate(PhasesAll):
print('--------------------------------------------------------------')
print(f'Amount of {PhasesAll[i]}:',res.Phases[PhasesAll[i]].Amount)
print(f'Endmembers of {PhasesAll[i]}:',res.Phases[PhasesAll[i]].Endmembers)
print(f'Composition of {PhasesAll[i]}:',res.Phases[PhasesAll[i]].xi)
print(' ')
Phase selection
equilipy
provides meta-stable phase equilibrium calculation through pre-selecting phases. The list of all available phase names can be obtained by list_phases()
. Users should construct a custom list of phase names and parse it to ListOfPhases
argument in equilib_single
at Step 3. An example of such calculation is given in Example02.
import equilipy as eq
# Step 1: Parse database
datafile=f'./Database/AlCuMgSi_ORNL'
DB=eq.read_dat(datafile+'.dat')
# Step 2: Parse input data
NTP = dict({
'T':700,
'P': 1,
'Al':0.060606061,
'Cu':0.42424242,
'Si':0.515151515})
# Step 2: Select phases
# 2.1: Get all available phases of the given system
PhasesAll=eq.list_phases(DB,list(NTP.keys())[2:])
# 2.2: Select phases
phases = PhasesAll[:7]
print(f'Selected phases: {phases}')
# Step 3: Calculate equilibrium
res=eq.equilib_single(DB,NTP, ListOfPhases=phases)
# Step 4: Post process
# 4.1: print all stable phases
print(res.StablePhases['Name'])
print(res.StablePhases['Amount'])
# 4.2 print all phases
PhasesAll=list(res.Phases.keys())
for i,ph in enumerate(PhasesAll):
print('--------------------------------------------------------------')
print(f'Amount of {PhasesAll[i]}:',res.Phases[PhasesAll[i]].Amount)
print(f'Endmembers of {PhasesAll[i]}:',res.Phases[PhasesAll[i]].Endmembers)
print(f'Composition of {PhasesAll[i]}:',res.Phases[PhasesAll[i]].xi)
print(' ')
Phase selection can also be used to calculation batch equilibrium and Scheil-Gulliver solidification.
Batch equilibrium
Calculating multiple NTP conditions are also available using a batch process. By default, equilipy
uses all available processors in the computing node via multiprocessing
.
multiprocessing
calls python script multiple times. Users should ensure using if __name__ == "__main__":
in their main script.
An example of calculating batch equilibrium is given in Example03.
Polars is used for reading large input data from an Excel
file, which requires fastexcel
as the optional dependancy. Install fastexcel
via pip install fastexcel
import polars as pl, time
from datetime import timedelta
import equilipy as eq
if __name__ == "__main__":
system = 'AlCuMgSi'
# system = 'AlCuMg'
# system = 'AlCuSi'
# system = 'AlMgSi'
# system = 'CuMgSi'
# Step 1: Parse database
datafile= './Database/AlCuMgSi_ORNL'
DB=eq.read_dat(datafile+'.dat')
# Step 2: Read input data using polars
df_name= 'Input_ACMS.xlsx'
NTP=pl.read_excel(f'{df_name}',sheet_name=system).to_dict()
# Step 3: Calculate batch equilibrium
starttime=time.time()
res=eq.equilib_batch(DB,NTP)
duration= time.time()-starttime
dftime=pl.DataFrame({'Time, s':duration})
# Step 4: Post processing
print('Total processing time:',timedelta(seconds=duration))
df=pl.DataFrame(res.to_dict())
df.write_csv(f'Result_Ex03_{system}.csv')
Scheil-Gulliver solidification
equilipy
offers phase stability calculations during Scheil-Gulliver solidification. The calculation procedure is similar to that of phase equilibrium calculation except for Step 3. The example is given in Example05
import numpy as np, matplotlib.pyplot as plt, polars as pl
import equilipy as eq
if __name__ == "__main__":
# Step 1: Parse database
datafile= './Database/AlCuMgSi_ORNL'
DB=eq.read_dat(datafile+'.dat')
# Step 2: Set input data
system=['Al','Cu','Mg','Si']
NTP = dict({
'T':1000,
'P': 1,
'Al':0.75,
'Cu': 0.05,
'Mg':0.1,
'Si': 0.1})
# Step 3: Calculate Scheil cooling based on LIQUID as target phase
TargetPhase='LIQUID'
res=eq.scheil_cooling(TargetPhase,DB,NTP,dT=10)
# Step 4: Post processing
print('Scheil Constituent information, mol. fr.:', res.ScheilConstituents)
df=pl.DataFrame(res.to_dict())
df.write_csv(f'Result_Ex05_ACMS.csv')
# Plot Phase amount as function of temperature
T= np.array(res.T)
phases=list(res.ScheilPhases.keys())
fig, ax = plt.subplots(figsize=(5,4))
for phase in phases:
plt.plot(T,res.ScheilPhases[phase],'-',linewidth=3,label=phase)
ax.legend(fontsize=14)
ax.set_xlabel('Temperature, K', fontsize=16)
ax.set_ylabel('Phase amount, mol', fontsize=16)
plt.tight_layout()
plt.show()