Пример #1
0
def cluster():
    from matplotlib import pyplot as plt
    fig_free = plt.figure()
    ax_free = fig_free.add_subplot(1, 1, 1)
    ax_entropy = ax_free.twinx()
    colors = ["#5D5C61", "#379683", "#7395AE", "#557A95", "#B1A296"]
    for col, db_name in zip(colors, DB_NAME_CLUSTER):
        db = dataset.connect(db_name)
        energy = []
        temperature = []
        tbl = db["thermodynamic"]
        for row in tbl.find():
            energy.append(row["energy"])
            temperature.append(row["temperature"])
        comp = {"Al": 0.75, "Mg": 0.25}
        free_eng = CanonicalFreeEnergy(comp, limit="lte")

        T, U, F = free_eng.get(temperature, energy)

        S = (U - F) / T

        # Plot free energy
        ax_free.plot(T,
                     F - F[0],
                     marker="o",
                     mfc="none",
                     color=col,
                     label=size[db_name])
        ax_entropy.plot(T, S * 1000.0, marker="v", mfc="none", color=col)
    ax_free.set_xlabel("Temperature (K)")
    ax_free.set_ylabel("Free energy change (eV)")
    ax_free.legend(loc="best", frameon=False)
    ax_entropy.set_ylabel("Entropy (meV/K)")
Пример #2
0
def get_free_energies():
    db = dataset.connect("sqlite:///" + mc_db_name)
    tbl = db["systems"]
    result = {}
    res_tbl = db["results"]
    for row in tbl.find(status="finished"):
        formula = get_formula(row["mg_conc"], row["si_conc"])
        internal_energy = []
        temperature = []
        mg_conc = row["mg_conc"]
        si_conc = row["si_conc"]
        conc = {"Mg": mg_conc, "Si": si_conc, "Al": 1.0 - mg_conc - si_conc}
        n_atoms = 1000
        for resrow in res_tbl.find(sysID=row["id"]):
            internal_energy.append(resrow["internal_energy"] / n_atoms)
            temperature.append(resrow["temperature"])
        free_eng = CanonicalFreeEnergy(conc)
        temp, internal, F = free_eng.get(temperature, internal_energy)
        result[formula] = {}
        result[formula]["temperature"] = temp
        result[formula]["internal_energy"] = internal
        result[formula]["free_energy"] = F
        result[formula]["entropy"] = (internal - F) / temp
        result[formula]["TS"] = internal - F
        result[formula]["conc"] = conc
    return result
Пример #3
0
def get_free_energies(mfa=False):
    """
    Compute the Free Energy for all entries in the database
    """
    unique_formulas = []
    db = connect(mc_db_name)
    for row in db.select(converged=1):
        if (row.formula not in unique_formulas):
            unique_formulas.append(row.formula)

    result = {}
    for formula in unique_formulas:
        conc = None
        internal_energy = []
        temperature = []
        for row in db.select(formula=formula, converged=1):
            if (conc is None):
                count = row.count_atoms()
                conc = {}
                for key, value in count.iteritems():
                    conc[key] = float(value) / row.natoms
            internal_energy.append(
                row.internal_energy /
                row.natoms)  # Normalize by the number of atoms
            temperature.append(row.temperature)
        free_eng = CanonicalFreeEnergy(conc)
        temp, internal, F = free_eng.get(temperature, internal_energy)
        result[formula] = {}
        result[formula]["temperature"] = temp
        result[formula]["internal_energy"] = internal
        result[formula]["free_energy"] = F
        result[formula]["conc"] = conc
        result[formula]["entropy"] = (internal - F) / temp
        result[formula]["TS"] = internal - F
    return result
