Spatial Weights

pysammos.spatial_weights package

Subpackage for spatial weighting functions and related utilities.

This subpackage contains the following modules:

Hashtable Search module

Kernels module

Resolution module

Hashtable Search module

pysammos.spatial_weights.hashtable_search module

To speed up repeated evaluations of the CG weights for particle-grid point pairs, we implemented a lookup table algorithm. This method discretises the input domain, and subsequently, evaluates the target function at those discrete points. The discretised points and their corresponding values yielded by the function are stored in a lookup table, with a corresponding index. Next, the continuous query values are mapped to the discrete index of the lookup table by dividing by the step size and rounding down.

Hashtable Search

Example of a lookup table. Schematic diagram of the lookup table algorithm implemented in Pysammos. r corresponds to the distance between a particle and a grid point. The resolution of the lookup table is res. W(r) is the Coarse-Graining function, and c corresponds to its cut-off distance (i.e., *W(c)*=0).

This module contains the following functions:
  • make_hash_table(): Constructs a hash table of function values by sampling a given function over a specified range.

  • hash_table_search_1d(): Efficiently searches the hash table for 1D arrays of query values.

  • hash_table_search_2d(): Efficiently searches the hash table for 2D arrays of query values.

  • hash_table_search(): Dispatcher that routes queries to the correct 1D or 2D search function based on input dimensionality.

Dispatch function to route query_values to the appropriate hash table search function based on dimensionality.

Inputs

query_valuesnp.ndarray

Input values to query. Must be 1D or 2D array.

hash_table_outputsnp.ndarray

Precomputed hash table outputs.

step_sizefloat

Sampling interval used in hash table construction.

Outputs

np.ndarray

Approximated function values with same shape as query_values.

raises ValueError:

If query_values is not 1D or 2D.

pysammos.spatial_weights.hashtable_search.hash_table_search_1d(query_values, hash_table_outputs, step_size)

Approximate function evaluation for 1D query arrays by indexing into the precomputed hash table.

Inputs

query_valuesnp.ndarray, shape (N,)

1D array of input values to query.

hash_table_outputsnp.ndarray, shape (M,)

Precomputed function values stored in the hash table.

step_sizefloat

Sampling interval used to build the hash table.

Outputs

query_resultsnp.ndarray, shape (N,)

Approximated function values corresponding to each input query.

pysammos.spatial_weights.hashtable_search.hash_table_search_2d(query_values, hash_table_outputs, step_size)

Approximate function evaluation for 2D query arrays by indexing into the precomputed hash table.

Inputs

query_valuesnp.ndarray, shape (N, M)

2D array of input values to query.

hash_table_outputsnp.ndarray, shape (K,)

Precomputed function values stored in the hash table.

step_sizefloat

Sampling interval used to build the hash table.

Outputs

outnp.ndarray, shape (N, M)

Approximated function values corresponding to each input query.

pysammos.spatial_weights.hashtable_search.make_hash_table(func, max_value, sensitivity)[source]

Construct a hash table by sampling a function at discrete input intervals.

Inputs

funccallable

The function to sample. Must accept two arguments: max_value and input_value.

max_valuefloat

The maximum input value to sample up to.

sensitivityfloat

Controls the granularity of the hash table sampling by dividing the position of the first significant digit of max_value.

Outputs

hash_table_outputsnp.ndarray

Array of function values sampled at discrete points from step_size to max_value.

step_sizefloat

The sampling interval between hash table inputs.

Notes

The step_size is calculated as the position of the first significant figure of max_value divided by sensitivity. The hash table inputs are then generated from step_size up to max_value in increments of step_size. The function is vectorized over these inputs to produce the outputs.

Kernels module

pysammos.spatial_weights.kernels module

Spatial Weights Kernels

Example of spatial weights kernels. Visualisation of the three implemented Coarse-graining weighting functions, W(r), in one dimension (r) normalised by the half-width (w). Note that the functions have been plotted with equal variance in order to ensure that any differences are due to kernel shape, not scale.

This module provides a collection of commonly used kernel functions for smoothing, weighting, and interpolation in particle-based methods such as Smoothed Particle Hydrodynamics (SPH) or coarse-graining techniques.

This module includes implementations of several kernel functions:

  • lucy(): The Lucy kernel, a smooth, compactly supported kernel with continuous derivatives.

  • h(): The top-hat (step) function, a simple binary indicator function.

  • heavySide(): The Heaviside kernel, which provides uniform weighting inside a spherical cutoff volume.

  • gaussian(): The Gaussian kernel, a smooth, bell-shaped kernel with compact support truncated at three standard deviations.

Each kernel function computes a weight based on the distance from a kernel center and a cutoff radius, ensuring locality and normalization properties as appropriate.

