class_docstr: Lattice is an object that describe the periodicity of the lattice.
  Note that this object does not know about atoms.
  For the integrated object between the lattice and atoms, please see Sol
  
  Examples
  --------
  >>> import torch
  >>> from deepchem.utils.dft_utils import Lattice
  >>> a = torch.tensor([[1., 0., 0.], [0., 1., 0.], [0., 0., 1.]])
  >>> lattice = Lattice(a)
  >>> lattice.lattice_vectors()
  tensor([[1., 0., 0.],
          [0., 1., 0.],
          [0., 0., 1.]])
  >>> lattice.recip_vectors()
  tensor([[6.2832, 0.0000, 0.0000],
          [0.0000, 6.2832, 0.0000],
          [0.0000, 0.0000, 6.2832]])
  >>> lattice.volume() # volume of the unit cell
  tensor(1.)
  >>> lattice.get_lattice_ls(1.0) # get the neighboring lattice vectors
  tensor([[ 0.,  0., -1.],
          [ 0., -1.,  0.],
          [-1.,  0.,  0.],
          [ 0.,  0.,  0.],
          [ 1.,  0.,  0.],
          [ 0.,  1.,  0.],
          [ 0.,  0.,  1.]])
  >>> lattice.get_gvgrids(6.0) # get the neighboring G-vectors
  (tensor([[ 0.0000,  0.0000, -6.2832],
          [ 0.0000, -6.2832,  0.0000],
          [-6.2832,  0.0000,  0.0000],
          [ 0.0000,  0.0000,  0.0000],
          [ 6.2832,  0.0000,  0.0000],
          [ 0.0000,  6.2832,  0.0000],
          [ 0.0000,  0.0000,  6.2832]]), tensor([1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000, 1.0000]))
  >>> lattice.estimate_ewald_eta(1e-5) # estimate the ewald's sum eta
  1.8
class_docstr_tok: ["Lattice","is","an","object","that","describe","the","periodicity","of","the","lattice",".","Note","that","this","object","does","not","know","about","atoms",".","For","the","integrated","object","between","the","lattice","and","atoms",",","please","see","Sol","Examples","--","--","--","--",">",">",">","import","torch",">",">",">","from","deepchem.utils.dft_utils","import","Lattice",">",">",">","a","=","torch.tensor","(","[","[","1.",",","0.",",","0",".","]",",","[","0.",",","1.",",","0",".","]",",","[","0.",",","0.",",","1",".","]","]",")",">",">",">","lattice","=","Lattice","(","a",")",">",">",">","lattice.lattice_vectors","(",")","tensor","(","[","[","1.",",","0.",",","0",".","]",",","[","0.",",","1.",",","0",".","]",",","[","0.",",","0.",",","1",".","]","]",")",">",">",">","lattice.recip_vectors","(",")","tensor","(","[","[","6.2832",",","0.0000",",","0.0000","]",",","[","0.0000",",","6.2832",",","0.0000","]",",","[","0.0000",",","0.0000",",","6.2832","]","]",")",">",">",">","lattice.volume","(",")","#","volume","of","the","unit","cell","tensor","(","1",".",")",">",">",">","lattice.get_lattice_ls","(","1.0",")","#","get","the","neighboring","lattice","vectors","tensor","(","[","[","0.",",","0.",",","-1",".","]",",","[","0.",",","-1.",",","0",".","]",",","[","-1.",",","0.",",","0",".","]",",","[","0.",",","0.",",","0",".","]",",","[","1.",",","0.",",","0",".","]",",","[","0.",",","1.",",","0",".","]",",","[","0.",",","0.",",","1",".","]","]",")",">",">",">","lattice.get_gvgrids","(","6.0",")","#","get","the","neighboring","G-vectors","(","tensor","(","[","[","0.0000",",","0.0000",",","-6.2832","]",",","[","0.0000",",","-6.2832",",","0.0000","]",",","[","-6.2832",",","0.0000",",","0.0000","]",",","[","0.0000",",","0.0000",",","0.0000","]",",","[","6.2832",",","0.0000",",","0.0000","]",",","[","0.0000",",","6.2832",",","0.0000","]",",","[","0.0000",",","0.0000",",","6.2832","]","]",")",",","tensor","(","[","1.0000",",","1.0000",",","1.0000",",","1.0000",",","1.0000",",","1.0000",",","1.0000","]",")",")",">",">",">","lattice.estimate_ewald_eta","(","1e-5",")","#","estimate","the","ewald","'s","sum","eta","1.8"]
docstr: generate the lattice vectors of multiply of a within the radius rcut.
  
  Parameters
  ----------
  a: torch.Tensor
      The lattice vectors with shape (ndim, ndim) with ndim == 3
  rcut: float
      The threshold of the distance from the main cell to be included
      in the neighbor.
  exclude_zeros: bool (default: False)
      If True, then it will exclude the vector that are all zeros.
  
  Returns
  -------
  ls: torch.Tensor
      Tensor with size `(nb, ndim)` containing the coordinates of the
      neighboring cells.
  
  Derived From pyscf:
  https://github.com/pyscf/pyscf/blob/e6c569932d5bab5e49994ae3dd365998fc5202b5/pyscf/pbc/tools/pbc.py#L473
