Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Add ShallowWater module #163

Draft
wants to merge 22 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/make.jl
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ sitename = "GeophysicalFlows.jl",
"modules/barotropicqg.md",
"modules/barotropicqgql.md",
"modules/multilayerqg.md",
"modules/surfaceqg.md"
"modules/surfaceqg.md",
"modules/shallowwater.md"
],
"Forcing" => "forcing.md",
"DocStrings" => Any[
Expand Down
17 changes: 17 additions & 0 deletions docs/src/modules/shallowwater.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# ShallowWater Module

### Basic Equations

This module solves the 2D shallow water equations:

```math
\begin{aligned}
\frac{\partial u}{\partial t} + \boldsymbol{u \cdot \nabla} u - f v & = - g \frac{\partial \eta}{\partial x} - \mathrm{D} u, \\
\frac{\partial v}{\partial t} + \boldsymbol{u \cdot \nabla} v + f u & = - \mathrm{D} v, \\
\frac{\partial \eta}{\partial t} + \boldsymbol{\nabla \cdot} ( \boldsymbol{u} h ) & = - \mathrm{D} \eta.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we write in conservative form?

Copy link
Member Author

@navidcy navidcy Dec 10, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes.

Also there are some typos, e.g., the -g ∂η/∂y term is missing from the v equation.

Also I'd like to include non-trivial bathymetry (which appears as a forcing term on the right-hand side in the momentum equations.)

Copy link
Member Author

@navidcy navidcy Jan 11, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here they are in conservative form:

Screen Shot 2021-01-11 at 2 07 49 pm

I made an attempt to write the calcN! function. Bit tricky...

Also, what's the form of dissipation? We want it to conserve the total hu, hv and h... Right?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We're having a related discussion at CliMA/Oceananigans.jl#1712

\end{aligned}
```

### Implementation

## Examples
1 change: 1 addition & 0 deletions src/GeophysicalFlows.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@ include("barotropicqg.jl")
include("barotropicqgql.jl")
include("multilayerqg.jl")
include("surfaceqg.jl")
include("shallowwater.jl")

end # module
203 changes: 203 additions & 0 deletions src/shallowwater.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
module ShallowWater

export
Problem,
updatevars!,

energy

using
CUDA,
Reexport

@reexport using FourierFlows

using LinearAlgebra: mul!, ldiv!
using FourierFlows: parsevalsum

nothingfunction(args...) = nothing

"""
Problem(; parameters...)

Construct a 2D shallow water problem.
"""
function Problem(dev::Device=CPU();
# Numerical parameters
nx = 256,
Lx = 2π,
ny = nx,
Ly = Lx,
dt = 0.01,
# Drag and/or hyper-/hypo-viscosity
ν = 0,
nν = 1,
μ = 0,
nμ = 0,
# Timestepper and equation options
stepper = "RK4",
calcF = nothingfunction,
stochastic = false,
T = Float64)

grid = TwoDGrid(dev, nx, Lx, ny, Ly; T=T)

params = Params{T}(ν, nν, μ, nμ, calcF)

vars = calcF == nothingfunction ? Vars(dev, grid) : (stochastic ? StochasticForcedVars(dev, grid) : ForcedVars(dev, grid))

equation = Equation(params, grid)

return FourierFlows.Problem(equation, stepper, dt, grid, vars, params, dev)
end


# ----------
# Parameters
# ----------

"""
Params(ν, nν, μ, nμ, calcF!)

Returns the params for two-dimensional turbulence.
"""
struct Params{T} <: AbstractParams
ν :: T # Vorticity viscosity
nν :: Int # Vorticity hyperviscous order
μ :: T # Bottom drag or hypoviscosity
nμ :: Int # Order of hypodrag
calcF! :: Function # Function that calculates the forcing F
end


# ---------
# Equations
# ---------

"""
Equation(params, grid)

Returns the equation for two-dimensional turbulence with `params` and `grid`.
"""
function Equation(params::Params, grid::AbstractGrid)
L = @. - params.ν * grid.Krsq^params.nν - params.μ * grid.Krsq^params.nμ
CUDA.@allowscalar L[1, 1] = 0
return FourierFlows.Equation(L, calcN!, grid)
end


# ----
# Vars
# ----

abstract type TwoDNavierStokesVars <: AbstractVars end

struct Vars{Aphys, Atrans, F, P} <: TwoDNavierStokesVars
u :: Aphys
v :: Aphys
η :: Aphys
uh :: Atrans
vh :: Atrans
ηh :: Atrans
Fh :: F
prevsol :: P
end

const ForcedVars = Vars{<:AbstractArray, <:AbstractArray, <:AbstractArray, Nothing}
const StochasticForcedVars = Vars{<:AbstractArray, <:AbstractArray, <:AbstractArray, <:AbstractArray}

"""
Vars(dev, grid)

Returns the `vars` for unforced two-dimensional turbulence on device `dev` and with `grid`.
"""
function Vars(::Dev, grid::AbstractGrid) where Dev
T = eltype(grid)
@devzeros Dev T (grid.nx, grid.ny) u v η
@devzeros Dev Complex{T} (grid.nkr, grid.nl) uh vh ηh
return Vars(u, v, η, uh, vh, ηh, nothing, nothing)
end

"""
ForcedVars(dev, grid)

Returns the vars for forced two-dimensional turbulence on device `dev` and with `grid`.
"""
function ForcedVars(dev::Dev, grid::AbstractGrid) where Dev
T = eltype(grid)
@devzeros Dev T (grid.nx, grid.ny) u v η
@devzeros Dev Complex{T} (grid.nkr, grid.nl) uh vh ηh Fh
return Vars(u, v, η, uh, vh, ηh, Fh, nothing)
end

"""
StochasticForcedVars(dev, grid)

Returns the vars for stochastically forced two-dimensional turbulence on device `dev` and with `grid`.
"""
function StochasticForcedVars(dev::Dev, grid::AbstractGrid) where Dev
T = eltype(grid)
@devzeros Dev T (grid.nx, grid.ny) u v η
@devzeros Dev Complex{T} (grid.nkr, grid.nl) uh vh ηh Fh prevsol
return Vars(u, v, η, uh, vh, ηh, Fh, prevsol)
end


# -------
# Solvers
# -------

"""
calcN_advection(N, sol, t, clock, vars, params, grid)

Calculates the advection term.
"""
function calcN_advection!(N, sol, t, clock, vars, params, grid)
@. N = 0 * sol

return nothing
end

function calcN!(N, sol, t, clock, vars, params, grid)
calcN_advection!(N, sol, t, clock, vars, params, grid)
addforcing!(N, sol, t, clock, vars, params, grid)

return nothing
end

addforcing!(N, sol, t, clock, vars::Vars, params, grid) = nothing

function addforcing!(N, sol, t, clock, vars::ForcedVars, params, grid)
params.calcF!(vars.Fh, sol, t, clock, vars, params, grid)

@. N += vars.Fh

return nothing
end

function addforcing!(N, sol, t, clock, vars::StochasticForcedVars, params, grid)
if t == clock.t # not a substep
@. vars.prevsol = sol # sol at previous time-step is needed to compute budgets for stochastic forcing
params.calcF!(vars.Fh, sol, t, clock, vars, params, grid)
end
@. N += vars.Fh
return nothing
end


# ----------------
# Helper functions
# ----------------

"""
updatevars!(prob)

Update variables in `vars` with solution in `sol`.
"""
function updatevars!(prob)
vars, grid, sol = prob.vars, prob.grid, prob.sol

return nothing
end

end # module
3 changes: 2 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import # use 'import' rather than 'using' for submodules to keep namespace clean
GeophysicalFlows.BarotropicQG,
GeophysicalFlows.BarotropicQGQL,
GeophysicalFlows.MultilayerQG,
GeophysicalFlows.SurfaceQG
GeophysicalFlows.SurfaceQG,
GeophysicalFlows.ShallowWater

using FourierFlows: parsevalsum
using GeophysicalFlows: lambdipole, peakedisotropicspectrum
Expand Down