Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support DPSpin for AtomicModel #3301

Merged
merged 69 commits into from
Mar 7, 2024
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
69 commits
Select commit Hold shift + click to select a range
c19f829
Support DPSpin for AtomicModel
iProzd Feb 19, 2024
cda2e60
Merge branch 'devel' into spin_rf
iProzd Feb 19, 2024
b740b2d
Improve the model inherit
iProzd Feb 20, 2024
85f8c12
delete abstractclassmethod
iProzd Feb 20, 2024
feb9907
resolve conversations
iProzd Feb 20, 2024
a8a6609
Merge branch 'devel' into spin_rf
iProzd Feb 20, 2024
cd23522
fix QL
iProzd Feb 21, 2024
3f4b46b
Merge branch 'devel' into spin_rf
iProzd Feb 21, 2024
5841e59
fix uts
iProzd Feb 21, 2024
96426c3
Merge branch 'devel' into spin_rf
iProzd Feb 21, 2024
c7b6c42
fix uts
iProzd Feb 21, 2024
2915121
reformat spin model
iProzd Feb 22, 2024
b4b0289
Merge branch 'devel' into spin_rf
iProzd Feb 22, 2024
65d6162
fix cuda error
iProzd Feb 22, 2024
07e3fca
Add uts and reformat SpinModel
iProzd Feb 25, 2024
2c44876
Merge branch 'devel' into spin_rf
iProzd Feb 25, 2024
412e98e
Update test_autodiff.py
iProzd Feb 25, 2024
6c8e57f
Merge branch 'spin_rf' of https://github.com/iProzd/deepmd-kit into s…
iProzd Feb 25, 2024
6179824
Add spin data and se_e2_a examples
iProzd Feb 25, 2024
4f67f78
Update test_ener_spin_model.py
iProzd Feb 25, 2024
5b5c085
Add dp SpinModel
iProzd Feb 26, 2024
4606ab0
Fix uts
iProzd Feb 26, 2024
51e5f49
use torch.logical_and
iProzd Feb 26, 2024
9bf51b4
Merge branch 'devel' into spin_rf
iProzd Feb 26, 2024
1185bc1
Fix uts; change force_real to force
iProzd Feb 26, 2024
e35d1ad
improve env_protection doc
iProzd Feb 27, 2024
503e8c0
Update test_smooth.py
iProzd Feb 27, 2024
b121140
update example
iProzd Feb 27, 2024
796d870
Merge branch 'devel' into spin_rf
iProzd Feb 27, 2024
c2f306c
Update __init__.py
iProzd Feb 27, 2024
847565a
fix uts
iProzd Feb 27, 2024
6529441
Update test_smooth.py
iProzd Feb 27, 2024
e7dab5d
Support spin dp_eval and test
iProzd Feb 27, 2024
98d8232
Update test_smooth.py
iProzd Feb 27, 2024
b8e1dab
move `has_spin` to `has_spin_pt` in pt deep_eval
iProzd Feb 27, 2024
2475dea
Merge branch 'devel' into spin_rf
iProzd Feb 27, 2024
872702e
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Feb 27, 2024
fd9ca77
Merge branch 'devel' into spin_rf
iProzd Feb 28, 2024
6c0ef31
Update test_permutation.py
iProzd Feb 28, 2024
6eddb89
Update deep_eval.py
iProzd Feb 28, 2024
4fede6a
megre devel into spin_rf
iProzd Mar 4, 2024
64410d0
Merge branch 'devel' into spin_rf
iProzd Mar 4, 2024
0cc0776
Merge branch 'devel' into spin_rf
iProzd Mar 5, 2024
449bbf5
Merge branch 'devel' into spin_rf
iProzd Mar 5, 2024
24f5fd4
Update spin
iProzd Mar 5, 2024
4f2a8fc
fix se_r
iProzd Mar 5, 2024
dcfcadb
Merge branch 'devel' into spin_rf
iProzd Mar 5, 2024
b7554b9
Update fitting.py
iProzd Mar 5, 2024
8a72e01
Remove virial support
iProzd Mar 5, 2024
9772fa4
Add exclude_types for data stat
iProzd Mar 5, 2024
f27ae51
Update outdef for mask_mag
iProzd Mar 5, 2024
7409e6b
Update test_output_def.py
iProzd Mar 5, 2024
62c30cb
Fix uts
iProzd Mar 5, 2024
7804da8
Fix uts
iProzd Mar 5, 2024
8376830
Merge branch 'devel' into spin_rf
iProzd Mar 5, 2024
37c6330
Update multi_task.py
iProzd Mar 5, 2024
93e253e
Update test_deeppot_a.py
iProzd Mar 5, 2024
9dccb1c
Merge branch 'devel' into spin_rf
iProzd Mar 6, 2024
3cb3316
use to_numpy_array
iProzd Mar 6, 2024
7cb8f9c
Update `has_spin`
iProzd Mar 6, 2024
84d1c70
add mask in stat data
iProzd Mar 6, 2024
fa9ff2c
Merge branch 'devel' into spin_rf
iProzd Mar 6, 2024
dcaf07c
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Mar 6, 2024
5b49c75
Fix uts
iProzd Mar 6, 2024
3c09148
replace expand_aparam from fitting to model
iProzd Mar 6, 2024
a73c314
Add dp test ut for spin
iProzd Mar 6, 2024
e9582c7
add ut for spin loss
iProzd Mar 7, 2024
09dfd10
add ut for spin
iProzd Mar 7, 2024
c0700c9
Update test_dp_test.py
iProzd Mar 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions deepmd/dpmodel/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
phys2inter,
to_face_distance,
)
from .spin import (
BaseSpin,
Spin,
)

