# Correctness Issue in NeuralOperators.jl: Mode truncation in SpectralConv excludes negative low-frequency modes

**URL:** <https://discourse.julialang.org/t/correctness-issue-in-neuraloperators-jl-mode-truncation-in-spectralconv-excludes-negative-low-frequency-modes/134403>\
**Category:** Machine Learning\
**Tags:** question, package, machine-learning, sciml, neural-network\
**Created:** [December 6, 2025, 8:03pm UTC](https://discourse.julialang.org/t/correctness-issue-in-neuraloperators-jl-mode-truncation-in-spectralconv-excludes-negative-low-frequency-modes/134403 "2025-12-06T20:03:31Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Azamat](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/azamat/32/6892_2.png) [@Azamat](https://discourse.julialang.org/u/Azamat)\
**Post date:** [December 6, 2025, 8:03pm UTC](https://discourse.julialang.org/t/correctness-issue-in-neuraloperators-jl-mode-truncation-in-spectralconv-excludes-negative-low-frequency-modes/134403/1 "2025-12-06T20:03:31Z")

</div>

I was looking at the mode truncation logic in NeuralOperators.jl and have a question about correctness.

Link: [NeuralOperators.jl/src/transform.jl at 39f8a3c6dc974e711c8de8a8fde804e096098157 · SciML/NeuralOperators.jl · GitHub](https://github.com/SciML/NeuralOperators.jl/blob/39f8a3c6dc974e711c8de8a8fde804e096098157/src/transform.jl#L54-L58)

It looks like the code currently only keeps the `1:d` slice in each dimension. Since standard FFT outputs place negative low-frequency modes at the end of the array, doesn’t this implementation drop those modes?

According to the [FNO paper](https://arxiv.org/abs/2010.08895), we should keep the lowest modes from both ends (e.g., `1:k` and `(end-k+1):end`). Is there a specific reason it’s implemented this way, or is this a bug?

I think the correct way to implement the truncation of higher frequency modes would be to apply `fftshift`, and then keep the center crop `x[center-k:center+k]`.

---

<div class="post-metadata">

**Author:** ![ChrisRackauckas](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/chrisrackauckas/32/77_2.png) [@ChrisRackauckas](https://discourse.julialang.org/u/ChrisRackauckas)\
**Post date:** [December 8, 2025, 2:01am UTC](https://discourse.julialang.org/t/correctness-issue-in-neuraloperators-jl-mode-truncation-in-spectralconv-excludes-negative-low-frequency-modes/134403/2 "2025-12-08T02:01:18Z")

</div>

@avikpal

---

<div class="post-metadata">

**Author:** ![Azamat](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/azamat/32/6892_2.png) [@Azamat](https://discourse.julialang.org/u/Azamat)\
**Post date:** [December 9, 2025, 8:26am UTC](https://discourse.julialang.org/t/correctness-issue-in-neuraloperators-jl-mode-truncation-in-spectralconv-excludes-negative-low-frequency-modes/134403/3 "2025-12-09T08:26:17Z")

</div>

After taking a closer look at the `FourierNeuralOperator` implementation in NeuralOperators.jl, I’m now convinced that the issue I described above is indeed a **correctness bug**.

More broadly, the current Fourier Neural Operator implementation in NeuralOperators.jl appears to be outdated. It follows the original FNO paper [1], whereas most modern implementations (for example, the PyTorch-based [neuraloperator](https://neuraloperator.github.io/dev/index.html)) are based on the follow-up work [2], which introduces a significantly improved FNO architecture.

To address this, I’ve implemented a modern FNO variant following [2] from scratch.  
GitHub repo: [FourierNeuralOperators.jl](https://github.com/AzamatB/FourierNeuralOperators.jl)

If there is interest from the maintainers, I’d be happy to discuss integrating this implementation into NeuralOperators.jl.

[1] [Fourier Neural Operator for Parametric Partial Differential Equations](https://arxiv.org/abs/2010.08895)  
[2] [Multi-Grid Tensorized Fourier Neural Operator for High-Resolution PDEs](https://arxiv.org/abs/2310.00120)
