Skip to content

Commit 3a286e5

Browse files
author
Han Wang
committed
feat(pt_expt): add descriptors dpa1 dpa2 dpa3 and hybrid
1 parent 09e40bb commit 3a286e5

33 files changed

Lines changed: 3004 additions & 486 deletions

deepmd/dpmodel/array_api.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ def xp_swapaxes(a: Array, axis1: int, axis2: int) -> Array:
2929

3030
def xp_take_along_axis(arr: Array, indices: Array, axis: int) -> Array:
3131
xp = array_api_compat.array_namespace(arr)
32+
# torch.take_along_dim requires int64 indices
33+
if array_api_compat.is_torch_array(indices):
34+
indices = xp.astype(indices, xp.int64)
3235
if Version(xp.__array_api_version__) >= Version("2024.12"):
3336
# see: https://github.com/data-apis/array-api-strict/blob/d086c619a58f35c38240592ef994aa19ca7beebc/array_api_strict/_indexing_functions.py#L30-L39
3437
return xp.take_along_axis(arr, indices, axis=axis)

deepmd/dpmodel/descriptor/dpa2.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -573,6 +573,7 @@ def init_subclass_params(sub_data: dict | Any, sub_class: type) -> Any:
573573
self.smooth = smooth
574574
self.exclude_types = exclude_types
575575
self.env_protection = env_protection
576+
self.rcut_smth = self.repinit.get_rcut_smth()
576577
self.trainable = trainable
577578
self.add_tebd_to_repinit_out = add_tebd_to_repinit_out
578579

