Public Documentation

Documentation for FourierFlows.jl's public interface.

See the Internals section of the manual for internal package docs covering all submodules.

FourierFlows

FourierFlows.FourierFlows — Module
source

Problem

Domain

FourierFlows.OneDGrid — Type
OneDGrid(dev::Device = CPU();
         nx, Lx,
         x0 = -Lx/2, nthreads = Sys.CPU_THREADS, effort = FFTW.MEASURE, 
         T = Float64, aliased_fraction = 1/3)

Construct a OneDGrid on device; by default on CPU(). Grid size is Lx, resolution is nx, and leftmost position is x0. FFT plans are generated for nthreads CPUs using FFTW flag effort. The float type is T. The aliased_fraction keyword determines the highest wavenubers that are being zero-ed out by dealias! function; 1/3 is the nominal value for quadratic nonlinearities.

source
FourierFlows.OneDGrid — Type
struct OneDGrid{T<:AbstractFloat, A, Tx, Tfft, Trfft, Talias} <: AbstractGrid{T, A, Talias, D}

A one-dimensional grid.

  • device::Any: device which the grid lives on

  • nx::Int64: number of points in $x$

  • nk::Int64: number of wavenumbers in $x$

  • nkr::Int64: number of positive wavenumbers in $x$ (real Fourier transforms)

  • dx::AbstractFloat: grid spacing in $x$

  • Lx::AbstractFloat: domain extent in $x$

  • x::Any: range with $x$-grid-points

  • k::Any: array with $x$-wavenumbers

  • kr::Any: array with positive $x$-wavenumbers (real Fourier transforms)

  • invksq::Any: array with inverse squared $k$-wavenumbers, $1 / k²$

  • invkrsq::Any: array with inverse squared $kᵣ$-wavenumbers, $1 / kᵣ²$

  • fftplan::Any: the FFT plan for complex-valued fields

  • rfftplan::Any: the FFT plan for real-valued fields

  • aliased_fraction::AbstractFloat: the fraction of wavenumbers that are aliased (e.g., 1/3 for quadradic nonlinearities)

  • kalias::Any: range of the indices of aliased $x$-wavenumbers

  • kralias::Any: range of the indices of aliased positive $x$-wavenumbers (real Fourier transforms)

source
FourierFlows.ThreeDGrid — Type
ThreeDGrid(dev::Device=CPU(); nx, Lx, ny=nx, Ly=Lx, nz=nx, Lz=Lx,
           x0=-Lx/2, y0=-Ly/2, z0=-Lz/2,
           nthreads=Sys.CPU_THREADS, effort=FFTW.MEASURE, T=Float64,
           aliased_fraction=1/3)

Construct a ThreeDGrid on device; by default on CPU(). Grid size is Lx, Ly, Lz, resolution is nx, ny, nz and leftmost positions are x0, y0, z0. FFT plans are generated for nthreads CPUs using FFTW flag effort. The float type is T. The aliased_fraction keyword determines the highest wavenubers that are being zero-ed out by dealias! function; 1/3 is the nominal value for quadratic nonlinearities.

source
FourierFlows.ThreeDGrid — Type
struct ThreeDGrid{T<:AbstractFloat, Tk, Tx, Tfft, Trfft, Talias} <: AbstractGrid{T, Tk, Talias}

A three-dimensional grid.

  • device::Any: device which the grid lives on

  • nx::Int64: number of points in $x$

  • ny::Int64: number of points in $y$

  • nz::Int64: number of points in $z$

  • nk::Int64: number of wavenumbers in $x$

  • nl::Int64: number of wavenumbers in $y$

  • nm::Int64: number of wavenumbers in $z$

  • nkr::Int64: number of positive wavenumers in $x$ (real Fourier transforms)

  • dx::AbstractFloat: grid spacing in $x$

  • dy::AbstractFloat: grid spacing in $y$

  • dz::AbstractFloat: grid spacing in $z$

  • Lx::AbstractFloat: domain extent in $x$

  • Ly::AbstractFloat: domain extent in $y$

  • Lz::AbstractFloat: domain extent in $z$

  • x::Any: range with $x$-grid-points

  • y::Any: range with $y$-grid-points

  • z::Any: range with $z$-grid-points

  • k::Any: array with $x$-wavenumbers

  • l::Any: array with $y$-wavenumbers

  • m::Any: array with $z$-wavenumbers

  • kr::Any: array with positive $x$-wavenumbers (real Fourier transforms)

  • Ksq::Any: array with squared total wavenumbers, $k² + l² + m²$

  • invKsq::Any: array with inverse squared total wavenumbers, $1 / (k² + l² + m²)$

  • Krsq::Any: array with squared total wavenumbers for real Fourier transforms, $kᵣ² + l² + m²$

  • invKrsq::Any: array with inverse squared total wavenumbers for real Fourier transforms, $1 / (kᵣ² + l² + m²)$

  • fftplan::Any: the FFT plan for complex-valued fields

  • rfftplan::Any: the FFT plan for real-valued fields

  • aliased_fraction::AbstractFloat: the fraction of wavenumbers that are aliased (e.g., 1/3 for quadradic nonlinearities)

  • kalias::Any: range of the indices of aliased $x$-wavenumbers

  • kralias::Any: range of the indices of aliased positive $x$-wavenumbers (real Fourier transforms)

  • lalias::Any: range of the indices of aliased $y$-wavenumbers

  • malias::Any: range of the indices of aliased $m$-wavenumbers

