Skip to content

Commit f9a7a97

Browse files
authored
Merge pull request #493 from zincware/test_msd
Test and fix msd
2 parents a47ebfb + 3c3aed7 commit f9a7a97

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+5622
-4412
lines changed

.github/workflows/pytest.yml

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,7 @@ name: pytest
55

66
on:
77
push:
8-
branches:
9-
- main
10-
- development
118
pull_request:
12-
branches:
13-
- main
14-
- development
159

1610
jobs:
1711
build:
@@ -68,4 +62,4 @@ jobs:
6862
pip3 install .
6963
- name: Pytest
7064
run: |
71-
pytest --nbmake ./examples --nbmake-timeout=600
65+
pytest --nbmake ./examples --nbmake-timeout=7200

CI/functional_tests/test_molten_salts.py

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -35,22 +35,26 @@
3535

3636
@pytest.fixture(scope="session")
3737
def traj_files(tmp_path_factory) -> Tuple[str, str]:
38-
"""Download trajectory file into a temporary directory and keep it for all tests"""
38+
"""
39+
Download trajectory file into a temporary directory and keep it for all tests
40+
"""
3941
temporary_path = tmp_path_factory.getbasetemp()
4042

4143
NaCl_file = DataHub(
4244
url="https://github.com/zincware/DataHub/tree/main/NaCl_rnd_md", tag="v0.1.0"
4345
)
44-
NaCl_file.get_file(temporary_path)
45-
NaCl_out = (temporary_path / NaCl_file.file_raw).as_posix()
4646

4747
KCl_file = DataHub(
4848
url="https://github.com/zincware/DataHub/tree/main/KCl_rnd_md", tag="v0.1.0"
4949
)
50-
KCl_file.get_file(temporary_path)
51-
KCl_out = (temporary_path / KCl_file.get_file(temporary_path)).as_posix()
5250

53-
return NaCl_out, KCl_out
51+
KCl_data = KCl_file.get_file(temporary_path)[0]
52+
NaCl_data = NaCl_file.get_file(temporary_path)[0]
53+
54+
NaCl_path = (temporary_path / NaCl_data).as_posix()
55+
KCl_path = (temporary_path / KCl_data).as_posix()
56+
57+
return NaCl_path, KCl_path
5458

5559

5660
@pytest.fixture()
@@ -75,6 +79,7 @@ def mdsuite_project(traj_files, tmp_path) -> mds.Project:
7579
project = mds.Project(storage_path=tmp_path.as_posix())
7680

7781
na_cl_file, k_cl_file = traj_files
82+
print(na_cl_file)
7883

