Beispiel #1
0
def test_equilibrium_raises_when_no_phases_can_be_active():
    """Equliibrium raises when the components passed cannot give any active phases"""
    # all phases contain AL and/or FE in a sublattice, so no phases can be active
    equilibrium(ALFE_DBF, ['VA'], list(ALFE_DBF.phases.keys()), {
        v.T: 300,
        v.P: 101325
    })
Beispiel #2
0
def test_equilibrium_raises_with_no_active_phases_passed():
    """Passing inactive phases to equilibrium raises a ConditionError."""
    # the only phases passed are the disordered phases, which are inactive
    equilibrium(ALNIFCC4SL_DBF, ['AL', 'NI', 'VA'], ['FCC_A1', 'BCC_A2'], {
        v.T: 300,
        v.P: 101325
    })
Beispiel #3
0
def test_eq_overdetermined_comps():
    """
    The number of composition conditions should yield exactly one dependent component.
    This is the overdetermined case.
    """
    equilibrium(ALFE_DBF, ['AL', 'FE'], 'LIQUID', {v.T: 2000, v.P: 101325,
                                                   v.X('FE'): 0.2, v.X('AL'): 0.8})
def test_eq_overdetermined_comps():
    """
    The number of composition conditions should yield exactly one dependent component.
    This is the overdetermined case.
    """
    equilibrium(ALFE_DBF, ['AL', 'FE'], 'LIQUID', {v.T: 2000, v.P: 101325,
                                                   v.X('FE'): 0.2, v.X('AL'): 0.8}, pbar=False)
def test_eq_on_endmember():
    """
    When the composition condition is right on top of an end-member
    the convex hull is still correctly constructed (gh-28).
    """
    equilibrium(ALFE_DBF, ['AL', 'FE', 'VA'], ['LIQUID', 'B2_BCC'],
                {v.X('AL'): [0.4, 0.5, 0.6], v.T: [300, 600], v.P: 101325}, pbar=False)
def test_eq_b2_without_all_comps():
    """
    All-vacancy endmembers are correctly excluded from the computation when fewer than
    all components in a Database are selected for the calculation.
    """
    equilibrium(Database(ALNIPT_TDB), ['AL', 'NI', 'VA'], 'BCC_B2', {v.X('NI'): 0.4, v.P: 101325, v.T: 1200},
                verbose=True, pbar=False)
def test_eq_on_endmember():
    """
    When the composition condition is right on top of an end-member
    the convex hull is still correctly constructed (gh-28).
    """
    equilibrium(ALFE_DBF, ['AL', 'FE', 'VA'], ['LIQUID', 'B2_BCC'],
                {v.X('AL'): [0.4, 0.5, 0.6], v.T: [300, 600], v.P: 101325}, verbose=True)
def test_eq_output_property():
    """
    Extra properties can be specified to `equilibrium`.
    """
    equilibrium(ALFE_DBF, ['AL', 'FE', 'VA'], ['LIQUID', 'B2_BCC'],
                {v.X('AL'): 0.25, v.T: (300, 2000, 500), v.P: 101325},
                output=['heat_capacity', 'degree_of_ordering'], pbar=False)
def test_eq_output_property():
    """
    Extra properties can be specified to `equilibrium`.
    """
    equilibrium(ALFE_DBF, ['AL', 'FE', 'VA'], ['LIQUID', 'B2_BCC'],
                {v.X('AL'): 0.25, v.T: (300, 2000, 500), v.P: 101325},
                output=['heat_capacity', 'degree_of_ordering'])
Beispiel #10
0
def test_equlibrium_no_opt_solver():
    """Passing in a solver with `ignore_convergence = True` gives a result."""
    class NoOptSolver(InteriorPointSolver):
        ignore_convergence = True

    comps = ['PB', 'SN', 'VA']
    phases = list(PBSN_DBF.phases.keys())
    conds = {v.T: 300, v.P: 101325, v.X('SN'): 0.50}
    ipopt_solver_eq_res = equilibrium(PBSN_DBF,
                                      comps,
                                      phases,
                                      conds,
                                      solver=InteriorPointSolver(),
                                      verbose=True)
    no_opt_eq_res = equilibrium(PBSN_DBF,
                                comps,
                                phases,
                                conds,
                                solver=NoOptSolver(),
                                verbose=True)

    ipopt_GM = ipopt_solver_eq_res.GM.values.squeeze()
    no_opt_GM = no_opt_eq_res.GM.values.squeeze()
    no_opt_MU = no_opt_eq_res.MU.values.squeeze()
    assert ipopt_GM != no_opt_GM  # global min energy is different from lower convex hull
    assert np.allclose([-17452.5115967],
                       no_opt_GM)  # energy from lower convex hull
    assert np.allclose([-19540.6522632, -15364.3709302],
                       no_opt_MU)  # chempots from lower convex hull
Beispiel #11
0
 def time_equilibrium_al_fe(self):
     equilibrium(self.db_alni, ['AL', 'NI', 'VA'], ['LIQUID', 'FCC_L12'], {
         v.X('AL'): 0.10,
         v.T: (300, 2500, 20),
         v.P: 101325
     },
                 pbar=False)
