Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

pymrm.particles

Back to modules overview

Particle-based immersed boundaries for pymrm.

Instead of sampling one global signed-distance field, an assembly of Particle objects generates the immersed-boundary data directly: each particle classifies the cells it covers (bounding-box window only), provides the exact wall position on every cut face (analytic where the shape allows it, root-finding otherwise), and evaluates the exact outward normal at every wall crossing. This avoids the two error sources of the union-SDF route near particle contacts:

Particle protocol

A particle answers three geometric questions, all in world coordinates:

The base class supplies world↔body transforms (position plus an orientation: an angle in 2-D, a scipy.spatial.transform.Rotation in 3-D) and numeric defaults for intersect (vectorised bisection) and normal (finite differences), so a new shape only has to implement the body-frame level function and bounding box. Sphere (alias Circle), Box, AnalyticParticle and GridParticle (B-spline interpolated local samples) are provided.

Contact policy

When two particles are closer than one grid cell, the cell-centre classification alone cannot see the gap: two adjacent cells are solid but belong to different particles. construct_ibm_particles detects these contact faces (the segment between the two cell centres leaves one particle before entering the other) and applies a policy:

Faces where the particles genuinely overlap (the segment does not leave one particle before entering the other) are always merged — interpenetrating particles form one body.

Usage

::

particles = [Sphere(c, r) for c, r in zip(centers, radii)]
ibm, info = construct_ibm_particles(particles, x_c)
recon = construct_ibm_normal_derivative(ibm, info.pseudo_sdf, x_c,
                                     normals=info.normals)
ic = contact_conditions(base_ic, ibm, info)
A, g = apply_ibm_interface(L, ibm, recon, ic)

View module source on GitHub

Public API

SymbolTypeSummary
AnalyticParticleclassParticle from a user-supplied body-frame level function.
BoxclassAxis-aligned (in body frame) box; rotate via orientation.
GridParticleclassParticle from level-function samples on its own body-frame grid.
ParticleclassAbstract particle: a shape at a position with an orientation.
ParticleIBMInfoclassSide-car information produced by construct_ibm_particles.
SphereclassSphere (any dimension; in 2-D this is a disk — see Circle).
construct_ibm_particlesfunctionBuild immersed-boundary data directly from a particle assembly.
contact_conditionsfunctionPer-crossing ic: base_ic everywhere, a contact condition on contacts.

AnalyticParticle(level_func, bounding_box, position, orientation = None, normal_func = None)

Open dedicated reference page

Particle from a user-supplied body-frame level function.

Parameters

View source on GitHub

Members

__init__(level_func, bounding_box, position, orientation = None, normal_func = None)

View source on GitHub

bounding_box(pad = 0.0)

World axis-aligned bounding box ((lo, hi), ...) per axis.

View source on GitHub

bounding_box_body()

Body-frame bounding box ((lo, hi), ...) per axis.

View source on GitHub

intersect(p0, p1)

Surface crossing fraction t on the segments p0 → p1.

p0/p1 are (n, ndim) batches whose endpoints straddle the surface (level(p0) and level(p1) of opposite sign); returns t in (0, 1) with level(p0 + t (p1 - p0)) == 0. Default: vectorised bisection on level; shapes with closed-form intersections override this.

View source on GitHub

level(coords)

Signed level function at world coords shaped (..., ndim).

View source on GitHub

level_body(coords)

Signed level function at body-frame coords shaped (..., ndim).

View source on GitHub

normal(coords)

Outward (solid→fluid) unit normal at world surface points.

View source on GitHub

normal_body(coords)

Gradient direction of level_body (finite differences).

View source on GitHub

to_body(coords)

View source on GitHub

vec_to_world(vecs)

View source on GitHub

__slots__

View source on GitHub

Box(position, half_extents, orientation = None)

Open dedicated reference page

Axis-aligned (in body frame) box; rotate via orientation.

half_extents are the half side lengths per axis. Exact SDF and face normals; segment intersections by the default bisection.

View source on GitHub

Members

__init__(position, half_extents, orientation = None)

View source on GitHub

bounding_box(pad = 0.0)

World axis-aligned bounding box ((lo, hi), ...) per axis.

View source on GitHub

bounding_box_body()

Body-frame bounding box ((lo, hi), ...) per axis.

View source on GitHub

intersect(p0, p1)

Surface crossing fraction t on the segments p0 → p1.

p0/p1 are (n, ndim) batches whose endpoints straddle the surface (level(p0) and level(p1) of opposite sign); returns t in (0, 1) with level(p0 + t (p1 - p0)) == 0. Default: vectorised bisection on level; shapes with closed-form intersections override this.

View source on GitHub

level(coords)

Signed level function at world coords shaped (..., ndim).

View source on GitHub

level_body(coords)

Signed level function at body-frame coords shaped (..., ndim).

View source on GitHub

normal(coords)

Outward (solid→fluid) unit normal at world surface points.

View source on GitHub

normal_body(coords)

Gradient direction of level_body (finite differences).

View source on GitHub

to_body(coords)

View source on GitHub

vec_to_world(vecs)

View source on GitHub

__slots__

View source on GitHub

GridParticle(values, x_local, position, orientation = None, method = 'cubic')

Open dedicated reference page

