grid.protransform module#

Promolecular Grid Transformation.

class grid.protransform.CubicProTransform(oned_grids, coeffs, exps, coords, boundary_epsilon=1e-12)#

Bases: _HyperRectangleGrid

Promolecular Grid Transformation of a Cubic Grid in \([-1, 1]^3\).

Grid is three-dimensional and modeled as Tensor Product of Three, one dimensional grids. Theta space is defined to be \([-1, 1]^3\). Real space is defined to be \(\mathbb{R}^3.\)

Attributes#

shape(int, int, int)

The number of points, including both of the end/boundary points, in x, y, and z direction.

prointegralfloat

The integration value of the promolecular density over Euclidean space.

promol_PromolParams

Data about the promolecular density.

pointsnp.ndarray(N, 3)

Grid points transformed to real space.

weightsnp.ndarray(N,)

The integration weights, multiplied by prointegral.

Methods#

integrate(trick=False)

Integral of a real-valued function over Euclidean space. Can use promolecular trick.

jacobian()

Jacobian of the transformation from Real space to Theta space \([-1, 1]^3\).

hessian()

Hessian of the transformation from Real space to Theta space \([-1, 1]^3\).

steepest_ascent_theta()

Map the real-space steepest-ascent direction to theta space.

transform():

Transform Real point to Theta space \([-1, 1]^3\).

inverse()

Transform Theta point to Real space \(\mathbb{R}^3\).

interpolate(use_log=False, nu=0)

Interpolate a function (or its logarithm) at a real point. Can interpolate its derivative.

Examples#

Define information of the Promolecular Density.

>>> c = np.array([[5.], [10.]])
>>> e = np.array([[2.], [3.]])
>>> coord = np.array([[0., 0., 0.], [2., 2., 2.]])

Define information of the grid and its weights.

>>> from grid.onedgrid import GaussChebyshev
>>> numb_x = 50

This is a grid in \([-1, 1]\).

>>> oned = GaussChebyshev(numb_x)

One dimensional grid is the same in all x, y, z directions.

>>> promol = CubicProTransform([oned, oned, oned], c, e, coord)

To integrate some function f.

>>> def f(pt):
...     return np.exp(-0.1 * np.linalg.norm(pt, axis=1) ** 2.)
>>> func_values = f(promol.points)
>>> print("The integral is %.4f" % promol.integrate(func_values, trick=False))

References#

Notes#

Let \(\rho^o(x, y, z) = \sum_{i=1}^M \sum_{j=1}^D e^{}\) be the Promolecular density of a linear combination of Gaussian functions.

The conditional distribution transformation from \(\mathbb{R}^3\) to \([-1, 1]^3\) transfers the (x, y, z) coordinates in \(\mathbb{R}^3\) to a set of coordinates, denoted as \((\theta_x, \theta_y, \theta_z)\), in \([-1,1]^3\) that are “bunched” up where \(\rho^o\) is large.

Precisely it is,

\[\begin{split}\begin{eqnarray} \theta_x(x) :&= -1 + 2 \frac{\int_{-\infty}^x \int \int \rho^o(x, y, z)dx dy dz } {\int \int \int \rho^o(x, y, z)dxdydz}\\ \theta_y(x, y) :&= -1 + 2 \frac{\int_{-\infty}^y \int \rho^o(x, y, z)dy dz } {\int \int \rho^o(x, y, z)dydz} \\ \theta_z(x, y, z) :&= -1 + 2 \frac{\int_{-\infty}^z \rho^o(x, y, z)dz } {\int \rho^o(x, y, z)dz}\\ \end{eqnarray}\end{split}\]

Integration of a integrable function \(f : \mathbb{R}^3 \rightarrow \mathbb{R}\) can be done as follows in theta space:

\[ \begin{align}\begin{aligned}\int \int \int f(x, y, z)dxdy dz \approx \frac{N}{8} \int_{-1}^1 \int_{-1}^1 \int_{-1}^1 \frac{f(\theta_x, \theta_y, \theta_z)} {\rho^o(\theta_x, \theta_y, \theta_z)} d\theta_x d\theta_y d\theta_z,\\\text{where } N = \int \int \int \rho^o(x, y, z) dx dy dz.\end{aligned}\end{align} \]

