Skip to main content

A Generic Particle+Grid Interface

Project description

GPGI

PyPI pre-commit.ci status Ruff

Fast particle deposition at post-processing time

This small Python library implements fundamental grid deposition algorithms to analyse (rectilinear) grid + particle datasets, with an emphasize on performance. Core algorithms are implemented as Cython extensions.

GPGI stands for Generic Particle + Grid data Interface

Table of Contents

Installation

python -m pip install --upgrade pip
python -m pip install gpgi

Supported applications

A rectilinear grid is defined as 1D arrays representing cell left edges in each directions. Note that the last point of such an array is interpreted as the right edge of the rightmost cell, so for instance, a 1D grid containing 100 cells is defined by 101 edges.

Particles are defined as points that live within the grid's bounds.

Deposition is the action of going from particle description to a grid description of a field. It is useful to analyze, compare and combine simulation data that exists in a combination of the two formalisms. This process is not reversible as it degrades information.

For instance, here's a simple overlay of a particle set (red dots) against a background that represents the deposited particle count.

This example illustrates the simplest possible deposition method, "Nearest Grid Point" (NGP), in which each particle contributes only to the cell that contains it.

More refined methods are also available.

Builtin deposition methods

method name abreviated name order
Nearest Grid Point NGP 0
Cloud in Cell CIC 1
Triangular Shaped Cloud TSC 2

new in gpgi 0.12 User-defined alternative methods may be provided to Dataset.deposit as method=my_func. Their signature need to be compatible with gpgi.types.DepositionMethodT.

Supported geometries

geometry name axes order
cartesian x, y, z
polar radius, z, azimuth
cylindrical radius, azimuth, z
spherical radius, colatitude, azimuth
equatorial radius, azimuth, latitude

Time complexity

An important step in perfoming deposition is to associate particle indices to cell indices. This step is called "particle indexing". In directions where the grid is uniformly stepped (if any), indexing a particle is an O(1) operation. In the more general case, indexing is performed by bisection, which is a O(log(nx))) operation (where nx represents the number of cells in the direction of interest).

Usage

The API consists in a load function, which returns a Dataset object.

Load data

import numpy as np
import gpgi

nx = ny = 64
nparticles = 600_000

prng = np.random.RandomState(0)
ds = gpgi.load(
    geometry="cartesian",
    grid={
        "cell_edges": {
            "x": np.linspace(-1, 1, nx),
            "y": np.linspace(-1, 1, ny),
        },
    },
    particles={
        "coordinates": {
            "x": 2 * (prng.normal(0.5, 0.25, nparticles) % 1 - 0.5),
            "y": 2 * (prng.normal(0.5, 0.25, nparticles) % 1 - 0.5),
        },
        "fields": {
            "mass": np.ones(nparticles),
        },
    },
)

The Dataset object holds a grid and a particles attribute, which both hold a fields attribute for accessing their data. But more importantly, the Dataset has a deposit method to translate particle fields to the grid formalism.

Deposit Particle fields on the grid

particle_mass = ds.deposit("mass", method="nearest_grid_point")  # or "ngp" for shorts

Visualize In this example we'll use matplotlib for rendering, but note that matplotlib is not a dependency to gpgi

import matplotlib.pyplot as plt

fig, ax = plt.subplots()
ax.set(aspect=1, xlabel="x", ylabel="y")

im = ax.pcolormesh(
    "x",
    "y",
    particle_mass.T,
    data=ds.grid.cell_edges,
    cmap="viridis",
)
fig.colorbar(im, ax=ax)

The example script given here takes about a second (top to bottom).

Supplying arbitrary metadata

new in gpgi 0.4.0

Dataset objects have a special attribute metadata which is a dictionary with string keys. This attribute is meant to hold any special metadata that may be relevant for labelling or processing (e.g. simulation time, author, ...). Metadata can be supplied at load time as

ds = gpgi.load(
    geometry="cartesian",
    grid=...,
    particles=...,
    metadata={"simulation_time": 12.5, "author": "Clément Robert"}
)

Boundary conditions

new in gpgi 0.5.0

With CIC and TSC deposition, particles contribute to cells neighbouring the one that contains them. For particles that live in the outermost layer of the domain, this means some of their contribution is lost. This behaviour corresponds to the default 'open' boundary condition, but gpgi has builtin support for more conservative boundary conditions.

