v2.2.0
PhysicsNeMo General Release v2.2.0
Added
- Adds
ShardTensorsupport for GeoTransolver and FLARE models. - Adds zarr save/load for
MeshandDomainMeshvia tensordict's zarr
storage backend:physicsnemo.mesh.io.to_zarr/from_zarr, with
training-appropriate chunking and zstd compression.MeshReaderand
DomainMeshReadertransparently read zarr stores alongside
.pmsh/.pdmsh(opt in viapattern). Requires optionalzarr >= 3
and a tensordict release with the zarr backend. - Promotes GeoTransolver out of
experimentalto
physicsnemo.models.geotransolver.GeoTransolver, together with the FLARE
model (physicsnemo.models.flare.FLARE) and the reusable GALE and FLARE
attention layers (physicsnemo.nn.GALE,physicsnemo.nn.GALEBlock,
physicsnemo.nn.FLARE). The embedded OOD guard is decoupled from the model.
Wrap a constructed GeoTransolver with
physicsnemo.experimental.guardrails.embedded.GuardedGeoTransolver(or
attach_ood_guard) to enable out-of-distribution guarding. PhysicsNeMo removes
theguard_configmodel argument. Legacy import shims keep the pre-move
physicsnemo.experimentalimport paths working and emit a
LegacyFeatureWarningpointing to the new locations. - Adds
zenith_azimuth_anglesandzenith_azimuth_angles_from_timestampto
physicsnemo.utils.zenith_angle, returning
(sin_zenith, cos_zenith, sin_azimuth, cos_azimuth)alongside the existing
cos_zenith_angle/cos_zenith_angle_from_timestamphelpers. The azimuth
follows the north-clockwise convention. - Adds
physicsnemo.nn.shrink_and_perturb_, an in-place shrink-and-perturb
weight re-initialization for warm-starting from pretrained weights. - Adds dimension-generic volume mesh generation for implicit domains to
physicsnemo.mesh.generate.mesh_implicit_domainmeshes
{x : phi(x) < 0}, clipped to the bounding box (box faces are honored
as a boundary, so that external-flow "box minus obstacle" domains work
directly), for any implicit function (signed-distance functions, level
sets, or neural fields). - Adds compile-safe subclassing extension points to
domain_parallel.ShardTensor
(_extra_inner_tensors,__subclass_flatten_context__/__subclass_unflatten__,
_stable_inner_sentinel, and a DTensor-style__metadata_guard__), so a subclass can
carry extra inner tensors and opaque metadata throughtorch.compilewithout
re-implementing the flatten protocol. Base behavior unchanged. - Adds
ShardTensor._subclass_propagated_attrs: attribute names base__torch_function__
copies from an op input onto its eager op-result, re-classing it to the subclass. Skipped
under compile; empty by default. - Adds
install_aot_plain_tangent_coercion(run on import): rebuilds a plain backward
cotangent into aShardTensorwhen a boundary crosses a Dynamo graph break, instead of
AOTAutograd raising "guessed its metadata incorrectly".__coerce_same_metadata_as_tangent__
now also coerces down to a plain tensor at a replicated boundary. - Adds
domain_parallel.shard_utils.halo_scatter: atorch.compile-safe halo
scatter-correction primitive forShard(0)ShardTensors with a borrowed-ghost overlay.
halo_scatter_correctfuses the fold-to-owner / refresh-ghost exchanges into a self-adjoint
custom_op(correct forward and backward underaot_eagerand inductor), with routing
passed as a packed graph-input tensor so it survives graph breaks;
register_halo_scatter_handlerswires it ontoscatter_add/index_add. The row
transport is a pluggable backend (select_halo_backend,PHYSICSNEMO_HALO_BACKEND):
a portablefuncolpath and an intra-node symmetric-memory (CUDA-IPC) path. - Extends
halo_scatterwithpack_halo_routing(cap=)fixed-shape routing (for compiled
dynamic=Falseruns), an in-placescatter_add_/index_add_dispatch handler, and
node-locality routing inselect_halo_backend(single-node uses symm-mem, multi-node falls
back tofuncol). - Adds a
ShardTensor.grad_dtypeproperty override (returns the local tensor's dtype)
so a newer-PyTorchgrad_dtyperead during Dynamo fake conversion doesn't fall back
to a non-leaf DTensor and break compile. Mirrors thegrad_fn/is_leaf/grad
shields. - Adds
integrate_momentandMesh.integrate_momentfor measure-weighted
outer-product moments. Mesh integration APIs now acceptnan_policy. - Adds per-cell measure weights that are preserved through cell subsampling
and consumed by mesh integration routines and GLOBE. - Adds a
global_shapeargument toShardTensor.from_local, enabling the
no-communicationsharding_shapes="chunk"path. - Adds exact-boundary quality mesh generation to
physicsnemo.mesh.tessellation:fill_interiortakes a closed
codimension-one boundaryMesh(2D edge loops today; loops in any order
and orientation, with holes, multiple components, and nested islands
resolved automatically) and fills the interior with quality simplices via
constrained Delaunay triangulation with Ruppert refinement — every input
vertex is preserved bit-identically, every output triangle meets the
guaranteed minimum-angle bound, output is aMeshwith provenance
point_data, deterministic, with optional bound-preserving ODT smoothing.
The contract is dimension-generic;n = 3raisesNotImplementedError
pending exact boundary recovery. Also addspolygon_interior_point,
which returns a point strictly inside a simple polygon. - Adds
rectilinear_grid_divergence,rectilinear_grid_curl, and
rectilinear_grid_laplaciantophysicsnemo.nn.functional, with Torch and
fused Warp implementations for periodic, nonuniform rectilinear grids. - Adds triangle-surface remeshing with NVIDIA Warp on CPU and CUDA, including
remesh,Mesh.remesh, topology cleanup, barycentric point-data transfer,
direct or attached linear-resolution-field control, and advanced tensor-level
tuning. - Adds coverage reporting on PRs — an informational
Coverage %check plus a
ready-to-enable Codecov integration. - Adds differentiable mesh morphing: Torch-backed dense
displace_points/
Mesh.displaceand Torch/NVIDIA Warp compact sparse-control
morph_points/Mesh.morph/DomainMesh.morph. - Adds differentiable Sobolev mesh deformation through
sobolev_deform_pointsandMesh.sobolev_deform. A matrix-free,
uniform-mass P1 Helmholtz solve smooths dense per-vertex displacements and
their adjoints, with optional fixed-point constraints. Torch and CUDA Warp
backends provide explicit implicit-adjoint differentiation. - Adds thin-plate-spline radial-basis deformation through
radial_basis_function_deform_points,
Mesh.radial_basis_function_deform, and
DomainMesh.radial_basis_function_deform. PyTorch performs the differentiable
coefficient solve. Torch and fused NVIDIA Warp backends evaluate the field. - Adds differentiable lattice free-form deformation with Torch and NVIDIA Warp
backends: dimension-genericfree_form_deform_points/
Mesh.free_form_deform/DomainMesh.free_form_deformwith Bernstein
(classic FFD) and locally supported uniform cubic B-spline bases, plus
node-interpolatinglinear,cubic_hermite, andquintic_hermitemodes. - Adds fixed-topology
simplex_strain_energy,simplex_measure_energy,
total_measure_energy,simplex_inversion_energy,
closed_surface_volume_energy, andsurface_bending_energyto
physicsnemo.nn.functional, with mesh-aware wrappers in
physicsnemo.mesh.deformation. Torch supports higher-order derivatives,
and Warp provides first-order GPU kernels. - Adds differentiable nearest-surface shrinkwrap through
shrinkwrap_pointsandMesh.shrinkwrap. Torch provides the reference
search, NVIDIA Warp acceleratesfloat32nearest-face queries on CPU and
CUDA. Both backends replay the selected projection with PyTorch autograd.
Triangulated examples demonstrate weighted panel conformance and partial
design-region projection onto a shape-optimization constraint. - Adds
uniform_grid_divergence,uniform_grid_curl, and
uniform_grid_laplaciantophysicsnemo.nn.functional, with Torch and fused
Warp implementations for periodic Cartesian grids. - Adds the experimental Strata weather-emulation models —
physicsnemo.experimental.models.strata.StrataandStrataTransformer3D— plus
the continuous / stereographic RoPE helpersbuild_rope_cos_sin_1d_continuous,
build_axial_rope_cos_sin_2d_continuous,stereographic_projection, and
spherical_centroidinphysicsnemo.experimental.nn. - Adds Point-Transformer local vector-attention blocks to
physicsnemo.nn. - Adds an
is_causaloption toTimmSelfAttentioninphysicsnemo.nnfor
causal self-attention. - FSDP2 checkpoint support: full save/load round-trip for
torch.distributed.fsdpv2 models, including DTensor edge cases,
cross-mesh reloads, and optimizer state loading. - Migrated the StormCast example from DDP + Domain Parallel to FSDP2 +
Domain Parallel. StormCast previously usedFullyShardedDataParallel
withShardingStrategy.NO_SHARD(equivalent to DDP) alongside domain
parallelism; it now uses the FSDP2fully_shardAPI, producing 2D-mesh
DTensor parameters whenuse_shard_tensoris enabled. - Adds tensor-returning
Mesh.gradient,Mesh.divergence,Mesh.curl, and
Mesh.laplacianconvenience methods tophysicsnemo.mesh, mirroring
Mesh.integrate(each returns a tensor and accepts a data key or a raw
tensor, with adata_source="points"|"cells"kwarg selecting vertex or
cell-centered fields). This gives the discrete differential operators a
consistent, discoverable surface onMesh; previously divergence/curl/
laplacian were reachable only as free functions inphysicsnemo.mesh.calculus.
Addscompute_divergence_cells_lsqandcompute_curl_cells_lsqfree
functions (cell-centered LSQ analogues); DEC operators and the cotangent
Laplacian remain vertex-only and raiseNotImplementedErrorfor cell data. - Adds
farthest_point_samplingtophysicsnemo.nn.functional, a greedy
farthest-point sampling (FPS) functional for point clouds. - Adds
FourierPositionalEmbeddingtophysicsnemo.nn, a deterministic
axis-wise (NeRF-style) Fourier positional embedding for continuous
coordinates with no learnable parameters. - Adds radiation transport example (
examples/nuclear_engineering/radiation_transport) - Adds agent skills structure, and initial skill for 'discoverability'.
- Adds the experimental AeroJEPA model
(physicsnemo.experimental.models.aerojepa.AeroJEPA), a joint-embedding
predictive architecture for 3D aerodynamic fields composing context and
target encoders, a query-token field decoder, and a JEPA predictor head,
together with its SIGReg, token-latent, and reconstruction loss family.
The generic point-cloud tokenizer and the batch/mask/k-NN helpers are added
underphysicsnemo.experimental.nn; the local point-transformer attention
blocks it composes come fromphysicsnemo.nn. - Adds the AeroJEPA SuperWing tutorial recipe
(examples/cfd/external_aerodynamics/aerojepa), an end-to-end Hydra-driven
workflow covering dataset download, normalization, JEPA training, chunked
inference, field-error plots, and CL/CD post-processing. - Adds xDeepONet to experimental models
(physicsnemo.experimental.models.xdeeponet.DeepONet). A single
dimension-generic (2D/3D) DeepONet that accepts a spatial or MLP branch,
an optional trunk, and an optional second branch asnn.Moduleinputs
(dependency injection). Six forward-call conventions cover trunked,
trunkless, packed/auto-padded, and xFNO-style time-axis-extend modes.
Supports multi-channel output, multiple decoder types (MLP, Conv,
temporal projection), composable Fourier / UNet / Conv spatial branches
(SpatialBranch), and coordinate features. - Adds
FNO4DWrapperto the xdeeponet package: a thin wrapper around the
libraryphysicsnemo.models.fno.FNO(dimension=4) that adds
autoregressive time-axis extension over(B, X, Y, Z, T, C)inputs (predict
aK-step forecast horizon viatarget_times). Use
physicsnemo.models.fno.FNO(dimension=4)directly when the time-axis
extension is not needed. 3D FNO / Conv-FNO / U-FNO operators are expressed
asDeepONet(trunk=None, dimension=3)with a Fourier/UNet/Conv
SpatialBranch. - Adds
Sinelementwise sine activation tophysicsnemo.nn, registered
inACT2FNso it can be looked up by name (get_activation("sin")). - Adds active-learning recipe for external-aerodynamics surrogates
(examples/cfd/external_aerodynamics/active_learning_aero/). Iteratively
fine-tunes a GP-augmented GeoTransolver onto an out-of-distribution
target class by scoring unlabeled candidates with a joint UQ signal
(GP-vs-integrated-drag disagreement + GP posterior std) and selecting
the top-kper round. Built on thephysicsnemo.active_learning
protocols andphysicsnemo.experimental.uq.VariationalGPHead, with a
layered structure (generic AL driver / GP-UQ recipe / aero adapter)
designed for reuse on other UQ-based regression problems. - Adds
FieldVariationalGPHeadtophysicsnemo.experimental.uq, a pointwise
independent multitask variational GP head for per-point, multi-channel field
uncertainty. It is the field sibling ofVariationalGPHead(which pools a
geometry to one embedding and predicts a scalar): it keeps the point dimension
and returns one Gaussian posterior per point per channel, so a single forward
pass yields the field prediction, the total predictive variance and the
epistemic-only variance — no ensembling or MC-Dropout. Backbone-agnostic (it
consumes only a(..., input_dim)feature tensor), with an optional DKL MLP,
a Matérn ARD kernel (5/2 by default), float64 GP internals, anl2_radialfeature
normalization that preserves the radial out-of-distribution cue, and an
optional heteroscedastic observation-noise MLP. Includes a surface field-GP
training recipe for GeoTransolver
(examples/cfd/external_aerodynamics/transformer_models/src/train_field_gp.py). - Adds a
return_point_featuresforward flag to
physicsnemo.models.geotransolver.GeoTransolver, which additionally returns
the per-point latents computed just before the output projection. These are
the features a pointwise head such asFieldVariationalGPHeadconsumes. - Adds
LatentNoveltyQueryStrategyto the active-learning aero recipe,
a third acquisition strategy that ranks unlabeled samples by their
average kNN cosine distance in the encoder's learned geometry latent
— reusing the sameOODGuard
(physicsnemo.experimental.guardrails.embedded) that flags
out-of-distribution inputs at inference time. The guard is calibrated
on the currently labeled set each round; round 1 falls back to
class-balanced random because the calibration buffer is empty. New
publicOODGuard.score_geometry()method exposes the raw per-sample
geometry-latent kNN distance as a continuous score for downstream
consumers (e.g. AL acquisition) without the boolean thresholding /
warning emission ofOODGuard.check(). - Adds rotary position embedding (RoPE) modules to
phyiscsnemo.nnand
integrates support for 2D RoPE in the neighborhood attention backend
ofDiTlayers. - Adds support for RoPE, dynamic invalid-region masking, and a new
ConvDetokenizerinphyiscsnemo.models.DiT. Invalid regions are supplied
per forward call via theinvalid_maskargument ofDiT.forward(a
per-sample, batch-variable pixel mask, domain-parallel safe), replacing
flagged tokens with a learned mask token. - Adds an inference script (
src/infer.py+conf/infer.yaml) to the
Unified External Aero Recipe
(examples/cfd/external_aerodynamics/unified_external_aero_recipe),
with integrated aerodynamic force/moment coefficients (src/forces.py:
CD/CL/CS/CMR/CMP/CMY). The script is model/dataset-agnostic, writes one
native.pdmshDomainMeshper sample (carrying physical-unit
pred_<field>/true_<field>), reports training-space metrics
(matching the training/validation loop), and reuses the trainer's
dataloader / collate / metric tooling (refactored intodatasets.py
andutils.py). - Adds
physicsnemo.mesh.spatial.signed_distance_field, aMesh-typed
wrapper over the Warp-backedphysicsnemo.nn.functional.signed_distance_field
op (CPU and CUDA), returning(sdf, hit_points, hit_faces)per query. The
sign comes from Warp's angle-weighted pseudo-normal (robust at
sharp/non-convex edges) or, withuse_sign_winding_number=True, its
generalized winding number (robust on non-watertight meshes).
(Near-)degenerate faces, which the Warp mesh query would otherwise skip,
are repaired into equivalent thin-but-valid triangles before the query.
Supersedes and removes the private datapipes implementation
(physicsnemo.datapipes.transforms._sdf_torch/_sdf_triton); the public
datapipes SDF transform delegates here. - Added an iterable style dataset to physicsnemo datapipes, for on-the-fly gpu simulations.
- DPS guidance now supports non-uniform guidance strength: the
std_yand
gammaarguments ofphysicsnemo.diffusion.guidance.ModelConsistencyDPSGuidance
/DataConsistencyDPSGuidanceand their
physicsnemo.diffusion.multi_diffusioncounterparts accept tensors as well as
floats. A tensor assigns a different measurement-noise level / SDA scaling to
each observation component, e.g. per-channel ((1, C, 1, 1)) or pointwise
(full observation shape). Passing floats keeps the previous uniform
behavior unchanged. - Adds
relative_mseandrelative_l2(target-normalized regression errors,
relative_l2 = sqrt(relative_mse)) tophysicsnemo.metrics.general
(relative_error.py), with optional elementweightsanddim-based
reduction matchinggeneral.mse. physicsnemo.metrics.general.msemse/rmsegain an optionalweights
argument for a masked/weighted mean (backward-compatible;weights=None
reproduces the prior unweighted result).- Adds a kinetic Monte Carlo (KMC) surrogate example
(examples/kinetic_monte_carlo): a probabilistic autoregressive surrogate
(ParticleGeoTransolver) that emulates a KMC event stream, predicting the
next event (the new particle's features and inter-event delay) from the
current particle population, an optional background mesh, and the simulation
time. Independent rollouts form an ensemble for uncertainty quantification.
Changed
- Splits the monolithic
physicsnemo.diffusion.noise_schedulers.noise_schedulers
andphysicsnemo.diffusion.samplers.solversmodules into one module per class,
named after the schedule or solver it defines, with theNoiseSchedulerand
Solverprotocols in abase.pyof their respective sub-package.
Implementations are unchanged and every class is still re-exported from
physicsnemo.diffusion.noise_schedulersandphysicsnemo.diffusion.samplers,
so the public import paths stay the same. The two old module paths remain as
deprecated shims that re-export the same classes and raise a
DeprecationWarningon import, so existing code keeps working. Import from
physicsnemo.diffusion.noise_schedulersandphysicsnemo.diffusion.samplers
instead. physicsnemo.nn.functional.signed_distance_fieldnow returns a 3-tuple
(sdf, hit_points, hit_faces)—hit_facesis the int64 index of the
triangle holding each closest point. Queries with no triangle within
max_distnow returnNaNdistance/hit point and a-1face index
(previously the out-of-band results were undefined: the kernel read from
an uninitialized face index). Mesh-index range validation on CUDA inputs is
now a device-side assert instead of a host-synchronizing check, so the op
is safe on a sync-free prefetch stream; the eagerValueErroris kept on
CPU.- Optimizes the production container build by consolidating related filesystem
operations, using BuildKit bind and cache mounts, and separating custom,
declared, and project dependency installation. Reduces total physicsnemo layers
by around 78%. GeoTransolver.forward'sreturn_embedding_statesandreturn_point_features
are now keyword-only. They share a return signature, so a positionalTruedid
not say which was meant. Callers already passing them by keyword are unaffected.ShardTensor.redistributenow computes receive shapes analytically when
sharding shapes are known, skipping the shape-negotiationall_to_all
collective (falls back to the collective only when shapes are unavailable).- PhysicsNeMo-Mesh tensor-valued gradients now consistently use the documented
derivative-first layout(entity, spatial_dimension, *value_shape)across
LSQ, intrinsic LSQ, and DEC. Earlier LSQ releases returned
(entity, *value_shape, spatial_dimension)instead; migrate a stored legacy
gradient withlegacy_gradient.movedim(-1, 1). Divergence and curl values
are unchanged. - xDeepONet
SpatialBranch
(physicsnemo.experimental.models.xdeeponet.SpatialBranch) now supports
mixed-precision (AMP/autocast) training: FFT-based spectral convolutions are
evaluated in float32 internally (cuFFT lacks complex-half support) while the
rest of the branch uses autocast. This is a no-op under full precision, so
fp32 outputs are unchanged. Also fixes a stale module docstring that
referenced removed trunk/MLP-branch builder helpers. physicsnemo.mesh.remeshing.remeshnow raisesNotImplementedErrorfor
non-2D-in-3D inputs (the remeshing implementation is surface-only) instead
of failing confusingly downstream, and its docstring reflects that
restriction.physicsnemo.mesh.spatial:BVH.from_meshandClusterTree.from_pointsnow
share a single morton-LBVH node-topology builder (spatial/_lbvh.py),
removing ~80 lines of duplicated build logic; construction output is
byte-identical.BVH.from_meshnow defaults toleaf_size=1(was 8),
matchingClusterTree.from_pointsand measured to be more performant across
platforms (smaller leaves yield fewer candidate cells per query). Containment /
nearest-cell query results are unchanged. Adds the first direct unit tests for
ClusterTree(construction invariants, aggregates, dual-tree cover).physicsnemo.meshperformance: eliminated host-device syncs on hot paths.
Cached topological adjacencies now store theAdjacencyobject directly instead
of reconstructing it (which re-ran its syncing__post_init__validation) on every
lookup — making cached adjacency lookups ~120x faster on GPU (~335us → ~3us for a
10k-point sphere); the BVH leaf-hit expansion drops two per-traversal-level syncs;
and the Laplacian smoother reuses its per-iteration buffers in place instead of
reallocating them.physicsnemo.mesh.Mesh.slice_cellsnow acceptsNone/Ellipsis(keep all
cells, return self), matching its type hint andslice_points;
gaussian_curvature_cellsreuses the cachedgaussian_curvature_vertices
property instead of recomputing it.physicsnemo.mesh.Meshconvenience methods now directly reuse shared
canonical functions, removing duplicate implementation bodies and docstrings.
This includes geometric, deformation (including radial-basis-function
deformation), calculus, topology, visualization, and validation operations.physicsnemo.mesh:drawandvalidateare now the canonical standalone
names matchingMesh.drawandMesh.validate. Thedraw_meshand
validate_meshremain as pending-deprecation compatibility names.
Mesh.validateandDomainMesh.validateshare the canonical validation
option order, preserve the historical positionaltoleranceargument, and
expose the newcheck_self_intersectionoption as keyword-only.physicsnemo.mesh:validate(check_self_intersection=True)now raises
NotImplementedError(the check is unimplemented) instead of silently returning a
Nonesentinel that masquerades as "no self-intersections found".physicsnemo.meshquality metrics now use a normalized
aspect ratio of longest edge to minimum altitude. The metric is dimensionless and
scale-invariant for simplices of every manifold dimension, and a regular
simplex now hasaspect_ratio=1andquality_score=1. This intentionally
corrects the previous erroneous aspect-ratio and quality-score values.Mesh.quality_metricsandMesh.statisticsagain use explicit property
getters so their class-facing documentation describes argument-free property
access. Configurable statistics tolerance remains available through the
standalonecompute_mesh_statisticsfunction.- Performance improvements in the diffusion module: reduced peak memory of
DPS-guided diffusion sampling most notably for multi-diffusion at large
domains. A guidedsample()loop run undertorch.no_grad()now detaches the
state between solver steps, so the guidance autograd graph is no longer
accumulated across the sampling trajectory (sampled outputs are unchanged;
usetorch.no_grad(), nottorch.inference_mode()). Also expands CI test
coverage and adds an API documentation page for
physicsnemo.diffusion.multi_diffusion. - Performance improvements in IO prefetching and GPU preprocessing in physicsnemo datapipes.
⚠️ BC-impact (DPS guidance): a customnormcallback passed to
physicsnemo.diffusion.guidance.ModelConsistencyDPSGuidance/
DataConsistencyDPSGuidance(and theirphysicsnemo.diffusion.multi_diffusion
counterparts) must now return an elementwise loss (same shape as its
inputs) instead of a per-batch-element reduced scalar of shape(B,).
Migration: drop the reduction from yournorm, e.g. return
(y_pred - y_true).abs().pow(2)rather than
(y_pred - y_true).pow(2).reshape(B, -1).sum(dim=1). For
DataConsistencyDPSGuidance(and itsmulti_diffusioncounterpart) the
normcallback now also receives the unmasked(x_0, y)and the mask is
applied to its output (mask * norm(x_0, y)), where it previously received
the pre-masked(mask * x_0, mask * y); the two agree for the built-inLp
norms, but a customnormthat relies on unobserved entries being zeroed
before the call may differ. The integernormselector (e.g.norm=2) is
unaffected.Mesh.transformandcompute_cotan_weights_femnow use the non-checking
torch.linalg.inv_ex/solve_exsolvers, and build their index tensors on
device. The checked solvers read a status code back to the host on every call,
which synchronizes on CUDA; removing that and the index-tensor uploads takes
Mesh.transformon a cached codimension-one mesh from three host
synchronizations to one, andcompute_cotan_weights_femfrom six to three. As
a consequence,
Mesh.transform(..., assume_invertible=True)no longer raises when the matrix
is in fact singular: it propagates NaN caches instead, as its docstring now
documents. The defaultassume_invertible=Nonestill tests the determinant
and is unaffected.physicsnemo.experimental.uq.VariationalGPHeadnow takesn_trainas a
required keyword-only argument, along with every argument afterinput_dim.
It was annotated optional while the constructor raised onNone, so callers
that already pass it by keyword are unaffected. It also gainsmatern_nu,
which was previously hardcoded to 2.5 (still the default).
Deprecated
physicsnemo.mesh.calculus.integrate_cell_dataandintegrate_point_data
are deprecated in favor ofintegrate(..., data_source="cells"|"points").
Compatibility wrappers remain available for this release and emit
LegacyFeatureWarning.
Fixed
MeshReader/DomainMeshReadersample discovery no longer uses
pathlib.Path.glob, which can silently drop entries under filesystem
metadata-server load (Lustre), causing training to proceed on a subset
of the dataset.- Unified external aerodynamics volume datasets now preserve in-file boundaries
by default, so GLOBE can resolveboundaries.vehicleduring collation.
Point-based volume model templates explicitly opt into the existing
boundary-dropping reader optimization. compute_cotan_weights_fem, and the calculus, curvature, and smoothing
routines built on it such asMesh.laplacian, no longer fail on degenerate
cells in float32. The Gram-matrix regularization is now scale-free, so it also
covers cells with no extent — including the null cells thatMesh.padand
Mesh.pad_to_next_powerinsert — and flat cells at large coordinate values,
both of which previously raised a singular-matrix_LinAlgErrorfrom
torch.linalg.inv. Weights for non-degenerate cells are unchanged bit for bit.- Multinomial index sampling now uses one shared
weighted_multinomial
functional across datapipes, DoMINO, and remeshing. Its core API follows
torch.multinomial, adds allocation-free integer input for uniform
populations, and supports sampling with or without replacement. Exact
sampling without replacement usestorch.randpermor a chunked exponential
race, with an explicit low-memory Poisson-gap approximation for uniform
sampling. This removes thetorch.multinomial2^24category limit for
sampling without replacement, consolidates duplicated Poisson index
samplers, and fixes incorrect chunk-local indices and biased per-chunk quotas
in DoMINO. - Unified external aerodynamics recipe: the aggregate metrics reported for
vector fields under the bare field name (e.g.wss_l2, likewise_l1/
_mae) were computed on per-point vector magnitudes, so direction errors
were invisible — a prediction with the correct magnitude but wrong direction
at every point scored 0. The bare-name aggregate is now computed over all
components jointly (whole-field relative norms, Frobenius forl2). The
broken magnitude-only aggregate is not retained under a separate key.
Per-component metrics (wss_x_l2, ...) were always direction-sensitive and
are unchanged, and training/checkpoints are unaffected (the training
objective goes throughLossCalculator, not this metric path) — only
reported aggregate vector metrics were misleading. - Unified external aerodynamics recipe: model templates can now carry
known-good training overrides (train.yaml's_self_merges before the
model template; all existing templates resolve identically). The GLOBE
example now uses the recipe's defaultcompileand learning-rate
settings — both measured equivalent or better than the previously
documented overrides on the DrivAerML surface case — and no longer sets
training.field_weights={pressure: 1.0, wss: 100.0}, which was redundant
withNormalizeMeshFieldsnormalization and starved the pressure field
of gradient signal (~2x worse converged pressure L2 at equal WSS L2). ShardTensornow survivestorch.compile/ AOTAutograd for tensor-subclass
users:__tensor_unflatten__no longer forcesrequires_gradon the
reconstructed inner (matching DTensor, so the inner/wrapper flags cannot
disagree and tripassert_metadata_equnder a Dynamo graph-break re-fake),
and__coerce_same_metadata_as_tangent__is subclass-friendly — it accepts a
subclass's nested flatten context, treats empty andNonesharding-shape maps
as equal, and rebuilds a differingShardTensor-subclass tangent via that
type's own__tensor_unflatten__instead of returningNone(the plain-tensor
/DTensorcross-typeNoneconvention is preserved).ShardTensor.to_local()(and op-result forwards feeding it) is now
differentiable undertorch.compile/ AOTAutograd. Previously the compiled
backward was silently dropped (zero / missing gradient): ShardTensor's
__torch_function__eager fallback converts toDTensorthrough
autograd.Functions that AOTAutograd traces through, severing the primal's
gradient connection during the joint trace. Under tracing, unpatched ops now
pass through to__torch_dispatch__(mirroringDTensor, which defines no
__torch_function__), keeping the graph differentiable while eager behavior
and registered shard patches are unchanged.- Datapipe contiguous-block subsampling now wraps cyclically, giving boundary
and interior elements equal inclusion probability. - Cell-subsampled GLOBE inputs now retain their effective integration measure,
preventing area-weighted outputs and gradients from collapsing. physicsnemo.mesh.io.from_pyvista(..., force_copy=True)now copies attached
point, cell, and global data as well as geometry. The matching new
to_pyvista(..., force_copy=True)option prevents exported PyVista geometry
and data from mutating the sourceMeshthrough shared CPU storage.physicsnemo.mesh.sampling.sample_data_at_pointsnow handles integer and
boolean fields by returningfloat64, so NaN sentinels and non-integral
interpolation or multi-cell means are representable (subject to the usual
float64precision limits). Point-data interpolation now promotes field and
geometry dtypes consistently, and accumulation uses fewer full-sized
temporaries and CUDA host synchronizations.physicsnemo.mesh.projections.extrudenow produces a conforming (crack-free)
simplicial complex for multi-cell inputs. Each prism was previously tessellated
using the per-cell local vertex order, so adjacent cells that listed a shared
edge's endpoints in different orders split the shared quad face along opposite
diagonals; the resulting non-manifold volume leaked interior crack faces into
get_boundary_mesh(boundary edges shared by 4 faces — e.g. an extruded L-shape
or any multi-column grid, which also brokerepair.fix_orientation). Parent-cell
vertices are now sorted into a global order before tessellation (the
Freudenthal-Kuhn subdivision), a no-op for already-sorted inputs.physicsnemo.mesh.generate.marching_cubesnow acceptsbfloat16fields by
converting them tofloat32before crossing the NumPy boundary.physicsnemo.mesh.projections.extrudenow returns consistently oriented cells
for full-dimensional (codimension-0) output.physicsnemo.mesh.remeshing.remeshnow preserves the input mesh's device and
floating dtype instead of dropping them to CPU/float32.physicsnemo.mesh.io.to_pyvistanow preserves supported dtypes for attached
point, cell, and global data instead of narrowing every array tofloat32.
Reduced-precision floating-point values are promoted only as needed for VTK.physicsnemo.mesh.io.from_pyvistaandto_pyvistanow preservefloat64
point coordinates instead of unconditionally narrowing geometry tofloat32,
which could collapse small features on meshes with large coordinate offsets.
Existingfloat32geometry remainsfloat32.physicsnemo.mesh:Mesh.to(<float dtype>)andDomainMesh.to(<float dtype>)
raisedTypeError: cells must have an int-like dtypebecause the cast was applied
to the integercellstensor. A floating/complex dtype is now applied only to
floating tensors; the integercells(and any integer data) are preserved. Device
moves are unchanged.physicsnemo.mesh: fixed several silent-wrong-result bugs —slice_cells
carried stale point-level and non-local (gaussian_curvature) caches onto the
sliced mesh; the intrinsic LSQ gradient returned all-zeros for codimension >= 2
manifolds (now estimates the tangent space via local PCA);smooth_laplacian
returned stale geometry caches after its in-place point update;transform
propagated an incorrect point-normals cache under anisotropic/shear maps; and the
derived-mesh methods (compute_point_derivatives,compute_cell_derivatives,
cell_data_to_point_data,point_data_to_cell_data) aliased the source mesh's
mutable_cache.physicsnemo.mesh.spatial.ClusterTree.compute_source_aggregatesnow
normalizes with its call-time area weights instead of the weights used when
constructing the tree, preserving correct aggregates when weights change.physicsnemo.mesh: fixed crash / data-integrity bugs —project(...)with
transform_point_data/transform_cell_data=Truemutated the input mesh in
place; visualization andto_pyvistacrashed on autograd-tracked tensors (now
detached before.numpy()); and integer/bool data crashed (safe_epson an
integer dtype) or truncated via integer division during facet/scatter
aggregation (now computed in a floating dtype).physicsnemo.meshMorton-code quantization now handles empty inputs, tiny
extents, half-precision coordinates, and one-dimensional endpoints correctly.physicsnemo.mesh: fixed Loop subdivision pulling open boundaries inward (now
applies the boundary/crease mask); subdivision zero-filling integer/bool
point_dataat new edge vertices (now inherits a parent label);
non-deterministic orientation flips and over-counted component sizes in
repair.fix_orientation; random point sampling drawing barycentric weights in
float32 for float64 meshes; andMesh.mergenot validatingpoint_data/
global_datakey consistency.- Fixed
DefaultTrainingLoopreadingDistributedManager.deviceat the class
level (apropertydescriptor) instead ofDistributedManager().device, which
left the loop's device set to apropertyobject under an initialized
DistributedManager(physicsnemo/active_learning/loop.py). - Replaced three plain-string regex / docstring literals containing invalid
escape sequences with raw-string equivalents
(physicsnemo/utils/logging/launch.py,
physicsnemo/metrics/general/calibration.py,
physicsnemo/metrics/general/crps.py); these wereSyntaxWarnings today
and becomeSyntaxErrors in Python 3.16. - Various test cleanups to remove self-inflicted warnings in CI output:
disabled pytest collection forTestModelA/TestModelBhelpers in
test/core/test_registry.pyvia__test__ = False; migrated
test/nn/module/test_interpolation.pyto call the non-deprecated
grid_to_point_interpolationand added a dedicated test for the
deprecation alias; scoped alr_scheduler.step()-before-optimizer.step()
UserWarningfilter to a single test in
test/optim/test_combined_optimizer.py; guarded the
DistributedManager.initialize()calls intest/utils/test_checkpoint.py
withis_initialized(); and suppressed the import-time
ExperimentalFeatureWarningintest/datapipes/healda/test_features.py
viawarnings.catch_warnings(). - Fixed
physicsnemo.utils.get_checkpoint_dirreturning paths with\
separators on Windows (e.g..\checkpoints_model), which was inconsistent
with the/-based paths used elsewhere in the checkpoint utilities and
broke thetest_get_checkpoint_dirCI test on Windows. The function now
always joins with/, working uniformly for local paths andfsspec
URIs (msc://, etc.) across operating systems.
Dependencies
- Raises the minimum TensorDict version to
tensordict[zarr]>=0.14.0,
restoring the stabletensordictdistribution while retaining Zarr support
and upstream bug fixes. - Removes
pyacvdfrom themesh-extrasoptional dependencies. Remeshing now
uses NVIDIA Warp. - Updates the minimum supported
warp-langversion to 1.14.0.
Contributors
We’re grateful to everyone who contributed code, fixes, documentation, reviews, and ideas to PhysicsNeMo v2.2.0. Your contributions help us continuously improve PhysicsNeMo for the entire community!
A special shout-out to our contributors, in no particular order:
@aayushg55, @fallintoplace, @fgiral000, @jleinonen, @ScSteffen, @wdyab, @zyhu-hu
Thank you ❤️ — we truly appreciate your contributions and hope to see more from you in the future!