Time-dependent Schrödinger equation on sparse grids (Gradinaru 2007)

This example implements the numerical setup in Section 4 of:

  • V. Gradinaru (2007), Fourier transform on sparse grids: Code design and the time dependent Schrödinger equation.

The corresponding implementation is in examples/gradinaru_2007_tdse.jl.

Model problem

We consider the periodic time-dependent Schrödinger equation (TDSE) on

\[\Omega = [0,2\pi]^d\]

\[i\,\varepsilon\,\partial_t u = -\frac{\varepsilon^2}{2}\,\Delta u + V(x)\,u, \qquad u(x,0)=g(x),\]

with the harmonic potential

\[V(x) = \frac12 \sum_{s=1}^d (x_s - \pi)^2.\]

Gradinaru uses Gaussian initial data (the example script follows the same choice).

Spatial discretization

Sparse grid Fourier collocation

The spatial discretization is Fourier collocation on a sparse grid:

  • Each 1D rule is FourierEquispacedNodes().
  • The multi-index set is SmolyakIndexSet(d, n) (paper resolution $n$).

Why LevelOrder() for the nodal data?

The recursive sparse grid layout and the unidirectional transform engine require that refining the 1D rule appends new points after the existing ones (nested-prefix order). For Fourier nodes this is provided by LevelOrder() (bit-reversal ordering on equispaced grids).

Internally, the example evaluates $V$ and $g$ on the sparse grid in the package’s recursive layout (order consistent with traverse(grid)), and stores the evolving wave function $u$ as a single complex vector.

Time discretization: Strang splitting

Following Gradinaru, we apply Strang splitting over a time step $\tau$. In the "physical-space" formulation (paper Eq. (11)):

\[u \leftarrow \exp\Bigl(-i\,\tfrac{\tau}{2\varepsilon}V\Bigr) \,F^{-1} \,\exp\Bigl(-i\,\tfrac{\tau\varepsilon}{2}|\omega|^2\Bigr) \,F \,\exp\Bigl(-i\,\tfrac{\tau}{2\varepsilon}V\Bigr) \,u,\]

where $F$ / $F^{-1}$ are the sparse grid Fourier transforms.

In code:

  • ForwardTransform(d) implements $F$.
  • InverseTransform(d) implements $F^{-1}$.

Both are matrix-free and evaluated by apply_unidirectional!(...) (fiber-by-fiber sweeps).

Diagonal phases

The Strang step becomes cheap once we precompute the diagonal phases:

  • phaseV = exp(-i * (τ/(2ε)) * V(x)) (pointwise multiplication in physical space).
  • phaseK = exp(-i * (τ*ε/2) * |ω|^2) (pointwise multiplication in Fourier space).

This is exactly what the example does.

Frequency indexing: σ-order in the paper vs natural order here

Gradinaru’s paper reindexes Fourier modes using the zig-zag map $\sigma$ (their Section 2), so that a single index $q = 0,\dots,2^\ell-1$ maps to a signed frequency $\sigma(q)$:

\[\sigma(q) = \begin{cases} -q/2, & q \text{ even},\\ (q+1)/2, & q \text{ odd}. \end{cases}\]

This "σ-order" is convenient for exposition because it enumerates the symmetric frequency set $\{1-2^{\ell-1},\dots,2^{\ell-1}\}$ in a nested way.

What we do instead

UnifiedSparseGrids intentionally keeps the output of the 1D FFT in standard FFTW natural order (indices $k = 0,\dots,N-1$). This avoids extra global permutations to/from σ-order, and fits cleanly into the in-place, fiber-by-fiber unidirectional transform engine.

The key invariant required by the unidirectional engine is not the σ-order per se, but the nested-prefix property of level-dependent fibers:

  • for a nested 1D rule, the data for level $\ell$ occupies the first npoints(nodes, ℓ) entries of the level $\ell+1$ fiber.

This is why LevelOrder() is used for nodal data, and why we avoid introducing additional reorderings in the modal representation.

Wrap-around map for physical frequencies

Because modal coefficients are stored in FFTW natural order, the mapping from array index $k \in \{0,\dots,N-1\}$ to the signed Fourier frequency $\omega \in \mathbb{Z}$ is the usual wrap-around:

\[\omega(k;N) = \begin{cases} \phantom{-}k, & 0 \le k \le N/2,\\ \phantom{-}k-N, & N/2 < k < N. \end{cases}\]

In $d$ dimensions we use $|\omega|^2 = \sum_{j=1}^d \omega_j^2$.

On sparse grids, a coefficient belongs to some tensor subspace $W_{\ell}$. Therefore the signed frequency must be interpreted with the corresponding local 1D resolution $N_j = npoints(\mathrm{nodes}[j], \ell_j)$. In the implementation we infer $\ell_j$ from the nested-prefix coordinate convention:

\[\ell_j = \min\{\ell \ge 0 : c_j \le npoints(\mathrm{nodes}[j], \ell)\}, \qquad N_j = npoints(\mathrm{nodes}[j], \ell_j), \qquad k_j = c_j - 1.\]

This is the only place where the "ordering difference" matters: the kinetic phase depends on the physical frequency, and with natural order we must apply the wrap-around map.