From e02ec199256d67901bd538c8b1bd646269894afc Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Mon, 5 Aug 2024 10:57:42 +0800 Subject: [PATCH 01/41] build against numpy2 --- pyproject.toml | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 3a46fdd..1752bb7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ license = { text = "Modified BSD" } dependencies = [ "ase>=3.23.0", "cython>=3", - "numpy>=1.26,<2", + "numpy>=1.26", "nvidia-ml-py3>=7.352.0", "pymatgen>=2023.10.11", "torch>=1.11.0", @@ -47,7 +47,12 @@ find = { include = ["chgnet*"], exclude = ["tests", "tests*"] } "chgnet.pretrained" = ["*", "**/*"] [build-system] -requires = ["Cython", "setuptools>=65,<70", "wheel"] +requires = [ + "Cython", + "setuptools>=65,<70", + "wheel", + "numpy>=2.0.0rc1", +] build-backend = "setuptools.build_meta" [tool.ruff] From d5817171d7f536e99ad5ef2e42ba9dc1c8469f74 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Mon, 5 Aug 2024 11:37:24 +0800 Subject: [PATCH 02/41] Need confirm: remove setuptool upper pin --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 1752bb7..746cdc6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -49,7 +49,7 @@ find = { include = ["chgnet*"], exclude = ["tests", "tests*"] } [build-system] requires = [ "Cython", - "setuptools>=65,<70", + "setuptools>=65", "wheel", "numpy>=2.0.0rc1", ] From 110f4eb89e71656637fd5e3660d4510fb0d053c0 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Fri, 9 Aug 2024 10:08:40 +0800 Subject: [PATCH 03/41] bump pymatgen version to support NP2 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 746cdc6..93deed1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ dependencies = [ "cython>=3", "numpy>=1.26", "nvidia-ml-py3>=7.352.0", - "pymatgen>=2023.10.11", + "pymatgen>=2024.8.8", "torch>=1.11.0", "typing-extensions>=4.12", ] From 9996c5deb1beafc8a768200693d787cab85127d3 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Fri, 9 Aug 2024 10:16:06 +0800 Subject: [PATCH 04/41] include wandb into test dependency as it's required by test_trainer --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 93deed1..4c40628 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -29,7 +29,7 @@ classifiers = [ ] [project.optional-dependencies] -test = ["pytest-cov>=4", "pytest>=8"] +test = ["pytest-cov>=4", "pytest>=8", "wandb>=0.17"] # needed to run interactive example notebooks examples = ["crystal-toolkit>=2023.11.3", "pandas>=2.2"] docs = ["lazydocs>=0.4"] From 1c74710cf355fd4169cd1308d8d65b72e355a518 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Fri, 9 Aug 2024 10:25:49 +0800 Subject: [PATCH 05/41] explicitly use weights_only False to avoid FutureWarning --- chgnet/model/model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chgnet/model/model.py b/chgnet/model/model.py index d2edb92..d203033 100644 --- a/chgnet/model/model.py +++ b/chgnet/model/model.py @@ -672,7 +672,7 @@ def from_dict(cls, dct: dict, **kwargs) -> Self: @classmethod def from_file(cls, path: str, **kwargs) -> Self: """Build a CHGNet from a saved file.""" - state = torch.load(path, map_location=torch.device("cpu")) + state = torch.load(path, map_location=torch.device("cpu"), weights_only=False) return cls.from_dict(state["model"], **kwargs) @classmethod From 6fa3755501240f732ce6eecfda0c06bcfb2a7b03 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Fri, 9 Aug 2024 10:57:29 +0800 Subject: [PATCH 06/41] use tem path in test --- tests/test_trainer.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_trainer.py b/tests/test_trainer.py index 6fdb731..329e56b 100644 --- a/tests/test_trainer.py +++ b/tests/test_trainer.py @@ -153,11 +153,11 @@ def test_wandb_init(mock_wandb): ) -def test_wandb_log_frequency(mock_wandb): +def test_wandb_log_frequency(tmp_path, mock_wandb): trainer = Trainer(model=chgnet, wandb_path="test-project/test-run", epochs=1) # Test epoch logging - trainer.train(train_loader, val_loader, wandb_log_freq="epoch", save_dir="") + trainer.train(train_loader, val_loader, wandb_log_freq="epoch", save_dir=tmp_path) assert ( mock_wandb.log.call_count == 2 * trainer.epochs ), "Expected one train and one val log per epoch" @@ -165,7 +165,7 @@ def test_wandb_log_frequency(mock_wandb): mock_wandb.log.reset_mock() # Test batch logging - trainer.train(train_loader, val_loader, wandb_log_freq="batch", save_dir="") + trainer.train(train_loader, val_loader, wandb_log_freq="batch", save_dir=tmp_path) expected_batch_calls = trainer.epochs * len(train_loader) assert ( mock_wandb.log.call_count > expected_batch_calls @@ -183,5 +183,5 @@ def test_wandb_log_frequency(mock_wandb): # Test no logging when wandb_path is not provided trainer_no_wandb = Trainer(model=chgnet, epochs=1) - trainer_no_wandb.train(train_loader, val_loader) + trainer_no_wandb.train(train_loader, val_loader, save_dir=tmp_path) mock_wandb.log.assert_not_called() From 3023f840dfedcf4ae19d4577d01f2e75b1abba03 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Tue, 10 Sep 2024 21:38:18 +0800 Subject: [PATCH 07/41] bump pymatgen to resolve np2 compatibility issue --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 4c40628..f20dd29 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ dependencies = [ "cython>=3", "numpy>=1.26", "nvidia-ml-py3>=7.352.0", - "pymatgen>=2024.8.8", + "pymatgen>=2024.9.10", "torch>=1.11.0", "typing-extensions>=4.12", ] From 6a4246dcc96b5840ca1a7559c914b9d7ae41ce51 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Wed, 11 Sep 2024 18:26:17 +0800 Subject: [PATCH 08/41] use int64 --- chgnet/graph/converter.py | 2 +- chgnet/model/composition_model.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/chgnet/graph/converter.py b/chgnet/graph/converter.py index 3fedf3c..477654c 100644 --- a/chgnet/graph/converter.py +++ b/chgnet/graph/converter.py @@ -248,7 +248,7 @@ def _create_graph_fast( """ center_index = np.ascontiguousarray(center_index) neighbor_index = np.ascontiguousarray(neighbor_index) - image = np.ascontiguousarray(image, dtype=np.int_) + image = np.ascontiguousarray(image, dtype=np.int64) distance = np.ascontiguousarray(distance) gc_saved = gc.get_threshold() gc.set_threshold(0) diff --git a/chgnet/model/composition_model.py b/chgnet/model/composition_model.py index 4a7e0e9..549dea7 100644 --- a/chgnet/model/composition_model.py +++ b/chgnet/model/composition_model.py @@ -146,7 +146,7 @@ def fit( if isinstance(structure, Structure): atomic_number = torch.tensor( [site.specie.Z for site in structure], - dtype=int, + dtype=np.int64, requires_grad=False, ) else: From 62f3638e98eda6d0f2bdf33d40ddfaf6f5286d31 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Wed, 11 Sep 2024 18:27:37 +0800 Subject: [PATCH 09/41] avoid release candidate for numpy build --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index f20dd29..3abd895 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -51,7 +51,7 @@ requires = [ "Cython", "setuptools>=65", "wheel", - "numpy>=2.0.0rc1", + "numpy>=2.0.0", ] build-backend = "setuptools.build_meta" From d628068751debc7a572598676176c9734f87bf7e Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Wed, 11 Sep 2024 19:02:41 +0800 Subject: [PATCH 10/41] revert dtype change for pytorch --- chgnet/model/composition_model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chgnet/model/composition_model.py b/chgnet/model/composition_model.py index 549dea7..4a7e0e9 100644 --- a/chgnet/model/composition_model.py +++ b/chgnet/model/composition_model.py @@ -146,7 +146,7 @@ def fit( if isinstance(structure, Structure): atomic_number = torch.tensor( [site.specie.Z for site in structure], - dtype=np.int64, + dtype=int, requires_grad=False, ) else: From d0c6b5b99f577fcb92304c94c48f213b674a6c77 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Wed, 11 Sep 2024 20:03:03 +0800 Subject: [PATCH 11/41] fix error type --- chgnet/utils/vasp_utils.py | 2 +- tests/test_vasp_utils.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/chgnet/utils/vasp_utils.py b/chgnet/utils/vasp_utils.py index bfb54a0..5b71226 100644 --- a/chgnet/utils/vasp_utils.py +++ b/chgnet/utils/vasp_utils.py @@ -38,7 +38,7 @@ def parse_vasp_dir( dict: a dictionary of lists with keys for structure, uncorrected_total_energy, energy_per_atom, force, magmom, stress. """ - if os.path.isdir(base_dir) is False: + if not os.path.isdir(base_dir): raise NotADirectoryError(f"{base_dir=} is not a directory") oszicar_path = zpath(f"{base_dir}/OSZICAR") diff --git a/tests/test_vasp_utils.py b/tests/test_vasp_utils.py index 8def656..b16c2ad 100644 --- a/tests/test_vasp_utils.py +++ b/tests/test_vasp_utils.py @@ -62,7 +62,7 @@ def test_parse_vasp_dir_without_magmoms(tmp_path: Path): def test_parse_vasp_dir_no_data(): # test non-existing directory - with pytest.raises(FileNotFoundError, match="is not a directory"): + with pytest.raises(NotADirectoryError, match="is not a directory"): parse_vasp_dir(f"{ROOT}/tests/files/non-existent") # test existing directory without VASP files From b4f05c52104d8d655eea5a8fdf35c7f1dbf9efe2 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Wed, 11 Sep 2024 20:26:47 +0800 Subject: [PATCH 12/41] NEED CONFIRM: patch numpy random generator --- tests/test_crystal_graph.py | 61 +++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/tests/test_crystal_graph.py b/tests/test_crystal_graph.py index 8834d23..4022e70 100644 --- a/tests/test_crystal_graph.py +++ b/tests/test_crystal_graph.py @@ -1,6 +1,7 @@ from __future__ import annotations from time import perf_counter +from unittest.mock import patch import numpy as np from pymatgen.core import Structure @@ -8,8 +9,6 @@ from chgnet import ROOT from chgnet.graph import CrystalGraphConverter -np.random.seed(0) - structure = Structure.from_file(f"{ROOT}/examples/mp-18767-LiMnO2.cif") converter = CrystalGraphConverter(atom_graph_cutoff=5, bond_graph_cutoff=3) converter_legacy = CrystalGraphConverter( @@ -127,55 +126,57 @@ def test_crystal_graph_different_cutoff_fast(): def test_crystal_graph_perturb_legacy(): - np.random.seed(0) structure_perturbed = structure.copy() - structure_perturbed.perturb(distance=0.1) + fixed_rng = np.random.default_rng(0) + with patch("numpy.random.default_rng", return_value=fixed_rng): + structure_perturbed.perturb(distance=0.1) start = perf_counter() graph = converter_legacy(structure_perturbed) print("Legacy test_crystal_graph_perturb time:", perf_counter() - start) # noqa: T201 assert list(graph.atom_frac_coord.shape) == [8, 3] - assert list(graph.atom_graph.shape) == [410, 2] - assert (graph.atom_graph[:, 0] == 3).sum().item() == 53 - assert (graph.atom_graph[:, 1] == 3).sum().item() == 53 - assert (graph.atom_graph[:, 1] == 6).sum().item() == 50 - - assert list(graph.bond_graph.shape) == [688, 5] - assert (graph.bond_graph[:, 0] == 1).sum().item() == 90 - assert (graph.bond_graph[:, 1] == 36).sum().item() == 17 - assert (graph.bond_graph[:, 3] == 36).sum().item() == 17 - assert (graph.bond_graph[:, 2] == 306).sum().item() == 10 + assert list(graph.atom_graph.shape) == [420, 2] + assert (graph.atom_graph[:, 0] == 3).sum().item() == 54 + assert (graph.atom_graph[:, 1] == 3).sum().item() == 54 + assert (graph.atom_graph[:, 1] == 6).sum().item() == 54 + + assert list(graph.bond_graph.shape) == [850, 5] + assert (graph.bond_graph[:, 0] == 1).sum().item() == 156 + assert (graph.bond_graph[:, 1] == 36).sum().item() == 18 + assert (graph.bond_graph[:, 3] == 36).sum().item() == 18 + assert (graph.bond_graph[:, 2] == 306).sum().item() == 0 assert (graph.bond_graph[:, 4] == 120).sum().item() == 0 assert list(graph.lattice.shape) == [3, 3] - assert list(graph.undirected2directed.shape) == [205] - assert list(graph.directed2undirected.shape) == [410] + assert list(graph.undirected2directed.shape) == [210] + assert list(graph.directed2undirected.shape) == [420] def test_crystal_graph_perturb_fast(): - np.random.seed(0) structure_perturbed = structure.copy() - structure_perturbed.perturb(distance=0.1) + fixed_rng = np.random.default_rng(0) + with patch("numpy.random.default_rng", return_value=fixed_rng): + structure_perturbed.perturb(distance=0.1) start = perf_counter() graph = converter_fast(structure_perturbed) print("Fast test_crystal_graph_perturb time:", perf_counter() - start) # noqa: T201 assert list(graph.atom_frac_coord.shape) == [8, 3] - assert list(graph.atom_graph.shape) == [410, 2] - assert (graph.atom_graph[:, 0] == 3).sum().item() == 53 - assert (graph.atom_graph[:, 1] == 3).sum().item() == 53 - assert (graph.atom_graph[:, 1] == 6).sum().item() == 50 - - assert list(graph.bond_graph.shape) == [688, 5] - assert (graph.bond_graph[:, 0] == 1).sum().item() == 90 - assert (graph.bond_graph[:, 1] == 36).sum().item() == 17 - assert (graph.bond_graph[:, 3] == 36).sum().item() == 17 - assert (graph.bond_graph[:, 2] == 306).sum().item() == 10 + assert list(graph.atom_graph.shape) == [420, 2] + assert (graph.atom_graph[:, 0] == 3).sum().item() == 54 + assert (graph.atom_graph[:, 1] == 3).sum().item() == 54 + assert (graph.atom_graph[:, 1] == 6).sum().item() == 54 + + assert list(graph.bond_graph.shape) == [850, 5] + assert (graph.bond_graph[:, 0] == 1).sum().item() == 156 + assert (graph.bond_graph[:, 1] == 36).sum().item() == 18 + assert (graph.bond_graph[:, 3] == 36).sum().item() == 18 + assert (graph.bond_graph[:, 2] == 306).sum().item() == 0 assert (graph.bond_graph[:, 4] == 120).sum().item() == 0 assert list(graph.lattice.shape) == [3, 3] - assert list(graph.undirected2directed.shape) == [205] - assert list(graph.directed2undirected.shape) == [410] + assert list(graph.undirected2directed.shape) == [210] + assert list(graph.directed2undirected.shape) == [420] def test_crystal_graph_isotropic_strained_legacy(): From 7f7d6b69db4adda4aaf1376641f07dfbb4f8f4c6 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Wed, 11 Sep 2024 21:39:40 +0800 Subject: [PATCH 13/41] pip install on win IS SLOW, do something while waiting --- pyproject.toml | 26 +++++++++++--------------- 1 file changed, 11 insertions(+), 15 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 00201f7..65ebbc7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,10 +19,10 @@ classifiers = [ "Intended Audience :: Science/Research", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", + "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", - "Programming Language :: Python :: 3.9", "Topic :: Scientific/Engineering :: Artificial Intelligence", "Topic :: Scientific/Engineering :: Chemistry", "Topic :: Scientific/Engineering :: Physics", @@ -63,35 +63,31 @@ target-version = "py39" select = ["ALL"] ignore = [ "ANN001", # TODO add missing type annotations - "ANN003", - "ANN101", - "ANN102", - "B019", # Use of functools.lru_cache on methods can lead to memory leaks - "BLE001", + "ANN003", # Missing type annotation for **{name} + "ANN101", # Missing type annotation for {name} in method + "ANN102", # Missing type annotation for {name} in classmethod + "BLE001", # use of general except Exception "C408", # unnecessary-collection-call "C901", # function is too complex "COM812", # trailing comma missing "D100", # Missing docstring in public module "D104", # Missing docstring in public package "D205", # 1 blank line required between summary line and description - "DTZ005", # use of datetime.now() without timezone "E731", # do not assign a lambda expression, use a def - "EM", + "EM", # error message related "ERA001", # found commented out code - "ISC001", "NPY002", # TODO replace legacy np.random.seed "PLR0912", # too many branches "PLR0913", # too many args in function def "PLR0915", # too many statements "PLW2901", # Outer for loop variable overwritten by inner assignment target - "PT006", # pytest-parametrize-names-wrong-type "PTH", # prefer Path to os.path - "S108", + "S108", # Probable insecure usage of temporary file or directory "S301", # pickle can be unsafe - "S310", - "S311", - "TRY003", - "TRY300", + "S310", # Audit URL open for permitted schemes + "S311", # pseudo-random generators not suitable for cryptographic purposes + "TRY003", # Avoid specifying long messages outside the exception class + "TRY300", # Consider moving this statement to an else block ] pydocstyle.convention = "google" isort.required-imports = ["from __future__ import annotations"] From c70f8047a82857c437c446ca8179a4941eb7d2c3 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Wed, 11 Sep 2024 21:56:09 +0800 Subject: [PATCH 14/41] use cython type --- chgnet/graph/cygraph.pyx | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/chgnet/graph/cygraph.pyx b/chgnet/graph/cygraph.pyx index 7b82fda..436021d 100644 --- a/chgnet/graph/cygraph.pyx +++ b/chgnet/graph/cygraph.pyx @@ -7,10 +7,14 @@ # cython: profile=False # distutils: language = c -import chgnet.graph.graph import numpy as np +cimport numpy as np + +import chgnet.graph.graph + from libc.stdlib cimport free + cdef extern from 'fast_converter_libraries/create_graph.c': ctypedef struct Node: long index @@ -62,12 +66,12 @@ cdef extern from 'fast_converter_libraries/create_graph.c': LongToDirectedEdgeList** get_neighbors(Node* node) def make_graph( - const long[::1] center_index, - const long n_e, - const long[::1] neighbor_index, - const long[:, ::1] image, - const double[::1] distance, - const long num_atoms + const np.intp_t[::1] center_index, + const np.intp_t n_e, + const np.intp_t[::1] neighbor_index, + const np.intp_t[:, ::1] image, + const np.float64_t[::1] distance, + const np.intp_t num_atoms ): cdef ReturnElems2* returned returned = create_graph( ¢er_index[0], n_e, &neighbor_index[0], &image[0][0], &distance[0], num_atoms) From 1d0b1530b93d5337f1f2a00472b00e50c108fe5d Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Wed, 11 Sep 2024 21:57:12 +0800 Subject: [PATCH 15/41] include numpy c header --- setup.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/setup.py b/setup.py index fee67ac..ab494d5 100644 --- a/setup.py +++ b/setup.py @@ -1,7 +1,12 @@ from __future__ import annotations +import numpy as np from setuptools import Extension, setup ext_modules = [Extension("chgnet.graph.cygraph", ["chgnet/graph/cygraph.pyx"])] -setup(ext_modules=ext_modules, setup_requires=["Cython"]) +setup( + ext_modules=ext_modules, + setup_requires=["Cython"], + include_dirs=[np.get_include()], +) From 4f044ebb6082998abfe052e16e22dbb178178686 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Wed, 11 Sep 2024 22:05:12 +0800 Subject: [PATCH 16/41] int64 might be better, intp is still platform dependent --- chgnet/graph/cygraph.pyx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/chgnet/graph/cygraph.pyx b/chgnet/graph/cygraph.pyx index 436021d..6540d92 100644 --- a/chgnet/graph/cygraph.pyx +++ b/chgnet/graph/cygraph.pyx @@ -66,12 +66,12 @@ cdef extern from 'fast_converter_libraries/create_graph.c': LongToDirectedEdgeList** get_neighbors(Node* node) def make_graph( - const np.intp_t[::1] center_index, - const np.intp_t n_e, - const np.intp_t[::1] neighbor_index, - const np.intp_t[:, ::1] image, + const np.int64_t[::1] center_index, + const np.int64_t n_e, + const np.int64_t[::1] neighbor_index, + const np.int64_t[:, ::1] image, const np.float64_t[::1] distance, - const np.intp_t num_atoms + const np.int64_t num_atoms ): cdef ReturnElems2* returned returned = create_graph( ¢er_index[0], n_e, &neighbor_index[0], &image[0][0], &distance[0], num_atoms) From 45a1fd75dcbb622a4d472d5004371cd1a87b6d69 Mon Sep 17 00:00:00 2001 From: Janosh Riebesell Date: Wed, 11 Sep 2024 10:38:42 -0400 Subject: [PATCH 17/41] maybe fix setup.py ModuleNotFoundError: No module named 'numpy' by lazy-importing numpy --- pyproject.toml | 7 +------ setup.py | 11 +++++++++-- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 65ebbc7..8e98a6a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,12 +48,7 @@ find = { include = ["chgnet*"], exclude = ["tests", "tests*"] } "chgnet.pretrained" = ["*", "**/*"] [build-system] -requires = [ - "Cython", - "setuptools>=65", - "wheel", - "numpy>=2.0.0", -] +requires = ["Cython", "numpy>=2", "setuptools>=65", "wheel"] build-backend = "setuptools.build_meta" [tool.ruff] diff --git a/setup.py b/setup.py index ab494d5..e01c268 100644 --- a/setup.py +++ b/setup.py @@ -1,12 +1,19 @@ from __future__ import annotations -import numpy as np from setuptools import Extension, setup ext_modules = [Extension("chgnet.graph.cygraph", ["chgnet/graph/cygraph.pyx"])] + +def lazy_numpy_include() -> str: + """Get the numpy include directory lazily.""" + import numpy as np + + return np.get_include() + + setup( ext_modules=ext_modules, setup_requires=["Cython"], - include_dirs=[np.get_include()], + include_dirs=[lazy_numpy_include()], ) From b8f6cfa432cfb3efc80988f522fc15125ba42343 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Wed, 11 Sep 2024 22:49:37 +0800 Subject: [PATCH 18/41] ruff fixes --- chgnet/trainer/trainer.py | 4 ++-- pyproject.toml | 1 + tests/test_converter.py | 2 +- tests/test_encoders.py | 2 +- tests/test_relaxation.py | 2 +- 5 files changed, 6 insertions(+), 5 deletions(-) diff --git a/chgnet/trainer/trainer.py b/chgnet/trainer/trainer.py index 3d3cdf4..60543ab 100644 --- a/chgnet/trainer/trainer.py +++ b/chgnet/trainer/trainer.py @@ -1,11 +1,11 @@ from __future__ import annotations +import datetime import inspect import os import random import shutil import time -from datetime import datetime from typing import TYPE_CHECKING, Literal, get_args import numpy as np @@ -285,7 +285,7 @@ def train( raise ValueError("Model needs to be initialized") global best_checkpoint # noqa: PLW0603 if save_dir is None: - save_dir = f"{datetime.now():%m-%d-%Y}" + save_dir = f"{datetime.datetime.now(tz=datetime.timezone.utc):%m-%d-%Y}" print(f"Begin Training: using {self.device} device") print(f"training targets: {self.targets}") diff --git a/pyproject.toml b/pyproject.toml index 8e98a6a..f362e70 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -61,6 +61,7 @@ ignore = [ "ANN003", # Missing type annotation for **{name} "ANN101", # Missing type annotation for {name} in method "ANN102", # Missing type annotation for {name} in classmethod + "B019", # Use of functools.lru_cache on methods can lead to memory leaks "BLE001", # use of general except Exception "C408", # unnecessary-collection-call "C901", # function is too complex diff --git a/tests/test_converter.py b/tests/test_converter.py index 46600ac..647f5c4 100644 --- a/tests/test_converter.py +++ b/tests/test_converter.py @@ -29,7 +29,7 @@ def _set_make_graph() -> Generator[None, None, None]: @pytest.mark.parametrize( - "atom_graph_cutoff, bond_graph_cutoff", [(5, 3), (5, None), (4, 2)] + ("atom_graph_cutoff", "bond_graph_cutoff"), [(5, 3), (5, None), (4, 2)] ) def test_crystal_graph_converter_cutoff( atom_graph_cutoff: float | None, bond_graph_cutoff: float | None diff --git a/tests/test_encoders.py b/tests/test_encoders.py index 6beda80..27d5b61 100644 --- a/tests/test_encoders.py +++ b/tests/test_encoders.py @@ -28,7 +28,7 @@ def test_atom_embedding(atom_feature_dim: int, max_num_elements: int) -> None: assert "index out of range" in str(exc_info.value) -@pytest.mark.parametrize("atom_graph_cutoff, bond_graph_cutoff", [(5, 3), (6, 4)]) +@pytest.mark.parametrize(("atom_graph_cutoff", "bond_graph_cutoff"), [(5, 3), (6, 4)]) def test_bond_encoder(atom_graph_cutoff: float, bond_graph_cutoff: float) -> None: undirected2directed = torch.tensor([0, 1]) image = torch.zeros((2, 3)) diff --git a/tests/test_relaxation.py b/tests/test_relaxation.py index 87241f5..c23b675 100644 --- a/tests/test_relaxation.py +++ b/tests/test_relaxation.py @@ -14,7 +14,7 @@ @pytest.mark.parametrize( - "algorithm, ase_filter, assign_magmoms", + ("algorithm", "ase_filter", "assign_magmoms"), [("legacy", FrechetCellFilter, True), ("fast", ExpCellFilter, False)], ) def test_relaxation( From e4ceb6a0d63c2a998ee6744b94343469e388791b Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Wed, 11 Sep 2024 22:57:49 +0800 Subject: [PATCH 19/41] Revert "maybe fix setup.py ModuleNotFoundError: No module named 'numpy'" This reverts commit 45a1fd75dcbb622a4d472d5004371cd1a87b6d69. --- pyproject.toml | 7 ++++++- setup.py | 11 ++--------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index f362e70..18419c0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -48,7 +48,12 @@ find = { include = ["chgnet*"], exclude = ["tests", "tests*"] } "chgnet.pretrained" = ["*", "**/*"] [build-system] -requires = ["Cython", "numpy>=2", "setuptools>=65", "wheel"] +requires = [ + "Cython", + "setuptools>=65", + "wheel", + "numpy>=2.0.0", +] build-backend = "setuptools.build_meta" [tool.ruff] diff --git a/setup.py b/setup.py index e01c268..ab494d5 100644 --- a/setup.py +++ b/setup.py @@ -1,19 +1,12 @@ from __future__ import annotations +import numpy as np from setuptools import Extension, setup ext_modules = [Extension("chgnet.graph.cygraph", ["chgnet/graph/cygraph.pyx"])] - -def lazy_numpy_include() -> str: - """Get the numpy include directory lazily.""" - import numpy as np - - return np.get_include() - - setup( ext_modules=ext_modules, setup_requires=["Cython"], - include_dirs=[lazy_numpy_include()], + include_dirs=[np.get_include()], ) From d00a42589ab3d0a13858eb2e7b7b4d865ccaf845 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Wed, 11 Sep 2024 22:58:58 +0800 Subject: [PATCH 20/41] I don't think we need to manually install build deps, hoping I'm not wrong --- .github/workflows/test.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index e2be1e1..405e954 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -34,11 +34,7 @@ jobs: - name: Install dependencies run: | - uv pip install cython 'setuptools<70' --system - - python setup.py build_ext --inplace - - uv pip install -e .[test,logging] --system --resolution=${{ matrix.version.resolution }} + uv pip install -e .[test,logging] --resolution=${{ matrix.version.resolution }} - name: Run Tests run: pytest --capture=no --cov --cov-report=xml From af86ce60b7d28ea0fc7a0d17d5e84985f0cf63be Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Wed, 11 Sep 2024 23:22:30 +0800 Subject: [PATCH 21/41] add --system arg to uv pip install --- .github/workflows/test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 405e954..6c234da 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -34,7 +34,7 @@ jobs: - name: Install dependencies run: | - uv pip install -e .[test,logging] --resolution=${{ matrix.version.resolution }} + uv pip install -e .[test,logging] --resolution=${{ matrix.version.resolution }} --system - name: Run Tests run: pytest --capture=no --cov --cov-report=xml From d7aaded455c7a0ccf05c83327edf47a950d706b5 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Wed, 11 Sep 2024 23:26:24 +0800 Subject: [PATCH 22/41] merge uv install stage? --- .github/workflows/test.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 6c234da..95b4a9a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -29,11 +29,9 @@ jobs: cache: pip cache-dependency-path: pyproject.toml - - name: Install uv - run: pip install uv - - - name: Install dependencies + - name: Install chgnet through uv run: | + pip install uv uv pip install -e .[test,logging] --resolution=${{ matrix.version.resolution }} --system - name: Run Tests From 47a77e059b65a6bce6bd80003148df40278c35fd Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Wed, 11 Sep 2024 23:32:20 +0800 Subject: [PATCH 23/41] fix typo in error message --- chgnet/graph/graph.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chgnet/graph/graph.py b/chgnet/graph/graph.py index ba619a7..a32e993 100644 --- a/chgnet/graph/graph.py +++ b/chgnet/graph/graph.py @@ -271,7 +271,7 @@ def line_graph_adjacency_list(self, cutoff) -> tuple[list[list[int]], list[int]] if len(self.directed_edges_list) != 2 * len(self.undirected_edges_list): raise ValueError( f"Error: number of directed edges={len(self.directed_edges_list)} != 2 " - f"* number of undirected edges={len(self.directed_edges_list)}!" + f"* number of undirected edges={len(self.undirected_edges_list)}!" f"This indicates directed edges are not complete" ) line_graph = [] From 570bfed458c8f7bac8d6c8b8a87f97f8eb167d53 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Wed, 11 Sep 2024 23:33:34 +0800 Subject: [PATCH 24/41] NEED CONFIRM: use torch.int32 over int for torch tensor --- chgnet/model/composition_model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chgnet/model/composition_model.py b/chgnet/model/composition_model.py index 4a7e0e9..71f0276 100644 --- a/chgnet/model/composition_model.py +++ b/chgnet/model/composition_model.py @@ -146,7 +146,7 @@ def fit( if isinstance(structure, Structure): atomic_number = torch.tensor( [site.specie.Z for site in structure], - dtype=int, + dtype=torch.int32, requires_grad=False, ) else: From ff8bf84c18ac9491467a7b09822838a87478f723 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Wed, 11 Sep 2024 23:40:12 +0800 Subject: [PATCH 25/41] raise error instead of systemexit when failure --- chgnet/graph/converter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chgnet/graph/converter.py b/chgnet/graph/converter.py index 477654c..3783b0a 100644 --- a/chgnet/graph/converter.py +++ b/chgnet/graph/converter.py @@ -150,7 +150,7 @@ def forward( # Report structures that failed creating bond graph # This happen occasionally with pymatgen version issue structure.to(filename="bond_graph_error.cif") - raise SystemExit( + raise RuntimeError( f"Failed creating bond graph for {graph_id}, check bond_graph_error.cif" ) from exc bond_graph = torch.tensor(bond_graph, dtype=torch.int32) From 1f400881ffee425267367fc1a8d73430060cc4ab Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Wed, 11 Sep 2024 23:47:22 +0800 Subject: [PATCH 26/41] make module level var all cap --- chgnet/graph/converter.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/chgnet/graph/converter.py b/chgnet/graph/converter.py index 3783b0a..4b26db5 100644 --- a/chgnet/graph/converter.py +++ b/chgnet/graph/converter.py @@ -3,7 +3,7 @@ import gc import sys import warnings -from typing import TYPE_CHECKING, Literal +from typing import TYPE_CHECKING import numpy as np import torch @@ -13,6 +13,8 @@ from chgnet.graph.graph import Graph, Node if TYPE_CHECKING: + from typing import Literal + from pymatgen.core import Structure from typing_extensions import Self @@ -21,7 +23,7 @@ except (ImportError, AttributeError): make_graph = None -datatype = torch.float32 +DATATYPE = torch.float32 class CrystalGraphConverter(nn.Module): @@ -122,10 +124,10 @@ def forward( requires_grad=False, ) atom_frac_coord = torch.tensor( - structure.frac_coords, dtype=datatype, requires_grad=True + structure.frac_coords, dtype=DATATYPE, requires_grad=True ) lattice = torch.tensor( - structure.lattice.matrix, dtype=datatype, requires_grad=True + structure.lattice.matrix, dtype=DATATYPE, requires_grad=True ) center_index, neighbor_index, image, distance = structure.get_neighbor_list( r=self.atom_graph_cutoff, sites=structure.sites, numerical_tol=1e-8 @@ -175,7 +177,7 @@ def forward( atomic_number=atomic_number, atom_frac_coord=atom_frac_coord, atom_graph=atom_graph, - neighbor_image=torch.tensor(image, dtype=datatype), + neighbor_image=torch.tensor(image, dtype=DATATYPE), directed2undirected=directed2undirected, undirected2directed=undirected2directed, bond_graph=bond_graph, From b60f5e48dcf154d2c9e0d128e7594074d039d60b Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Wed, 11 Sep 2024 23:57:01 +0800 Subject: [PATCH 27/41] fix: /Users/runner/work/chgnet/chgnet/chgnet/model/dynamics.py:297: DeprecationWarning: Use FrechetCellFilter for better convergence w.r.t. cell variables. atoms = ase_filter(atoms) --- chgnet/model/dynamics.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/chgnet/model/dynamics.py b/chgnet/model/dynamics.py index 37c2431..dee289d 100644 --- a/chgnet/model/dynamics.py +++ b/chgnet/model/dynamics.py @@ -10,6 +10,7 @@ import numpy as np from ase import Atoms, units from ase.calculators.calculator import Calculator, all_changes, all_properties +from ase.filters import FrechetCellFilter from ase.md.npt import NPT from ase.md.nptberendsen import Inhomogeneous_NPTBerendsen, NPTBerendsen from ase.md.nvtberendsen import NVTBerendsen @@ -294,7 +295,7 @@ def relax( cry_obs = CrystalFeasObserver(atoms) if relax_cell: - atoms = ase_filter(atoms) + atoms = FrechetCellFilter(atoms) optimizer: Optimizer = self.optimizer_class(atoms, **kwargs) optimizer.attach(obs, interval=loginterval) From e53337e52045f1afa9a82bfbea4c24e5c409ab19 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Thu, 12 Sep 2024 10:05:19 +0800 Subject: [PATCH 28/41] let's see if any array is not int64 --- chgnet/model/dynamics.py | 9 +++++---- tests/test_graph.py | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/chgnet/model/dynamics.py b/chgnet/model/dynamics.py index dee289d..05569cd 100644 --- a/chgnet/model/dynamics.py +++ b/chgnet/model/dynamics.py @@ -5,6 +5,7 @@ import io import pickle import sys +import warnings from typing import TYPE_CHECKING, Literal import numpy as np @@ -12,8 +13,7 @@ from ase.calculators.calculator import Calculator, all_changes, all_properties from ase.filters import FrechetCellFilter from ase.md.npt import NPT -from ase.md.nptberendsen import Inhomogeneous_NPTBerendsen, NPTBerendsen -from ase.md.nvtberendsen import NVTBerendsen +from ase.md.nptberendsen import Inhomogeneous_NPTBerendsen, NPTBerendsen, NVTBerendsen from ase.md.velocitydistribution import MaxwellBoltzmannDistribution, Stationary from ase.md.verlet import VelocityVerlet from ase.optimize.bfgs import BFGS @@ -611,11 +611,12 @@ def __init__( except Exception: bulk_modulus_au = 2 / 160.2176 compressibility_au = 1 / bulk_modulus_au - print( + warnings.warn( "Warning!!! Equation of State fitting failed, setting bulk " "modulus to 2 GPa. NPT simulation can proceed with incorrect " "pressure relaxation time." - "User input for bulk modulus is recommended." + "User input for bulk modulus is recommended.", + stacklevel=2, ) self.bulk_modulus = bulk_modulus diff --git a/tests/test_graph.py b/tests/test_graph.py index c52f883..583a1e7 100644 --- a/tests/test_graph.py +++ b/tests/test_graph.py @@ -59,8 +59,8 @@ def bigraph() -> Graph: bigraph.add_edge(0, 2, np.zeros(3), 2) bigraph.add_edge(1, 0, np.zeros(3), 1) bigraph.add_edge(1, 2, np.zeros(3), 5) - bigraph.add_edge(1, 1, np.array([0, 0, 1]), 4) - bigraph.add_edge(1, 1, np.array([0, 0, -1]), 4) + bigraph.add_edge(1, 1, np.array([0, 0, 1], dtype=np.int64), 4) + bigraph.add_edge(1, 1, np.array([0, 0, -1], dtype=np.int64), 4) bigraph.add_edge(2, 0, np.zeros(3), 2) bigraph.add_edge(2, 1, np.zeros(3), 5) return bigraph From 1b84de42b67c5a674cf7f4b5eb5949c5bfb1e0a9 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Thu, 12 Sep 2024 10:18:24 +0800 Subject: [PATCH 29/41] use setup-uv as Janosh suggested --- .github/workflows/test.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 95b4a9a..1989d35 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -22,16 +22,16 @@ jobs: - name: Check out repo uses: actions/checkout@v4 - - name: Set up Python - uses: actions/setup-python@v5 + - name: Install uv + uses: astral-sh/setup-uv@v2 with: - python-version: ${{ matrix.version.python }} - cache: pip - cache-dependency-path: pyproject.toml + enable-cache: true + + - name: Set up Python ${{ matrix.version.python }} + run: uv python install ${{ matrix.version.python }} - name: Install chgnet through uv run: | - pip install uv uv pip install -e .[test,logging] --resolution=${{ matrix.version.resolution }} --system - name: Run Tests From 59787a62f7d16184390707044f6fe45f7434b6a3 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Thu, 12 Sep 2024 10:20:56 +0800 Subject: [PATCH 30/41] try to fix package install --- .github/workflows/test.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1989d35..5870260 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -32,10 +32,11 @@ jobs: - name: Install chgnet through uv run: | - uv pip install -e .[test,logging] --resolution=${{ matrix.version.resolution }} --system + uv sync --all-extras --dev + # uv pip install -e .[test,logging] --resolution=${{ matrix.version.resolution }} --system - name: Run Tests - run: pytest --capture=no --cov --cov-report=xml + run: uv run pytest --capture=no --cov --cov-report=xml env: CHGNET_DEVICE: cpu From bda704b30efeddc72bc13935088158733a5d73e6 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Thu, 12 Sep 2024 10:24:22 +0800 Subject: [PATCH 31/41] NEED CONFIRM: drop python 3.9 --- README.md | 2 +- pyproject.toml | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1773c1e..72b41be 100755 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ ![GitHub repo size](https://img.shields.io/github/repo-size/CederGroupHub/chgnet?logo=github&logoColor=white&label=Repo%20Size) [![PyPI](https://img.shields.io/pypi/v/chgnet?logo=pypi&logoColor=white)](https://pypi.org/project/chgnet?logo=pypi&logoColor=white) [![Docs](https://img.shields.io/badge/API-Docs-blue?logo=readthedocs&logoColor=white)](https://chgnet.lbl.gov) -[![Requires Python 3.9+](https://img.shields.io/badge/Python-3.9+-blue.svg?logo=python&logoColor=white)](https://python.org/downloads) +[![Requires Python 3.10+](https://img.shields.io/badge/Python-3.10+-blue.svg?logo=python&logoColor=white)](https://python.org/downloads) diff --git a/pyproject.toml b/pyproject.toml index 18419c0..8830fb2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ name = "chgnet" version = "0.3.8" description = "Pretrained Universal Neural Network Potential for Charge-informed Atomistic Modeling" authors = [{ name = "Bowen Deng", email = "bowendeng@berkeley.edu" }] -requires-python = ">=3.9" +requires-python = ">=3.10" readme = "README.md" license = { text = "Modified BSD" } dependencies = [ @@ -19,7 +19,6 @@ classifiers = [ "Intended Audience :: Science/Research", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", - "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", From 4eed20591f7ee51f3d111eb9772cdf285ee7dfa8 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Thu, 12 Sep 2024 10:26:24 +0800 Subject: [PATCH 32/41] Revert "NEED CONFIRM: drop python 3.9" This reverts commit bda704b30efeddc72bc13935088158733a5d73e6. --- README.md | 2 +- pyproject.toml | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 72b41be..1773c1e 100755 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ ![GitHub repo size](https://img.shields.io/github/repo-size/CederGroupHub/chgnet?logo=github&logoColor=white&label=Repo%20Size) [![PyPI](https://img.shields.io/pypi/v/chgnet?logo=pypi&logoColor=white)](https://pypi.org/project/chgnet?logo=pypi&logoColor=white) [![Docs](https://img.shields.io/badge/API-Docs-blue?logo=readthedocs&logoColor=white)](https://chgnet.lbl.gov) -[![Requires Python 3.10+](https://img.shields.io/badge/Python-3.10+-blue.svg?logo=python&logoColor=white)](https://python.org/downloads) +[![Requires Python 3.9+](https://img.shields.io/badge/Python-3.9+-blue.svg?logo=python&logoColor=white)](https://python.org/downloads) diff --git a/pyproject.toml b/pyproject.toml index 8830fb2..18419c0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ name = "chgnet" version = "0.3.8" description = "Pretrained Universal Neural Network Potential for Charge-informed Atomistic Modeling" authors = [{ name = "Bowen Deng", email = "bowendeng@berkeley.edu" }] -requires-python = ">=3.10" +requires-python = ">=3.9" readme = "README.md" license = { text = "Modified BSD" } dependencies = [ @@ -19,6 +19,7 @@ classifiers = [ "Intended Audience :: Science/Research", "License :: OSI Approved :: BSD License", "Operating System :: OS Independent", + "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", From 1d1ec65cc31e1b1bda134e4a9813320a09616793 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Thu, 12 Sep 2024 10:28:02 +0800 Subject: [PATCH 33/41] use uv pip install for now --- .github/workflows/test.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 5870260..f146fe2 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,6 +7,9 @@ on: workflow_dispatch: workflow_call: +env: + UV_SYSTEM_PYTHON: 1 + jobs: tests: strategy: @@ -32,8 +35,7 @@ jobs: - name: Install chgnet through uv run: | - uv sync --all-extras --dev - # uv pip install -e .[test,logging] --resolution=${{ matrix.version.resolution }} --system + uv pip install -e .[test,logging] --resolution=${{ matrix.version.resolution }} - name: Run Tests run: uv run pytest --capture=no --cov --cov-report=xml From 4cafef7b69127404f01f0e0503eb1fdf247bc40a Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Thu, 12 Sep 2024 10:36:11 +0800 Subject: [PATCH 34/41] revert to traditional uv pip install for now as setup-uv doesn't have permission for some reason --- .github/workflows/test.yml | 19 ++++++++----------- chgnet/graph/cygraph.pyx | 2 +- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f146fe2..95b4a9a 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -7,9 +7,6 @@ on: workflow_dispatch: workflow_call: -env: - UV_SYSTEM_PYTHON: 1 - jobs: tests: strategy: @@ -25,20 +22,20 @@ jobs: - name: Check out repo uses: actions/checkout@v4 - - name: Install uv - uses: astral-sh/setup-uv@v2 + - name: Set up Python + uses: actions/setup-python@v5 with: - enable-cache: true - - - name: Set up Python ${{ matrix.version.python }} - run: uv python install ${{ matrix.version.python }} + python-version: ${{ matrix.version.python }} + cache: pip + cache-dependency-path: pyproject.toml - name: Install chgnet through uv run: | - uv pip install -e .[test,logging] --resolution=${{ matrix.version.resolution }} + pip install uv + uv pip install -e .[test,logging] --resolution=${{ matrix.version.resolution }} --system - name: Run Tests - run: uv run pytest --capture=no --cov --cov-report=xml + run: pytest --capture=no --cov --cov-report=xml env: CHGNET_DEVICE: cpu diff --git a/chgnet/graph/cygraph.pyx b/chgnet/graph/cygraph.pyx index 6540d92..b47686c 100644 --- a/chgnet/graph/cygraph.pyx +++ b/chgnet/graph/cygraph.pyx @@ -81,7 +81,7 @@ def make_graph( chg_UndirectedEdge = chgnet.graph.graph.UndirectedEdge - image_np = np.asarray(image) + image_np = np.asarray(image, dtype=np.int64) cdef LongToDirectedEdgeList** node_neighbors cdef Node this_node From d1bf176d641175980dbe997c60d4053d385de7ab Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Thu, 12 Sep 2024 10:53:14 +0800 Subject: [PATCH 35/41] fix more missing type changes --- chgnet/graph/cygraph.pyx | 48 ++++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/chgnet/graph/cygraph.pyx b/chgnet/graph/cygraph.pyx index b47686c..ac1da92 100644 --- a/chgnet/graph/cygraph.pyx +++ b/chgnet/graph/cygraph.pyx @@ -17,50 +17,50 @@ from libc.stdlib cimport free cdef extern from 'fast_converter_libraries/create_graph.c': ctypedef struct Node: - long index + np.int64_t index LongToDirectedEdgeList* neighbors - long num_neighbors + np.int64_t num_neighbors ctypedef struct NodeIndexPair: - long center - long neighbor + np.int64_t center + np.int64_t neighbor ctypedef struct UndirectedEdge: NodeIndexPair nodes - long index - long* directed_edge_indices - long num_directed_edges - double distance + np.int64_t index + np.int64_t* directed_edge_indices + np.int64_t num_directed_edges + np.float64_t distance ctypedef struct DirectedEdge: NodeIndexPair nodes - long index - const long* image - long undirected_edge_index - double distance + np.int64_t index + const np.int64_t* image + np.int64_t undirected_edge_index + np.float64_t distance ctypedef struct LongToDirectedEdgeList: - long key + np.int64_t key DirectedEdge** directed_edges_list int num_directed_edges_in_group ctypedef struct ReturnElems2: - long num_nodes - long num_directed_edges - long num_undirected_edges + np.int64_t num_nodes + np.int64_t num_directed_edges + np.int64_t num_undirected_edges Node* nodes UndirectedEdge** undirected_edges_list DirectedEdge** directed_edges_list ReturnElems2* create_graph( - long* center_index, - long n_e, - long* neighbor_index, - long* image, - double* distance, - long num_atoms) + np.int64_t* center_index, + np.int64_t n_e, + np.int64_t* neighbor_index, + np.int64_t* image, + np.float64_t* distance, + np.int64_t num_atoms) - void free_LongToDirectedEdgeList_in_nodes(Node* nodes, long num_nodes) + void free_LongToDirectedEdgeList_in_nodes(Node* nodes, np.int64_t num_nodes) LongToDirectedEdgeList** get_neighbors(Node* node) @@ -74,7 +74,7 @@ def make_graph( const np.int64_t num_atoms ): cdef ReturnElems2* returned - returned = create_graph( ¢er_index[0], n_e, &neighbor_index[0], &image[0][0], &distance[0], num_atoms) + returned = create_graph( ¢er_index[0], n_e, &neighbor_index[0], &image[0][0], &distance[0], num_atoms) chg_DirectedEdge = chgnet.graph.graph.DirectedEdge chg_Node = chgnet.graph.graph.Node From 107fb025078517a7df38b19303b0de89ac767f71 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Thu, 12 Sep 2024 11:38:02 +0800 Subject: [PATCH 36/41] revert changes to cygraph.pyx --- chgnet/graph/cygraph.pyx | 68 +++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 36 deletions(-) diff --git a/chgnet/graph/cygraph.pyx b/chgnet/graph/cygraph.pyx index ac1da92..7b82fda 100644 --- a/chgnet/graph/cygraph.pyx +++ b/chgnet/graph/cygraph.pyx @@ -7,81 +7,77 @@ # cython: profile=False # distutils: language = c -import numpy as np -cimport numpy as np - import chgnet.graph.graph - +import numpy as np from libc.stdlib cimport free - cdef extern from 'fast_converter_libraries/create_graph.c': ctypedef struct Node: - np.int64_t index + long index LongToDirectedEdgeList* neighbors - np.int64_t num_neighbors + long num_neighbors ctypedef struct NodeIndexPair: - np.int64_t center - np.int64_t neighbor + long center + long neighbor ctypedef struct UndirectedEdge: NodeIndexPair nodes - np.int64_t index - np.int64_t* directed_edge_indices - np.int64_t num_directed_edges - np.float64_t distance + long index + long* directed_edge_indices + long num_directed_edges + double distance ctypedef struct DirectedEdge: NodeIndexPair nodes - np.int64_t index - const np.int64_t* image - np.int64_t undirected_edge_index - np.float64_t distance + long index + const long* image + long undirected_edge_index + double distance ctypedef struct LongToDirectedEdgeList: - np.int64_t key + long key DirectedEdge** directed_edges_list int num_directed_edges_in_group ctypedef struct ReturnElems2: - np.int64_t num_nodes - np.int64_t num_directed_edges - np.int64_t num_undirected_edges + long num_nodes + long num_directed_edges + long num_undirected_edges Node* nodes UndirectedEdge** undirected_edges_list DirectedEdge** directed_edges_list ReturnElems2* create_graph( - np.int64_t* center_index, - np.int64_t n_e, - np.int64_t* neighbor_index, - np.int64_t* image, - np.float64_t* distance, - np.int64_t num_atoms) + long* center_index, + long n_e, + long* neighbor_index, + long* image, + double* distance, + long num_atoms) - void free_LongToDirectedEdgeList_in_nodes(Node* nodes, np.int64_t num_nodes) + void free_LongToDirectedEdgeList_in_nodes(Node* nodes, long num_nodes) LongToDirectedEdgeList** get_neighbors(Node* node) def make_graph( - const np.int64_t[::1] center_index, - const np.int64_t n_e, - const np.int64_t[::1] neighbor_index, - const np.int64_t[:, ::1] image, - const np.float64_t[::1] distance, - const np.int64_t num_atoms + const long[::1] center_index, + const long n_e, + const long[::1] neighbor_index, + const long[:, ::1] image, + const double[::1] distance, + const long num_atoms ): cdef ReturnElems2* returned - returned = create_graph( ¢er_index[0], n_e, &neighbor_index[0], &image[0][0], &distance[0], num_atoms) + returned = create_graph( ¢er_index[0], n_e, &neighbor_index[0], &image[0][0], &distance[0], num_atoms) chg_DirectedEdge = chgnet.graph.graph.DirectedEdge chg_Node = chgnet.graph.graph.Node chg_UndirectedEdge = chgnet.graph.graph.UndirectedEdge - image_np = np.asarray(image, dtype=np.int64) + image_np = np.asarray(image) cdef LongToDirectedEdgeList** node_neighbors cdef Node this_node From 190d6e8b5891e0fb0f85182bb95ddcab38a3cc67 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Thu, 12 Sep 2024 11:40:52 +0800 Subject: [PATCH 37/41] revert changes related to np2 --- pyproject.toml | 3 +-- tests/test_graph.py | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 18419c0..5e32bf2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -9,7 +9,7 @@ license = { text = "Modified BSD" } dependencies = [ "ase>=3.23.0", "cython>=3", - "numpy>=1.26", + "numpy>=1.26,<2", "nvidia-ml-py3>=7.352.0", "pymatgen>=2024.9.10", "torch>=1.11.0", @@ -52,7 +52,6 @@ requires = [ "Cython", "setuptools>=65", "wheel", - "numpy>=2.0.0", ] build-backend = "setuptools.build_meta" diff --git a/tests/test_graph.py b/tests/test_graph.py index 583a1e7..c52f883 100644 --- a/tests/test_graph.py +++ b/tests/test_graph.py @@ -59,8 +59,8 @@ def bigraph() -> Graph: bigraph.add_edge(0, 2, np.zeros(3), 2) bigraph.add_edge(1, 0, np.zeros(3), 1) bigraph.add_edge(1, 2, np.zeros(3), 5) - bigraph.add_edge(1, 1, np.array([0, 0, 1], dtype=np.int64), 4) - bigraph.add_edge(1, 1, np.array([0, 0, -1], dtype=np.int64), 4) + bigraph.add_edge(1, 1, np.array([0, 0, 1]), 4) + bigraph.add_edge(1, 1, np.array([0, 0, -1]), 4) bigraph.add_edge(2, 0, np.zeros(3), 2) bigraph.add_edge(2, 1, np.zeros(3), 5) return bigraph From c9e8e5f1e58267f1014da4499bf5e25619989b85 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Thu, 12 Sep 2024 11:43:09 +0800 Subject: [PATCH 38/41] revert more np2 related changes --- chgnet/graph/converter.py | 2 +- pyproject.toml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/chgnet/graph/converter.py b/chgnet/graph/converter.py index 4b26db5..b83ea5a 100644 --- a/chgnet/graph/converter.py +++ b/chgnet/graph/converter.py @@ -250,7 +250,7 @@ def _create_graph_fast( """ center_index = np.ascontiguousarray(center_index) neighbor_index = np.ascontiguousarray(neighbor_index) - image = np.ascontiguousarray(image, dtype=np.int64) + image = np.ascontiguousarray(image, dtype=np.int_) distance = np.ascontiguousarray(distance) gc_saved = gc.get_threshold() gc.set_threshold(0) diff --git a/pyproject.toml b/pyproject.toml index 5e32bf2..ceae6e9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,6 +52,7 @@ requires = [ "Cython", "setuptools>=65", "wheel", + "numpy>=2.0.0", ] build-backend = "setuptools.build_meta" From 8875487117a9f1bb37b3b48789aab1cb6a7dd197 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Thu, 12 Sep 2024 11:51:38 +0800 Subject: [PATCH 39/41] revert more np related changes --- pyproject.toml | 3 +-- setup.py | 2 -- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ceae6e9..00a2fa7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ dependencies = [ "cython>=3", "numpy>=1.26,<2", "nvidia-ml-py3>=7.352.0", - "pymatgen>=2024.9.10", + "pymatgen<2024.9.10", "torch>=1.11.0", "typing-extensions>=4.12", ] @@ -52,7 +52,6 @@ requires = [ "Cython", "setuptools>=65", "wheel", - "numpy>=2.0.0", ] build-backend = "setuptools.build_meta" diff --git a/setup.py b/setup.py index ab494d5..e949209 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,5 @@ from __future__ import annotations -import numpy as np from setuptools import Extension, setup ext_modules = [Extension("chgnet.graph.cygraph", ["chgnet/graph/cygraph.pyx"])] @@ -8,5 +7,4 @@ setup( ext_modules=ext_modules, setup_requires=["Cython"], - include_dirs=[np.get_include()], ) From 8c3ffa2fadb854007340ed9692eedd47237e1407 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Thu, 12 Sep 2024 11:55:08 +0800 Subject: [PATCH 40/41] pin pmg 24.8.9 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 00a2fa7..bfcf21f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -11,7 +11,7 @@ dependencies = [ "cython>=3", "numpy>=1.26,<2", "nvidia-ml-py3>=7.352.0", - "pymatgen<2024.9.10", + "pymatgen==2024.8.9", "torch>=1.11.0", "typing-extensions>=4.12", ] From aeb90530c51d80708031b66248430fc33d330c39 Mon Sep 17 00:00:00 2001 From: "Haoyu (Daniel)" Date: Thu, 12 Sep 2024 19:47:25 +0800 Subject: [PATCH 41/41] Revert "fix: /Users/runner/work/chgnet/chgnet/chgnet/model/dynamics.py:297: DeprecationWarning: Use FrechetCellFilter for better convergence w.r.t. cell variables." This reverts commit b60f5e48dcf154d2c9e0d128e7594074d039d60b. --- chgnet/model/dynamics.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/chgnet/model/dynamics.py b/chgnet/model/dynamics.py index 05569cd..c1a8601 100644 --- a/chgnet/model/dynamics.py +++ b/chgnet/model/dynamics.py @@ -11,7 +11,6 @@ import numpy as np from ase import Atoms, units from ase.calculators.calculator import Calculator, all_changes, all_properties -from ase.filters import FrechetCellFilter from ase.md.npt import NPT from ase.md.nptberendsen import Inhomogeneous_NPTBerendsen, NPTBerendsen, NVTBerendsen from ase.md.velocitydistribution import MaxwellBoltzmannDistribution, Stationary @@ -295,7 +294,7 @@ def relax( cry_obs = CrystalFeasObserver(atoms) if relax_cell: - atoms = FrechetCellFilter(atoms) + atoms = ase_filter(atoms) optimizer: Optimizer = self.optimizer_class(atoms, **kwargs) optimizer.attach(obs, interval=loginterval)