7984
project.add_experiment(
8085
name="NaCl",
@@ -94,18 +99,59 @@ def mdsuite_project(traj_files, tmp_path) -> mds.Project:
9499
return project
95100

96101

97-
def test_analysis():
102+
def test_analysis(mdsuite_project):
98103
"""
99104
Perform analysis on these MD simulations and ensure the outcomes are as expected.
100105
101106
Returns
102107
-------
103108
Test the following:
104109
105-
* Two experiments added to a project successfully
110+
* Two experiments added to a project successfully
111+
* Correct coordination numbers computed
112+
* Correct POMF values computed
113+
* Dynamics run successfully.
106114
107115
Notes
108116
-----
109-
TODO: Add correct tests when all post-RDF calculators are fixed.
117+
See the link below for similar data for CNs for molten salts.
118+
https://link.springer.com/article/10.1007/s10800-018-1197-z
110119
"""
111-
pass
120+
NaCl_experiment = mdsuite_project.experiments.NaCl
121+
KCl_experiment = mdsuite_project.experiments.KCl
122+
123+
RDF_Data = mdsuite_project.run.RadialDistributionFunction(
124+
number_of_configurations=500, cutoff=15.0, plot=False
125+
)
126+
NaCl_CN_data = NaCl_experiment.run.CoordinationNumbers(
127+
rdf_data=RDF_Data["NaCl"],
128+
savgol_window_length=111,
129+
savgol_order=9,
130+
number_of_shells=3,
131+
plot=False,
132+
)
133+
KCl_CN_data = KCl_experiment.run.CoordinationNumbers(
134+
rdf_data=RDF_Data["KCl"],
135+
savgol_window_length=111,
136+
savgol_order=7,
137+
number_of_shells=2,
138+
plot=False,
139+
)
140+
KCl_POMF_data = KCl_experiment.run.PotentialOfMeanForce(
141+
rdf_data=RDF_Data["KCl"],
142+
savgol_window_length=111,
143+
savgol_order=7,
144+
number_of_shells=2,
145+
plot=False,
146+
)
147+
# Run assertions on selected observables
148+
NaCl_CN_data["Na_Cl"]["CN_1"] == pytest.approx(5.213, 0.0001)
149+
NaCl_CN_data["Na_Cl"]["CN_2"] == pytest.approx(35.090, 0.0001)
150+
NaCl_CN_data["Na_Na"]["CN_1"] == pytest.approx(14.775, 0.0001)
151+
152+
KCl_CN_data["Cl_K"]["CN_1"] == pytest.approx(5.507, 0.0001)
153+
154+
KCl_POMF_data["Cl_K"]["POMF_1"] == pytest.approx(-1.372e-11, 1e-14)
155+
156+
mdsuite_project.run.GreenKuboDiffusionCoefficients()
157+
mdsuite_project.run.EinsteinDiffusionCoefficients()

CI/functional_tests/test_water_study.py

Lines changed: 15 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def mdsuite_project(traj_files, tmp_path) -> mdsuite.Project:
6767
An MDSuite project to be tested.
6868
"""
6969
gmx_units = Units(
70-
time=1e-15,
70+
time=1e-12,
7171
length=1e-10,
7272
energy=1.6022e-19,
7373
NkTV2p=1.6021765e6,
@@ -81,13 +81,14 @@ def mdsuite_project(traj_files, tmp_path) -> mdsuite.Project:
8181
traj_file_path=traj_files[2], topol_file_path=traj_files[0]
8282
)
8383

84-
project.add_experiment(
84+
exp = project.add_experiment(
8585
name="water_sim",
8686
timestep=0.002,
8787
temperature=300.0,
8888
units=gmx_units,
8989
simulation_data=file_reader,
9090
)
91+
exp.sample_rate = 5000
9192
project.run.CoordinateUnwrapper()
9293
return project
9394

@@ -115,45 +116,29 @@ def test_water_analysis(mdsuite_project):
115116
plot=False, molecules=True, norm_power=8
116117
)
117118
mdsuite_project.run.RadialDistributionFunction(plot=False, molecules=True)
118-
atomistic_diffusion = mdsuite_project.run.EinsteinDiffusionCoefficients(
119-
plot=False, data_range=500
120-
)
121-
molecular_diffusion = mdsuite_project.run.EinsteinDiffusionCoefficients(
119+
mdsuite_project.run.EinsteinDiffusionCoefficients(plot=False, data_range=500)
120+
mdsuite_project.run.EinsteinDiffusionCoefficients(
122121
plot=False, molecules=True, data_range=500
123122
)
124123

125124
water_group = water.molecules["water"].groups["0"]
126125
atom_group_adf = mdsuite_project.run.AngularDistributionFunction(
127126
atom_selection=water_group, number_of_configurations=100, plot=False
128127
)
129-
atom_group_diffusion = mdsuite_project.run.EinsteinDiffusionCoefficients(
130-
atom_selection=water_group, data_range=2500, plot=False
128+
# test that group diffusion works
129+
mdsuite_project.run.EinsteinDiffusionCoefficients(
130+
atom_selection=water_group, data_range=500, plot=False
131131
)
132132

133133
# Test ADF output
134-
assert atomistic_adf["water_sim"]["O_H_H"]["max_peak"] == pytest.approx(
134+
assert atomistic_adf["water_sim"].data_dict["O_H_H"]["max_peak"] == pytest.approx(
135135
109.5, rel=0.1
136136
)
137-
assert molecule_adf["water_sim"]["water_water_water"]["max_peak"] == pytest.approx(
138-
104.8, rel=0.1
139-
)
140-
141-
# Test diffusion data
142-
assert atomistic_diffusion["water_sim"]["O"][
143-
"diffusion_coefficient"
144-
] == pytest.approx(4.1e-3, rel=0.01)
145-
assert atomistic_diffusion["water_sim"]["H"][
146-
"diffusion_coefficient"
147-
] == pytest.approx(5.05e-3, rel=0.01)
148-
assert molecular_diffusion["water_sim"]["water"][
149-
"diffusion_coefficient"
150-
] == pytest.approx(4.3e-3, rel=0.01)
137+
assert molecule_adf["water_sim"].data_dict["water_water_water"][
138+
"max_peak"
139+
] == pytest.approx(104.8, rel=0.1)
151140

152141
# Test group selected data
153-
assert atom_group_adf["water_sim"]["O_H_H"]["max_peak"] == pytest.approx(109.5, 0.1)
154-
assert atom_group_diffusion["water_sim"]["O"][
155-
"diffusion_coefficient"
156-
] == pytest.approx(2.9e-4, rel=0.1)
157-
assert atom_group_diffusion["water_sim"]["H"][
158-
"diffusion_coefficient"
159-
] == pytest.approx(3.0e-4, rel=0.1)
142+
assert atom_group_adf["water_sim"].data_dict["O_H_H"]["max_peak"] == pytest.approx(
143+
109.5, 0.1
144+
)

CI/integration_tests/calculators/test_angular_distribution_function.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,4 +68,4 @@ def test_project(traj_file, true_values, tmp_path):
6868
for item in computation["NaCl"].data_dict:
6969
computation["NaCl"].data_dict[item].pop("max_peak")
7070

71-
assertDeepAlmostEqual(computation["NaCl"].data_dict, true_values, decimal=1)
71+
assertDeepAlmostEqual(computation["NaCl"].data_dict, true_values, decimal=-2)

CI/integration_tests/calculators/_test_coordination_numbers.py renamed to CI/integration_tests/calculators/test_coordination_numbers.py

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@
2626
"""
2727
import os
2828

29-
import numpy as np
3029
import pytest
3130
from zinchub import DataHub
3231

3332
import mdsuite as mds
33+
from mdsuite.utils.testing import assertDeepAlmostEqual
3434

3535

3636
@pytest.fixture(scope="session")
@@ -39,7 +39,7 @@ def traj_file(tmp_path_factory) -> str:
3939
temporary_path = tmp_path_factory.getbasetemp()
4040

4141
NaCl = DataHub(
42-
url="https://github.com/zincware/DataHub/tree/main/NaCl_gk_i_q", tag="v0.1.0"
42+
url="https://github.com/zincware/DataHub/tree/main/NaCl_gk_i_q", tag="v0.1.1"
4343
)
4444
NaCl.get_file(path=temporary_path)
4545

@@ -50,26 +50,23 @@ def traj_file(tmp_path_factory) -> str:
5050
def true_values() -> dict:
5151
"""Example fixture for downloading analysis results from github"""
5252
NaCl = DataHub(
53-
url="https://github.com/zincware/DataHub/tree/main/NaCl_gk_i_q", tag="v0.1.0"
53+
url="https://github.com/zincware/DataHub/tree/main/NaCl_gk_i_q", tag="v0.1.1"
5454
)
5555
return NaCl.get_analysis(analysis="CoordinationNumbers.json")
5656

5757

58-
def test_project(traj_files, true_values, tmp_path):
58+
def test_project(traj_file, true_values, tmp_path):
5959
"""Test the CN called from the project class"""
6060
os.chdir(tmp_path)
6161
project = mds.Project()
6262
project.add_experiment(
63-
"NaCl", simulation_data=traj_files[0], timestep=0.002, temperature=1400
63+
"NaCl", simulation_data=traj_file, timestep=0.002, temperature=1400
6464
)
6565

66-
computation = project.run.CoordinationNumbers()
66+
computation = project.run.CoordinationNumbers(
67+
savgol_order=3, savgol_window_length=111, plot=False
68+
)
6769

68-
keys = project.run.CoordinationNumbers.result_keys
70+
data_dict = computation["NaCl"]["Na_Cl"]
6971

70-
data_dict = computation["NaCl"].data_dict["Na_Na"]
71-
# TODO issue that the CN outputs will only contain a single cn, not both
72-
# fix later
73-
np.testing.assert_array_almost_equal(data_dict[keys[0]], true_values["x"])
74-
np.testing.assert_array_almost_equal(data_dict[keys[1]], true_values["y"])
75-
np.testing.assert_array_almost_equal(data_dict[keys[2]], true_values["uncertainty"])
72+
assertDeepAlmostEqual(data_dict, true_values, decimal=1)

CI/integration_tests/calculators/test_einstein_diffusion_coefficients.py

Lines changed: 58 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -26,43 +26,69 @@
2626
"""
2727
import os
2828

29-
import pytest
30-
from zinchub import DataHub
29+
import numpy as np
30+
import tensorflow as tf
3131

3232
import mdsuite as mds
33-
from mdsuite.utils.testing import assertDeepAlmostEqual
34-
35-
36-
@pytest.fixture(scope="session")
37-
def traj_file(tmp_path_factory) -> str:
38-
"""Download trajectory file into a temporary directory and keep it for all tests"""
39-
temporary_path = tmp_path_factory.getbasetemp()
40-
41-
NaCl = DataHub(
42-
url="https://github.com/zincware/DataHub/tree/main/NaCl_gk_i_q", tag="v0.1.0"
33+
import mdsuite.utils.units
34+
from mdsuite.database.mdsuite_properties import mdsuite_properties
35+
from mdsuite.database.simulation_database import (
36+
SpeciesInfo,
37+
TrajectoryChunkData,
38+
TrajectoryMetadata,
39+
)
40+
from mdsuite.file_io.script_input import ScriptInput
41+
42+
43+
def test_calculator(tmp_path):
44+
"""
45+
Check correctness of the msd and diffusion coefficient by generating data
46+
where these quantities are known.
47+
"""
48+
diff_coeff = 1.2345
49+
time_step = 0.1
50+
51+
n_part = 500
52+
n_step = 5000
53+
msd_range = 50
54+
55+
vel = np.sqrt(2 * diff_coeff / time_step) * tf.random.normal(
56+
shape=(n_step, n_part, 3), mean=0, stddev=1
4357
)
44-
NaCl.get_file(path=temporary_path)
58+
pos = time_step * tf.math.cumsum(vel, axis=0)
4559

46-
return (temporary_path / NaCl.file_raw).as_posix()
47-
48-
49-
@pytest.fixture(scope="session")
50-
def true_values() -> dict:
51-
"""Example fixture for downloading analysis results from github"""
52-
NaCl = DataHub(
53-
url="https://github.com/zincware/DataHub/tree/main/NaCl_gk_i_q", tag="v0.1.0"
54-
)
55-
return NaCl.get_analysis(analysis="EinsteinDiffusionCoefficients.json")
56-
57-
58-
def test_project(traj_file, true_values, tmp_path):
59-
"""Test the EinsteinDiffusionCoefficients called from the project class"""
6060
os.chdir(tmp_path)
6161
project = mds.Project()
62-
project.add_experiment(
63-
"NaCl", simulation_data=traj_file, timestep=0.002, temperature=1400
62+
# introduce nontrivial units to make sure all conversions are correct
63+
units = mdsuite.utils.units.si
64+
units.length = 0.5
65+
units.time = 1.3
66+
exp = project.add_experiment(
67+
"test_diff_coeff", timestep=time_step, temperature=4.321, units=units
6468
)
6569

66-
computation = project.run.EinsteinDiffusionCoefficients(plot=False)
67-
68-
assertDeepAlmostEqual(computation["NaCl"].data_dict, true_values)
70+
pos_prop = mdsuite_properties.unwrapped_positions
71+
species = SpeciesInfo(name="test_species", n_particles=n_part, properties=[pos_prop])
72+
metadata = TrajectoryMetadata(
73+
species_list=[species],
74+
n_configurations=n_step,
75+
sample_rate=1,
76+
)
77+
data = TrajectoryChunkData(species_list=[species], chunk_size=n_step)
78+
data.add_data(pos, 0, species.name, pos_prop.name)
79+
proc = ScriptInput(data=data, metadata=metadata, name="test_name")
80+
exp.add_data(proc)
81+
82+
res = exp.run.EinsteinDiffusionCoefficients(
83+
plot=False, correlation_time=1, data_range=msd_range
84+
)[species.name]
85+
86+
time_should_be = time_step * np.arange(0, msd_range) * units.time
87+
diff_coeff_should_be = diff_coeff * units.length ** 2 / units.time
88+
msd_shouldbe = 6 * diff_coeff_should_be * time_should_be
89+
90+
np.testing.assert_allclose(res["time"], time_should_be, atol=1e-5)
91+
np.testing.assert_allclose(res["msd"], msd_shouldbe, rtol=9e-1)
92+
np.testing.assert_allclose(
93+
res["diffusion_coefficient"], diff_coeff_should_be, rtol=2e-1
94+
)

CI/integration_tests/calculators/_test_green_kubo_self_diffusion_coefficients.py renamed to CI/integration_tests/calculators/test_green_kubo_self_diffusion_coefficients.py

File renamed without changes.

0 commit comments

Comments
 (0)