Beispiel #12
0
 def time_equilibrium_al_ni(self):
     equilibrium(self.db_alfe, ['AL', 'FE', 'VA'], ['LIQUID', 'B2_BCC'], {
         v.X('AL'): 0.25,
         v.T: (300, 2000, 50),
         v.P: 101325
     },
                 pbar=False)
def test_eq_unary_issue78():
    "Unary equilibrium calculations work with property calculations."
    eq = equilibrium(ALFE_DBF, ['AL', 'VA'], 'FCC_A1', {v.T: 1200, v.P: 101325}, output='SM')
    np.testing.assert_allclose(eq.SM, 68.143273)
    eq = equilibrium(ALFE_DBF, ['AL', 'VA'], 'FCC_A1', {v.T: 1200, v.P: 101325}, output='SM', parameters={'GHSERAL': 1000})
    np.testing.assert_allclose(eq.GM, 1000)
    np.testing.assert_allclose(eq.SM, 0)
def test_eq_b2_without_all_comps():
    """
    All-vacancy endmembers are correctly excluded from the computation when fewer than
    all components in a Database are selected for the calculation.
    """
    equilibrium(Database(ALNIPT_TDB), ['AL', 'NI', 'VA'], 'BCC_B2', {v.X('NI'): 0.4, v.P: 101325, v.T: 1200},
                verbose=True)
def test_eq_underdetermined_comps():
    """
    The number of composition conditions should yield exactly one dependent component.
    This is the underdetermined case.
    """
    with pytest.raises(ValueError):
        equilibrium(ALFE_DBF, ['AL', 'FE'], 'LIQUID', {v.T: 2000, v.P: 101325})
Beispiel #16
0
def test_eq_missing_component():
    """
    Specifying a condition involving a non-existent component raises an error.
    """
    # No Co or Cr in this database ; Co condition specification should cause failure
    equilibrium(ALNIFCC4SL_DBF, ['AL', 'NI', 'VA'], ['LIQUID'],
                {v.T: 1523, v.X('AL'): 0.88811111111111107,
                 v.X('CO'): 0.11188888888888888, v.P: 101325})
def test_eq_avoid_phase_cycling():
    """
    Converge without getting stuck in an add/remove phase cycle.
    """
    # This set of conditions is known to trigger the issue
    my_phases_alfe = ['LIQUID', 'B2_BCC', 'FCC_A1', 'HCP_A3', 'AL5FE2', 'AL2FE', 'AL13FE4', 'AL5FE4']
    equilibrium(ALFE_DBF, ['AL', 'FE', 'VA'], my_phases_alfe, {v.X('AL'): 0.44,
                                                               v.T: 1600, v.P: 101325}, verbose=True)
Beispiel #18
0
def test_eq_missing_component():
    """
    Specifying a condition involving a non-existent component raises an error.
    """
    # No Co or Cr in this database ; Co condition specification should cause failure
    equilibrium(ALNIFCC4SL_DBF, ['AL', 'NI', 'VA'], ['LIQUID'],
                {v.T: 1523, v.X('AL'): 0.88811111111111107,
                 v.X('CO'): 0.11188888888888888, v.P: 101325}, pbar=False)
def test_unused_equilibrium_kwarg_warns():
    "Check that an unused keyword argument raises a warning"
    with warnings.catch_warnings(record=True) as w:
        equilibrium(ALFE_DBF, ['AL', 'FE', 'VA'], 'FCC_A1', {v.T: 1300, v.P: 101325, v.X('AL'): 0}, unused_kwarg='should raise a warning')
        assert len(w) >= 1
        categories = [warning.__dict__['_category_name'] for warning in w]
        assert 'UserWarning' in categories
        expected_string_fragment = 'keyword arguments were passed, but unused'
        assert any([expected_string_fragment in str(warning.message) for warning in w])
Beispiel #20
0
def test_dilute_condition():
    """
    'Zero' and dilute composition conditions are correctly handled.
    """
    eq = equilibrium(ALFE_DBF, ['AL', 'FE', 'VA'], 'FCC_A1', {v.T: 1300, v.P: 101325, v.X('AL'): 0}, verbose=True)
    assert_allclose(np.squeeze(eq.GM.values), -64415.84, atol=0.1)
    eq = equilibrium(ALFE_DBF, ['AL', 'FE', 'VA'], 'FCC_A1', {v.T: 1300, v.P: 101325, v.X('AL'): 1e-12}, verbose=True)
    assert_allclose(np.squeeze(eq.GM.values), -64415.841)
    assert_allclose(np.squeeze(eq.MU.values), [-385499.682936,  -64415.837878], atol=1.0)
Beispiel #21
0
def test_eq_some_phases_filtered():
    """
    Phases are filtered out from equilibrium() when some cannot be built.
    """
    # should not raise; AL13FE4 should be filtered out
    equilibrium(ALFE_DBF, ['AL', 'VA'], ['FCC_A1', 'AL13FE4'], {
        v.T: 1200,
        v.P: 101325
    })
