Skip to content

Commit

Permalink
Propper rendering of InversePowerLawPotential docs
Browse files Browse the repository at this point in the history
  • Loading branch information
PicoCentauri committed Aug 15, 2024
1 parent 9d94241 commit 37a8790
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 50 deletions.
6 changes: 6 additions & 0 deletions docs/src/references/lib/potentials.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Potentials
==========

.. automodule:: torchpme.lib.potentials
:members:
:undoc-members:
108 changes: 58 additions & 50 deletions src/torchpme/lib/potentials.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,14 @@ def gamma(x: torch.Tensor):


class InversePowerLawPotential:
"""
Class to handle inverse power-law potentials of the form 1/r^p, where r is a
distance parameter and p an exponent.
"""Inverse power-law potentials of the form :math:`1/r^p`.
Herem :math:`r` is a distance parameter and :math:`p` an exponent.
It can be used to compute:
1. the full 1/r^p potential
2. its short-range (SR) and long-range (LR) parts, the split being determined by a
1. the full :math:`1/r^p` potential
2. its short-range (SR) and long-range (LR) parts, the split being determined by a
length-scale parameter (called "smearing" in the code)
3. the Fourier transform of the LR part
Expand All @@ -30,17 +31,15 @@ def __init__(self, exponent: float):

def potential_from_dist(self, dist: torch.Tensor) -> torch.Tensor:
"""
Full 1/r^p potential as a function of r
Full :math:`1/r^p` potential as a function of :math:`r`.
:param dist: torch.tensor containing the distances at which the potential is to
be evaluated.
"""
return torch.pow(dist, -self.exponent)

