Skip to content

Commit 668dd1f

Browse files
committed
test(dpa4): enable array-api-strict consistency tests
1 parent 1cd6556 commit 668dd1f

8 files changed

Lines changed: 240 additions & 32 deletions

File tree

deepmd/dpmodel/descriptor/dpa4_nn/norm.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ def call(self, x: Any) -> Any:
546546
if x.ndim == 2:
547547
inv_rms = 1.0 / xp.sqrt(xp.mean(x * x, axis=-1, keepdims=True) + self.eps)
548548
x = x * inv_rms
549-
x = x * xp_asarray_nodetach(xp, self.adam_scale[...], device=device)[0]
549+
x = x * xp_asarray_nodetach(xp, self.adam_scale[...], device=device)[0, :]
550550
return xp.astype(x, in_dtype)
551551

552552
inv_rms = 1.0 / xp.sqrt(xp.mean(x * x, axis=-1, keepdims=True) + self.eps)

source/tests/array_api_strict/common.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,10 @@ def to_array_api_strict_array(array: np.ndarray | None) -> Any:
5959
f"{_PACKAGE_ROOT}.descriptor.dpa2",
6060
f"{_PACKAGE_ROOT}.descriptor.repflows",
6161
f"{_PACKAGE_ROOT}.descriptor.dpa3",
62+
f"{_PACKAGE_ROOT}.descriptor.dpa4",
6263
f"{_PACKAGE_ROOT}.descriptor.hybrid",
6364
f"{_PACKAGE_ROOT}.fitting",
65+
f"{_PACKAGE_ROOT}.fitting.dpa4_ener",
6466
)
6567

6668

source/tests/array_api_strict/descriptor/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@
88
from .dpa3 import (
99
DescrptDPA3,
1010
)
11+
from .dpa4 import (
12+
DescrptDPA4,
13+
)
1114
from .hybrid import (
1215
DescrptHybrid,
1316
)
@@ -31,6 +34,7 @@
3134
"DescrptDPA1",
3235
"DescrptDPA2",
3336
"DescrptDPA3",
37+
"DescrptDPA4",
3438
"DescrptHybrid",
3539
"DescrptSeA",
3640
"DescrptSeAttenV2",
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# SPDX-License-Identifier: LGPL-3.0-or-later
2+
from deepmd.dpmodel.descriptor.dpa4 import DescrptDPA4 as DescrptDPA4DP
3+
from deepmd.dpmodel.descriptor.dpa4_nn.activation import (
4+
SwiGLU,
5+
)
6+
from deepmd.dpmodel.descriptor.dpa4_nn.grid_net import (
7+
GridProduct,
8+
)
9+
from deepmd.dpmodel.descriptor.dpa4_nn.radial import (
10+
BridgingSwitch,
11+
C3CutoffEnvelope,
12+
InnerClamp,
13+
)
14+
from deepmd.dpmodel.descriptor.dpa4_nn.wignerd import (
15+
WignerDCalculator,
16+
)
17+
18+
from ..common import (
19+
array_api_strict_module,
20+
register_dpmodel_mapping,
21+
)
22+
from ..utils import exclude_mask as _strict_exclude_mask # noqa: F401
23+
from ..utils import network as _strict_network # noqa: F401
24+
from .base_descriptor import (
25+
BaseDescriptor,
26+
)
27+
28+
29+
@BaseDescriptor.register("SeZM")
30+
@BaseDescriptor.register("sezm")
31+
@BaseDescriptor.register("DPA4")
32+
@BaseDescriptor.register("dpa4")
33+
@array_api_strict_module
34+
class DescrptDPA4(DescrptDPA4DP):
35+
pass
36+
37+
38+
for _stateless_cls in (
39+
BridgingSwitch,
40+
C3CutoffEnvelope,
41+
GridProduct,
42+
InnerClamp,
43+
SwiGLU,
44+
WignerDCalculator,
45+
):
46+
register_dpmodel_mapping(_stateless_cls, lambda v: v)

source/tests/array_api_strict/fitting/__init__.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
# SPDX-License-Identifier: LGPL-3.0-or-later
2+
from .dpa4_ener import (
3+
SeZMEnergyFittingNet,
4+
)
25
from .fitting import (
36
DipoleFittingNet,
47
DOSFittingNet,
@@ -13,4 +16,5 @@
1316
"EnergyFittingNet",
1417
"PolarFittingNet",
1518
"PropertyFittingNet",
19+
"SeZMEnergyFittingNet",
1620
]
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# SPDX-License-Identifier: LGPL-3.0-or-later
2+
from typing import (
3+
ClassVar,
4+
)
5+
6+
from deepmd.dpmodel.fitting.dpa4_ener import GLUFittingNet as GLUFittingNetDP
7+
from deepmd.dpmodel.fitting.dpa4_ener import (
8+
SeZMEnergyFittingNet as SeZMEnergyFittingNetDP,
9+
)
10+
from deepmd.dpmodel.fitting.dpa4_ener import (
11+
SeZMNetworkCollection as SeZMNetworkCollectionDP,
12+
)
13+
14+
from ..common import (
15+
array_api_strict_module,
16+
register_dpmodel_mapping,
17+
)
18+
from ..utils import network as _strict_network # noqa: F401
19+
20+
21+
@array_api_strict_module
22+
class GLUFittingNet(GLUFittingNetDP):
23+
pass
24+
25+
26+
@array_api_strict_module
27+
class SeZMNetworkCollection(SeZMNetworkCollectionDP):
28+
NETWORK_TYPE_MAP: ClassVar[dict[str, type]] = {
29+
"sezm_fitting_network": GLUFittingNet,
30+
}
31+
32+
33+
@array_api_strict_module
34+
class SeZMEnergyFittingNet(SeZMEnergyFittingNetDP):
35+
pass
36+
37+
38+
register_dpmodel_mapping(
39+
GLUFittingNetDP,
40+
lambda v: GLUFittingNet.deserialize(v.serialize()),
41+
)
42+
43+
register_dpmodel_mapping(
44+
SeZMNetworkCollectionDP,
45+
lambda v: SeZMNetworkCollection.deserialize(v.serialize()),
46+
)

