import torch from onescience.datapipes.materials.nequip import AtomicDataDict from ._graph_mixin import GraphModuleMixin from .model_modifier_utils import replace_submodules, model_modifier class GhostExchangeModule(GraphModuleMixin, torch.nn.Module): """Base class for ghost atom exchange modules.""" def __init__( self, field: str = AtomicDataDict.NODE_FEATURES_KEY, irreps_in={}, ): super().__init__() self.field = field self._init_irreps( irreps_in=irreps_in, my_irreps_in={field: irreps_in[field]}, irreps_out={field: irreps_in[field]}, ) def forward( self, data: AtomicDataDict.Type, ghost_included: bool, ) -> AtomicDataDict.Type: raise NotImplementedError("Subclasses must implement forward method") class NoOpGhostExchangeModule(GhostExchangeModule): """Base ghost exchange module that performs a no-op.""" def forward( self, data: AtomicDataDict.Type, ghost_included: bool, ) -> AtomicDataDict.Type: return data @model_modifier(persistent=True, private=True) @classmethod def enable_LAMMPSMLIAPGhostExchange(cls, model): """Enable LAMMPS ML-IAP ghost exchange for inference in LAMMPS ML-IAP.""" from ._ghost_exchange_lmp_mliap import LAMMPSMLIAPGhostExchangeModule def factory(old): new = LAMMPSMLIAPGhostExchangeModule( field=old.field, irreps_in=old.irreps_in, ) return new return replace_submodules(model, cls, factory)