Boundary conditions can selected per field, per axis and per side. Builtin recipes all perform linear combinations of ghost layers (same-side and opposite side) and active domain layers (same-side and opposite side), and replace the same-side active layer with the result.

User-selected boundary conditions take the form of an optional argument to Dataset.deposit, as dictionnary with keys being axes names, and values being 2-tuples of boundary conditions names (for left and right side respectively). For instance, here's how one would require periodic boundary conditions on all axes:

ds.deposit(
    "mass",
    method="cic",
    boundaries={
        "x": ("periodic", "periodic"),
        "y": ("periodic", "periodic"),
    }
)

Unspecified axes will use the default 'open' boundary.

Builtin recipes

boundary conditions description conservative ?
open (default) no special treatment no
periodic add opposite ghost layer to the active domain yes
wall add same-side ghost layer to the active domain yes
antisymmetric substract same-side ghost layer from the active domain no

Define custom recipes

gpgi's boundary recipes can be customized. Let's illustrate this feature with a simple example. Say we want to fix the value of the deposited field in some outer layer. This is done by defining a new function on the user side:

def ones(
    same_side_active_layer,
    same_side_ghost_layer,
    opposite_side_active_layer,
    opposite_side_ghost_layer,
    weight_same_side_active_layer,
    weight_same_side_ghost_layer,
    weight_opposite_side_active_layer,
    weight_opposite_side_ghost_layer,
    side,
    metadata,
):
   return 1.0

where all first eight arguments are numpy.ndarray objects with the same shape (which includes ghost padding !), to which the return value must be broadcastable, side can only be either "left" or "right", and metadata is the special Dataset.metadata attribute. Not all arguments need be used in the body of the function, but this signature is required.

The method must then be registered as a boundary condition recipe as

ds.boundary_recipes.register("ones", ones)

where the associated key (here "ones") is arbitrary. The recipe can now be used exactly as builtin ones, and all of them can be mixed arbitrarily.

ds.deposit(
    "mass",
    method="cic",
    boundaries={
        "x": ("ones", "wall"),
        "y": ("periodic", "periodic"),
    }
)

Note that all first eight arguments in a boundary recipe function should represent an extensive physical quantity (as opposed to intensive). When depositing an intensive quantity u, a weight field w should be supplied (see next section), in which case, the first four arguments represent u*w and the following four represent w, so that u can still be obtained within the function as a ratio if needed.

Weight fields (Depositing intensive quantities)

new in gpgi 0.7.0

Fundamentally, deposition algorithms construct on-grid fields by performing summations. An implication is that the physical quantities being deposited are required to be extensive (like mass or momentum). Intensive quantities (like velocity or temperature) require additional operations, and necessitate the use of an additional weight field.

This section provides showcases their usage. For a detailled explanation of the deposition algorithm for intensive quantities, see Deposition algorithm.

In order to deposit an intensive field (e.g., vx), an additional weight_field argument must be provided as

ds.deposit(
    "vx",
    method="cic",
    boundaries={
        "y": ("periodic", "periodic"),
        "x": ("antisymmetric", "antisymmetric"),
    },
    weight_field="mass",
    weight_field_boundaries={
        "y": ("periodic", "periodic"),
        "x": ("open", "open"),
    },
)

Boundary recipes may be also associated to the weight field with the weight_field_boundaries argument. This arguments becomes required if boundaries and weight_field are both provided.

Call help(ds.deposit) for more detail.

Count Sorting

new in gpgi 0.14.0

gpgi can load arbitrarily ordered particle sets, though deposition algorithms perform better when the in-memory position of particles correlates with their physical positions relative to the grid, since such a state minimizes the number of cache misses.

Particles may be sorted by a counting sort algorithm, as

ds = ds.sorted()

Note that this method returns a copy of the dataset, so it will best perform for datasets that, at most, fit in half your RAM.

This operation is costly in itself, so there may be a trade-off depending on how many depositions one needs to perform on a given dataset before tossing it out.

By default, axes are weighted in the order that's optimal for gpgi's deposition routines, but arbitrary priority order may be specified as, for instance

ds = ds.sorted(axes=(1, 0))

Use the Dataset.is_sorted method to check wether particles are already sorted without performing the sort. Dataset.is_sorted accepts an axes argument just like Dataset.sorted. This is useful for testing and comparative purposes.