source/tests/consistent/descriptor/test_dpa4.py

Lines changed: 59 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
)
2020

2121
from ..common import (
22+
INSTALLED_ARRAY_API_STRICT,
2223
INSTALLED_PT,
2324
INSTALLED_PT_EXPT,
2425
CommonTest,
@@ -28,14 +29,40 @@
2829
DescriptorTest,
2930
)
3031

31-
if INSTALLED_PT:
32-
from deepmd.pt.model.descriptor.sezm import DescrptSeZM as DescrptDPA4PT
33-
else:
34-
DescrptDPA4PT = None
35-
if INSTALLED_PT_EXPT:
36-
from deepmd.pt_expt.descriptor.dpa4 import DescrptDPA4 as DescrptDPA4PTExpt
32+
DescrptDPA4PT = None
33+
DescrptDPA4PTExpt = None
34+
35+
36+
def _get_descrpt_dpa4_pt() -> type | None:
37+
global DescrptDPA4PT
38+
if not INSTALLED_PT:
39+
return None
40+
if DescrptDPA4PT is None:
41+
from deepmd.pt.model.descriptor.sezm import (
42+
DescrptSeZM,
43+
)
44+
45+
DescrptDPA4PT = DescrptSeZM
46+
return DescrptDPA4PT
47+
48+
49+
def _get_descrpt_dpa4_pt_expt() -> type | None:
50+
global DescrptDPA4PTExpt
51+
if not INSTALLED_PT_EXPT:
52+
return None
53+
if DescrptDPA4PTExpt is None:
54+
from deepmd.pt_expt.descriptor.dpa4 import (
55+
DescrptDPA4,
56+
)
57+
58+
DescrptDPA4PTExpt = DescrptDPA4
59+
return DescrptDPA4PTExpt
60+
61+
62+
if INSTALLED_ARRAY_API_STRICT:
63+
from ...array_api_strict.descriptor.dpa4 import DescrptDPA4 as DescrptDPA4Strict
3764
else:
38-
DescrptDPA4PTExpt = None
65+
DescrptDPA4Strict = None
3966

4067
# not implemented
4168
DescrptDPA4TF = None
@@ -146,22 +173,31 @@ def data(self) -> dict:
146173

147174
@property
148175
def skip_pt(self) -> bool:
149-
return CommonTest.skip_pt
176+
return CommonTest.skip_pt or _get_descrpt_dpa4_pt() is None
177+
178+
@property
179+
def skip_pt_expt(self) -> bool:
180+
return not INSTALLED_PT_EXPT or _get_descrpt_dpa4_pt_expt() is None
181+
182+
@property
183+
def pt_class(self) -> type | None:
184+
return _get_descrpt_dpa4_pt()
185+
186+
@property
187+
def pt_expt_class(self) -> type | None:
188+
return _get_descrpt_dpa4_pt_expt()
150189

151190
skip_dp = False
152191
skip_tf = True
153192
skip_jax = True
154193
skip_pd = True
155-
skip_pt_expt = not INSTALLED_PT_EXPT
156-
skip_array_api_strict = True
194+
skip_array_api_strict = not INSTALLED_ARRAY_API_STRICT
157195

158196
tf_class = DescrptDPA4TF
159197
dp_class = DescrptDPA4DP
160-
pt_class = DescrptDPA4PT
161-
pt_expt_class = DescrptDPA4PTExpt
162198
jax_class = None
163199
pd_class = None
164-
array_api_strict_class = None
200+
array_api_strict_class = DescrptDPA4Strict
165201
args: ClassVar[list] = [
166202
*descrpt_se_zm_args(),
167203
Argument("ntypes", int, optional=False),
@@ -234,6 +270,16 @@ def eval_pt_expt(self, pt_expt_obj: Any) -> Any:
234270
mixed_types=True,
235271
)
236272

273+
def eval_array_api_strict(self, array_api_strict_obj: Any) -> Any:
274+
return self.eval_array_api_strict_descriptor(
275+
array_api_strict_obj,
276+
self.natoms,
277+
self.coords,
278+
self.atype,
279+
self.box,
280+
mixed_types=True,
281+
)
282+
237283
def extract_ret(self, ret: Any, backend) -> tuple[np.ndarray, ...]:
238284
return (ret[0],)
239285

0 commit comments

Comments
 (0)