pysammos.spatial_weights.kernels.gaussian(c, dist)[source]

Gaussian kernel function with compact support.

Computes the Gaussian kernel value used for continuous interpolation or smoothing operations. The kernel is truncated at the cutoff distance c, which corresponds to three standard deviations.

\[w = \dfrac{c}{3}\]
\[\begin{split}W(r) = \begin{cases} \dfrac{1}{V_w} \exp\left(-\dfrac{r^2}{2w^2}\right) & \text{if } r \leq c \\ 0 & \text{if } r > c \end{cases}\end{split}\]

where \(V_w\) is a normalization constant to ensure the kernel integrates to 1:

\[V_w = 2\sqrt{2}w^3\pi^{3/2} \operatorname{erf}\left(\dfrac{c\sqrt{2}}{2w}\right) - 4cw^2\pi \exp\left(-\dfrac{c^2}{2w^2}\right)\]

Inputs

cfloat

Cutoff distance (typically ).

distfloat

Distance between the evaluation point and the kernel center.

Outputs

Wfloat

The Gaussian kernel value.

pysammos.spatial_weights.kernels.h(dis)[source]

Top-hat (step) function.

A basic step function defined as:

\[\begin{split}h(x) = \begin{cases} 1 & \text{if } x > 0 \\ 0 & \text{otherwise} \end{cases}\end{split}\]

Inputs

disfloat

Input value.

Outputs

int

1 if dis > 0, otherwise 0.

pysammos.spatial_weights.kernels.heavySide(c, dist)[source]

Heaviside kernel function.

Computes the Heaviside (uniform sphere) kernel value for a given distance.

The function returns:

\[\begin{split}H(r) = \begin{cases} \dfrac{1}{\Omega} & \text{if } r \leq c \\ 0 & \text{otherwise} \end{cases}\end{split}\]

where \(\Omega = \dfrac{4}{3}\pi c^3\) is the normalization volume of a sphere.

Inputs

cfloat

Cutoff distance (radius of the uniform sphere).

distfloat

Distance from the kernel center.

Outputs

HSfloat

The Heaviside kernel value.

pysammos.spatial_weights.kernels.lucy(c, dist)[source]

Lucy kernel function.

Computes the Lucy weight at a given distance within the cutoff radius.

The Lucy kernel is defined as:

\[\begin{split}W(r) = \begin{cases} \dfrac{105}{16\pi c^3} \left( -3\left(\dfrac{r}{c}\right)^4 + 8\left(\dfrac{r}{c}\right)^3 - 6\left(\dfrac{r}{c}\right)^2 + 1 \right) & \text{if } r \leq c \\ 0 & \text{if } r > c \end{cases}\end{split}\]

Inputs

cfloat

Cutoff distance.

distfloat

Distance between the evaluation point and the kernel center.

Outputs

Wfloat

The weight computed from the Lucy kernel.

Resolution module

pysammos.spatial_weights.resolution module

This module provides helper functions for determining characteristic length scales used in kernel-based coarse-graining, smoothing, and interpolation methods. These parameters are essential in defining the support domain of a kernel function and thus controlling the spatial resolution of computed fields.

This module includes the following functions:
  • calc_half_width(): Computes the kernel half-width w from an average particle diameter D scaled by a user-defined multiplicative factor.

  • calc_cutoff(): Computes the kernel cutoff radius c based on the half-width w and the chosen kernel type (Lucy, Gaussian, or HeavySide).

These functions are often called during preprocessing to set consistent smoothing parameters for all particles in a simulation, ensuring that the kernel shape and support are appropriately scaled to particle size.

pysammos.spatial_weights.resolution.calc_cutoff(w, function)[source]

Calculate the cutoff radius c for a given kernel function.

This function determines the cutoff distance \(c\) used to truncate the kernel or filter function, based on the half-width w and the specified kernel type.

The cutoff c is calculated as:

  • For the Lucy kernel: \(c = 2w\)

  • For the Gaussian kernel: \(c = 3w\)

  • For the Heaviside (step) function: \(c = w\)

Inputs

wfloat

The half-width parameter used in the kernel.

functionstr

The name of the kernel function. Must be one of: 'Lucy', 'Gaussian', or 'HeavySide'.

Outputs

cfloat

The calculated cutoff value.

raises ValueError:

If the function argument is not one of the supported types.

pysammos.spatial_weights.resolution.calc_half_width(Average_part_diam, w_mult=0.75)[source]

Calculate the half-width parameter w based on average particle diameter.

This function computes the smoothing or weighting half-width w used in kernel functions for back-projection or filtering processes. The value of w is computed by scaling the average particle diameter by a multiplicative factor.

\[w = w_{\text{mult}} \cdot D\]

where \(D\) is the average particle diameter and \(w_{\text{mult}}\) is the user-defined multiplicative scaling factor.