Deposition algorithm

This section provides details on the general deposition algorithm, as implemented in gpgi.

Without loss of generality, we will illustrate how an intensive field (v) is deposited, since this case requires the most computational steps. As it happens, depositing an extensive field (w) separately is actually part of the algorithm.

Definitions

  • v is an intensive field that we want to deposit on the grid
  • w is an extensive field that will be used as weights
  • u = v * w is an extensive equivalent to v (conceptually, if v is a velocity and w is a mass, u corresponds to a momentum)

u(i), v(i) and w(i) are defined for each particle i.

We note U(x), V(x) and W(x) the corresponding on-grid fields, where V(x) is the final output of the algorithm. These are defined at grid cell centers x, within the active domain.

Last, we note U'(x), V'(x) and W'(x) the raw deposited fields, meaning no special treatment is applied to the outermost layers (boundary conditions). These are defined at grid cell centers, including one ghost layer that will be used to apply boundary conditions.

Algorithm

  1. W' and U' are computed as
W'(x) = Σ c(i,x) w(i)
U'(x) = Σ c(i,x) w(i) v(i)

where c(i,x) are geometric coefficients associated with the deposition method. Taking the nearest grid point (NGP) method for illustration, c(i,x) = 1 if particle i is contained in the cell whose center is x, and c(i,x) = 0 elsewhere.

  1. boundary conditions are applied
W(x) = W_BCO(W', 1, metadata)
U(x) = U_BCO(U', W', metadata)

where W_BCO and U_BCO denote arbitrary boundary condition operators associated with W and U respectively, and which take 3 arguments, representing the field to be transformed, its associated weight field and a wildcard metadata argument which may contain any additional data relevant to the operator.

Note 1 is used a placeholder "weight" for W, for symmetry reasons: all boundary condition operators must expose a similar interface, as explained in Define custom recipes.

  1. Finally, V(x) is obtained as
V(x) = (U/W)(x)

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

gpgi-1.0.0.tar.gz (38.6 kB view details)

Uploaded Source

Built Distributions

gpgi-1.0.0-cp312-cp312-win_amd64.whl (242.3 kB view details)

Uploaded CPython 3.12 Windows x86-64

gpgi-1.0.0-cp312-cp312-musllinux_1_1_x86_64.whl (1.7 MB view details)

Uploaded CPython 3.12 musllinux: musl 1.1+ x86-64

gpgi-1.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.7 MB view details)

Uploaded CPython 3.12 manylinux: glibc 2.17+ x86-64

gpgi-1.0.0-cp312-cp312-macosx_11_0_arm64.whl (246.1 kB view details)

Uploaded CPython 3.12 macOS 11.0+ ARM64

gpgi-1.0.0-cp312-cp312-macosx_10_9_x86_64.whl (324.3 kB view details)

Uploaded CPython 3.12 macOS 10.9+ x86-64

gpgi-1.0.0-cp311-cp311-win_amd64.whl (239.5 kB view details)

Uploaded CPython 3.11 Windows x86-64

gpgi-1.0.0-cp311-cp311-musllinux_1_1_x86_64.whl (1.7 MB view details)

Uploaded CPython 3.11 musllinux: musl 1.1+ x86-64

gpgi-1.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.7 MB view details)

Uploaded CPython 3.11 manylinux: glibc 2.17+ x86-64

gpgi-1.0.0-cp311-cp311-macosx_11_0_arm64.whl (243.8 kB view details)

Uploaded CPython 3.11 macOS 11.0+ ARM64

gpgi-1.0.0-cp311-cp311-macosx_10_9_x86_64.whl (316.3 kB view details)

Uploaded CPython 3.11 macOS 10.9+ x86-64

gpgi-1.0.0-cp310-cp310-win_amd64.whl (239.1 kB view details)

Uploaded CPython 3.10 Windows x86-64

gpgi-1.0.0-cp310-cp310-musllinux_1_1_x86_64.whl (1.6 MB view details)

Uploaded CPython 3.10 musllinux: musl 1.1+ x86-64

gpgi-1.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.6 MB view details)

Uploaded CPython 3.10 manylinux: glibc 2.17+ x86-64

gpgi-1.0.0-cp310-cp310-macosx_11_0_arm64.whl (244.1 kB view details)