Note that this class always assumed the boundary of [-1, 1]^3 is always included.

gradient_to_theta(real_pt, real_gradient)#

Transform real-space gradient components to theta coordinates.

It returns the gradient of g in theta-space, given the gradient of f in real-space.

Given the inverse promolecular transformation from theta-space to real-space:

\[g(\boldsymbol{\theta}) = f(\mathbf{r}(\boldsymbol{\theta}))\]

then:

\[\nabla_{\boldsymbol{\theta}} g = J^{-T}\nabla_{\mathbf r} f\]

where \(J\) is the Jacobian matrix of the forward transformation from real space to theta space.

Parameters#

real_ptnp.ndarray, shape (3,)

Point in \(\mathbb{R}^3\).

real_gradientnp.ndarray, shape (3,)

Gradient of a function in real space with respect to x, y, z coordinates.

Returns#

theta_gradientnp.ndarray, shape (3,)

Gradient of a function in theta space with respect to theta coordinates.

Notes#

This transforms gradient components and does not map the real-space steepest-ascent direction.

See Also#

steepest_ascent_theta : Steepest-ascent direction.

hessian(real_pt)#

Return the Hessian of the transformation from real space to theta space.

The Hessian elements are defined as

\[H_{ijk} = \frac{\partial^2 \Theta_i} {\partial r_j \partial r_k}.\]

Since \(\Theta_i\) depends only on \(r_0, \ldots, r_i\), \(H_{ijk}=0\) if \(j>i\) or \(k>i\).

For the smooth Gaussian transformation, mixed partial derivatives commute,

\[H_{ijk} = H_{ikj}.\]

Parameters#

real_ptnp.ndarray(N,)

Real point in \(\mathbb{R}^N\).

Returns#

hessiannp.ndarray(N, N, N)

Hessian tensor of the transformation at the real point. The \(H_{ijk}\) entry is the second partial derivative of the \(i`th transformation function with respect to the :math:`j`th and :math:`k`th coordinates. Nonzero entries satisfy :math:`j \leq i\) and \(k \leq i\); for example, when \(i = 0\), only \(H_{000}\) can be nonzero.

integrate(*value_arrays, trick=False, tol=1e-10)#

Integrate any real-valued function on Euclidean space.

For an integrable function:

\[f : \mathbb{R}^3 \rightarrow \mathbb{R}\]

The integral is approximated as follows:

\[ \begin{align}\begin{aligned}\int \int \int f(x, y, z)dxdy dz \approx \frac{1}{8} N \int_{-1}^1 \int_{-1}^1 \int_{-1}^1 \frac{f(\theta_x, \theta_y, \theta_z)} {\rho^o(\theta_x, \theta_y, \theta_z)} d\theta_x d\theta_y d\theta_z,\\\text{where } N = \int \int \int \rho^o(x, y, z) dx dy dz.\end{aligned}\end{align} \]

Assumes the function decays faster than the promolecular density.

Parameters#

*value_arrays(np.ndarray(N, dtype=float),)

One or multiple value array to integrate.

trickbool, optional

If true, uses the promolecular trick.

tolfloat, optional

Integrand is set to zero whenever promolecular density is less than tolerance. Default value is 1e-10.

Returns#

float :

Return the integration of the function.

Raises#

TypeError

Input integrand is not of type np.ndarray.

ValueError

Input integrand array is given or not of proper shape.

interpolate(points, values, oned_grids, use_log=False, nu=0)#

Interpolate a function or its gradient at real-space points.

Parameters#

pointsnp.ndarray(M, 3)

Points in \(\mathbb{R}^3\) at which to interpolate.

valuesnp.ndarray(N,)

Function values at the tensor-product grid defined by oned_grids.

oned_gridslist[OneDGrid]

Three one-dimensional grids corresponding to the x, y, and z directions.

use_logbool, optional

If True, interpolate the logarithm of the function values.

nu{0, 1}, optional

Derivative order. If zero, interpolate the function values. If one, interpolate the real-space gradient.

Returns#

np.ndarray

