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

Field major refactor: one Field to rule them all #2121

Merged
merged 150 commits into from
Jan 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
150 commits
Select commit Hold shift + click to select a range
251cc95
One Field to rule them all
glwagner Dec 10, 2021
4ffaeb2
test_field success
glwagner Dec 15, 2021
a28c71f
Fix up nonhydrostatic model tests
glwagner Dec 15, 2021
39a8f65
Moves reduced field tests into test_field
glwagner Dec 15, 2021
0e18182
Bugfix in test_field
glwagner Dec 15, 2021
e844db4
Changing the Field API one constructor at a time
glwagner Dec 15, 2021
d9df9df
Fixes for test_poisson_solvers
glwagner Dec 17, 2021
8ea5331
Fix time-stepping tests and DiffusivityFields
glwagner Dec 18, 2021
79cdafb
Fixing up hydrostatic model tests
glwagner Dec 18, 2021
13be16a
Fixes tests and implmements field Reductions
glwagner Dec 29, 2021
983d268
Widespread bugfixes
glwagner Dec 30, 2021
057f573
Fixes bug with Average field reduction
glwagner Dec 31, 2021
86eff52
Updates computed Field and BuoyancyField tests
glwagner Dec 31, 2021
e0c9761
Fix broadcasting tests
glwagner Dec 31, 2021
82595b7
Updates simulation tests
glwagner Dec 31, 2021
8ce4c54
Merge branch 'main' into glw/one-field-rule-all
glwagner Dec 31, 2021
3bcbcff
Bugfix in show mmethod for lat-lon grid
glwagner Dec 31, 2021
e7aaf09
Import total_extent into test_grids
glwagner Dec 31, 2021
30952c4
Fixs abstract operatons tests
glwagner Dec 31, 2021
8d9672f
Multifarous updates
glwagner Jan 3, 2022
f6fbf49
Fixes some tests
glwagner Jan 3, 2022
ceec2dc
Fix shallow water tests
glwagner Jan 3, 2022
09d3aa6
ComputedField -> Field in validation
glwagner Jan 3, 2022
e5543f6
Touch up FieldTimeSeries
glwagner Jan 3, 2022
b1bd858
Fixes bug in FieldTimeSeries
glwagner Jan 3, 2022
94fceab
Fixes tridiagonal solver test
glwagner Jan 3, 2022
236dc46
No longer need both arch and grid
glwagner Jan 3, 2022
6f86969
Updates stratified couette flow script
glwagner Jan 3, 2022
5174310
Bugfix in building PCG implicit free surface solver
glwagner Jan 10, 2022
f9e7f8c
Fixes bug in DistributedField constructor
glwagner Jan 10, 2022
d6338b4
Bugfixes in Matrix implicit solver
glwagner Jan 11, 2022
2eb44ae
Need halo=(3, 3, 3) with WENO advection
glwagner Jan 11, 2022
e63ad80
Fix matrix poisson solver tests
glwagner Jan 11, 2022
52226ab
Different fix for immersed boundary test issue
glwagner Jan 11, 2022
f48c6fc
Updates to matrix poisson solver tests
glwagner Jan 11, 2022
5de6818
Random fix to matrix poisson solver test
glwagner Jan 11, 2022
de58b4f
Update new_data for ConformalCubedSphereGrid
glwagner Jan 11, 2022
34c798a
Update validate_field_data for cubed sphere fields
glwagner Jan 11, 2022
c879974
Dont use WENO5 advection for conjugate gradient solver test
glwagner Jan 11, 2022
dbac16d
Import fill_halo_regions into field.jl plus cosmetics
glwagner Jan 11, 2022
e3f0c44
Change ComputedField to Field in docs
glwagner Jan 11, 2022
3b28967
Use architecture(field)
glwagner Jan 11, 2022
f6f20b3
Missing comma
glwagner Jan 11, 2022
6e161b7
Figuring out fill_halo_regions for distributed fields
glwagner Jan 11, 2022
733d228
Gets rid of ReducedField
glwagner Jan 11, 2022
0956f84
Missing comma
glwagner Jan 11, 2022
9ac2d1b
Dispatch shenanigans
glwagner Jan 11, 2022
df643d1
CubedSphere updates
glwagner Jan 11, 2022
01aed6d
Merge branch 'main' into glw/one-field-rule-all
glwagner Jan 11, 2022
45b28d6
Accept kwargs in distributed halo filling functions
glwagner Jan 11, 2022
ee68573
Typing issues plus better show for computed Fields
glwagner Jan 11, 2022
62ea28b
Adds get_face for KernelFunctionOperation
glwagner Jan 11, 2022
e229e58
Bugfix in halo exchange test
glwagner Jan 11, 2022
ff7a551
Fiddling with dispatch for distributed halo filling
glwagner Jan 11, 2022
65925f9
loosen type restriction on RectilinearGrid architecture
glwagner Jan 11, 2022
e72fc8a
Ok completely release type restriction in grid constructors
glwagner Jan 11, 2022
365b87e
Bugfix in distributed fill_halo_regions!
glwagner Jan 11, 2022
50f7a69
Fixes bug in reconstruct_global_grid
glwagner Jan 11, 2022
30a79d0
Fix doctest for grid_metrics
glwagner Jan 11, 2022
781e1f2
Fix doctest for binary operation
glwagner Jan 11, 2022
79d7dd7
Fix doctest in UnaryOperation
glwagner Jan 11, 2022
3ab3e55
Fix doctest in multiary operation
glwagner Jan 11, 2022
99314c7
my_grid -> local_grid
glwagner Jan 11, 2022
4946540
Only replace shallow water model grid if necessary
glwagner Jan 11, 2022
cce7dde
Update docstring for rectilinear grid
glwagner Jan 12, 2022
b300ebb
Use on_architecture rather than adapt_structure in similar
glwagner Jan 12, 2022
ab684c5
Minor fixes
glwagner Jan 12, 2022
b11d14a
Merge branch 'glw/one-field-rule-all' of https://github.com/CliMA/Oce…
glwagner Jan 12, 2022
93cffd2
Get arch from local_grid in FFT-based PoissonSolver
glwagner Jan 12, 2022
8bae800
Only remake grid if halos are too _small_
glwagner Jan 12, 2022
e12883f
Brings examples up to date with current Field syntax
glwagner Jan 12, 2022
1c5cce6
fixed bug in grid
simone-silvestri Jan 12, 2022
4a5ee20
Updates docstring output
glwagner Jan 12, 2022
6d02ead
Merge branch 'glw/one-field-rule-all' of https://github.com/CliMA/Oce…
glwagner Jan 12, 2022
c4e04d3
May need to relax tolerances in field reduction tests
glwagner Jan 12, 2022
c9dec67
Merge branch 'glw/one-field-rule-all' of https://github.com/CliMA/Oce…
glwagner Jan 12, 2022
07c2f96
Fusses with tolerance for field reduction tests
glwagner Jan 12, 2022
a72b13c
Update show_coordinate
glwagner Jan 12, 2022
4f5e6af
Fixes NonhydrostaticModel comparison
glwagner Jan 12, 2022
92a36d6
Merge branch 'glw/one-field-rule-all' of https://github.com/CliMA/Oce…
glwagner Jan 12, 2022
fff0b6b
Move show_coordinate to grid_utils and import Printf
glwagner Jan 12, 2022
d14325f
Fix doctest for grid
glwagner Jan 12, 2022
c36f948
Fix docstring in rectilinear_grid
glwagner Jan 12, 2022
7e3e4b0
set! only Field and use child_arch in distributed field type param
glwagner Jan 12, 2022
041939f
on_architecture for conformal cubed sphere grid
glwagner Jan 12, 2022
d437213
Fix typo
glwagner Jan 12, 2022
158e1ba
Bugfixes in conformal cubed sphere grid
glwagner Jan 12, 2022
24e3c17
Fixes FieldTimeSeries tests
glwagner Jan 13, 2022
557a40d
Allow scalar indexing in on_architecture
glwagner Jan 13, 2022
4f33243
Adds on_architecture for ImmersedBoundaryGrid
glwagner Jan 13, 2022
0b95ed7
Adds array_type for MultiArch
glwagner Jan 13, 2022
be6994e
Cosmetics
glwagner Jan 13, 2022
0282c7a
bump minor release
navidcy Jan 13, 2022
843fe21
CenterField infers arch from grid
navidcy Jan 13, 2022
6ec01fe
avoid ambiguity in `on_architecture` method
navidcy Jan 13, 2022
0c53f78
Bugfix in on_architecture for immersed boundary girds
glwagner Jan 13, 2022
fcc7454
Bugfix in adapt_structure for conformal cubed sphere grid
glwagner Jan 13, 2022
f5f5065
Merge branch 'glw/one-field-rule-all' of https://github.com/CliMA/Oce…
glwagner Jan 13, 2022
9b5fc07
Bug fix in distributed poisson solvers test
glwagner Jan 13, 2022
4bf77eb
Update src/AbstractOperations/kernel_function_operation.jl
glwagner Jan 13, 2022
fb86cdd
Eliminate on_architecture(::Nothing, grid)
glwagner Jan 13, 2022
cf419f1
Add arch_array for abstract range
glwagner Jan 13, 2022
d5f61a0
Merge branch 'glw/one-field-rule-all' of https://github.com/CliMA/Oce…
glwagner Jan 13, 2022
9fdb82b
Remove Architecture as type parameter in Field and AbstractField plus…
glwagner Jan 13, 2022
ca77537
End the Fields module
glwagner Jan 13, 2022
966db50
Reorganize show and short_show for ReducedComputedFields
glwagner Jan 13, 2022
c77cdcb
Numerous bugfixes
glwagner Jan 13, 2022
83732b9
Bugfix for derivatives
glwagner Jan 13, 2022
b0d5677
Bugfix in CubedSphere
glwagner Jan 13, 2022
4ac3e92
Dont import KernelComputedField into CubedSpheres
glwagner Jan 13, 2022
7b171d3
Simplify CubedSphere set!
glwagner Jan 13, 2022
6c10263
Adds back fallback for location
glwagner Jan 13, 2022
5a47c29
Resolve ambiguities for setting fields on the cubed sphere
glwagner Jan 13, 2022
89eb639
Update DistributedField constructor
glwagner Jan 13, 2022
3cd5e34
Fixes show_location
glwagner Jan 13, 2022
95d40c5
Spruse up info formatting for cubed sphere tests
glwagner Jan 13, 2022
4512c64
Fix adapt_structure for reduced fields
glwagner Jan 13, 2022
cfa3d03
Fix ViewField alias
glwagner Jan 13, 2022
0013723
Bugfix in interior_copy
glwagner Jan 13, 2022
731d5ca
Fix field for gpu grids
glwagner Jan 13, 2022
363ba06
Add allowscalar for time_discretization determination
glwagner Jan 13, 2022
c8a833e
import CUDA into single_column_model_mode.jl
glwagner Jan 13, 2022
188fc4e
Bugfix in interior for FieldTimeSeries
glwagner Jan 13, 2022
d439132
Ensure that set! for functions is always on cpu
glwagner Jan 13, 2022
5335b84
Set for Array right
glwagner Jan 13, 2022
91e32c5
Respect architecture when grid is specified
glwagner Jan 13, 2022
341abdf
Restrict set! for arrays to specific kinds of arrays
glwagner Jan 13, 2022
a10a8c5
Fix method resolution in cubed sphere set
glwagner Jan 13, 2022
a4754ac
Distinguish between CPU and GPU cases in field-field setting
glwagner Jan 14, 2022
154c013
Import CUDA into cubed_sphere_faces
glwagner Jan 14, 2022
48add20
Fix on_architecture for non-conversions
glwagner Jan 14, 2022
ab0073d
Merge branch 'glw/one-field-rule-all' of https://github.com/CliMA/Oce…
glwagner Jan 14, 2022
3b31b0b
Refactor on_architecture
glwagner Jan 14, 2022
2a5197d
Missing comma
glwagner Jan 14, 2022
cae064f
Write loop in on_architecture explicitly
glwagner Jan 14, 2022
e89900e
Bugfix in on_architecture for conformal cubed sphere grid
glwagner Jan 14, 2022
3a39126
Add numbers to the list of architecture-agnostic objs
glwagner Jan 14, 2022
e9f4e51
Slightly reorganize computed field test
glwagner Jan 14, 2022
925653f
Add functionality to set! for cpu-gpu transfers of views
glwagner Jan 14, 2022
d619484
Bugfix on_architecture for lat-lon grid
glwagner Jan 14, 2022
b98fb59
Regular grid shortcut plus fix on_architecture
glwagner Jan 14, 2022
7701b42
Shortcut for regular grids
glwagner Jan 14, 2022
adb2e8b
Add abstol to some netcdf time averaging tests
glwagner Jan 14, 2022
cb615be
Add Colon to list of valid dims
glwagner Jan 14, 2022
7ba6eef
Minor updates and bugfix for Average with dims=:
glwagner Jan 14, 2022
ee945bc
Fix show for ReducedComputedField
glwagner Jan 14, 2022
2b6a119
Disambiguate bc regularization for CubedSphere
glwagner Jan 14, 2022
59717c5
Fixes bug in set!
glwagner Jan 14, 2022
2cbc5bd
Merge branch 'glw/one-field-rule-all' of https://github.com/CliMA/Oce…
glwagner Jan 14, 2022
24f7e8c
Restore all regression tests
glwagner Jan 14, 2022
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
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
name = "Oceananigans"
uuid = "9e8cae18-63c1-5223-a75c-80ca9d6e9a09"
version = "0.67.1"
version = "0.68.0"