def potential_from_dist_sq(self, dist_sq: torch.Tensor) -> torch.Tensor:
"""
Full 1/r^p potential as a function of r^2, which is more useful in some
implementations
"""Full :math:`1/r^p` potential as a function of :math:`r^2`.
:param dist_sq: torch.tensor containing the squared distances at which the
potential is to be evaluated.
Expand All @@ -50,52 +49,58 @@ def potential_from_dist_sq(self, dist_sq: torch.Tensor) -> torch.Tensor:
def potential_sr_from_dist(
self, dist: torch.Tensor, smearing: float
) -> torch.Tensor:
"""
Short-range (SR) part of the range-separated 1/r^p potential as a function of r.
More explicitly: it corresponds to V_SR(r) in 1/r^p = V_SR(r) + V_LR(r),
where the location of the split is determined by the smearing parameter.
r"""Short-range (SR) part of the range-separated :math:`1/r^p` potential.
More explicitly: it corresponds to `:math:`V_\mathrm{SR}(r)` in :math:`1/r^p =
V_\mathrm{SR}(r) + V_\mathrm{LR}(r)`, where the location of the split is
determined by the smearing parameter.
For the Coulomb potential, this would return
potential = erfc(dist / torch.sqrt(2.) / smearing) / dist
.. code-block:: python
potential = torch.erfc(dist / torch.sqrt(2.0) / smearing) / dist
:param dist: torch.tensor containing the distances at which the potential is to
be evaluated.
:param smearing: float containing the parameter often called "sigma" in
publications, which determines the length-scale at which the short-range and
long-range parts of the naive 1/r^p potential are separated. For the Coulomb
potential (p=1), this potential can be interpreted as the effective
potential generated by a Gaussian charge density, in which case this
smearing parameter corresponds to the "width" of the Gaussian.
long-range parts of the naive :math:`1/r^p` potential are separated. For the
Coulomb potential (:math:`p=1`), this potential can be interpreted as the
effective potential generated by a Gaussian charge density, in which case
this smearing parameter corresponds to the "width" of the Gaussian.
"""
exponent = torch.tensor(self.exponent, device=dist.device, dtype=dist.dtype)
x = 0.5 * dist**2 / smearing**2
peff = exponent / 2
prefac = 1.0 / (2 * smearing**2) ** peff
potential = prefac * gammaincc(peff, x) / x**peff

# potential = erfc(dist / torch.sqrt(torch.tensor(2.)) / smearing) / dist
return potential

def potential_lr_from_dist(
self, dist: torch.Tensor, smearing: float
) -> torch.Tensor:
"""
Long-range (LR) part of the range-separated 1/r^p potential as a function of r.
Used to subtract out the interior contributions after computing the LR part
in reciprocal (Fourier) space.
"""LR part of the range-separated :math:`1/r^p` potential.
Used to subtract out the interior contributions after computing the LR part in
reciprocal (Fourier) space.
For the Coulomb potential, this would return (note that the only change between
the SR and LR parts is the fact that erfc changes to erf)
potential = erf(dist / sqrt(2) / smearing) / dist
.. code-block:: python
potential = erf(dist / sqrt(2) / smearing) / dist
:param dist: torch.tensor containing the distances at which the potential is to
be evaluated.
:param smearing: float containing the parameter often called "sigma" in
publications, which determines the length-scale at which the short-range and
long-range parts of the naive 1/r^p potential are separated. For the Coulomb
potential (p=1), this potential can be interpreted as the effective
potential generated by a Gaussian charge density, in which case this
smearing parameter corresponds to the "width" of the Gaussian.
long-range parts of the naive :math:`1/r^p` potential are separated. For the
Coulomb potential (:math:`p=1`), this potential can be interpreted as the
effective potential generated by a Gaussian charge density, in which case
this smearing parameter corresponds to the "width" of the Gaussian.
"""
exponent = torch.tensor(self.exponent, device=dist.device, dtype=dist.dtype)
x = 0.5 * dist**2 / smearing**2
Expand All @@ -107,20 +112,23 @@ def potential_lr_from_dist(
def potential_fourier_from_k_sq(
self, k_sq: torch.Tensor, smearing: float
) -> torch.Tensor:
"""
Fourier transform of the long-range (LR) part potential parametrized in terms of
k^2.
If only the Coulomb potential is needed, the last line can be replaced by
fourier = 4 * torch.pi * torch.exp(-0.5 * smearing**2 * k_sq) / k_sq
"""Fourier transform of the LR part potential in terms of :math:`k^2`.
If only the Coulomb potential is needed, the last line can be
replaced by
.. code-block:: python
fourier = 4 * torch.pi * torch.exp(-0.5 * smearing**2 * k_sq) / k_sq
:param k_sq: torch.tensor containing the squared lengths (2-norms) of the wave
vectors k at which the Fourier-transformed potential is to be evaluated
:param smearing: float containing the parameter often called "sigma" in
publications, which determines the length-scale at which the short-range and
long-range parts of the naive 1/r^p potential are separated. For the Coulomb
potential (p=1), this potential can be interpreted as the effective
potential generated by a Gaussian charge density, in which case this
smearing parameter corresponds to the "width" of the Gaussian.
long-range parts of the naive :math:`1/r^p` potential are separated. For the
Coulomb potential (:math:`p=1`), this potential can be interpreted as the
effective potential generated by a Gaussian charge density, in which case
this smearing parameter corresponds to the "width" of the Gaussian.
"""
exponent = torch.tensor(self.exponent, device=k_sq.device, dtype=k_sq.dtype)
peff = (3 - exponent) / 2
Expand All @@ -131,21 +139,21 @@ def potential_fourier_from_k_sq(
return fourier

def potential_fourier_at_zero(self, smearing: float) -> torch.Tensor:
"""
The value of the Fourier-transformed potential (LR part implemented above) as
k --> 0 often needs to be set separately since for exponents p <= 3 = dimension,
there is a divergence to +infinity.
Setting this value manually to zero physically corresponds to the addition of a
uniform backgruond charge to make the system charge-neutral.
For p > 3, on the other hand, the Fourier-transformed LR potential does not
diverge as k --> 0, and one could instead assign the correct limit.
This is not implemented for now for consistency reasons.
r"""Value of the Fourier-transformed LR potential as :math:`k \rightarrow 0`.
This often needs to be set separately since for exponents `math:`p <= 3`
dimension, there is a divergence to +infinity. Setting this value manually to
zero physically corresponds to the addition of a uniform background charge to
make the system charge-neutral. For :math:`p > 3`, on the other hand, the
Fourier-transformed LR potential does not diverge as :math:`k \rightarrow 0`,
and one could instead assign the correct limit. This is not implemented for now
for consistency reasons.
:param smearing: float containing the parameter often called "sigma" in
publications, which determines the length-scale at which the short-range and
long-range parts of the naive 1/r^p potential are separated. For the Coulomb
potential (p=1), this potential can be interpreted as the effective
potential generated by a Gaussian charge density, in which case this
smearing parameter corresponds to the "width" of the Gaussian.
long-range parts of the naive :math:`1/r^p` potential are separated. For the
Coulomb potential (:math:`p=1`), this potential can be interpreted as the
effective potential generated by a Gaussian charge density, in which case
this smearing parameter corresponds to the "width" of the Gaussian.
"""
return torch.tensor(0.0)

0 comments on commit 37a8790

Please sign in to comment.