diff --git a/deepmd/dpmodel/atomic_model/dp_atomic_model.py b/deepmd/dpmodel/atomic_model/dp_atomic_model.py index 178b286e79..cd349749fa 100644 --- a/deepmd/dpmodel/atomic_model/dp_atomic_model.py +++ b/deepmd/dpmodel/atomic_model/dp_atomic_model.py @@ -17,6 +17,9 @@ from deepmd.dpmodel.output_def import ( FittingOutputDef, ) +from deepmd.utils.version import ( + check_version_compatibility, +) from .base_atomic_model import ( BaseAtomicModel, @@ -132,6 +135,7 @@ def serialize(self) -> dict: return { "@class": "Model", "type": "standard", + "@version": 1, "type_map": self.type_map, "descriptor": self.descriptor.serialize(), "fitting": self.fitting.serialize(), @@ -140,6 +144,7 @@ def serialize(self) -> dict: @classmethod def deserialize(cls, data) -> "DPAtomicModel": data = copy.deepcopy(data) + check_version_compatibility(data.pop("@version", 1), 1, 1) data.pop("@class") data.pop("type") descriptor_obj = BaseDescriptor.deserialize(data["descriptor"]) diff --git a/deepmd/dpmodel/atomic_model/linear_atomic_model.py b/deepmd/dpmodel/atomic_model/linear_atomic_model.py index e1130eaf45..6d8aea499e 100644 --- a/deepmd/dpmodel/atomic_model/linear_atomic_model.py +++ b/deepmd/dpmodel/atomic_model/linear_atomic_model.py @@ -19,6 +19,9 @@ get_multiple_nlist_key, nlist_distinguish_types, ) +from deepmd.utils.version import ( + check_version_compatibility, +) from ..output_def import ( FittingOutputDef, @@ -185,6 +188,7 @@ def serialize(models) -> dict: return { "@class": "Model", "type": "linear", + "@version": 1, "models": [model.serialize() for model in models], "model_name": [model.__class__.__name__ for model in models], } @@ -192,6 +196,7 @@ def serialize(models) -> dict: @staticmethod def deserialize(data) -> List[BaseAtomicModel]: data = copy.deepcopy(data) + check_version_compatibility(data.pop("@version", 1), 1, 1) data.pop("@class") data.pop("type") model_names = data["model_name"] @@ -271,6 +276,7 @@ def serialize(self) -> dict: return { "@class": "Model", "type": "zbl", + "@version": 1, "models": LinearAtomicModel.serialize([self.dp_model, self.zbl_model]), "sw_rmin": self.sw_rmin, "sw_rmax": self.sw_rmax, @@ -280,6 +286,7 @@ def serialize(self) -> dict: @classmethod def deserialize(cls, data) -> "DPZBLLinearAtomicModel": data = copy.deepcopy(data) + check_version_compatibility(data.pop("@version", 1), 1, 1) data.pop("@class") data.pop("type") sw_rmin = data["sw_rmin"] diff --git a/deepmd/dpmodel/atomic_model/pairtab_atomic_model.py b/deepmd/dpmodel/atomic_model/pairtab_atomic_model.py index dc3dfaf2ed..ddece80f2d 100644 --- a/deepmd/dpmodel/atomic_model/pairtab_atomic_model.py +++ b/deepmd/dpmodel/atomic_model/pairtab_atomic_model.py @@ -16,6 +16,9 @@ from deepmd.utils.pair_tab import ( PairTab, ) +from deepmd.utils.version import ( + check_version_compatibility, +) from .base_atomic_model import ( BaseAtomicModel, @@ -109,6 +112,7 @@ def serialize(self) -> dict: return { "@class": "Model", "type": "pairtab", + "@version": 1, "tab": self.tab.serialize(), "rcut": self.rcut, "sel": self.sel, @@ -117,6 +121,7 @@ def serialize(self) -> dict: @classmethod def deserialize(cls, data) -> "PairTabAtomicModel": data = copy.deepcopy(data) + check_version_compatibility(data.pop("@version", 1), 1, 1) data.pop("@class") data.pop("type") rcut = data["rcut"] diff --git a/deepmd/dpmodel/descriptor/se_e2_a.py b/deepmd/dpmodel/descriptor/se_e2_a.py index a28215c35a..b102933ac9 100644 --- a/deepmd/dpmodel/descriptor/se_e2_a.py +++ b/deepmd/dpmodel/descriptor/se_e2_a.py @@ -9,6 +9,9 @@ from deepmd.utils.path import ( DPPath, ) +from deepmd.utils.version import ( + check_version_compatibility, +) try: from deepmd._version import version as __version__ @@ -345,6 +348,7 @@ def serialize(self) -> dict: return { "@class": "Descriptor", "type": "se_e2_a", + "@version": 1, "rcut": self.rcut, "rcut_smth": self.rcut_smth, "sel": self.sel, @@ -371,6 +375,7 @@ def serialize(self) -> dict: def deserialize(cls, data: dict) -> "DescrptSeA": """Deserialize from dict.""" data = copy.deepcopy(data) + check_version_compatibility(data.pop("@version", 1), 1, 1) data.pop("@class", None) data.pop("type", None) variables = data.pop("@variables") diff --git a/deepmd/dpmodel/descriptor/se_r.py b/deepmd/dpmodel/descriptor/se_r.py index 77e43f7d85..5973c55353 100644 --- a/deepmd/dpmodel/descriptor/se_r.py +++ b/deepmd/dpmodel/descriptor/se_r.py @@ -4,6 +4,9 @@ from deepmd.utils.path import ( DPPath, ) +from deepmd.utils.version import ( + check_version_compatibility, +) try: from deepmd._version import version as __version__ @@ -282,6 +285,7 @@ def serialize(self) -> dict: return { "@class": "Descriptor", "type": "se_r", + "@version": 1, "rcut": self.rcut, "rcut_smth": self.rcut_smth, "sel": self.sel, @@ -307,6 +311,7 @@ def serialize(self) -> dict: def deserialize(cls, data: dict) -> "DescrptSeR": """Deserialize from dict.""" data = copy.deepcopy(data) + check_version_compatibility(data.pop("@version", 1), 1, 1) data.pop("@class", None) data.pop("type", None) variables = data.pop("@variables") diff --git a/deepmd/dpmodel/fitting/general_fitting.py b/deepmd/dpmodel/fitting/general_fitting.py index 152836e928..752a550849 100644 --- a/deepmd/dpmodel/fitting/general_fitting.py +++ b/deepmd/dpmodel/fitting/general_fitting.py @@ -21,6 +21,9 @@ FittingNet, NetworkCollection, ) +from deepmd.utils.version import ( + check_version_compatibility, +) from .base_fitting import ( BaseFitting, @@ -210,6 +213,7 @@ def serialize(self) -> dict: """Serialize the fitting to dict.""" return { "@class": "Fitting", + "@version": 1, "var_name": self.var_name, "ntypes": self.ntypes, "dim_descrpt": self.dim_descrpt, @@ -241,6 +245,7 @@ def serialize(self) -> dict: @classmethod def deserialize(cls, data: dict) -> "GeneralFitting": data = copy.deepcopy(data) + check_version_compatibility(data.pop("@version", 1), 1, 1) data.pop("@class") data.pop("type") variables = data.pop("@variables") diff --git a/deepmd/dpmodel/utils/network.py b/deepmd/dpmodel/utils/network.py index 2133bc4889..feb3355e77 100644 --- a/deepmd/dpmodel/utils/network.py +++ b/deepmd/dpmodel/utils/network.py @@ -20,6 +20,10 @@ import h5py import numpy as np +from deepmd.utils.version import ( + check_version_compatibility, +) + try: from deepmd._version import version as __version__ except ImportError: @@ -189,6 +193,8 @@ def serialize(self) -> dict: "idt": self.idt, } return { + "@class": "Layer", + "@version": 1, "bias": self.b is not None, "use_timestep": self.idt is not None, "activation_function": self.activation_function, @@ -208,6 +214,8 @@ def deserialize(cls, data: dict) -> "NativeLayer": The dict to deserialize from. """ data = copy.deepcopy(data) + check_version_compatibility(data.pop("@version", 1), 1, 1) + data.pop("@class", None) variables = data.pop("@variables") assert variables["w"] is not None and len(variables["w"].shape) == 2 num_in, num_out = variables["w"].shape @@ -349,7 +357,11 @@ def serialize(self) -> dict: dict The serialized network. """ - return {"layers": [layer.serialize() for layer in self.layers]} + return { + "@class": "NN", + "@version": 1, + "layers": [layer.serialize() for layer in self.layers], + } @classmethod def deserialize(cls, data: dict) -> "NN": @@ -360,6 +372,9 @@ def deserialize(cls, data: dict) -> "NN": data : dict The dict to deserialize from. """ + data = data.copy() + check_version_compatibility(data.pop("@version", 1), 1, 1) + data.pop("@class", None) return cls(data["layers"]) def __getitem__(self, key): @@ -471,6 +486,8 @@ def serialize(self) -> dict: The serialized network. """ return { + "@class": "EmbeddingNetwork", + "@version": 1, "in_dim": self.in_dim, "neuron": self.neuron.copy(), "activation_function": self.activation_function, @@ -490,6 +507,8 @@ def deserialize(cls, data: dict) -> "EmbeddingNet": The dict to deserialize from. """ data = copy.deepcopy(data) + check_version_compatibility(data.pop("@version", 1), 1, 1) + data.pop("@class", None) layers = data.pop("layers") obj = cls(**data) super(EN, obj).__init__(layers) @@ -566,6 +585,8 @@ def serialize(self) -> dict: The serialized network. """ return { + "@class": "FittingNetwork", + "@version": 1, "in_dim": self.in_dim, "out_dim": self.out_dim, "neuron": self.neuron.copy(), @@ -586,6 +607,8 @@ def deserialize(cls, data: dict) -> "FittingNet": The dict to deserialize from. """ data = copy.deepcopy(data) + check_version_compatibility(data.pop("@version", 1), 1, 1) + data.pop("@class", None) layers = data.pop("layers") obj = cls(**data) T_Network.__init__(obj, layers) @@ -688,6 +711,8 @@ def serialize(self) -> dict: network_type_map_inv = {v: k for k, v in self.NETWORK_TYPE_MAP.items()} network_type_name = network_type_map_inv[self.network_type] return { + "@class": "NetworkCollection", + "@version": 1, "ndim": self.ndim, "ntypes": self.ntypes, "network_type": network_type_name, @@ -703,4 +728,7 @@ def deserialize(cls, data: dict) -> "NetworkCollection": data : dict The dict to deserialize from. """ + data = data.copy() + check_version_compatibility(data.pop("@version", 1), 1, 1) + data.pop("@class", None) return cls(**data) diff --git a/deepmd/pt/model/atomic_model/dp_atomic_model.py b/deepmd/pt/model/atomic_model/dp_atomic_model.py index 881ea4c97d..d2c1743d30 100644 --- a/deepmd/pt/model/atomic_model/dp_atomic_model.py +++ b/deepmd/pt/model/atomic_model/dp_atomic_model.py @@ -24,6 +24,9 @@ from deepmd.utils.path import ( DPPath, ) +from deepmd.utils.version import ( + check_version_compatibility, +) from .base_atomic_model import ( BaseAtomicModel, @@ -95,6 +98,7 @@ def serialize(self) -> dict: return { "@class": "Model", "type": "standard", + "@version": 1, "type_map": self.type_map, "descriptor": self.descriptor.serialize(), "fitting": self.fitting_net.serialize(), @@ -103,6 +107,7 @@ def serialize(self) -> dict: @classmethod def deserialize(cls, data) -> "DPAtomicModel": data = copy.deepcopy(data) + check_version_compatibility(data.pop("@version", 1), 1, 1) descriptor_obj = BaseDescriptor.deserialize(data["descriptor"]) fitting_obj = BaseFitting.deserialize(data["fitting"]) obj = cls(descriptor_obj, fitting_obj, type_map=data["type_map"]) diff --git a/deepmd/pt/model/atomic_model/linear_atomic_model.py b/deepmd/pt/model/atomic_model/linear_atomic_model.py index 68ff303d64..52f5f1d13c 100644 --- a/deepmd/pt/model/atomic_model/linear_atomic_model.py +++ b/deepmd/pt/model/atomic_model/linear_atomic_model.py @@ -1,4 +1,5 @@ # SPDX-License-Identifier: LGPL-3.0-or-later +import copy import sys from abc import ( abstractmethod, @@ -24,6 +25,9 @@ get_multiple_nlist_key, nlist_distinguish_types, ) +from deepmd.utils.version import ( + check_version_compatibility, +) from .base_atomic_model import ( BaseAtomicModel, @@ -206,6 +210,7 @@ def fitting_output_def(self) -> FittingOutputDef: def serialize(models) -> dict: return { "@class": "Model", + "@version": 1, "type": "linear", "models": [model.serialize() for model in models], "model_name": [model.__class__.__name__ for model in models], @@ -213,6 +218,8 @@ def serialize(models) -> dict: @staticmethod def deserialize(data) -> List[BaseAtomicModel]: + data = copy.deepcopy(data) + check_version_compatibility(data.pop("@version", 1), 1, 1) model_names = data["model_name"] models = [ getattr(sys.modules[__name__], name).deserialize(model) @@ -303,6 +310,7 @@ def serialize(self) -> dict: return { "@class": "Model", "type": "zbl", + "@version": 1, "models": LinearAtomicModel.serialize([self.dp_model, self.zbl_model]), "sw_rmin": self.sw_rmin, "sw_rmax": self.sw_rmax, @@ -311,6 +319,8 @@ def serialize(self) -> dict: @classmethod def deserialize(cls, data) -> "DPZBLLinearAtomicModel": + data = copy.deepcopy(data) + check_version_compatibility(data.pop("@version", 1), 1, 1) sw_rmin = data["sw_rmin"] sw_rmax = data["sw_rmax"] smin_alpha = data["smin_alpha"] diff --git a/deepmd/pt/model/atomic_model/pairtab_atomic_model.py b/deepmd/pt/model/atomic_model/pairtab_atomic_model.py index 86bfe98c36..c0b7c65d7a 100644 --- a/deepmd/pt/model/atomic_model/pairtab_atomic_model.py +++ b/deepmd/pt/model/atomic_model/pairtab_atomic_model.py @@ -1,4 +1,5 @@ # SPDX-License-Identifier: LGPL-3.0-or-later +import copy from typing import ( Dict, List, @@ -15,6 +16,9 @@ from deepmd.utils.pair_tab import ( PairTab, ) +from deepmd.utils.version import ( + check_version_compatibility, +) from .base_atomic_model import ( BaseAtomicModel, @@ -124,6 +128,7 @@ def serialize(self) -> dict: return { "@class": "Model", "type": "pairtab", + "@version": 1, "tab": self.tab.serialize(), "rcut": self.rcut, "sel": self.sel, @@ -131,6 +136,8 @@ def serialize(self) -> dict: @classmethod def deserialize(cls, data) -> "PairTabAtomicModel": + data = copy.deepcopy(data) + check_version_compatibility(data.pop("@version", 1), 1, 1) rcut = data["rcut"] sel = data["sel"] tab = PairTab.deserialize(data["tab"]) diff --git a/deepmd/pt/model/descriptor/se_a.py b/deepmd/pt/model/descriptor/se_a.py index 033d640ad8..6c29636d6d 100644 --- a/deepmd/pt/model/descriptor/se_a.py +++ b/deepmd/pt/model/descriptor/se_a.py @@ -31,6 +31,9 @@ from deepmd.utils.path import ( DPPath, ) +from deepmd.utils.version import ( + check_version_compatibility, +) try: from typing import ( @@ -182,6 +185,7 @@ def serialize(self) -> dict: return { "@class": "Descriptor", "type": "se_e2_a", + "@version": 1, "rcut": obj.rcut, "rcut_smth": obj.rcut_smth, "sel": obj.sel, @@ -208,6 +212,7 @@ def serialize(self) -> dict: @classmethod def deserialize(cls, data: dict) -> "DescrptSeA": data = data.copy() + check_version_compatibility(data.pop("@version", 1), 1, 1) data.pop("@class", None) data.pop("type", None) variables = data.pop("@variables") diff --git a/deepmd/pt/model/descriptor/se_r.py b/deepmd/pt/model/descriptor/se_r.py index c685640426..bdb7dafe73 100644 --- a/deepmd/pt/model/descriptor/se_r.py +++ b/deepmd/pt/model/descriptor/se_r.py @@ -36,6 +36,9 @@ from deepmd.utils.path import ( DPPath, ) +from deepmd.utils.version import ( + check_version_compatibility, +) from .base_descriptor import ( BaseDescriptor, @@ -277,6 +280,7 @@ def serialize(self) -> dict: return { "@class": "Descriptor", "type": "se_r", + "@version": 1, "rcut": self.rcut, "rcut_smth": self.rcut_smth, "sel": self.sel, @@ -302,6 +306,7 @@ def serialize(self) -> dict: @classmethod def deserialize(cls, data: dict) -> "DescrptSeR": data = data.copy() + check_version_compatibility(data.pop("@version", 1), 1, 1) variables = data.pop("@variables") embeddings = data.pop("embeddings") env_mat = data.pop("env_mat") diff --git a/deepmd/pt/model/task/fitting.py b/deepmd/pt/model/task/fitting.py index 6c395d3800..0c64983f60 100644 --- a/deepmd/pt/model/task/fitting.py +++ b/deepmd/pt/model/task/fitting.py @@ -43,6 +43,9 @@ to_numpy_array, to_torch_tensor, ) +from deepmd.utils.version import ( + check_version_compatibility, +) dtype = env.GLOBAL_PT_FLOAT_PRECISION device = env.DEVICE @@ -367,6 +370,7 @@ def serialize(self) -> dict: """Serialize the fitting to dict.""" return { "@class": "Fitting", + "@version": 1, "var_name": self.var_name, "ntypes": self.ntypes, "dim_descrpt": self.dim_descrpt, @@ -404,6 +408,7 @@ def serialize(self) -> dict: @classmethod def deserialize(cls, data: dict) -> "GeneralFitting": data = copy.deepcopy(data) + check_version_compatibility(data.pop("@version", 1), 1, 1) variables = data.pop("@variables") nets = data.pop("nets") obj = cls(**data) diff --git a/deepmd/tf/descriptor/se_a.py b/deepmd/tf/descriptor/se_a.py index e1b7258c63..0e15ba13a8 100644 --- a/deepmd/tf/descriptor/se_a.py +++ b/deepmd/tf/descriptor/se_a.py @@ -65,6 +65,9 @@ from deepmd.tf.utils.type_embed import ( embed_atom_type, ) +from deepmd.utils.version import ( + check_version_compatibility, +) from .descriptor import ( Descriptor, @@ -1368,6 +1371,7 @@ def deserialize(cls, data: dict, suffix: str = ""): if cls is not DescrptSeA: raise NotImplementedError("Not implemented in class %s" % cls.__name__) data = data.copy() + check_version_compatibility(data.pop("@version", 1), 1, 1) data.pop("@class", None) data.pop("type", None) embedding_net_variables = cls.deserialize_network( @@ -1422,6 +1426,7 @@ def serialize(self, suffix: str = "") -> dict: return { "@class": "Descriptor", "type": "se_e2_a", + "@version": 1, "rcut": self.rcut_r, "rcut_smth": self.rcut_r_smth, "sel": self.sel_a, diff --git a/deepmd/tf/descriptor/se_r.py b/deepmd/tf/descriptor/se_r.py index 1a12befdf0..ba1a261390 100644 --- a/deepmd/tf/descriptor/se_r.py +++ b/deepmd/tf/descriptor/se_r.py @@ -38,6 +38,9 @@ from deepmd.tf.utils.tabulate import ( DPTabulate, ) +from deepmd.utils.version import ( + check_version_compatibility, +) from .descriptor import ( Descriptor, @@ -720,6 +723,7 @@ def deserialize(cls, data: dict, suffix: str = ""): if cls is not DescrptSeR: raise NotImplementedError("Not implemented in class %s" % cls.__name__) data = data.copy() + check_version_compatibility(data.pop("@version", 1), 1, 1) embedding_net_variables = cls.deserialize_network( data.pop("embeddings"), suffix=suffix ) @@ -763,6 +767,7 @@ def serialize(self, suffix: str = "") -> dict: return { "@class": "Descriptor", "type": "se_r", + "@version": 1, "rcut": self.rcut, "rcut_smth": self.rcut_smth, "sel": self.sel_r, diff --git a/deepmd/tf/fit/dipole.py b/deepmd/tf/fit/dipole.py index 3557d00aa0..f503789308 100644 --- a/deepmd/tf/fit/dipole.py +++ b/deepmd/tf/fit/dipole.py @@ -30,6 +30,9 @@ one_layer, one_layer_rand_seed_shift, ) +from deepmd.utils.version import ( + check_version_compatibility, +) @Fitting.register("dipole") @@ -346,6 +349,7 @@ def serialize(self, suffix: str) -> dict: data = { "@class": "Fitting", "type": "dipole", + "@version": 1, "var_name": "dipole", "ntypes": self.ntypes, "dim_descrpt": self.dim_descrpt, @@ -388,6 +392,8 @@ def deserialize(cls, data: dict, suffix: str): Model The deserialized model """ + data = data.copy() + check_version_compatibility(data.pop("@version", 1), 1, 1) fitting = cls(**data) fitting.fitting_net_variables = cls.deserialize_network( data["nets"], diff --git a/deepmd/tf/fit/ener.py b/deepmd/tf/fit/ener.py index 0cdd1a1676..106e10839d 100644 --- a/deepmd/tf/fit/ener.py +++ b/deepmd/tf/fit/ener.py @@ -53,6 +53,9 @@ from deepmd.tf.utils.spin import ( Spin, ) +from deepmd.utils.version import ( + check_version_compatibility, +) if TYPE_CHECKING: pass @@ -959,6 +962,8 @@ def deserialize(cls, data: dict, suffix: str = ""): Model The deserialized model """ + data = data.copy() + check_version_compatibility(data.pop("@version", 1), 1, 1) fitting = cls(**data) fitting.fitting_net_variables = cls.deserialize_network( data["nets"], @@ -984,6 +989,7 @@ def serialize(self, suffix: str = "") -> dict: data = { "@class": "Fitting", "type": "ener", + "@version": 1, "var_name": "energy", "ntypes": self.ntypes, "dim_descrpt": self.dim_descrpt, diff --git a/deepmd/tf/fit/polar.py b/deepmd/tf/fit/polar.py index f5cebf9a39..002082ad2e 100644 --- a/deepmd/tf/fit/polar.py +++ b/deepmd/tf/fit/polar.py @@ -34,6 +34,9 @@ one_layer, one_layer_rand_seed_shift, ) +from deepmd.utils.version import ( + check_version_compatibility, +) @Fitting.register("polar") @@ -536,6 +539,7 @@ def serialize(self, suffix: str) -> dict: data = { "@class": "Fitting", "type": "polar", + "@version": 1, "var_name": "polar", "ntypes": self.ntypes, "dim_descrpt": self.dim_descrpt, @@ -581,6 +585,8 @@ def deserialize(cls, data: dict, suffix: str): Model The deserialized model """ + data = data.copy() + check_version_compatibility(data.pop("@version", 1), 1, 1) fitting = cls(**data) fitting.fitting_net_variables = cls.deserialize_network( data["nets"], diff --git a/deepmd/tf/model/model.py b/deepmd/tf/model/model.py index 2ae2879226..889f7ccc4d 100644 --- a/deepmd/tf/model/model.py +++ b/deepmd/tf/model/model.py @@ -63,6 +63,9 @@ from deepmd.utils.plugin import ( make_plugin_registry, ) +from deepmd.utils.version import ( + check_version_compatibility, +) class Model(ABC, make_plugin_registry("model")): @@ -778,7 +781,7 @@ def deserialize(cls, data: dict, suffix: str = "") -> "Descriptor": The deserialized descriptor """ data = copy.deepcopy(data) - + check_version_compatibility(data.pop("@version", 1), 1, 1) descriptor = Descriptor.deserialize(data.pop("descriptor"), suffix=suffix) fitting = Fitting.deserialize(data.pop("fitting"), suffix=suffix) return cls( @@ -807,6 +810,7 @@ def serialize(self, suffix: str = "") -> dict: return { "@class": "Model", "type": "standard", + "@version": 1, "type_map": self.type_map, "descriptor": self.descrpt.serialize(suffix=suffix), "fitting": self.fitting.serialize(suffix=suffix), diff --git a/deepmd/utils/pair_tab.py b/deepmd/utils/pair_tab.py index b807354171..1b397a3cfa 100644 --- a/deepmd/utils/pair_tab.py +++ b/deepmd/utils/pair_tab.py @@ -12,6 +12,10 @@ CubicSpline, ) +from deepmd.utils.version import ( + check_version_compatibility, +) + log = logging.getLogger(__name__) @@ -72,6 +76,8 @@ def reinit(self, filename: str, rcut: Optional[float] = None) -> None: def serialize(self) -> dict: return { + "@class": "PairTab", + "@version": 1, "rmin": self.rmin, "rmax": self.rmax, "hh": self.hh, @@ -87,6 +93,9 @@ def serialize(self) -> dict: @classmethod def deserialize(cls, data) -> "PairTab": + data = data.copy() + check_version_compatibility(data.pop("@version", 1), 1, 1) + data.pop("@class") variables = data.pop("@variables") tab = PairTab(None, None) tab.vdata = variables["vdata"] diff --git a/deepmd/utils/version.py b/deepmd/utils/version.py new file mode 100644 index 0000000000..a0b479778d --- /dev/null +++ b/deepmd/utils/version.py @@ -0,0 +1,27 @@ +# SPDX-License-Identifier: LGPL-3.0-or-later +def check_version_compatibility( + current_version: int, + maximum_supported_version: int, + minimal_supported_version: int = 1, +): + """Check if the current version is compatible with the supported versions. + + Parameters + ---------- + current_version : int + The current version. + maximum_supported_version : int + The maximum supported version. + minimal_supported_version : int, optional + The minimal supported version. Default is 1. + + Raises + ------ + ValueError + If the current version is not compatible with the supported versions. + """ + if not minimal_supported_version <= current_version <= maximum_supported_version: + raise ValueError( + f"Current version {current_version} is not compatible with supported versions " + f"[{minimal_supported_version}, {maximum_supported_version}]." + )