jaxdem.utils.surfaceProperties#
Monte-Carlo-style sampling of the surface of a clump particle with a tracer clump.
The target (“central”) clump is held fixed. A tracer clump is placed at a
sequence of approach directions on a sphere (3D) or circle (2D) surrounding
the target. At every approach direction, the tracer is pushed toward the
target along the center-to-center direction until the two clumps achieve a
user-specified geometric overlap – defined as the maximum pairwise sphere
overlap delta = r_i + r_j - |x_i - x_j| over all (central-sphere,
tracer-sphere) pairs. Once the target overlap is reached, the interaction
force is decomposed into normal/tangential components with respect to the
center-to-center axis, yielding an effective friction coefficient
mu = |F_t| / |F_n|.
This sweep is repeated over a set of tracer orientations, so the map of
mu across the target surface represents the tracer-accessible surface
area (SASA-like) along with the contact-anisotropy at every sample point.
In 3D, full SO(3) orientation coverage is obtained by sweeping over
(facing direction on S^2, roll angle about that facing axis), which
correctly handles asymmetric tracers. In 2D the orientation degree of
freedom is a single angle.
Functions
|
Sample surface friction / accessibility over the surface of |
- jaxdem.utils.surfaceProperties.compute_surface_properties(central_state: State, tracer_state: State, target_overlap: float, *, system: System | None = None, n_points: int = 100, n_orientations: int = 1, n_rolls: int = 1, separation_tolerance: float = 1e-10, separation_scale: float = 1.1, batch_size: int = 10000) dict[str, np.ndarray | jax.Array][source]#
Sample surface friction / accessibility over the surface of
central_stateusingtracer_stateas a probe.- Parameters:
central_state (State) – Single-clump
Stateinstances. Their initial orientations are ignored (both are reset per probe: central to identity, tracer to the swept orientation), so the sampling directions live in the body frame of each clump as encoded by itspos_p.tracer_state (State) – Single-clump
Stateinstances. Their initial orientations are ignored (both are reset per probe: central to identity, tracer to the swept orientation), so the sampling directions live in the body frame of each clump as encoded by itspos_p.target_overlap (float) – Desired maximum pairwise sphere overlap (
r_i + r_j - |x_i - x_j|) between central and tracer at the reported contact configuration. Must be positive; small values correspond to “just barely indented”. The converged state satisfies this exactly up toseparation_tolerance.system (System, optional) – Interaction system used to compute forces (for
mu). IfNone, a default static measurement system is built (spring force, elastic material, naive collider, periodic box large enough for the pair).n_points (int) – Exact number of surface sample points (approach directions). In 2D these are equispaced on
S^1; in 3D they are placed onS^2via a Fibonacci (golden-spiral) lattice.n_orientations (int) – Number of tracer orientations. In 2D: this is the count of uniformly spaced rotation angles. In 3D: the count of facing directions sampled on
S^2via a Fibonacci (golden-spiral) lattice (each facing direction is paired with everyrollangle below, so total orientations aren_orientations * n_rolls).n_rolls (int) – 3D only: number of uniformly spaced rolls about the facing axis. Must be 1 in 2D (no roll degree of freedom). For asymmetric tracers set this > 1 to obtain full
SO(3)coverage.separation_tolerance (float) – Bisection convergence tolerance on the tracer center-to-center separation. The converged
max(overlap)error shrinks linearly with this value.separation_scale (float) – Safety factor for the upper bound of the bisection bracket.
batch_size (int) – Number of probes per
vmapcall, over the flatn_points * n_orientations * n_rollsprobe grid. Larger is better for GPU utilization; smaller cuts peak memory. With the default10_000typical sweeps fit in a single kernel launch.
- Returns:
A dictionary of stacked ndarrays:
- Common
mu– friction coefficient|F_t| / |F_n|per probe, shape(n_points, *orientation_shape).separation– center-to-center distance attarget_overlap, same shape asmu.n_central_contacts–intper probe, same shape asmu; number of central-clump vertex spheres with at least one force-bearing external contact at the bisected configuration.n_tracer_contacts– same, for the tracer clump.tracer_quaternions– shape(n_points, *orientation_shape, 4); the composed quaternion actually applied to the tracer at the bisected configuration (approach-direction rotation composed with the per-orientation base).central_position– shape(dim,); COM of the central clump (constant across probes; equalssystem.domain.box_size / 2). Combined withapproach_directionsandseparationthis gives the tracer COM ascentral_position + separation * approach_dir.approach_directions– surface sample directions, shape(n_points, dim).target_overlap– scalar float; echo of the input.dim– int; dimensionality (2 or 3).
- 2D only
angle_surface–(n_points,); polar angle of each approach direction.tracer_angles–(n_orientations,); the swept tracer rotation angles. Grid shape:(n_orientations,).
- 3D only
theta_surface,phi_surface–(n_points,)each; spherical coordinates of each approach direction.tracer_facings–(n_orientations, 3); body-frame directions sampled onS^2.tracer_facing_theta,tracer_facing_phi–(n_orientations,)each; spherical coords of the facings.tracer_rolls–(n_rolls,); roll angles about each facing axis. Grid shape:(n_orientations, n_rolls).
- Return type:
dict
Notes
The
orientation_shapeis(n_orientations,)in 2D and(n_orientations, n_rolls)in 3D, somu[i, ...]gives the full orientation map for approach-directioniand any slice along the leading axis gives the surface map for a fixed orientation.To reproduce the exact contact configuration of probe
(i, j[, k])given the originalcentral_stateandtracer_state:idx = (i, j, k) if dim == 3 else (i, j) tracer_com = result["central_position"] + ( result["separation"][idx] * result["approach_directions"][i] ) tracer_quat = result["tracer_quaternions"][idx] # (4,)
Apply
tracer_comto the tracer’sstate.pos_candtracer_quatto itsstate.q, leave the central atresult["central_position"], and callsystem.collider.compute_force(state, system)to get the bisected force network.