Uploaded CPython 3.10 macOS 11.0+ ARM64

gpgi-1.0.0-cp310-cp310-macosx_10_9_x86_64.whl (317.8 kB view details)

Uploaded CPython 3.10 macOS 10.9+ x86-64

File details

Details for the file gpgi-1.0.0.tar.gz.

File metadata

  • Download URL: gpgi-1.0.0.tar.gz
  • Upload date:
  • Size: 38.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.2

File hashes

Hashes for gpgi-1.0.0.tar.gz
Algorithm Hash digest
SHA256 10860d0a79ffe745d9e7314f03a1ba3c47a4664c180132d44bcdc8971b57250a
MD5 3500b316af205ec252ce95bafa1582fd
BLAKE2b-256 992b50292bf25d10472ff35ea82f6cce691433f9b3f6f4de8b0b5fed2fcf9b68

See more details on using hashes here.

File details

Details for the file gpgi-1.0.0-cp312-cp312-win_amd64.whl.

File metadata

  • Download URL: gpgi-1.0.0-cp312-cp312-win_amd64.whl
  • Upload date:
  • Size: 242.3 kB
  • Tags: CPython 3.12, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.2

File hashes

Hashes for gpgi-1.0.0-cp312-cp312-win_amd64.whl
Algorithm Hash digest
SHA256 3cde31b752d19cd8dabdf96af4985d874aa39da3a250eea80a0b77a97e9a10d5
MD5 c505ac54b449093abdc57d4dbcee9874
BLAKE2b-256 04ce57385afad137d3d31b17b41865ca43cbc0d4e746ea261e642bb2454cd68b

See more details on using hashes here.

File details

Details for the file gpgi-1.0.0-cp312-cp312-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for gpgi-1.0.0-cp312-cp312-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 1460cb78bf953db0a883128d94a87024eca22c1233aaa95cacc20ba6983d671b
MD5 d9b4c29e97ca7f7b5a1bc6c706b95141
BLAKE2b-256 a786313b3b197edf138f6e27e195d46fb7c98a63676072cd72079274c5be4fc3

See more details on using hashes here.

File details

Details for the file gpgi-1.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for gpgi-1.0.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 0e6c6e742e197f4b539b9d5ba2ff3e701e658da73e310272b4ba95f4e18a9575
MD5 900c575c2f04637649ff72da8ad87189
BLAKE2b-256 e2ecaa09a7eb3f5bbe688ed884476f09da259525dd6d15aeb3f73079b7b9e680

See more details on using hashes here.

File details

Details for the file gpgi-1.0.0-cp312-cp312-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for gpgi-1.0.0-cp312-cp312-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 1f633a494b81961c27957abdc5908947756a256d454558906ef353b207c8d1eb
MD5 954aafaddd8d6bc8e812b731c323db14
BLAKE2b-256 784a34ba773323348abb763f0289da06fc2609ae5bf171998f23a16de69a9512

See more details on using hashes here.

File details

Details for the file gpgi-1.0.0-cp312-cp312-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for gpgi-1.0.0-cp312-cp312-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 812a2a84e3bd7d7619fefc95d52a808ab48422de51e64a1cc52a947ba621319c
MD5 d47cd78697750d679a98b6a78f9cc8a8
BLAKE2b-256 862fadff2386544a532698a0aecd91e2b8138ae6c33221f2d1277eb84440091a

See more details on using hashes here.

File details

Details for the file gpgi-1.0.0-cp311-cp311-win_amd64.whl.

File metadata

  • Download URL: gpgi-1.0.0-cp311-cp311-win_amd64.whl
  • Upload date:
  • Size: 239.5 kB
  • Tags: CPython 3.11, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.2

File hashes

Hashes for gpgi-1.0.0-cp311-cp311-win_amd64.whl
Algorithm Hash digest
SHA256 10e44476968c8b451c497297108abeb9a9bc175017bb6898efe83e74a172ca6e
MD5 c1545f6b12b2840592271d45fad50e97
BLAKE2b-256 98cc4941c202287680085c9a85d0532d6298ed2ea18e5d69864c63fcdd514708

See more details on using hashes here.

File details