Пример #4
0
def free_energy_of_formation(db_name, ref_energy):
    """Computes the free energy of formation."""
    db = dataset.connect("sqlite:///{}".format(db_name))
    tbl = db["results"]
    temps = [800, 700, 600, 500, 400, 300, 200, 100]
    concs = np.arange(0.05, 1, 0.05)
    all_F = {}
    c_found = []
    for c in concs:
        statement = "SELECT temperature, energy FROM results WHERE al_conc > {} AND al_conc < {}".format(c-0.01, c+0.01)
        T = []
        U = []
        for res in db.query(statement):
            T.append(res["temperature"])
            U.append(res["energy"]/1000.0)
        comp = {"Al": c, "Zn": 1-c}
        if not T:
            continue
        c_found.append(c)
        free_eng = CanonicalFreeEnergy(comp)
        T, U, F = free_eng.get(T, U)
        for temp, f in zip(list(T), list(F)):
            if temp not in all_F.keys():
                all_F[temp] = [f]
            else:
                all_F[temp].append(f)
    cmap = mpl.cm.copper
    norm = mpl.colors.Normalize(vmin=np.min(temps), vmax=np.max(temps))
    scalar_map = mpl.cm.ScalarMappable(cmap=cmap, norm=norm)
    scalar_map.set_array(temps)

    fig = plt.figure()
    ax = fig.add_subplot(1, 1, 1)
    concs = np.array(c_found)
    for T in temps:
        f_form = np.array(all_F[T]) - concs * ref_energy["Al"] - (1.0-concs)*ref_energy["Zn"]
        f_form *= mol/kJ
        f_form = f_form.tolist()
        f_form.insert(0, 0)
        f_form.append(0)
        ax.plot([0.0]+concs.tolist()+[1.0], f_form, color=scalar_map.to_rgba(T), marker="^")
    ax.set_xlabel("Al concentration")
    ax.set_ylabel("Free energy of formation (kJ/mol)")
    ax.spines["right"].set_visible(False)
    ax.spines["top"].set_visible(False)
    ax_divider = make_axes_locatable(ax)
    c_ax = ax_divider.append_axes("top", size="7%", pad="2%")
    cb = fig.colorbar(scalar_map, orientation="horizontal", cax=c_ax)
    cb.ax.xaxis.set_ticks_position('top')
    cb.ax.xaxis.set_label_position('top')
    cb.set_label("Temperature (K)")
    plt.show()
    def test_free_energy(self):
        if (not available):
            self.skipTest("Test not available")
            return
        T = np.linspace(100, 1000, 40)
        energy = 0.1 * T**2

        msg = ""
        no_throw = True
        comp = {"Al": 0.5, "Mg": 0.5}
        try:
            free_eng = CanonicalFreeEnergy(comp)
            temp, U, F = free_eng.get(T, energy)
        except Exception as exc:
            msg = str(exc)
            no_throw = False
        self.assertTrue(no_throw, msg=msg)
Пример #6
0
def pure_phase():
    from matplotlib import pyplot as plt
    db = dataset.connect(DB_NAME_PURE)
    energy = []
    temperature = []
    order_param = []
    tbl = db["thermodynamic"]
    for row in tbl.find():
        energy.append(row["energy"])
        temperature.append(row["temperature"])
        order_param.append(row["site_order"])
    comp = {"Al": 0.75, "Mg": 0.25}
    free_eng = CanonicalFreeEnergy(comp, limit="lte")

    T, U, F = free_eng.get(temperature, energy)
    S = (U - F) / T

    F *= (4.0 / 1000.0)  # Convert to per f.u.
    S *= (4.0 / 1000.0)  # Convert to per f.u.

    # Plot the order parameter
    f = 1.0 - (np.array(order_param) / 1000.0) * 8.0 / 3.0
    fig_order = plt.figure()
    ax_order = fig_order.add_subplot(1, 1, 1)
    ax_order.plot(temperature, f, marker="o", mfc="none", color="#5D5C61")
    ax_order.set_xlabel("Temperature (K)")
    ax_order.set_ylabel("Order parameter")
    ax_order.spines["right"].set_visible(False)
    ax_order.spines["top"].set_visible(False)

    # Plot free energy
    fig_free = plt.figure()
    ax_free = fig_free.add_subplot(1, 1, 1)
    ax_free.plot(T, (F - F[0]) * 1000.0,
                 marker="o",
                 mfc="none",
                 color="#557A95")
    ax_entropy = ax_free.twinx()
    ax_entropy.plot(T, S * 1000.0, marker="v", mfc="none", color="#5D5C61")
    #ax_free.axvline(x=293, ls="--", color="#B1A296")
    ax_free.set_xlabel("Temperature (K)")
    ax_free.set_ylabel("Free energy change (meV/f.u.)")
    ax_entropy.set_ylabel("Entropy (meV/f.u./K)")
