-
Notifications
You must be signed in to change notification settings - Fork 209
/
Copy pathcomputed_field.jl
92 lines (69 loc) · 3.02 KB
/
computed_field.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
85
86
87
88
89
90
91
92
#####
##### Fields computed from abstract operations
#####
using KernelAbstractions: @kernel, @index
using Oceananigans.Grids: default_indices
using Oceananigans.Fields: FieldStatus, reduced_dimensions, validate_indices, offset_compute_index
using Oceananigans.Utils: launch!
import Oceananigans.Fields: Field, compute!
const ComputedField = Field{<:Any, <:Any, <:Any, <:AbstractOperation}
"""
Field(operand::AbstractOperation;
data = nothing,
indices = indices(operand),
boundary_conditions = FieldBoundaryConditions(operand.grid, location(operand)),
recompute_safely = true)
Return a field `f` where `f.data` is computed from `f.operand` by calling `compute!(f)`.
Keyword arguments
=================
`data` (`AbstractArray`): An offset Array or CuArray for storing the result of a computation.
Must have `total_size(location(operand), grid)`.
`boundary_conditions` (`FieldBoundaryConditions`): Boundary conditions for `f`.
`recompute_safely` (`Bool`): whether or not to _always_ "recompute" `f` if `f` is
nested within another computation via an `AbstractOperation`.
If `data` is not provided then `recompute_safely=false` and
recomputation is _avoided_. If `data` is provided, then
`recompute_safely = true` by default.
"""
function Field(operand::AbstractOperation;
data = nothing,
indices = indices(operand),
boundary_conditions = FieldBoundaryConditions(operand.grid, location(operand)),
recompute_safely = true)
grid = operand.grid
loc = location(operand)
indices = validate_indices(indices, loc, grid)
boundary_conditions = FieldBoundaryConditions(indices, boundary_conditions)
if isnothing(data)
data = new_data(grid, loc, indices)
recompute_safely = false
end
status = recompute_safely ? nothing : FieldStatus()
return Field(loc, grid, data, boundary_conditions, indices, operand, status)
end
"""
compute!(comp::ComputedField)
Compute `comp.operand` and store the result in `comp.data`.
"""
function compute!(comp::ComputedField, time=nothing)
# First compute `dependencies`:
@apply_regionally compute_at!(comp.operand, time)
# Now perform the primary computation
@apply_regionally compute_computed_field!(comp)
fill_halo_regions!(comp)
return comp
end
function compute_computed_field!(comp)
arch = architecture(comp)
event = launch!(arch, comp.grid, size(comp), _compute!, comp.data, comp.operand, comp.indices)
wait(device(arch), event)
return comp
end
"""Compute an `operand` and store in `data`."""
@kernel function _compute!(data, operand, index_ranges)
i, j, k = @index(Global, NTuple)
i′ = offset_compute_index(index_ranges[1], i)
j′ = offset_compute_index(index_ranges[2], j)
k′ = offset_compute_index(index_ranges[3], k)
@inbounds data[i′, j′, k′] = operand[i′, j′, k′]
end