Skip to content

ConjugateGradientPoissonSolver blows up with PartialCellBottom #4634

@xkykai

Description

@xkykai

Using PartialCellBottom causes ConjugateGradientPoissonSolver to blow up. This is independent of the preconditioner as the simulation blows up with or without a preconditioner.

Here's an MWE:

using Oceananigans
using Oceananigans.Models.NonhydrostaticModels: ConjugateGradientPoissonSolver, FFTBasedPoissonSolver, FourierTridiagonalPoissonSolver
using Oceananigans.Models.NonhydrostaticModels: nonhydrostatic_pressure_solver
using Oceananigans.Grids: with_number_type
using Printf

function initial_conditions!(model)
    h = 0.05
    x₀ = 0.5
    y₀ = 0.5
    z₀ = 0.55
    bᵢ(x, y, z) = - exp(-((x - x₀)^2 + (y - y₀)^2 + (z - z₀)^2) / 2h^2)

    set!(model, b=bᵢ)
end

function setup_grid(Nx, Ny, Nz, arch)
    grid = RectilinearGrid(arch, Float64,
                        size = (Nx, Ny, Nz), 
                        halo = (4, 4, 4),
                        x = (0, 1),
                        y = (0, 1),
                        z = (0, 1),
                        topology = (Bounded, Bounded, Bounded))

    slope(x, y) = (5 + tanh(40*(x - 1/6)) + tanh(40*(x - 2/6)) + tanh(40*(x - 3/6)) + tanh(40*(x - 4/6)) + tanh(40*(x - 5/6))) / 20 + 
                  (5 + tanh(40*(y - 1/6)) + tanh(40*(y - 2/6)) + tanh(40*(y - 3/6)) + tanh(40*(y - 4/6)) + tanh(40*(y - 5/6))) / 20

    # grid = ImmersedBoundaryGrid(grid, GridFittedBottom(slope))
    grid = ImmersedBoundaryGrid(grid, PartialCellBottom(slope))
    return grid
end

function setup_model(grid, pressure_solver)
    model = NonhydrostaticModel(; grid, pressure_solver,
                                  advection = WENO(),
                                  coriolis = FPlane(f=0.1),
                                  tracers = :b,
                                  buoyancy = BuoyancyTracer())

    initial_conditions!(model)
    return model
end

function setup_simulation(model, Δt, stop_iteration)
    return Simulation(model, Δt=Δt, stop_iteration=stop_iteration)
end

function setup_simulation(model)
    Δt = 1e-4
    stop_iteration = 10
    simulation = Simulation(model; Δt = Δt, stop_iteration = stop_iteration, minimum_relative_step = 1e-10)
    
    wall_time = Ref(time_ns())

    function progress(sim)
        pressure_solver = sim.model.pressure_solver
    
        if pressure_solver isa ConjugateGradientPoissonSolver
            pressure_iters = iteration(pressure_solver)
        else
            pressure_iters = 0
        end

        msg = @sprintf("iter: %d, time: %s, Δt: %.4f, Poisson iters: %d",
                        iteration(sim), prettytime(time(sim)), sim.Δt, pressure_iters)
    
        elapsed = 1e-9 * (time_ns() - wall_time[])
    
        u, v, w = sim.model.velocities
        d = Field(∂x(u) + ∂y(v) + ∂z(w))
        compute!(d)
    
        msg *= @sprintf(", max u: %6.3e, max w: %6.3e, max b: %6.3e, max d: %6.3e, max pressure: %6.3e, wall time: %s",
                        maximum(sim.model.velocities.u),
                        maximum(sim.model.velocities.w),
                        maximum(sim.model.tracers.b),
                        maximum(d),
                        maximum(sim.model.pressures.pNHS),
                        prettytime(elapsed))
    
        @info msg
        wall_time[] = time_ns()
    
        return nothing
    end

    simulation.callbacks[:progress] = Callback(progress, IterationInterval(1))
    
    return simulation
end

const Nx = 32
const Ny = 32
const Nz = 32

arch = CPU()
grid = setup_grid(Nx, Ny, Nz, arch)