Beispiel #22
0
def test_dilute_condition():
    """
    'Zero' and dilute composition conditions are correctly handled.
    """
    eq = equilibrium(ALFE_DBF, ["AL", "FE", "VA"], "FCC_A1", {v.T: 1300, v.P: 101325, v.X("AL"): 0}, pbar=False)
    assert_allclose(np.squeeze(eq.GM.values), -64415.84, atol=0.1)
    eq = equilibrium(ALFE_DBF, ["AL", "FE", "VA"], "FCC_A1", {v.T: 1300, v.P: 101325, v.X("AL"): 1e-8}, pbar=False)
    assert_allclose(np.squeeze(eq.GM.values), -64415.84069827)
    assert_allclose(eq.MU.values, [[[[-335723.04320981, -64415.8379852]]]], atol=0.1)
Beispiel #23
0
def test_equilibrium_raises_with_invalid_solver():
    """
    SolverBase instances passed to equilibrium should raise an error.
    """
    equilibrium(CUO_DBF, ['O'],
                'GAS', {
                    v.T: 1000,
                    v.P: 1e5
                },
                solver=SolverBase())
def test_dilute_condition():
    """
    'Zero' and dilute composition conditions are correctly handled.
    """
    eq = equilibrium(ALFE_DBF, ['AL', 'FE', 'VA'], 'FCC_A1', {v.T: 1300, v.P: 101325, v.X('AL'): 0}, verbose=True)
    assert_allclose(np.squeeze(eq.GM.values), -64415.84, atol=0.1)
    eq = equilibrium(ALFE_DBF, ['AL', 'FE', 'VA'], 'FCC_A1', {v.T: 1300, v.P: 101325, v.X('AL'): 1e-8}, verbose=True)
    # Checked in TC
    assert_allclose(np.squeeze(eq.GM.values), -64415.841)
    # We loosen the tolerance a bit here because our convergence tolerance is too low for the last digit
    assert_allclose(np.squeeze(eq.MU.values), [-335723.28,  -64415.838], atol=1.0)
def test_eq_underdetermined_comps():
    """
    The number of composition conditions should yield exactly one dependent component.
    This is the underdetermined case.
    """
    equilibrium(ALFE_DBF, ['AL', 'FE'],
                'LIQUID', {
                    v.T: 2000,
                    v.P: 101325
                },
                pbar=False)
Beispiel #26
0
def test_missing_models_with_phase_records_passed_to_equilibrium_raises():
    "equilibrium should raise an error if all the active phases are not included in the phase_records"
    my_phases = ['LIQUID', 'FCC_A1', 'HCP_A3', 'AL5FE2', 'AL2FE', 'AL13FE4', 'AL5FE4']
    comps = ['AL', 'FE', 'VA']
    conds = {v.T: 1400, v.P: 101325, v.N: 1.0, v.X('AL'): 0.55}

    models = instantiate_models(ALFE_DBF, comps, my_phases)
    phase_records = build_phase_records(ALFE_DBF, comps, my_phases, conds, models)

    with pytest.raises(ValueError):
        # model=models NOT passed
        equilibrium(ALFE_DBF, comps, my_phases, conds, verbose=True, phase_records=phase_records)
Beispiel #27
0
def test_eq_output_property():
    """
    Extra properties can be specified to `equilibrium`.
    """
    equilibrium(
        ALFE_DBF,
        ["AL", "FE", "VA"],
        ["LIQUID", "B2_BCC"],
        {v.X("AL"): 0.25, v.T: (300, 2000, 500), v.P: 101325},
        output=["heat_capacity", "degree_of_ordering"],
        pbar=False,
    )
Beispiel #28
0
def test_eq_on_endmember():
    """
    When the composition condition is right on top of an end-member
    the convex hull is still correctly constructed (gh-28).
    """
    equilibrium(
        ALFE_DBF,
        ["AL", "FE", "VA"],
        ["LIQUID", "B2_BCC"],
        {v.X("AL"): [0.4, 0.5, 0.6], v.T: [300, 600], v.P: 101325},
        pbar=False,
    )
Beispiel #29
0
def test_eq_missing_component():
    """
    Specifying a condition involving a non-existent component raises an error.
    """
    # No Co or Cr in this database ; Co condition specification should cause failure
    equilibrium(
        ALNIFCC4SL_DBF,
        ["AL", "NI", "VA"],
        ["LIQUID"],
        {v.T: 1523, v.X("AL"): 0.88811111111111107, v.X("CO"): 0.11188888888888888, v.P: 101325},
        pbar=False,
    )
Beispiel #30
0
def test_eq_gas_phase():
    eq = equilibrium(CUO_DBF, ['O'],
                     'GAS', {
                         v.T: 1000,
                         v.P: 1e5
                     },
                     verbose=True)
    np.testing.assert_allclose(eq.GM, -110380.61071, atol=0.1)
    eq = equilibrium(CUO_DBF, ['O'],
                     'GAS', {
                         v.T: 1000,
                         v.P: 1e9
                     },
                     verbose=True)
    np.testing.assert_allclose(eq.GM, -7.20909E+04, atol=0.1)
