Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions espei/error_functions/non_equilibrium_thermochemical_error.py
Original file line number Diff line number Diff line change
Expand Up @@ -475,7 +475,7 @@ def __init__(
comps = sorted(phase_models.components)
model_dict = phase_models.get_model_dict()
else:
comps = sorted(database.elements)
comps = sorted(set(database.elements) - {'/-'})
model_dict = dict()
phases = sorted(filter_phases(database, unpack_species(database, comps), database.phases.keys()))
if symbols_to_fit is None:
Expand Down Expand Up @@ -504,4 +504,4 @@ def get_likelihood(self, parameters) -> float:
return likelihood


residual_function_registry.register(FixedConfigurationPropertyResidual)
residual_function_registry.register(FixedConfigurationPropertyResidual)
2 changes: 2 additions & 0 deletions espei/error_functions/zpf_error.py
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,8 @@ def __init__(
self.zpf_data = get_zpf_data(database, comps, phases, datasets, parameters, model_dict)

def get_residuals(self, parameters: ArrayLike) -> Tuple[List[float], List[float]]:
if len(self.zpf_data) == 0:
return [], []
driving_forces, weights = calculate_zpf_driving_forces(self.zpf_data, parameters, short_circuit=True)
# Driving forces and weights are 2D ragged arrays with the shape (len(zpf_data), len(zpf_data['values']))
residuals = np.concatenate(driving_forces).tolist()
Expand Down
31 changes: 31 additions & 0 deletions tests/test_error_functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,25 @@ def test_fixed_configuration_residual_with_internal_degrees_of_freedom(datasets_
assert np.allclose(residuals, [0.0])


def test_fixed_configuration_residual_with_electron_element(datasets_db):
"""Fixed configuration residuals work for databases that declare the electron (/-)"""
dbf = Database("ELEMENT /- ELECTRON_GAS 0.0 0.0 0.0 !\n" + A_B_REGULAR_SOLUTION_TDB)
datasets_db.insert({
"components": ["A", "B"], "phases": ["ALPHA"], "output": "HM_MIX",
"solver": {"mode": "manual", "sublattice_site_ratios": [1],
"sublattice_configurations": [[["A", "B"]], [["A", "B"]]],
"sublattice_occupancies": [[[0.5, 0.5]], [[0.2, 0.8]]]},
"conditions": {"P": 101325, "T": 600}, "values": [[[0.0, 0.0]]], "reference": "regular solution",
})

residual_func = FixedConfigurationPropertyResidual(dbf, datasets_db, phase_models=None, symbols_to_fit=['L_ALPHA'])

# HM_MIX = L x_A x_B for a regular solution
residuals, weights = residual_func.get_residuals(np.asarray([2000.0]))
assert len(residuals) == len(weights)
assert np.allclose(residuals, [500.0, 320.0])


def test_get_thermochemical_data_filters_configurations_when_all_configurations_are_invalid(datasets_db):
datasets_db.insert(CU_MG_HM_MIX_CUMG2_ALL_INVALID) # No valid configurations

Expand Down Expand Up @@ -340,6 +359,18 @@ def test_zpf_residual_function(datasets_db):
assert np.isclose(likelihood, zero_error_prob, rtol=1e-6)


def test_zpf_residual_function_without_data(datasets_db):
"""ZPF residuals are empty without ZPF data"""
dbf = Database(CU_MG_TDB)

residual_func = ZPFResidual(dbf, datasets_db, phase_models=None, symbols_to_fit=[])

residuals, weights = residual_func.get_residuals(np.asarray([]))
assert residuals == []
assert weights == []
assert residual_func.get_likelihood(np.asarray([])) == 0.0


def test_subsystem_zpf_probability(datasets_db):
"""Test binary Cr-Ni data produces the same probability regardless of whether the main system is a binary or ternary."""

Expand Down
Loading