Skip to content

feat: implement ConvolutionalNeuralOperator (CNO) (closes #122)#134

Open
jitendravjh wants to merge 3 commits into
SciML:mainfrom
jitendravjh:feat/convolutional-neural-operator
Open

feat: implement ConvolutionalNeuralOperator (CNO) (closes #122)#134
jitendravjh wants to merge 3 commits into
SciML:mainfrom
jitendravjh:feat/convolutional-neural-operator

Conversation

@jitendravjh
Copy link
Copy Markdown

Implements CNO from Raonic et al., NeurIPS 2023 (https://arxiv.org/abs/2302.01178).

Each CNOBlock follows the paper: Upsample → Conv(3×3, act, SamePad) → MeanPool, ensuring the discrete operator converges to a continuous limit as resolution increases.

Architecture: Lifting → CNOBlock × N → Projection
API: consistent with FourierNeuralOperator(modes, in_ch, out_ch, hidden_ch; ...)

Tested locally (CPU): 1D, 2D, multi-channel, resolution invariance (spatial=32/64/128 with same weights), finite outputs, doctest shape.

Checklist

  • Appropriate tests were added
  • Any code changes were done in a way that does not break public API
  • All documentation related to code changes were updated
  • The new code follows the contributor guidelines, in particular the SciML Style Guide and COLPRAC
  • Any new documentation only uses public API

…ndexing SciML#125)

GridEmbedding built the positional grid using CPU range/meshgrid, then
called cat(grid, x) where x may be a CuArray. This caused:

  ERROR: Scalar indexing is disallowed. Invocation of getindex resulted
  in scalar indexing of a GPU array.

Fix: call Lux.get_device(x)(grid) immediately after building the grid,
so the array is moved to the same device as the input before the cat.
This is a no-op on CPU and transparently transfers to GPU/Metal/etc.

Fixes SciML#125
Implements the Convolutional Neural Operator from:
  Raonic et al., "Convolutional Neural Operators for robust and accurate
  learning of PDEs", NeurIPS 2023. https://arxiv.org/abs/2302.01178

Architecture:
  - Lifting:     Conv(1x...x1): in_channels → hidden_channels
  - CNO blocks:  Upsample(:bilinear) → Conv(3x...x3, act, SamePad) → MeanPool
  - Projection:  Conv(1x...x1, act) → Conv(1x...x1): → out_channels

Each CNOBlock upsamples by upsample_factor, convolves at higher resolution,
then downsamples via MeanPool — ensuring the operator converges to a
continuous limit as spatial resolution increases (resolution-invariant).

New types exported:
  - ConvolutionalNeuralOperator  (the full model)
  - CNOBlock                     (the building block, composable)

Closes SciML#122
@jitendravjh jitendravjh force-pushed the feat/convolutional-neural-operator branch from d81efeb to e2ded64 Compare May 16, 2026 20:19
@ChrisRackauckas
Copy link
Copy Markdown
Member

Missing tests

@jitendravjh
Copy link
Copy Markdown
Author

Added test/models/cno_tests.jl with 1D + 2D forward pass, Reactant consistency, and gradient checks (matching the pattern of fno_tests.jl). Doctests and Aqua QA also pass locally.

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.

2 participants