33
44using Dates
55
6+
7+ abstract type AbstractTimeAxis end
8+ abstract type AbstractTimePeriod end
9+
10+ """
11+ struct TimeAxis{Ty} <: AbstractTimeAxis
12+
13+ Time axis specification for `FlowFields` data structure. This un-mutable specification
14+ describes the overall range of simulations that can be performed using the `FlowFields`.
15+
16+ - initial : beginning of simulation period
17+ - final : end of simulation period
18+ - origin : beginning of the valid time period, when flow fields are available
19+ - horizon : end of the valid time period, when flow fields are available
20+ - climatology : false by default ; but can be set to true for time-periodic flow fields.
21+
22+ Rules :
23+
24+ - In most simple cases `origin,horizon` is just the same as `initial,final`.
25+ - By default `initial,final` and `origin,horizon` are set to the `FlowField`'s `TimePeriod`.
26+ - However, any specification where `initial,final` is within `origin,horizon` is correct.
27+ - This more general approach makes it easy to split simulations into smaller intervals.
28+
29+ ```
30+ using Drifters, Dates
31+
32+ D0=DateTime(2000,1,1)
33+ D1=DateTime(2000,3,1)
34+ TA=Drifters.TimeAxis(D0,D1)
35+ TA=Drifters.TimeAxis(D0,D1,D0,D1,false)
36+ ```
37+ """
38+ struct TimeAxis{Ty} <: AbstractTimeAxis
39+ initial:: Ty
40+ final:: Ty
41+ origin:: Ty
42+ horizon:: Ty
43+ Climatology:: Bool
44+ end
45+
46+ TimeAxis (t0= 0.0 ,t1= 1.0 ) = TimeAxis (t0,t1,t0,t1,false )
47+
48+ """
49+ struct TimePeriod{Ty} <: AbstractTimePeriod
50+
51+ Time period for next simulation of `Individuals` displacement specified
52+ as a vector `[initial,final]`. The `value` field is a mutable vector that
53+ can be changed, e.g. within a time loop when carrying out longer simulations.
54+
55+ Rules :
56+
57+ - if `final` precedes `initial` then the simulation goes backward in time
58+ - in most simple cases, `initial,final` are the same in `TimePeriod` and `TimeAxis`.
59+ - but any `initial,final` within the periods defined in 'TimeAxis` works for `TimePeriod`.
60+
61+ ```
62+ using Drifters, Dates
63+
64+ D0=DateTime(2000,1,1)
65+ D1=DateTime(2000,3,1)
66+ TP=Drifters.TimePeriod([D0,D1])
67+ TA=Drifters.TimeAxis(TP)
68+ ```
69+ """
70+ struct TimePeriod{Ty} <: AbstractTimePeriod
71+ value:: Array{Ty,1}
72+ end
73+
74+ TimePeriod (T0,T1) = TimePeriod ([T0,T1])
75+
76+ TimeAxis (TP:: TimePeriod ) = TimeAxis (TP. value... )
77+
678"""
779 abstract type FlowFields
880
@@ -53,17 +125,20 @@ struct uvArrays{Ty} <: FlowFields
53125 v0:: Array{Ty,2}
54126 v1:: Array{Ty,2}
55127 T:: Union{Array{Ty},Array{DateTime}}
128+ TimeAxis:: AbstractTimeAxis
56129end
57130
58131function FlowFields (u0:: Array{Ty,2} ,u1:: Array{Ty,2} ,
59- v0:: Array{Ty,2} ,v1:: Array{Ty,2} ,T:: Union{Array,Tuple} ) where Ty
132+ v0:: Array{Ty,2} ,v1:: Array{Ty,2} ,T:: Union{Array,Tuple} ;
133+ time_axis= missing ) where Ty
60134 # ensure T is a vector and enforce type
61135 T= time_set_type .(collect (T),Ty)
136+ TA= (ismissing (time_axis) ? TimeAxis (T... ) : time_axis)
62137 # check array size concistency
63138 tst= prod ([(size (u0)== size (tmp)) for tmp in (u1,v0,v1)])
64139 ! tst ? error (" inconsistent array sizes" ) : nothing
65140 # call constructor
66- uvArrays (u0,u1,v0,v1,T)
141+ uvArrays (u0,u1,v0,v1,T,TA )
67142end
68143
69144struct uvwArrays{Ty} <: FlowFields
@@ -74,6 +149,7 @@ struct uvwArrays{Ty} <: FlowFields
74149 w0:: Array{Ty,3}
75150 w1:: Array{Ty,3}
76151 T:: Union{Array{Ty},Array{DateTime}}
152+ TimeAxis:: AbstractTimeAxis
77153end
78154
79155"""
@@ -90,7 +166,7 @@ F=FlowFields(u=uC,v=vC,period=(0,10.))
90166```
91167"""
92168function FlowFields (; u:: Union{Array,Tuple} = [], v:: Union{Array,Tuple} = [], w:: Union{Array,Tuple} = [],
93- period:: Union{Array,Tuple} = [])
169+ period:: Union{Array,Tuple} = [], time_axis = missing )
94170 (isa (u,Tuple)|| length (u[:])== 2 ) ? (u0= u[1 ]; u1= u[2 ]) : (u0= u; u1= u)
95171 (isa (v,Tuple)|| length (v[:])== 2 ) ? (v0= v[1 ]; v1= v[2 ]) : (v0= v; v1= v)
96172 (isa (w,Tuple)|| length (w[:])== 2 ) ? (w0= w[1 ]; w1= w[2 ]) : (w0= w; w1= w)
@@ -99,9 +175,9 @@ function FlowFields(; u::Union{Array,Tuple}=[], v::Union{Array,Tuple}=[], w::Uni
99175 end
100176 if ! isempty (u0) && ! isempty (v0)
101177 if ! isempty (w0)
102- FlowFields (u0,u1,v0,v1,w0,w1,period)
178+ FlowFields (u0,u1,v0,v1,w0,w1,period,time_axis = time_axis )
103179 else
104- FlowFields (u0,u1,v0,v1,period)
180+ FlowFields (u0,u1,v0,v1,period,time_axis = time_axis )
105181 end
106182 else
107183 []
@@ -139,15 +215,16 @@ to_C_grid!(x;dims=0) = begin
139215end
140216
141217function FlowFields (u0:: Array{Ty,3} ,u1:: Array{Ty,3} ,v0:: Array{Ty,3} ,v1:: Array{Ty,3} ,
142- w0:: Array{Ty,3} ,w1:: Array{Ty,3} ,T:: Union{Array,Tuple} ) where Ty
218+ w0:: Array{Ty,3} ,w1:: Array{Ty,3} ,T:: Union{Array,Tuple} ; time_axis = missing ) where Ty
143219 # ensure T is a vector and enforce type
144220 T= time_set_type .(collect (T),Ty)
221+ TA= (ismissing (time_axis) ? TimeAxis (T... ) : time_axis)
145222 # check array size concistency
146223 tst= prod ([(size (u0)== size (tmp)) for tmp in (u1,v0,v1)])
147224 tst= tst* prod ([(size (u0)== size (tmp).- (0 ,0 ,1 )) for tmp in (w0,w1)])
148225 ! tst ? error (" inconsistent array sizes" ) : nothing
149226 # call constructor
150- uvwArrays (u0,u1,v0,v1,w0,w1,T)
227+ uvwArrays (u0,u1,v0,v1,w0,w1,T,TA )
151228end
152229
153230struct uvMeshArrays{Ty} <: FlowFields
@@ -156,26 +233,28 @@ struct uvMeshArrays{Ty} <: FlowFields
156233 v0:: AbstractMeshArray{Ty,1}
157234 v1:: AbstractMeshArray{Ty,1}
158235 T:: Union{Array{Ty},Array{DateTime}}
236+ TimeAxis:: AbstractTimeAxis
159237 update_location!:: Function
160238end
161239
162240function FlowFields (u0:: MeshArrays.MeshArray_wh ,u1:: MeshArrays.MeshArray_wh ,
163241 v0:: MeshArrays.MeshArray_wh ,v1:: MeshArrays.MeshArray_wh ,
164- T:: Union{Array,Tuple} ,update_location!:: Function )
242+ T:: Union{Array,Tuple} ,update_location!:: Function ; time_axis = missing )
165243
166- FlowFields (u0. MA,u1. MA,v0. MA,v1. MA,T,update_location!)
244+ FlowFields (u0. MA,u1. MA,v0. MA,v1. MA,T,update_location!,time_axis = time_axis )
167245end
168246
169247function FlowFields (u0:: AbstractMeshArray{Ty,1} ,u1:: AbstractMeshArray{Ty,1} ,
170248 v0:: AbstractMeshArray{Ty,1} ,v1:: AbstractMeshArray{Ty,1} ,
171- T:: Union{Array,Tuple} ,update_location!:: Function ) where Ty
249+ T:: Union{Array,Tuple} ,update_location!:: Function ; time_axis = missing ) where Ty
172250 # ensure T is a vector and enforce type
173251 T= time_set_type .(collect (T),Ty)
252+ TA= (ismissing (time_axis) ? TimeAxis (T... ) : time_axis)
174253 # check array size concistency
175254 tst= prod ([(size (u0)== size (tmp))* (u0. fSize== tmp. fSize) for tmp in (u1,v0,v1)])
176255 ! tst ? error (" inconsistent array sizes" ) : nothing
177256 # call constructor
178- uvMeshArrays (u0,u1,v0,v1,T,update_location!)
257+ uvMeshArrays (u0,u1,v0,v1,T,TA, update_location!)
179258end
180259
181260struct uvwMeshArrays{Ty} <: FlowFields
@@ -186,30 +265,32 @@ struct uvwMeshArrays{Ty} <: FlowFields
186265 w0:: AbstractMeshArray{Ty,2}
187266 w1:: AbstractMeshArray{Ty,2}
188267 T:: Union{Array{Ty},Array{DateTime}}
268+ TimeAxis:: AbstractTimeAxis
189269 update_location!:: Function
190270end
191271
192272function FlowFields (u0:: MeshArrays.MeshArray_wh ,u1:: MeshArrays.MeshArray_wh ,
193273 v0:: MeshArrays.MeshArray_wh ,v1:: MeshArrays.MeshArray_wh ,
194274 w0:: MeshArrays.MeshArray_wh ,w1:: MeshArrays.MeshArray_wh ,
195- T:: Union{Array,Tuple} ,update_location!:: Function )
275+ T:: Union{Array,Tuple} ,update_location!:: Function ; time_axis = missing )
196276
197- FlowFields (u0. MA,u1. MA,v0. MA,v1. MA,w0. MA,w1. MA,T,update_location!)
277+ FlowFields (u0. MA,u1. MA,v0. MA,v1. MA,w0. MA,w1. MA,T,update_location!,time_axis = time_axis )
198278end
199279
200280function FlowFields (u0:: AbstractMeshArray{Ty,2} ,u1:: AbstractMeshArray{Ty,2} ,
201281 v0:: AbstractMeshArray{Ty,2} ,v1:: AbstractMeshArray{Ty,2} ,
202282 w0:: AbstractMeshArray{Ty,2} ,w1:: AbstractMeshArray{Ty,2} ,
203- T:: Union{Array,Tuple} ,update_location!:: Function ) where Ty
283+ T:: Union{Array,Tuple} ,update_location!:: Function ; time_axis = missing ) where Ty
204284 # ensure T is a vector and enforce type
205285 T= time_set_type .(collect (T),Ty)
286+ TA= (ismissing (time_axis) ? TimeAxis (T... ) : time_axis)
206287 # check array size consistency
207288 tst= prod ([(size (u0)== size (tmp))* (u0. fSize== tmp. fSize) for tmp in (u1,v0,v1)])
208289 tst= tst* prod ([(size (u0)== size (tmp).- (0 ,1 ))* (u0. fSize== tmp. fSize) for tmp in (w0,w1)])
209290 ! tst ? error (" inconsistent array sizes" ) : nothing
210291
211292 # call constructor
212- uvwMeshArrays (u0,u1,v0,v1,w0,w1,T,update_location!)
293+ uvwMeshArrays (u0,u1,v0,v1,w0,w1,T,TA, update_location!)
213294end
214295
215296"""
@@ -230,7 +311,7 @@ function ensemble_solver(prob::ODEProblem;solver=Tsit5(),reltol=1e-8,abstol=1e-8
230311end
231312
232313a= fill (0.0 ,1 ,1 )
233- default_flowfields = uvArrays {Float64} (a,a,a,a,[0. 1. ])
314+ default_flowfields = uvArrays {Float64} (a,a,a,a,[0. 1. ], TimeAxis ( 0. , 1. ) )
234315default_recorder = DataFrame (ID= Int[], x= Float64[], y= Float64[], t= Float64[])
235316default_postproc = (x-> x)
236317
0 commit comments