__all__ = [
"EnvMat",
Expand Down Expand Up @@ -59,4 +63,6 @@
"to_face_distance",
"AtomExcludeMask",
"PairExcludeMask",
"BaseSpin",
"Spin",
]
218 changes: 218 additions & 0 deletions deepmd/dpmodel/utils/spin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
# SPDX-License-Identifier: LGPL-3.0-or-later
import copy
from abc import (
ABC,
abstractmethod,
)
from typing import (
List,
Tuple,
Union,
)

import numpy as np


class BaseSpin(ABC):
"""Abstract class for spin, mainly processes the spin type-related information.
Atom types can be split into three kinds:
1. Real types: real atom species, "Fe", "H", "O", etc.
2. Spin types: atom species with spin, as virtual atoms in input, "Fe_spin", etc.
3. Placeholder types: atom species without spin, as placeholders in input without contribution,
also name "H_spin", "O_spin", etc.
For any types in 2. or 3., the type index is `ntypes` plus index of its corresponding real type.

Parameters
----------
use_spin: List[bool]
A list of boolean values indicating whether to use atomic spin for each atom type.
True for spin and False for not. List of bool values with shape of [ntypes].
virtual_scale: List[float], float
The scaling factor to determine the virtual distance
between a virtual atom representing spin and its corresponding real atom
for each atom type with spin. This factor is defined as the virtual distance
divided by the magnitude of atomic spin for each atom type with spin.
The virtual coordinate is defined as the real coordinate plus spin * virtual_scale.
List of float values with shape of [ntypes] or [ntypes_spin] or one single float value for all types,
only used when use_spin is True for each atom type.
"""

def __init__(
self,
use_spin: List[bool],
virtual_scale: Union[List[float], float],
) -> None:
self.ntypes_real = len(use_spin)
self.ntypes_spin = use_spin.count(True)
self.use_spin = np.array(use_spin)
self.spin_mask = self.use_spin.astype(np.int64)
self.ntypes_real_and_spin = self.ntypes_real + self.ntypes_spin
self.ntypes_placeholder = self.ntypes_real - self.ntypes_spin
self.ntypes_input = 2 * self.ntypes_real # with placeholder for input types
self.real_type = np.arange(self.ntypes_real)
self.spin_type = np.arange(self.ntypes_real)[self.use_spin] + self.ntypes_real
self.real_and_spin_type = np.concatenate([self.real_type, self.spin_type])
self.placeholder_type = (
np.arange(self.ntypes_real)[~self.use_spin] + self.ntypes_real
)
self.spin_placeholder_type = np.arange(self.ntypes_real) + self.ntypes_real
self.input_type = np.arange(self.ntypes_real * 2)
if isinstance(virtual_scale, list):
if len(virtual_scale) == self.ntypes_real:
self.virtual_scale = virtual_scale
elif len(virtual_scale) == self.ntypes_spin:
self.virtual_scale = virtual_scale + [
0.0 for _ in range(self.ntypes_real - self.ntypes_spin)
]
iProzd marked this conversation as resolved.
Show resolved Hide resolved
elif isinstance(virtual_scale, float):
self.virtual_scale = [virtual_scale for _ in range(self.ntypes_real)]
else:
raise ValueError(f"Invalid virtual scale type: {type(virtual_scale)}")
self.virtual_scale = np.array(self.virtual_scale)
self.pair_exclude_types = []
self.init_pair_exclude_types_placeholder()
self.atom_exclude_types_ps = []
self.init_atom_exclude_types_placeholder_spin()
self.atom_exclude_types_p = []
self.init_atom_exclude_types_placeholder()

