-
Notifications
You must be signed in to change notification settings - Fork 523
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Feat (pt): Expose Linear Ener Model (#4194)
<!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Introduced two new JSON configuration files for linear energy calculations in water simulations. - Launched the `LinearEnergyModel` class for advanced energy and force calculations. - Added a parameter for customizable model weighting in the linear energy model. - Expanded test suite with new test classes for validating linear energy models. - Added new model configurations and test classes to enhance testing capabilities. - **Bug Fixes** - Corrected input handling in the deserialization method for version compatibility. - Adjusted numerical values in data files for accurate testing. <!-- end of auto-generated comment: release notes by coderabbit.ai --> --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
- Loading branch information
1 parent
3939786
commit 61f1681
Showing
12 changed files
with
622 additions
and
12 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
# SPDX-License-Identifier: LGPL-3.0-or-later | ||
from copy import ( | ||
deepcopy, | ||
) | ||
from typing import ( | ||
Optional, | ||
) | ||
|
||
import torch | ||
|
||
from deepmd.pt.model.atomic_model import ( | ||
LinearEnergyAtomicModel, | ||
) | ||
from deepmd.pt.model.model.model import ( | ||
BaseModel, | ||
) | ||
from deepmd.utils.data_system import ( | ||
DeepmdDataSystem, | ||
) | ||
|
||
from .dp_model import ( | ||
DPModelCommon, | ||
) | ||
from .make_model import ( | ||
make_model, | ||
) | ||
|
||
DPLinearModel_ = make_model(LinearEnergyAtomicModel) | ||
|
||
|
||
@BaseModel.register("linear_ener") | ||
class LinearEnergyModel(DPLinearModel_): | ||
model_type = "ener" | ||
|
||
def __init__( | ||
self, | ||
*args, | ||
**kwargs, | ||
): | ||
super().__init__(*args, **kwargs) | ||
|
||
def translated_output_def(self): | ||
out_def_data = self.model_output_def().get_data() | ||
output_def = { | ||
"atom_energy": deepcopy(out_def_data["energy"]), | ||
"energy": deepcopy(out_def_data["energy_redu"]), | ||
} | ||
if self.do_grad_r("energy"): | ||
output_def["force"] = deepcopy(out_def_data["energy_derv_r"]) | ||
output_def["force"].squeeze(-2) | ||
if self.do_grad_c("energy"): | ||
output_def["virial"] = deepcopy(out_def_data["energy_derv_c_redu"]) | ||
output_def["virial"].squeeze(-2) | ||
output_def["atom_virial"] = deepcopy(out_def_data["energy_derv_c"]) | ||
output_def["atom_virial"].squeeze(-3) | ||
if "mask" in out_def_data: | ||
output_def["mask"] = deepcopy(out_def_data["mask"]) | ||
return output_def | ||
|
||
def forward( | ||
self, | ||
coord, | ||
atype, | ||
box: Optional[torch.Tensor] = None, | ||
fparam: Optional[torch.Tensor] = None, | ||
aparam: Optional[torch.Tensor] = None, | ||
do_atomic_virial: bool = False, | ||
) -> dict[str, torch.Tensor]: | ||
model_ret = self.forward_common( | ||
coord, | ||
atype, | ||
box, | ||
fparam=fparam, | ||
aparam=aparam, | ||
do_atomic_virial=do_atomic_virial, | ||
) | ||
|
||
model_predict = {} | ||
model_predict["atom_energy"] = model_ret["energy"] | ||
model_predict["energy"] = model_ret["energy_redu"] | ||
if self.do_grad_r("energy"): | ||
model_predict["force"] = model_ret["energy_derv_r"].squeeze(-2) | ||
if self.do_grad_c("energy"): | ||
model_predict["virial"] = model_ret["energy_derv_c_redu"].squeeze(-2) | ||
if do_atomic_virial: | ||
model_predict["atom_virial"] = model_ret["energy_derv_c"].squeeze(-3) | ||
else: | ||
model_predict["force"] = model_ret["dforce"] | ||
if "mask" in model_ret: | ||
model_predict["mask"] = model_ret["mask"] | ||
return model_predict | ||
|
||
@torch.jit.export | ||
def forward_lower( | ||
self, | ||
extended_coord, | ||
extended_atype, | ||
nlist, | ||
mapping: Optional[torch.Tensor] = None, | ||
fparam: Optional[torch.Tensor] = None, | ||
aparam: Optional[torch.Tensor] = None, | ||
do_atomic_virial: bool = False, | ||
): | ||
model_ret = self.forward_common_lower( | ||
extended_coord, | ||
extended_atype, | ||
nlist, | ||
mapping=mapping, | ||
fparam=fparam, | ||
aparam=aparam, | ||
do_atomic_virial=do_atomic_virial, | ||
extra_nlist_sort=self.need_sorted_nlist_for_lower(), | ||
) | ||
|
||
model_predict = {} | ||
model_predict["atom_energy"] = model_ret["energy"] | ||
model_predict["energy"] = model_ret["energy_redu"] | ||
if self.do_grad_r("energy"): | ||
model_predict["extended_force"] = model_ret["energy_derv_r"].squeeze(-2) | ||
if self.do_grad_c("energy"): | ||
model_predict["virial"] = model_ret["energy_derv_c_redu"].squeeze(-2) | ||
if do_atomic_virial: | ||
model_predict["extended_virial"] = model_ret["energy_derv_c"].squeeze( | ||
-3 | ||
) | ||
else: | ||
assert model_ret["dforce"] is not None | ||
model_predict["dforce"] = model_ret["dforce"] | ||
return model_predict | ||
|
||
@classmethod | ||
def update_sel( | ||
cls, | ||
train_data: DeepmdDataSystem, | ||
type_map: Optional[list[str]], | ||
local_jdata: dict, | ||
) -> tuple[dict, Optional[float]]: | ||
"""Update the selection and perform neighbor statistics. | ||
Parameters | ||
---------- | ||
train_data : DeepmdDataSystem | ||
data used to do neighbor statictics | ||
type_map : list[str], optional | ||
The name of each type of atoms | ||
local_jdata : dict | ||
The local data refer to the current class | ||
Returns | ||
------- | ||
dict | ||
The updated local data | ||
float | ||
The minimum distance between two atoms | ||
""" | ||
local_jdata_cpy = local_jdata.copy() | ||
type_map = local_jdata_cpy["type_map"] | ||
min_nbor_dist = None | ||
for idx, sub_model in enumerate(local_jdata_cpy["models"]): | ||
if "tab_file" not in sub_model: | ||
sub_model, temp_min = DPModelCommon.update_sel( | ||
train_data, type_map, local_jdata["models"][idx] | ||
) | ||
if min_nbor_dist is None or temp_min <= min_nbor_dist: | ||
min_nbor_dist = temp_min | ||
return local_jdata_cpy, min_nbor_dist |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.