| """ |
| Copyright (c) Facebook, Inc. and its affiliates. |
| |
| This source code is licensed under the MIT license found in the |
| LICENSE file in the root directory of this source tree. |
| """ |
|
|
| import logging |
|
|
| import torch |
| import torch.nn as nn |
| from torch_geometric.nn import radius_graph |
|
|
| from ..common.utils import ( |
| compute_neighbors, |
| conditional_grad, |
| get_pbc_distances, |
| radius_graph_pbc, |
| ) |
|
|
|
|
| class BaseModel(nn.Module): |
| def __init__(self, num_atoms=None, bond_feat_dim=None, num_targets=None): |
| super(BaseModel, self).__init__() |
| self.num_atoms = num_atoms |
| self.bond_feat_dim = bond_feat_dim |
| self.num_targets = num_targets |
|
|
| def forward(self, data): |
| raise NotImplementedError |
|
|
| def generate_graph( |
| self, |
| data, |
| cutoff=None, |
| max_neighbors=None, |
| use_pbc=None, |
| otf_graph=None, |
| ): |
| cutoff = cutoff or self.cutoff |
| max_neighbors = max_neighbors or self.max_neighbors |
| use_pbc = use_pbc or self.use_pbc |
| otf_graph = otf_graph or self.otf_graph |
|
|
| if not otf_graph: |
| try: |
| edge_index = data.edge_index |
|
|
| if use_pbc: |
| cell_offsets = data.cell_offsets |
| neighbors = data.neighbors |
|
|
| except AttributeError: |
| logging.warning( |
| "Turning otf_graph=True as required attributes not present in data object" |
| ) |
| otf_graph = True |
|
|
| if use_pbc: |
| if otf_graph: |
| edge_index, cell_offsets, neighbors = radius_graph_pbc( |
| data, cutoff, max_neighbors |
| ) |
|
|
| out = get_pbc_distances( |
| data.pos, |
| edge_index, |
| data.cell, |
| cell_offsets, |
| neighbors, |
| return_offsets=True, |
| return_distance_vec=True, |
| ) |
|
|
| edge_index = out["edge_index"] |
| edge_dist = out["distances"] |
| cell_offset_distances = out["offsets"] |
| distance_vec = out["distance_vec"] |
| else: |
| if otf_graph: |
| edge_index = radius_graph( |
| data.pos, |
| r=cutoff, |
| batch=data.batch, |
| max_num_neighbors=max_neighbors, |
| ) |
|
|
| j, i = edge_index |
| distance_vec = data.pos[j] - data.pos[i] |
|
|
| edge_dist = distance_vec.norm(dim=-1) |
| cell_offsets = torch.zeros( |
| edge_index.shape[1], 3, device=data.pos.device |
| ) |
| cell_offset_distances = torch.zeros_like( |
| cell_offsets, device=data.pos.device |
| ) |
| neighbors = compute_neighbors(data, edge_index) |
|
|
| return ( |
| edge_index, |
| edge_dist, |
| distance_vec, |
| cell_offsets, |
| cell_offset_distances, |
| neighbors, |
| ) |
|
|
| @property |
| def num_params(self): |
| return sum(p.numel() for p in self.parameters()) |
|
|