Skip to content

Commit b037154

Browse files
author
Han Wang
committed
test(pt_expt): pin the public-BaseModel native-spin round trip
Asserts the reviewer's exact contract (PR deepmodeling#5884, 3638137290): the public pt_expt BaseModel.deserialize(model.serialize()) returns the pt_expt NativeSpinEnergyModel, a torch.nn.Module accepting .to(DEVICE) (the concrete finetune failure), carrying the graph-export machinery, with forward parity at 1e-12 on energy/force/force_mag.
1 parent 71239f9 commit b037154

1 file changed

Lines changed: 46 additions & 0 deletions

File tree

source/tests/pt_expt/model/test_dpa4_native_spin.py

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -957,3 +957,49 @@ def test_allow_missing_label_data_requirement(
957957
spin_req = next(rr for rr in reqs if rr.key == "spin")
958958
assert spin_req.must is expected_must
959959
assert spin_req.default == 0.0
960+
961+
962+
class TestPublicBaseModelRoundTrip:
963+
"""Review 3638137290: pt_expt must round-trip its own native-spin
964+
serialization through the PUBLIC BaseModel entry point, returning the
965+
pt_expt class (a torch.nn.Module with .to() and the graph-export
966+
machinery), with forward parity.
967+
968+
Before the registry dispatch, ``BaseModel.deserialize`` entered a
969+
hard-coded dpmodel branch and returned the numpy class here -- no
970+
``.to()`` (the concrete finetune failure: ``training.py`` calls
971+
``BaseModel.deserialize(...).to(DEVICE)``), no torch export machinery.
972+
"""
973+
974+
def test_roundtrip_returns_pt_expt_module(self) -> None:
975+
from deepmd.pt_expt.model.model import (
976+
BaseModel,
977+
)
978+
979+
model = _jittered_wrapper(seed=11)
980+
m2 = BaseModel.deserialize(model.serialize())
981+
assert type(m2) is NativeSpinEnergyModel
982+
assert isinstance(m2, torch.nn.Module)
983+
m2 = m2.to(_env.DEVICE) # the concrete finetune failure: .to(DEVICE)
984+
assert hasattr(m2, "forward_common_lower_graph_exportable")
985+
m2 = m2.eval()
986+
generator = torch.Generator(device=_env.DEVICE).manual_seed(GLOBAL_SEED)
987+
cell = torch.rand(
988+
[3, 3], dtype=torch.float64, device=_env.DEVICE, generator=generator
989+
)
990+
cell = (cell + cell.T) + 5.0 * torch.eye(3, device=_env.DEVICE)
991+
coord = torch.matmul(
992+
torch.rand(
993+
[6, 3], dtype=torch.float64, device=_env.DEVICE, generator=generator
994+
),
995+
cell,
996+
).unsqueeze(0)
997+
atype = torch.tensor([[0, 0, 1, 0, 1, 1]], device=_env.DEVICE)
998+
spin = torch.rand(
999+
[1, 6, 3], dtype=torch.float64, device=_env.DEVICE, generator=generator
1000+
)
1001+
box = cell.unsqueeze(0)
1002+
r1 = model(coord, atype, spin, box=box)
1003+
r2 = m2(coord, atype, spin, box=box)
1004+
for key in ("energy", "force", "force_mag"):
1005+
torch.testing.assert_close(r1[key], r2[key], rtol=1e-12, atol=1e-12)

0 commit comments

Comments
 (0)