def test_eq_issue62_last_component_not_va():
    """
    VA is not last when components are sorted alphabetically.
    """
    test_tdb = """
    ELEMENT VA   VACUUM                    0.0000E+00  0.0000E+00  0.0000E+00!
    ELEMENT AL   FCC_A1                    2.6982E+01  4.5773E+03  2.8322E+01!
    ELEMENT CO   HCP_A3                    5.8933E+01  4.7656E+03  3.0040E+00!
    ELEMENT CR   BCC_A2                    5.1996E+01  4.0500E+03  2.3560E+01!
    ELEMENT W    BCC_A2                    1.8385E+02  4.9700E+03  3.2620E+01!
    PHASE FCC_A1  %  2 1   1 !
    CONSTITUENT FCC_A1  :AL,CO,CR,W : VA% :  !
    """
    equilibrium(Database(test_tdb), ['AL', 'CO', 'CR', 'W', 'VA'], ['FCC_A1'],
                {"T": 1248, "P": 101325, v.X("AL"): 0.081, v.X("CR"): 0.020, v.X("W"): 0.094})
Beispiel #32
0
def plot_convex_hull(dbf, comps, phases, conds, ax=None):
    if ax is None:
        ax = plt.gca()

    result = equilibrium(dbf, comps, phases, conds)
    unique_phase_sets = np.unique(result['Phase'].values.squeeze(), axis=0)

    comp_cond = [c for c in conds.keys() if isinstance(c, v.X)]
    if len(comp_cond) != 1:
        raise ValueError(
            f"Exactly one composition condition required for plotting convex hull. Got {len(comp_cond)} with conditions for {comp_cond}"
        )
    comp_cond = str(comp_cond[0])

    for phase_set in unique_phase_sets:
        label = '+'.join([ph for ph in phase_set if ph != ''])
        # composition indices with the same unique phase
        unique_phase_idx = np.nonzero(
            np.all(result['Phase'].values.squeeze() == phase_set, axis=1))[0]
        masked_result = result.isel(**{comp_cond: unique_phase_idx})
        ax.plot(masked_result[comp_cond].squeeze(),
                masked_result.GM.squeeze(),
                color='limegreen',
                linestyle=':',
                lw=4,
                label='convex hull',
                zorder=3)
    return ax
Beispiel #33
0
def test_eq_charge_ndzro():
    """Nd-Zr-O system (with charged species) are correctly calculated and charged balanced in equilibrium"""
    comps = ['ND', 'ZR', 'O', 'VA']
    phases = ['ND2O3_A', 'PYRO']
    conds = {v.P: 101325, v.N: 1, v.T: 1400, v.X('ND'): 0.25, v.X('O'): 0.625}
    # Higher point density is required for convergence. Lower point densities
    # Can result in either no phases, or only FLUO phase (incorrect)
    res = equilibrium(AL2O3_ND2O3_ZRO2_DBF, comps, phases, conds, verbose=True)
    # Values below checked with Thermo-Calc
    assert np.isclose(-432325.423784, res.GM.values.squeeze())
    assert np.all(res.Phase.values.squeeze() == np.array(['ND2O3_A', 'PYRO', '', '']))
    assert np.allclose(res.NP.values.squeeze()[:2], [0.30164254, 0.69835646])
    # site fractions of ND2O3_A
    Y_ND2O3_A = res.Y.values.squeeze()[0, :5]
    Y_PYRO = res.Y.values.squeeze()[1, :]
    SPEC_CHG_ND2O3_A = np.array([3, 4, -2, -2, 0])  # (ND+3,ZR+4):(O-2):(O-2,VA)
    SITE_RATIO_ND2O3_A = np.array([2, 2, 3, 1, 1])  # 2:3:1
    SPEC_CHG_PYRO = np.array([3, 4, 3, 4, -2, 0, -2, -2, 0])  # (ND+3,ZR+4):(ND+3,ZR+4):(O-2,VA):(O-2):(O-2,VA)
    SITE_RATIO_PYRO = np.array([2, 2, 2, 2, 6, 6, 1, 1, 1])  # 2:2:6:1:1
    CHG_ND2O3_A = np.dot(Y_ND2O3_A*SPEC_CHG_ND2O3_A, SITE_RATIO_ND2O3_A)
    CHG_PYRO = np.dot(Y_PYRO*SPEC_CHG_PYRO, SITE_RATIO_PYRO)
    print('CHARGE ND2O3_A', CHG_ND2O3_A)
    print('CHARGE PYRO', CHG_PYRO)
    assert np.isclose(CHG_ND2O3_A, 0)
    assert np.isclose(CHG_PYRO, 0)
    assert np.allclose(Y_ND2O3_A, [9.79497936e-01, 2.05020639e-02, 1.00000000e+00, 2.05020639e-02, 9.79497936e-01],
                       rtol=5e-4)
    assert np.allclose(Y_PYRO, [9.99970071e-01, 2.99288042e-05, 3.83395063e-02, 9.61660494e-01, 9.93381787e-01,
                                6.61821340e-03, 1.00000000e+00, 1.39970285e-03, 9.98600297e-01], rtol=5e-4)