@info "Create pressure solver"
# preconditioner = nonhydrostatic_pressure_solver(with_number_type(Float32, grid.underlying_grid))
# preconditioner = FourierTridiagonalPoissonSolver(grid.underlying_grid)
preconditioner = nothing

reltol = abstol = 1e-7
pressure_solver = ConjugateGradientPoissonSolver(
    grid, maxiter=10000, preconditioner=preconditioner; reltol, abstol)

@info "Create model"
model = setup_model(grid, pressure_solver)

simulation = setup_simulation(model)

run!(simulation)

which gives the output of

[ Info: Initializing simulation...
[ Info: iter: 0, time: 0 seconds, Δt: 0.0001, Poisson iters: 0, max u: 0.000e+00, max w: 0.000e+00, max b: -2.750e-66, max d: 0.000e+00, max pressure: 0.000e+00, wall time: 444.359 ms
[ Info:     ... simulation initialization complete (576.466 ms)
[ Info: Executing initial time step...
[ Info: iter: 1, time: 100 μs, Δt: 0.0001, Poisson iters: 125, max u: 3.783e-05, max w: 2.261e-05, max b: -2.750e-66, max d: 3.888e-03, max pressure: 3.194e-02, wall time: 511.381 ms
[ Info:     ... initial time step complete (803.167 ms).
[ Info: iter: 2, time: 200.000 μs, Δt: 0.0001, Poisson iters: 117, max u: 4.387e-05, max w: 1.381e-05, max b: -2.750e-66, max d: 2.169e-03, max pressure: 2.018e-02, wall time: 550.837 ms
[ Info: iter: 3, time: 300.000 μs, Δt: 0.0001, Poisson iters: 198, max u: 2.443e-04, max w: 1.401e-04, max b: -2.750e-66, max d: 4.469e-02, max pressure: 2.528e-01, wall time: 627.441 ms
[ Info: iter: 4, time: 400.000 μs, Δt: 0.0001, Poisson iters: 866, max u: 1.114e-03, max w: 3.694e-04, max b: -2.750e-66, max d: 1.158e-01, max pressure: 1.645e+00, wall time: 2.619 seconds
[ Info: iter: 5, time: 500.000 μs, Δt: 0.0001, Poisson iters: 420, max u: 4.251e-02, max w: 5.466e-03, max b: -2.750e-66, max d: 1.696e+00, max pressure: 9.528e+00, wall time: 2.286 seconds
[ Info: iter: 6, time: 600 μs, Δt: 0.0001, Poisson iters: 247, max u: 4.238e-02, max w: 1.437e-02, max b: 7.223e-52, max d: 5.950e+01, max pressure: 6.749e+03, wall time: 988.661 ms
[ Info: iter: 7, time: 700 μs, Δt: 0.0001, Poisson iters: 234, max u: 1.741e+02, max w: 2.057e-01, max b: 9.315e-45, max d: 5.466e+03, max pressure: 5.876e+02, wall time: 893.501 ms
[ Info: iter: 8, time: 800.000 μs, Δt: 0.0001, Poisson iters: 205, max u: 2.560e+04, max w: 6.915e+01, max b: 1.092e-39, max d: 2.371e+06, max pressure: 4.060e+07, wall time: 949.581 ms
[ Info: iter: 9, time: 900.000 μs, Δt: 0.0001, Poisson iters: 177, max u: 1.623e+20, max w: 1.931e+18, max b: 1.698e+02, max d: 2.387e+22, max pressure: 2.208e+23, wall time: 750.430 ms
[ Info: Simulation is stopping after running for 13.094 seconds.
[ Info: Model iteration 10 equals or exceeds stop iteration 10.
[ Info: iter: 10, time: 1000.000 μs, Δt: 0.0001, Poisson iters: 158, max u: 4.397e+147, max w: 1.564e+145, max b: 5.441e+108, max d: 5.818e+149, max pressure: 4.489e+150, wall time: 629.644 ms

When PartialCellBottom is replaced with GridFittedBottom then the simulation does not blow up.

Sub-issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions