Tune Ewald

The tuning is based on the following error formulas:

\[\Delta F_\mathrm{real} \approx \frac{Q^2}{\sqrt{N}} \frac{2}{\sqrt{r_{\text{cutoff}} V}} e^{-r_{\text{cutoff}}^2 / 2 \sigma^2}\]
\[\Delta F_\mathrm{Fourier}^\mathrm{Ewald} \approx \frac{Q^2}{\sqrt{N}} \frac{\sqrt{2} / \sigma}{\pi\sqrt{2 V / h}} e^{-2\pi^2 \sigma^2 / h ^ 2}\]

where \(N\) is the number of charges, \(Q^2 = \sum_{i = 1}^N q_i^2\), is the sum of squared charges, \(r_{\text{cutoff}}\) is the short-range cutoff, \(V\) is the volume of the simulation box and \(h^2\) is the long range wavelength.

torchpme.tuning.tune_ewald(charges: Tensor, cell: Tensor, positions: Tensor, cutoff: float, neighbor_indices: Tensor, neighbor_distances: Tensor, exponent: int = 1, ns_lo: int = 1, ns_hi: int = 14, accuracy: float = 0.001, dtype: dtype | None = None, device: device | None = None) tuple[float, dict[str, Any], float][source]

Find the optimal parameters for torchpme.EwaldCalculator.

Note

The torchpme.tuning.ewald.EwaldErrorBounds.forward() method takes floats as the input, in order to be in consistency with the rest of the package – these parameters are always float but not torch.Tensor. This design, however, prevents the utilization of torch.autograd and other torch features. To take advantage of these features, one can use the torchpme.tuning.ewald.EwaldErrorBounds.err_rspace() and torchpme.tuning.ewald.EwaldErrorBounds.err_kspace(), which takes torch.Tensor as parameters.

Parameters:
  • charges (Tensor) – torch.Tensor, atomic (pseudo-)charges

  • cell (Tensor) – torch.Tensor, periodic supercell for the system

  • positions (Tensor) – torch.Tensor, Cartesian coordinates of the particles within the supercell.

  • cutoff (float) – float, cutoff distance for the neighborlist

  • exponent (int) – \(p\) in \(1/r^p\) potentials, currently only \(p=1\) is supported

  • neighbor_indices (Tensor) – torch.Tensor with the i,j indices of neighbors for which the potential should be computed in real space.

  • neighbor_distances (Tensor) – torch.Tensor with the pair distances of the neighbors for which the potential should be computed in real space.

  • ns_lo (int) – Minimum number of spatial resolution along each axis

  • ns_hi (int) – Maximum number of spatial resolution along each axis

  • accuracy (float) – Recomended values for a balance between the accuracy and speed is \(10^{-3}\). For more accurate results, use \(10^{-6}\).

  • dtype (dtype | None)

  • device (device | None)

Returns:

Tuple containing a float of the optimal smearing for the :class: CoulombPotential, and a dictionary with the parameters for EwaldCalculator, and the timing of this set of parameters.

Return type:

tuple[float, dict[str, Any], float]

Example

>>> import torch
>>> positions = torch.tensor(
...     [[0.0, 0.0, 0.0], [0.4, 0.4, 0.4]], dtype=torch.float64
... )
>>> charges = torch.tensor([[1.0], [-1.0]], dtype=torch.float64)
>>> cell = torch.eye(3, dtype=torch.float64)
>>> neighbor_distances = torch.tensor(
...     [0.9381, 0.9381, 0.8246, 0.9381, 0.8246, 0.8246, 0.6928],
...     dtype=torch.float64,
... )
>>> neighbor_indices = torch.tensor(
...     [[0, 1], [0, 1], [0, 1], [0, 1], [0, 1], [0, 1], [0, 1]]
... )
>>> smearing, parameter, timing = tune_ewald(
...     charges,
...     cell,
...     positions,
...     cutoff=1.0,
...     neighbor_distances=neighbor_distances,
...     neighbor_indices=neighbor_indices,
...     accuracy=1e-1,
... )
class torchpme.tuning.ewald.EwaldErrorBounds(charges: Tensor, cell: Tensor, positions: Tensor)[source]

Error bounds for torchpme.calculators.ewald.EwaldCalculator.

\[\text{Error}_{\text{total}} = \sqrt{\text{Error}_{\text{real space}}^2 + \text{Error}_{\text{Fourier space}}^2\]
Parameters:
  • charges (Tensor) – atomic charges

  • cell (Tensor) – single tensor of shape (3, 3), describing the bounding

  • positions (Tensor) – single tensor of shape (len(charges), 3) containing the Cartesian positions of all point charges in the system.

Example

>>> import torch
>>> positions = torch.tensor(
...     [[0.0, 0.0, 0.0], [0.4, 0.4, 0.4]], dtype=torch.float64
... )
>>> charges = torch.tensor([[1.0], [-1.0]], dtype=torch.float64)
>>> cell = torch.eye(3, dtype=torch.float64)
>>> error_bounds = EwaldErrorBounds(charges, cell, positions)
>>> print(error_bounds(smearing=1.0, lr_wavelength=0.5, cutoff=4.4))
tensor(8.4304e-05, dtype=torch.float64)
err_kspace(smearing: Tensor, lr_wavelength: Tensor) Tensor[source]

The Fourier space error of Ewald.

Parameters:
Return type:

Tensor

err_rspace(smearing: Tensor, cutoff: Tensor) Tensor[source]

The real space error of Ewald.

Parameters:
Return type:

Tensor

forward(smearing: float, lr_wavelength: float, cutoff: float) Tensor[source]

Calculate the error bound of Ewald.

Parameters:
Return type:

Tensor