def test_eq_model_phase_name():
    """
    Phase name is set in PhaseRecord when using Model-based JIT compilation.
    """
    eq = equilibrium(ALFE_DBF, ['AL', 'FE', 'VA'], 'LIQUID',
                     {v.X('FE'): 0.3, v.T: 1000, v.P: 101325}, model=Model)
    assert eq.Phase.sel(vertex=0).isel(T=0, P=0, X_FE=0) == 'LIQUID'
Beispiel #35
0
def test_eq_binary():
    "Binary phase diagram point equilibrium calculation with magnetism."
    my_phases = ["LIQUID", "FCC_A1", "HCP_A3", "AL5FE2", "AL2FE", "AL13FE4", "AL5FE4"]
    comps = ["AL", "FE", "VA"]
    conds = {v.T: 1400, v.P: 101325, v.X("AL"): 0.55}
    eqx = equilibrium(ALFE_DBF, comps, my_phases, conds, pbar=False)
    assert_allclose(eqx.GM.values.flat[0], -9.608807e4)
Beispiel #36
0
def estimate_hyperplane(dbf, comps, phases, current_statevars, comp_dicts, phase_models, parameters):
    region_chemical_potentials = []
    parameters = OrderedDict(sorted(parameters.items(), key=str))
    for cond_dict, phase_flag in comp_dicts:
        # We are now considering a particular tie vertex
        for key, val in cond_dict.items():
            if val is None:
                cond_dict[key] = np.nan
        cond_dict.update(current_statevars)
        if np.any(np.isnan(list(cond_dict.values()))):
            # This composition is unknown -- it doesn't contribute to hyperplane estimation
            pass
        else:
            # Extract chemical potential hyperplane from multi-phase calculation
            # Note that we consider all phases in the system, not just ones in this tie region
            multi_eqdata = equilibrium(dbf, comps, phases, cond_dict, verbose=False,
                                       model=phase_models, scheduler=dask.local.get_sync, parameters=parameters)
            # Does there exist only a single phase in the result with zero internal degrees of freedom?
            # We should exclude those chemical potentials from the average because they are meaningless.
            num_phases = len(np.squeeze(multi_eqdata['Phase'].values != ''))
            zero_dof = np.all((multi_eqdata['Y'].values == 1.) | np.isnan(multi_eqdata['Y'].values))
            if (num_phases == 1) and zero_dof:
                region_chemical_potentials.append(np.full_like(np.squeeze(multi_eqdata['MU'].values), np.nan))
            else:
                region_chemical_potentials.append(np.squeeze(multi_eqdata['MU'].values))
    region_chemical_potentials = np.nanmean(region_chemical_potentials, axis=0, dtype=np.float)
    return region_chemical_potentials
def test_eq_parameter_override():
    """
    Check that overriding parameters works in equilibrium().
    """
    comps = ["AL"]
    dbf = AL_PARAMETER_DBF
    phases = ['FCC_A1']
    conds = {v.P: 101325, v.T: 500}

    # Check that current database should work as expected
    eq_res = equilibrium(dbf, comps, phases, conds)
    np.testing.assert_allclose(eq_res.GM.values.squeeze(), 5000.0)

    # Check that overriding parameters works
    eq_res = equilibrium(dbf, comps, phases, conds, parameters={'VV0000': 10000})
    np.testing.assert_allclose(eq_res.GM.values.squeeze(), 10000.0)
Beispiel #38
0
def ternplot(dbf,
             comps,
             phases,
             conds,
             x=None,
             y=None,
             eq_kwargs=None,
             **plot_kwargs):
    """
    Calculate the ternary isothermal, isobaric phase diagram.
    This function is a convenience wrapper around equilibrium() and eqplot().

    Parameters
    ----------
    dbf : Database
        Thermodynamic database containing the relevant parameters.
    comps : list
        Names of components to consider in the calculation.
    phases : list
        Names of phases to consider in the calculation.
    conds : dict
        Maps StateVariables to values and/or iterables of values.
        For ternplot only one changing composition and one potential coordinate each is supported.
    x : Composition
        instance of a pycalphad.variables.composition to plot on the x-axis.
        Must correspond to an independent condition.
    y : Composition
        instance of a pycalphad.variables.composition to plot on the y-axis.
        Must correspond to an independent condition.
    eq_kwargs : optional
        Keyword arguments to equilibrium().
    plot_kwargs : optional
        Keyword arguments to eqplot().

    Returns
    -------
    A phase diagram as a figure.

    Examples
    --------
    None yet.
    """
    eq_kwargs = eq_kwargs if eq_kwargs is not None else dict()
    indep_comps = [
        key for key, value in conds.items()
        if isinstance(key, v.Composition) and len(np.atleast_1d(value)) > 1
    ]
    indep_pots = [
        key for key, value in conds.items()
        if ((key == v.T) or (key == v.P)) and len(np.atleast_1d(value)) > 1
    ]
    if (len(indep_comps) != 2) or (len(indep_pots) != 0):
        raise ValueError(
            'ternplot() requires exactly two composition coordinates')
    full_eq = equilibrium(dbf, comps, phases, conds, **eq_kwargs)
    # TODO: handle x and y as strings with #87
    x = x if x in indep_comps else indep_comps[0]
    y = y if y in indep_comps else indep_comps[1]
    return eqplot(full_eq, x=x, y=y, **plot_kwargs)
