grid.protransform module#
Promolecular Grid Transformation.
- class grid.protransform.CubicProTransform(oned_grids, coeffs, exps, coords, boundary_epsilon=1e-12)#
Bases:
_HyperRectangleGridPromolecular 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,). Ifnu == 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_ptdoes 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_ptdoes not have shape(D,)or contains NaN values.
- property u_bnd#
float: Upper bound in theta space, corresponding to \(+\infty\) in real space.