@@ -324,12 +324,28 @@ correct implementation of these functions and the indexing syntax they enable.
324
324
``` @example param_timeseries
325
325
using SymbolicIndexingInterface
326
326
327
+ # First, we must implement a parameter object that knows where the parameters in
328
+ # each parameter timeseries are stored
329
+ struct MyParameterObject
330
+ p::Vector{Float64}
331
+ disc_idxs::Vector{Vector{Int}}
332
+ end
333
+
334
+ # To be able to access parameter values
335
+ SymbolicIndexingInterface.parameter_values(mpo::MyParameterObject) = mpo.p
336
+ # Update the parameter object with new values
337
+ function SymbolicIndexingInterface.with_updated_parameter_timeseries_values(mpo::MyParameterObject, args::Pair...)
338
+ for (ts_idx, val) in args
339
+ mpo.p[mpo.disc_idxs[ts_idx]] = val
340
+ end
341
+ return mpo
342
+ end
343
+
327
344
struct ExampleSolution2
328
345
sys::SymbolCache
329
346
u::Vector{Vector{Float64}}
330
347
t::Vector{Float64}
331
- p::Vector{Float64} # the parameter object. Only some parameters are timeseries params
332
- p_idxs::Vector{Vector{Int}}
348
+ p::MyParameterObject # the parameter object. Only some parameters are timeseries params
333
349
p_ts::ParameterTimeseriesCollection
334
350
end
335
351
@@ -344,30 +360,7 @@ SymbolicIndexingInterface.state_values(fs::ExampleSolution2) = fs.u
344
360
SymbolicIndexingInterface.current_time(fs::ExampleSolution2) = fs.t
345
361
# By default, `parameter_values` refers to the last value
346
362
SymbolicIndexingInterface.parameter_values(fs::ExampleSolution2) = fs.p
347
- SymbolicIndexingInterface.parameter_values(fs::ExampleSolution2, i) = fs.p[i]
348
- function SymbolicIndexingInterface.parameter_values(fs::ExampleSolution2, i::ParameterTimeseriesIndex, j)
349
- return fs.p_ts[i, j]
350
- end
351
- # Index into the parameter timeseries vector
352
- function SymbolicIndexingInterface.parameter_values_at_time(fs::ExampleSolution2, t)
353
- newp = copy(fs.p)
354
- # iterating over `ParameterTimeseriesCollection` iterates over the contained timeseries
355
- # objects
356
- for (idxs, timeseries) in zip(fs.p_idxs, fs.p_ts)
357
- # find the index of the last point in time the parameter values were saved
358
- # before the requested time `t`
359
- index_in_timeseries = searchsortedlast(current_time(timeseries), t)
360
- # obtain the required values
361
- timeseries_values = state_values(timeseries, index_in_timeseries)
362
- # update parameter vector
363
- newp[idxs] = timeseries_values
364
- end
365
- return newp
366
- end
367
- function SymbolicIndexingInterface.parameter_timeseries(fs::ExampleSolution2, i)
368
- # `ParameterTimeseriesCollection` implements this for us
369
- return parameter_timeseries(fs.p_ts, i)
370
- end
363
+ SymbolicIndexingInterface.get_parameter_timeseries_collection(fs::FakeSolution) = fs.p_ts
371
364
# Mark the object as a timeseries object
372
365
SymbolicIndexingInterface.is_timeseries(::Type{ExampleSolution2}) = Timeseries()
373
366
# Mark the object as a parameter timeseries object
@@ -391,7 +384,9 @@ SymbolicIndexingInterface.state_values(a::MyDiffEqArray) = a.u
391
384
```
392
385
393
386
Now we can create an example object and observe the new functionality. Note that
394
- ` sol.ps[sym, args...] ` is identical to ` getp(sol, sym)(sol, args...) ` .
387
+ ` sol.ps[sym, args...] ` is identical to ` getp(sol, sym)(sol, args...) ` . In a real
388
+ application, the solution object will be populated during the solve process. We manually
389
+ construct the object here for demonstration.
395
390
396
391
``` @example param_timeseries
397
392
sys = SymbolCache(
@@ -412,12 +407,16 @@ d_timeseries = MyDiffEqArray(
412
407
collect(0.0:0.2:1.0),
413
408
[[0.17i] for i in 1:6]
414
409
)
410
+ p = MyParameterObject(
411
+ # parameter values at the final time
412
+ [4.2, b_c_timeseries.u[end]..., d_timeseries.u[end]...],
413
+ [[2, 3], 4]
414
+ )
415
415
sol = ExampleSolution2(
416
416
sys,
417
417
[i * ones(3) for i in 1:5], # u
418
418
collect(0.0:0.25:1.0), # t
419
- [4.2, b_c_timeseries.u[end]..., d_timeseries.u[end]...], # p must contain final values
420
- [[2, 3], 4], # p_idxs
419
+ p,
421
420
ParameterTimeseriesCollection([b_c_timeseries, d_timeseries]) # p_ts
422
421
)
423
422
sol.ps[:a] # returns the value of non-timeseries parameter
0 commit comments