-
Notifications
You must be signed in to change notification settings - Fork 195
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
Fix test for implicit free surface with ImmersedBoundary
and indexed ReducedField
s
#2723
Conversation
@elise-palethorpe, fyi. |
I'll try to parse this carefully, but I do have a comment on this part:
Crucially, |
One problem is that |
I'm wasn't setting the Still I get julia> η = model.free_surface.η
128×1×1 Field{Center, Center, Nothing} reduced over dims = (3,) on ImmersedBoundaryGrid on CPU
├── grid: 128×1×5 ImmersedBoundaryGrid{Float64, Bounded, Periodic, Bounded} on CPU with 3×3×3 halo
├── boundary conditions: FieldBoundaryConditions
│ └── west: ZeroFlux, east: ZeroFlux, south: Periodic, north: Periodic, bottom: Nothing, top: Nothing, immersed: ZeroFlux
└── data: 134×7×1 OffsetArray(::Array{Float64, 3}, -2:131, -2:4, 1:1) with eltype Float64 with indices -2:131×-2:4×1:1
└── max=0.0, min=0.0, mean=0.0
julia> @info "implicit free surface solver test, norm(η): $(norm(η)), maximum(abs, η): $(maximum(abs, η))"
[ Info: implicit free surface solver test, norm(η): 0.0, maximum(abs, η): 0.0 |
Is |
No |
grid isa ImmersedBoundaryGrid && | ||
grid.immersed_boundary.bottom_height[i, j] ≥ grid.underlying_grid.zᵃᵃᶜ[k] && | ||
@error "The point to set u is on land!" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would something like
inactive_cell(i, j, k, grid) && error("The nudged cell at ($i, $j, $k) is inactive.")
work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This catches both halos and immersed cells, and doesn't require so many explicit references to grid properties that might have to be changed / maintained in the future if we change the names of those properties.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's great suggestion. I did it!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The problem persists though: the cell I'm nudging is not inactive but still I get η=0....
An update: using Oceananigans
using Statistics
using Oceananigans.Units
using Oceananigans.Architectures: device_event
using Oceananigans.TimeSteppers: update_state!
using LinearAlgebra: norm
using Oceananigans.Models.HydrostaticFreeSurfaceModels:
ImplicitFreeSurface,
FreeSurface,
PCGImplicitFreeSurfaceSolver,
implicit_free_surface_step!
function set_simple_divergent_velocity!(model)
# Create a divergent velocity
grid = model.grid
u, v, w = model.velocities
η = model.free_surface.η
u .= 0
v .= 0
η .= 0
# pick a surface cell at the middle of the domain
i, j, k = Int(floor(grid.Nx / 2)) + 1, Int(floor(grid.Ny / 2)) + 1, grid.Nz
inactive_cell(i, j, k, grid) && error("The nudged cell at ($i, $j, $k) is inactive.")
if grid isa RectilinearGrid
Δy = grid.Δyᵃᶜᵃ
end
if grid isa LatitudeLongitudeGrid
Δy = grid.Δyᶜᶠᵃ
end
if grid isa ImmersedBoundaryGrid
if grid isa ImmersedBoundaryGrid && grid.underlying_grid isa RectilinearGrid
Δy = grid.underlying_grid.Δyᵃᶜᵃ
elseif grid.underlying_grid isa LatitudeLongitudeGrid
Δy = grid.underlying_grid.Δyᶜᶠᵃ
end
end
Δz = CUDA.@allowscalar grid.Δzᵃᵃᶜ
# We prescribe the value of the zonal transport in a cell, i.e., `u * Δy * Δz`. This
# way `norm(rhs)` of the free-surface solver does not depend on the grid extensd/resolution.
transport = 1e5 # m³ s⁻¹
CUDA.@allowscalar u[i, j, k] = transport / (Δy * Δz)
update_state!(model)
return nothing
end
arch = CPU()
rectilinear_grid = RectilinearGrid(arch, size = (128, 1, 5),
x = (-5000kilometers, 5000kilometers),
y = (0, 100kilometers),
z = (-500, 0),
topology = (Bounded, Periodic, Bounded))
Lz = rectilinear_grid.Lz
width = rectilinear_grid.Lx / 20
bump(x, y) = - Lz * (1 - 0.2 * exp(-x^2 / 2width^2))
grid = ImmersedBoundaryGrid(rectilinear_grid, GridFittedBottom(bump))
free_surface = ImplicitFreeSurface(solver_method=:PreconditionedConjugateGradient,
abstol=1e-15, reltol=0)
model = HydrostaticFreeSurfaceModel(; grid,
momentum_advection = nothing,
free_surface)
set_simple_divergent_velocity!(model)
@show model.velocities.u
events = ((device_event(arch), device_event(arch)), (device_event(arch), device_event(arch)))
Δt = 900.0
implicit_free_surface_step!(model.free_surface, model, Δt, 1.5, events)
η = model.free_surface.η
@show norm(η)
@show maximum(abs, η)
@show maximum(abs, η.data) gives julia> @show maximum(abs, model.velocities.u)
maximum(abs, model.velocities.u) = 0.01
0.01
julia> @show norm(η)
norm(η) = 0.0
0.0
julia> @show maximum(abs, η)
maximum(abs, η) = 0.0
0.0
julia> @show maximum(abs, η.data)
maximum(abs, η.data) = 0.0
0.0 |
The problem stems (I think) that after Oceananigans.jl/src/Models/HydrostaticFreeSurfaceModels/implicit_free_surface.jl Line 140 in 0aa674f
maximum(rhs) = 0
maximum(rhs.data) = 11.330180144199204 and then when Oceananigans.jl/src/Models/HydrostaticFreeSurfaceModels/implicit_free_surface.jl Line 145 in 0aa674f
solve returns an maximum(η.data) = 0.0 (cc @glwagner, @simone-silvestri) |
most tests fail now...... :( Also I get julia> ∫ᶻ_Axᶠᶜᶜ = Field{Face, Center, Nothing}(with_halo((3, 3, 1), grid), indices = grid.Nz)
ERROR: BoundsError: attempt to access Tuple{Int64} at index [2]
Stacktrace:
[1] indexed_iterate
@ ./tuple.jl:86 [inlined]
[2] new_data(FT::DataType, grid::ImmersedBoundaryGrid{Float64, Bounded, Periodic, Bounded, RectilinearGrid{Float64, Bounded, Periodic, Bounded, Float64, Float64, Float64, OffsetVector{Float64, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}}, OffsetVector{Float64, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}}, OffsetVector{Float64, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}}, CPU}, GridFittedBottom{OffsetMatrix{Float64, Matrix{Float64}}, Oceananigans.ImmersedBoundaries.CenterImmersedCondition}, CPU}, loc::Tuple{DataType, DataType, DataType}, indices::Int64)
@ Oceananigans.Grids ~/Research/OC2.jl/src/Grids/new_data.jl:59
[3] (Field{Face, Center, Nothing, O, G, I, D, T, B, S, F} where {O, G, I, D, T, B, S, F})(grid::ImmersedBoundaryGrid{Float64, Bounded, Periodic, Bounded, RectilinearGrid{Float64, Bounded, Periodic, Bounded, Float64, Float64, Float64, OffsetVector{Float64, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}}, OffsetVector{Float64, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}}, OffsetVector{Float64, StepRangeLen{Float64, Base.TwicePrecision{Float64}, Base.TwicePrecision{Float64}}}, CPU}, GridFittedBottom{OffsetMatrix{Float64, Matrix{Float64}}, Oceananigans.ImmersedBoundaries.CenterImmersedCondition}, CPU}, T::DataType; kw::Base.Iterators.Pairs{Symbol, Int64, Tuple{Symbol}, NamedTuple{(:indices,), Tuple{Int64}}})
@ Oceananigans.Fields ~/Research/OC2.jl/src/Fields/field.jl:158
[4] top-level scope
@ REPL[24]:1
[5] top-level scope
@ ~/.julia/packages/CUDA/DfvRa/src/initialization.jl:52 |
that should be
there are a couple of things to smooth out |
This is the progress
I am still struggling with the |
ImmersedBoundary
ImmersedBoundary
and indexed for ReducedField
s
ImmersedBoundary
and indexed for ReducedField
sImmersedBoundary
and indexed ReducedField
s
the boundary conditions will be a bit tricky to handle since we pass only the data and not the field... but we can fix it |
now |
weird, I get this
Maybe we have not set correctly the index of the residuals? |
…into ncc/test-for-2710
What is expected? Isn't |
Yeah so this should be ok. Reductions and reduced fields without a specified position are located at I am still bugfixing a bit though. |
I don't totally understand. I think we want to build out support for behavior when a field is sliced at a single index. But why would we want to build this feature for fields that are also reduced?
I'm opposed to this, which reduces the concepts we can express in the code. I think we retain more flexibility if we interpret a I think in fact that it should be invalid to specify the index of a field in the reduced direction. |
|
||
function validate_index(idx::UnitRange, loc, topo, N, H) | ||
all_idx = all_indices(loc, topo, N, H) | ||
(first(idx) ∈ all_idx && last(idx) ∈ all_idx) || throw(ArgumentError("The indices $idx must slice $I")) | ||
(first(idx) ∈ all_idx && last(idx) ∈ all_idx) || throw(ArgumentError("The indices $idx must be a slice of the domain")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The original message was more specific and clear. Can we return to that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
but what was I
?
All of that said, I suspect that the changes in this PR are important --- it's just that we need to clarify the difference between a One consequence is: the free surface will not be a reduced field. This design was the primary motivation for PR #2246. |
Ok, I agree with your comments.
|
That will be so so beautiful |
There is a test for immersed boundary inside
test_implicit_free_surface.jl
but it seems to be trivially passing (see, e.g., the log from tests run onmain
).One problem was that
set_simple_divergent_velocity!
function defined atOceananigans.jl/test/test_implicit_free_surface_solver.jl
Lines 17 to 35 in af21542
was setting a non-zero
u
velocity in the center of the domain atk = 1
, but that was inside the immersed boundary. I changed theset_simple_divergent_velocity!
function to address that. However, still there is an issue...I managed to pinpoint it down to the step:
Oceananigans.jl/src/Models/HydrostaticFreeSurfaceModels/implicit_free_surface.jl
Line 140 in f585ef8
Here's a demonstration... (not a MWE). I have a model with non-zero
u
velocity:I call
Now, when I print out
∫ᶻQ.u
I see that all its elements are supposedly 0:But this returns the right answer
The velocity set by
set_simple_divergent_velocity!
is 0.1 andΔz = 80
so that's correct!Hm.... Here's a MWE now to demonstrate that somewhere something is not passed on.
gives
cc @glwagner, @simone-silvestri