source
FourierFlows.TwoDGrid — Type
TwoDGrid(dev::Device=CPU(); nx, Lx, ny=nx, Ly=Lx,
         x0=-Lx/2, y0=-Ly/2, nthreads=Sys.CPU_THREADS, effort=FFTW.MEASURE,
         T=Float64, aliased_fraction=1/3)

Construct a TwoDGrid on device; by default on CPU(). Grid size is Lx, Ly, resolution is nx, ny, and leftmost positions are x0, y0. FFT plans are generated for nthreads CPUs using FFTW flag effort. The float type is T. The aliased_fraction keyword determines the highest wavenubers that are being zero-ed out by dealias! function; 1/3 is the nominal value for quadratic nonlinearities.

source
FourierFlows.TwoDGrid — Type
struct TwoDGrid{T<:AbstractFloat, A, Tx, Tfft, Trfft, Talias, D} <: AbstractGrid{T, Tk, Talias, D}

A two-dimensional grid.

  • device::Any: device which the grid lives on

  • nx::Int64: number of points in $x$

  • ny::Int64: number of points in $y$

  • nk::Int64: number of wavenumbers in $x$

  • nl::Int64: number of wavenumbers in $y$

  • nkr::Int64: number of positive wavenumers in $x$ (real Fourier transforms)

  • dx::AbstractFloat: grid spacing in $x$

  • dy::AbstractFloat: grid spacing in $y$

  • Lx::AbstractFloat: domain extent in $x$

  • Ly::AbstractFloat: domain extent in $y$

  • x::Any: range with $x$-grid-points

  • y::Any: range with $y$-grid-points

  • k::Any: array with $x$-wavenumbers

  • l::Any: array with $y$-wavenumbers

  • kr::Any: array with positive $x$-wavenumbers (real Fourier transforms)

  • Ksq::Any: array with squared total wavenumbers, $k² + l²$

  • invKsq::Any: array with inverse squared total wavenumbers, $1 / (k² + l²)$

  • Krsq::Any: array with squared total wavenumbers for real Fourier transforms, $kᵣ² + l²$

  • invKrsq::Any: array with inverse squared total wavenumbers for real Fourier transforms, $1 / (kᵣ² + l²)$

  • fftplan::Any: the FFT plan for complex-valued fields

  • rfftplan::Any: the FFT plan for real-valued fields

  • aliased_fraction::AbstractFloat: the fraction of wavenumbers that are aliased (e.g., 1/3 for quadradic nonlinearities)

  • kalias::Any: range of the indices of aliased $x$-wavenumbers

  • kralias::Any: range of the indices of aliased positive $x$-wavenumbers (real Fourier transforms)

  • lalias::Any: range of the indices of aliased $y$-wavenumbers

source
FourierFlows.gridpoints — Method
gridpoints(grid::OneDDGrid)
gridpoints(grid::TwoDGrid)
gridpoints(grid::ThreeDGrid)

Return the collocation points of the grid in 1D (X), 2D (X, Y) or 3D arrays (X, Y, Z).

source

Utilities

FourierFlows.device_array — Method
device_array(grid::AbstractGrid)

Return the proper array type according to the grid's device, i.e., Array for CPU and CuArray for GPU.

source
FourierFlows.device_array — Method
device_array(device::Device)
device_array(device::Device, T, dim)

Return the proper array type according to the device, i.e., Array for CPU and CuArray for GPU.

source
FourierFlows.innereltype — Method
innereltype(x)

Recursively determine the 'innermost' type in by the collection x (which may be, for example, a collection of a collection).

source
FourierFlows.superzeros — Method
superzeros(T, A)

Returns an array like A, but full of zeros. If innereltype(A) can be promoted to T, then the innermost elements of the array will have type T.

source
FourierFlows.@devzeros — Macro
@devzeros dev T dims a b c...