Beispiel #39
0
def test_eq_binary():
    "Binary phase diagram point equilibrium calculation with magnetism."
    my_phases = ['LIQUID', 'FCC_A1', 'HCP_A3', 'AL5FE2',
                 'AL2FE', 'AL13FE4', 'AL5FE4']
    comps = ['AL', 'FE', 'VA']
    conds = {v.T: 1400, v.P: 101325, v.X('AL'): 0.55}
    eqx = equilibrium(ALFE_DBF, comps, my_phases, conds, pbar=False)
    assert_allclose(eqx.GM.values.flat[0], -9.608807e4)
def test_equilibrium_result_dataset_can_serialize_to_netcdf():
    """
    The xarray Dataset returned by equilibrium should serializable to a netcdf file.
    """
    fname = 'eq_result_netcdf_test.nc'
    eq = equilibrium(ALFE_DBF, ['AL', 'VA'], 'FCC_A1', {v.T: 1200, v.P: 101325})
    eq.to_netcdf(fname)
    os.remove(fname)  # cleanup
def test_eq_binary():
    "Binary phase diagram point equilibrium calculation with magnetism."
    my_phases = ['LIQUID', 'FCC_A1', 'HCP_A3', 'AL5FE2',
                 'AL2FE', 'AL13FE4', 'AL5FE4']
    comps = ['AL', 'FE', 'VA']
    conds = {v.T: 1400, v.P: 101325, v.X('AL'): 0.55}
    eqx = equilibrium(ALFE_DBF, comps, my_phases, conds, verbose=True)
    assert_allclose(eqx.GM.values.flat[0], -9.608807e4)
Beispiel #42
0
def test_degree_of_ordering():
    "Degree of ordering should be calculated properly."
    my_phases = ['B2_BCC']
    comps = ['AL', 'FE', 'VA']
    conds = {v.T: 300, v.P: 101325, v.X('AL'): 0.25}
    eqx = equilibrium(ALFE_DBF, comps, my_phases, conds, output='degree_of_ordering', verbose=True)
    print('Degree of ordering: {}'.format(eqx.degree_of_ordering.sel(vertex=0).values.flatten()))
    assert np.isclose(eqx.degree_of_ordering.sel(vertex=0).values.flatten(), np.array([0.66663873]))
Beispiel #43
0
def test_rose_nine():
    "Nine-component rose diagram point equilibrium calculation."
    my_phases_rose = ["TEST"]
    comps = ["H", "HE", "LI", "BE", "B", "C", "N", "O", "F"]
    conds = dict({v.T: 1000, v.P: 101325})
    for comp in comps[:-1]:
        conds[v.X(comp)] = 1.0 / float(len(comps))
    eqx = equilibrium(ROSE_DBF, comps, my_phases_rose, conds, pbar=False)
    assert_allclose(eqx.GM.values.flat[0], -5.8351e3, atol=0.1)
Beispiel #44
0
def test_rose_nine():
    "Nine-component rose diagram point equilibrium calculation."
    my_phases_rose = ['TEST']
    comps = ['H', 'HE', 'LI', 'BE', 'B', 'C', 'N', 'O', 'F']
    conds = dict({v.T: 1000, v.P: 101325})
    for comp in comps[:-1]:
        conds[v.X(comp)] = 1.0/float(len(comps))
    eqx = equilibrium(ROSE_DBF, comps, my_phases_rose, conds, pbar=False)
    assert_allclose(eqx.GM.values.flat[0], -5.8351e3)
Beispiel #45
0
def test_eq_single_phase():
    "Equilibrium energy should be the same as for a single phase with no miscibility gaps."
    res = calculate(ALFE_DBF, ['AL', 'FE'], 'LIQUID', T=[1400, 2500], P=101325,
                    points={'LIQUID': [[0.1, 0.9], [0.2, 0.8], [0.3, 0.7],
                                       [0.7, 0.3], [0.8, 0.2]]})
    eq = equilibrium(ALFE_DBF, ['AL', 'FE'], 'LIQUID',
                     {v.T: [1400, 2500], v.P: 101325,
                      v.X('AL'): [0.1, 0.2, 0.3, 0.7, 0.8]}, verbose=True, pbar=False)
    assert_allclose(eq.GM, res.GM, atol=0.1)
Beispiel #46
0
def test_eq_illcond_magnetic_hessian():
    """
    Check equilibrium of a system with an ill-conditioned Hessian due to magnetism (Tc->0).
    This is difficult to reproduce so we only include some known examples here.
    """
    # This set of conditions is known to trigger the issue
    eq = equilibrium(ALFE_DBF, ['AL', 'FE', 'VA'], ['FCC_A1', 'AL13FE4'],
                     {v.X('AL'): 0.8, v.T: 300, v.P: 1e5}, pbar=False)
    assert_allclose(eq.GM.values, [[[-31414.46677]]])