def get_ntypes_real(self) -> int:
"""Returns the number of real atom types."""
return self.ntypes_real

def get_ntypes_spin(self) -> int:
"""Returns the number of atom types which contain spin."""
return self.ntypes_spin

def get_ntypes_real_and_spin(self) -> int:
"""Returns the number of real atom types and types which contain spin."""
return self.ntypes_real_and_spin

def get_ntypes_input(self) -> int:
"""Returns the number of double real atom types for input placeholder."""
return self.ntypes_input

def get_use_spin(self) -> List[bool]:
"""Returns the list of whether to use spin for each atom type."""
return self.use_spin

def get_virtual_scale(self) -> np.ndarray:
"""Returns the list of magnitude of atomic spin for each atom type."""
return self.virtual_scale

def init_pair_exclude_types_placeholder(self) -> None:
"""
Initialize the pair-wise exclusion types for descriptor.
The placeholder types for those without spin are excluded.
"""
ti_grid, tj_grid = np.meshgrid(
self.placeholder_type, self.input_type, indexing="ij"
)
self.pair_exclude_types = (
np.stack((ti_grid, tj_grid), axis=-1).reshape(-1, 2).tolist()
)

def init_atom_exclude_types_placeholder_spin(self) -> None:
"""
Initialize the atom-wise exclusion types for fitting.
Both the placeholder types and spin types are excluded.
"""
self.atom_exclude_types_ps = self.spin_placeholder_type.tolist()

def init_atom_exclude_types_placeholder(self) -> None:
"""
Initialize the atom-wise exclusion types for fitting.
The placeholder types for those without spin are excluded.
"""
self.atom_exclude_types_p = self.placeholder_type.tolist()

def get_pair_exclude_types(self, exclude_types=None) -> List[Tuple[int, int]]:
"""
Return the pair-wise exclusion types for descriptor.
The placeholder types for those without spin are excluded.
"""
if exclude_types is None:
return self.pair_exclude_types
else:
_exclude_types: List[Tuple[int, int]] = copy.deepcopy(
self.pair_exclude_types
)
for tt in exclude_types:
assert len(tt) == 2
_exclude_types.append((tt[0], tt[1]))
return _exclude_types

def get_atom_exclude_types(self, exclude_types=None) -> List[int]:
"""
Return the atom-wise exclusion types for fitting before out_def.
Both the placeholder types and spin types are excluded.
"""
if exclude_types is None:
return self.atom_exclude_types_ps
else:
_exclude_types: List[int] = copy.deepcopy(self.atom_exclude_types_ps)
_exclude_types += exclude_types
_exclude_types = list(set(_exclude_types))
return _exclude_types

def get_atom_exclude_types_placeholder(self, exclude_types=None) -> List[int]:
"""
Return the atom-wise exclusion types for fitting after out_def.
The placeholder types for those without spin are excluded.
"""
if exclude_types is None:
return self.atom_exclude_types_p
else:
_exclude_types: List[int] = copy.deepcopy(self.atom_exclude_types_p)
_exclude_types += exclude_types
_exclude_types = list(set(_exclude_types))
return _exclude_types

@abstractmethod
def serialize(
self,
) -> dict:
pass

@classmethod
@abstractmethod
def deserialize(
cls,
data: dict,
) -> "BaseSpin":
pass

@abstractmethod
def get_virtual_scale_mask(self):
pass

@abstractmethod
def get_spin_mask(self):
pass


class Spin(BaseSpin):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.virtual_scale_mask = (self.virtual_scale * self.use_spin).reshape([-1])

def get_virtual_scale_mask(self):
return self.virtual_scale_mask

def get_spin_mask(self):
return self.spin_mask

def serialize(
self,
) -> dict:
return {
"use_spin": self.use_spin,
"virtual_scale": self.virtual_scale,
}

@classmethod
def deserialize(
cls,
data: dict,
) -> "Spin":
return cls(**data)
4 changes: 4 additions & 0 deletions deepmd/pt/loss/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@
from .ener import (
EnergyStdLoss,
)
from .ener_spin import (
EnergySpinLoss,
)
from .loss import (
TaskLoss,
)

__all__ = [
"DenoiseLoss",
"EnergyStdLoss",
"EnergySpinLoss",
"TaskLoss",
]
Loading
Loading