Create arrays of all zeros with element type T, size dims, and global names a, b, c (for example) on device dev.

source
FourierFlows.@superzeros — Macro
@superzeros T a b c d...
@superzeros T dims b c d...

Generate arrays b, c, d... with the super-dimensions of a and innereltype T.

source
FourierFlows.@zeros — Macro
@zeros T dims a b c...

Create arrays of all zeros with element type T, size dims, and global names a, b, c (for example). An arbitrary number of arrays may be created.

source

Diagnostics

FourierFlows.Diagnostic — Type
mutable struct Diagnostic{T, N} <: AbstractDiagnostic

A diagnostic that includes N elements of type T.

  • calc::Function: function that returns the diagnostic via calc(prob)

  • prob::FourierFlows.Problem: the relevant problem for this diagnostic

  • data::Vector: vector where the diagnostic time-series is saved

  • t::Vector{Float64}: vector with the times for which the diagnostic was saved

  • steps::Vector{Int64}: vector with the problem's step for which the diagnostic was saved

  • freq::Int64: integer denoting how often (every how many problem.steps) to save the diagnostic

  • i::Int64: integer denoting how many times the diagnostic.data was updated

source
FourierFlows.Diagnostic — Method
Diagnostic(calc, prob; freq=1, nsteps=100, ndata=ceil(Int, (nsteps+1)/freq))

Construct a diagnostic that stores the result of calc(prob) with frequency freq.

Keywords

  • freq: Diagnostic is saved every freq steps.
  • nsteps: The total number of steps in problem.
  • ndata: The number of diagnostics to be saved.
source

Output

FourierFlows.Output — Type
struct Output

The composite type for output.

  • prob::FourierFlows.Problem: the relevant problem for the output

  • path::String: the path for the output file

  • fields::Dict{Symbol, Function}: the fields to be saved; the relevant problem for this diagnostic

source
FourierFlows.Output — Method
Output(prob, filename, fieldtuples...)

Define output for prob with fields and functions that calculate the output in the list of tuples fieldtuples = (fldname, func)....

source
FourierFlows.savediagnostic — Method
savediagnostic(diagnostic, diagname, filename)

Save diagnostic to filename under name diagname. Only the computed diagnostic is saved, that is, everything up to diagnostic's iteration diagnostic.i.

source

Timesteppers

FourierFlows.AB3TimeStepper — Type
AB3TimeStepper(equation::Equation, dev::Device=CPU())

Construct a 3rd order Adams-Bashforth timestepper for equation on device dev.

source
FourierFlows.AB3TimeStepper — Type
struct AB3TimeStepper{T} <: AbstractTimeStepper{T}

A 3rd-order Adams-Bashforth timestepper for time-stepping ∂u/∂t = RHS(u, t) via:

uⁿ⁺¹ = uⁿ + dt/12 * (23 * RHS(uⁿ, tⁿ) - 16 * RHS(uⁿ⁻¹, tⁿ⁻¹) + 5 * RHS(uⁿ⁻², tⁿ⁻²))

Adams-Bashforth is a multistep method, i.e., it not only requires information from the n-th time-step (uⁿ) but also from the previous two timesteps (uⁿ⁻¹ and uⁿ⁻²). For the first two timesteps, it falls back to a forward Euler timestepping scheme:

uⁿ⁺¹ = uⁿ + dt * RHS(uⁿ, tⁿ)
source
FourierFlows.ETDRK4TimeStepper — Type
ETDRK4TimeStepper(equation::Equation, dt, dev::Device=CPU())

Construct a 4th-order exponential-time-differencing Runge-Kutta timestepper with timestep dt for equation on device dev.

source
FourierFlows.ETDRK4TimeStepper — Type
struct ETDRK4TimeStepper{T,TL} <: AbstractTimeStepper{T}

A 4th-order exponential-time-differencing Runge-Kutta timestepper for time-stepping ∂u/∂t = L * u + N(u). The scheme treats the linear term L exactly while for the nonlinear terms N(u) it uses a 4th-order Runge-Kutta scheme (RK4TimeStepper). That is,

uⁿ⁺¹ = exp(L * dt) * uⁿ + RK4(N(uⁿ))

For more info refer to [2].

source
FourierFlows.FilteredAB3TimeStepper — Type
FilteredAB3TimeStepper(equation::Equation, dev::Device=CPU(); filterkwargs...)

Construct a 3rd order Adams-Bashforth timestepper with spectral filtering for equation on device dev.

source
FourierFlows.FilteredETDRK4TimeStepper — Type
FilteredETDRK4TimeStepper(equation, dt; filterkwargs...)