Beispiel #47
0
def test_eq_four_sublattice():
    """
    Balancing mass in a multi-sublattice phase in a single-phase configuration.
    """
    eq = equilibrium(ALNIFCC4SL_DBF, ['AL', 'NI', 'VA'], 'FCC_L12',
                     {v.T: 1073, v.X('NI'): 0.7601, v.P: 101325}, pbar=False)
    assert_allclose(np.squeeze(eq.X.sel(vertex=0).values), [1-.7601, .7601])
    # Not a strict equality here because we can't yet reach TC's value of -87260.6
    assert eq.GM.values < -87256.3
Beispiel #48
0
def test_eq_ternary_edge_case_mass():
    """
    Equilibrium along an edge of composition space will still balance mass.
    """
    eq = equilibrium(ALCOCRNI_DBF, ['AL', 'CO', 'CR', 'VA'], ['L12_FCC', 'BCC_B2', 'LIQUID'],
                     {v.T: 1523, v.X('AL'): 0.88811111111111107,
                      v.X('CO'): 0.11188888888888888, v.P: 101325}, pbar=False)
    mass_error = np.nansum(np.squeeze(eq.NP * eq.X), axis=-2) - \
                 [0.88811111111111107, 0.11188888888888888, 0]
    assert np.all(np.abs(mass_error) < 0.01)
Beispiel #49
0
def test_eqplot_ternary():
    """
    eqplot should return an axes object that has a traingular projection when
    two independent components and one independent potential are passed.
    """
    eq = equilibrium(ALCOCRNI_DBF, ['AL', 'CO', 'CR', 'VA'], ['LIQUID'],
                     {v.T: 2500, v.X('AL'): (0,0.5,0.33), v.X('CO'): (0,0.5,0.3), v.P: 101325})
    ax = eqplot(eq)
    assert isinstance(ax, Axes)
    assert ax.name == 'triangular'
Beispiel #50
0
def test_eq_ternary_edge_misc_gap():
    """
    Equilibrium at edge of miscibility gap will still balance mass.
    """
    eq = equilibrium(ALCOCRNI_DBF, ['AL', 'CO', 'CR', 'VA'], ['L12_FCC', 'BCC_B2', 'LIQUID'],
                     {v.T: 1523, v.X('AL'): 0.33366666666666667,
                      v.X('CO'): 0.44455555555555554, v.P: 101325}, pbar=False)
    mass_error = np.nansum(np.squeeze(eq.NP * eq.X), axis=-2) - \
                 [0.33366666666666667, 0.44455555555555554, 0.22177777777777785]
    assert np.all(np.abs(mass_error) < 0.001)
Beispiel #51
0
def test_eq_ternary_inside_mass():
    """
    Equilibrium in interior of composition space will still balance mass.
    """
    eq = equilibrium(ALCOCRNI_DBF, ['AL', 'CO', 'CR', 'VA'], ['L12_FCC', 'BCC_B2', 'LIQUID'],
                     {v.T: 1523, v.X('AL'): 0.44455555555555554,
                      v.X('CO'): 0.22277777777777777, v.P: 101325}, pbar=False)
    mass_error = np.nansum(np.squeeze(eq.NP * eq.X), axis=-2) - \
                 [0.44455555555555554, 0.22277777777777777, 0.333]
    assert np.all(np.abs(mass_error) < 0.01)
Beispiel #52
0
def test_eqplot_binary():
    """
    eqplot should return an axes object when one independent component and one
    independent potential are passed.
    """
    my_phases = ['LIQUID', 'FCC_A1', 'HCP_A3', 'AL5FE2',
                 'AL2FE', 'AL13FE4', 'AL5FE4']
    comps = ['AL', 'FE', 'VA']
    conds = {v.T: (1400, 1500, 50), v.P: 101325, v.X('AL'): (0, 1, 0.5)}
    eq = equilibrium(ALFE_DBF, comps, my_phases, conds)
    ax = eqplot(eq)
    assert isinstance(ax, Axes)
Beispiel #53
0
def test_eq_composition_cond_sorting():
    """
    Composition conditions are correctly constructed when the dependent component does not
    come last in alphabetical order (gh-21).
    """
    eq = equilibrium(ALFE_DBF, ["AL", "FE"], "LIQUID", {v.T: 2000, v.P: 101325, v.X("FE"): 0.2}, pbar=False)
    # Values computed by Thermo-Calc
    tc_energy = -143913.3
    tc_mu_fe = -184306.01
    tc_mu_al = -133815.12
    assert_allclose(eq.GM.values, tc_energy)
    assert_allclose(eq.MU.values, [[[[tc_mu_al, tc_mu_fe]]]], rtol=1e-6)
