Can we impose a surface boundary condition that depends on the surface average of a field? #2386
Unanswered
tomchor
asked this question in
Computational science!
Replies: 2 comments 5 replies
-
There are two primary ways I can think of (but probably many more):
|
Beta Was this translation helpful? Give feedback.
3 replies
-
Just for reference this is how I ended up implementing a MWE of an adaptive top BC based on @glwagner's option 1 (with callbacks): using Oceananigans
using Oceananigans.Fields: VelocityFields, TracerFields
Nx = 64
Nz = 32
grid = RectilinearGrid(topology=(Periodic, Flat, Bounded),
size=(Nx, Nz),
x=(0, 1), z=(0, 1),
halo=(3,3),
)
u_top_bc = FluxBoundaryCondition(zeros(grid, grid.Nx, grid.Ny))
u_bc = FieldBoundaryConditions(top=u_top_bc)
model = NonhydrostaticModel(; grid,
boundary_conditions=(u=u_bc,),
closure = ScalarDiffusivity(ν=1e-3),
)
u_ic(x, y, z) = randn()
set!(model, u=u_ic)
u, v, w = model.velocities
using Oceananigans.Grids: min_Δz
simulation = Simulation(model, Δt=0.1min_Δz(grid)/maximum(u), stop_time=10)
using Statistics: mean
function update_boundary_condition!(simulation)
u, v, w = simulation.model.velocities
U = mean(interior(u)[:,:,grid.Nz]) # this and the following line probably require adaptation to run on GPUs
model.velocities.u.boundary_conditions.top.condition .= U
return nothing
end
simulation.callbacks[:bc] = Callback(update_boundary_condition!)
wizard = TimeStepWizard(max_change=1.1, cfl=0.7)
simulation.callbacks[:wizard] = Callback(wizard, IterationInterval(2))
output_interval = 5
fields_to_output = merge(model.velocities, model.tracers,)
simulation.output_writers[:fields] = NetCDFOutputWriter(model, fields_to_output,
schedule = TimeInterval(output_interval),
filepath = "op1.nc",
mode = "c")
run!(simulation) This turned out to be pretty close to what I had originally tried, with the exception that I was trying to use callbacks to change Thanks again to @glwagner for the help. |
Beta Was this translation helpful? Give feedback.
2 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Basically I'd like to know if it's currently possible to impose a surface boundary condition for a field (say
u
) that depends on the surface average of that field (in this case anxy
average ofu
at the point closest to the surface)?I know that the answer to this question used to be a no (I'm guessing because the kernels only access local information?), but with the recent improvements to reductions, callbacks, etc., I figured there could be a way to achieve that?
That said, every attempt that I've tried today failed completely... heh
If it's not indeed possible yet, maybe we can discuss ideas of how to implement that? The easiest to me seems to be changing the boundary condition of the given field with a callback at every iteration, but I get an error every time I try that:
so my guess is that currently the BCs are implemented with immutable
struct
s or something along those lines...Beta Was this translation helpful? Give feedback.
All reactions