Diagnostics

We can add diagnostics to a FourierFlows's problem using Diagnostic functionality.

To demonstrate how we add diagnostics to a PDE problem, let's try to add one to the simple PDE problem we constructed in the Problem section. For example, say we'd like to add a diagnostic we refer to as the "energy" and which we define to be:

\[E = \int u^2 \, \mathrm{d} x .\]

After we have constructed the problem (prob) (see Problem section), we then create a function that takes prob as its argument returns the diagnostic:

using LinearAlgebra: ldiv!

function energy(prob)
    ldiv!(prob.vars.u, grid.rfftplan, prob.sol)

    return sum(prob.vars.u.^2) * prob.grid.dx
end

and then we create a Diagnostic using the Diagnostic constructor. Say we want to save energy every 2 time-steps, then:

E = Diagnostic(energy, prob, freq=2, nsteps=200)
Diagnostic
  ├─── calc: energy
  ├─── prob: FourierFlows.Problem{DataType, Vector{ComplexF64}, Float64, Vector{Float64}}
  ├─── data: 101-element Vector{Float64}
  ├────── t: 101-element Vector{Float64}
  ├── steps: 101-element Vector{Int64}
  ├─── freq: 2
  └────── i: 1

Now, when we step forward the problem we provide the diagnostic as the second positional argument in stepforward!:

stepforward!(prob, E, 200)

Doing so, the diagnostic is computed and saved at the appropriate frequency (prescribed by E.freq).

Multiple diagnostics

If we want to include multiple diagnostics we can gather all of them in an array, e.g.,

diag1 = Diagnostic(foo, prob)
diag2 = Diagnostic(bar, prob)

stepforward!(prob, [diag1, diag2], 1)

The times that the diagnostic was saved are gathered in E.t. Thus, we can easily plot the energy time-series, e.g.,

using CairoMakie

lines(E.t, E.data, axis = (xlabel = "time", ylabel = "energy"))
Example block output