Skip to content

Commit 02fa9d0

Browse files
committed
fix bug based on coderabbit
1 parent 2dbd423 commit 02fa9d0

5 files changed

Lines changed: 81 additions & 91 deletions

File tree

deepmd/dpmodel/atomic_model/base_atomic_model.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,14 @@ def forward_common_atomic(
226226
ret_dict[kk] = xp.reshape(tmp_arr, out_shape)
227227
if atomic_weight is not None:
228228
_out_shape = ret_dict[kk].shape
229+
# Validate that atomic_weight.shape[2] matches the flattened trailing dimensions
230+
# of the output to ensure correct broadcasting behavior
231+
out_shape2 = math.prod(_out_shape[2:])
232+
if atomic_weight.shape[2] != out_shape2:
233+
raise ValueError(
234+
f"atomic_weight shape {atomic_weight.shape} incompatible with output shape {_out_shape}. "
235+
f"Expected atomic_weight.shape[2] to be {out_shape2} for key '{kk}'"
236+
)
229237
ret_dict[kk] = ret_dict[kk] * atomic_weight.reshape(
230238
[_out_shape[0], _out_shape[1], -1]
231239
)

deepmd/dpmodel/model/make_model.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def model_call_from_call_lower(
6868
fparam: Array | None = None,
6969
aparam: Array | None = None,
7070
do_atomic_virial: bool = False,
71-
atomic_weight: Optional[np.ndarray] = None,
71+
atomic_weight: Array | None = None,
7272
) -> dict[str, Array]:
7373
"""Return model prediction from lower interface.
7474
@@ -231,7 +231,7 @@ def call(
231231
fparam: Array | None = None,
232232
aparam: Array | None = None,
233233
do_atomic_virial: bool = False,
234-
atomic_weight: Optional[np.ndarray] = None,
234+
atomic_weight: Array | None = None,
235235
) -> dict[str, Array]:
236236
"""Return model prediction.
237237
@@ -292,7 +292,7 @@ def call_lower(
292292
fparam: Array | None = None,
293293
aparam: Array | None = None,
294294
do_atomic_virial: bool = False,
295-
atomic_weight: Optional[np.ndarray] = None,
295+
atomic_weight: Array | None = None,
296296
) -> dict[str, Array]:
297297
"""Return model prediction. Lower interface that takes
298298
extended atomic coordinates and types, nlist, and mapping
@@ -359,7 +359,7 @@ def forward_common_atomic(
359359
fparam: Array | None = None,
360360
aparam: Array | None = None,
361361
do_atomic_virial: bool = False,
362-
atomic_weight: Optional[np.ndarray] = None,
362+
atomic_weight: Array | None = None,
363363
) -> dict[str, Array]:
364364
atomic_ret = self.atomic_model.forward_common_atomic(
365365
extended_coord,
@@ -387,7 +387,9 @@ def input_type_cast(
387387
fparam: Array | None = None,
388388
aparam: Array | None = None,
389389
atomic_weight: Array | None = None,
390-
) -> tuple[Array, Array, np.ndarray | None, np.ndarray | None, np.ndarray | None, str]:
390+
) -> tuple[
391+
Array, Array, np.ndarray | None, np.ndarray | None, np.ndarray | None, str
392+
]:
391393
"""Cast the input data to global float type."""
392394
input_prec = RESERVED_PRECISION_DICT[self.precision_dict[coord.dtype.name]]
393395
###

deepmd/pt/infer/deep_eval.py

Lines changed: 62 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ def eval(
379379
else:
380380
if atomic_weight is not None:
381381
raise ValueError(
382-
"atomic_weight is not supported when spin is provided. "
382+
"atomic_weight is not supported when spin is provided."
383383
)
384384
out = self._eval_func(self._eval_model_spin, numb_test, natoms)(
385385
coords,
@@ -533,43 +533,9 @@ def _eval_model(
533533
else:
534534
aparam_input = None
535535
if atomic_weight is not None:
536-
# Validate atomic_weight shape
537-
if atomic_weight.ndim == 1:
538-
# (natoms,) - broadcast across frames
539-
if atomic_weight.shape[0] != natoms:
540-
raise ValueError(
541-
f"atomic_weight shape {atomic_weight.shape} incompatible with number of atoms {natoms}"
542-
)
543-
atomic_weight = np.tile(atomic_weight, (nframes, 1))
544-
elif atomic_weight.ndim == 2:
545-
# (nframes, natoms) or (natoms, k)
546-
if (
547-
atomic_weight.shape[0] == natoms
548-
and atomic_weight.shape[1] != nframes
549-
):
550-
# (natoms, k) - broadcast across frames
551-
atomic_weight = np.tile(atomic_weight, (nframes, 1, 1))
552-
elif (
553-
atomic_weight.shape[0] != nframes
554-
or atomic_weight.shape[1] != natoms
555-
):
556-
raise ValueError(
557-
f"atomic_weight shape {atomic_weight.shape} incompatible with nframes={nframes} and natoms={natoms}"
558-
)
559-
elif atomic_weight.ndim == 3:
560-
# (nframes, natoms, k)
561-
if (
562-
atomic_weight.shape[0] != nframes
563-
or atomic_weight.shape[1] != natoms
564-
):
565-
raise ValueError(
566-
f"atomic_weight shape {atomic_weight.shape} incompatible with nframes={nframes} and natoms={natoms}"
567-
)
568-
else:
569-
raise ValueError(
570-
f"atomic_weight must have 1, 2, or 3 dimensions, got {atomic_weight.ndim}"
571-
)
572-
536+
atomic_weight = self._validate_and_reshape_atomic_weight(
537+
atomic_weight, nframes, natoms
538+
)
573539
atomic_weight_input = to_torch_tensor(
574540
atomic_weight.reshape(nframes, natoms, -1)
575541
)
@@ -613,7 +579,6 @@ def _eval_model_spin(
613579
fparam: np.ndarray | None,
614580
aparam: np.ndarray | None,
615581
request_defs: list[OutputVariableDef],
616-
atomic_weight: Optional[np.ndarray] = None,
617582
) -> tuple[np.ndarray, ...]:
618583
model = self.dp.to(DEVICE)
619584

@@ -655,49 +620,7 @@ def _eval_model_spin(
655620
)
656621
else:
657622
aparam_input = None
658-
if atomic_weight is not None:
659-
# Validate atomic_weight shape for spin model
660-
if atomic_weight.ndim == 1:
661-
# (natoms,) - broadcast across frames
662-
if atomic_weight.shape[0] != natoms:
663-
raise ValueError(
664-
f"atomic_weight shape {atomic_weight.shape} incompatible with number of atoms {natoms}"
665-
)
666-
atomic_weight = np.tile(atomic_weight, (nframes, 1))
667-
elif atomic_weight.ndim == 2:
668-
# (nframes, natoms) or (natoms, k)
669-
if (
670-
atomic_weight.shape[0] == natoms
671-
and atomic_weight.shape[1] != nframes
672-
):
673-
# (natoms, k) - broadcast across frames
674-
atomic_weight = np.tile(atomic_weight, (nframes, 1, 1))
675-
elif (
676-
atomic_weight.shape[0] != nframes
677-
or atomic_weight.shape[1] != natoms
678-
):
679-
raise ValueError(
680-
f"atomic_weight shape {atomic_weight.shape} incompatible with nframes={nframes} and natoms={natoms}"
681-
)
682-
elif atomic_weight.ndim == 3:
683-
# (nframes, natoms, k)
684-
if (
685-
atomic_weight.shape[0] != nframes
686-
or atomic_weight.shape[1] != natoms
687-
):
688-
raise ValueError(
689-
f"atomic_weight shape {atomic_weight.shape} incompatible with nframes={nframes} and natoms={natoms}"
690-
)
691-
else:
692-
raise ValueError(
693-
f"atomic_weight must have 1, 2, or 3 dimensions, got {atomic_weight.ndim}"
694-
)
695-
696-
atomic_weight_input = to_torch_tensor(
697-
atomic_weight.reshape(nframes, natoms, -1)
698-
)
699-
else:
700-
atomic_weight_input = None
623+
atomic_weight_input = None
701624

702625
do_atomic_virial = any(
703626
x.category == OutputVariableCategory.DERV_C_REDU for x in request_defs
@@ -954,3 +877,60 @@ def eval_fitting_last_layer(
954877
fitting_net = model.eval_fitting_last_layer()
955878
model.set_eval_fitting_last_layer_hook(False)
956879
return to_numpy_array(fitting_net)
880+
881+
def _validate_and_reshape_atomic_weight(
882+
self,
883+
atomic_weight: np.ndarray,
884+
nframes: int,
885+
natoms: int,
886+
) -> np.ndarray:
887+
"""Validate and reshape atomic_weight to (nframes, natoms, k).
888+
889+
Parameters
890+
----------
891+
atomic_weight : np.ndarray
892+
Input atomic weights with various possible shapes
893+
nframes : int
894+
Number of frames
895+
natoms : int
896+
Number of atoms
897+
898+
Returns
899+
-------
900+
np.ndarray
901+
Reshaped atomic_weight with shape (nframes, natoms, k)
902+
903+
Raises
904+
------
905+
ValueError
906+
If atomic_weight shape is incompatible
907+
"""
908+
# Validate atomic_weight shape
909+
if atomic_weight.ndim == 1:
910+
# (natoms,) - broadcast across frames
911+
if atomic_weight.shape[0] != natoms:
912+
raise ValueError(
913+
f"atomic_weight shape {atomic_weight.shape} incompatible with number of atoms {natoms}"
914+
)
915+
atomic_weight = np.tile(atomic_weight, (nframes, 1))
916+
elif atomic_weight.ndim == 2:
917+
# (nframes, natoms) or (natoms, k)
918+
if atomic_weight.shape[0] == natoms and atomic_weight.shape[1] != nframes:
919+
# (natoms, k) - broadcast across frames
920+
atomic_weight = np.tile(atomic_weight, (nframes, 1, 1))
921+
elif atomic_weight.shape[0] != nframes or atomic_weight.shape[1] != natoms:
922+
raise ValueError(
923+
f"atomic_weight shape {atomic_weight.shape} incompatible with nframes={nframes} and natoms={natoms}"
924+
)
925+
elif atomic_weight.ndim == 3:
926+
# (nframes, natoms, k)
927+
if atomic_weight.shape[0] != nframes or atomic_weight.shape[1] != natoms:
928+
raise ValueError(
929+
f"atomic_weight shape {atomic_weight.shape} incompatible with nframes={nframes} and natoms={natoms}"
930+
)
931+
else:
932+
raise ValueError(
933+
f"atomic_weight must have 1, 2, or 3 dimensions, got {atomic_weight.ndim}"
934+
)
935+
936+
return atomic_weight

deepmd/pt/model/model/dipole_model.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def forward(
6060
fparam: torch.Tensor | None = None,
6161
aparam: torch.Tensor | None = None,
6262
do_atomic_virial: bool = False,
63-
atomic_weight: Optional[torch.Tensor] = None,
63+
atomic_weight: torch.Tensor | None = None,
6464
) -> dict[str, torch.Tensor]:
6565
model_ret = self.forward_common(
6666
coord,

deepmd/pt/model/model/make_model.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ def forward_common(
138138
fparam: torch.Tensor | None = None,
139139
aparam: torch.Tensor | None = None,
140140
do_atomic_virial: bool = False,
141-
atomic_weight: Optional[torch.Tensor] = None,
141+
atomic_weight: torch.Tensor | None = None,
142142
) -> dict[str, torch.Tensor]:
143143
"""Return model prediction.
144144
@@ -255,7 +255,7 @@ def forward_common_lower(
255255
do_atomic_virial: bool = False,
256256
comm_dict: dict[str, torch.Tensor] | None = None,
257257
extra_nlist_sort: bool = False,
258-
atomic_weight: Optional[torch.Tensor] = None,
258+
atomic_weight: torch.Tensor | None = None,
259259
) -> dict[str, torch.Tensor]:
260260
"""Return model prediction. Lower interface that takes
261261
extended atomic coordinates and types, nlist, and mapping
@@ -642,7 +642,7 @@ def forward(
642642
fparam: torch.Tensor | None = None,
643643
aparam: torch.Tensor | None = None,
644644
do_atomic_virial: bool = False,
645-
atomic_weight: Optional[torch.Tensor] = None,
645+
atomic_weight: torch.Tensor | None = None,
646646
) -> dict[str, torch.Tensor]:
647647
# directly call the forward_common method when no specific transform rule
648648
return self.forward_common(

0 commit comments

Comments
 (0)