Particle from level-function samples on its own body-frame grid.

The samples are interpolated with a cubic B-spline (scipy.interpolate.RegularGridInterpolator), so the particle can be translated and rotated for free. The local grid must extend beyond the particle surface (positive samples all around); queries outside the local grid return the clamped boundary value plus the clamping distance, keeping the sign correct far away.

Parameters

View source on GitHub

Members

__init__(values, x_local, position, orientation = None, method = 'cubic')

View source on GitHub

bounding_box(pad = 0.0)

World axis-aligned bounding box ((lo, hi), ...) per axis.

View source on GitHub

bounding_box_body()

Body-frame bounding box ((lo, hi), ...) per axis.

View source on GitHub

intersect(p0, p1)

Surface crossing fraction t on the segments p0 → p1.

p0/p1 are (n, ndim) batches whose endpoints straddle the surface (level(p0) and level(p1) of opposite sign); returns t in (0, 1) with level(p0 + t (p1 - p0)) == 0. Default: vectorised bisection on level; shapes with closed-form intersections override this.

View source on GitHub

level(coords)

Signed level function at world coords shaped (..., ndim).

View source on GitHub

level_body(coords)

Signed level function at body-frame coords shaped (..., ndim).

View source on GitHub

normal(coords)

Outward (solid→fluid) unit normal at world surface points.

View source on GitHub

normal_body(coords)

Gradient direction of level_body (finite differences).

View source on GitHub

to_body(coords)

View source on GitHub

vec_to_world(vecs)

View source on GitHub

__slots__

View source on GitHub

Particle(position, orientation = None)

Open dedicated reference page

Abstract particle: a shape at a position with an orientation.

Subclasses implement the body-frame interface (level_body, bounding_box_body, optionally normal_body); the world-frame API used by the IBM assembly (level, normal, intersect, bounding_box) is provided here, including the numeric fallbacks.

Parameters

View source on GitHub

Members

__init__(position, orientation = None)

View source on GitHub

bounding_box(pad = 0.0)

World axis-aligned bounding box ((lo, hi), ...) per axis.

View source on GitHub

bounding_box_body()

Body-frame bounding box ((lo, hi), ...) per axis.

View source on GitHub

intersect(p0, p1)

Surface crossing fraction t on the segments p0 → p1.

p0/p1 are (n, ndim) batches whose endpoints straddle the surface (level(p0) and level(p1) of opposite sign); returns t in (0, 1) with level(p0 + t (p1 - p0)) == 0. Default: vectorised bisection on level; shapes with closed-form intersections override this.

View source on GitHub

level(coords)

Signed level function at world coords shaped (..., ndim).

View source on GitHub

level_body(coords)

Signed level function at body-frame coords shaped (..., ndim).

View source on GitHub

normal(coords)

Outward (solid→fluid) unit normal at world surface points.

View source on GitHub

normal_body(coords)

Gradient direction of level_body (finite differences).

View source on GitHub

to_body(coords)

View source on GitHub

vec_to_world(vecs)

View source on GitHub

__slots__

View source on GitHub

ParticleIBMInfo()

Open dedicated reference page

Side-car information produced by construct_ibm_particles.

Attributes

View source on GitHub

Members

contact

View source on GitHub

contact_partner

View source on GitHub

crossing_particle

View source on GitHub

normals

View source on GitHub

owner

View source on GitHub

pseudo_sdf

View source on GitHub

segmentation

View source on GitHub

Sphere(center, radius)

Open dedicated reference page

Sphere (any dimension; in 2-D this is a disk — see Circle).

Fully analytic: exact level function, normals, and segment intersections.

View source on GitHub

Members

__init__(center, radius)

View source on GitHub

bounding_box(pad = 0.0)

World axis-aligned bounding box ((lo, hi), ...) per axis.

View source on GitHub

bounding_box_body()

Body-frame bounding box ((lo, hi), ...) per axis.

View source on GitHub

intersect(p0, p1)

Surface crossing fraction t on the segments p0 → p1.

p0/p1 are (n, ndim) batches whose endpoints straddle the surface (level(p0) and level(p1) of opposite sign); returns t in (0, 1) with level(p0 + t (p1 - p0)) == 0. Default: vectorised bisection on level; shapes with closed-form intersections override this.

View source on GitHub

level(coords)

Signed level function at world coords shaped (..., ndim).

View source on GitHub

level_body(coords)

Signed level function at body-frame coords shaped (..., ndim).

View source on GitHub

normal(coords)

Outward (solid→fluid) unit normal at world surface points.

View source on GitHub

normal_body(coords)

Gradient direction of level_body (finite differences).

View source on GitHub

to_body(coords)

View source on GitHub

vec_to_world(vecs)

View source on GitHub

__slots__

View source on GitHub

construct_ibm_particles(particles, x_c, *, axes = None, shape = None, rescale = True, contact = 'no_flux', halo = 2, fill_value = None)

Open dedicated reference page

Build immersed-boundary data directly from a particle assembly.

Parameters

Returns

View source on GitHub

contact_conditions(base_ic, ibm, info, *, contact_ic = None)

Open dedicated reference page

Per-crossing ic: base_ic everywhere, a contact condition on contacts.

Parameters

Returns

View source on GitHub