Пример #7
0
def free_energy_vs_size(temps=[293, 353]):
    db_name = "sqlite:///data/heat_almg_cluster_size_all_size.db"
    outfname = "data/almg_review/free_energy_size.json"
    sizes = range(3, 51)
    db = dataset.connect(db_name)
    tbl = db["thermodynamic"]
    free_energies = {int(T): [] for T in temps}
    entropy = {int(T): [] for T in temps}
    internal_energy = {int(T): [] for T in temps}
    for size in sizes:
        energy = []
        temperature = []
        for row in tbl.find(size=size):
            energy.append(row["energy"])
            temperature.append(row["temperature"])
        energy = np.array(energy)
        temperature = np.array(temperature)
        indx = np.argsort(temperature)
        temperature = temperature[indx]
        energy = energy[indx]
        comp = {"Al": 0.75, "Mg": 0.25}
        free_eng = CanonicalFreeEnergy(comp, limit="lte")
        T, U, F = free_eng.get(temperature, energy)
        S = (U - F) / T
        for target_temp in temps:
            indx = np.argmin(np.abs(target_temp - T))
            free_energies[target_temp].append(F[indx])
            internal_energy[target_temp].append(U[indx])
            entropy[target_temp].append(S[indx])

    data = {}
    data["sizes"] = list(sizes)
    data["free_energy"] = free_energies
    data["entropy"] = entropy
    data["internal_energy"] = internal_energy
    # for target_temp in temps:
    #     free_energies[target_temp] = list(free_energies[target_temp])

    with open(outfname, 'w') as outfile:
        json.dump(data, outfile)
    print("Free energies written to {}".format(outfname))
Пример #8
0
def update_entries():
    db = dataset.connect("sqlite:///{}".format(db_name))

    # Find all unique compositions in the db
    statement = "SELECT au_conc FROM results"
    concs = []
    for conc in db.query(statement):
        concs.append(float(conc["au_conc"]))
    concs = np.array(concs)
    concs *= 100
    concs = concs.astype(np.int32)
    concs = np.unique(concs) / 100.0

    tbl = db["results"]
    # concs = [0.1, 0.3, 0.95]
    for c in list(concs):
        sql = "SELECT id, temperature, energy FROM results WHERE au_conc > {} AND au_conc < {}".format(
            c - 0.01, c + 0.01)
        T = []
        U = []
        for res in db.query(sql):
            T.append(res["temperature"])
            U.append(res["energy"] / 1000.0)

        comp = {"Au": c, "Cu": 1 - c}
        free_eng = CanonicalFreeEnergy(comp)
        T, U, F = free_eng.get(T, U)

        for temp, u, f in zip(list(T), list(U), list(F)):
            # Update the database
            sql = "SELECT id FROM results WHERE au_conc > {} AND au_conc < {} AND temperature={}".format(
                c - 0.01, c + 0.01, temp)
            res = db.query(sql)
            uid = res.next()["id"]
            new_cols = {"id": uid, "free_energy": f, "entropy": (u - f) / temp}
            tbl.update(new_cols, ["id"])
Пример #9
0
# This file contains the data from a fictitous MC simulation
# The file has two columns separated by comma
# The first is tempeature the second is internal energy
fname = "examples/free_energy_data.csv"
n_atoms = 1000  # The MC simulation of the data in the file used 1000 atoms

# The chemical formula of the system in the file was Al750Mg250
conc = {
    "Mg":0.25,
    "Al":0.75
}

# Import the Canonical Free Energy class
from cemc.tools import CanonicalFreeEnergy

free_eng = CanonicalFreeEnergy(conc)

import numpy as np
temperature, internal_energy = np.loadtxt( fname, delimiter=",", unpack=True )

# The function also return internal energy and temperature
# Because the data in a file might not be sorted
# In the case of unsorted data the function will sort the data
temperature,internal_energy,helmholtz_free_energy = free_eng.get( temperature, internal_energy/n_atoms )

entropy = (internal_energy-helmholtz_free_energy)/temperature
enthalpy = helmholtz_free_energy + temperature*entropy

# Plot the results
from matplotlib import pyplot as plt
fig, ax = plt.subplots( ncols=2, nrows=2 )