Skip to content

v2.1.0

Choose a tag to compare

@ktangsali ktangsali released this 27 May 01:18
766e485

PhysicsNeMo General Release v2.1.0

Added

  • Adds GLOBE model (physicsnemo.experimental.models.globe.model.GLOBE),
    including new variant that uses a dual tree traversal algorithm to reduce the
    complexity of the kernel evaluations from O(N^2) to O(N).
  • Adds GLOBE AirFRANS example case (examples/cfd/external_aerodynamics/globe/airfrans)
  • Adds GLOBE DrivAerML example case (examples/cfd/external_aerodynamics/globe/drivaer)
  • Adds drop-test dynamics recipe.
  • Adds concrete dropout uncertainty quantification for GeoTransolver. Learnable
    per-layer dropout rates enable MC-Dropout inference for uncertainty
    estimates. Disabled by default (concrete_dropout: false).
  • Adds automatic support for FSDP and/or ShardTensor models in checkpoint save/load
    functionality
  • PhysicsNeMo-Mesh now supports conversion from PyVista/VTK/VTU meshes that may
    contain polyhedral cells.
  • In PhysicsNeMo-Mesh, adds Mesh.to_point_cloud(), .to_edge_graph(), and
    .to_dual_graph() methods. These allow Mesh conversion to 0D point clouds, 1D
    edge graphs, and 1D dual graphs, respectively, when connectivity information
    is not needed.
  • Adds physicsnemo.mesh.generate subpackage with marching_cubes for
    isosurface extraction from 3D scalar fields, returning a Mesh object.
    Supports the NVIDIA Warp backend.
  • Adds a type system to PhysicsNeMo-Mesh, allowing annotation of Mesh dimensions
    using notation like Mesh[2, 3] for a 2D manifold in 3D space.
  • Adds adjacency caching to PhysicsNeMo-Mesh Mesh objects, allowing efficient
    reuse of neighbor information.
  • Adds DomainMesh class for grouping an interior mesh with named boundary
    meshes and domain-level metadata, with passthrough geometric transforms
    (translate, rotate, scale, transform) and data operations.
  • Allows selective per-field transformation of Mesh objects: transform_point_data,
    transform_cell_data, and transform_global_data now accept bool | TensorDict
    (or plain dict for convenience).
  • Adds physicsnemo.mesh.remeshing subpackage with partition_cells() for
    creating Voronoi regions around seed points. BVH-accelerated.
  • Added support for 1D, 2D, and 3D neighborhood attention (natten) via
    physicsnemo.nn.functional interface, with full ShardTensor support.
  • Added derivative functionals in physicsnemo.nn.functional for
    uniform_grid_gradient, rectilinear_grid_gradient,
    spectral_grid_gradient, meshless_fd_derivatives, mesh_lsq_gradient,
    and mesh_green_gauss_gradient.
  • Adds physicsnemo.sym module for symbolic PDE residual computation
    (PhysicsInformer). Users define PDEs via SymPy and select a gradient method
    (autodiff, finite_difference, spectral, meshless_finite_difference,
    least_squares); spatial derivatives are computed automatically using the
    nn.functional.derivatives functionals.
  • Ports all physics-informed examples (LDC PINNs, Darcy, Stokes MGN, DoMINO,
    datacenter, xaeronet, MHD/SWE PINO) to the new physicsnemo.sym interface,
    replacing the separate physicsnemo-sym package dependency. Geometry is now
    handled via physicsnemo.mesh and PyVista.
  • Added geometry functionals in physicsnemo.nn.functional for
    mesh_poisson_disk_sample, mesh_to_voxel_fraction, and
    signed_distance_field.
  • Adds embedded OOD guardrail OODGuard at
    physicsnemo.experimental.guardrails.embedded, optionally
    wired into GeoTransolver via a new guard_config constructor argument.
    The guard calibrates per-channel global bounds and a geometry-latent
    kNN threshold during training, and emits warnings on out-of-distribution
    inputs at inference.
  • In PhysicsNeMo-Mesh, physicsnemo.mesh.geometry now publicly exposes
    stable_angle_between_vectors and compute_triangle_angles (previously
    only available via the private physicsnemo.mesh.curvature._utils).
  • PhysicsNeMo Datapipes enables reproducability through torch.generator
    utilities.
  • PhysicsNeMo Datapipes now supports physicsnemo.mesh.Mesh and
    physicsnemo.mesh.DomainMesh objects for deserialization, with
    transformations and utilities for mesh-based datasets.
  • PhysicsNeMo Datapipes now support MultiDataset construction,
    allowing on-the-fly construction of multi-source composite datasets
    that can be sampled and processed efficiently and coherently
    as one dataset.
  • PhysicsNeMo Datapipes also support random augmentations for
    mesh-based datapipes, leveraging torch.distributions for
    broad random distribution support. Mesh and DomainMesh
    datasets allow random translation, scaling, and rotation
    of mesh data in coherent ways, compatible with reproducability
    features of physicsnemo datapipes.
  • Adds a new unified training recipe for external aerodynamics
    that supports training on multiple datasets (DrivaerML, ShiftSUV,
    HighLiftAeroML, or more, bring your own, mix and match), supports
    training several different models (Domino, Transolver, GeoTransolver,
    Flare, GeoTransolver with Flare-attention, bring your own!). Leverages
    mesh datasets and non-dimensionalization to enable dataset mixing and
    matching at runtime. Train with surface or volume data.
  • Adds a new physicsnemo.diffusion.multi_diffusion subpackage that
    scales 2D diffusion models to large domains via patch-based training
    and inference. Provides MultiDiffusionModel2D (wraps a base model and
    handles state patching, conditioning preprocessing, positional-embedding
    injection, and per-patch output fusion), the
    MultiDiffusionMSEDSMLoss / MultiDiffusionWeightedMSEDSMLoss losses
    for patch-based DSM training, and MultiDiffusionPredictor for
    sampling (plugs straight into sample() / get_denoiser() and the
    standard solvers). Patching primitives (BasePatching2D,
    GridPatching2D, RandomPatching2D) are exposed under the same
    subpackage and are torch.compile-friendly with fullgraph=True.
    MultiDiffusionPredictor supports memory-efficient inference on
    large domains via chunk_size and use_checkpointing. The
    subpackage also ships patch-local DPS guidance:
    MultiDiffusionDPSScorePredictor (drop-in score predictor that plugs
    into the standard sampling stack),
    MultiDiffusionDataConsistencyDPSGuidance for inpainting and sparse
    data assimilation, and MultiDiffusionModelConsistencyDPSGuidance for
    generic patch-local observation operators. Use these instead of the
    global DPSScorePredictor to run guided sampling on domains that
    would otherwise OOM.
  • Adds "epsilon" as a supported prediction type throughout the diffusion
    framework, alongside the existing "x0" and "score" modes. A new
    PredictorType = Literal["x0", "score", "epsilon"] alias in
    physicsnemo.diffusion.base is wired through losses (MSEDSMLoss,
    WeightedMSEDSMLoss, and the multi-diffusion losses), preconditioners,
    samplers / solvers, DPS guidance, and noise schedulers, enabling
    end-to-end training and sampling of epsilon-parameterized models.
    Losses gain an epsilon_to_x0_fn kwarg used for the epsilon-to-x0
    conversion required during DSM training.
  • Adds DiffusionUNet3D 3D U-Net diffusion backbone for volumetric data at
    physicsnemo.experimental.models.diffusion_unets. Implements the
    DiffusionModel protocol. Exposes reusable 3D building blocks
    (Conv3D, GroupNorm3D, UNetAttention3D, UNetBlock3D) at
    physicsnemo.experimental.nn.
  • Added support for Batched radius search, which enables Domino
    and GeoTransolver with local features and batch size > 1.
  • Added the underfill recipe.