Inputs

Average_part_diamfloat

The average particle diameter \(D\).

w_multfloat, optional

The multiplicative factor for calculating the half-width w. Default is 0.75.

Outputs

wfloat

The computed half-width w.

This module provides utility functions commonly used in numerical computations, particularly in physics and engineering simulations involving integration along branches or paths, and geometric distance calculations.

This module includes the following functions:

pysammos.spatial_weights.utils.compute_dist_along_branch(r_ri_c, s, BranchVector_i, part_ind_c)

Compute Euclidean distances along a branch for multiple contact points and scalar steps.

\[d_{ij} = \left\| \mathbf{r}_{ri}^{(j)} + s_i \, \mathbf{B}_{\text{part}}^{(k_j)} \right\|_2\]

where:

\(d_{ij}\) is the distance for scalar step \(s_i\) and contact point \(j\), \(\mathbf{r}_{ri}^{(j)}\) is the displacement vector from the reference point to contact point \(j\), \(s_i\) is the scalar step along the branch, \(\mathbf{B}_{\text{part}}^{(k_j)}\) is the branch direction vector associated with particle \(k_j\), and \(k_j = \text{part_ind_c}[j]\) is the index mapping contact points to particles.

Inputs

r_ri_cnp.ndarray, shape (n_contacts, 3)

Displacement vectors from reference points to contact points.

snp.ndarray, shape (n_s,)

Scalars along the branch for which distances are computed.

BranchVector_inp.ndarray, shape (n_particles, 3)

Branch direction vectors associated with each particle.

part_ind_cnp.ndarray, shape (n_contacts,)

Indices mapping contacts to corresponding particles in BranchVector_i.

Outputs

np.ndarray, shape (n_s, n_contacts)

Euclidean distances along the branch for each scalar step and contact.

Notes

This function is JIT-compiled with Numba and parallelized for efficiency.

Examples

>>> r_ri_c = np.array([[1,0,0], [0,1,0]], dtype=np.float64)
>>> s = np.array([0, 1], dtype=np.float64)
>>> BranchVector_i = np.array([[1,0,0], [0,1,0]], dtype=np.float32)
>>> part_ind_c = np.array([0, 1], dtype=np.int32)
>>> compute_dist_along_branch(r_ri_c, s, BranchVector_i, part_ind_c)
array([[1., 1.],
       [2., 2.]])
pysammos.spatial_weights.utils.first_significant_figure_position(number)[source]

Calculate the position (value) of the first significant figure of a number.

Return type:

float

Inputs

numberfloat

Input number to analyze.

Outputs

float

The value of the first significant figure's position. For example, if number = 345.6, returns 100.0. Special case: returns 0 if number is zero.

Examples

>>> first_significant_figure_position(345.6)
100.0
>>> first_significant_figure_position(0.00789)
0.001
>>> first_significant_figure_position(0)
0
pysammos.spatial_weights.utils.integration_scalar(s0, s1, n)[source]

Create a linearly spaced scalar array for integration over [s0, s1].

Return type:

ndarray

Inputs

s0float

Start of the integration interval.

s1float

End of the integration interval.

nint

Number of sample points.

Outputs

np.ndarray, shape (n,)

Linearly spaced array of scalars from s0 to s1.

Examples

>>> integration_scalar(0, 1, 5)
array([0.  , 0.25, 0.5 , 0.75, 1.  ])
pysammos.spatial_weights.utils.trapezoidal_integration(s0, s1, n, W)[source]

Compute numerical integral of sampled function W using the trapezoidal rule.

\[\begin{split}I_m = \int_{s_0}^{s_1} W_m(s) \, ds \approx \frac{\Delta s}{2} \left( W_m(s_0) + 2 \sum_{i=1}^{n-2} W_m(s_i) + W_m(s_{n-1}) \right) \\ \text{for } m = 0, \ldots, M-1\end{split}\]

where: \(I_m\) is the integral of the m-th component of W, \(W_m(s)\) is the m-th component of the function W evaluated at s, \(s_0\) and \(s_1\) are the integration bounds, \(n\) is the number of sample points, \(\Delta s = \frac{s_1 - s_0}{n-1}\) is the step size, and \(M\) is the number of components (columns) in W.

Inputs

s0float

Start of the integration interval.

s1float

End of the integration interval.

nint

Number of sample points.

Wnp.ndarray, shape (n, m)

Values of the function sampled at the points defined by s0, s1, and n. Integration is performed along the first axis.

Outputs

np.ndarray, shape (m,)

Resulting integral values for each column of W.

Examples

>>> s0, s1, n = 0, 1, 5
>>> W = np.array([[0], [1], [4], [9], [16]])
>>> trapezoidal_integration(s0, s1, n, W)
array([5.0])