Construct a 4th-order exponential-time-differencing Runge-Kutta timestepper with timestep dt and spectral filtering for equation on device dev.

source
FourierFlows.FilteredLSRK54TimeStepper — Type
FilteredRK4TimeStepper(equation::Equation, dev::Device=CPU(); filterkwargs...)

Construct a 4th-order 5-stages 2-storage Runge-Kutta timestepper with spectral filtering for equation on device dev.

source
FourierFlows.FilteredRK4TimeStepper — Type
FilteredRK4TimeStepper(equation::Equation, dev::Device=CPU(); filterkwargs...)

Construct a 4th-order Runge-Kutta timestepper with spectral filtering for equation on device dev.

source
FourierFlows.ForwardEulerTimeStepper — Type
struct ForwardEulerTimeStepper{T} <: AbstractTimeStepper{T}

A forward Euler timestepper for time-stepping ∂u/∂t = RHS(u, t) via:

uⁿ⁺¹ = uⁿ + dt * RHS(uⁿ, tⁿ)
source
FourierFlows.LSRK54TimeStepper — Type
LSRK54TimeStepper(equation::Equation, dev::Device=CPU())

Construct a 4th-order 5-stages low-storage Runge-Kutta timestepper for equation on device dev.

source
FourierFlows.LSRK54TimeStepper — Type
struct LSRK54TimeStepper{T} <: AbstractTimeStepper{T}

A 4th-order 5-stages 2-storage Runge-Kutta timestepper for time-stepping ∂u/∂t = RHS(u, t) via:

S² = 0

for i = 1:5
  S² = Aᵢ * S² + dt * RHS(uⁿ, t₀ + Cᵢ * dt)
  uⁿ += Bᵢ * S²
end

uⁿ⁺¹ = uⁿ

where Aᵢ, Bᵢ, and Cᵢ are the $A$, $B$, and $C$ coefficients from the LSRK table at the $i$-th stage. For details, refer to [6].

Usage

The LSRK54TimeStepper is slower than the RK4TimeStepper but has less memory footprint; half compared to RK4TimeStepper.

If your simulation is bound by performance then use RK4TimeStepper; if your simulation is bound by memory then consider using LSRK54TimeStepper.

source
FourierFlows.RK4TimeStepper — Type
RK4TimeStepper(equation::Equation, dev::Device=CPU())

Construct a 4th-order Runge-Kutta timestepper for equation on device dev.

source
FourierFlows.RK4TimeStepper — Type
struct RK4TimeStepper{T} <: AbstractTimeStepper{T}

A 4th-order Runge-Kutta timestepper for time-stepping ∂u/∂t = RHS(u, t) via:

uⁿ⁺¹ = uⁿ + dt/6 * (k₁ + 2 * k₂ + 2 * k₃ + k₄)

where

k₁ = RHS(uⁿ, tⁿ)
k₂ = RHS(uⁿ + k₁ * dt/2, tⁿ + dt/2)
k₃ = RHS(uⁿ + k₂ * dt/2, tⁿ + dt/2)
k₄ = RHS(uⁿ + k₃ * dt, tⁿ + dt)
Usage

If your simulation is limited by memory then consider switching to LSRK54TimeStepper. The LSRK54TimeStepper timestepper has about half the memory footprint compared to the RK4TimeStepper with a about 25%-30% performance trade off.

source
FourierFlows.TimeStepper — Function
TimeStepper(stepper, equation, dt=nothing, dev=CPU(); kw...)

Instantiate the Timestepper for equation with timestep dt and on the device. The keyword arguments, kw, are passed to the timestepper constructor.

source
FourierFlows.stepforward! — Method
stepforward!(prob::Problem, diags, nsteps::Int)

Step forward prob for nsteps, incrementing diags along the way. diags may be a single Diagnostic or a Vector of Diagnostics.

source

Diffusion Testbed Module

FourierFlows.Diffusion.Problem — Function
Problem(dev::Device = CPU();
                 nx = 128,
                 Lx = 2π,
                  κ = 0,
                 dt = 0.01,
            stepper = "RK4",           
   aliased_fraction = 0,
                  T = Float64)

Construct a constant diffusivity problem.

Keyword arguments

  • dev: (required) CPU() or GPU(); computer architecture used to time-step problem.
  • nx: Number of grid points in $x$-domain.
  • Lx: Extent of the $x$-domain.
  • κ: Diffusivity coefficient.
  • dt: Time-step.
  • stepper: The extent of the $y$-domain.
  • aliased_fraction: the fraction of high-wavenubers that are zero-ed out by dealias!().
  • T: Float64 or Float32; floating point type used for problem data.
source