docstr_tok: ["generate","the","lattice","vectors","of","multiply","of","a","within","the","radius","rcut",".","Parameters","--","--","--","--","--","a",":","torch.Tensor","The","lattice","vectors","with","shape","(","ndim",",","ndim",")","with","ndim","==","3","rcut",":","float","The","threshold","of","the","distance","from","the","main","cell","to","be","included","in","the","neighbor",".","exclude_zeros",":","bool","(","default",":","False",")","If","True",",","then","it","will","exclude","the","vector","that","are","all","zeros",".","Returns","--","--","--","-","ls",":","torch.Tensor","Tensor","with","size","`","(","nb",",","ndim",")","`","containing","the","coordinates","of","the","neighboring","cells",".","Derived","From","pyscf",":","https",":","\/\/github.com\/pyscf\/pyscf\/blob\/e6c569932d5bab5e49994ae3dd365998fc5202b5\/pyscf\/pbc\/tools\/pbc.py","#","L473"]
code: def _generate_lattice_vectors(
      self, a: torch.Tensor, rcut: float, exclude_zeros: bool
  ) -> torch.Tensor:
      """generate the lattice vectors of multiply of a within the radius rcut.
  
      Parameters
      ----------
      a: torch.Tensor
          The lattice vectors with shape (ndim, ndim) with ndim == 3
      rcut: float
          The threshold of the distance from the main cell to be included
          in the neighbor.
      exclude_zeros: bool (default: False)
          If True, then it will exclude the vector that are all zeros.
  
      Returns
      -------
      ls: torch.Tensor
          Tensor with size `(nb, ndim)` containing the coordinates of the
          neighboring cells.
  
      Derived From pyscf:
      https://github.com/pyscf/pyscf/blob/e6c569932d5bab5e49994ae3dd365998fc5202b5/pyscf/pbc/tools/pbc.py#L473
  
      """
      b = torch.inverse(a.transpose(-2, -1))
      heights_inv = torch.norm(b, dim=-1).detach().numpy()  # (ndim)
      nimgs = (rcut * heights_inv + 1.1).astype(np.int32)  # (ndim)
  
      n1_0 = torch.arange(
          -nimgs[0], nimgs[0] + 1, dtype=torch.int32, device=self.device
      )  # (nimgs2,)
      n1_1 = torch.arange(
          -nimgs[1], nimgs[1] + 1, dtype=torch.int32, device=self.device
      )  # (nimgs2,)
      n1_2 = torch.arange(
          -nimgs[2], nimgs[2] + 1, dtype=torch.int32, device=self.device
      )  # (nimgs2,)
      ls = n1_2[:, None] * a[0, :]  # (nimgs2, ndim)
      ls = ls + n1_1[:, None, None] * a[1, :]  # (nimgs2, nimgs2, ndim)
      ls = (
          ls + n1_0[:, None, None, None] * a[2, :]
      )  # (nimgs2, nimgs2, nimgs2, ndim)
      ls = ls.view(-1, ls.shape[-1])  # (nb, ndim)
  
      # drop ls that has norm > rcut * 1.05
      ls = ls[ls.norm(dim=-1) <= rcut * 1.05, :]  # (nb2, ndim)
  
      if exclude_zeros:
          ls = ls[torch.any(ls != 0, dim=-1), :]
  
      return ls
  
file_path: deepchem/deepchem/utils/dft_utils/hamilton/intor/lattice.py
imports: from typing import Tuple
  import torch
  import numpy
  from scipy.special import erfcinv
label_desc: Use image node_id 9 for calling the Lattice obj's underlying member method code with example usage: obj._generate_lattice_vectors(a, rcut, exclude_zeros) and returns: ls