Skip to content

Add VolumeConservationLoss to physicsnemo.experimental.losses - #1809

Closed
wdyab wants to merge 2 commits into
NVIDIA:mainfrom
wdyab:nof/pr3c-volume-conservation-loss
Closed

Add VolumeConservationLoss to physicsnemo.experimental.losses#1809
wdyab wants to merge 2 commits into
NVIDIA:mainfrom
wdyab:nof/pr3c-volume-conservation-loss

Conversation

@wdyab

@wdyab wdyab commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Summary

Adds VolumeConservationLoss to physicsnemo.experimental.losses: a generic,
dimension-agnostic weak-conservation loss. It compares the (optionally
volume-weighted) spatial integral of pred and target at each step of a
trailing feature/time axis, using a dependency-injected data-fitting metric
callable and an optional inactive-cell mask.

The default metric is mse (always available); any physicsnemo.metrics.general
function — or a relative-error metric such as the one proposed in #1746 once it
lands — can be dependency-injected. Inputs are validated (pred/target shape,
cell_volumes shape, and static/per-sample mask shape) under a
torch.compiler.is_compiling() guard; the masking path uses static-shape
weighting (no boolean indexing), so it is torch.compile-compatible.

Named volume conservation (not "mass conservation") on purpose: it conserves
a volume-weighted spatial integral, not true mass — no material density or
porosity is applied.

Stacked PR. Depends on #1808, which creates the physicsnemo.experimental.losses
package. This branch is based on nof/pr3b-spatial-derivative-loss, so the diff
also shows #1808's files until it merges; the change owned by this PR is the top
commit (physicsnemo/experimental/losses/volume_conservation.py + its test, plus
the __init__ export). Once #1808 merges I'll rebase this onto main.

Closes #1806

Test plan

  • test/experimental/losses/test_volume_conservation.py: analytic 2D/3D
    reservoir integrals (known totals), dependency-injected metric sweep,
    volume-weighted vs uniform, multi-timestep, masking (static + per-sample),
    gradient flow, scale invariance, uniform-default, and error paths
    (pred/target, cell_volumes, and mask shape mismatches).
  • interrogate 100%, ruff check+format clean, doctest, license headers, CHANGELOG.

@copy-pr-bot

copy-pr-bot Bot commented Jul 8, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@greptile-apps

greptile-apps Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR adds experimental weak-physics losses for conservation and derivative regularization. The main changes are:

  • New physicsnemo.experimental.losses package exports.
  • Added VolumeConservationLoss for volume-weighted spatial integrals.
  • Added SpatialDerivativeLoss and central-difference helpers.
  • Added tests for metrics, masking, gradients, and validation paths.

Important Files Changed

Filename Overview
physicsnemo/experimental/losses/volume_conservation.py Adds VolumeConservationLoss with shape validation, optional volume weights, and per-sample or static masking.
physicsnemo/experimental/losses/derivative.py Adds SpatialDerivativeLoss with central-difference helpers and mask-aware stencil selection.
physicsnemo/experimental/losses/init.py Exports the new experimental loss classes and derivative helpers.
test/experimental/losses/test_volume_conservation.py Adds coverage for volume conservation behavior, masking, custom metrics, gradients, and shape errors.
test/experimental/losses/test_derivative_loss.py Adds coverage for finite differences, derivative loss behavior, masking, gradients, and shape errors.

Reviews (2): Last reviewed commit: "Add VolumeConservationLoss to physicsnem..." | Re-trigger Greptile

Comment thread physicsnemo/experimental/losses/volume_conservation.py Outdated
Comment thread physicsnemo/experimental/losses/derivative.py Outdated
wdyab added 2 commits July 14, 2026 02:25
Adds a generic, dimension-agnostic spatial-derivative regularization loss that
compares the interior (non-periodic) central-difference gradients of a
prediction and a target on a non-uniform grid (per-axis cell widths), using an
injectable data-fitting metric from physicsnemo.metrics.general and optional
inactive-cell masking for sparse grids. The reusable central_difference and
cell_centre_distance helpers are also exported.

The existing physicsnemo.nn.functional.derivatives operators are periodic,
coordinate-based, and single-field, so they do not cover this batched,
non-periodic, masked regularization regime; this is documented in the module.

Pre-commit: markdownlint and import-linter were skipped (SKIP=...) as they fail
only on local environment artifacts (markdownlint's Node/npm cannot write to
the sandbox tmp cache; import-linter reports pre-existing external-import
violations with 0 file violations, which pass in upstream CI). ruff-check,
ruff-format, interrogate, license header, and large-file hooks ran and passed.

Signed-off-by: wdyab <wdyab@nvidia.com>
Adds a generic, dimension-agnostic weak-conservation loss that compares the
(optionally volume-weighted) spatial integral of a prediction and a target at
each step of a trailing feature/time axis, using an injectable data-fitting
metric from physicsnemo.metrics.general and optional inactive-cell masking for
sparse grids.

Named "volume conservation" (not "mass conservation") because it enforces
conservation of a volume-weighted spatial integral; no material density or
porosity is applied, so it is meaningful only for quantities whose volume
integral is approximately conserved.

Pre-commit: markdownlint and import-linter were skipped (SKIP=...) as they fail
only on local environment artifacts (markdownlint's Node/npm cannot write to
the sandbox tmp cache; import-linter reports pre-existing external-import
violations with 0 file violations, which pass in upstream CI). ruff-check,
ruff-format, interrogate, license header, and large-file hooks ran and passed.

Signed-off-by: wdyab <wdyab@nvidia.com>
@wdyab
wdyab force-pushed the nof/pr3c-volume-conservation-loss branch from c9e38cc to c34cc5d Compare July 14, 2026 09:26
@wdyab

wdyab commented Jul 14, 2026

Copy link
Copy Markdown
Contributor Author

@peterdsharpe @mnabian @melo-gonzo for your review

@wdyab

wdyab commented Jul 17, 2026

Copy link
Copy Markdown
Contributor Author

Closing per the offline discussion with the maintainers: these regularization losses will live in the reservoir-simulation example recipe downstream, and the generic finite-difference need will be addressed by extending physicsnemo.nn.functional.derivatives (non-periodic + batched) rather than adding a parallel implementation. Thanks for the reviews!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add a generic volume-conservation loss to physicsnemo.experimental.losses

1 participant