Beispiel #54
0
def test_eq_illcond_hessian():
    """
    Check equilibrium of a system with an ill-conditioned Hessian.
    This is difficult to reproduce so we only include some known examples here (gh-23).
    """
    # This set of conditions is known to trigger the issue
    eq = equilibrium(ALFE_DBF, ['AL', 'FE', 'VA'], 'LIQUID',
                     {v.X('FE'): 0.73999999999999999, v.T: 401.5625, v.P: 1e5}, pbar=False)
    assert_allclose(eq.GM.values, [[[-16507.22325998]]])
    # chemical potentials were checked in TC and accurate to 1 J/mol
    # pycalphad values used for more significant figures
    # once again, py33 converges to a slightly different value versus every other python
    assert_allclose(eq.MU.values, [[[[-55611.954141,  -2767.72322]]]], atol=0.1)
Beispiel #55
0
def test_eq_ternary_edge_case_mass():
    """
    Equilibrium along an edge of composition space will still balance mass.
    """
    eq = equilibrium(
        ALCOCRNI_DBF,
        ["AL", "CO", "CR", "VA"],
        ["L12_FCC", "BCC_B2", "LIQUID"],
        {v.T: 1523, v.X("AL"): 0.88811111111111107, v.X("CO"): 0.11188888888888888, v.P: 101325},
        pbar=False,
    )
    mass_error = np.nansum(np.squeeze(eq.NP * eq.X), axis=-2) - [0.88811111111111107, 0.11188888888888888, 0]
    assert np.all(np.abs(mass_error) < 0.01)
Beispiel #56
0
def test_eq_ternary_inside_mass():
    """
    Equilibrium in interior of composition space will still balance mass.
    """
    eq = equilibrium(
        ALCOCRNI_DBF,
        ["AL", "CO", "CR", "VA"],
        ["L12_FCC", "BCC_B2", "LIQUID"],
        {v.T: 1523, v.X("AL"): 0.44455555555555554, v.X("CO"): 0.22277777777777777, v.P: 101325},
        pbar=False,
        verbose=True,
    )
    mass_error = np.nansum(np.squeeze(eq.NP * eq.X), axis=-2) - [0.44455555555555554, 0.22277777777777777, 0.333]
    assert np.all(np.abs(mass_error) < 0.01)
Beispiel #57
0
def test_eq_issue43_chempots_misc_gap():
    """
    Equilibrium for complex ternary miscibility gap (gh-43).
    """
    eq = equilibrium(
        ISSUE43_DBF,
        ["AL", "NI", "CR", "VA"],
        "GAMMA_PRIME",
        {v.X("AL"): 0.1246, v.X("CR"): 1e-9, v.T: 1273, v.P: 101325},
        verbose=False,
        pbar=False,
    )
    chempots = 8.31451 * np.squeeze(eq["T"].values) * np.array([[[[[-19.47631644, -25.71249032, -6.0706158]]]]])
    assert_allclose(eq.GM.values, -81933.259)
    assert_allclose(eq.MU.values, chempots, atol=1)
Beispiel #58
0
def test_eq_issue43_chempots_tricky_potentials():
    """
    Ternary equilibrium with difficult convergence for chemical potentials (gh-43).
    """
    eq = equilibrium(
        ISSUE43_DBF,
        ["AL", "NI", "CR", "VA"],
        ["FCC_A1", "GAMMA_PRIME"],
        {v.X("AL"): 0.1246, v.X("CR"): 0.6, v.T: 1273, v.P: 101325},
        verbose=False,
        pbar=False,
    )
    chempots = 8.31451 * np.squeeze(eq["T"].values) * np.array([[[[[-12.78777939, -4.42862046, -8.77499585]]]]])
    assert_allclose(eq.GM.values, -70567.7329)
    assert_allclose(eq.MU.values, chempots, atol=1)
Beispiel #59
0
def test_eq_illcond_magnetic_hessian():
    """
    Check equilibrium of a system with an ill-conditioned Hessian due to magnetism (Tc->0).
    This is difficult to reproduce so we only include some known examples here.
    """
    # This set of conditions is known to trigger the issue
    eq = equilibrium(
        ALFE_DBF,
        ["AL", "FE", "VA"],
        ["FCC_A1", "AL13FE4"],
        {v.X("AL"): 0.8, v.T: 300, v.P: 1e5},
        pbar=False,
        verbose=True,
    )
    assert_allclose(eq.GM.values, [[[-31414.46677]]])
    assert_allclose(eq.MU.values, [[[[-8490.140, -123111.773]]]], atol=0.1)
Beispiel #60
0
def test_eq_ternary_edge_misc_gap():
    """
    Equilibrium at edge of miscibility gap will still balance mass.
    """
    eq = equilibrium(
        ALCOCRNI_DBF,
        ["AL", "CO", "CR", "VA"],
        ["L12_FCC", "BCC_B2", "LIQUID"],
        {v.T: 1523, v.X("AL"): 0.33366666666666667, v.X("CO"): 0.44455555555555554, v.P: 101325},
        pbar=False,
    )
    mass_error = np.nansum(np.squeeze(eq.NP * eq.X), axis=-2) - [
        0.33366666666666667,
        0.44455555555555554,
        0.22177777777777785,
    ]
    assert np.all(np.abs(mass_error) < 0.001)