Inter-particle distances
Table of Contents
1. Squared distance
1.1. qmckl_distance_sq
The qmckl_distance_sq function computes the matrix of squared Euclidean
distances between all pairs of points from two sets. For each point in set A
and each point in set B, it calculates the squared distance, which avoids the
computational cost of square root operations that would be needed for actual
distances. In many quantum chemistry applications, squared distances are
directly needed (e.g., in Gaussian functions), making this an efficient choice.
The function computes:
\[ C_{ij} = \sum_{k=1}^3 (A_{k,i}-B_{k,j})^2 \]
where \(A\) and \(B\) are sets of 3D points and \(C\) is the resulting distance matrix.
The function supports both normal and transposed input matrices through the
transa and transb parameters, allowing efficient handling of data in
different memory layouts.
| Variable | Type | In/Out | Description |
|---|---|---|---|
context |
qmckl_context |
in | Global state |
transa |
char |
in | Array A is 'N': Normal, 'T': Transposed |
transb |
char |
in | Array B is 'N': Normal, 'T': Transposed |
m |
int64_t |
in | Number of points in the first set |
n |
int64_t |
in | Number of points in the second set |
A |
double[][lda] |
in | Array containing the \(m \times 3\) matrix \(A\) |
lda |
int64_t |
in | Leading dimension of array A |
B |
double[][ldb] |
in | Array containing the \(n \times 3\) matrix \(B\) |
ldb |
int64_t |
in | Leading dimension of array B |
C |
double[n][ldc] |
out | Array containing the \(m \times n\) matrix \(C\) |
ldc |
int64_t |
in | Leading dimension of array C |
Requirements:
contextis notQMCKL_NULL_CONTEXTm > 0n > 0lda >= 3iftransa == 'N'lda >= miftransa == 'T'ldb >= 3iftransb == 'N'ldb >= niftransb == 'T'ldc >= mAis allocated with at least \(3 \times m \times 8\) bytesBis allocated with at least \(3 \times n \times 8\) bytesCis allocated with at least \(m \times n \times 8\) bytes
qmckl_exit_code qmckl_distance_sq ( const qmckl_context context, const char transa, const char transb, const int64_t m, const int64_t n, const double* A, const int64_t lda, const double* B, const int64_t ldb, double* const C, const int64_t ldc );
function qmckl_distance_sq(context, transa, transb, m, n, & A, LDA, B, LDB, C, LDC) & bind(C) result(info) use qmckl_constants implicit none integer (qmckl_context) , intent(in) , value :: context character(c_char) , intent(in) , value :: transa character(c_char) , intent(in) , value :: transb integer (c_int64_t) , intent(in) , value :: m integer (c_int64_t) , intent(in) , value :: n integer (c_int64_t) , intent(in) , value :: lda integer (c_int64_t) , intent(in) , value :: ldb integer (c_int64_t) , intent(in) , value :: ldc real (c_double ) , intent(in) :: A(lda,*) real (c_double ) , intent(in) :: B(ldb,*) real (c_double ) , intent(out) :: C(ldc,n) integer(qmckl_exit_code) :: info integer*8 :: i,j real*8 :: x, y, z integer :: transab info = QMCKL_SUCCESS if (context == QMCKL_NULL_CONTEXT) then info = QMCKL_INVALID_CONTEXT return endif if (m <= 0_8) then info = QMCKL_INVALID_ARG_4 return endif if (n <= 0_8) then info = QMCKL_INVALID_ARG_5 return endif if (transa == 'N' .or. transa == 'n') then transab = 0 else if (transa == 'T' .or. transa == 't') then transab = 1 else transab = -100 endif if (transb == 'N' .or. transb == 'n') then continue else if (transb == 'T' .or. transb == 't') then transab = transab + 2 else transab = -100 endif if (transab < 0) then info = QMCKL_INVALID_ARG_1 return endif if (iand(transab,1) == 0 .and. LDA < 3) then info = QMCKL_INVALID_ARG_7 return endif if (iand(transab,1) == 1 .and. LDA < m) then info = QMCKL_INVALID_ARG_7 return endif if (iand(transab,2) == 0 .and. LDB < 3) then info = QMCKL_INVALID_ARG_7 return endif if (iand(transab,2) == 2 .and. LDB < n) then info = QMCKL_INVALID_ARG_7 return endif select case (transab) case(0) do j=1,n do i=1,m x = A(1,i) - B(1,j) y = A(2,i) - B(2,j) z = A(3,i) - B(3,j) C(i,j) = x*x + y*y + z*z end do end do case(1) do j=1,n do i=1,m x = A(i,1) - B(1,j) y = A(i,2) - B(2,j) z = A(i,3) - B(3,j) C(i,j) = x*x + y*y + z*z end do end do case(2) do j=1,n do i=1,m x = A(1,i) - B(j,1) y = A(2,i) - B(j,2) z = A(3,i) - B(j,3) C(i,j) = x*x + y*y + z*z end do end do case(3) do j=1,n do i=1,m x = A(i,1) - B(j,1) y = A(i,2) - B(j,2) z = A(i,3) - B(j,3) C(i,j) = x*x + y*y + z*z end do end do end select end function qmckl_distance_sq
1.1.1. Performance
This function is more efficient when A and B are
transposed.
2. Distance
2.1. qmckl_distance
qmckl_distance computes the matrix of the distances between all
pairs of points in two sets, one point within each set:
\[ C_{ij} = \sqrt{\sum_{k=1}^3 (A_{k,i}-B_{k,j})^2} \]
If the input array is normal ('N'), the xyz coordinates are in
the leading dimension: [n][3] in C and (3,n) in Fortran.
| Variable | Type | In/Out | Description |
|---|---|---|---|
context |
qmckl_context |
in | Global state |
transa |
char |
in | Array A is 'N': Normal, 'T': Transposed |
transb |
char |
in | Array B is 'N': Normal, 'T': Transposed |
m |
int64_t |
in | Number of points in the first set |
n |
int64_t |
in | Number of points in the second set |
A |
double[][lda] |
in | Array containing the \(m \times 3\) matrix \(A\) |
lda |
int64_t |
in | Leading dimension of array A |
B |
double[][ldb] |
in | Array containing the \(n \times 3\) matrix \(B\) |
ldb |
int64_t |
in | Leading dimension of array B |
C |
double[n][ldc] |
out | Array containing the \(m \times n\) matrix \(C\) |
ldc |
int64_t |
in | Leading dimension of array C |
2.1.1. Requirements
contextis notQMCKL_NULL_CONTEXTm > 0n > 0lda >= 3iftransa == 'N'lda >= miftransa == 'T'ldb >= 3iftransb == 'N'ldb >= niftransb == 'T'ldc >= mAis allocated with at least \(3 \times m \times 8\) bytesBis allocated with at least \(3 \times n \times 8\) bytesCis allocated with at least \(m \times n \times 8\) bytes
2.1.2. C header
qmckl_exit_code qmckl_distance ( const qmckl_context context, const char transa, const char transb, const int64_t m, const int64_t n, const double* A, const int64_t lda, const double* B, const int64_t ldb, double* const C, const int64_t ldc );
2.1.3. Source
function qmckl_distance(context, transa, transb, m, n, & A, LDA, B, LDB, C, LDC) & bind(C) result(info) use qmckl_constants implicit none integer(qmckl_context), intent(in), value :: context character(c_char) , intent(in) , value :: transa character(c_char) , intent(in) , value :: transb integer (c_int64_t) , intent(in) , value :: m integer (c_int64_t) , intent(in) , value :: n integer (c_int64_t) , intent(in) , value :: lda integer (c_int64_t) , intent(in) , value :: ldb integer (c_int64_t) , intent(in) , value :: ldc real (c_double ) , intent(in) :: A(lda,*) real (c_double ) , intent(in) :: B(ldb,*) real (c_double ) , intent(out) :: C(ldc,n) integer (qmckl_exit_code) :: info integer*8 :: i,j real*8 :: x, y, z integer :: transab info = QMCKL_SUCCESS if (context == QMCKL_NULL_CONTEXT) then info = QMCKL_INVALID_CONTEXT return endif if (m <= 0_8) then info = QMCKL_INVALID_ARG_4 return endif if (n <= 0_8) then info = QMCKL_INVALID_ARG_5 return endif if (transa == 'N' .or. transa == 'n') then transab = 0 else if (transa == 'T' .or. transa == 't') then transab = 1 else transab = -100 endif if (transb == 'N' .or. transb == 'n') then continue else if (transb == 'T' .or. transb == 't') then transab = transab + 2 else transab = -100 endif if (transab < 0) then info = QMCKL_INVALID_ARG_1 return endif ! check for LDA if (iand(transab,1) == 0 .and. LDA < 3) then info = QMCKL_INVALID_ARG_7 return endif if (iand(transab,1) == 1 .and. LDA < m) then info = QMCKL_INVALID_ARG_7 return endif ! check for LDB if (iand(transab,1) == 0 .and. LDB < 3) then info = QMCKL_INVALID_ARG_9 return endif if (iand(transab,1) == 1 .and. LDB < n) then info = QMCKL_INVALID_ARG_9 return endif ! check for LDC if (LDC < m) then info = QMCKL_INVALID_ARG_11 return endif select case (transab) case(0) do j=1,n do i=1,m x = A(1,i) - B(1,j) y = A(2,i) - B(2,j) z = A(3,i) - B(3,j) C(i,j) = x*x + y*y + z*z end do C(:,j) = dsqrt(C(:,j)) end do case(1) do j=1,n do i=1,m x = A(i,1) - B(1,j) y = A(i,2) - B(2,j) z = A(i,3) - B(3,j) C(i,j) = x*x + y*y + z*z end do C(:,j) = dsqrt(C(:,j)) end do case(2) do j=1,n do i=1,m x = A(1,i) - B(j,1) y = A(2,i) - B(j,2) z = A(3,i) - B(j,3) C(i,j) = x*x + y*y + z*z end do C(:,j) = dsqrt(C(:,j)) end do case(3) do j=1,n do i=1,m x = A(i,1) - B(j,1) y = A(i,2) - B(j,2) z = A(i,3) - B(j,3) C(i,j) = x*x + y*y + z*z end do C(:,j) = dsqrt(C(:,j)) end do end select end function qmckl_distance
2.1.4. Performance
This function is more efficient when A and B are transposed.
3. Rescaled Distance
3.1. qmckl_distance_rescaled
qmckl_distance_rescaled computes the matrix of the rescaled distances between all
pairs of points in two sets, one point within each set:
\[ C_{ij} = \frac{ 1 - e^{-\kappa r_{ij}}}{\kappa} \]
If the input array is normal ('N'), the xyz coordinates are in
the leading dimension: [n][3] in C and (3,n) in Fortran.
| Variable | Type | In/Out | Description |
|---|---|---|---|
context |
qmckl_context |
in | Global state |
transa |
char |
in | Array A is 'N': Normal, 'T': Transposed |
transb |
char |
in | Array B is 'N': Normal, 'T': Transposed |
m |
int64_t |
in | Number of points in the first set |
n |
int64_t |
in | Number of points in the second set |
A |
double[][lda] |
in | Array containing the \(m \times 3\) matrix \(A\) |
lda |
int64_t |
in | Leading dimension of array A |
B |
double[][ldb] |
in | Array containing the \(n \times 3\) matrix \(B\) |
ldb |
int64_t |
in | Leading dimension of array B |
C |
double[n][ldc] |
out | Array containing the \(m \times n\) matrix \(C\) |
ldc |
int64_t |
in | Leading dimension of array C |
rescale_factor_kappa |
double |
in | Factor for calculating rescaled distances |
3.1.1. Requirements
contextis notQMCKL_NULL_CONTEXTm > 0n > 0lda >= 3iftransa == 'N'lda >= miftransa == 'T'ldb >= 3iftransb == 'N'ldb >= niftransb == 'T'ldc >= mAis allocated with at least \(3 \times m \times 8\) bytesBis allocated with at least \(3 \times n \times 8\) bytesCis allocated with at least \(m \times n \times 8\) bytes
3.1.2. C header
qmckl_exit_code qmckl_distance_rescaled ( const qmckl_context context, const char transa, const char transb, const int64_t m, const int64_t n, const double* A, const int64_t lda, const double* B, const int64_t ldb, double* const C, const int64_t ldc, const double rescale_factor_kappa );
3.1.3. Source
function qmckl_distance_rescaled(context, transa, transb, m, n, & A, LDA, B, LDB, C, LDC, rescale_factor_kappa) & bind(C) result(info) use qmckl_constants implicit none integer (qmckl_context), intent(in) , value :: context character(c_char ) , intent(in) , value :: transa character(c_char ) , intent(in) , value :: transb integer (c_int64_t) , intent(in) , value :: m integer (c_int64_t) , intent(in) , value :: n integer (c_int64_t) , intent(in) , value :: lda integer (c_int64_t) , intent(in) , value :: ldb integer (c_int64_t) , intent(in) , value :: ldc real (c_double ) , intent(in) , value :: rescale_factor_kappa real (c_double ) , intent(in) :: A(lda,*) real (c_double ) , intent(in) :: B(ldb,*) real (c_double ) , intent(out) :: C(ldc,n) integer(qmckl_exit_code) :: info integer*8 :: i,j real*8 :: x, y, z, dist, rescale_factor_kappa_inv integer :: transab rescale_factor_kappa_inv = 1.0d0/rescale_factor_kappa; info = QMCKL_SUCCESS if (context == QMCKL_NULL_CONTEXT) then info = QMCKL_INVALID_CONTEXT return endif if (m <= 0_8) then info = QMCKL_INVALID_ARG_4 return endif if (n <= 0_8) then info = QMCKL_INVALID_ARG_5 return endif if (transa == 'N' .or. transa == 'n') then transab = 0 else if (transa == 'T' .or. transa == 't') then transab = 1 else transab = -100 endif if (transb == 'N' .or. transb == 'n') then continue else if (transb == 'T' .or. transb == 't') then transab = transab + 2 else transab = -100 endif ! check for LDA if (transab < 0) then info = QMCKL_INVALID_ARG_1 return endif if (iand(transab,1) == 0 .and. LDA < 3) then info = QMCKL_INVALID_ARG_7 return endif if (iand(transab,1) == 1 .and. LDA < m) then info = QMCKL_INVALID_ARG_7 return endif ! check for LDB if (iand(transab,2) == 0 .and. LDB < 3) then info = QMCKL_INVALID_ARG_9 return endif if (iand(transab,2) == 2 .and. LDB < n) then info = QMCKL_INVALID_ARG_9 return endif ! check for LDC if (LDC < m) then info = QMCKL_INVALID_ARG_11 return endif select case (transab) case(0) do j=1,n do i=1,m x = A(1,i) - B(1,j) y = A(2,i) - B(2,j) z = A(3,i) - B(3,j) dist = dsqrt(x*x + y*y + z*z) C(i,j) = (1.0d0 - dexp(-rescale_factor_kappa * dist)) * rescale_factor_kappa_inv end do end do case(1) do j=1,n do i=1,m x = A(i,1) - B(1,j) y = A(i,2) - B(2,j) z = A(i,3) - B(3,j) dist = dsqrt(x*x + y*y + z*z) C(i,j) = (1.0d0 - dexp(-rescale_factor_kappa * dist)) * rescale_factor_kappa_inv end do end do case(2) do j=1,n do i=1,m x = A(1,i) - B(j,1) y = A(2,i) - B(j,2) z = A(3,i) - B(j,3) dist = dsqrt(x*x + y*y + z*z) C(i,j) = (1.0d0 - dexp(-rescale_factor_kappa * dist)) * rescale_factor_kappa_inv end do end do case(3) do j=1,n do i=1,m x = A(i,1) - B(j,1) y = A(i,2) - B(j,2) z = A(i,3) - B(j,3) dist = dsqrt(x*x + y*y + z*z) C(i,j) = (1.0d0 - dexp(-rescale_factor_kappa * dist)) * rescale_factor_kappa_inv end do end do end select end function qmckl_distance_rescaled
3.1.4. Performance
This function is more efficient when A and B are transposed.
4. Rescaled Distance Derivatives
4.1. qmckl_distance_rescaled_gl
qmckl_distance_rescaled_gl computes the matrix of the gradient and Laplacian of the
rescaled distance with respect to the electron coordinates. The derivative is a rank 3 tensor.
The first dimension has a dimension of 4 of which the first three coordinates
contains the gradient vector and the last index is the Laplacian.
\[ C(r_{ij}) = \left( 1 - \exp(-\kappa\, r_{ij})\right)/\kappa \]
Here the gradient is defined as follows:
\[ \nabla_i C(r_{ij}) = \left(\frac{\partial C(r_{ij})}{\partial x_i},\frac{\partial C(r_{ij})}{\partial y_i},\frac{\partial C(r_{ij})}{\partial z_i} \right) \] and the Laplacian is defined as follows:
\[ \Delta_i C(r_{ij}) = \frac{\partial^2}{\partial x_i^2} + \frac{\partial^2}{\partial y_i^2} + \frac{\partial^2}{\partial z_i^2} \]
Using the above three formulas, the expression for the gradient and Laplacian is:
\[ \frac{\partial C(r_{ij})}{\partial x_i} = \frac{|(x_i - x_j)|}{r_{ij}} \exp (- \kappa \, r_{ij}) \]
\[ \Delta C_{ij}(r_{ij}) = \left[ \frac{2}{r_{ij}} - \kappa \right] \exp (- \kappa \, r_{ij}) \]
If the input array is normal ('N'), the xyz coordinates are in
the leading dimension: [n][3] in C and (3,n) in Fortran.
| Variable | Type | In/Out | Description |
|---|---|---|---|
context |
qmckl_context |
in | Global state |
transa |
char |
in | Array A is 'N': Normal, 'T': Transposed |
transb |
char |
in | Array B is 'N': Normal, 'T': Transposed |
m |
int64_t |
in | Number of points in the first set |
n |
int64_t |
in | Number of points in the second set |
A |
double[][lda] |
in | Array containing the \(m \times 3\) matrix \(A\) |
lda |
int64_t |
in | Leading dimension of array A |
B |
double[][ldb] |
in | Array containing the \(n \times 3\) matrix \(B\) |
ldb |
int64_t |
in | Leading dimension of array B |
C |
double[n][ldc][4] |
out | Array containing the \(4 \times m \times n\) matrix \(C\) |
ldc |
int64_t |
in | Leading dimension of array C |
rescale_factor_kappa |
double |
in | Factor for calculating rescaled distances derivatives |
Requirements:
contextis notQMCKL_NULL_CONTEXTm > 0n > 0lda >= 3iftransa == 'N'lda >= miftransa == 'T'ldb >= 3iftransb == 'N'ldb >= niftransb == 'T'ldc >= mAis allocated with at least \(3 \times m \times 8\) bytesBis allocated with at least \(3 \times n \times 8\) bytesCis allocated with at least \(4 \times m \times n \times 8\) bytes
qmckl_exit_code qmckl_distance_rescaled_gl ( const qmckl_context context, const char transa, const char transb, const int64_t m, const int64_t n, const double* A, const int64_t lda, const double* B, const int64_t ldb, double* const C, const int64_t ldc, const double rescale_factor_kappa );
function qmckl_distance_rescaled_gl(context, transa, transb, m, n, & A, LDA, B, LDB, C, LDC, rescale_factor_kappa) & bind(C) result(info) use qmckl_constants implicit none integer(qmckl_exit_code) :: info integer (qmckl_context), intent(in) , value :: context character(c_char ) , intent(in) , value :: transa character(c_char ) , intent(in) , value :: transb integer (c_int64_t) , intent(in) , value :: m integer (c_int64_t) , intent(in) , value :: n integer (c_int64_t) , intent(in) , value :: lda integer (c_int64_t) , intent(in) , value :: ldb integer (c_int64_t) , intent(in) , value :: ldc real (c_double ) , intent(in) , value :: rescale_factor_kappa real (c_double ) , intent(in) :: A(lda,*) real (c_double ) , intent(in) :: B(ldb,*) real (c_double ) , intent(out) :: C(4,ldc,n) integer*8 :: i,j real*8 :: x, y, z, dist, dist_inv real*8 :: rij integer :: transab info = QMCKL_SUCCESS if (context == QMCKL_NULL_CONTEXT) then info = QMCKL_INVALID_CONTEXT return endif if (m <= 0_8) then info = QMCKL_INVALID_ARG_4 return endif if (n <= 0_8) then info = QMCKL_INVALID_ARG_5 return endif if (transa == 'N' .or. transa == 'n') then transab = 0 else if (transa == 'T' .or. transa == 't') then transab = 1 else transab = -100 endif if (transb == 'N' .or. transb == 'n') then continue else if (transb == 'T' .or. transb == 't') then transab = transab + 2 else transab = -100 endif ! check for LDA if (transab < 0) then info = QMCKL_INVALID_ARG_1 return endif if (iand(transab,1) == 0 .and. LDA < 3) then info = QMCKL_INVALID_ARG_7 return endif if (iand(transab,1) == 1 .and. LDA < m) then info = QMCKL_INVALID_ARG_7 return endif ! check for LDB if (iand(transab,2) == 0 .and. LDB < 3) then info = QMCKL_INVALID_ARG_9 return endif if (iand(transab,2) == 2 .and. LDB < n) then info = QMCKL_INVALID_ARG_9 return endif ! check for LDC if (LDC < m) then info = QMCKL_INVALID_ARG_11 return endif select case (transab) case(0) do j=1,n do i=1,m x = A(1,i) - B(1,j) y = A(2,i) - B(2,j) z = A(3,i) - B(3,j) dist = max(1.d-20, dsqrt(x*x + y*y + z*z)) dist_inv = 1.0d0/dist rij = dexp(-rescale_factor_kappa * dist) C(1,i,j) = x * dist_inv * rij C(2,i,j) = y * dist_inv * rij C(3,i,j) = z * dist_inv * rij C(4,i,j) = (2.0d0 * dist_inv - rescale_factor_kappa) * rij end do end do case(1) do j=1,n do i=1,m x = A(i,1) - B(1,j) y = A(i,2) - B(2,j) z = A(i,3) - B(3,j) dist = max(1.d-20, dsqrt(x*x + y*y + z*z)) dist_inv = 1.0d0/dist rij = dexp(-rescale_factor_kappa * dist) C(1,i,j) = x * dist_inv * rij C(2,i,j) = y * dist_inv * rij C(3,i,j) = z * dist_inv * rij C(4,i,j) = (2.0d0 * dist_inv - rescale_factor_kappa) * rij end do end do case(2) do j=1,n do i=1,m x = A(1,i) - B(j,1) y = A(2,i) - B(j,2) z = A(3,i) - B(j,3) dist = max(1.d-20, dsqrt(x*x + y*y + z*z)) dist_inv = 1.0d0/dist rij = dexp(-rescale_factor_kappa * dist) C(1,i,j) = x * dist_inv * rij C(2,i,j) = y * dist_inv * rij C(3,i,j) = z * dist_inv * rij C(4,i,j) = (2.0d0 * dist_inv - rescale_factor_kappa) * rij end do end do case(3) do j=1,n do i=1,m x = A(i,1) - B(j,1) y = A(i,2) - B(j,2) z = A(i,3) - B(j,3) dist = max(1.d-20, dsqrt(x*x + y*y + z*z)) dist_inv = 1.0d0/dist rij = dexp(-rescale_factor_kappa * dist) C(1,i,j) = x * dist_inv * rij C(2,i,j) = y * dist_inv * rij C(3,i,j) = z * dist_inv * rij C(4,i,j) = (2.0d0 * dist_inv - rescale_factor_kappa) * rij end do end do end select end function qmckl_distance_rescaled_gl
This function is more efficient when A and B are transposed.