-
Notifications
You must be signed in to change notification settings - Fork 193
/
explicit_free_surface.jl
84 lines (62 loc) · 3.01 KB
/
explicit_free_surface.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
using Oceananigans.Architectures: device_event
using Oceananigans.Grids: AbstractGrid
using Oceananigans.Operators: ∂xᶠᶜᶜ, ∂yᶜᶠᶜ
using Oceananigans.BoundaryConditions: regularize_field_boundary_conditions
using Adapt
"""
struct ExplicitFreeSurface{E, T}
The explicit free surface solver.
$(TYPEDFIELDS)
"""
struct ExplicitFreeSurface{E, G} <: AbstractFreeSurface{E, G}
"free surface elevation"
η :: E
"gravitational accelerations"
gravitational_acceleration :: G
end
ExplicitFreeSurface(; gravitational_acceleration=g_Earth) =
ExplicitFreeSurface(nothing, gravitational_acceleration)
Adapt.adapt_structure(to, free_surface::ExplicitFreeSurface) =
ExplicitFreeSurface(Adapt.adapt(to, free_surface.η), free_surface.gravitational_acceleration)
#####
##### Interface to HydrostaticFreeSurfaceModel
#####
function FreeSurface(free_surface::ExplicitFreeSurface{Nothing}, velocities, grid)
η = FreeSurfaceDisplacementField(velocities, free_surface, grid)
g = convert(eltype(grid), free_surface.gravitational_acceleration)
return ExplicitFreeSurface(η, g)
end
#####
##### Kernel functions for HydrostaticFreeSurfaceModel
#####
@inline explicit_barotropic_pressure_x_gradient(i, j, k, grid, free_surface::ExplicitFreeSurface) =
free_surface.gravitational_acceleration * ∂xᶠᶜᶜ(i, j, grid.Nz+1, grid, free_surface.η)
@inline explicit_barotropic_pressure_y_gradient(i, j, k, grid, free_surface::ExplicitFreeSurface) =
free_surface.gravitational_acceleration * ∂yᶜᶠᶜ(i, j, grid.Nz+1, grid, free_surface.η)
#####
##### Time stepping
#####
function ab2_step_free_surface!(free_surface::ExplicitFreeSurface, model, Δt, χ, prognostic_field_events)
@apply_regionally prognostic_field_events = explicit_ab2_step_free_surface!(free_surface, model, Δt, χ, prognostic_field_events)
return prognostic_field_events
end
# ab2_step_free_surface!(free_surface::ExplicitFreeSurface, model, Δt, χ, prognostic_field_events) =
# @apply_regionally explicit_ab2_step_free_surface!(free_surface, model, Δt, χ, prognostic_field_events)
function explicit_ab2_step_free_surface!(free_surface, model, Δt, χ, prognostic_field_events)
free_surface_event = launch!(model.architecture, model.grid, :xy,
_explicit_ab2_step_free_surface!, free_surface.η, Δt, χ,
model.timestepper.Gⁿ.η, model.timestepper.G⁻.η, size(model.grid, 3),
dependencies = device_event(model.architecture))
return MultiEvent(tuple(prognostic_field_events[1]..., prognostic_field_events[2]..., free_surface_event))
# wait(device(model.architecture), free_surface_event)
# return nothing
end
#####
##### Kernel
#####
@kernel function _explicit_ab2_step_free_surface!(η, Δt, χ::FT, Gηⁿ, Gη⁻, Nz) where FT
i, j = @index(Global, NTuple)
@inbounds begin
η[i, j, Nz+1] += Δt * ((FT(1.5) + χ) * Gηⁿ[i, j, Nz+1] - (FT(0.5) + χ) * Gη⁻[i, j, Nz+1])
end
end