Details for the file gpgi-1.0.0-cp311-cp311-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for gpgi-1.0.0-cp311-cp311-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 e3eaf3aa8a92b242c271bf1c629b310cf47162a2538031fac64040a4e473ffe6
MD5 ee81778f6806f682d9490e11f23e46aa
BLAKE2b-256 1a9ecdf57a726bdddc4cebbf652a3f769a726f46f874af4c5c19444c5187b977

See more details on using hashes here.

File details

Details for the file gpgi-1.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for gpgi-1.0.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 b673a4ab6143bacbb66656f35588625ca23ba3c11c54b06421017195310b8b6a
MD5 4e1bef70489ade0926bdb818ffb61e4b
BLAKE2b-256 07bac4440bac60fa30115f87d545a47f23bbf4a861af06e8a1dd7c8cc1311272

See more details on using hashes here.

File details

Details for the file gpgi-1.0.0-cp311-cp311-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for gpgi-1.0.0-cp311-cp311-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 0a6259c6f6e9b8e49d1108173adb14d0c68ec816007bbd265b9ea8c8e7907c35
MD5 bd5a322ab687baf704374a46ec6271cb
BLAKE2b-256 2c7378f6100e0759d79aa64a01d0ec95d0f77e85f155f04bf9fa77e90d4b9d9d

See more details on using hashes here.

File details

Details for the file gpgi-1.0.0-cp311-cp311-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for gpgi-1.0.0-cp311-cp311-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 d5d10300a59f924eced43eacc981b19654a628dc271647f988d35946d8077025
MD5 217ef1e5dc8337e459d7581e681b0365
BLAKE2b-256 9afdc60080d711ad6695b5c5dafa916d11e0bc5610368c467f985c6363f8f9cf

See more details on using hashes here.

File details

Details for the file gpgi-1.0.0-cp310-cp310-win_amd64.whl.

File metadata

  • Download URL: gpgi-1.0.0-cp310-cp310-win_amd64.whl
  • Upload date:
  • Size: 239.1 kB
  • Tags: CPython 3.10, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/5.0.0 CPython/3.12.2

File hashes

Hashes for gpgi-1.0.0-cp310-cp310-win_amd64.whl
Algorithm Hash digest
SHA256 cf31fe6692bd5ef674068c3e80263f789a21b0801facfb8992c87ee74d45a779
MD5 147c74e2ad03d0a29b5a5cb44e511476
BLAKE2b-256 d3a6d56fda119d8afc9e4901b7de437adabfbe83a75ebd75fcd3f6acdc2d0ceb

See more details on using hashes here.

File details

Details for the file gpgi-1.0.0-cp310-cp310-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for gpgi-1.0.0-cp310-cp310-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 27c1ef9bd574741074af90249f568aabcf7ddadc022cc47425d688215a24569d
MD5 a1bd6d114ac637e8ea2cf8d203585967
BLAKE2b-256 e7a5c7f935f5b716dd135dcc11797adb820f40e383f06164bace8bcdc0f3673f

See more details on using hashes here.

File details

Details for the file gpgi-1.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for gpgi-1.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 1b46b57ca74ad95601222b96904a4cc000ff345d27ab477b23ab921a89341ed3
MD5 c16f531462b9a1f547cf671eb16c0e73
BLAKE2b-256 005b0750248ce8d0fa14b75afcdd7b530129410a9309c68d93f5c586a572b91f

See more details on using hashes here.

File details

Details for the file gpgi-1.0.0-cp310-cp310-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for gpgi-1.0.0-cp310-cp310-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 e49af83ec595bfbdcc191676dd0149482ae4b9d7e38447b415850babc388dcea
MD5 fe27f248a6f311e2b769dd4daac11e43
BLAKE2b-256 3576853a6919d3eb1d1acbf2823308ffc4567458a5e95706e04e730e519de7d7

See more details on using hashes here.

File details

Details for the file gpgi-1.0.0-cp310-cp310-macosx_10_9_x86_64.whl.

File metadata

File hashes

Hashes for gpgi-1.0.0-cp310-cp310-macosx_10_9_x86_64.whl
Algorithm Hash digest
SHA256 5da1885b3711f545949f9e6de3059b18cd1ab69fb711823f036f147a3219abef
MD5 731d644a9dd4bfb08952aeee5583ac20
BLAKE2b-256 ec74c0333764e95281098cb66601d7e7e884119fd1178bf243b211c0ec22b822

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page