-
Notifications
You must be signed in to change notification settings - Fork 19
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #164 from ipcamit/kliff-master-v1
Added tests for newer modules
- Loading branch information
Showing
13 changed files
with
408 additions
and
8 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
from pathlib import Path | ||
|
||
import numpy as np | ||
import pytest | ||
from ase import io | ||
|
||
from kliff.dataset import Configuration | ||
from kliff.dataset.dataset import ConfigurationError | ||
from kliff.utils import stress_to_voigt | ||
|
||
|
||
def test_configuration_from_ase(): | ||
"""Test initializing Configuration from ASE atoms object""" | ||
|
||
filename = Path(__file__).parents[1].joinpath("test_data/configs/Si_4.xyz") | ||
atoms = io.read(filename, index=":") | ||
config = Configuration.from_ase_atoms( | ||
atoms[0], energy_key="Energy", forces_key="force" | ||
) | ||
|
||
assert config.species == ["Si" for _ in range(4)] | ||
assert config.coords.shape == (4, 3) | ||
assert config.energy == 123.45 | ||
assert np.allclose(config.stress, np.array([1.1, 5.5, 9.9, 8.8, 7.7, 4.4])) | ||
assert config.forces.shape == (4, 3) | ||
assert config.stress.shape == (6,) | ||
|
||
|
||
def test_configuration_to_ase(): | ||
"""Test converting Configuration to ASE atoms object""" | ||
|
||
filename = Path(__file__).parents[1].joinpath("test_data/configs/Si_4.xyz") | ||
atoms = io.read(filename, index=":") | ||
config = Configuration.from_ase_atoms( | ||
atoms[0], energy_key="Energy", forces_key="force" | ||
) | ||
|
||
atoms = config.to_ase_atoms() | ||
assert np.allclose(atoms.get_positions(), config.coords) | ||
assert atoms.info["energy"] == config.energy | ||
assert np.allclose(atoms.arrays["forces"], config.forces) | ||
assert np.allclose(stress_to_voigt(atoms.info["stress"]), config.stress) | ||
# TODO: As per Marcos' suggestion, we should use the dict | ||
# method to get the ASE atoms properties. It solves the issue | ||
# of associated calculator. | ||
|
||
|
||
def test_configuration_from_file(): | ||
"""Test initializing Configuration from file""" | ||
|
||
filename = ( | ||
Path(__file__).parents[1].joinpath("test_data/configs/Si_4/Si_T300_step_0.xyz") | ||
) | ||
config = Configuration.from_file(filename) | ||
|
||
assert config.species == ["Si" for _ in range(64)] | ||
assert config.coords.shape == (64, 3) | ||
assert config.energy == 0.0 | ||
assert config.forces.shape == (64, 3) | ||
# stress should raise exception | ||
with pytest.raises(ConfigurationError): | ||
stress = config.stress |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import numpy as np | ||
import pytest | ||
|
||
from kliff.utils import stress_to_tensor, stress_to_voigt | ||
|
||
|
||
def test_stress_conversion(): | ||
stress_tensor = np.random.rand(3, 3) | ||
stress_tensor = stress_tensor + stress_tensor.T # make it symmetric | ||
stress_voigt = stress_to_voigt(stress_tensor) | ||
assert np.allclose( | ||
stress_voigt, | ||
np.array( | ||
[ | ||
stress_tensor[0, 0], | ||
stress_tensor[1, 1], | ||
stress_tensor[2, 2], | ||
stress_tensor[1, 2], | ||
stress_tensor[0, 2], | ||
stress_tensor[0, 1], | ||
] | ||
), | ||
) | ||
print(stress_tensor, stress_to_tensor(stress_voigt)) | ||
assert np.allclose(stress_tensor, stress_to_tensor(stress_voigt)) |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
import numpy as np | ||
from ase.data import atomic_numbers | ||
|
||
from kliff.dataset import Configuration | ||
from kliff.transforms.configuration_transforms import ConfigurationTransform | ||
|
||
|
||
class GlobalCoulombMatrix(ConfigurationTransform): | ||
""" | ||
Coulomb matrix representation of the configuration. | ||
""" | ||
|
||
def __init__(self, max_atoms: int = 5, copy_to_config: bool = False): | ||
super().__init__(copy_to_config) | ||
self.max_atoms = max_atoms | ||
|
||
def forward(self, configuration: Configuration): | ||
""" | ||
Generate the Coulomb matrix for the configuration. | ||
Args: | ||
configuration: Instance of ~:class:`kliff.dataset.Configuration`. For which the | ||
Coulomb matrix is to be generated. | ||
Returns: | ||
Coulomb matrix of the configuration. | ||
""" | ||
coords = configuration.coords | ||
n_atoms = configuration.get_num_atoms() | ||
coulomb_mat = np.zeros((self.max_atoms, self.max_atoms)) | ||
species = [atomic_numbers[elem] for elem in configuration.species] | ||
for i in range(n_atoms): | ||
for j in range(i + 1): | ||
if i == j: | ||
coulomb_mat[i, j] = 0.5 * (species[i] ** 2.4) | ||
else: | ||
r = np.linalg.norm(coords[i] - coords[j]) | ||
coulomb_mat[i, j] = species[i] * species[j] / r | ||
coulomb_mat[j, i] = coulomb_mat[i, j] | ||
return coulomb_mat | ||
|
||
def backward(self, fingerprint, configuration): | ||
""" | ||
Inverse mapping of the transform. This is not implemented for any of the transforms, | ||
but is there for future use. | ||
""" | ||
NotImplementedError( | ||
"Any of the implemented transforms do not support inverse mapping.\n" | ||
"For computing jacobian-vector product use `backward` function." | ||
) | ||
|
||
def collate_fn(self, config_list): | ||
""" | ||
Collate function for the Coulomb matrix transform. | ||
""" | ||
return [self.forward(config) for config in config_list] | ||
|
||
|
||
def test_configuration_transform(test_data_dir): | ||
config = Configuration.from_file(test_data_dir / "configs/Si.xyz") | ||
transform = GlobalCoulombMatrix(max_atoms=8) | ||
fingerprint = transform(config) | ||
assert fingerprint.shape == (8, 8) | ||
assert np.allclose(fingerprint, fingerprint.T) | ||
assert np.allclose( | ||
fingerprint, np.load(test_data_dir / "precomputed_numpy_arrays/cm_si.npy") | ||
) | ||
assert config.fingerprint is None | ||
dataset = [config, config] | ||
fingerprints = transform.collate_fn(dataset) | ||
assert len(fingerprints) == 2 | ||
assert fingerprints[0].shape == (8, 8) | ||
assert fingerprints[1].shape == (8, 8) | ||
assert np.array(fingerprints).shape == (2, 8, 8) |
Oops, something went wrong.