If nu == 0, interpolated function values with shape (M,). If nu == 1, interpolated real-space gradients with shape (M, 3).

inverse(theta_pt)#

Transform a theta-space point to three-dimensional real space.

Parameters#

theta_ptnp.ndarray(3)

Point in \([-1, 1]^3\).

Returns#

real_ptnp.ndarray(3)

Point in \(\mathbb{R}^3\).

Raises#

ValueError

If theta_pt does not have shape (D,).

Notes#

Theta-space boundary values \(-1\) and \(1\) map to \(-\infty\) and \(+\infty\), respectively.

jacobian(real_pt)#

Return the Jacobian of the transformation from real space to theta space.

The Jacobian elements are defined as

\[J_{ij} = \frac{\partial \Theta_i}{\partial r_j}.\]

The transformation maps \(\mathbf{r} \in \mathbb{R}^D\) to \(\boldsymbol{\theta} \in [-1, 1]^D\) sequentially as

\[\Theta_i(r_i \mid \mathbf{r}_{<i}) = 2\frac{N_i(r_i, \mathbf{r}_{<i})}{D_i(\mathbf{r}_{<i})} - 1,\]

where

\[N_i(r_i, \mathbf{r}_{<i}) = \int_{-\infty}^{r_i} \int_{\mathbb{R}^{D-i-1}} \rho^o(\mathbf{r}_{<i}, s_i, \mathbf{s}_{>i}) \,d\mathbf{s}_{>i}\,ds_i,\]

and

\[D_i(\mathbf{r}_{<i}) = \int_{-\infty}^{\infty} \int_{\mathbb{R}^{D-i-1}} \rho^o(\mathbf{r}_{<i}, s_i, \mathbf{s}_{>i}) \,d\mathbf{s}_{>i}\,ds_i.\]

Since \(\Theta_i\) depends only on \(r_0, \ldots, r_i\), \(J_{ij}=0\) for \(j>i\). Therefore, the Jacobian is lower triangular:

\[\begin{split}\mathbf{J} = \begin{bmatrix} J_{00} & 0 & \cdots & 0 \\ J_{10} & J_{11} & \cdots & 0 \\ \vdots & \vdots & \ddots & \vdots \\ J_{D-1,0} & J_{D-1,1} & \cdots & J_{D-1,D-1} \end{bmatrix}.\end{split}\]

For the diagonal terms, \(D_i\) is independent of \(r_i\), so

\[J_{ii} = 2\frac{\partial_{r_i}N_i}{D_i}\]

For the off-diagonal terms, \(j<i\), both \(N_i\) and \(D_i\) depend on \(r_j\), giving

\[J_{ij} = 2 \frac{(\partial_{r_j}N_i)D_i - N_i(\partial_{r_j}D_i)}{D_i^2}.\]

Parameters#

real_ptnp.ndarray(D,)

Point in \(\mathbb{R}^D\) at which the Jacobian is evaluated.

Returns#

np.ndarray(D, D)

Jacobian \(\partial\boldsymbol{\theta}/\partial\mathbf{r}\) evaluated at real_pt.

property l_bnd#

float: Lower bound in theta space, corresponding to \(-\infty\) in real space.

property prointegral#

Return integration of Promolecular density.

property promol#

Return PromolParams data class.

steepest_ascent_theta(real_pt, real_grad)#

Map the real-space steepest-ascent direction to theta space.

The real-space gradient defines the steepest-ascent direction in real space. This direction is mapped to theta space using the Jacobian of the forward transformation.

Parameters#

real_ptnp.ndarray(3)

Point in \(\mathbb{R}^3\)

real_gradnp.ndarray(3)

Gradient of a function in real space.

Returns#

theta_directionnp.ndarray(3)

Theta-space image of the real-space steepest-ascent direction.

transform(real_pt)#

Transform a real-space point to theta space.

Parameters#

real_ptarray-like, shape (D,)

Real-space point in \(\mathbb{R}^D\).

Returns#

theta_ptndarray, shape (D,)

Transformed point in \([-1,1]^D\).

Raises#

ValueError

If real_pt does not have shape (D,) or contains NaN values.

property u_bnd#

float: Upper bound in theta space, corresponding to \(+\infty\) in real space.