|
1 | | -struct FieldDataset{F, M, P, KW} |
| 1 | +using Oceananigans.Fields: instantiated_location, indices, boundary_conditions |
| 2 | +import Oceananigans.Fields: set! |
| 3 | + |
| 4 | +struct FieldDataset{F, B, M, P, KW} |
2 | 5 | fields :: F |
| 6 | + backend :: B |
3 | 7 | metadata :: M |
4 | 8 | filepath :: P |
5 | 9 | reader_kw :: KW |
@@ -52,7 +56,7 @@ function FieldDataset(filepath; |
52 | 56 |
|
53 | 57 | close(file) |
54 | 58 |
|
55 | | - return FieldDataset(ds, metadata, abspath(filepath), reader_kw) |
| 59 | + return FieldDataset(ds, backend, metadata, abspath(filepath), reader_kw) |
56 | 60 | end |
57 | 61 |
|
58 | 62 | Base.getindex(fds::FieldDataset, inds...) = Base.getindex(fds.fields, inds...) |
@@ -80,3 +84,139 @@ function Base.show(io::IO, fds::FieldDataset) |
80 | 84 |
|
81 | 85 | return print(io, s) |
82 | 86 | end |
| 87 | + |
| 88 | +""" |
| 89 | + FieldDataset(grid, times, fields; |
| 90 | + backend = OnDisk(), |
| 91 | + path = nothing, |
| 92 | + location = NamedTuple(), |
| 93 | + indices = NamedTuple(), |
| 94 | + boundary_conditions = NamedTuple(), |
| 95 | + metadata = Dict(), |
| 96 | + reader_kw = NamedTuple()) |
| 97 | +
|
| 98 | +Returns a `FieldDataset` containing a new `FieldTimeSeries` for each key in `fields` |
| 99 | +on `grid` at `times`. |
| 100 | +
|
| 101 | +Keyword arguments |
| 102 | +================= |
| 103 | +- `backend`: backend, `InMemory(indices=Colon())` or `OnDisk()` |
| 104 | +
|
| 105 | +- `path`: path to data for `backend = OnDisk()` |
| 106 | +
|
| 107 | +- `location`: `NamedTuple` of location specifications, defaults to |
| 108 | + (Center, Center, Center) for each field` |
| 109 | +
|
| 110 | +- `indices`: `NamedTuple` of spatial indices, defaults to (:, :, :) for each field |
| 111 | +
|
| 112 | +- `boundary_conditions`: `NamedTuple` of boundary conditions for each field |
| 113 | +
|
| 114 | +- `metadata`: `Dict` containing metadata entries |
| 115 | +""" |
| 116 | +function FieldDataset(grid, times, fields::NTuple{N, Symbol}; |
| 117 | + backend=OnDisk(), |
| 118 | + path=nothing, |
| 119 | + location=NamedTuple(), |
| 120 | + indices=NamedTuple(), |
| 121 | + boundary_conditions=NamedTuple(), |
| 122 | + metadata=Dict(), |
| 123 | + reader_kw=NamedTuple(), |
| 124 | + ) where {N} |
| 125 | + |
| 126 | + field_names = map(String, fields) |
| 127 | + |
| 128 | + # Default behaviour |
| 129 | + indices = merge( |
| 130 | + NamedTuple(field=>(:, :, :) for field in fields), |
| 131 | + indices |
| 132 | + ) |
| 133 | + location = merge( |
| 134 | + NamedTuple(field=>(Center(), Center(), Center()) for field in fields), |
| 135 | + location |
| 136 | + ) |
| 137 | + boundary_conditions = merge( |
| 138 | + NamedTuple(field=>UnspecifiedBoundaryConditions() for field in fields), |
| 139 | + boundary_conditions |
| 140 | + ) |
| 141 | + |
| 142 | + # Create the FieldTimeSeries |
| 143 | + ftss = map(fields, field_names) do field, name |
| 144 | + inds = indices[field] |
| 145 | + loc = location[field] |
| 146 | + bcs = boundary_conditions[field] |
| 147 | + |
| 148 | + FieldTimeSeries(loc, grid, times; |
| 149 | + indices=inds, |
| 150 | + backend, |
| 151 | + path, |
| 152 | + name, |
| 153 | + reader_kw, |
| 154 | + boundary_conditions=bcs |
| 155 | + ) |
| 156 | + end |
| 157 | + |
| 158 | + ds = Dict{String, FieldTimeSeries}( |
| 159 | + name => fts |
| 160 | + for (name, fts) in zip(field_names, ftss) |
| 161 | + ) |
| 162 | + |
| 163 | + return FieldDataset(ds, backend, metadata, path, reader_kw) |
| 164 | +end |
| 165 | + |
| 166 | + |
| 167 | +""" |
| 168 | + FieldDataset(times, fields; |
| 169 | + backend = OnDisk(), |
| 170 | + path = nothing, |
| 171 | + metadata = Dict(), |
| 172 | + reader_kw = NamedTuple()) |
| 173 | +
|
| 174 | +Returns a `FieldDataset` containing a new `FieldTimeSeries` for each field |
| 175 | +in the `NamedTuple``fields` at `times`. Locations, indices and boundary |
| 176 | +conditions are extracted from `fields`` |
| 177 | +
|
| 178 | +Keyword arguments |
| 179 | +================= |
| 180 | +- `backend`: backend, `InMemory(indices=Colon())` or `OnDisk()` |
| 181 | +
|
| 182 | +- `path`: path to data for `backend = OnDisk()` |
| 183 | +
|
| 184 | +- `metadata`: `Dict` containing metadata entries |
| 185 | +""" |
| 186 | +function FieldDataset(times, fields; |
| 187 | + fds_kw... |
| 188 | + ) |
| 189 | + |
| 190 | + grid = fields[1].grid |
| 191 | + any([field.grid != grid for field in fields]) && throw(ArgumentError("All fields must be defined on the same grid")) |
| 192 | + |
| 193 | + loc = map(instantiated_location, fields) |
| 194 | + inds = map(Fields.indices, fields) |
| 195 | + bcs = map(Fields.boundary_conditions, fields) |
| 196 | + |
| 197 | + return FieldDataset(grid, times, keys(fields); |
| 198 | + location=loc, |
| 199 | + indices=inds, |
| 200 | + boundary_conditions=bcs, |
| 201 | + fds_kw... |
| 202 | + ) |
| 203 | +end |
| 204 | + |
| 205 | +# Setting a FieldDataset iterates over contained FieldTimeSeries |
| 206 | +function set!(fds::FieldDataset, args...; fields...) |
| 207 | + for (k, v) in pairs(fields) |
| 208 | + set!(fds[k], v, args...) |
| 209 | + end |
| 210 | +end |
| 211 | + |
| 212 | +# Write metadata if possible for OnDisk FieldDataset |
| 213 | +function set!(fds::FieldDataset{F, B, M, P, KW}, args...; fields...) where {F, B<:OnDisk, M, P, KW} |
| 214 | + jldopen(fds.filepath, "a+") do file |
| 215 | + for (k, v) in pairs(fds.metadata) |
| 216 | + maybe_write_property!(file, "metadata/$k", v) |
| 217 | + end |
| 218 | + end |
| 219 | + for (k, v) in pairs(fields) |
| 220 | + set!(fds[k], v, args...) |
| 221 | + end |
| 222 | +end |
0 commit comments