[deps]
Adapt = "79e6a3ab-5dfb-504d-930d-738a2a938a0e"
Expand Down
4 changes: 2 additions & 2 deletions docs/src/model_setup/grids.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,8 +115,8 @@ RectilinearGrid{Float64, Periodic, Bounded, Bounded}
size (Nx, Ny, Nz): (64, 64, 32)
halo (Hx, Hy, Hz): (1, 1, 1)
spacing in x: Regular, with spacing 156.25
spacing in y: Stretched, with spacing min=6.022718974138115, max=245.33837163709035
spacing in z: Stretched, with spacing min=2.407636663901485, max=49.008570164780394
spacing in y: Stretched, with spacing min=6.022719, max=245.338372
spacing in z: Stretched, with spacing min=2.407637, max=49.008570
```

```@setup 1
Expand Down
2 changes: 1 addition & 1 deletion docs/src/model_setup/output_writers.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ function init_save_some_metadata!(file, model)
return nothing
end

c_avg = AveragedField(model.tracers.c, dims=(1, 2))
c_avg = Field(Average(model.tracers.c, dims=(1, 2)))

# Note that model.velocities is NamedTuple
simulation.output_writers[:velocities] = JLD2OutputWriter(model, model.velocities,
Expand Down
93 changes: 38 additions & 55 deletions docs/src/simulation_tips.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@

# Simulation tips

In Oceananigans we try to do most of the optimizing behind the scenes, that way the average user
doesn't have to worry about details when setting up a simulation. However, there's just so much
optimization that can be done in the source code. Because of Oceananigans script-based interface,
the user has to be aware of some things when writing the simulation script in order to take full
advantage of Julia's speed. Furthermore, in case of more complex GPU runs, some details could
Oceananigans attemps to optimize as much of a computation as possible "behind the scenes".
Yet Oceananigans' flexibility places some responsibility on users to ensure high performance simulations,
especially for complex setups with user-defined forcing functions, boundary condition functions, and diagnostics.
Furthermore, in case of more complex GPU runs, some details could
sometimes prevent your simulation from running altogether. While Julia knowledge is obviously
desirable here, a user that is unfamiliar with Julia can get away with efficient simulations by
learning a few rules of thumb. It is nonetheless recommended that users go through Julia's
[performance tips](https://docs.julialang.org/en/v1/manual/performance-tips/), which contains more
in-depth explanations of some of the aspects discussed here.



## General (CPU/GPU) simulation tips

### Avoid global variables whenever possible
Expand All @@ -37,7 +33,6 @@ GPU kernels (such as functions defining boundary conditions and forcings). Other
compiler can fail with obscure errors. This is explained in more detail in the GPU simulation tips
section below.


### Consider inlining small functions

Inlining is when the compiler [replaces a function call with the body of the function that is being
Expand All @@ -58,8 +53,6 @@ certainty_, since Julia and KernelAbstractions.jl (needed for GPU runs) already
functions automatically. However, it is generally a good idea to at least investigate this aspect in
your code as the benefits can potentially be significant.



## GPU simulation tips

Running on GPUs can be very different from running on CPUs. Oceananigans makes most of the necessary
Expand All @@ -69,7 +62,6 @@ for more complex simulations some care needs to be taken on the part of the user
GPU computing (and Julia) is again desirable, an inexperienced user can also achieve high efficiency
in GPU simulations by following a few simple principles.


### Global variables that need to be used in GPU computations need to be defined as constants or passed as parameters

Any global variable that needs to be accessed by the GPU needs to be a constant or the simulation
Expand Down Expand Up @@ -102,9 +94,9 @@ surface_temperature(x, y, t, p) = p.T₀ * sin(2π / 86400 * t)
T_bcs = FieldBoundaryConditions(bottom = GradientBoundaryCondition(surface_temperature, parameters=(T₀=T₀,)))
```

### Complex diagnostics using `ComputedField`s may not work on GPUs
### Complex diagnostics using computed `Field`s may not work on GPUs

`ComputedField`s are the most convenient way to calculate diagnostics for your simulation. They will
`Field`s are the most convenient way to calculate diagnostics for your simulation. They will
always work on CPUs, but when their complexity is high (in terms of number of abstract operations)
the compiler can't translate them into GPU code and they fail for GPU runs. (This limitation is summarized
in [this Github issue](https://github.com/CliMA/Oceananigans.jl/issues/1886) and contributions are welcome.)
Expand All @@ -117,40 +109,33 @@ grid = RectilinearGrid(size=(4, 4, 4), extent=(1, 1, 1))
model = NonhydrostaticModel(grid=grid, closure=IsotropicDiffusivity(ν=1e-6))
u, v, w = model.velocities
ν = model.closure.ν
u² = ComputedField(u^2)
ε = ComputedField(ν*(∂x(u)^2 + ∂x(v)^2 + ∂x(w)^2 + ∂y(u)^2 + ∂y(v)^2 + ∂y(w)^2 + ∂z(u)^2 + ∂z(v)^2 + ∂z(w)^2))
u² = Field(u^2)
ε = Field(ν*(∂x(u)^2 + ∂x(v)^2 + ∂x(w)^2 + ∂y(u)^2 + ∂y(v)^2 + ∂y(w)^2 + ∂z(u)^2 + ∂z(v)^2 + ∂z(w)^2))
compute!(u²)
compute!(ε)
```

There are two approaches to
bypass this issue. The first is to nest `ComputedField`s. For example,
we can make `ε` be successfully computed on GPUs by defining it as
There are a few ways to work around this issue.
One is to compute `ε` in steps by nesting computed `Field`s,
```julia
ddx² = ComputedField(∂x(u)^2 + ∂x(v)^2 + ∂x(w)^2)
ddy² = ComputedField(∂y(u)^2 + ∂y(v)^2 + ∂y(w)^2)
ddz² = ComputedField(∂z(u)^2 + ∂z(v)^2 + ∂z(w)^2)
ε = ComputedField(ν*(ddx² + ddy² + ddz²))
ddx² = Field(∂x(u)^2 + ∂x(v)^2 + ∂x(w)^2)
ddy² = Field(∂y(u)^2 + ∂y(v)^2 + ∂y(w)^2)
ddz² = Field(∂z(u)^2 + ∂z(v)^2 + ∂z(w)^2)
ε = Field(ν * (ddx² + ddy² + ddz²))
compute!(ε)
```

This is a simple workaround that is especially suited for the development stage of a simulation.
However, when running this, the code will iterate over the whole domain 4 times to calculate `ε`
(one for each computed field defined), which is not very efficient and may slow down your simulation
if this diagnostic is being calculated very often.

A different way to calculate `ε` is by using `KernelFunctionOperations`s, where the
user manually specifies the computing kernel function to the compiler. The advantage of this method is that
it's more efficient (the code will only iterate once over the domain in order to calculate `ε`),
but the disadvantage is that this method requires some knowledge of Oceananigans operations
and how they should be performed on a C-grid. For example calculating `ε` with this approach would
look like this:
This method is expensive because it requires computing and storing 3 intermediate terms.
`ε` may also be calculated via `KernelFunctionOperations`s, which
requires explicitly building a "kernel function" from low-level Oceananigans
operators.

```julia
using Oceananigans.Operators
using Oceananigans.AbstractOperations: KernelFunctionOperation

@inline fψ_plus_gφ²(i, j, k, grid, f, ψ, g, φ) = @inbounds (f(i, j, k, grid, ψ) + g(i, j, k, grid, φ))^2

function isotropic_viscous_dissipation_rate_ccc(i, j, k, grid, u, v, w, ν)
Σˣˣ² = ∂xᶜᵃᵃ(i, j, k, grid, u)^2
Σʸʸ² = ∂yᵃᶜᵃ(i, j, k, grid, v)^2
Expand All @@ -162,45 +147,46 @@ function isotropic_viscous_dissipation_rate_ccc(i, j, k, grid, u, v, w, ν)

return ν * 2 * (Σˣˣ² + Σʸʸ² + Σᶻᶻ² + 2 * (Σˣʸ² + Σˣᶻ² + Σʸᶻ²))
end
ε = ComputedField(KernelFunctionOperation{Center, Center, Center}(isotropic_viscous_dissipation_rate_ccc, grid;
computed_dependencies=(u, v, w, ν)))

ε_op = KernelFunctionOperation{Center, Center, Center}(isotropic_viscous_dissipation_rate_ccc,
grid;
computed_dependencies=(u, v, w, ν))

ε = Field(ε_op)

compute!(ε)
```

Writing kernel functions like `isotropic_viscous_dissipation_rate_ccc`
requires understanding the C-grid, but incurs only one iteration over the domain.

It may be useful to know that there are some kernels already defined for commonly-used diagnostics
in packages that are companions to Oceananigans. For example
[Oceanostics.jl](https://github.com/tomchor/Oceanostics.jl/blob/3b8f67338656557877ef8ef5ebe3af9e7b2974e2/src/TurbulentKineticEnergyTerms.jl#L35-L57)
and
[LESbrary.jl](https://github.com/CliMA/LESbrary.jl/blob/master/src/TurbulenceStatistics/shear_production.jl).
Users should first look there before writing any kernel by hand and are always welcome to [start an
issue on Github](https://github.com/CliMA/Oceananigans.jl/issues/new) if they need help to write a
different kernel. As an illustration, the calculation of `ε` using Oceanostics.jl (after installing the package)
which works on both CPUs and GPUs is simply
`KernelFunctionOperation`s for some diagnostics common to large eddy simulation are defined in
[Oceanostics.jl](https://github.com/tomchor/Oceanostics.jl/blob/3b8f67338656557877ef8ef5ebe3af9e7b2974e2/src/TurbulentKineticEnergyTerms.jl#L35-L57),

```julia
using Oceanostics: IsotropicPseudoViscousDissipationRate
ε = IsotropicViscousDissipationRate(model, u, v, w, ν)
compute!(ε)
```
[Start an issue on Github](https://github.com/CliMA/Oceananigans.jl/issues/new) if more help is needed.


### Try to decrease the memory-use of your runs

GPU runs are generally memory-limited. As an example, a state-of-the-art Tesla V100 GPU has 32GB of
memory, which is enough to fit, on average, a simulation with about 100 million points --- a bit
smaller than a 512-cubed simulation. (The precise number depends on many other things, such as the
number of tracers simulated, as well as the diagnostics that are calculated.) This means that it is
especially important to be mindful of the size of your runs when running Oceananigans on GPUs and it
is generally good practice to decrease the memory required for your runs. Below are some useful tips
to achieve this
GPU runs are sometimes memory-limited. A state-of-the-art Tesla V100 GPU has 32GB of
memory --- enough memory for simulations with about 100 million points, or grids a bit smaller
than 512 × 512 × 512. (The maximum grid size depends on some user-specified factors,
like the number of passive tracers or computed diagnostics.)
For large simulations on the GPU, careful management of memory allocation may be required:

- Use the [`nvidia-smi`](https://developer.nvidia.com/nvidia-system-management-interface) command
line utility to monitor the memory usage of the GPU. It should tell you how much memory there is
on your GPU and how much of it you're using and you can run it from Julia with the command ``run(`nvidia-smi`)``.

- Try to use higher-order advection schemes. In general when you use a higher-order scheme you need
fewer grid points to achieve the same accuracy that you would with a lower-order one. Oceananigans
provides two high-order advection schemes: 5th-order WENO method (WENO5) and 3rd-order upwind.

- Manually define scratch space to be reused in diagnostics. By default, every time a user-defined
diagnostic is calculated the compiler reserves a new chunk of memory for that calculation, usually
called scratch space. In general, the more diagnostics, the more scratch space needed and the bigger
Expand All @@ -212,8 +198,6 @@ to achieve this
and then being used in calculations
[here](https://github.com/CliMA/LESbrary.jl/blob/cf31b0ec20219d5ad698af334811d448c27213b0/src/TurbulenceStatistics/first_through_third_order.jl#L109-L112).



### Arrays in GPUs are usually different from arrays in CPUs

Oceananigans.jl uses [`CUDA.CuArray`](https://cuda.juliagpu.org/stable/usage/array/) to store
Expand All @@ -227,7 +211,6 @@ which is very slow and can result in huge slowdowns. For this reason, Oceananiga
scalar indexing by default. See the [scalar indexing](https://juliagpu.github.io/CUDA.jl/dev/usage/workflow/#UsageWorkflowScalar)
section of the CUDA.jl documentation for more information on scalar indexing.


For example if can be difficult to just view a `CuArray` since Julia needs to access
its elements to do that. Consider the example below:

Expand Down
11 changes: 5 additions & 6 deletions examples/convecting_plankton.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
# and grazing by zooplankton.
# * How to set time-dependent boundary conditions.
# * How to use the `TimeStepWizard` to adapt the simulation time-step.
# * How to use `AveragedField` to diagnose spatial averages of model fields.
# * How to use `Average` and `Field` to diagnose spatial averages of model fields.
#
# ## Install dependencies
#
Expand Down Expand Up @@ -175,7 +175,7 @@ simulation.callbacks[:progress] = Callback(progress, IterationInterval(20))
# and a basic `JLD2OutputWriter` that writes velocities and both
# the two-dimensional and horizontally-averaged plankton concentration,

averaged_plankton = AveragedField(model.tracers.P, dims=(1, 2))
averaged_plankton = Field(Average(model.tracers.P, dims=(1, 2)))

outputs = (w = model.velocities.w,
plankton = model.tracers.P,
Expand All @@ -190,10 +190,9 @@ simulation.output_writers[:simple_output] =
# !!! info "Using multiple output writers"
# Because each output writer is associated with a single output `schedule`,
# it often makes sense to use _different_ output writers for different types of output.
# For example, reduced fields like `AveragedField` usually consume less disk space than
# two- or three-dimensional fields, and can thus be output more frequently without
# blowing up your hard drive. An arbitrary number of output writers may be added to
# `simulation.output_writers`.
# For example, smaller outputs that consume less disk space may be written more
# frequently without threatening the capacity of your hard drive.
# An arbitrary number of output writers may be added to `simulation.output_writers`.
#
# The simulation is set up. Let there be plankton:

Expand Down
10 changes: 5 additions & 5 deletions examples/eady_turbulence.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# * How to use a tuple of turbulence closures
# * How to use hyperdiffusivity
# * How to implement background velocity and tracer distributions
# * How to use `ComputedField`s for output
# * How to build `Field`s that compute output
#
# ## Install dependencies
#
Expand Down Expand Up @@ -275,16 +275,16 @@ simulation.callbacks[:progress] = Callback(progress, IterationInterval(10))
# ### Output
#
# To visualize the baroclinic turbulence ensuing in the Eady problem,
# we use `ComputedField`s to diagnose and output vertical vorticity and divergence.
# Note that `ComputedField`s take "AbstractOperations" on `Field`s as input:
# we use computed `Field`s to diagnose and output vertical vorticity and divergence.
# Note that computed `Field`s take "AbstractOperations" on `Field`s as input:

u, v, w = model.velocities # unpack velocity `Field`s

## Vertical vorticity [s⁻¹]
ζ = ComputedField(∂x(v) - ∂y(u))
ζ = Field(∂x(v) - ∂y(u))

## Horizontal divergence, or ∂x(u) + ∂y(v) [s⁻¹]
δ = ComputedField(-∂z(w))
δ = Field(-∂z(w))

# With the vertical vorticity, `ζ`, and the horizontal divergence, `δ` in hand,
# we create a `JLD2OutputWriter` that saves `ζ` and `δ` and add them to
Expand Down
16 changes: 8 additions & 8 deletions examples/horizontal_convection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
#
# This example demonstrates:
#
# * How to use `ComputedField`s for output.
# * How to use computed `Field`s for output.
# * How to post-process saved output using `FieldTimeSeries`.
#
# ## Install dependencies
Expand Down Expand Up @@ -128,18 +128,18 @@ simulation.callbacks[:progress] = Callback(progress, IterationInterval(50))

# ### Output
#
# We use `ComputedField`s to diagnose and output the total flow speed, the vorticity, ``\zeta``,
# and the buoyancy, ``b``. Note that `ComputedField`s take "AbstractOperations" on `Field`s as
# We use computed `Field`s to diagnose and output the total flow speed, the vorticity, ``\zeta``,
# and the buoyancy, ``b``. Note that computed `Field`s take "AbstractOperations" on `Field`s as
# input:

u, v, w = model.velocities # unpack velocity `Field`s
b = model.tracers.b # unpack buoyancy `Field`

## total flow speed
s = ComputedField(sqrt(u^2 + w^2))
s = Field(sqrt(u^2 + w^2))

## y-component of vorticity
ζ = ComputedField(∂z(u) - ∂x(w))
ζ = Field(∂z(u) - ∂x(w))

outputs = (s = s, b = b, ζ = ζ)
nothing # hide
Expand Down Expand Up @@ -209,7 +209,7 @@ anim = @animate for i in 1:length(times)
ζ_snapshot = interior(ζ_timeseries[i])[:, 1, :]

b = b_timeseries[i]
χ = ComputedField(κ * (∂x(b)^2 + ∂z(b)^2))
χ = Field(κ * (∂x(b)^2 + ∂z(b)^2))
compute!(χ)

b_snapshot = interior(b)[:, 1, :]
Expand Down Expand Up @@ -313,8 +313,8 @@ nothing # hide

grid = b_timeseries.grid

∫ⱽ_s² = ReducedField(Nothing, Nothing, Nothing, CPU(), grid, dims=(1, 2, 3))
∫ⱽ_mod²_∇b = ReducedField(Nothing, Nothing, Nothing, CPU(), grid, dims=(1, 2, 3))
∫ⱽ_s² = Field{Nothing, Nothing, Nothing}(grid)
∫ⱽ_mod²_∇b = Field{Nothing, Nothing, Nothing}(grid)

# We recover the time from the saved `FieldTimeSeries` and construct two empty arrays to store
# the volume-averaged kinetic energy and the instantaneous Nusselt number,
Expand Down
8 changes: 4 additions & 4 deletions examples/kelvin_helmholtz_instability.jl
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ nothing # hide
u, v, w = model.velocities
b = model.tracers.b

perturbation_vorticity = ComputedField(∂z(u) - ∂x(w))
perturbation_vorticity = Field(∂z(u) - ∂x(w))

xF, yF, zF = nodes(perturbation_vorticity)

Expand Down Expand Up @@ -332,7 +332,7 @@ nothing # hide

using Random, Statistics

mean_perturbation_kinetic_energy = AveragedField(1/2 * (u^2 + w^2), dims=(1, 2, 3))
mean_perturbation_kinetic_energy = Field(Average(1/2 * (u^2 + w^2)))

noise(x, y, z) = randn()

Expand Down Expand Up @@ -377,9 +377,9 @@ rescale!(simulation.model, mean_perturbation_kinetic_energy, target_kinetic_ener
# buoyancy (perturbation + basic state). It'll be also neat to plot the kinetic energy time-series
# and confirm it grows with the estimated growth rate.

total_vorticity = ComputedField(∂z(u) + ∂z(model.background_fields.velocities.u) - ∂x(w))
total_vorticity = Field(∂z(u) + ∂z(model.background_fields.velocities.u) - ∂x(w))

total_b = ComputedField(b + model.background_fields.tracers.b)
total_b = Field(b + model.background_fields.tracers.b)

simulation.output_writers[:vorticity] =
JLD2OutputWriter(model, (ω=perturbation_vorticity, Ω=total_vorticity, b=b, B=total_b, KE=mean_perturbation_kinetic_energy),
Expand Down
10 changes: 5 additions & 5 deletions examples/langmuir_turbulence.jl
Original file line number Diff line number Diff line change
Expand Up @@ -225,12 +225,12 @@ simulation.output_writers[:fields] =

u, v, w = model.velocities

U = AveragedField(u, dims=(1, 2))
V = AveragedField(v, dims=(1, 2))
B = AveragedField(model.tracers.b, dims=(1, 2))
U = Field(Average(u, dims=(1, 2)))
V = Field(Average(v, dims=(1, 2)))
B = Field(Average(model.tracers.b, dims=(1, 2)))

wu = AveragedField(w * u, dims=(1, 2))
wv = AveragedField(w * v, dims=(1, 2))
wu = Field(Average(w * u, dims=(1, 2)))
wv = Field(Average(w * v, dims=(1, 2)))

simulation.output_writers[:averages] =
JLD2OutputWriter(model, (u=U, v=V, b=B, wu=wu, wv=wv),
Expand Down
Loading