@@ -85,7 +85,7 @@ period = t[end] - t[1] + Δt
85
85
"""
86
86
struct Cyclical{FT}
87
87
period :: FT
88
- end
88
+ end
89
89
90
90
Cyclical () = Cyclical (nothing )
91
91
@@ -164,7 +164,7 @@ Nt = 5
164
164
backend = InMemory(4, 3) # so we have (4, 5, 1)
165
165
n = 1 # so, the right answer is m̃ = 3
166
166
m = 1 - (4 - 1) # = -2
167
- m̃ = mod1(-2, 5) # = 3 ✓
167
+ m̃ = mod1(-2, 5) # = 3 ✓
168
168
```
169
169
170
170
# Another shifting + wrapping example
@@ -213,7 +213,7 @@ Base.length(backend::PartlyInMemory) = backend.length
213
213
# #### FieldTimeSeries
214
214
# ####
215
215
216
- mutable struct FieldTimeSeries{LX, LY, LZ, TI, K, I, D, G, ET, B, χ, P, N} <: AbstractField{LX, LY, LZ, G, ET, 4}
216
+ mutable struct FieldTimeSeries{LX, LY, LZ, TI, K, I, D, G, ET, B, χ, P, N, KW } <: AbstractField{LX, LY, LZ, G, ET, 4}
217
217
data :: D
218
218
grid :: G
219
219
backend :: K
@@ -223,16 +223,18 @@ mutable struct FieldTimeSeries{LX, LY, LZ, TI, K, I, D, G, ET, B, χ, P, N} <: A
223
223
path :: P
224
224
name :: N
225
225
time_indexing :: TI
226
-
226
+ reader_kw :: KW
227
+
227
228
function FieldTimeSeries {LX, LY, LZ} (data:: D ,
228
229
grid:: G ,
229
230
backend:: K ,
230
231
bcs:: B ,
231
- indices:: I ,
232
+ indices:: I ,
232
233
times,
233
234
path,
234
235
name,
235
- time_indexing) where {LX, LY, LZ, K, D, G, B, I}
236
+ time_indexing,
237
+ reader_kw) where {LX, LY, LZ, K, D, G, B, I}
236
238
237
239
ET = eltype (data)
238
240
@@ -250,7 +252,7 @@ mutable struct FieldTimeSeries{LX, LY, LZ, TI, K, I, D, G, ET, B, χ, P, N} <: A
250
252
251
253
times = on_architecture (architecture (grid), times)
252
254
end
253
-
255
+
254
256
if time_indexing isa Cyclical{Nothing} # we have to infer the period
255
257
Δt = @allowscalar times[end ] - times[end - 1 ]
256
258
period = @allowscalar times[end ] - times[1 ] + Δt
@@ -261,23 +263,25 @@ mutable struct FieldTimeSeries{LX, LY, LZ, TI, K, I, D, G, ET, B, χ, P, N} <: A
261
263
TI = typeof (time_indexing)
262
264
P = typeof (path)
263
265
N = typeof (name)
266
+ KW = typeof (reader_kw)
264
267
265
- return new {LX, LY, LZ, TI, K, I, D, G, ET, B, χ, P, N} (data, grid, backend, bcs,
266
- indices, times, path, name,
267
- time_indexing)
268
+ return new {LX, LY, LZ, TI, K, I, D, G, ET, B, χ, P, N, KW } (data, grid, backend, bcs,
269
+ indices, times, path, name,
270
+ time_indexing, reader_kw )
268
271
end
269
272
end
270
273
271
- on_architecture (to, fts:: FieldTimeSeries{LX, LY, LZ} ) where {LX, LY, LZ} =
274
+ on_architecture (to, fts:: FieldTimeSeries{LX, LY, LZ} ) where {LX, LY, LZ} =
272
275
FieldTimeSeries {LX, LY, LZ} (on_architecture (to, fts. data),
273
276
on_architecture (to, fts. grid),
274
277
on_architecture (to, fts. backend),
275
278
on_architecture (to, fts. bcs),
276
- on_architecture (to, fts. indices),
279
+ on_architecture (to, fts. indices),
277
280
on_architecture (to, fts. times),
278
281
on_architecture (to, fts. path),
279
282
on_architecture (to, fts. name),
280
- on_architecture (to, fts. time_indexing))
283
+ on_architecture (to, fts. time_indexing),
284
+ on_architecture (to, fts. reader_kw))
281
285
282
286
# ####
283
287
# #### Minimal implementation of FieldTimeSeries for use in GPU kernels
@@ -290,7 +294,7 @@ struct GPUAdaptedFieldTimeSeries{LX, LY, LZ, TI, K, ET, D, χ} <: AbstractField{
290
294
times :: χ
291
295
backend :: K
292
296
time_indexing :: TI
293
-
297
+
294
298
function GPUAdaptedFieldTimeSeries {LX, LY, LZ} (data:: D ,
295
299
times: :χ ,
296
300
backend:: K ,
@@ -313,7 +317,7 @@ const FTS{LX, LY, LZ, TI, K} = FieldTimeSeries{LX, LY, LZ, TI, K} w
313
317
const GPUFTS{LX, LY, LZ, TI, K} = GPUAdaptedFieldTimeSeries{LX, LY, LZ, TI, K} where {LX, LY, LZ, TI, K}
314
318
315
319
const FlavorOfFTS{LX, LY, LZ, TI, K} = Union{GPUFTS{LX, LY, LZ, TI, K},
316
- FTS{LX, LY, LZ, TI, K}} where {LX, LY, LZ, TI, K}
320
+ FTS{LX, LY, LZ, TI, K}} where {LX, LY, LZ, TI, K}
317
321
318
322
const InMemoryFTS = FlavorOfFTS{<: Any , <: Any , <: Any , <: Any , <: AbstractInMemoryBackend }
319
323
const OnDiskFTS = FlavorOfFTS{<: Any , <: Any , <: Any , <: Any , <: OnDisk }
@@ -345,7 +349,7 @@ instantiate(T::Type) = T()
345
349
new_data (FT, grid, loc, indices, :: Nothing ) = nothing
346
350
347
351
# Apparently, not explicitly specifying Int64 in here makes this function
348
- # fail on x86 processors where `Int` is implied to be `Int32`
352
+ # fail on x86 processors where `Int` is implied to be `Int32`
349
353
# see ClimaOcean commit 3c47d887659d81e0caed6c9df41b7438e1f1cd52 at https://github.com/CliMA/ClimaOcean.jl/actions/runs/8804916198/job/24166354095)
350
354
function new_data (FT, grid, loc, indices, Nt:: Union{Int, Int64} )
351
355
space_size = total_size (grid, loc, indices)
@@ -360,12 +364,13 @@ time_indices_length(backend::PartlyInMemory, times) = length(backend)
360
364
time_indices_length (:: OnDisk , times) = nothing
361
365
362
366
function FieldTimeSeries (loc, grid, times= ();
363
- indices = (:, :, :),
367
+ indices = (:, :, :),
364
368
backend = InMemory (),
365
- path = nothing ,
369
+ path = nothing ,
366
370
name = nothing ,
367
371
time_indexing = Linear (),
368
- boundary_conditions = nothing )
372
+ boundary_conditions = nothing ,
373
+ reader_kw = Dict {Symbol, Any} ())
369
374
370
375
LX, LY, LZ = loc
371
376
@@ -376,9 +381,9 @@ function FieldTimeSeries(loc, grid, times=();
376
381
isnothing (path) && error (ArgumentError (" Must provide the keyword argument `path` when `backend=OnDisk()`." ))
377
382
isnothing (name) && error (ArgumentError (" Must provide the keyword argument `name` when `backend=OnDisk()`." ))
378
383
end
379
-
380
- return FieldTimeSeries {LX, LY, LZ} (data, grid, backend, boundary_conditions,
381
- indices, times, path, name, time_indexing)
384
+
385
+ return FieldTimeSeries {LX, LY, LZ} (data, grid, backend, boundary_conditions, indices,
386
+ times, path, name, time_indexing, reader_kw )
382
387
end
383
388
384
389
"""
@@ -405,10 +410,16 @@ end
405
410
struct UnspecifiedBoundaryConditions end
406
411
407
412
"""
408
- FieldTimeSeries(path, name, backend = InMemory();
413
+ FieldTimeSeries(path, name;
414
+ backend = InMemory(),
415
+ architecture = nothing,
409
416
grid = nothing,
417
+ location = nothing,
418
+ boundary_conditions = UnspecifiedBoundaryConditions(),
419
+ time_indexing = Linear(),
410
420
iterations = nothing,
411
- times = nothing)
421
+ times = nothing,
422
+ reader_kw = Dict{Symbol, Any}())
412
423
413
424
Return a `FieldTimeSeries` containing a time-series of the field `name`
414
425
load from JLD2 output located at `path`.
@@ -427,6 +438,9 @@ Keyword arguments
427
438
- `times`: Save times to load, as determined through an approximate floating point
428
439
comparison to recorded save times. Defaults to times associated with `iterations`.
429
440
Takes precedence over `iterations` if `times` is specified.
441
+
442
+ - `reader_kw`: A dictionary of keyword arguments to pass to the reader (currently only JLD2)
443
+ to be used when opening files.
430
444
"""
431
445
function FieldTimeSeries (path:: String , name:: String ;
432
446
backend = InMemory (),
@@ -436,9 +450,10 @@ function FieldTimeSeries(path::String, name::String;
436
450
boundary_conditions = UnspecifiedBoundaryConditions (),
437
451
time_indexing = Linear (),
438
452
iterations = nothing ,
439
- times = nothing )
453
+ times = nothing ,
454
+ reader_kw = Dict {Symbol, Any} ())
440
455
441
- file = jldopen (path)
456
+ file = jldopen (path; reader_kw ... )
442
457
443
458
# Defaults
444
459
isnothing (iterations) && (iterations = parse .(Int, keys (file[" timeseries/t" ])))
@@ -520,8 +535,8 @@ function FieldTimeSeries(path::String, name::String;
520
535
Nt = time_indices_length (backend, times)
521
536
data = new_data (eltype (grid), grid, loc, indices, Nt)
522
537
523
- time_series = FieldTimeSeries {LX, LY, LZ} (data, grid, backend, boundary_conditions,
524
- indices, times, path, name, time_indexing)
538
+ time_series = FieldTimeSeries {LX, LY, LZ} (data, grid, backend, boundary_conditions, indices,
539
+ times, path, name, time_indexing, reader_kw )
525
540
526
541
set! (time_series, path, name)
527
542
533
548
grid = nothing,
534
549
architecture = nothing,
535
550
indices = (:, :, :),
536
- boundary_conditions = nothing)
551
+ boundary_conditions = nothing,
552
+ reader_kw = Dict{Symbol, Any}())
537
553
538
554
Load a field called `name` saved in a JLD2 file at `path` at `iter`ation.
539
555
Unless specified, the `grid` is loaded from `path`.
@@ -542,7 +558,8 @@ function Field(location, path::String, name::String, iter;
542
558
grid = nothing ,
543
559
architecture = nothing ,
544
560
indices = (:, :, :),
545
- boundary_conditions = nothing )
561
+ boundary_conditions = nothing ,
562
+ reader_kw = Dict {Symbol, Any} ())
546
563
547
564
# Default to CPU if neither architecture nor grid is specified
548
565
if isnothing (architecture)
@@ -552,9 +569,9 @@ function Field(location, path::String, name::String, iter;
552
569
architecture = Architectures. architecture (grid)
553
570
end
554
571
end
555
-
572
+
556
573
# Load the grid and data from file
557
- file = jldopen (path)
574
+ file = jldopen (path; reader_kw ... )
558
575
559
576
isnothing (grid) && (grid = file[" serialized/grid" ])
560
577
raw_data = file[" timeseries/$name /$iter " ]
@@ -565,7 +582,7 @@ function Field(location, path::String, name::String, iter;
565
582
grid = on_architecture (architecture, grid)
566
583
raw_data = on_architecture (architecture, raw_data)
567
584
data = offset_data (raw_data, grid, location, indices)
568
-
585
+
569
586
return Field (location, grid; boundary_conditions, indices, data)
570
587
end
571
588
@@ -625,4 +642,3 @@ function fill_halo_regions!(fts::InMemoryFTS)
625
642
626
643
return nothing
627
644
end
628
-
0 commit comments