Changed

  • Improved crash recipe with configurable stats directory.
  • physicsnemo.mesh.sampling.find_nearest_cells uses a KNN-backed
    implementation, and no longer accepts the bvh=, chunk_size=,
    max_rounds=, or max_candidates_per_point= parameters.
  • ⚠️ BC-impact (deep imports): internal physicsnemo.nn.functional
    modules were reorganized by category. Public top-level functional imports are
    unchanged, but code importing internal module paths directly (for example
    physicsnemo.nn.functional.knn or
    physicsnemo.nn.functional.radius_search) should migrate to
    physicsnemo.nn.functional.neighbors.*.
  • Consolidated Warp interpolation kernels for grid-to-point and point-to-grid
    backends, and added missing kernel/helper docstrings.
  • In PhysicsNeMo-Mesh, dual-mesh primitives gained closed-form fast paths
    for triangle meshes embedded in 3D. compute_circumcenters is up to
    ~10000x faster (e.g. 11 s -> ~1 ms on a 360 K-triangle AirFRANS mesh,
    RTX 4090) by replacing batched torch.linalg.lstsq over (2, 3) systems
    with a closed-form cross product, and compute_vertex_angles is up to
    ~15x faster on the same meshes by replacing the dimension-agnostic
    Gram-determinant formula with an atan2(||cross||, dot) formulation.
    Anything that depends on these (Gaussian curvature, FEM Laplacian,
    cotangent weights, Voronoi areas, smoothing) inherits the speedup. See
    perf.md for the full audit.
  • In PhysicsNeMo-Mesh, BVH construction is faster on GPU.
    _compute_morton_codes has a CUDA-specific fused-bits path that
    eliminates the n_bits sequential kernel launches of the previous
    bit-loop (5-8x speedup on small / medium meshes), and BVH.from_mesh
    reuses the cached Mesh.cell_centroids instead of recomputing.
    End-to-end BVH.from_mesh is ~2x faster on a 162 K-tet cube_volume
    mesh.
  • In PhysicsNeMo-Mesh, the topology-dedup APIs
    (categorize_facets_by_count, find_edges_in_reference,
    remove_duplicate_cells, build_adjacency_from_pairs) gained optional
    index_bound / n_targets parameters. When the caller passes a strict
    upper bound (typically mesh.n_points or mesh.n_cells), the implicit
    tensor.max().item() GPU sync is avoided and the dedup uses a packed
    int64 unique (via the new internal unique_index_tuples) and a single
    composite-key argsort. End-to-end get_boundary_edges and
    cell_to_cells_adjacency are ~2x faster on practical-size unstructured
    meshes (e.g. 360 K-triangle AirFRANS).
  • ⚠️ BC-impact (deep imports): in PhysicsNeMo-Mesh,
    stable_angle_between_vectors and compute_triangle_angles moved from
    physicsnemo.mesh.curvature._utils to physicsnemo.mesh.geometry._angles.
    The old private path is no longer available; use the
    physicsnemo.mesh.geometry re-export instead.
  • ⚠️ BC-impact (pre-release rename): in PhysicsNeMo-Mesh,
    DomainMesh.apply was renamed to DomainMesh.apply_to_meshes. The
    original name shadowed the recursive Tensor -> Tensor apply method
    that @tensorclass auto-injects, breaking duck-type symmetry with
    Mesh.apply for any code that handled both classes. After the rename,
    dm.apply(tensor_fn) works as expected (recurses through every leaf
    tensor in interior, boundaries, and global_data); the original
    Mesh-to-Mesh broadcast is now dm.apply_to_meshes(mesh_fn). Early
    adopters of the unreleased DomainMesh API should rename their
    .apply(...) callsites to .apply_to_meshes(...).
  • Refactored the patching utilities under
    physicsnemo.diffusion.multi_diffusion.patching. Patching and fusion
    operations are now more performant and torch.compile-friendly (e.g.
    fullgraph=True,error_on_recompile=True).
  • Refactored the examples/geophysics/diffusion_fwi full-waveform
    inversion example to use the consolidated physicsnemo.diffusion API
    (preconditioners, samplers, losses, DPS guidance) and removed the
    recipe-local copies of these utilities under utils/.
  • Refactored the examples/generative/topodiff recipe to use the
    consolidated physicsnemo.diffusion API (MSEDSMLoss with
    prediction_type="epsilon", sample(), DPSScorePredictor) plus a
    recipe-local DDPM scheduler, solver, and classifier guidance. Removed
    the now-unused Diffusion, DatasetTopoDiff, and load_data_topodiff
    abstractions from physicsnemo.models.topodiff.
  • Significantly expanded CI test coverage for physicsnemo.diffusion,
    including new tests for samplers, solvers, preconditioners, losses,
    DPS guidance, multi-diffusion, and patching utilities, plus
    combined-workflow and from-checkpoint round-trip tests. Most tests
    run with fullgraph=True and error_on_recompile to catch
    torch.compile regressions.
  • Internal weight initialization in the distributed AFNO layers and the
    EarthAttention blocks of physicsnemo.nn.module.attention_layers now
    dispatches to torch.nn.init.trunc_normal_ directly instead of going
    through frozen in-tree copies of the pre-PyTorch-2.12 inverse-CDF
    implementation. PyTorch 2.12 reimplemented trunc_normal_ as a
    rejection-sampling loop on top of normal_() (see
    pytorch/pytorch#174997),
    so seeded from-scratch initialization consumes the RNG stream
    differently on 2.12+ vs older versions. Existing trained checkpoints
    are unaffected (loading bypasses init). Forward-accuracy reference
    outputs for AFNO, ModAFNO, Transolver, FLARE, and Pangu were
    regenerated against the new algorithm. Rather than wiring per-model
    skips, test.common.validate_forward_accuracy now uniformly skips on
    torch < 2.12 (the reference data is locked to that floor via a single
    _REFERENCE_DATA_MIN_TORCH constant; bump it when a PyTorch
    release next changes an init/RNG algorithm any forward-accuracy model
    depends on, and regenerate the .pth files at the same time).

Deprecated

  • physicsnemo.utils.mesh is deprecated and will be removed in v2.2.0. For
    isosurface extraction, use physicsnemo.mesh.generate.marching_cubes instead
    of sdf_to_stl. For VTP/OBJ/STL file conversion (combine_vtp_files,
    convert_tesselated_files_in_directory), use VTK or PyVista directly.
  • physicsnemo.nn.module.utils.trunc_normal_ (and its submodule path
    physicsnemo.nn.module.utils.weight_init.trunc_normal_) is deprecated
    and will be removed in v2.2.0. It is now a thin wrapper around
    torch.nn.init.trunc_normal_ that emits a DeprecationWarning on
    call, replacing the frozen in-tree copy of the legacy inverse-CDF
    implementation. Use torch.nn.init.trunc_normal_ directly.

Removed

  • The legacy in-tree trunc_normal_ implementation that lived in
    physicsnemo/models/afno/distributed/layers.py (_trunc_normal_ /
    _no_grad_trunc_normal_) is removed. These names were private; all
    in-tree call sites now use torch.nn.init.trunc_normal_.

Fixed

  • Fixed functional benchmark plot fallback labeling so unlabeled ASV results use
    the same key ordering as the benchmark runner.
  • Fixed graph break caused by FunctionSpec dispatch (max(key=) is not supported by torch.compile)
  • Fixed bug in Pangu, FengWu attention window shift for asymmetric longitudes
  • Fixed a bug in mesh.sampling.find_nearest_cells, where a mixup between L2 and L-inf norms
    could cause slightly incorrect nearest-neighbor assignments in highly skewed meshes.
  • Fixed TensorDict key-ordering bug in GLOBE's Barnes-Hut kernel that caused
    incorrect results when tensordict >= 0.12 reordered leaves during
    TensorDict construction from dict literals mixing plain and nested keys.
  • In PhysicsNeMo-Mesh, from_pyvista now correctly handles
    UnstructuredGrid inputs in newer pyvista versions, looking up
    cell-type buckets in cells_dict with np.uint8(pv.CellType.X) keys
    rather than the IntEnum value, and skipping non-numeric VTK arrays
    (strings, objects) when copying point / cell / field data into the
    Mesh TensorDicts instead of failing the conversion.
  • In PhysicsNeMo-Mesh, the Mesh constructor now preserves data when
    point_data / cell_data / global_data are passed as a non-dict
    Mapping (notably PyVista's DataSetAttributes). Previously, with
    tensordict >= 0.12, the @tensorclass(tensor_only=True) auto-init
    silently wrapped such Mappings as NonTensorData and dropped every key,
    so e.g. Mesh(cell_data=pv_mesh.cell_data, ...) produced an empty
    cell_data. Mesh.__post_init__ now detects this wrapping and unwraps
    the original Mapping before coercing to TensorDict. The tensor_only
    fast path is preserved, so internal Mesh constructions (slicing,
    transforms, from_pyvista) keep their full speed. Backed by new direct-
    construction regression tests, a cell_data / global_data memmap
    round-trip test, and a committed .pmsh golden fixture that locks the
    on-disk format against silent breakage in future changes.
  • In PhysicsNeMo-Mesh, safe_eps(dtype) is now capped at
    torch.finfo(dtype).eps, which fixes a float16 corner case where the
    previous tiny ** 0.25 floor exceeded machine epsilon and could
    corrupt fp16 mesh quantities. Ad-hoc + 1e-10 denominators in
    smooth_laplacian and compute_quality_metrics have been replaced
    with the dtype-aware .clamp(min=safe_eps(dtype)) to avoid silently
    zeroing fp16 weights.
  • Fixed a silent bug in loading state from checkpoint for
    FSDP-backed models with use_orig_params=False and channels last
    memory format.
  • Fixed issues with physicsnemo.nn.functional's radius_search that
    caused crashes when used with torch.compile.
  • Fixed the sinusoidal positional embeddings formula in SongUNet and
    MultiDiffusionModel2D so it now follows the standard sin / cos
    convention. Affected reference data was regenerated.
  • Constructing a Mesh (or DomainMesh) inside a torch.compile-traced
    function no longer raises AttributeError / KeyError or silently
    produces wrong output. The breakage came from two regressions in
    tensordict >= 0.12.0 (PR pytorch/tensordict#1552), where the
    @tensorclass init wrapper's bypass branch silently skipped both
    field-default normalization and __post_init__ under
    torch.compile. We pin tensordict < 0.12 until the upstream fix
    (pytorch/tensordict#1708, pytorch/tensordict#1709) ships, and add
    a regression test (test/mesh/mesh/test_compile.py) that constructs
    a Mesh inside torch.compile and reads cached properties, so the
    same bug cannot return on a future pin bump unnoticed.

Dependencies

  • Increments minimum viable PyTorch version to torch>=2.5.0 to support FSDP better
  • Upper-bounds tensordict < 0.12 to avoid the torch.compile regressions
    in tensordict >= 0.12.0 (see corresponding entry under Fixed).

Contributors

We’re grateful to everyone who contributed issues, feature ideas, fixes, and documentation updates — your input is what helps us continuously improve PhysicsNeMo for the whole community!
A special shout-out to the authors of the pull requests listed above, in no particular order:

@jleinonen, @Brumbelow, @ghasemiAb, @albertocarpentieri, @dakhare-creator, @manmeet3591,
@nloppi, @nbren12

Thank you ❤️ — we truly appreciate your contributions and hope to see more from you in the future!