import numpy as np
import matplotlib.pyplot as plt
from pycalphad import Database, binplot, variables as v
from pycalphad.core.utils import extract_parameters
from espei.datasets import load_datasets, recursive_glob
from espei.error_functions.zpf_error import get_zpf_data, calculate_zpf_driving_forces
= Database("Cr-Ni_mcmc.tdb")
dbf = ["CR", "NI", "VA"]
comps = list(dbf.phases.keys())
phases = v.X("NI") # binary assumed
indep_comp_cond = {v.N: 1, v.P: 101325, v.T: (500, 2200, 20), indep_comp_cond: (0, 1, 0.01)}
conditions = {} # e.g. {"VV0001": 10000.0}, if empty, will use the current database parameters
parameters
# Get the datasets, construct ZPF data and compute driving forces
# Driving forces and weights are ragged 2D arrays of shape (len(zpf_data), len(vertices in each zpf_data))
= load_datasets(recursive_glob("input-data"))
datasets = get_zpf_data(dbf, comps, phases, datasets, parameters=parameters)
zpf_data = extract_parameters(parameters)[1]
param_vec = calculate_zpf_driving_forces(zpf_data, param_vec)
driving_forces, weights
# Construct the plotting compositions, temperatures and driving forces
# Each should have len() == (number of vertices)
# Driving forces already have the vertices unrolled so we can concatenate directly
= []
Xs = []
Ts = []
dfs for data, data_driving_forces in zip(zpf_data, driving_forces):
# zpf_data have (ragged) shape (len(datasets), len(phase_regions), len(vertices))
# while driving_forces have (ragged) shape (len(datasets), len(vertices)), concatenating along the phase regions dimension
# so we need an offset to account for phase veritices from previous phase regions
= 0
driving_force_offset for phase_region in data["phase_regions"]:
for vertex, df in zip(phase_region.vertices, data_driving_forces[driving_force_offset:]):
+= 1
driving_force_offset = vertex.comp_conds
comp_cond if vertex.has_missing_comp_cond:
# No composition to plot
continue
dfs.append(df)
Ts.append(phase_region.potential_conds[v.T])# Binary assumptions here
assert len(comp_cond) == 1
if indep_comp_cond in comp_cond:
Xs.append(comp_cond[indep_comp_cond])else:
# Switch the dependent and independent component
1.0 - tuple(comp_cond.values())[0])
Xs.append(
# Plot the phase diagram with driving forces
= plt.subplots(dpi=100, figsize=(8,4))
fig, ax =dict(ax=ax), eq_kwargs={"parameters": parameters})
binplot(dbf, comps, phases, conditions, plot_kwargs= plt.cm.ScalarMappable(cmap="hot")
sm
sm.set_array(dfs)=dfs, cmap="hot", edgecolors="k")
ax.scatter(Xs, Ts, c=ax, pad=0.25, label="Driving Force")
fig.colorbar(sm, ax fig.show()
Plot ZPF Driving Forces
This visualization can be used as a diagnostic for understanding which ZPF data are contributing the most driving force towards the likelihood. Note that these driving forces are unweighted, since the weight is applied when computing the log-likelihood of each driving force.