deepmd/dpmodel/descriptor/repflows.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -595,8 +595,12 @@ def call(
595595
# n_angle x 1
596596
a_sw = (a_sw[:, :, :, None] * a_sw[:, :, None, :])[a_nlist_mask]
597597
else:
598-
edge_index = xp.zeros([2, 1], dtype=nlist.dtype)
599-
angle_index = xp.zeros([3, 1], dtype=nlist.dtype)
598+
edge_index = xp.zeros(
599+
[2, 1], dtype=nlist.dtype, device=array_api_compat.device(nlist)
600+
)
601+
angle_index = xp.zeros(
602+
[3, 1], dtype=nlist.dtype, device=array_api_compat.device(nlist)
603+
)
600604

601605
# get edge and angle embedding
602606
# nb x nloc x nnei x e_dim [OR] n_edge x e_dim
@@ -1711,6 +1715,7 @@ def call(
17111715
xp.zeros(
17121716
(nb, nloc, self.nnei - self.a_sel, self.e_dim),
17131717
dtype=edge_ebd.dtype,
1718+
device=array_api_compat.device(edge_ebd),
17141719
),
17151720
],
17161721
axis=2,
@@ -1741,6 +1746,7 @@ def call(
17411746
xp.zeros(
17421747
(nb, nloc, self.nnei - self.a_sel),
17431748
dtype=a_nlist_mask.dtype,
1749+
device=array_api_compat.device(a_nlist_mask),
17441750
),
17451751
],
17461752
axis=-1,

deepmd/dpmodel/descriptor/repformers.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -475,7 +475,7 @@ def call(
475475
g1 = self.act(atype_embd)
476476
# nf x nloc x nnei x 1, nf x nloc x nnei x 3
477477
if not self.direct_dist:
478-
g2, h2 = xp.split(dmatrix, [1], axis=-1)
478+
g2, h2 = dmatrix[..., :1], dmatrix[..., 1:]
479479
else:
480480
g2, h2 = safe_for_vector_norm(diff, axis=-1, keepdims=True), diff
481481
g2 = g2 / self.rcut
@@ -756,10 +756,12 @@ def _cal_hg(
756756
else:
757757
g = _apply_switch(g, sw)
758758
if not use_sqrt_nnei:
759-
invnnei = (1.0 / float(nnei)) * xp.ones((nf, nloc, 1, 1), dtype=g.dtype)
759+
invnnei = (1.0 / float(nnei)) * xp.ones(
760+
(nf, nloc, 1, 1), dtype=g.dtype, device=array_api_compat.device(g)
761+
)
760762
else:
761763
invnnei = (1.0 / (float(nnei) ** 0.5)) * xp.ones(
762-
(nf, nloc, 1, 1), dtype=g.dtype
764+
(nf, nloc, 1, 1), dtype=g.dtype, device=array_api_compat.device(g)
763765
)
764766
# nf x nloc x 3 x ng
765767
hg = xp.matmul(xp.matrix_transpose(h), g) * invnnei
@@ -1655,7 +1657,9 @@ def _update_g1_conv(
16551657
invnnei = invnnei[:, :, xp.newaxis]
16561658
else:
16571659
gg1 = _apply_switch(gg1, sw)
1658-
invnnei = (1.0 / float(nnei)) * xp.ones((nf, nloc, 1), dtype=gg1.dtype)
1660+
invnnei = (1.0 / float(nnei)) * xp.ones(
1661+
(nf, nloc, 1), dtype=gg1.dtype, device=array_api_compat.device(gg1)
1662+
)
16591663
if not self.g1_out_conv:
16601664
# nf x nloc x ng2
16611665
g1_11 = xp.sum(g2 * gg1, axis=2) * invnnei

deepmd/dpmodel/descriptor/se_e2_a.py

Lines changed: 35 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -427,45 +427,64 @@ def call(
427427
The smooth switch function.
428428
"""
429429
del mapping
430+
xp = array_api_compat.array_namespace(coord_ext, atype_ext, nlist)
431+
input_dtype = coord_ext.dtype
430432
# nf x nloc x nnei x 4
431433
rr, diff, ww = self.env_mat.call(
432-
coord_ext, atype_ext, nlist, self.davg, self.dstd
434+
coord_ext,
435+
atype_ext,
436+
nlist,
437+
self.davg[...],
438+
self.dstd[...],
433439
)
434440
nf, nloc, nnei, _ = rr.shape
435-
sec = np.append([0], np.cumsum(self.sel))
441+
sec = self.sel_cumsum
436442

437443
ng = self.neuron[-1]
438-
gr = np.zeros([nf * nloc, ng, 4], dtype=PRECISION_DICT[self.precision])
444+
gr = xp.zeros(
445+
[nf * nloc, ng, 4],
446+
dtype=input_dtype,
447+
device=array_api_compat.device(coord_ext),
448+
)
439449
exclude_mask = self.emask.build_type_exclude_mask(nlist, atype_ext)
440450
# merge nf and nloc axis, so for type_one_side == False,
441451
# we don't require atype is the same in all frames
442-
exclude_mask = exclude_mask.reshape(nf * nloc, nnei)
443-
rr = rr.reshape(nf * nloc, nnei, 4)
452+
exclude_mask = xp.reshape(exclude_mask, (nf * nloc, nnei))
453+
rr = xp.reshape(rr, (nf * nloc, nnei, 4))
454+
rr = xp.astype(rr, self.dstd.dtype)
455+
456+
if not self.type_one_side:
457+
# nf x nloc -> (nf * nloc)
458+
atype_loc = xp.reshape(atype_ext[:, :nloc], (nf * nloc,))
444459

445460
for embedding_idx in itertools.product(
446461
range(self.ntypes), repeat=self.embeddings.ndim
447462
):
448463
if self.type_one_side:
449464
(tt,) = embedding_idx
450-
ti_mask = np.s_[:]
451465
else:
452466
ti, tt = embedding_idx
453-
ti_mask = atype_ext[:, :nloc].ravel() == ti
454-
mm = exclude_mask[ti_mask, sec[tt] : sec[tt + 1]]
455-
tr = rr[ti_mask, sec[tt] : sec[tt + 1], :]
456-
tr = tr * mm[:, :, None]
467+
mm = exclude_mask[:, sec[tt] : sec[tt + 1]]
468+
tr = rr[:, sec[tt] : sec[tt + 1], :]
469+
tr = tr * xp.astype(mm[:, :, None], tr.dtype)
457470
ss = tr[..., 0:1]
458471
gg = self.cal_g(ss, embedding_idx)
459-
gr_tmp = np.einsum("lni,lnj->lij", gg, tr)
460-
gr[ti_mask] += gr_tmp
461-
gr = gr.reshape(nf, nloc, ng, 4)
472+
gr_tmp = xp.sum(gg[:, :, :, None] * tr[:, :, None, :], axis=1)
473+
if not self.type_one_side:
474+
# (nf * nloc) x 1 x 1
475+
ti_mask = xp.astype(
476+
xp.reshape(atype_loc == ti, (nf * nloc, 1, 1)), gr_tmp.dtype
477+
)
478+
gr_tmp = gr_tmp * ti_mask
479+
gr += gr_tmp
480+
gr = xp.reshape(gr, (nf, nloc, ng, 4))
462481
# nf x nloc x ng x 4
463482
gr /= self.nnei
464483
gr1 = gr[:, :, : self.axis_neuron, :]
465484
# nf x nloc x ng x ng1
466-
grrg = np.einsum("flid,fljd->flij", gr, gr1)
485+
grrg = xp.sum(gr[:, :, :, None, :] * gr1[:, :, None, :, :], axis=4)
467486
# nf x nloc x (ng x ng1)
468-
grrg = grrg.reshape(nf, nloc, ng * self.axis_neuron)
487+
grrg = xp.reshape(grrg, (nf, nloc, ng * self.axis_neuron))
469488
return grrg, gr[..., 1:], None, None, ww
470489

471490
def serialize(self) -> dict:
@@ -553,94 +572,4 @@ def update_sel(
553572
return local_jdata_cpy, min_nbor_dist
554573

555574

556-
class DescrptSeAArrayAPI(DescrptSeA):
557-
@cast_precision
558-
def call(
559-
self,
560-
coord_ext: Array,
561-
atype_ext: Array,
562-
nlist: Array,
563-
mapping: Array | None = None,
564-
) -> Array:
565-
"""Compute the descriptor.
566-
567-
Parameters
568-
----------
569-
coord_ext
570-
The extended coordinates of atoms. shape: nf x (nallx3)
571-
atype_ext
572-
The extended aotm types. shape: nf x nall
573-
nlist
574-
The neighbor list. shape: nf x nloc x nnei
575-
mapping
576-
The index mapping from extended to local region. not used by this descriptor.
577-
578-
Returns
579-
-------
580-
descriptor
581-
The descriptor. shape: nf x nloc x (ng x axis_neuron)
582-
gr
583-
The rotationally equivariant and permutationally invariant single particle
584-
representation. shape: nf x nloc x ng x 3
585-
g2
586-
The rotationally invariant pair-partical representation.
587-
this descriptor returns None
588-
h2
589-
The rotationally equivariant pair-partical representation.
590-
this descriptor returns None
591-
sw
592-
The smooth switch function.
593-
"""
594-
if not self.type_one_side:
595-
raise NotImplementedError(
596-
"type_one_side == False is not supported in DescrptSeAArrayAPI"
597-
)
598-
del mapping
599-
xp = array_api_compat.array_namespace(coord_ext, atype_ext, nlist)
600-
input_dtype = coord_ext.dtype
601-
# nf x nloc x nnei x 4
602-
rr, diff, ww = self.env_mat.call(
603-
coord_ext,
604-
atype_ext,
605-
nlist,
606-
self.davg[...],
607-
self.dstd[...],
608-
)
609-
nf, nloc, nnei, _ = rr.shape
610-
sec = self.sel_cumsum
611-
612-
ng = self.neuron[-1]
613-
gr = xp.zeros(
614-
[nf * nloc, ng, 4],
615-
dtype=input_dtype,
616-
device=array_api_compat.device(coord_ext),
617-
)
618-
exclude_mask = self.emask.build_type_exclude_mask(nlist, atype_ext)
619-
# merge nf and nloc axis, so for type_one_side == False,
620-
# we don't require atype is the same in all frames
621-
exclude_mask = xp.reshape(exclude_mask, (nf * nloc, nnei))
622-
rr = xp.reshape(rr, (nf * nloc, nnei, 4))
623-
rr = xp.astype(rr, self.dstd.dtype)
624-
625-
for embedding_idx in itertools.product(
626-
range(self.ntypes), repeat=self.embeddings.ndim
627-
):
628-
(tt,) = embedding_idx
629-
mm = exclude_mask[:, sec[tt] : sec[tt + 1]]
630-
tr = rr[:, sec[tt] : sec[tt + 1], :]
631-
tr = tr * xp.astype(mm[:, :, None], tr.dtype)
632-
ss = tr[..., 0:1]
633-
gg = self.cal_g(ss, embedding_idx)
634-
# gr_tmp = xp.einsum("lni,lnj->lij", gg, tr)
635-
gr_tmp = xp.sum(gg[:, :, :, None] * tr[:, :, None, :], axis=1)
636-
gr += gr_tmp
637-
gr = xp.reshape(gr, (nf, nloc, ng, 4))
638-
# nf x nloc x ng x 4
639-
gr /= self.nnei
640-
gr1 = gr[:, :, : self.axis_neuron, :]
641-
# nf x nloc x ng x ng1
642-
# grrg = xp.einsum("flid,fljd->flij", gr, gr1)
643-
grrg = xp.sum(gr[:, :, :, None, :] * gr1[:, :, None, :, :], axis=4)
644-
# nf x nloc x (ng x ng1)
645-
grrg = xp.reshape(grrg, (nf, nloc, ng * self.axis_neuron))
646-
return grrg, gr[..., 1:], None, None, ww
575+
DescrptSeAArrayAPI = DescrptSeA

0 commit comments

Comments
 (0)