From 063f8e711ea1d04e5573298dea5d6f2025e206bd Mon Sep 17 00:00:00 2001 From: anyangml Date: Sun, 3 Mar 2024 03:49:45 +0000 Subject: [PATCH 01/59] feat: add zbl training --- .../model/atomic_model/linear_atomic_model.py | 32 ++++++++++++++++++- deepmd/pt/train/training.py | 6 +++- 2 files changed, 36 insertions(+), 2 deletions(-) diff --git a/deepmd/pt/model/atomic_model/linear_atomic_model.py b/deepmd/pt/model/atomic_model/linear_atomic_model.py index 5efbe533da..2e761803e6 100644 --- a/deepmd/pt/model/atomic_model/linear_atomic_model.py +++ b/deepmd/pt/model/atomic_model/linear_atomic_model.py @@ -28,7 +28,9 @@ from deepmd.utils.version import ( check_version_compatibility, ) - +from deepmd.utils.path import ( + DPPath, +) from .base_atomic_model import ( BaseAtomicModel, ) @@ -307,6 +309,34 @@ def __init__( # this is a placeholder being updated in _compute_weight, to handle Jit attribute init error. self.zbl_weight = torch.empty(0, dtype=torch.float64, device=env.DEVICE) + def compute_or_load_stat( + self, + sampled_func, + stat_file_path: Optional[DPPath] = None, + ): + """ + Compute or load the statistics parameters of the model, + such as mean and standard deviation of descriptors or the energy bias of the fitting net. + When `sampled` is provided, all the statistics parameters will be calculated (or re-calculated for update), + and saved in the `stat_file_path`(s). + When `sampled` is not provided, it will check the existence of `stat_file_path`(s) + and load the calculated statistics parameters. + + Parameters + ---------- + sampled_func + The lazy sampled function to get data frames from different data systems. + stat_file_path + The dictionary of paths to the statistics files. + """ + if stat_file_path is not None and self.type_map is not None: + # descriptors and fitting net with different type_map + # should not share the same parameters + stat_file_path /= " ".join(self.type_map) + self.dp_model.descriptor.compute_input_stats(sampled_func, stat_file_path) + if self.dp_model.fitting_net is not None: + self.dp_model.fitting_net.compute_output_stats(sampled_func, stat_file_path) + def serialize(self) -> dict: dd = BaseAtomicModel.serialize(self) dd.update( diff --git a/deepmd/pt/train/training.py b/deepmd/pt/train/training.py index 77e6b1c709..c62f3f855d 100644 --- a/deepmd/pt/train/training.py +++ b/deepmd/pt/train/training.py @@ -26,6 +26,7 @@ ) from deepmd.pt.model.model import ( get_model, + get_zbl_model, ) from deepmd.pt.optimizer import ( KFOptimizerWrapper, @@ -243,7 +244,10 @@ def get_sample(): def get_single_model( _model_params, ): - model = get_model(deepcopy(_model_params)).to(DEVICE) + if "use_srtab" in _model_params: + model = get_zbl_model(deepcopy(_model_params)).to(DEVICE) + else: + model = get_model(deepcopy(_model_params)).to(DEVICE) return model def get_lr(lr_params): From 8f06ab0a20ce3fee678eae48062da9ae01313e9e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 3 Mar 2024 03:51:17 +0000 Subject: [PATCH 02/59] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- deepmd/pt/model/atomic_model/linear_atomic_model.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/deepmd/pt/model/atomic_model/linear_atomic_model.py b/deepmd/pt/model/atomic_model/linear_atomic_model.py index 2e761803e6..09fec6c92a 100644 --- a/deepmd/pt/model/atomic_model/linear_atomic_model.py +++ b/deepmd/pt/model/atomic_model/linear_atomic_model.py @@ -25,12 +25,13 @@ get_multiple_nlist_key, nlist_distinguish_types, ) -from deepmd.utils.version import ( - check_version_compatibility, -) from deepmd.utils.path import ( DPPath, ) +from deepmd.utils.version import ( + check_version_compatibility, +) + from .base_atomic_model import ( BaseAtomicModel, ) From 2f7fa773df912c483aeee4fe160c34409c9cb0a6 Mon Sep 17 00:00:00 2001 From: anyangml Date: Sun, 3 Mar 2024 05:08:32 +0000 Subject: [PATCH 03/59] fix: add atom bias --- .../model/atomic_model/linear_atomic_model.py | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/deepmd/pt/model/atomic_model/linear_atomic_model.py b/deepmd/pt/model/atomic_model/linear_atomic_model.py index 09fec6c92a..580577d559 100644 --- a/deepmd/pt/model/atomic_model/linear_atomic_model.py +++ b/deepmd/pt/model/atomic_model/linear_atomic_model.py @@ -187,14 +187,19 @@ def forward_atomic( weights = self._compute_weight(extended_coord, extended_atype, nlists_) + if self.models[0].fitting_net.bias_atom_e is not None: + self.atomic_bias = self.models[0].fitting_net.bias_atom_e if self.atomic_bias is not None: - raise NotImplementedError("Need to add bias in a future PR.") - else: - fit_ret = { - "energy": torch.sum( - torch.stack(ener_list) * torch.stack(weights), dim=0 - ), - } # (nframes, nloc, 1) + # nf, nloc, 1; ntype, 1 + # need to add bias to corresponding types + atype = extended_atype[:,:nloc] + ener_list[1] += self.atomic_bias[atype] + # raise NotImplementedError("Need to add bias in a future PR.") + fit_ret = { + "energy": torch.sum( + torch.stack(ener_list) * torch.stack(weights), dim=0 + ), + } # (nframes, nloc, 1) return fit_ret def fitting_output_def(self) -> FittingOutputDef: From 672563c4782070a9c6b3d2cc09d933dc4dcb5628 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 3 Mar 2024 05:09:03 +0000 Subject: [PATCH 04/59] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- deepmd/pt/model/atomic_model/linear_atomic_model.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/deepmd/pt/model/atomic_model/linear_atomic_model.py b/deepmd/pt/model/atomic_model/linear_atomic_model.py index 580577d559..cf714c6350 100644 --- a/deepmd/pt/model/atomic_model/linear_atomic_model.py +++ b/deepmd/pt/model/atomic_model/linear_atomic_model.py @@ -188,17 +188,15 @@ def forward_atomic( weights = self._compute_weight(extended_coord, extended_atype, nlists_) if self.models[0].fitting_net.bias_atom_e is not None: - self.atomic_bias = self.models[0].fitting_net.bias_atom_e + self.atomic_bias = self.models[0].fitting_net.bias_atom_e if self.atomic_bias is not None: # nf, nloc, 1; ntype, 1 # need to add bias to corresponding types - atype = extended_atype[:,:nloc] + atype = extended_atype[:, :nloc] ener_list[1] += self.atomic_bias[atype] # raise NotImplementedError("Need to add bias in a future PR.") fit_ret = { - "energy": torch.sum( - torch.stack(ener_list) * torch.stack(weights), dim=0 - ), + "energy": torch.sum(torch.stack(ener_list) * torch.stack(weights), dim=0), } # (nframes, nloc, 1) return fit_ret From 52ab95fb2af6df5511da9599885759cc9a6da493 Mon Sep 17 00:00:00 2001 From: anyangml Date: Sun, 3 Mar 2024 05:20:59 +0000 Subject: [PATCH 05/59] chore: refactor --- deepmd/pt/model/atomic_model/linear_atomic_model.py | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/deepmd/pt/model/atomic_model/linear_atomic_model.py b/deepmd/pt/model/atomic_model/linear_atomic_model.py index cf714c6350..40dc9a4a9c 100644 --- a/deepmd/pt/model/atomic_model/linear_atomic_model.py +++ b/deepmd/pt/model/atomic_model/linear_atomic_model.py @@ -333,13 +333,7 @@ def compute_or_load_stat( stat_file_path The dictionary of paths to the statistics files. """ - if stat_file_path is not None and self.type_map is not None: - # descriptors and fitting net with different type_map - # should not share the same parameters - stat_file_path /= " ".join(self.type_map) - self.dp_model.descriptor.compute_input_stats(sampled_func, stat_file_path) - if self.dp_model.fitting_net is not None: - self.dp_model.fitting_net.compute_output_stats(sampled_func, stat_file_path) + self.dp_model.compute_or_load(sampled_func, stat_file_path) def serialize(self) -> dict: dd = BaseAtomicModel.serialize(self) From 993efe96ac1f9218f50888b19db57a52091e5f93 Mon Sep 17 00:00:00 2001 From: anyangml Date: Sun, 3 Mar 2024 07:23:59 +0000 Subject: [PATCH 06/59] fix: add pairtab stat --- .../model/atomic_model/linear_atomic_model.py | 19 ++--- .../atomic_model/pairtab_atomic_model.py | 77 ++++++++++++++++++- 2 files changed, 85 insertions(+), 11 deletions(-) diff --git a/deepmd/pt/model/atomic_model/linear_atomic_model.py b/deepmd/pt/model/atomic_model/linear_atomic_model.py index 40dc9a4a9c..48c6128a6c 100644 --- a/deepmd/pt/model/atomic_model/linear_atomic_model.py +++ b/deepmd/pt/model/atomic_model/linear_atomic_model.py @@ -187,14 +187,14 @@ def forward_atomic( weights = self._compute_weight(extended_coord, extended_atype, nlists_) - if self.models[0].fitting_net.bias_atom_e is not None: - self.atomic_bias = self.models[0].fitting_net.bias_atom_e - if self.atomic_bias is not None: - # nf, nloc, 1; ntype, 1 - # need to add bias to corresponding types - atype = extended_atype[:, :nloc] - ener_list[1] += self.atomic_bias[atype] - # raise NotImplementedError("Need to add bias in a future PR.") + atype = extended_atype[:, :nloc] + for idx, m in enumerate(self.models): + if isinstance(m, DPAtomicModel) and m.fitting_net is not None: + bias_atom_e = m.fitting_net.bias_atom_e + elif isinstance(m, PairTabAtomicModel): + bias_atom_e = m.bias_atom_e + ener_list[idx] += bias_atom_e[atype] + fit_ret = { "energy": torch.sum(torch.stack(ener_list) * torch.stack(weights), dim=0), } # (nframes, nloc, 1) @@ -333,7 +333,8 @@ def compute_or_load_stat( stat_file_path The dictionary of paths to the statistics files. """ - self.dp_model.compute_or_load(sampled_func, stat_file_path) + self.dp_model.compute_or_load_stat(sampled_func, stat_file_path) + self.zbl_model.compute_output_stats(sampled_func, stat_file_path) def serialize(self) -> dict: dd = BaseAtomicModel.serialize(self) diff --git a/deepmd/pt/model/atomic_model/pairtab_atomic_model.py b/deepmd/pt/model/atomic_model/pairtab_atomic_model.py index 47a20d3be9..32bbd736c2 100644 --- a/deepmd/pt/model/atomic_model/pairtab_atomic_model.py +++ b/deepmd/pt/model/atomic_model/pairtab_atomic_model.py @@ -1,13 +1,17 @@ # SPDX-License-Identifier: LGPL-3.0-or-later import copy from typing import ( + Callable, Dict, List, Optional, Union, ) - +from deepmd.pt.utils import ( + env, +) import torch +import numpy as np from deepmd.dpmodel import ( FittingOutputDef, @@ -19,11 +23,19 @@ from deepmd.utils.version import ( check_version_compatibility, ) +from deepmd.pt.utils.utils import ( + to_numpy_array, +) +from deepmd.utils.out_stat import ( + compute_stats_from_redu, +) from .base_atomic_model import ( BaseAtomicModel, ) - +from deepmd.utils.path import ( + DPPath, +) class PairTabAtomicModel(torch.nn.Module, BaseAtomicModel): """Pairwise tabulation energy model. @@ -57,6 +69,7 @@ def __init__( self.tab_file = tab_file self.rcut = rcut self.tab = self._set_pairtab(tab_file, rcut) + BaseAtomicModel.__init__(self, **kwargs) # handle deserialization with no input file @@ -70,6 +83,7 @@ def __init__( else: self.register_buffer("tab_info", None) self.register_buffer("tab_data", None) + self.bias_atom_e = None # self.model_type = "ener" # self.model_version = MODEL_VERSION ## this shoud be in the parent class @@ -153,6 +167,65 @@ def deserialize(cls, data) -> "PairTabAtomicModel": tab_model.register_buffer("tab_info", torch.from_numpy(tab_model.tab.tab_info)) tab_model.register_buffer("tab_data", torch.from_numpy(tab_model.tab.tab_data)) return tab_model + + def compute_output_stats( + self, + merged: Union[Callable[[], List[dict]], List[dict]], + stat_file_path: Optional[DPPath] = None, + ): + """ + Compute the output statistics (e.g. energy bias) for the fitting net from packed data. + + Parameters + ---------- + merged : Union[Callable[[], List[dict]], List[dict]] + - List[dict]: A list of data samples from various data systems. + Each element, `merged[i]`, is a data dictionary containing `keys`: `torch.Tensor` + originating from the `i`-th data system. + - Callable[[], List[dict]]: A lazy function that returns data samples in the above format + only when needed. Since the sampling process can be slow and memory-intensive, + the lazy function helps by only sampling once. + stat_file_path : Optional[DPPath] + The path to the stat file. + + """ + if stat_file_path is not None: + stat_file_path = stat_file_path / "bias_atom_e" + if stat_file_path is not None and stat_file_path.is_file(): + bias_atom_e = stat_file_path.load_numpy() + else: + if callable(merged): + # only get data for once + sampled = merged() + else: + sampled = merged + energy = [item["energy"] for item in sampled] + data_mixed_type = "real_natoms_vec" in sampled[0] + if data_mixed_type: + input_natoms = [item["real_natoms_vec"] for item in sampled] + else: + input_natoms = [item["natoms"] for item in sampled] + # shape: (nframes, ndim) + merged_energy = to_numpy_array(torch.cat(energy)) + # shape: (nframes, ntypes) + merged_natoms = to_numpy_array(torch.cat(input_natoms)[:, 2:]) + + bias_atom_e, _ = compute_stats_from_redu( + merged_energy, + merged_natoms, + assigned_bias=None, + rcond=None, + ) + if stat_file_path is not None: + stat_file_path.save_numpy(bias_atom_e) + assert all(x is not None for x in [bias_atom_e]) + ntypes = merged_natoms.shape[1] + self.bias_atom_e = torch.empty([ntypes, 1], dtype=torch.float64, device=env.DEVICE) + self.bias_atom_e.copy_( + torch.tensor(bias_atom_e, device=env.DEVICE).view( + [ntypes, 1] + ) + ) def forward_atomic( self, From 897f9f34f2ea973dc7ce4eca192a540df9b1f3d6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 3 Mar 2024 07:24:27 +0000 Subject: [PATCH 07/59] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../atomic_model/pairtab_atomic_model.py | 39 ++++++++++--------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/deepmd/pt/model/atomic_model/pairtab_atomic_model.py b/deepmd/pt/model/atomic_model/pairtab_atomic_model.py index 32bbd736c2..0004d44493 100644 --- a/deepmd/pt/model/atomic_model/pairtab_atomic_model.py +++ b/deepmd/pt/model/atomic_model/pairtab_atomic_model.py @@ -7,21 +7,15 @@ Optional, Union, ) -from deepmd.pt.utils import ( - env, -) + import torch -import numpy as np from deepmd.dpmodel import ( FittingOutputDef, OutputVariableDef, ) -from deepmd.utils.pair_tab import ( - PairTab, -) -from deepmd.utils.version import ( - check_version_compatibility, +from deepmd.pt.utils import ( + env, ) from deepmd.pt.utils.utils import ( to_numpy_array, @@ -29,13 +23,20 @@ from deepmd.utils.out_stat import ( compute_stats_from_redu, ) - -from .base_atomic_model import ( - BaseAtomicModel, +from deepmd.utils.pair_tab import ( + PairTab, ) from deepmd.utils.path import ( DPPath, ) +from deepmd.utils.version import ( + check_version_compatibility, +) + +from .base_atomic_model import ( + BaseAtomicModel, +) + class PairTabAtomicModel(torch.nn.Module, BaseAtomicModel): """Pairwise tabulation energy model. @@ -69,7 +70,7 @@ def __init__( self.tab_file = tab_file self.rcut = rcut self.tab = self._set_pairtab(tab_file, rcut) - + BaseAtomicModel.__init__(self, **kwargs) # handle deserialization with no input file @@ -167,7 +168,7 @@ def deserialize(cls, data) -> "PairTabAtomicModel": tab_model.register_buffer("tab_info", torch.from_numpy(tab_model.tab.tab_info)) tab_model.register_buffer("tab_data", torch.from_numpy(tab_model.tab.tab_data)) return tab_model - + def compute_output_stats( self, merged: Union[Callable[[], List[dict]], List[dict]], @@ -209,7 +210,7 @@ def compute_output_stats( merged_energy = to_numpy_array(torch.cat(energy)) # shape: (nframes, ntypes) merged_natoms = to_numpy_array(torch.cat(input_natoms)[:, 2:]) - + bias_atom_e, _ = compute_stats_from_redu( merged_energy, merged_natoms, @@ -220,11 +221,11 @@ def compute_output_stats( stat_file_path.save_numpy(bias_atom_e) assert all(x is not None for x in [bias_atom_e]) ntypes = merged_natoms.shape[1] - self.bias_atom_e = torch.empty([ntypes, 1], dtype=torch.float64, device=env.DEVICE) + self.bias_atom_e = torch.empty( + [ntypes, 1], dtype=torch.float64, device=env.DEVICE + ) self.bias_atom_e.copy_( - torch.tensor(bias_atom_e, device=env.DEVICE).view( - [ntypes, 1] - ) + torch.tensor(bias_atom_e, device=env.DEVICE).view([ntypes, 1]) ) def forward_atomic( From 701cb55759a3a6167752e6ed79932d351f81b14e Mon Sep 17 00:00:00 2001 From: anyangml Date: Sun, 3 Mar 2024 07:48:17 +0000 Subject: [PATCH 08/59] fix: add UTs --- source/tests/pt/test_training.py | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/source/tests/pt/test_training.py b/source/tests/pt/test_training.py index bcb8c6c188..4d6e34bbaa 100644 --- a/source/tests/pt/test_training.py +++ b/source/tests/pt/test_training.py @@ -21,6 +21,7 @@ model_dpa2, model_hybrid, model_se_e2_a, + model_zbl, ) @@ -63,9 +64,14 @@ def test_trainable(self): trainer_fix.run() model_dict_after_training = deepcopy(trainer_fix.model.state_dict()) for key in model_dict_before_training: - torch.testing.assert_close( - model_dict_before_training[key], model_dict_after_training[key] - ) + if model_dict_before_training[key].shape == model_dict_after_training[key].shape: + torch.testing.assert_close( + model_dict_before_training[key], model_dict_after_training[key] + ) + else: + torch.testing.assert_close( + model_dict_before_training[key].flatten(), model_dict_after_training[key].flatten() + ) self.tearDown() def tearDown(self): @@ -93,6 +99,21 @@ def setUp(self): def tearDown(self) -> None: DPTrainTest.tearDown(self) +class TestEnergyZBLModelSeA(unittest.TestCase, DPTrainTest): + def setUp(self): + input_json = str(Path(__file__).parent / "water/zbl.json") + with open(input_json) as f: + self.config = json.load(f) + data_file = [str(Path(__file__).parent / "water/data/data_0")] + self.config["training"]["training_data"]["systems"] = data_file + self.config["training"]["validation_data"]["systems"] = data_file + self.config["model"] = deepcopy(model_zbl) + self.config["training"]["numb_steps"] = 1 + self.config["training"]["save_freq"] = 1 + + def tearDown(self) -> None: + DPTrainTest.tearDown(self) + class TestFparam(unittest.TestCase, DPTrainTest): """Test if `fparam` can be loaded correctly.""" From e27a816df6b9bb39b54851cf516d7857e8dede41 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 3 Mar 2024 07:49:11 +0000 Subject: [PATCH 09/59] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- source/tests/pt/test_training.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/source/tests/pt/test_training.py b/source/tests/pt/test_training.py index 4d6e34bbaa..41eb0e2a7b 100644 --- a/source/tests/pt/test_training.py +++ b/source/tests/pt/test_training.py @@ -64,13 +64,17 @@ def test_trainable(self): trainer_fix.run() model_dict_after_training = deepcopy(trainer_fix.model.state_dict()) for key in model_dict_before_training: - if model_dict_before_training[key].shape == model_dict_after_training[key].shape: + if ( + model_dict_before_training[key].shape + == model_dict_after_training[key].shape + ): torch.testing.assert_close( model_dict_before_training[key], model_dict_after_training[key] ) else: torch.testing.assert_close( - model_dict_before_training[key].flatten(), model_dict_after_training[key].flatten() + model_dict_before_training[key].flatten(), + model_dict_after_training[key].flatten(), ) self.tearDown() @@ -99,6 +103,7 @@ def setUp(self): def tearDown(self) -> None: DPTrainTest.tearDown(self) + class TestEnergyZBLModelSeA(unittest.TestCase, DPTrainTest): def setUp(self): input_json = str(Path(__file__).parent / "water/zbl.json") From dc30bbd95730981467319cb3b9859bc227beaa95 Mon Sep 17 00:00:00 2001 From: anyangml Date: Sun, 3 Mar 2024 07:51:50 +0000 Subject: [PATCH 10/59] fix: add UT input --- source/tests/pt/model/water/zbl.json | 92 ++++++++++++++++++++++++++++ 1 file changed, 92 insertions(+) create mode 100644 source/tests/pt/model/water/zbl.json diff --git a/source/tests/pt/model/water/zbl.json b/source/tests/pt/model/water/zbl.json new file mode 100644 index 0000000000..cb5602d92d --- /dev/null +++ b/source/tests/pt/model/water/zbl.json @@ -0,0 +1,92 @@ +{ + "_comment1": " model parameters", + "model": { + "use_srtab": "H2O_tab_potential.txt", + "smin_alpha": 0.1, + "sw_rmin": 0.8, + "sw_rmax": 1.0, + "type_map": [ + "O", + "H" + ], + "descriptor": { + "type": "se_e2_a", + "sel": [ + 46, + 92 + ], + "rcut_smth": 0.50, + "rcut": 6.00, + "neuron": [ + 25, + 50, + 100 + ], + "resnet_dt": false, + "axis_neuron": 16, + "type_one_side": true, + "precision": "float64", + "seed": 1, + "_comment2": " that's all" + }, + "fitting_net": { + "neuron": [ + 240, + 240, + 240 + ], + "resnet_dt": true, + "precision": "float64", + "seed": 1, + "_comment3": " that's all" + }, + "_comment4": " that's all" + }, + + "learning_rate": { + "type": "exp", + "decay_steps": 5000, + "start_lr": 0.001, + "stop_lr": 3.51e-8, + "_comment5": "that's all" + }, + + "loss": { + "type": "ener", + "start_pref_e": 0.02, + "limit_pref_e": 1, + "start_pref_f": 1000, + "limit_pref_f": 1, + "start_pref_v": 0, + "limit_pref_v": 0, + "_comment6": " that's all" + }, + + "training": { + "training_data": { + "systems": [ + "../data/data_0/", + "../data/data_1/", + "../data/data_2/" + ], + "batch_size": "auto", + "_comment7": "that's all" + }, + "validation_data": { + "systems": [ + "../data/data_3" + ], + "batch_size": 1, + "numb_btch": 3, + "_comment8": "that's all" + }, + "numb_steps": 1000000, + "seed": 10, + "disp_file": "lcurve.out", + "disp_freq": 100, + "save_freq": 1000, + "_comment9": "that's all" + }, + + "_comment10": "that's all" +} From a232cf39123137ce2f4b4aeb3fe609058e318fbb Mon Sep 17 00:00:00 2001 From: anyangml Date: Sun, 3 Mar 2024 09:25:45 +0000 Subject: [PATCH 11/59] fix: UTs --- .../pt/model/atomic_model/linear_atomic_model.py | 15 +++++++++------ source/tests/pt/test_training.py | 16 ++++------------ 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/deepmd/pt/model/atomic_model/linear_atomic_model.py b/deepmd/pt/model/atomic_model/linear_atomic_model.py index 48c6128a6c..1c56fb849b 100644 --- a/deepmd/pt/model/atomic_model/linear_atomic_model.py +++ b/deepmd/pt/model/atomic_model/linear_atomic_model.py @@ -188,12 +188,15 @@ def forward_atomic( weights = self._compute_weight(extended_coord, extended_atype, nlists_) atype = extended_atype[:, :nloc] - for idx, m in enumerate(self.models): - if isinstance(m, DPAtomicModel) and m.fitting_net is not None: - bias_atom_e = m.fitting_net.bias_atom_e - elif isinstance(m, PairTabAtomicModel): - bias_atom_e = m.bias_atom_e - ener_list[idx] += bias_atom_e[atype] + for idx, model in enumerate(self.models): + if isinstance(model, DPAtomicModel): + bias_atom_e = model.fitting_net.bias_atom_e + elif isinstance(model, PairTabAtomicModel): + bias_atom_e = model.bias_atom_e + else: + bias_atom_e = None + if bias_atom_e is not None: + ener_list[idx] += bias_atom_e[atype] fit_ret = { "energy": torch.sum(torch.stack(ener_list) * torch.stack(weights), dim=0), diff --git a/source/tests/pt/test_training.py b/source/tests/pt/test_training.py index 41eb0e2a7b..119024b6ce 100644 --- a/source/tests/pt/test_training.py +++ b/source/tests/pt/test_training.py @@ -64,18 +64,10 @@ def test_trainable(self): trainer_fix.run() model_dict_after_training = deepcopy(trainer_fix.model.state_dict()) for key in model_dict_before_training: - if ( - model_dict_before_training[key].shape - == model_dict_after_training[key].shape - ): - torch.testing.assert_close( - model_dict_before_training[key], model_dict_after_training[key] - ) - else: - torch.testing.assert_close( - model_dict_before_training[key].flatten(), - model_dict_after_training[key].flatten(), - ) + torch.testing.assert_close( + model_dict_before_training[key], model_dict_after_training[key] + ) + self.tearDown() def tearDown(self): From 004b63e02546427ee08210006259bfbab897557d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 3 Mar 2024 09:26:15 +0000 Subject: [PATCH 12/59] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- source/tests/pt/test_training.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/tests/pt/test_training.py b/source/tests/pt/test_training.py index 119024b6ce..db69a1bcea 100644 --- a/source/tests/pt/test_training.py +++ b/source/tests/pt/test_training.py @@ -67,7 +67,7 @@ def test_trainable(self): torch.testing.assert_close( model_dict_before_training[key], model_dict_after_training[key] ) - + self.tearDown() def tearDown(self): From ca9970184f28879b312cbad918fb8ded2e0a1882 Mon Sep 17 00:00:00 2001 From: anyangml Date: Sun, 3 Mar 2024 11:33:48 +0000 Subject: [PATCH 13/59] fix: UTs --- deepmd/pt/train/training.py | 17 +++++++++-------- deepmd/utils/pair_tab.py | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/deepmd/pt/train/training.py b/deepmd/pt/train/training.py index 0ddde0bff6..345838192a 100644 --- a/deepmd/pt/train/training.py +++ b/deepmd/pt/train/training.py @@ -507,14 +507,15 @@ def get_loss(loss_params, start_lr, _ntypes, _model): model_params["type_map"], model_params["new_type_map"], ) - self.model.fitting_net.change_energy_bias( - config, - self.model, - old_type_map, - new_type_map, - ntest=ntest, - bias_shift=model_params.get("bias_shift", "delta"), - ) + if hasattr(self.model, "fitting_net"): + self.model.fitting_net.change_energy_bias( + config, + self.model, + old_type_map, + new_type_map, + ntest=ntest, + bias_shift=model_params.get("bias_shift", "delta"), + ) if init_frz_model is not None: frz_model = torch.jit.load(init_frz_model, map_location=DEVICE) self.model.load_state_dict(frz_model.state_dict()) diff --git a/deepmd/utils/pair_tab.py b/deepmd/utils/pair_tab.py index 1b397a3cfa..4b7a5aabc4 100644 --- a/deepmd/utils/pair_tab.py +++ b/deepmd/utils/pair_tab.py @@ -72,7 +72,7 @@ def reinit(self, filename: str, rcut: Optional[float] = None) -> None: self.vdata.shape[0] - 1 ) # this nspline is updated based on the expanded table. self.tab_info = np.array([self.rmin, self.hh, self.nspline, self.ntypes]) - self.tab_data = self._make_data() + self.tab_data = self._make_data().reshape(self.ntypes, self.ntypes, self.nspline, 4) def serialize(self) -> dict: return { From 162fc16e14322d52263439b455cfc9ef52ca9a39 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 3 Mar 2024 11:34:15 +0000 Subject: [PATCH 14/59] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- deepmd/utils/pair_tab.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/deepmd/utils/pair_tab.py b/deepmd/utils/pair_tab.py index 4b7a5aabc4..832f84c495 100644 --- a/deepmd/utils/pair_tab.py +++ b/deepmd/utils/pair_tab.py @@ -72,7 +72,9 @@ def reinit(self, filename: str, rcut: Optional[float] = None) -> None: self.vdata.shape[0] - 1 ) # this nspline is updated based on the expanded table. self.tab_info = np.array([self.rmin, self.hh, self.nspline, self.ntypes]) - self.tab_data = self._make_data().reshape(self.ntypes, self.ntypes, self.nspline, 4) + self.tab_data = self._make_data().reshape( + self.ntypes, self.ntypes, self.nspline, 4 + ) def serialize(self) -> dict: return { From 9c25175f057e71b5131d1762008fe7c65ffbf28e Mon Sep 17 00:00:00 2001 From: anyangml Date: Sun, 3 Mar 2024 12:18:25 +0000 Subject: [PATCH 15/59] fix: UTs --- deepmd/pt/model/atomic_model/pairtab_atomic_model.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/deepmd/pt/model/atomic_model/pairtab_atomic_model.py b/deepmd/pt/model/atomic_model/pairtab_atomic_model.py index 0004d44493..0a815d3255 100644 --- a/deepmd/pt/model/atomic_model/pairtab_atomic_model.py +++ b/deepmd/pt/model/atomic_model/pairtab_atomic_model.py @@ -79,8 +79,9 @@ def __init__( tab_info, tab_data, ) = self.tab.get() # this returns -> Tuple[np.array, np.array] + nspline, ntypes = tab_info[-2:].astype(int) self.register_buffer("tab_info", torch.from_numpy(tab_info)) - self.register_buffer("tab_data", torch.from_numpy(tab_data)) + self.register_buffer("tab_data", torch.from_numpy(tab_data).reshape(ntypes,ntypes,nspline,4)) else: self.register_buffer("tab_info", None) self.register_buffer("tab_data", None) From 8fc3a70d00bc2ec0cec62960188965127129dc5a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 3 Mar 2024 12:39:51 +0000 Subject: [PATCH 16/59] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- deepmd/pt/model/atomic_model/pairtab_atomic_model.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/deepmd/pt/model/atomic_model/pairtab_atomic_model.py b/deepmd/pt/model/atomic_model/pairtab_atomic_model.py index 0a815d3255..f52486478a 100644 --- a/deepmd/pt/model/atomic_model/pairtab_atomic_model.py +++ b/deepmd/pt/model/atomic_model/pairtab_atomic_model.py @@ -81,7 +81,10 @@ def __init__( ) = self.tab.get() # this returns -> Tuple[np.array, np.array] nspline, ntypes = tab_info[-2:].astype(int) self.register_buffer("tab_info", torch.from_numpy(tab_info)) - self.register_buffer("tab_data", torch.from_numpy(tab_data).reshape(ntypes,ntypes,nspline,4)) + self.register_buffer( + "tab_data", + torch.from_numpy(tab_data).reshape(ntypes, ntypes, nspline, 4), + ) else: self.register_buffer("tab_info", None) self.register_buffer("tab_data", None) From 84fb8165381b58211e500a12f8f0b9fda390039b Mon Sep 17 00:00:00 2001 From: anyangml Date: Sun, 3 Mar 2024 12:41:22 +0000 Subject: [PATCH 17/59] chore: merge conflict --- deepmd/utils/pair_tab.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/deepmd/utils/pair_tab.py b/deepmd/utils/pair_tab.py index 832f84c495..1b397a3cfa 100644 --- a/deepmd/utils/pair_tab.py +++ b/deepmd/utils/pair_tab.py @@ -72,9 +72,7 @@ def reinit(self, filename: str, rcut: Optional[float] = None) -> None: self.vdata.shape[0] - 1 ) # this nspline is updated based on the expanded table. self.tab_info = np.array([self.rmin, self.hh, self.nspline, self.ntypes]) - self.tab_data = self._make_data().reshape( - self.ntypes, self.ntypes, self.nspline, 4 - ) + self.tab_data = self._make_data() def serialize(self) -> dict: return { From 55e2b7f7b8e0e1bc4db164abd4aeb67dd70ce455 Mon Sep 17 00:00:00 2001 From: anyangml Date: Sun, 3 Mar 2024 13:30:01 +0000 Subject: [PATCH 18/59] fix: update numpy shape --- deepmd/dpmodel/atomic_model/pairtab_atomic_model.py | 5 ++++- deepmd/pt/model/atomic_model/pairtab_atomic_model.py | 3 ++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/deepmd/dpmodel/atomic_model/pairtab_atomic_model.py b/deepmd/dpmodel/atomic_model/pairtab_atomic_model.py index 5469ee80d2..49fb70af58 100644 --- a/deepmd/dpmodel/atomic_model/pairtab_atomic_model.py +++ b/deepmd/dpmodel/atomic_model/pairtab_atomic_model.py @@ -60,6 +60,8 @@ def __init__( if self.tab_file is not None: self.tab_info, self.tab_data = self.tab.get() + nspline, ntypes = self.tab_info.astype(int) + self.tab_data = self.tab_data.reshape(ntypes,ntypes,nspline,4) else: self.tab_info, self.tab_data = None, None @@ -134,7 +136,8 @@ def deserialize(cls, data) -> "PairTabAtomicModel": tab_model = cls(None, rcut, sel, **data) tab_model.tab = tab tab_model.tab_info = tab_model.tab.tab_info - tab_model.tab_data = tab_model.tab.tab_data + nspline, ntypes = tab_model.tab_info[-2:].astype(int) + tab_model.tab_data = tab_model.tab.tab_data.reshape(ntypes,ntypes,nspline,4) return tab_model def forward_atomic( diff --git a/deepmd/pt/model/atomic_model/pairtab_atomic_model.py b/deepmd/pt/model/atomic_model/pairtab_atomic_model.py index f52486478a..81c4dc476c 100644 --- a/deepmd/pt/model/atomic_model/pairtab_atomic_model.py +++ b/deepmd/pt/model/atomic_model/pairtab_atomic_model.py @@ -170,7 +170,8 @@ def deserialize(cls, data) -> "PairTabAtomicModel": tab_model = cls(None, rcut, sel, **data) tab_model.tab = tab tab_model.register_buffer("tab_info", torch.from_numpy(tab_model.tab.tab_info)) - tab_model.register_buffer("tab_data", torch.from_numpy(tab_model.tab.tab_data)) + nspline, ntypes = tab_model.tab.tab_info[-2:].astype(int) + tab_model.register_buffer("tab_data", torch.from_numpy(tab_model.tab.tab_data).reshape(ntypes,ntypes,nspline,4)) return tab_model def compute_output_stats( From 0b9f7ae613462d48f7429921bf259ba1405c7556 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 3 Mar 2024 13:30:30 +0000 Subject: [PATCH 19/59] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- deepmd/dpmodel/atomic_model/pairtab_atomic_model.py | 4 ++-- deepmd/pt/model/atomic_model/pairtab_atomic_model.py | 7 ++++++- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/deepmd/dpmodel/atomic_model/pairtab_atomic_model.py b/deepmd/dpmodel/atomic_model/pairtab_atomic_model.py index 49fb70af58..d5e0ffcbbe 100644 --- a/deepmd/dpmodel/atomic_model/pairtab_atomic_model.py +++ b/deepmd/dpmodel/atomic_model/pairtab_atomic_model.py @@ -61,7 +61,7 @@ def __init__( if self.tab_file is not None: self.tab_info, self.tab_data = self.tab.get() nspline, ntypes = self.tab_info.astype(int) - self.tab_data = self.tab_data.reshape(ntypes,ntypes,nspline,4) + self.tab_data = self.tab_data.reshape(ntypes, ntypes, nspline, 4) else: self.tab_info, self.tab_data = None, None @@ -137,7 +137,7 @@ def deserialize(cls, data) -> "PairTabAtomicModel": tab_model.tab = tab tab_model.tab_info = tab_model.tab.tab_info nspline, ntypes = tab_model.tab_info[-2:].astype(int) - tab_model.tab_data = tab_model.tab.tab_data.reshape(ntypes,ntypes,nspline,4) + tab_model.tab_data = tab_model.tab.tab_data.reshape(ntypes, ntypes, nspline, 4) return tab_model def forward_atomic( diff --git a/deepmd/pt/model/atomic_model/pairtab_atomic_model.py b/deepmd/pt/model/atomic_model/pairtab_atomic_model.py index 81c4dc476c..1aee5cc8ab 100644 --- a/deepmd/pt/model/atomic_model/pairtab_atomic_model.py +++ b/deepmd/pt/model/atomic_model/pairtab_atomic_model.py @@ -171,7 +171,12 @@ def deserialize(cls, data) -> "PairTabAtomicModel": tab_model.tab = tab tab_model.register_buffer("tab_info", torch.from_numpy(tab_model.tab.tab_info)) nspline, ntypes = tab_model.tab.tab_info[-2:].astype(int) - tab_model.register_buffer("tab_data", torch.from_numpy(tab_model.tab.tab_data).reshape(ntypes,ntypes,nspline,4)) + tab_model.register_buffer( + "tab_data", + torch.from_numpy(tab_model.tab.tab_data).reshape( + ntypes, ntypes, nspline, 4 + ), + ) return tab_model def compute_output_stats( From 65246940c9712e14b5e111b8ba858960c4cd2608 Mon Sep 17 00:00:00 2001 From: anyangml Date: Sun, 3 Mar 2024 14:01:32 +0000 Subject: [PATCH 20/59] fix: UTs --- deepmd/dpmodel/atomic_model/pairtab_atomic_model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deepmd/dpmodel/atomic_model/pairtab_atomic_model.py b/deepmd/dpmodel/atomic_model/pairtab_atomic_model.py index d5e0ffcbbe..5b75df031b 100644 --- a/deepmd/dpmodel/atomic_model/pairtab_atomic_model.py +++ b/deepmd/dpmodel/atomic_model/pairtab_atomic_model.py @@ -60,7 +60,7 @@ def __init__( if self.tab_file is not None: self.tab_info, self.tab_data = self.tab.get() - nspline, ntypes = self.tab_info.astype(int) + nspline, ntypes = self.tab_info[-2:].astype(int) self.tab_data = self.tab_data.reshape(ntypes, ntypes, nspline, 4) else: self.tab_info, self.tab_data = None, None From e3d9a7b85773eb810e68f8e3e8d2b95e4d42e25c Mon Sep 17 00:00:00 2001 From: anyangml Date: Sun, 3 Mar 2024 14:52:00 +0000 Subject: [PATCH 21/59] feat: add UTs --- source/tests/pt/test_finetune.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/source/tests/pt/test_finetune.py b/source/tests/pt/test_finetune.py index 226fed3c65..bbf441f43e 100644 --- a/source/tests/pt/test_finetune.py +++ b/source/tests/pt/test_finetune.py @@ -18,6 +18,7 @@ ) from deepmd.pt.model.model import ( get_model, + get_zbl_model, ) from deepmd.utils.data_system import ( DeepmdDataSystem, @@ -30,6 +31,7 @@ model_dpa1, model_dpa2, model_se_e2_a, + model_zbl, ) @@ -108,6 +110,20 @@ def setUp(self): def tearDown(self) -> None: FinetuneTest.tearDown(self) +class TestEnergyZBLModelSeA(unittest.TestCase, FinetuneTest): + def setUp(self): + self.data_file = [str(Path(__file__).parent / "water/data/data_0")] + self.data = DeepmdDataSystem( + self.data_file, + batch_size=1, + test_size=1, + ) + self.data.add("energy", ndof=1, atomic=False, must=True, high_prec=True) + self.model_config = model_zbl + + def tearDown(self) -> None: + FinetuneTest.tearDown(self) + class TestEnergyModelDPA1(unittest.TestCase, FinetuneTest): def setUp(self): From e648ab4f4b0da1e3e7e92f11e8863b5d86681c9d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 3 Mar 2024 14:52:29 +0000 Subject: [PATCH 22/59] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- source/tests/pt/test_finetune.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/tests/pt/test_finetune.py b/source/tests/pt/test_finetune.py index bbf441f43e..0f09b09043 100644 --- a/source/tests/pt/test_finetune.py +++ b/source/tests/pt/test_finetune.py @@ -18,7 +18,6 @@ ) from deepmd.pt.model.model import ( get_model, - get_zbl_model, ) from deepmd.utils.data_system import ( DeepmdDataSystem, @@ -110,6 +109,7 @@ def setUp(self): def tearDown(self) -> None: FinetuneTest.tearDown(self) + class TestEnergyZBLModelSeA(unittest.TestCase, FinetuneTest): def setUp(self): self.data_file = [str(Path(__file__).parent / "water/data/data_0")] From 6ed8fdea8828d9fd26ed98fdec84c1eb2049aba9 Mon Sep 17 00:00:00 2001 From: anyangml Date: Mon, 4 Mar 2024 01:58:57 +0000 Subject: [PATCH 23/59] fix: UTs --- .../model/atomic_model/linear_atomic_model.py | 11 ++++-- source/tests/pt/test_finetune.py | 37 +++++++++++++++---- 2 files changed, 36 insertions(+), 12 deletions(-) diff --git a/deepmd/pt/model/atomic_model/linear_atomic_model.py b/deepmd/pt/model/atomic_model/linear_atomic_model.py index 1c56fb849b..a25edb6905 100644 --- a/deepmd/pt/model/atomic_model/linear_atomic_model.py +++ b/deepmd/pt/model/atomic_model/linear_atomic_model.py @@ -80,10 +80,9 @@ def get_rcut(self) -> float: """Get the cut-off radius.""" return max(self.get_model_rcuts()) - @torch.jit.export + @abstractmethod def get_type_map(self) -> List[str]: """Get the type map.""" - raise NotImplementedError("TODO: implement this method") def get_model_rcuts(self) -> List[float]: """Get the cut-off radius for each individual models.""" @@ -106,8 +105,8 @@ def _sort_rcuts_sels(self, device: torch.device) -> Tuple[List[float], List[int] nsels = torch.tensor(self.get_model_nsels(), device=device) zipped = torch.stack( [ - torch.tensor(rcuts, device=device), - torch.tensor(nsels, device=device), + rcuts, + nsels, ], dim=0, ).T @@ -316,6 +315,10 @@ def __init__( # this is a placeholder being updated in _compute_weight, to handle Jit attribute init error. self.zbl_weight = torch.empty(0, dtype=torch.float64, device=env.DEVICE) + @torch.jit.export + def get_type_map(self): + return self.dp_model.get_type_map() + def compute_or_load_stat( self, sampled_func, diff --git a/source/tests/pt/test_finetune.py b/source/tests/pt/test_finetune.py index 0f09b09043..b6d25c0569 100644 --- a/source/tests/pt/test_finetune.py +++ b/source/tests/pt/test_finetune.py @@ -19,6 +19,11 @@ from deepmd.pt.model.model import ( get_model, ) +from deepmd.pt.model.model import ( + EnergyModel, + DPZBLModel, +) + from deepmd.utils.data_system import ( DeepmdDataSystem, ) @@ -37,14 +42,30 @@ class FinetuneTest: def test_finetune_change_energy_bias(self): # get model - model = get_model(self.model_config) - model.fitting_net.bias_atom_e = torch.rand_like(model.fitting_net.bias_atom_e) - energy_bias_before = deepcopy( - model.fitting_net.bias_atom_e.detach().cpu().numpy().reshape(-1) - ) - bias_atom_e_input = deepcopy( - model.fitting_net.bias_atom_e.detach().cpu().numpy().reshape(-1) - ) + if "use_srtab" in self.model_config: + model = get_zbl_model(self.model_config) + else: + model = get_model(self.model_config) + if isinstance(model, EnergyModel): + model.fitting_net.bias_atom_e = torch.rand_like(model.fitting_net.bias_atom_e) + energy_bias_before = deepcopy( + model.fitting_net.bias_atom_e.detach().cpu().numpy().reshape(-1) + ) + bias_atom_e_input = deepcopy( + model.fitting_net.bias_atom_e.detach().cpu().numpy().reshape(-1) + ) + elif isinstance(model, DPZBLModel): + model.dp_model.fitting_net.bias_atom_e = torch.rand_like(model.dp_model.fitting_net.bias_atom_e) + energy_bias_before = deepcopy( + model.dp_model.fitting_net.bias_atom_e.detach().cpu().numpy().reshape(-1) + ) + bias_atom_e_input = deepcopy( + model.dp_model.fitting_net.bias_atom_e.detach().cpu().numpy().reshape(-1) + ) + print(f"here: {bias_atom_e_input}") + else: + bias_atom_e_input = None + model = torch.jit.script(model) tmp_model = tempfile.NamedTemporaryFile(delete=False, suffix=".pth") torch.jit.save(model, tmp_model.name) From aadddcbe608cc8efb7854c7e4de7e4515bf703f2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 01:59:40 +0000 Subject: [PATCH 24/59] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- source/tests/pt/test_finetune.py | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/source/tests/pt/test_finetune.py b/source/tests/pt/test_finetune.py index b6d25c0569..752c072d9a 100644 --- a/source/tests/pt/test_finetune.py +++ b/source/tests/pt/test_finetune.py @@ -17,13 +17,10 @@ DeepEval, ) from deepmd.pt.model.model import ( - get_model, -) -from deepmd.pt.model.model import ( - EnergyModel, DPZBLModel, + EnergyModel, + get_model, ) - from deepmd.utils.data_system import ( DeepmdDataSystem, ) @@ -47,7 +44,9 @@ def test_finetune_change_energy_bias(self): else: model = get_model(self.model_config) if isinstance(model, EnergyModel): - model.fitting_net.bias_atom_e = torch.rand_like(model.fitting_net.bias_atom_e) + model.fitting_net.bias_atom_e = torch.rand_like( + model.fitting_net.bias_atom_e + ) energy_bias_before = deepcopy( model.fitting_net.bias_atom_e.detach().cpu().numpy().reshape(-1) ) @@ -55,17 +54,25 @@ def test_finetune_change_energy_bias(self): model.fitting_net.bias_atom_e.detach().cpu().numpy().reshape(-1) ) elif isinstance(model, DPZBLModel): - model.dp_model.fitting_net.bias_atom_e = torch.rand_like(model.dp_model.fitting_net.bias_atom_e) + model.dp_model.fitting_net.bias_atom_e = torch.rand_like( + model.dp_model.fitting_net.bias_atom_e + ) energy_bias_before = deepcopy( - model.dp_model.fitting_net.bias_atom_e.detach().cpu().numpy().reshape(-1) + model.dp_model.fitting_net.bias_atom_e.detach() + .cpu() + .numpy() + .reshape(-1) ) bias_atom_e_input = deepcopy( - model.dp_model.fitting_net.bias_atom_e.detach().cpu().numpy().reshape(-1) + model.dp_model.fitting_net.bias_atom_e.detach() + .cpu() + .numpy() + .reshape(-1) ) print(f"here: {bias_atom_e_input}") else: bias_atom_e_input = None - + model = torch.jit.script(model) tmp_model = tempfile.NamedTemporaryFile(delete=False, suffix=".pth") torch.jit.save(model, tmp_model.name) From f36988de773fb16b307dcd674b797768b67c57ff Mon Sep 17 00:00:00 2001 From: anyangml Date: Mon, 4 Mar 2024 02:05:32 +0000 Subject: [PATCH 25/59] fix: UTs --- source/tests/pt/test_finetune.py | 1 + 1 file changed, 1 insertion(+) diff --git a/source/tests/pt/test_finetune.py b/source/tests/pt/test_finetune.py index 752c072d9a..4e57110b0e 100644 --- a/source/tests/pt/test_finetune.py +++ b/source/tests/pt/test_finetune.py @@ -20,6 +20,7 @@ DPZBLModel, EnergyModel, get_model, + get_zbl_model, ) from deepmd.utils.data_system import ( DeepmdDataSystem, From 9c9cbbec85f22d515ce880736226a04f539e58fe Mon Sep 17 00:00:00 2001 From: anyangml Date: Mon, 4 Mar 2024 02:36:28 +0000 Subject: [PATCH 26/59] feat: update UTs --- deepmd/pt/model/atomic_model/linear_atomic_model.py | 5 +++++ deepmd/pt/model/atomic_model/pairtab_atomic_model.py | 4 ++++ deepmd/pt/train/training.py | 6 ++++++ 3 files changed, 15 insertions(+) diff --git a/deepmd/pt/model/atomic_model/linear_atomic_model.py b/deepmd/pt/model/atomic_model/linear_atomic_model.py index a25edb6905..9735c6d008 100644 --- a/deepmd/pt/model/atomic_model/linear_atomic_model.py +++ b/deepmd/pt/model/atomic_model/linear_atomic_model.py @@ -342,6 +342,11 @@ def compute_or_load_stat( self.dp_model.compute_or_load_stat(sampled_func, stat_file_path) self.zbl_model.compute_output_stats(sampled_func, stat_file_path) + def change_energy_bias(self): + # need to implement + pass + + def serialize(self) -> dict: dd = BaseAtomicModel.serialize(self) dd.update( diff --git a/deepmd/pt/model/atomic_model/pairtab_atomic_model.py b/deepmd/pt/model/atomic_model/pairtab_atomic_model.py index 1aee5cc8ab..03a7e62a05 100644 --- a/deepmd/pt/model/atomic_model/pairtab_atomic_model.py +++ b/deepmd/pt/model/atomic_model/pairtab_atomic_model.py @@ -238,6 +238,10 @@ def compute_output_stats( torch.tensor(bias_atom_e, device=env.DEVICE).view([ntypes, 1]) ) + def change_energy_bias(self) -> None: + # need to implement + pass + def forward_atomic( self, extended_coord: torch.Tensor, diff --git a/deepmd/pt/train/training.py b/deepmd/pt/train/training.py index 345838192a..faa27e9ba8 100644 --- a/deepmd/pt/train/training.py +++ b/deepmd/pt/train/training.py @@ -28,6 +28,9 @@ EnergyStdLoss, TensorLoss, ) +from deepmd.pt.model.model import ( + DPZBLModel +) from deepmd.pt.model.model import ( get_model, get_zbl_model, @@ -516,6 +519,9 @@ def get_loss(loss_params, start_lr, _ntypes, _model): ntest=ntest, bias_shift=model_params.get("bias_shift", "delta"), ) + elif isinstance(self.model, DPZBLModel): + # need to updated + self.model.change_energy_bias() if init_frz_model is not None: frz_model = torch.jit.load(init_frz_model, map_location=DEVICE) self.model.load_state_dict(frz_model.state_dict()) From d2adebbc058512af3ea991604ee711e596179b7e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 02:36:57 +0000 Subject: [PATCH 27/59] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- deepmd/pt/model/atomic_model/linear_atomic_model.py | 1 - deepmd/pt/train/training.py | 4 +--- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/deepmd/pt/model/atomic_model/linear_atomic_model.py b/deepmd/pt/model/atomic_model/linear_atomic_model.py index 9735c6d008..dcbb677970 100644 --- a/deepmd/pt/model/atomic_model/linear_atomic_model.py +++ b/deepmd/pt/model/atomic_model/linear_atomic_model.py @@ -345,7 +345,6 @@ def compute_or_load_stat( def change_energy_bias(self): # need to implement pass - def serialize(self) -> dict: dd = BaseAtomicModel.serialize(self) diff --git a/deepmd/pt/train/training.py b/deepmd/pt/train/training.py index faa27e9ba8..f5d7c42194 100644 --- a/deepmd/pt/train/training.py +++ b/deepmd/pt/train/training.py @@ -29,9 +29,7 @@ TensorLoss, ) from deepmd.pt.model.model import ( - DPZBLModel -) -from deepmd.pt.model.model import ( + DPZBLModel, get_model, get_zbl_model, ) From 00c877c85c5eb6187b4f1ca9daa69e3072d69a46 Mon Sep 17 00:00:00 2001 From: Anyang Peng <137014849+anyangml@users.noreply.github.com> Date: Mon, 4 Mar 2024 11:52:17 +0800 Subject: [PATCH 28/59] fix: UTs --- .../atomic_model/make_base_atomic_model.py | 15 ++++++++++ .../model/atomic_model/linear_atomic_model.py | 2 +- .../atomic_model/pairtab_atomic_model.py | 2 +- .../pt/model/test_linear_atomic_model.py | 6 ++-- source/tests/pt/test_finetune.py | 28 +++++++++---------- 5 files changed, 33 insertions(+), 20 deletions(-) diff --git a/deepmd/dpmodel/atomic_model/make_base_atomic_model.py b/deepmd/dpmodel/atomic_model/make_base_atomic_model.py index 5548147d54..4a0e32f077 100644 --- a/deepmd/dpmodel/atomic_model/make_base_atomic_model.py +++ b/deepmd/dpmodel/atomic_model/make_base_atomic_model.py @@ -5,9 +5,15 @@ abstractmethod, ) from typing import ( + Callable, Dict, List, Optional, + Union, +) + +from deepmd.utils.path import ( + DPPath, ) from deepmd.dpmodel.output_def import ( @@ -117,6 +123,15 @@ def mixed_types(self) -> bool: """ pass + @abstractmethod + def compute_or_load_stat( + self, + merged: Union[Callable[[], List[dict]], List[dict]], + stat_file_path: Optional[DPPath] = None, + ): + pass + + @abstractmethod def fwd( self, diff --git a/deepmd/pt/model/atomic_model/linear_atomic_model.py b/deepmd/pt/model/atomic_model/linear_atomic_model.py index dcbb677970..b1cdaa23e1 100644 --- a/deepmd/pt/model/atomic_model/linear_atomic_model.py +++ b/deepmd/pt/model/atomic_model/linear_atomic_model.py @@ -340,7 +340,7 @@ def compute_or_load_stat( The dictionary of paths to the statistics files. """ self.dp_model.compute_or_load_stat(sampled_func, stat_file_path) - self.zbl_model.compute_output_stats(sampled_func, stat_file_path) + self.zbl_model.compute_or_load_stat(sampled_func, stat_file_path) def change_energy_bias(self): # need to implement diff --git a/deepmd/pt/model/atomic_model/pairtab_atomic_model.py b/deepmd/pt/model/atomic_model/pairtab_atomic_model.py index 03a7e62a05..933b8c5ee6 100644 --- a/deepmd/pt/model/atomic_model/pairtab_atomic_model.py +++ b/deepmd/pt/model/atomic_model/pairtab_atomic_model.py @@ -179,7 +179,7 @@ def deserialize(cls, data) -> "PairTabAtomicModel": ) return tab_model - def compute_output_stats( + def compute_or_load_stat( self, merged: Union[Callable[[], List[dict]], List[dict]], stat_file_path: Optional[DPPath] = None, diff --git a/source/tests/pt/model/test_linear_atomic_model.py b/source/tests/pt/model/test_linear_atomic_model.py index aae1a66618..fc2e8ea64a 100644 --- a/source/tests/pt/model/test_linear_atomic_model.py +++ b/source/tests/pt/model/test_linear_atomic_model.py @@ -171,12 +171,10 @@ def test_self_consistency(self): def test_jit(self): md1 = torch.jit.script(self.md1) self.assertEqual(md1.get_rcut(), self.rcut) - with self.assertRaises(torch.jit.Error): - self.assertEqual(md1.get_type_map(), ["foo", "bar"]) + self.assertEqual(md1.get_type_map(), ["foo", "bar"]) md3 = torch.jit.script(self.md3) self.assertEqual(md3.get_rcut(), self.rcut) - with self.assertRaises(torch.jit.Error): - self.assertEqual(md3.get_type_map(), ["foo", "bar"]) + self.assertEqual(md3.get_type_map(), ["foo", "bar"]) if __name__ == "__main__": diff --git a/source/tests/pt/test_finetune.py b/source/tests/pt/test_finetune.py index 4e57110b0e..445ce579a1 100644 --- a/source/tests/pt/test_finetune.py +++ b/source/tests/pt/test_finetune.py @@ -138,20 +138,20 @@ def setUp(self): def tearDown(self) -> None: FinetuneTest.tearDown(self) - -class TestEnergyZBLModelSeA(unittest.TestCase, FinetuneTest): - def setUp(self): - self.data_file = [str(Path(__file__).parent / "water/data/data_0")] - self.data = DeepmdDataSystem( - self.data_file, - batch_size=1, - test_size=1, - ) - self.data.add("energy", ndof=1, atomic=False, must=True, high_prec=True) - self.model_config = model_zbl - - def tearDown(self) -> None: - FinetuneTest.tearDown(self) +## disabled for now. +# class TestEnergyZBLModelSeA(unittest.TestCase, FinetuneTest): +# def setUp(self): +# self.data_file = [str(Path(__file__).parent / "water/data/data_0")] +# self.data = DeepmdDataSystem( +# self.data_file, +# batch_size=1, +# test_size=1, +# ) +# self.data.add("energy", ndof=1, atomic=False, must=True, high_prec=True) +# self.model_config = model_zbl + +# def tearDown(self) -> None: +# FinetuneTest.tearDown(self) class TestEnergyModelDPA1(unittest.TestCase, FinetuneTest): From 5de72140b236233fa9c8666f014917e91efe3ee6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 03:52:57 +0000 Subject: [PATCH 29/59] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- deepmd/dpmodel/atomic_model/make_base_atomic_model.py | 8 +++----- source/tests/pt/test_finetune.py | 2 +- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/deepmd/dpmodel/atomic_model/make_base_atomic_model.py b/deepmd/dpmodel/atomic_model/make_base_atomic_model.py index 4a0e32f077..b5ed590692 100644 --- a/deepmd/dpmodel/atomic_model/make_base_atomic_model.py +++ b/deepmd/dpmodel/atomic_model/make_base_atomic_model.py @@ -12,13 +12,12 @@ Union, ) -from deepmd.utils.path import ( - DPPath, -) - from deepmd.dpmodel.output_def import ( FittingOutputDef, ) +from deepmd.utils.path import ( + DPPath, +) def make_base_atomic_model( @@ -131,7 +130,6 @@ def compute_or_load_stat( ): pass - @abstractmethod def fwd( self, diff --git a/source/tests/pt/test_finetune.py b/source/tests/pt/test_finetune.py index 445ce579a1..87316cd923 100644 --- a/source/tests/pt/test_finetune.py +++ b/source/tests/pt/test_finetune.py @@ -33,7 +33,6 @@ model_dpa1, model_dpa2, model_se_e2_a, - model_zbl, ) @@ -138,6 +137,7 @@ def setUp(self): def tearDown(self) -> None: FinetuneTest.tearDown(self) + ## disabled for now. # class TestEnergyZBLModelSeA(unittest.TestCase, FinetuneTest): # def setUp(self): From 8b35fa496cf1d6461922c65fe54078bb5cee5da9 Mon Sep 17 00:00:00 2001 From: anyangml Date: Mon, 4 Mar 2024 04:21:05 +0000 Subject: [PATCH 30/59] rix: revert abstract method --- .../dpmodel/atomic_model/make_base_atomic_model.py | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) diff --git a/deepmd/dpmodel/atomic_model/make_base_atomic_model.py b/deepmd/dpmodel/atomic_model/make_base_atomic_model.py index b5ed590692..09e95bc0ca 100644 --- a/deepmd/dpmodel/atomic_model/make_base_atomic_model.py +++ b/deepmd/dpmodel/atomic_model/make_base_atomic_model.py @@ -5,19 +5,15 @@ abstractmethod, ) from typing import ( - Callable, Dict, List, Optional, - Union, ) from deepmd.dpmodel.output_def import ( FittingOutputDef, ) -from deepmd.utils.path import ( - DPPath, -) + def make_base_atomic_model( @@ -122,14 +118,6 @@ def mixed_types(self) -> bool: """ pass - @abstractmethod - def compute_or_load_stat( - self, - merged: Union[Callable[[], List[dict]], List[dict]], - stat_file_path: Optional[DPPath] = None, - ): - pass - @abstractmethod def fwd( self, From bbc7ad2c6a9f2dbe40f7c83f8085da2623cdfb3f Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 04:21:34 +0000 Subject: [PATCH 31/59] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- deepmd/dpmodel/atomic_model/make_base_atomic_model.py | 1 - 1 file changed, 1 deletion(-) diff --git a/deepmd/dpmodel/atomic_model/make_base_atomic_model.py b/deepmd/dpmodel/atomic_model/make_base_atomic_model.py index 09e95bc0ca..5548147d54 100644 --- a/deepmd/dpmodel/atomic_model/make_base_atomic_model.py +++ b/deepmd/dpmodel/atomic_model/make_base_atomic_model.py @@ -15,7 +15,6 @@ ) - def make_base_atomic_model( t_tensor, fwd_method_name: str = "forward_atomic", From c384b3b548bcf61f5b77e9db702e4fc6a8138a02 Mon Sep 17 00:00:00 2001 From: anyangml Date: Mon, 4 Mar 2024 05:39:38 +0000 Subject: [PATCH 32/59] fix: UTs --- deepmd/pt/train/training.py | 2 ++ source/tests/pt/test_finetune.py | 22 +++------------------- 2 files changed, 5 insertions(+), 19 deletions(-) diff --git a/deepmd/pt/train/training.py b/deepmd/pt/train/training.py index f5d7c42194..24dcc99e20 100644 --- a/deepmd/pt/train/training.py +++ b/deepmd/pt/train/training.py @@ -520,6 +520,8 @@ def get_loss(loss_params, start_lr, _ntypes, _model): elif isinstance(self.model, DPZBLModel): # need to updated self.model.change_energy_bias() + else: + raise NotImplementedError if init_frz_model is not None: frz_model = torch.jit.load(init_frz_model, map_location=DEVICE) self.model.load_state_dict(frz_model.state_dict()) diff --git a/source/tests/pt/test_finetune.py b/source/tests/pt/test_finetune.py index 87316cd923..5656f295b0 100644 --- a/source/tests/pt/test_finetune.py +++ b/source/tests/pt/test_finetune.py @@ -33,6 +33,7 @@ model_dpa1, model_dpa2, model_se_e2_a, + model_zbl, ) @@ -69,7 +70,6 @@ def test_finetune_change_energy_bias(self): .numpy() .reshape(-1) ) - print(f"here: {bias_atom_e_input}") else: bias_atom_e_input = None @@ -138,23 +138,7 @@ def tearDown(self) -> None: FinetuneTest.tearDown(self) -## disabled for now. -# class TestEnergyZBLModelSeA(unittest.TestCase, FinetuneTest): -# def setUp(self): -# self.data_file = [str(Path(__file__).parent / "water/data/data_0")] -# self.data = DeepmdDataSystem( -# self.data_file, -# batch_size=1, -# test_size=1, -# ) -# self.data.add("energy", ndof=1, atomic=False, must=True, high_prec=True) -# self.model_config = model_zbl - -# def tearDown(self) -> None: -# FinetuneTest.tearDown(self) - - -class TestEnergyModelDPA1(unittest.TestCase, FinetuneTest): +class TestEnergyZBLModelSeA(unittest.TestCase, FinetuneTest): def setUp(self): self.data_file = [str(Path(__file__).parent / "water/data/data_0")] self.data = DeepmdDataSystem( @@ -163,7 +147,7 @@ def setUp(self): test_size=1, ) self.data.add("energy", ndof=1, atomic=False, must=True, high_prec=True) - self.model_config = model_dpa1 + self.model_config = model_zbl def tearDown(self) -> None: FinetuneTest.tearDown(self) From 1d5fad0f0fbda91cefb5da4c2e12d348c5b2090e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 05:40:16 +0000 Subject: [PATCH 33/59] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- source/tests/pt/test_finetune.py | 1 - 1 file changed, 1 deletion(-) diff --git a/source/tests/pt/test_finetune.py b/source/tests/pt/test_finetune.py index 5656f295b0..4049aa86ee 100644 --- a/source/tests/pt/test_finetune.py +++ b/source/tests/pt/test_finetune.py @@ -30,7 +30,6 @@ ) from .model.test_permutation import ( - model_dpa1, model_dpa2, model_se_e2_a, model_zbl, From dc407e3ee4383276dc83dad2d2b96257e213366e Mon Sep 17 00:00:00 2001 From: anyangml Date: Mon, 4 Mar 2024 07:46:36 +0000 Subject: [PATCH 34/59] chore: refactor --- .../atomic_model/pairtab_atomic_model.py | 17 +++- .../model/atomic_model/linear_atomic_model.py | 4 +- .../atomic_model/pairtab_atomic_model.py | 79 +++++++++---------- deepmd/pt/model/task/ener.py | 49 +++--------- deepmd/pt/utils/stat.py | 77 ++++++++++++++++++ .../pt/model/test_linear_atomic_model.py | 4 +- .../pt/model/test_pairtab_atomic_model.py | 13 ++- source/tests/pt/test_finetune.py | 28 +++---- 8 files changed, 161 insertions(+), 110 deletions(-) diff --git a/deepmd/dpmodel/atomic_model/pairtab_atomic_model.py b/deepmd/dpmodel/atomic_model/pairtab_atomic_model.py index 5b75df031b..754299f4a6 100644 --- a/deepmd/dpmodel/atomic_model/pairtab_atomic_model.py +++ b/deepmd/dpmodel/atomic_model/pairtab_atomic_model.py @@ -47,21 +47,28 @@ class PairTabAtomicModel(BaseAtomicModel): The cutoff radius. sel : int or list[int] The maxmum number of atoms in the cut-off radius. + type_map: List[str] + Mapping atom type to the name (str) of the type. + For example `type_map[1]` gives the name of the type 1. """ def __init__( - self, tab_file: str, rcut: float, sel: Union[int, List[int]], **kwargs + self, tab_file: str, rcut: float, sel: Union[int, List[int]], type_map: List[str], **kwargs ): super().__init__() self.tab_file = tab_file self.rcut = rcut self.tab = PairTab(self.tab_file, rcut=rcut) + self.type_map = type_map + self.ntypes = len(type_map) if self.tab_file is not None: self.tab_info, self.tab_data = self.tab.get() - nspline, ntypes = self.tab_info[-2:].astype(int) - self.tab_data = self.tab_data.reshape(ntypes, ntypes, nspline, 4) + nspline, ntypes_tab = self.tab_info[-2:].astype(int) + self.tab_data = self.tab_data.reshape(ntypes_tab, ntypes_tab, nspline, 4) + if self.ntypes != ntypes_tab: + raise ValueError("The `type_map` provided does not match the number of columns in the table.") else: self.tab_info, self.tab_data = None, None @@ -120,6 +127,7 @@ def serialize(self) -> dict: "tab": self.tab.serialize(), "rcut": self.rcut, "sel": self.sel, + "type_map": self.type_map, } ) return dd @@ -132,8 +140,9 @@ def deserialize(cls, data) -> "PairTabAtomicModel": data.pop("type") rcut = data.pop("rcut") sel = data.pop("sel") + type_map = data.pop("type_map") tab = PairTab.deserialize(data.pop("tab")) - tab_model = cls(None, rcut, sel, **data) + tab_model = cls(None, rcut, sel, type_map, **data) tab_model.tab = tab tab_model.tab_info = tab_model.tab.tab_info nspline, ntypes = tab_model.tab_info[-2:].astype(int) diff --git a/deepmd/pt/model/atomic_model/linear_atomic_model.py b/deepmd/pt/model/atomic_model/linear_atomic_model.py index b1cdaa23e1..2d699cb185 100644 --- a/deepmd/pt/model/atomic_model/linear_atomic_model.py +++ b/deepmd/pt/model/atomic_model/linear_atomic_model.py @@ -316,7 +316,9 @@ def __init__( self.zbl_weight = torch.empty(0, dtype=torch.float64, device=env.DEVICE) @torch.jit.export - def get_type_map(self): + def get_type_map(self) -> List[str]: + dp_map = self.dp_model.get_type_map() + zbl_map = self.zbl_model.get_type_map() return self.dp_model.get_type_map() def compute_or_load_stat( diff --git a/deepmd/pt/model/atomic_model/pairtab_atomic_model.py b/deepmd/pt/model/atomic_model/pairtab_atomic_model.py index 933b8c5ee6..7078319e5e 100644 --- a/deepmd/pt/model/atomic_model/pairtab_atomic_model.py +++ b/deepmd/pt/model/atomic_model/pairtab_atomic_model.py @@ -20,8 +20,8 @@ from deepmd.pt.utils.utils import ( to_numpy_array, ) -from deepmd.utils.out_stat import ( - compute_stats_from_redu, +from deepmd.pt.utils.stat import ( + compute_output_stats, ) from deepmd.utils.pair_tab import ( PairTab, @@ -60,10 +60,17 @@ class PairTabAtomicModel(torch.nn.Module, BaseAtomicModel): The cutoff radius. sel : int or list[int] The maxmum number of atoms in the cut-off radius. + type_map: List[str] + Mapping atom type to the name (str) of the type. + For example `type_map[1]` gives the name of the type 1. + rcond : float, optional + The condition number for the regression of atomic energy. + atom_ener + Specifying atomic energy contribution in vacuum. The `set_davg_zero` key in the descrptor should be set. """ def __init__( - self, tab_file: str, rcut: float, sel: Union[int, List[int]], **kwargs + self, tab_file: str, rcut: float, sel: Union[int, List[int]], type_map: List[str], rcond: Optional[float] = None, atom_ener: Optional[List[float]] = None, **kwargs ): torch.nn.Module.__init__(self) self.model_def_script = "" @@ -72,6 +79,10 @@ def __init__( self.tab = self._set_pairtab(tab_file, rcut) BaseAtomicModel.__init__(self, **kwargs) + self.rcond = rcond + self.atom_ener = atom_ener + self.type_map = type_map + self.ntypes = len(type_map) # handle deserialization with no input file if self.tab_file is not None: @@ -79,16 +90,18 @@ def __init__( tab_info, tab_data, ) = self.tab.get() # this returns -> Tuple[np.array, np.array] - nspline, ntypes = tab_info[-2:].astype(int) + nspline, ntypes_tab = tab_info[-2:].astype(int) self.register_buffer("tab_info", torch.from_numpy(tab_info)) self.register_buffer( "tab_data", - torch.from_numpy(tab_data).reshape(ntypes, ntypes, nspline, 4), + torch.from_numpy(tab_data).reshape(ntypes_tab, ntypes_tab, nspline, 4), ) + if self.ntypes != ntypes_tab: + raise ValueError("The `type_map` provided does not match the number of columns in the table.") else: self.register_buffer("tab_info", None) self.register_buffer("tab_data", None) - self.bias_atom_e = None + self.bias_atom_e = torch.zeros(self.ntypes,1, dtype=env.GLOBAL_PT_ENER_FLOAT_PRECISION, device=env.DEVICE) # self.model_type = "ener" # self.model_version = MODEL_VERSION ## this shoud be in the parent class @@ -122,8 +135,8 @@ def get_rcut(self) -> float: return self.rcut @torch.jit.export - def get_type_map(self) -> Optional[List[str]]: - raise NotImplementedError("TODO: implement this method") + def get_type_map(self) -> List[str]: + return self.type_map def get_sel(self) -> List[int]: return [self.sel] @@ -154,6 +167,9 @@ def serialize(self) -> dict: "tab": self.tab.serialize(), "rcut": self.rcut, "sel": self.sel, + "type_map": self.type_map, + "rcond": self.rcond, + "atom_ener": self.atom_ener } ) return dd @@ -164,10 +180,13 @@ def deserialize(cls, data) -> "PairTabAtomicModel": check_version_compatibility(data.pop("@version", 1), 1, 1) rcut = data.pop("rcut") sel = data.pop("sel") + type_map = data.pop("type_map") + rcond = data.pop("rcond") + atom_ener = data.pop("atom_ener") tab = PairTab.deserialize(data.pop("tab")) data.pop("@class", None) data.pop("type", None) - tab_model = cls(None, rcut, sel, **data) + tab_model = cls(None, rcut, sel, type_map, **data) tab_model.tab = tab tab_model.register_buffer("tab_info", torch.from_numpy(tab_model.tab.tab_info)) nspline, ntypes = tab_model.tab.tab_info[-2:].astype(int) @@ -200,42 +219,16 @@ def compute_or_load_stat( The path to the stat file. """ - if stat_file_path is not None: - stat_file_path = stat_file_path / "bias_atom_e" - if stat_file_path is not None and stat_file_path.is_file(): - bias_atom_e = stat_file_path.load_numpy() - else: - if callable(merged): - # only get data for once - sampled = merged() - else: - sampled = merged - energy = [item["energy"] for item in sampled] - data_mixed_type = "real_natoms_vec" in sampled[0] - if data_mixed_type: - input_natoms = [item["real_natoms_vec"] for item in sampled] - else: - input_natoms = [item["natoms"] for item in sampled] - # shape: (nframes, ndim) - merged_energy = to_numpy_array(torch.cat(energy)) - # shape: (nframes, ntypes) - merged_natoms = to_numpy_array(torch.cat(input_natoms)[:, 2:]) - - bias_atom_e, _ = compute_stats_from_redu( - merged_energy, - merged_natoms, - assigned_bias=None, - rcond=None, - ) - if stat_file_path is not None: - stat_file_path.save_numpy(bias_atom_e) - assert all(x is not None for x in [bias_atom_e]) - ntypes = merged_natoms.shape[1] - self.bias_atom_e = torch.empty( - [ntypes, 1], dtype=torch.float64, device=env.DEVICE + bias_atom_e = compute_output_stats( + merged, + stat_file_path, + self.rcond, + self.atom_ener ) self.bias_atom_e.copy_( - torch.tensor(bias_atom_e, device=env.DEVICE).view([ntypes, 1]) + torch.tensor(bias_atom_e, device=env.DEVICE).view( + [self.ntypes, self.dim_out] + ) ) def change_energy_bias(self) -> None: diff --git a/deepmd/pt/model/task/ener.py b/deepmd/pt/model/task/ener.py index 8bf9cc1c90..fba8bb85c8 100644 --- a/deepmd/pt/model/task/ener.py +++ b/deepmd/pt/model/task/ener.py @@ -33,8 +33,8 @@ from deepmd.pt.utils.utils import ( to_numpy_array, ) -from deepmd.utils.out_stat import ( - compute_stats_from_redu, +from deepmd.pt.utils.stat import ( + compute_output_stats, ) from deepmd.utils.path import ( DPPath, @@ -84,8 +84,8 @@ class InvarFitting(GeneralFitting): Random seed. exclude_types: List[int] Atomic contributions of the excluded atom types are set zero. - atom_ener - Specifying atomic energy contribution in vacuum. The `set_davg_zero` key in the descrptor should be set. + atom_ener: List[float], optional + Specifying atomic energy contribution in vacuum. The `set_davg_zero` key in the descrptor should be set. """ @@ -164,41 +164,12 @@ def compute_output_stats( The path to the stat file. """ - if stat_file_path is not None: - stat_file_path = stat_file_path / "bias_atom_e" - if stat_file_path is not None and stat_file_path.is_file(): - bias_atom_e = stat_file_path.load_numpy() - else: - if callable(merged): - # only get data for once - sampled = merged() - else: - sampled = merged - energy = [item["energy"] for item in sampled] - data_mixed_type = "real_natoms_vec" in sampled[0] - if data_mixed_type: - input_natoms = [item["real_natoms_vec"] for item in sampled] - else: - input_natoms = [item["natoms"] for item in sampled] - # shape: (nframes, ndim) - merged_energy = to_numpy_array(torch.cat(energy)) - # shape: (nframes, ntypes) - merged_natoms = to_numpy_array(torch.cat(input_natoms)[:, 2:]) - if self.atom_ener is not None and len(self.atom_ener) > 0: - assigned_atom_ener = np.array( - [ee if ee is not None else np.nan for ee in self.atom_ener] - ) - else: - assigned_atom_ener = None - bias_atom_e, _ = compute_stats_from_redu( - merged_energy, - merged_natoms, - assigned_bias=assigned_atom_ener, - rcond=self.rcond, - ) - if stat_file_path is not None: - stat_file_path.save_numpy(bias_atom_e) - assert all(x is not None for x in [bias_atom_e]) + bias_atom_e = compute_output_stats( + merged, + stat_file_path, + self.rcond, + self.atom_ener + ) self.bias_atom_e.copy_( torch.tensor(bias_atom_e, device=env.DEVICE).view( [self.ntypes, self.dim_out] diff --git a/deepmd/pt/utils/stat.py b/deepmd/pt/utils/stat.py index 3b246a0ec2..2e6009366a 100644 --- a/deepmd/pt/utils/stat.py +++ b/deepmd/pt/utils/stat.py @@ -2,10 +2,23 @@ import logging import torch +from typing import ( + Callable, + Dict, + List, + Optional, + Union, +) +from deepmd.utils.out_stat import ( + compute_stats_from_redu, +) from deepmd.pt.utils.utils import ( dict_to_device, ) +from deepmd.utils.path import ( + DPPath, +) log = logging.getLogger(__name__) @@ -50,3 +63,67 @@ def make_stat_input(datasets, dataloaders, nbatches): dict_to_device(sys_stat) lst.append(sys_stat) return lst + +def compute_output_stats( + self, + merged: Union[Callable[[], List[dict]], List[dict]], + stat_file_path: Optional[DPPath] = None, + rcond: Optional[float] = None, + atom_ener: Optional[List[float]] = None + ): + """ + Compute the output statistics (e.g. energy bias) for the fitting net from packed data. + + Parameters + ---------- + merged : Union[Callable[[], List[dict]], List[dict]] + - List[dict]: A list of data samples from various data systems. + Each element, `merged[i]`, is a data dictionary containing `keys`: `torch.Tensor` + originating from the `i`-th data system. + - Callable[[], List[dict]]: A lazy function that returns data samples in the above format + only when needed. Since the sampling process can be slow and memory-intensive, + the lazy function helps by only sampling once. + stat_file_path : DPPath, optional + The path to the stat file. + rcond : float, optional + The condition number for the regression of atomic energy. + atom_ener : List[float], optional + Specifying atomic energy contribution in vacuum. The `set_davg_zero` key in the descrptor should be set. + + """ + if stat_file_path is not None: + stat_file_path = stat_file_path / "bias_atom_e" + if stat_file_path is not None and stat_file_path.is_file(): + bias_atom_e = stat_file_path.load_numpy() + else: + if callable(merged): + # only get data for once + sampled = merged() + else: + sampled = merged + energy = [item["energy"] for item in sampled] + data_mixed_type = "real_natoms_vec" in sampled[0] + if data_mixed_type: + input_natoms = [item["real_natoms_vec"] for item in sampled] + else: + input_natoms = [item["natoms"] for item in sampled] + # shape: (nframes, ndim) + merged_energy = to_numpy_array(torch.cat(energy)) + # shape: (nframes, ntypes) + merged_natoms = to_numpy_array(torch.cat(input_natoms)[:, 2:]) + if atom_ener is not None and len(atom_ener) > 0: + assigned_atom_ener = np.array( + [ee if ee is not None else np.nan for ee in atom_ener] + ) + else: + assigned_atom_ener = None + bias_atom_e, _ = compute_stats_from_redu( + merged_energy, + merged_natoms, + assigned_bias=assigned_atom_ener, + rcond=rcond, + ) + if stat_file_path is not None: + stat_file_path.save_numpy(bias_atom_e) + assert all(x is not None for x in [bias_atom_e]) + return torch.tensor(bias_atom_e, device=env.DEVICE).view([ntypes, 1]) \ No newline at end of file diff --git a/source/tests/pt/model/test_linear_atomic_model.py b/source/tests/pt/model/test_linear_atomic_model.py index fc2e8ea64a..66df1df8fd 100644 --- a/source/tests/pt/model/test_linear_atomic_model.py +++ b/source/tests/pt/model/test_linear_atomic_model.py @@ -69,7 +69,7 @@ def test_pairwise(self, mock_loadtxt): ).to(env.DEVICE) type_map = ["foo", "bar"] - zbl_model = PairTabAtomicModel(tab_file=file_path, rcut=0.3, sel=2) + zbl_model = PairTabAtomicModel(tab_file=file_path, rcut=0.3, sel=2, type_map=["H", "O"]) dp_model = DPAtomicModel(ds, ft, type_map=type_map).to(env.DEVICE) wgt_model = DPZBLLinearAtomicModel( dp_model, @@ -139,7 +139,7 @@ def setUp(self, mock_loadtxt): ).to(env.DEVICE) type_map = ["foo", "bar"] dp_model = DPAtomicModel(ds, ft, type_map=type_map).to(env.DEVICE) - zbl_model = PairTabAtomicModel(file_path, self.rcut, sum(self.sel)) + zbl_model = PairTabAtomicModel(file_path, self.rcut, sum(self.sel), type_map=["H", "O"]) self.md0 = DPZBLLinearAtomicModel( dp_model, zbl_model, diff --git a/source/tests/pt/model/test_pairtab_atomic_model.py b/source/tests/pt/model/test_pairtab_atomic_model.py index 021035e3de..66fdae5fdb 100644 --- a/source/tests/pt/model/test_pairtab_atomic_model.py +++ b/source/tests/pt/model/test_pairtab_atomic_model.py @@ -31,8 +31,8 @@ def setUp(self, mock_loadtxt) -> None: [0.02, 0.25, 0.4, 0.75], ] ) - - self.model = PairTabAtomicModel(tab_file=file_path, rcut=0.02, sel=2) + self.type_map = ['H', "O"] + self.model = PairTabAtomicModel(tab_file=file_path, rcut=0.02, sel=2, type_map=self.type_map) self.extended_coord = torch.tensor( [ @@ -61,6 +61,7 @@ def setUp(self, mock_loadtxt) -> None: self.nlist = torch.tensor( [[[1, 2], [0, 2]], [[1, 2], [0, 3]]], device=env.DEVICE ) + def test_without_mask(self): result = self.model.forward_atomic( @@ -97,8 +98,7 @@ def test_with_mask(self): def test_jit(self): model = torch.jit.script(self.model) self.assertEqual(model.get_rcut(), 0.02) - with self.assertRaises(torch.jit.Error): - self.assertEqual(model.get_type_map(), None) + self.assertEqual(model.get_type_map(), ["H", "O"]) def test_deserialize(self): model1 = PairTabAtomicModel.deserialize(self.model.serialize()) @@ -121,8 +121,7 @@ def test_deserialize(self): model1 = torch.jit.script(model1) self.assertEqual(model1.get_rcut(), 0.02) - with self.assertRaises(torch.jit.Error): - self.assertEqual(model1.get_type_map(), None) + self.assertEqual(model1.get_type_map(), ["H", "O"]) def test_cross_deserialize(self): model_dict = self.model.serialize() # pytorch model to dict @@ -228,7 +227,7 @@ def test_extrapolation_nonzero_rmax(self, mock_loadtxt) -> None: device=env.DEVICE, ) - model = PairTabAtomicModel(tab_file=file_path, rcut=rcut, sel=2) + model = PairTabAtomicModel(tab_file=file_path, rcut=rcut, sel=2, type_map=["H"]) results.append( model.forward_atomic(extended_coord, extended_atype, nlist)["energy"] ) diff --git a/source/tests/pt/test_finetune.py b/source/tests/pt/test_finetune.py index 4049aa86ee..b0ee75af4e 100644 --- a/source/tests/pt/test_finetune.py +++ b/source/tests/pt/test_finetune.py @@ -136,20 +136,20 @@ def setUp(self): def tearDown(self) -> None: FinetuneTest.tearDown(self) - -class TestEnergyZBLModelSeA(unittest.TestCase, FinetuneTest): - def setUp(self): - self.data_file = [str(Path(__file__).parent / "water/data/data_0")] - self.data = DeepmdDataSystem( - self.data_file, - batch_size=1, - test_size=1, - ) - self.data.add("energy", ndof=1, atomic=False, must=True, high_prec=True) - self.model_config = model_zbl - - def tearDown(self) -> None: - FinetuneTest.tearDown(self) +## Disabled for now. +# class TestEnergyZBLModelSeA(unittest.TestCase, FinetuneTest): +# def setUp(self): +# self.data_file = [str(Path(__file__).parent / "water/data/data_0")] +# self.data = DeepmdDataSystem( +# self.data_file, +# batch_size=1, +# test_size=1, +# ) +# self.data.add("energy", ndof=1, atomic=False, must=True, high_prec=True) +# self.model_config = model_zbl + +# def tearDown(self) -> None: +# FinetuneTest.tearDown(self) class TestEnergyModelDPA2(unittest.TestCase, FinetuneTest): From a9f65be65f8555d45f5039d7618997f3b348bd3c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 07:48:06 +0000 Subject: [PATCH 35/59] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../atomic_model/pairtab_atomic_model.py | 11 ++++++-- .../atomic_model/pairtab_atomic_model.py | 27 +++++++++++-------- deepmd/pt/model/task/ener.py | 8 +----- deepmd/pt/utils/stat.py | 26 +++++++++--------- .../pt/model/test_linear_atomic_model.py | 8 ++++-- .../pt/model/test_pairtab_atomic_model.py | 11 +++++--- source/tests/pt/test_finetune.py | 2 +- 7 files changed, 53 insertions(+), 40 deletions(-) diff --git a/deepmd/dpmodel/atomic_model/pairtab_atomic_model.py b/deepmd/dpmodel/atomic_model/pairtab_atomic_model.py index 754299f4a6..795d111a8c 100644 --- a/deepmd/dpmodel/atomic_model/pairtab_atomic_model.py +++ b/deepmd/dpmodel/atomic_model/pairtab_atomic_model.py @@ -53,7 +53,12 @@ class PairTabAtomicModel(BaseAtomicModel): """ def __init__( - self, tab_file: str, rcut: float, sel: Union[int, List[int]], type_map: List[str], **kwargs + self, + tab_file: str, + rcut: float, + sel: Union[int, List[int]], + type_map: List[str], + **kwargs, ): super().__init__() self.tab_file = tab_file @@ -68,7 +73,9 @@ def __init__( nspline, ntypes_tab = self.tab_info[-2:].astype(int) self.tab_data = self.tab_data.reshape(ntypes_tab, ntypes_tab, nspline, 4) if self.ntypes != ntypes_tab: - raise ValueError("The `type_map` provided does not match the number of columns in the table.") + raise ValueError( + "The `type_map` provided does not match the number of columns in the table." + ) else: self.tab_info, self.tab_data = None, None diff --git a/deepmd/pt/model/atomic_model/pairtab_atomic_model.py b/deepmd/pt/model/atomic_model/pairtab_atomic_model.py index 7078319e5e..6d42dae9c5 100644 --- a/deepmd/pt/model/atomic_model/pairtab_atomic_model.py +++ b/deepmd/pt/model/atomic_model/pairtab_atomic_model.py @@ -17,9 +17,6 @@ from deepmd.pt.utils import ( env, ) -from deepmd.pt.utils.utils import ( - to_numpy_array, -) from deepmd.pt.utils.stat import ( compute_output_stats, ) @@ -70,7 +67,14 @@ class PairTabAtomicModel(torch.nn.Module, BaseAtomicModel): """ def __init__( - self, tab_file: str, rcut: float, sel: Union[int, List[int]], type_map: List[str], rcond: Optional[float] = None, atom_ener: Optional[List[float]] = None, **kwargs + self, + tab_file: str, + rcut: float, + sel: Union[int, List[int]], + type_map: List[str], + rcond: Optional[float] = None, + atom_ener: Optional[List[float]] = None, + **kwargs, ): torch.nn.Module.__init__(self) self.model_def_script = "" @@ -97,11 +101,15 @@ def __init__( torch.from_numpy(tab_data).reshape(ntypes_tab, ntypes_tab, nspline, 4), ) if self.ntypes != ntypes_tab: - raise ValueError("The `type_map` provided does not match the number of columns in the table.") + raise ValueError( + "The `type_map` provided does not match the number of columns in the table." + ) else: self.register_buffer("tab_info", None) self.register_buffer("tab_data", None) - self.bias_atom_e = torch.zeros(self.ntypes,1, dtype=env.GLOBAL_PT_ENER_FLOAT_PRECISION, device=env.DEVICE) + self.bias_atom_e = torch.zeros( + self.ntypes, 1, dtype=env.GLOBAL_PT_ENER_FLOAT_PRECISION, device=env.DEVICE + ) # self.model_type = "ener" # self.model_version = MODEL_VERSION ## this shoud be in the parent class @@ -169,7 +177,7 @@ def serialize(self) -> dict: "sel": self.sel, "type_map": self.type_map, "rcond": self.rcond, - "atom_ener": self.atom_ener + "atom_ener": self.atom_ener, } ) return dd @@ -220,10 +228,7 @@ def compute_or_load_stat( """ bias_atom_e = compute_output_stats( - merged, - stat_file_path, - self.rcond, - self.atom_ener + merged, stat_file_path, self.rcond, self.atom_ener ) self.bias_atom_e.copy_( torch.tensor(bias_atom_e, device=env.DEVICE).view( diff --git a/deepmd/pt/model/task/ener.py b/deepmd/pt/model/task/ener.py index fba8bb85c8..a11f6410a4 100644 --- a/deepmd/pt/model/task/ener.py +++ b/deepmd/pt/model/task/ener.py @@ -30,9 +30,6 @@ from deepmd.pt.utils.env import ( DEFAULT_PRECISION, ) -from deepmd.pt.utils.utils import ( - to_numpy_array, -) from deepmd.pt.utils.stat import ( compute_output_stats, ) @@ -165,10 +162,7 @@ def compute_output_stats( """ bias_atom_e = compute_output_stats( - merged, - stat_file_path, - self.rcond, - self.atom_ener + merged, stat_file_path, self.rcond, self.atom_ener ) self.bias_atom_e.copy_( torch.tensor(bias_atom_e, device=env.DEVICE).view( diff --git a/deepmd/pt/utils/stat.py b/deepmd/pt/utils/stat.py index 2e6009366a..11c9cfd38c 100644 --- a/deepmd/pt/utils/stat.py +++ b/deepmd/pt/utils/stat.py @@ -1,21 +1,20 @@ # SPDX-License-Identifier: LGPL-3.0-or-later import logging - -import torch from typing import ( Callable, - Dict, List, Optional, Union, ) -from deepmd.utils.out_stat import ( - compute_stats_from_redu, -) + +import torch from deepmd.pt.utils.utils import ( dict_to_device, ) +from deepmd.utils.out_stat import ( + compute_stats_from_redu, +) from deepmd.utils.path import ( DPPath, ) @@ -64,13 +63,14 @@ def make_stat_input(datasets, dataloaders, nbatches): lst.append(sys_stat) return lst + def compute_output_stats( - self, - merged: Union[Callable[[], List[dict]], List[dict]], - stat_file_path: Optional[DPPath] = None, - rcond: Optional[float] = None, - atom_ener: Optional[List[float]] = None - ): + self, + merged: Union[Callable[[], List[dict]], List[dict]], + stat_file_path: Optional[DPPath] = None, + rcond: Optional[float] = None, + atom_ener: Optional[List[float]] = None, +): """ Compute the output statistics (e.g. energy bias) for the fitting net from packed data. @@ -126,4 +126,4 @@ def compute_output_stats( if stat_file_path is not None: stat_file_path.save_numpy(bias_atom_e) assert all(x is not None for x in [bias_atom_e]) - return torch.tensor(bias_atom_e, device=env.DEVICE).view([ntypes, 1]) \ No newline at end of file + return torch.tensor(bias_atom_e, device=env.DEVICE).view([ntypes, 1]) diff --git a/source/tests/pt/model/test_linear_atomic_model.py b/source/tests/pt/model/test_linear_atomic_model.py index 66df1df8fd..bafea1cf80 100644 --- a/source/tests/pt/model/test_linear_atomic_model.py +++ b/source/tests/pt/model/test_linear_atomic_model.py @@ -69,7 +69,9 @@ def test_pairwise(self, mock_loadtxt): ).to(env.DEVICE) type_map = ["foo", "bar"] - zbl_model = PairTabAtomicModel(tab_file=file_path, rcut=0.3, sel=2, type_map=["H", "O"]) + zbl_model = PairTabAtomicModel( + tab_file=file_path, rcut=0.3, sel=2, type_map=["H", "O"] + ) dp_model = DPAtomicModel(ds, ft, type_map=type_map).to(env.DEVICE) wgt_model = DPZBLLinearAtomicModel( dp_model, @@ -139,7 +141,9 @@ def setUp(self, mock_loadtxt): ).to(env.DEVICE) type_map = ["foo", "bar"] dp_model = DPAtomicModel(ds, ft, type_map=type_map).to(env.DEVICE) - zbl_model = PairTabAtomicModel(file_path, self.rcut, sum(self.sel), type_map=["H", "O"]) + zbl_model = PairTabAtomicModel( + file_path, self.rcut, sum(self.sel), type_map=["H", "O"] + ) self.md0 = DPZBLLinearAtomicModel( dp_model, zbl_model, diff --git a/source/tests/pt/model/test_pairtab_atomic_model.py b/source/tests/pt/model/test_pairtab_atomic_model.py index 66fdae5fdb..072d4fd186 100644 --- a/source/tests/pt/model/test_pairtab_atomic_model.py +++ b/source/tests/pt/model/test_pairtab_atomic_model.py @@ -31,8 +31,10 @@ def setUp(self, mock_loadtxt) -> None: [0.02, 0.25, 0.4, 0.75], ] ) - self.type_map = ['H', "O"] - self.model = PairTabAtomicModel(tab_file=file_path, rcut=0.02, sel=2, type_map=self.type_map) + self.type_map = ["H", "O"] + self.model = PairTabAtomicModel( + tab_file=file_path, rcut=0.02, sel=2, type_map=self.type_map + ) self.extended_coord = torch.tensor( [ @@ -61,7 +63,6 @@ def setUp(self, mock_loadtxt) -> None: self.nlist = torch.tensor( [[[1, 2], [0, 2]], [[1, 2], [0, 3]]], device=env.DEVICE ) - def test_without_mask(self): result = self.model.forward_atomic( @@ -227,7 +228,9 @@ def test_extrapolation_nonzero_rmax(self, mock_loadtxt) -> None: device=env.DEVICE, ) - model = PairTabAtomicModel(tab_file=file_path, rcut=rcut, sel=2, type_map=["H"]) + model = PairTabAtomicModel( + tab_file=file_path, rcut=rcut, sel=2, type_map=["H"] + ) results.append( model.forward_atomic(extended_coord, extended_atype, nlist)["energy"] ) diff --git a/source/tests/pt/test_finetune.py b/source/tests/pt/test_finetune.py index b0ee75af4e..2aa4a7a310 100644 --- a/source/tests/pt/test_finetune.py +++ b/source/tests/pt/test_finetune.py @@ -32,7 +32,6 @@ from .model.test_permutation import ( model_dpa2, model_se_e2_a, - model_zbl, ) @@ -136,6 +135,7 @@ def setUp(self): def tearDown(self) -> None: FinetuneTest.tearDown(self) + ## Disabled for now. # class TestEnergyZBLModelSeA(unittest.TestCase, FinetuneTest): # def setUp(self): From 18a4897b491045773d4576ad2b4b65cafe249c6e Mon Sep 17 00:00:00 2001 From: anyangml Date: Mon, 4 Mar 2024 07:52:02 +0000 Subject: [PATCH 36/59] fix: precommit --- deepmd/pt/utils/stat.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/deepmd/pt/utils/stat.py b/deepmd/pt/utils/stat.py index 11c9cfd38c..3acfc0a1af 100644 --- a/deepmd/pt/utils/stat.py +++ b/deepmd/pt/utils/stat.py @@ -6,7 +6,13 @@ Optional, Union, ) - +import numpy as np +from deepmd.pt.utils import ( + env, +) +from deepmd.pt.utils.utils import ( + to_numpy_array, +) import torch from deepmd.pt.utils.utils import ( From 94bea6a6f09da11c4454df65a4400cc228c1dee3 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 07:52:33 +0000 Subject: [PATCH 37/59] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- deepmd/pt/utils/stat.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/deepmd/pt/utils/stat.py b/deepmd/pt/utils/stat.py index 3acfc0a1af..34296cb1d1 100644 --- a/deepmd/pt/utils/stat.py +++ b/deepmd/pt/utils/stat.py @@ -6,17 +6,16 @@ Optional, Union, ) + import numpy as np +import torch + from deepmd.pt.utils import ( env, ) -from deepmd.pt.utils.utils import ( - to_numpy_array, -) -import torch - from deepmd.pt.utils.utils import ( dict_to_device, + to_numpy_array, ) from deepmd.utils.out_stat import ( compute_stats_from_redu, From 09f9352b6ae2b2546059a512f7bb32495860fb4f Mon Sep 17 00:00:00 2001 From: anyangml Date: Mon, 4 Mar 2024 08:22:09 +0000 Subject: [PATCH 38/59] fix: precommit --- deepmd/pt/model/atomic_model/pairtab_atomic_model.py | 2 +- deepmd/pt/utils/stat.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/deepmd/pt/model/atomic_model/pairtab_atomic_model.py b/deepmd/pt/model/atomic_model/pairtab_atomic_model.py index 6d42dae9c5..5ecde209a5 100644 --- a/deepmd/pt/model/atomic_model/pairtab_atomic_model.py +++ b/deepmd/pt/model/atomic_model/pairtab_atomic_model.py @@ -194,7 +194,7 @@ def deserialize(cls, data) -> "PairTabAtomicModel": tab = PairTab.deserialize(data.pop("tab")) data.pop("@class", None) data.pop("type", None) - tab_model = cls(None, rcut, sel, type_map, **data) + tab_model = cls(None, rcut, sel, type_map, rcond, atom_ener, **data) tab_model.tab = tab tab_model.register_buffer("tab_info", torch.from_numpy(tab_model.tab.tab_info)) nspline, ntypes = tab_model.tab.tab_info[-2:].astype(int) diff --git a/deepmd/pt/utils/stat.py b/deepmd/pt/utils/stat.py index 34296cb1d1..38b8b7c3f1 100644 --- a/deepmd/pt/utils/stat.py +++ b/deepmd/pt/utils/stat.py @@ -131,4 +131,4 @@ def compute_output_stats( if stat_file_path is not None: stat_file_path.save_numpy(bias_atom_e) assert all(x is not None for x in [bias_atom_e]) - return torch.tensor(bias_atom_e, device=env.DEVICE).view([ntypes, 1]) + return torch.tensor(bias_atom_e, device=env.DEVICE) From a63089dd3bca915dbc56509544e563504716a83b Mon Sep 17 00:00:00 2001 From: anyangml Date: Mon, 4 Mar 2024 08:59:50 +0000 Subject: [PATCH 39/59] fix: UTs --- deepmd/pt/model/model/__init__.py | 2 +- deepmd/pt/utils/stat.py | 1 - source/tests/common/dpmodel/test_linear_atomic_model.py | 4 ++-- source/tests/common/dpmodel/test_pairtab_atomic_model.py | 4 ++-- 4 files changed, 5 insertions(+), 6 deletions(-) diff --git a/deepmd/pt/model/model/__init__.py b/deepmd/pt/model/model/__init__.py index bd354af8d8..aba73ae76d 100644 --- a/deepmd/pt/model/model/__init__.py +++ b/deepmd/pt/model/model/__init__.py @@ -66,7 +66,7 @@ def get_zbl_model(model_params): # pairtab filepath = model_params["use_srtab"] pt_model = PairTabAtomicModel( - filepath, model_params["descriptor"]["rcut"], model_params["descriptor"]["sel"] + filepath, model_params["descriptor"]["rcut"], model_params["descriptor"]["sel"], type_map=model_params["type_map"] ) rmin = model_params["sw_rmin"] diff --git a/deepmd/pt/utils/stat.py b/deepmd/pt/utils/stat.py index 38b8b7c3f1..63abccc75d 100644 --- a/deepmd/pt/utils/stat.py +++ b/deepmd/pt/utils/stat.py @@ -70,7 +70,6 @@ def make_stat_input(datasets, dataloaders, nbatches): def compute_output_stats( - self, merged: Union[Callable[[], List[dict]], List[dict]], stat_file_path: Optional[DPPath] = None, rcond: Optional[float] = None, diff --git a/source/tests/common/dpmodel/test_linear_atomic_model.py b/source/tests/common/dpmodel/test_linear_atomic_model.py index 79eef46b8a..67dda6d14e 100644 --- a/source/tests/common/dpmodel/test_linear_atomic_model.py +++ b/source/tests/common/dpmodel/test_linear_atomic_model.py @@ -53,7 +53,7 @@ def test_pairwise(self, mock_loadtxt): ) type_map = ["foo", "bar"] - zbl_model = PairTabAtomicModel(tab_file=file_path, rcut=0.3, sel=2) + zbl_model = PairTabAtomicModel(tab_file=file_path, rcut=0.3, sel=2, type_map=type_map) dp_model = DPAtomicModel(ds, ft, type_map=type_map) wgt_model = DPZBLLinearAtomicModel( @@ -145,7 +145,7 @@ def setUp(self, mock_loadtxt): ) type_map = ["foo", "bar"] dp_model = DPAtomicModel(ds, ft, type_map=type_map) - zbl_model = PairTabAtomicModel(file_path, self.rcut, sum(self.sel)) + zbl_model = PairTabAtomicModel(file_path, self.rcut, sum(self.sel), type_map=type_map) self.md0 = DPZBLLinearAtomicModel( dp_model, zbl_model, diff --git a/source/tests/common/dpmodel/test_pairtab_atomic_model.py b/source/tests/common/dpmodel/test_pairtab_atomic_model.py index d004f9a37a..391be74170 100644 --- a/source/tests/common/dpmodel/test_pairtab_atomic_model.py +++ b/source/tests/common/dpmodel/test_pairtab_atomic_model.py @@ -24,7 +24,7 @@ def setUp(self, mock_loadtxt) -> None: ] ) - self.model = PairTabAtomicModel(tab_file=file_path, rcut=0.02, sel=2) + self.model = PairTabAtomicModel(tab_file=file_path, rcut=0.02, sel=2, type_map=["H", "O"]) self.extended_coord = np.array( [ @@ -166,7 +166,7 @@ def test_extrapolation_nonzero_rmax(self, mock_loadtxt) -> None: ] ) - model = PairTabAtomicModel(tab_file=file_path, rcut=rcut, sel=2) + model = PairTabAtomicModel(tab_file=file_path, rcut=rcut, sel=2, type_map=["H"]) results.append( model.forward_atomic(extended_coord, extended_atype, nlist)["energy"] ) From bda547de3882f8c01faf8c5f64cfa0155da8dcd5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 09:00:44 +0000 Subject: [PATCH 40/59] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- deepmd/pt/model/model/__init__.py | 5 ++++- source/tests/common/dpmodel/test_linear_atomic_model.py | 8 ++++++-- source/tests/common/dpmodel/test_pairtab_atomic_model.py | 8 ++++++-- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/deepmd/pt/model/model/__init__.py b/deepmd/pt/model/model/__init__.py index aba73ae76d..3827aa330f 100644 --- a/deepmd/pt/model/model/__init__.py +++ b/deepmd/pt/model/model/__init__.py @@ -66,7 +66,10 @@ def get_zbl_model(model_params): # pairtab filepath = model_params["use_srtab"] pt_model = PairTabAtomicModel( - filepath, model_params["descriptor"]["rcut"], model_params["descriptor"]["sel"], type_map=model_params["type_map"] + filepath, + model_params["descriptor"]["rcut"], + model_params["descriptor"]["sel"], + type_map=model_params["type_map"], ) rmin = model_params["sw_rmin"] diff --git a/source/tests/common/dpmodel/test_linear_atomic_model.py b/source/tests/common/dpmodel/test_linear_atomic_model.py index 67dda6d14e..1d79e2fc18 100644 --- a/source/tests/common/dpmodel/test_linear_atomic_model.py +++ b/source/tests/common/dpmodel/test_linear_atomic_model.py @@ -53,7 +53,9 @@ def test_pairwise(self, mock_loadtxt): ) type_map = ["foo", "bar"] - zbl_model = PairTabAtomicModel(tab_file=file_path, rcut=0.3, sel=2, type_map=type_map) + zbl_model = PairTabAtomicModel( + tab_file=file_path, rcut=0.3, sel=2, type_map=type_map + ) dp_model = DPAtomicModel(ds, ft, type_map=type_map) wgt_model = DPZBLLinearAtomicModel( @@ -145,7 +147,9 @@ def setUp(self, mock_loadtxt): ) type_map = ["foo", "bar"] dp_model = DPAtomicModel(ds, ft, type_map=type_map) - zbl_model = PairTabAtomicModel(file_path, self.rcut, sum(self.sel), type_map=type_map) + zbl_model = PairTabAtomicModel( + file_path, self.rcut, sum(self.sel), type_map=type_map + ) self.md0 = DPZBLLinearAtomicModel( dp_model, zbl_model, diff --git a/source/tests/common/dpmodel/test_pairtab_atomic_model.py b/source/tests/common/dpmodel/test_pairtab_atomic_model.py index 391be74170..524e869701 100644 --- a/source/tests/common/dpmodel/test_pairtab_atomic_model.py +++ b/source/tests/common/dpmodel/test_pairtab_atomic_model.py @@ -24,7 +24,9 @@ def setUp(self, mock_loadtxt) -> None: ] ) - self.model = PairTabAtomicModel(tab_file=file_path, rcut=0.02, sel=2, type_map=["H", "O"]) + self.model = PairTabAtomicModel( + tab_file=file_path, rcut=0.02, sel=2, type_map=["H", "O"] + ) self.extended_coord = np.array( [ @@ -166,7 +168,9 @@ def test_extrapolation_nonzero_rmax(self, mock_loadtxt) -> None: ] ) - model = PairTabAtomicModel(tab_file=file_path, rcut=rcut, sel=2, type_map=["H"]) + model = PairTabAtomicModel( + tab_file=file_path, rcut=rcut, sel=2, type_map=["H"] + ) results.append( model.forward_atomic(extended_coord, extended_atype, nlist)["energy"] ) From e6be71b339bcc092bd9a31bf6b07e8e23fa8e8aa Mon Sep 17 00:00:00 2001 From: anyangml Date: Mon, 4 Mar 2024 12:23:49 +0000 Subject: [PATCH 41/59] fix: UTs --- deepmd/pt/model/atomic_model/pairtab_atomic_model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deepmd/pt/model/atomic_model/pairtab_atomic_model.py b/deepmd/pt/model/atomic_model/pairtab_atomic_model.py index 5ecde209a5..79c2c5cb43 100644 --- a/deepmd/pt/model/atomic_model/pairtab_atomic_model.py +++ b/deepmd/pt/model/atomic_model/pairtab_atomic_model.py @@ -232,7 +232,7 @@ def compute_or_load_stat( ) self.bias_atom_e.copy_( torch.tensor(bias_atom_e, device=env.DEVICE).view( - [self.ntypes, self.dim_out] + [self.ntypes, 1] ) ) From 3482ef25e845185e295a5fc829162a128cbd5658 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 4 Mar 2024 12:24:25 +0000 Subject: [PATCH 42/59] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- deepmd/pt/model/atomic_model/pairtab_atomic_model.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/deepmd/pt/model/atomic_model/pairtab_atomic_model.py b/deepmd/pt/model/atomic_model/pairtab_atomic_model.py index 79c2c5cb43..44bec91485 100644 --- a/deepmd/pt/model/atomic_model/pairtab_atomic_model.py +++ b/deepmd/pt/model/atomic_model/pairtab_atomic_model.py @@ -231,9 +231,7 @@ def compute_or_load_stat( merged, stat_file_path, self.rcond, self.atom_ener ) self.bias_atom_e.copy_( - torch.tensor(bias_atom_e, device=env.DEVICE).view( - [self.ntypes, 1] - ) + torch.tensor(bias_atom_e, device=env.DEVICE).view([self.ntypes, 1]) ) def change_energy_bias(self) -> None: From f8e340ad7c4c42d4966be6d3fff0704d22e2f0b2 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 5 Mar 2024 06:30:01 +0000 Subject: [PATCH 43/59] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- source/tests/common/dpmodel/test_pairtab_atomic_model.py | 1 - 1 file changed, 1 deletion(-) diff --git a/source/tests/common/dpmodel/test_pairtab_atomic_model.py b/source/tests/common/dpmodel/test_pairtab_atomic_model.py index 35772ef84c..e2866d3766 100644 --- a/source/tests/common/dpmodel/test_pairtab_atomic_model.py +++ b/source/tests/common/dpmodel/test_pairtab_atomic_model.py @@ -169,7 +169,6 @@ def test_extrapolation_nonzero_rmax(self, mock_loadtxt) -> None: ) model = PairTabAtomicModel( - tab_file=file_path, rcut=rcut, sel=2, type_map=["S"] ) results.append( From 3610b3d6883a28f9bf247d6e4f2d0aa82d3ca71d Mon Sep 17 00:00:00 2001 From: anyangml Date: Tue, 5 Mar 2024 06:30:58 +0000 Subject: [PATCH 44/59] feat: add atype remap --- .../model/atomic_model/linear_atomic_model.py | 45 ++++++++++++++----- .../pt/model/test_linear_atomic_model.py | 23 ++++++++++ 2 files changed, 58 insertions(+), 10 deletions(-) diff --git a/deepmd/pt/model/atomic_model/linear_atomic_model.py b/deepmd/pt/model/atomic_model/linear_atomic_model.py index 9c30beca57..7d9e877a3e 100644 --- a/deepmd/pt/model/atomic_model/linear_atomic_model.py +++ b/deepmd/pt/model/atomic_model/linear_atomic_model.py @@ -94,9 +94,9 @@ def get_rcut(self) -> float: """Get the cut-off radius.""" return max(self.get_model_rcuts()) + @torch.jit.export def get_type_map(self) -> List[str]: - """Get the type map.""" - return self.type_map + self.type_map def get_model_rcuts(self) -> List[float]: """Get the cut-off radius for each individual models.""" @@ -187,10 +187,12 @@ def forward_atomic( ener_list = [] for i, model in enumerate(self.models): + ori_map = model.get_type_map() + updated_atype = self.remap_atype(extended_atype,ori_map,self.type_map) ener_list.append( model.forward_atomic( extended_coord, - extended_atype, + updated_atype, nlists_[i], mapping, fparam, @@ -216,6 +218,35 @@ def forward_atomic( } # (nframes, nloc, 1) return fit_ret + @staticmethod + def remap_atype(atype:torch.Tensor, ori_map: List[str], new_map: List[str]) -> torch.Tensor: + """ + This method is used to map the atype from the common type_map to the original type_map of + indivial AtomicModels. + + Parameters + ---------- + atype: torch.Tensor + The atom type tensor being updated, shape of (nframes, natoms) + ori_map: List[str] + The original type map of an AtomicModel. + new_map: List[str] + The common type map of the DPZBLLinearAtomicModel, created by the `get_type_map` method, + must be a subset of the ori_map. + + Return + ------- + torch.Tensor + """ + assert max(atype) < len(new_map), "The input `atype` cannot be handled by the type_map." + idx_2_type = {k: new_map[k] for k in range(len(new_map))} + type_2_idx = {atp: idx for idx, atp in enumerate(ori_map)} + # this maps the atype in the new map to the original map + mapping = {idx: type_2_idx[idx_2_type[idx]] for idx in range(len(new_map))} + updated_atype = atype.clone() + updated_atype.apply_(mapping.get) + return updated_atype + def fitting_output_def(self) -> FittingOutputDef: return FittingOutputDef( [ @@ -343,13 +374,7 @@ def __init__( # this is a placeholder being updated in _compute_weight, to handle Jit attribute init error. self.zbl_weight = torch.empty(0, dtype=torch.float64, device=env.DEVICE) - - @torch.jit.export - def get_type_map(self) -> List[str]: - dp_map = self.dp_model.get_type_map() - zbl_map = self.zbl_model.get_type_map() - return self.dp_model.get_type_map() - + def compute_or_load_stat( self, sampled_func, diff --git a/source/tests/pt/model/test_linear_atomic_model.py b/source/tests/pt/model/test_linear_atomic_model.py index fab6481a6f..4838daadfc 100644 --- a/source/tests/pt/model/test_linear_atomic_model.py +++ b/source/tests/pt/model/test_linear_atomic_model.py @@ -184,6 +184,29 @@ def test_jit(self): self.assertEqual(md3.get_rcut(), self.rcut) self.assertEqual(md3.get_type_map(), ["foo", "bar"]) +class TestRemmapMethod(unittest.TestCase): + + def test_invalid(self): + atype = torch.randint(2,4, (2,5)) + commonl = ["H"] + originl = ["Si","H","O", "S"] + with self.assertRaises(): + new_atype = remap_atype(atype, originl, commonl) + + def test_valid(self): + atype = torch.randint(0,3, (4,20)) + nl = ["H", "O", "S"] + ol = ["Si","H","O", "S"] + new_atype = remap_atype(atype, originl, commonl) + def trans(atype, map): + idx = atype.flatten().tolist() + res = [] + for i in idx: + res.append(map[i]) + return res + + assert trans(atype,nl) == trans(new_atype, ol) + if __name__ == "__main__": unittest.main(warnings="ignore") From caf5f781c9a3d031e29e1ed0c5fba8ce153c4f4c Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 5 Mar 2024 06:32:48 +0000 Subject: [PATCH 45/59] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../model/atomic_model/linear_atomic_model.py | 30 +++++++++++-------- .../pt/model/test_linear_atomic_model.py | 17 ++++++----- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/deepmd/pt/model/atomic_model/linear_atomic_model.py b/deepmd/pt/model/atomic_model/linear_atomic_model.py index 7d9e877a3e..9440b8276c 100644 --- a/deepmd/pt/model/atomic_model/linear_atomic_model.py +++ b/deepmd/pt/model/atomic_model/linear_atomic_model.py @@ -188,7 +188,7 @@ def forward_atomic( for i, model in enumerate(self.models): ori_map = model.get_type_map() - updated_atype = self.remap_atype(extended_atype,ori_map,self.type_map) + updated_atype = self.remap_atype(extended_atype, ori_map, self.type_map) ener_list.append( model.forward_atomic( extended_coord, @@ -219,30 +219,34 @@ def forward_atomic( return fit_ret @staticmethod - def remap_atype(atype:torch.Tensor, ori_map: List[str], new_map: List[str]) -> torch.Tensor: - """ - This method is used to map the atype from the common type_map to the original type_map of + def remap_atype( + atype: torch.Tensor, ori_map: List[str], new_map: List[str] + ) -> torch.Tensor: + """ + This method is used to map the atype from the common type_map to the original type_map of indivial AtomicModels. Parameters ---------- - atype: torch.Tensor + atype : torch.Tensor The atom type tensor being updated, shape of (nframes, natoms) - ori_map: List[str] + ori_map : List[str] The original type map of an AtomicModel. - new_map: List[str] + new_map : List[str] The common type map of the DPZBLLinearAtomicModel, created by the `get_type_map` method, must be a subset of the ori_map. - - Return + + Returns ------- torch.Tensor """ - assert max(atype) < len(new_map), "The input `atype` cannot be handled by the type_map." + assert max(atype) < len( + new_map + ), "The input `atype` cannot be handled by the type_map." idx_2_type = {k: new_map[k] for k in range(len(new_map))} - type_2_idx = {atp: idx for idx, atp in enumerate(ori_map)} + type_2_idx = {atp: idx for idx, atp in enumerate(ori_map)} # this maps the atype in the new map to the original map - mapping = {idx: type_2_idx[idx_2_type[idx]] for idx in range(len(new_map))} + mapping = {idx: type_2_idx[idx_2_type[idx]] for idx in range(len(new_map))} updated_atype = atype.clone() updated_atype.apply_(mapping.get) return updated_atype @@ -374,7 +378,7 @@ def __init__( # this is a placeholder being updated in _compute_weight, to handle Jit attribute init error. self.zbl_weight = torch.empty(0, dtype=torch.float64, device=env.DEVICE) - + def compute_or_load_stat( self, sampled_func, diff --git a/source/tests/pt/model/test_linear_atomic_model.py b/source/tests/pt/model/test_linear_atomic_model.py index 4838daadfc..f168e1613c 100644 --- a/source/tests/pt/model/test_linear_atomic_model.py +++ b/source/tests/pt/model/test_linear_atomic_model.py @@ -184,28 +184,29 @@ def test_jit(self): self.assertEqual(md3.get_rcut(), self.rcut) self.assertEqual(md3.get_type_map(), ["foo", "bar"]) -class TestRemmapMethod(unittest.TestCase): +class TestRemmapMethod(unittest.TestCase): def test_invalid(self): - atype = torch.randint(2,4, (2,5)) + atype = torch.randint(2, 4, (2, 5)) commonl = ["H"] - originl = ["Si","H","O", "S"] + originl = ["Si", "H", "O", "S"] with self.assertRaises(): new_atype = remap_atype(atype, originl, commonl) - + def test_valid(self): - atype = torch.randint(0,3, (4,20)) + atype = torch.randint(0, 3, (4, 20)) nl = ["H", "O", "S"] - ol = ["Si","H","O", "S"] + ol = ["Si", "H", "O", "S"] new_atype = remap_atype(atype, originl, commonl) + def trans(atype, map): idx = atype.flatten().tolist() res = [] for i in idx: res.append(map[i]) return res - - assert trans(atype,nl) == trans(new_atype, ol) + + assert trans(atype, nl) == trans(new_atype, ol) if __name__ == "__main__": From 7d4e49c22e2a6dcb60de17c1fce88593bc89c203 Mon Sep 17 00:00:00 2001 From: anyangml Date: Tue, 5 Mar 2024 08:11:37 +0000 Subject: [PATCH 46/59] fix: add UTs --- .../atomic_model/make_base_atomic_model.py | 11 +++------ .../model/atomic_model/linear_atomic_model.py | 12 ++++------ .../pt/model/test_linear_atomic_model.py | 23 +++++++++---------- 3 files changed, 18 insertions(+), 28 deletions(-) diff --git a/deepmd/dpmodel/atomic_model/make_base_atomic_model.py b/deepmd/dpmodel/atomic_model/make_base_atomic_model.py index 5548147d54..ce1a6708e6 100644 --- a/deepmd/dpmodel/atomic_model/make_base_atomic_model.py +++ b/deepmd/dpmodel/atomic_model/make_base_atomic_model.py @@ -54,18 +54,13 @@ def get_rcut(self) -> float: pass @abstractmethod - def get_type_map(self) -> Optional[List[str]]: + def get_type_map(self) -> List[str]: """Get the type map.""" + pass def get_ntypes(self) -> int: """Get the number of atom types.""" - tmap = self.get_type_map() - if tmap is not None: - return len(tmap) - else: - raise ValueError( - "cannot infer the number of types from a None type map" - ) + return len(self.get_type_map()) @abstractmethod def get_sel(self) -> List[int]: diff --git a/deepmd/pt/model/atomic_model/linear_atomic_model.py b/deepmd/pt/model/atomic_model/linear_atomic_model.py index 9440b8276c..446b88da46 100644 --- a/deepmd/pt/model/atomic_model/linear_atomic_model.py +++ b/deepmd/pt/model/atomic_model/linear_atomic_model.py @@ -96,7 +96,7 @@ def get_rcut(self) -> float: @torch.jit.export def get_type_map(self) -> List[str]: - self.type_map + return self.type_map def get_model_rcuts(self) -> List[float]: """Get the cut-off radius for each individual models.""" @@ -240,15 +240,11 @@ def remap_atype( ------- torch.Tensor """ - assert max(atype) < len( - new_map - ), "The input `atype` cannot be handled by the type_map." - idx_2_type = {k: new_map[k] for k in range(len(new_map))} + assert torch.max(atype) < len(new_map), "The input `atype` cannot be handled by the type_map." type_2_idx = {atp: idx for idx, atp in enumerate(ori_map)} # this maps the atype in the new map to the original map - mapping = {idx: type_2_idx[idx_2_type[idx]] for idx in range(len(new_map))} - updated_atype = atype.clone() - updated_atype.apply_(mapping.get) + mapping = torch.tensor([type_2_idx[new_map[idx]] for idx in range(len(new_map))]).to(atype.device) + updated_atype = mapping[atype.long()] return updated_atype def fitting_output_def(self) -> FittingOutputDef: diff --git a/source/tests/pt/model/test_linear_atomic_model.py b/source/tests/pt/model/test_linear_atomic_model.py index f168e1613c..e6fbbb0304 100644 --- a/source/tests/pt/model/test_linear_atomic_model.py +++ b/source/tests/pt/model/test_linear_atomic_model.py @@ -187,26 +187,25 @@ def test_jit(self): class TestRemmapMethod(unittest.TestCase): def test_invalid(self): - atype = torch.randint(2, 4, (2, 5)) + atype = torch.randint(2,4, (2,5), device=env.DEVICE) commonl = ["H"] - originl = ["Si", "H", "O", "S"] - with self.assertRaises(): - new_atype = remap_atype(atype, originl, commonl) - + originl = ["Si","H","O", "S"] + with self.assertRaises(AssertionError): + new_atype = DPZBLLinearAtomicModel.remap_atype(atype, originl, commonl) + def test_valid(self): - atype = torch.randint(0, 3, (4, 20)) - nl = ["H", "O", "S"] - ol = ["Si", "H", "O", "S"] - new_atype = remap_atype(atype, originl, commonl) - + atype = torch.randint(0,3, (4,20), device=env.DEVICE) + commonl = ["H", "O", "S"] + originl = ["Si","H","O", "S"] + new_atype = DPZBLLinearAtomicModel.remap_atype(atype, originl, commonl) def trans(atype, map): idx = atype.flatten().tolist() res = [] for i in idx: res.append(map[i]) return res - - assert trans(atype, nl) == trans(new_atype, ol) + + assert trans(atype,commonl) == trans(new_atype, originl) if __name__ == "__main__": From a30bc354e2f08c8d2e792eaef712e502576e3ded Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 5 Mar 2024 08:16:27 +0000 Subject: [PATCH 47/59] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../pt/model/atomic_model/linear_atomic_model.py | 8 ++++++-- source/tests/pt/model/test_linear_atomic_model.py | 15 ++++++++------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/deepmd/pt/model/atomic_model/linear_atomic_model.py b/deepmd/pt/model/atomic_model/linear_atomic_model.py index 446b88da46..a0c34bed6e 100644 --- a/deepmd/pt/model/atomic_model/linear_atomic_model.py +++ b/deepmd/pt/model/atomic_model/linear_atomic_model.py @@ -240,10 +240,14 @@ def remap_atype( ------- torch.Tensor """ - assert torch.max(atype) < len(new_map), "The input `atype` cannot be handled by the type_map." + assert torch.max(atype) < len( + new_map + ), "The input `atype` cannot be handled by the type_map." type_2_idx = {atp: idx for idx, atp in enumerate(ori_map)} # this maps the atype in the new map to the original map - mapping = torch.tensor([type_2_idx[new_map[idx]] for idx in range(len(new_map))]).to(atype.device) + mapping = torch.tensor( + [type_2_idx[new_map[idx]] for idx in range(len(new_map))] + ).to(atype.device) updated_atype = mapping[atype.long()] return updated_atype diff --git a/source/tests/pt/model/test_linear_atomic_model.py b/source/tests/pt/model/test_linear_atomic_model.py index e6fbbb0304..54128969b2 100644 --- a/source/tests/pt/model/test_linear_atomic_model.py +++ b/source/tests/pt/model/test_linear_atomic_model.py @@ -187,25 +187,26 @@ def test_jit(self): class TestRemmapMethod(unittest.TestCase): def test_invalid(self): - atype = torch.randint(2,4, (2,5), device=env.DEVICE) + atype = torch.randint(2, 4, (2, 5), device=env.DEVICE) commonl = ["H"] - originl = ["Si","H","O", "S"] + originl = ["Si", "H", "O", "S"] with self.assertRaises(AssertionError): new_atype = DPZBLLinearAtomicModel.remap_atype(atype, originl, commonl) - + def test_valid(self): - atype = torch.randint(0,3, (4,20), device=env.DEVICE) + atype = torch.randint(0, 3, (4, 20), device=env.DEVICE) commonl = ["H", "O", "S"] - originl = ["Si","H","O", "S"] + originl = ["Si", "H", "O", "S"] new_atype = DPZBLLinearAtomicModel.remap_atype(atype, originl, commonl) + def trans(atype, map): idx = atype.flatten().tolist() res = [] for i in idx: res.append(map[i]) return res - - assert trans(atype,commonl) == trans(new_atype, originl) + + assert trans(atype, commonl) == trans(new_atype, originl) if __name__ == "__main__": From d43644428c3f4d197b0f76313dd6e8ec4df800fb Mon Sep 17 00:00:00 2001 From: anyangml Date: Tue, 5 Mar 2024 08:18:58 +0000 Subject: [PATCH 48/59] fix: UTs --- deepmd/pt/model/atomic_model/linear_atomic_model.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/deepmd/pt/model/atomic_model/linear_atomic_model.py b/deepmd/pt/model/atomic_model/linear_atomic_model.py index a0c34bed6e..663cd0338a 100644 --- a/deepmd/pt/model/atomic_model/linear_atomic_model.py +++ b/deepmd/pt/model/atomic_model/linear_atomic_model.py @@ -245,9 +245,7 @@ def remap_atype( ), "The input `atype` cannot be handled by the type_map." type_2_idx = {atp: idx for idx, atp in enumerate(ori_map)} # this maps the atype in the new map to the original map - mapping = torch.tensor( - [type_2_idx[new_map[idx]] for idx in range(len(new_map))] - ).to(atype.device) + mapping = torch.tensor([type_2_idx[new_map[idx]] for idx in range(len(new_map))], device=atype.device) updated_atype = mapping[atype.long()] return updated_atype From ba643b90c72d9ea07abd7f55440637809c96c3eb Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 5 Mar 2024 08:22:05 +0000 Subject: [PATCH 49/59] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- deepmd/pt/model/atomic_model/linear_atomic_model.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/deepmd/pt/model/atomic_model/linear_atomic_model.py b/deepmd/pt/model/atomic_model/linear_atomic_model.py index 663cd0338a..88940fcbdc 100644 --- a/deepmd/pt/model/atomic_model/linear_atomic_model.py +++ b/deepmd/pt/model/atomic_model/linear_atomic_model.py @@ -245,7 +245,10 @@ def remap_atype( ), "The input `atype` cannot be handled by the type_map." type_2_idx = {atp: idx for idx, atp in enumerate(ori_map)} # this maps the atype in the new map to the original map - mapping = torch.tensor([type_2_idx[new_map[idx]] for idx in range(len(new_map))], device=atype.device) + mapping = torch.tensor( + [type_2_idx[new_map[idx]] for idx in range(len(new_map))], + device=atype.device, + ) updated_atype = mapping[atype.long()] return updated_atype From b60f03841c7290de92757c7bfd2455a069e8d9c6 Mon Sep 17 00:00:00 2001 From: anyangml Date: Tue, 5 Mar 2024 08:31:51 +0000 Subject: [PATCH 50/59] fix: update numpy --- .../atomic_model/linear_atomic_model.py | 57 +++++++++++++++---- .../pt/model/test_linear_atomic_model.py | 2 +- 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/deepmd/dpmodel/atomic_model/linear_atomic_model.py b/deepmd/dpmodel/atomic_model/linear_atomic_model.py index b1a32cdaa5..bdad3bc6eb 100644 --- a/deepmd/dpmodel/atomic_model/linear_atomic_model.py +++ b/deepmd/dpmodel/atomic_model/linear_atomic_model.py @@ -163,17 +163,21 @@ def forward_atomic( self.mixed_types_list, raw_nlists, self.get_model_sels() ) ] - ener_list = [ - model.forward_atomic( - extended_coord, - extended_atype, - nl, - mapping, - fparam, - aparam, - )["energy"] - for model, nl in zip(self.models, nlists_) - ] + ener_list = [] + + for i, model in enumerate(self.models): + ori_map = model.get_type_map() + updated_atype = self.remap_atype(extended_atype, ori_map, self.type_map) + ener_list.append( + model.forward_atomic( + extended_coord, + updated_atype, + nlists_[i], + mapping, + fparam, + aparam, + )["energy"] + ) self.weights = self._compute_weight(extended_coord, extended_atype, nlists_) self.atomic_bias = None if self.atomic_bias is not None: @@ -184,6 +188,37 @@ def forward_atomic( } # (nframes, nloc, 1) return fit_ret + @staticmethod + def remap_atype( + atype: np.ndarray, ori_map: List[str], new_map: List[str] + ) -> np.ndarray: + """ + This method is used to map the atype from the common type_map to the original type_map of + indivial AtomicModels. + + Parameters + ---------- + atype : np.ndarray + The atom type tensor being updated, shape of (nframes, natoms) + ori_map : List[str] + The original type map of an AtomicModel. + new_map : List[str] + The common type map of the DPZBLLinearAtomicModel, created by the `get_type_map` method, + must be a subset of the ori_map. + + Returns + ------- + np.ndarray + """ + assert np.max(atype) < len( + new_map + ), "The input `atype` cannot be handled by the type_map." + type_2_idx = {atp: idx for idx, atp in enumerate(ori_map)} + # this maps the atype in the new map to the original map + mapping = np.array([type_2_idx[new_map[idx]] for idx in range(len(new_map))]) + updated_atype = mapping[atype] + return updated_atype + def fitting_output_def(self) -> FittingOutputDef: return FittingOutputDef( [ diff --git a/source/tests/pt/model/test_linear_atomic_model.py b/source/tests/pt/model/test_linear_atomic_model.py index 54128969b2..656ff46d9e 100644 --- a/source/tests/pt/model/test_linear_atomic_model.py +++ b/source/tests/pt/model/test_linear_atomic_model.py @@ -70,7 +70,7 @@ def test_pairwise(self, mock_loadtxt): type_map = ["foo", "bar"] zbl_model = PairTabAtomicModel( - tab_file=file_path, rcut=0.3, sel=2, type_map=type_map + tab_file=file_path, rcut=0.3, sel=2, type_map=type_map[::-1] ) dp_model = DPAtomicModel(ds, ft, type_map=type_map).to(env.DEVICE) wgt_model = DPZBLLinearAtomicModel( From e5a905b589c8216673abcb1e14d92b13d4efdc30 Mon Sep 17 00:00:00 2001 From: anyangml Date: Tue, 5 Mar 2024 09:16:34 +0000 Subject: [PATCH 51/59] chore:skip test --- source/tests/pt/test_finetune.py | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/source/tests/pt/test_finetune.py b/source/tests/pt/test_finetune.py index 2aa4a7a310..06080cfd8c 100644 --- a/source/tests/pt/test_finetune.py +++ b/source/tests/pt/test_finetune.py @@ -32,6 +32,7 @@ from .model.test_permutation import ( model_dpa2, model_se_e2_a, + model_zbl, ) @@ -135,21 +136,20 @@ def setUp(self): def tearDown(self) -> None: FinetuneTest.tearDown(self) +@unittest.skip("change bias not implemented yet.") +class TestEnergyZBLModelSeA(unittest.TestCase, FinetuneTest): + def setUp(self): + self.data_file = [str(Path(__file__).parent / "water/data/data_0")] + self.data = DeepmdDataSystem( + self.data_file, + batch_size=1, + test_size=1, + ) + self.data.add("energy", ndof=1, atomic=False, must=True, high_prec=True) + self.model_config = model_zbl -## Disabled for now. -# class TestEnergyZBLModelSeA(unittest.TestCase, FinetuneTest): -# def setUp(self): -# self.data_file = [str(Path(__file__).parent / "water/data/data_0")] -# self.data = DeepmdDataSystem( -# self.data_file, -# batch_size=1, -# test_size=1, -# ) -# self.data.add("energy", ndof=1, atomic=False, must=True, high_prec=True) -# self.model_config = model_zbl - -# def tearDown(self) -> None: -# FinetuneTest.tearDown(self) + def tearDown(self) -> None: + FinetuneTest.tearDown(self) class TestEnergyModelDPA2(unittest.TestCase, FinetuneTest): From 25f1ff89de163d1e06ebd98ea16dcadeebf2a954 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 5 Mar 2024 09:17:22 +0000 Subject: [PATCH 52/59] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- source/tests/pt/test_finetune.py | 1 + 1 file changed, 1 insertion(+) diff --git a/source/tests/pt/test_finetune.py b/source/tests/pt/test_finetune.py index 06080cfd8c..d21a44acc7 100644 --- a/source/tests/pt/test_finetune.py +++ b/source/tests/pt/test_finetune.py @@ -136,6 +136,7 @@ def setUp(self): def tearDown(self) -> None: FinetuneTest.tearDown(self) + @unittest.skip("change bias not implemented yet.") class TestEnergyZBLModelSeA(unittest.TestCase, FinetuneTest): def setUp(self): From 85baa596b088e657d680dc0d5734b5010f1cf0f4 Mon Sep 17 00:00:00 2001 From: Anyang Peng <137014849+anyangml@users.noreply.github.com> Date: Tue, 5 Mar 2024 18:19:17 +0800 Subject: [PATCH 53/59] chore: rename class --- deepmd/dpmodel/atomic_model/__init__.py | 8 ++++---- .../dpmodel/atomic_model/linear_atomic_model.py | 12 ++++++------ deepmd/pt/model/atomic_model/__init__.py | 8 ++++---- .../pt/model/atomic_model/linear_atomic_model.py | 12 ++++++------ deepmd/pt/model/model/dp_zbl_model.py | 4 ++-- .../common/dpmodel/test_linear_atomic_model.py | 8 ++++---- .../tests/pt/model/test_linear_atomic_model.py | 16 ++++++++-------- 7 files changed, 34 insertions(+), 34 deletions(-) diff --git a/deepmd/dpmodel/atomic_model/__init__.py b/deepmd/dpmodel/atomic_model/__init__.py index 2cd20f54c1..e51ca0a65e 100644 --- a/deepmd/dpmodel/atomic_model/__init__.py +++ b/deepmd/dpmodel/atomic_model/__init__.py @@ -22,8 +22,8 @@ DPAtomicModel, ) from .linear_atomic_model import ( - DPZBLLinearAtomicModel, - LinearAtomicModel, + DPZBLLinearEnergyAtomicModel, + LinearEnergyAtomicModel, ) from .make_base_atomic_model import ( make_base_atomic_model, @@ -37,6 +37,6 @@ "BaseAtomicModel", "DPAtomicModel", "PairTabAtomicModel", - "LinearAtomicModel", - "DPZBLLinearAtomicModel", + "LinearEnergyAtomicModel", + "DPZBLLinearEnergyAtomicModel", ] diff --git a/deepmd/dpmodel/atomic_model/linear_atomic_model.py b/deepmd/dpmodel/atomic_model/linear_atomic_model.py index bdad3bc6eb..2ea3ca4b47 100644 --- a/deepmd/dpmodel/atomic_model/linear_atomic_model.py +++ b/deepmd/dpmodel/atomic_model/linear_atomic_model.py @@ -38,7 +38,7 @@ ) -class LinearAtomicModel(BaseAtomicModel): +class LinearEnergyAtomicModel(BaseAtomicModel): """Linear model make linear combinations of several existing models. Parameters @@ -203,7 +203,7 @@ def remap_atype( ori_map : List[str] The original type map of an AtomicModel. new_map : List[str] - The common type map of the DPZBLLinearAtomicModel, created by the `get_type_map` method, + The common type map of the DPZBLLinearEnergyAtomicModel, created by the `get_type_map` method, must be a subset of the ori_map. Returns @@ -296,7 +296,7 @@ def is_aparam_nall(self) -> bool: return False -class DPZBLLinearAtomicModel(LinearAtomicModel): +class DPZBLLinearEnergyAtomicModel(LinearEnergyAtomicModel): """Model linearly combine a list of AtomicModels. Parameters @@ -343,7 +343,7 @@ def serialize(self) -> dict: "@class": "Model", "type": "zbl", "@version": 1, - "models": LinearAtomicModel.serialize( + "models": LinearEnergyAtomicModel.serialize( [self.dp_model, self.zbl_model], self.type_map ), "sw_rmin": self.sw_rmin, @@ -354,7 +354,7 @@ def serialize(self) -> dict: return dd @classmethod - def deserialize(cls, data) -> "DPZBLLinearAtomicModel": + def deserialize(cls, data) -> "DPZBLLinearEnergyAtomicModel": data = copy.deepcopy(data) check_version_compatibility(data.pop("@version", 1), 1, 1) data.pop("@class") @@ -363,7 +363,7 @@ def deserialize(cls, data) -> "DPZBLLinearAtomicModel": sw_rmax = data.pop("sw_rmax") smin_alpha = data.pop("smin_alpha") - ([dp_model, zbl_model], type_map) = LinearAtomicModel.deserialize( + ([dp_model, zbl_model], type_map) = LinearEnergyAtomicModel.deserialize( data.pop("models") ) diff --git a/deepmd/pt/model/atomic_model/__init__.py b/deepmd/pt/model/atomic_model/__init__.py index 75c1ce3c2e..a747f28556 100644 --- a/deepmd/pt/model/atomic_model/__init__.py +++ b/deepmd/pt/model/atomic_model/__init__.py @@ -21,8 +21,8 @@ DPAtomicModel, ) from .linear_atomic_model import ( - DPZBLLinearAtomicModel, - LinearAtomicModel, + DPZBLLinearEnergyAtomicModel, + LinearEnergyAtomicModel, ) from .pairtab_atomic_model import ( PairTabAtomicModel, @@ -32,6 +32,6 @@ "BaseAtomicModel", "DPAtomicModel", "PairTabAtomicModel", - "LinearAtomicModel", - "DPZBLLinearAtomicModel", + "LinearEnergyAtomicModel", + "DPZBLLinearEnergyAtomicModel", ] diff --git a/deepmd/pt/model/atomic_model/linear_atomic_model.py b/deepmd/pt/model/atomic_model/linear_atomic_model.py index 88940fcbdc..82c5514111 100644 --- a/deepmd/pt/model/atomic_model/linear_atomic_model.py +++ b/deepmd/pt/model/atomic_model/linear_atomic_model.py @@ -43,7 +43,7 @@ ) -class LinearAtomicModel(torch.nn.Module, BaseAtomicModel): +class LinearEnergyAtomicModel(torch.nn.Module, BaseAtomicModel): """Linear model make linear combinations of several existing models. Parameters @@ -233,7 +233,7 @@ def remap_atype( ori_map : List[str] The original type map of an AtomicModel. new_map : List[str] - The common type map of the DPZBLLinearAtomicModel, created by the `get_type_map` method, + The common type map of the DPZBLLinearEnergyAtomicModel, created by the `get_type_map` method, must be a subset of the ori_map. Returns @@ -336,7 +336,7 @@ def is_aparam_nall(self) -> bool: return False -class DPZBLLinearAtomicModel(LinearAtomicModel): +class DPZBLLinearEnergyAtomicModel(LinearEnergyAtomicModel): """Model linearly combine a list of AtomicModels. Parameters @@ -414,7 +414,7 @@ def serialize(self) -> dict: "@class": "Model", "@version": 1, "type": "zbl", - "models": LinearAtomicModel.serialize( + "models": LinearEnergyAtomicModel.serialize( [self.dp_model, self.zbl_model], self.type_map ), "sw_rmin": self.sw_rmin, @@ -425,14 +425,14 @@ def serialize(self) -> dict: return dd @classmethod - def deserialize(cls, data) -> "DPZBLLinearAtomicModel": + def deserialize(cls, data) -> "DPZBLLinearEnergyAtomicModel": data = copy.deepcopy(data) check_version_compatibility(data.pop("@version", 1), 1, 1) sw_rmin = data.pop("sw_rmin") sw_rmax = data.pop("sw_rmax") smin_alpha = data.pop("smin_alpha") - [dp_model, zbl_model], type_map = LinearAtomicModel.deserialize( + [dp_model, zbl_model], type_map = LinearEnergyAtomicModel.deserialize( data.pop("models") ) diff --git a/deepmd/pt/model/model/dp_zbl_model.py b/deepmd/pt/model/model/dp_zbl_model.py index dcf1c36e83..cacf59c16c 100644 --- a/deepmd/pt/model/model/dp_zbl_model.py +++ b/deepmd/pt/model/model/dp_zbl_model.py @@ -10,7 +10,7 @@ DPModel, ) from deepmd.pt.model.atomic_model import ( - DPZBLLinearAtomicModel, + DPZBLLinearEnergyAtomicModel, ) from deepmd.pt.model.model.model import ( BaseModel, @@ -20,7 +20,7 @@ make_model, ) -DPZBLModel_ = make_model(DPZBLLinearAtomicModel) +DPZBLModel_ = make_model(DPZBLLinearEnergyAtomicModel) @BaseModel.register("zbl") diff --git a/source/tests/common/dpmodel/test_linear_atomic_model.py b/source/tests/common/dpmodel/test_linear_atomic_model.py index aa56feb3e5..56a0a73683 100644 --- a/source/tests/common/dpmodel/test_linear_atomic_model.py +++ b/source/tests/common/dpmodel/test_linear_atomic_model.py @@ -10,7 +10,7 @@ DPAtomicModel, ) from deepmd.dpmodel.atomic_model.linear_atomic_model import ( - DPZBLLinearAtomicModel, + DPZBLLinearEnergyAtomicModel, ) from deepmd.dpmodel.atomic_model.pairtab_atomic_model import ( PairTabAtomicModel, @@ -58,7 +58,7 @@ def test_pairwise(self, mock_loadtxt): ) dp_model = DPAtomicModel(ds, ft, type_map=type_map) - wgt_model = DPZBLLinearAtomicModel( + wgt_model = DPZBLLinearEnergyAtomicModel( dp_model, zbl_model, sw_rmin=0.1, @@ -151,14 +151,14 @@ def setUp(self, mock_loadtxt): zbl_model = PairTabAtomicModel( file_path, self.rcut, sum(self.sel), type_map=type_map ) - self.md0 = DPZBLLinearAtomicModel( + self.md0 = DPZBLLinearEnergyAtomicModel( dp_model, zbl_model, sw_rmin=0.1, sw_rmax=0.25, type_map=type_map, ) - self.md1 = DPZBLLinearAtomicModel.deserialize(self.md0.serialize()) + self.md1 = DPZBLLinearEnergyAtomicModel.deserialize(self.md0.serialize()) def test_self_consistency(self): ret0 = self.md0.forward_atomic(self.coord_ext, self.atype_ext, self.nlist) diff --git a/source/tests/pt/model/test_linear_atomic_model.py b/source/tests/pt/model/test_linear_atomic_model.py index 656ff46d9e..4804258260 100644 --- a/source/tests/pt/model/test_linear_atomic_model.py +++ b/source/tests/pt/model/test_linear_atomic_model.py @@ -8,11 +8,11 @@ import torch from deepmd.dpmodel.atomic_model import ( - DPZBLLinearAtomicModel as DPDPZBLLinearAtomicModel, + DPZBLLinearEnergyAtomicModel as DPDPZBLLinearEnergyAtomicModel, ) from deepmd.pt.model.atomic_model import ( DPAtomicModel, - DPZBLLinearAtomicModel, + DPZBLLinearEnergyAtomicModel, PairTabAtomicModel, ) from deepmd.pt.model.descriptor.se_a import ( @@ -73,7 +73,7 @@ def test_pairwise(self, mock_loadtxt): tab_file=file_path, rcut=0.3, sel=2, type_map=type_map[::-1] ) dp_model = DPAtomicModel(ds, ft, type_map=type_map).to(env.DEVICE) - wgt_model = DPZBLLinearAtomicModel( + wgt_model = DPZBLLinearEnergyAtomicModel( dp_model, zbl_model, sw_rmin=0.1, @@ -145,17 +145,17 @@ def setUp(self, mock_loadtxt): zbl_model = PairTabAtomicModel( file_path, self.rcut, sum(self.sel), type_map=type_map ) - self.md0 = DPZBLLinearAtomicModel( + self.md0 = DPZBLLinearEnergyAtomicModel( dp_model, zbl_model, sw_rmin=0.1, sw_rmax=0.25, type_map=type_map, ).to(env.DEVICE) - self.md1 = DPZBLLinearAtomicModel.deserialize(self.md0.serialize()).to( + self.md1 = DPZBLLinearEnergyAtomicModel.deserialize(self.md0.serialize()).to( env.DEVICE ) - self.md2 = DPDPZBLLinearAtomicModel.deserialize(self.md0.serialize()) + self.md2 = DPDPZBLLinearEnergyAtomicModel.deserialize(self.md0.serialize()) self.md3 = DPZBLModel( dp_model, zbl_model, sw_rmin=0.1, sw_rmax=0.25, type_map=type_map ) @@ -191,13 +191,13 @@ def test_invalid(self): commonl = ["H"] originl = ["Si", "H", "O", "S"] with self.assertRaises(AssertionError): - new_atype = DPZBLLinearAtomicModel.remap_atype(atype, originl, commonl) + new_atype = DPZBLLinearEnergyAtomicModel.remap_atype(atype, originl, commonl) def test_valid(self): atype = torch.randint(0, 3, (4, 20), device=env.DEVICE) commonl = ["H", "O", "S"] originl = ["Si", "H", "O", "S"] - new_atype = DPZBLLinearAtomicModel.remap_atype(atype, originl, commonl) + new_atype = DPZBLLinearEnergyAtomicModel.remap_atype(atype, originl, commonl) def trans(atype, map): idx = atype.flatten().tolist() From a29541c01688d38a540f993a630c98215a2cb766 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 5 Mar 2024 10:19:48 +0000 Subject: [PATCH 54/59] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- source/tests/pt/model/test_linear_atomic_model.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/source/tests/pt/model/test_linear_atomic_model.py b/source/tests/pt/model/test_linear_atomic_model.py index 4804258260..d18201a356 100644 --- a/source/tests/pt/model/test_linear_atomic_model.py +++ b/source/tests/pt/model/test_linear_atomic_model.py @@ -191,7 +191,9 @@ def test_invalid(self): commonl = ["H"] originl = ["Si", "H", "O", "S"] with self.assertRaises(AssertionError): - new_atype = DPZBLLinearEnergyAtomicModel.remap_atype(atype, originl, commonl) + new_atype = DPZBLLinearEnergyAtomicModel.remap_atype( + atype, originl, commonl + ) def test_valid(self): atype = torch.randint(0, 3, (4, 20), device=env.DEVICE) From 18ec6a525e3f5aa5a44732726752547d2a399567 Mon Sep 17 00:00:00 2001 From: Anyang Peng <137014849+anyangml@users.noreply.github.com> Date: Wed, 6 Mar 2024 09:32:34 +0800 Subject: [PATCH 55/59] fix: add TODO --- deepmd/pt/model/atomic_model/linear_atomic_model.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/deepmd/pt/model/atomic_model/linear_atomic_model.py b/deepmd/pt/model/atomic_model/linear_atomic_model.py index 82c5514111..b5bd2b100b 100644 --- a/deepmd/pt/model/atomic_model/linear_atomic_model.py +++ b/deepmd/pt/model/atomic_model/linear_atomic_model.py @@ -96,6 +96,7 @@ def get_rcut(self) -> float: @torch.jit.export def get_type_map(self) -> List[str]: + """Get the type map.""" return self.type_map def get_model_rcuts(self) -> List[float]: @@ -204,6 +205,7 @@ def forward_atomic( atype = extended_atype[:, :nloc] for idx, model in enumerate(self.models): + #TODO: provide interfaces for atomic models to access bias_atom_e if isinstance(model, DPAtomicModel): bias_atom_e = model.fitting_net.bias_atom_e elif isinstance(model, PairTabAtomicModel): From d62bacbd1645487eb73b4ffef5690c41d186439d Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 6 Mar 2024 01:33:36 +0000 Subject: [PATCH 56/59] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- deepmd/pt/model/atomic_model/linear_atomic_model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deepmd/pt/model/atomic_model/linear_atomic_model.py b/deepmd/pt/model/atomic_model/linear_atomic_model.py index b5bd2b100b..f905eab35d 100644 --- a/deepmd/pt/model/atomic_model/linear_atomic_model.py +++ b/deepmd/pt/model/atomic_model/linear_atomic_model.py @@ -205,7 +205,7 @@ def forward_atomic( atype = extended_atype[:, :nloc] for idx, model in enumerate(self.models): - #TODO: provide interfaces for atomic models to access bias_atom_e + # TODO: provide interfaces for atomic models to access bias_atom_e if isinstance(model, DPAtomicModel): bias_atom_e = model.fitting_net.bias_atom_e elif isinstance(model, PairTabAtomicModel): From c012b3faa060aa07101d7eb8a46e2dcc4a9e7a08 Mon Sep 17 00:00:00 2001 From: anyangml Date: Wed, 6 Mar 2024 06:46:23 +0000 Subject: [PATCH 57/59] chore: refactor remap --- .../atomic_model/linear_atomic_model.py | 19 +++++-------- .../model/atomic_model/linear_atomic_model.py | 27 ++++++++----------- .../pt/model/test_linear_atomic_model.py | 11 ++------ 3 files changed, 20 insertions(+), 37 deletions(-) diff --git a/deepmd/dpmodel/atomic_model/linear_atomic_model.py b/deepmd/dpmodel/atomic_model/linear_atomic_model.py index 2ea3ca4b47..63332f5b1c 100644 --- a/deepmd/dpmodel/atomic_model/linear_atomic_model.py +++ b/deepmd/dpmodel/atomic_model/linear_atomic_model.py @@ -59,14 +59,16 @@ def __init__( self.models = models sub_model_type_maps = [md.get_type_map() for md in models] err_msg = [] + self.mapping_list = [] common_type_map = set(type_map) + self.type_map = type_map for tpmp in sub_model_type_maps: if not common_type_map.issubset(set(tpmp)): err_msg.append( f"type_map {tpmp} is not a subset of type_map {type_map}" ) + self.mapping_list.append(self.remap_atype(tpmp, self.type_map)) assert len(err_msg) == 0, "\n".join(err_msg) - self.type_map = type_map self.mixed_types_list = [model.mixed_types() for model in self.models] super().__init__(**kwargs) @@ -166,12 +168,11 @@ def forward_atomic( ener_list = [] for i, model in enumerate(self.models): - ori_map = model.get_type_map() - updated_atype = self.remap_atype(extended_atype, ori_map, self.type_map) + mapping = self.mapping_list[i] ener_list.append( model.forward_atomic( extended_coord, - updated_atype, + mapping[extended_atype], nlists_[i], mapping, fparam, @@ -190,7 +191,7 @@ def forward_atomic( @staticmethod def remap_atype( - atype: np.ndarray, ori_map: List[str], new_map: List[str] + ori_map: List[str], new_map: List[str] ) -> np.ndarray: """ This method is used to map the atype from the common type_map to the original type_map of @@ -198,8 +199,6 @@ def remap_atype( Parameters ---------- - atype : np.ndarray - The atom type tensor being updated, shape of (nframes, natoms) ori_map : List[str] The original type map of an AtomicModel. new_map : List[str] @@ -210,14 +209,10 @@ def remap_atype( ------- np.ndarray """ - assert np.max(atype) < len( - new_map - ), "The input `atype` cannot be handled by the type_map." type_2_idx = {atp: idx for idx, atp in enumerate(ori_map)} # this maps the atype in the new map to the original map mapping = np.array([type_2_idx[new_map[idx]] for idx in range(len(new_map))]) - updated_atype = mapping[atype] - return updated_atype + return mapping def fitting_output_def(self) -> FittingOutputDef: return FittingOutputDef( diff --git a/deepmd/pt/model/atomic_model/linear_atomic_model.py b/deepmd/pt/model/atomic_model/linear_atomic_model.py index f905eab35d..16ab925a36 100644 --- a/deepmd/pt/model/atomic_model/linear_atomic_model.py +++ b/deepmd/pt/model/atomic_model/linear_atomic_model.py @@ -65,14 +65,17 @@ def __init__( self.models = torch.nn.ModuleList(models) sub_model_type_maps = [md.get_type_map() for md in models] err_msg = [] + self.mapping_list = [] common_type_map = set(type_map) + self.type_map = type_map for tpmp in sub_model_type_maps: if not common_type_map.issubset(set(tpmp)): err_msg.append( f"type_map {tpmp} is not a subset of type_map {type_map}" ) + self.mapping_list.append(self.remap_atype(tpmp, self.type_map)) assert len(err_msg) == 0, "\n".join(err_msg) - self.type_map = type_map + self.atomic_bias = None self.mixed_types_list = [model.mixed_types() for model in self.models] BaseAtomicModel.__init__(self, **kwargs) @@ -188,12 +191,11 @@ def forward_atomic( ener_list = [] for i, model in enumerate(self.models): - ori_map = model.get_type_map() - updated_atype = self.remap_atype(extended_atype, ori_map, self.type_map) + mapping = self.mapping_list[i] if mapping is None else mapping ener_list.append( model.forward_atomic( extended_coord, - updated_atype, + mapping[extended_atype], nlists_[i], mapping, fparam, @@ -221,17 +223,14 @@ def forward_atomic( return fit_ret @staticmethod - def remap_atype( - atype: torch.Tensor, ori_map: List[str], new_map: List[str] + def remap_atype(ori_map: List[str], new_map: List[str] ) -> torch.Tensor: """ This method is used to map the atype from the common type_map to the original type_map of - indivial AtomicModels. + indivial AtomicModels. It creates a index mapping for the conversion. Parameters ---------- - atype : torch.Tensor - The atom type tensor being updated, shape of (nframes, natoms) ori_map : List[str] The original type map of an AtomicModel. new_map : List[str] @@ -242,17 +241,13 @@ def remap_atype( ------- torch.Tensor """ - assert torch.max(atype) < len( - new_map - ), "The input `atype` cannot be handled by the type_map." + type_2_idx = {atp: idx for idx, atp in enumerate(ori_map)} # this maps the atype in the new map to the original map mapping = torch.tensor( [type_2_idx[new_map[idx]] for idx in range(len(new_map))], - device=atype.device, - ) - updated_atype = mapping[atype.long()] - return updated_atype + device= env.DEVICE) + return mapping def fitting_output_def(self) -> FittingOutputDef: return FittingOutputDef( diff --git a/source/tests/pt/model/test_linear_atomic_model.py b/source/tests/pt/model/test_linear_atomic_model.py index 98c84510c7..1b87157f73 100644 --- a/source/tests/pt/model/test_linear_atomic_model.py +++ b/source/tests/pt/model/test_linear_atomic_model.py @@ -186,20 +186,13 @@ def test_jit(self): class TestRemmapMethod(unittest.TestCase): - def test_invalid(self): - atype = torch.randint(2, 4, (2, 5), device=env.DEVICE) - commonl = ["H"] - originl = ["Si", "H", "O", "S"] - with self.assertRaises(AssertionError): - new_atype = DPZBLLinearEnergyAtomicModel.remap_atype( - atype, originl, commonl - ) def test_valid(self): atype = torch.randint(0, 3, (4, 20), device=env.DEVICE) commonl = ["H", "O", "S"] originl = ["Si", "H", "O", "S"] - new_atype = DPZBLLinearEnergyAtomicModel.remap_atype(atype, originl, commonl) + mapping = DPZBLLinearEnergyAtomicModel.remap_atype(originl, commonl) + new_atype = mapping[atype] def trans(atype, map): idx = atype.flatten().tolist() From a0d7cafb91368d40ed7c30e445d2c2d7405e1879 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 6 Mar 2024 06:46:52 +0000 Subject: [PATCH 58/59] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- deepmd/dpmodel/atomic_model/linear_atomic_model.py | 4 +--- deepmd/pt/model/atomic_model/linear_atomic_model.py | 10 ++++------ source/tests/pt/model/test_linear_atomic_model.py | 1 - 3 files changed, 5 insertions(+), 10 deletions(-) diff --git a/deepmd/dpmodel/atomic_model/linear_atomic_model.py b/deepmd/dpmodel/atomic_model/linear_atomic_model.py index 63332f5b1c..ac2a73a381 100644 --- a/deepmd/dpmodel/atomic_model/linear_atomic_model.py +++ b/deepmd/dpmodel/atomic_model/linear_atomic_model.py @@ -190,9 +190,7 @@ def forward_atomic( return fit_ret @staticmethod - def remap_atype( - ori_map: List[str], new_map: List[str] - ) -> np.ndarray: + def remap_atype(ori_map: List[str], new_map: List[str]) -> np.ndarray: """ This method is used to map the atype from the common type_map to the original type_map of indivial AtomicModels. diff --git a/deepmd/pt/model/atomic_model/linear_atomic_model.py b/deepmd/pt/model/atomic_model/linear_atomic_model.py index 16ab925a36..3da4d4479b 100644 --- a/deepmd/pt/model/atomic_model/linear_atomic_model.py +++ b/deepmd/pt/model/atomic_model/linear_atomic_model.py @@ -75,7 +75,7 @@ def __init__( ) self.mapping_list.append(self.remap_atype(tpmp, self.type_map)) assert len(err_msg) == 0, "\n".join(err_msg) - + self.atomic_bias = None self.mixed_types_list = [model.mixed_types() for model in self.models] BaseAtomicModel.__init__(self, **kwargs) @@ -223,8 +223,7 @@ def forward_atomic( return fit_ret @staticmethod - def remap_atype(ori_map: List[str], new_map: List[str] - ) -> torch.Tensor: + def remap_atype(ori_map: List[str], new_map: List[str]) -> torch.Tensor: """ This method is used to map the atype from the common type_map to the original type_map of indivial AtomicModels. It creates a index mapping for the conversion. @@ -241,12 +240,11 @@ def remap_atype(ori_map: List[str], new_map: List[str] ------- torch.Tensor """ - type_2_idx = {atp: idx for idx, atp in enumerate(ori_map)} # this maps the atype in the new map to the original map mapping = torch.tensor( - [type_2_idx[new_map[idx]] for idx in range(len(new_map))], - device= env.DEVICE) + [type_2_idx[new_map[idx]] for idx in range(len(new_map))], device=env.DEVICE + ) return mapping def fitting_output_def(self) -> FittingOutputDef: diff --git a/source/tests/pt/model/test_linear_atomic_model.py b/source/tests/pt/model/test_linear_atomic_model.py index 1b87157f73..adc682a41f 100644 --- a/source/tests/pt/model/test_linear_atomic_model.py +++ b/source/tests/pt/model/test_linear_atomic_model.py @@ -186,7 +186,6 @@ def test_jit(self): class TestRemmapMethod(unittest.TestCase): - def test_valid(self): atype = torch.randint(0, 3, (4, 20), device=env.DEVICE) commonl = ["H", "O", "S"] From edd9a10b1ec3165c3c351d41fecfa84526fca14c Mon Sep 17 00:00:00 2001 From: anyangml Date: Wed, 6 Mar 2024 07:20:44 +0000 Subject: [PATCH 59/59] fix: UTs --- deepmd/pt/model/atomic_model/linear_atomic_model.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/deepmd/pt/model/atomic_model/linear_atomic_model.py b/deepmd/pt/model/atomic_model/linear_atomic_model.py index 3da4d4479b..5e1a80087e 100644 --- a/deepmd/pt/model/atomic_model/linear_atomic_model.py +++ b/deepmd/pt/model/atomic_model/linear_atomic_model.py @@ -191,7 +191,7 @@ def forward_atomic( ener_list = [] for i, model in enumerate(self.models): - mapping = self.mapping_list[i] if mapping is None else mapping + mapping = self.mapping_list[i] ener_list.append( model.forward_atomic( extended_coord,