Skip to content

Commit f021b84

Browse files
fixup! docs: update documentation with new parameter indexing API and semantics
1 parent 25fe115 commit f021b84

File tree

2 files changed

+34
-34
lines changed

2 files changed

+34
-34
lines changed

docs/src/api.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,12 +80,14 @@ If a solution object saves a timeseries of parameter values that are updated dur
8080
simulation (such as by callbacks), it must implement the following methods to ensure
8181
correct functioning of [`getu`](@ref) and [`getp`](@ref).
8282

83+
Parameter timeseries support requires that the value provider store the different
84+
timeseries in a [`ParameterTimeseriesCollection`](@ref).
85+
8386
```@docs
8487
is_parameter_timeseries
85-
parameter_timeseries
86-
parameter_values_at_time
87-
parameter_values_at_state_time
88-
parameter_timeseries_at_state_time
88+
get_parameter_timeseries_collection
89+
ParameterTimeseriesCollection
90+
with_updated_parameter_timeseries_values
8991
```
9092

9193
### Batched Queries and Updates
@@ -118,5 +120,4 @@ symbolic_evaluate
118120
```@docs
119121
SymbolCache
120122
ProblemState
121-
ParameterTimeseriesCollection
122123
```

docs/src/complete_sii.md

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -324,12 +324,28 @@ correct implementation of these functions and the indexing syntax they enable.
324324
```@example param_timeseries
325325
using SymbolicIndexingInterface
326326
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+
327344
struct ExampleSolution2
328345
sys::SymbolCache
329346
u::Vector{Vector{Float64}}
330347
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
333349
p_ts::ParameterTimeseriesCollection
334350
end
335351
@@ -344,30 +360,7 @@ SymbolicIndexingInterface.state_values(fs::ExampleSolution2) = fs.u
344360
SymbolicIndexingInterface.current_time(fs::ExampleSolution2) = fs.t
345361
# By default, `parameter_values` refers to the last value
346362
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
371364
# Mark the object as a timeseries object
372365
SymbolicIndexingInterface.is_timeseries(::Type{ExampleSolution2}) = Timeseries()
373366
# Mark the object as a parameter timeseries object
@@ -391,7 +384,9 @@ SymbolicIndexingInterface.state_values(a::MyDiffEqArray) = a.u
391384
```
392385

393386
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.
395390

396391
```@example param_timeseries
397392
sys = SymbolCache(
@@ -412,12 +407,16 @@ d_timeseries = MyDiffEqArray(
412407
collect(0.0:0.2:1.0),
413408
[[0.17i] for i in 1:6]
414409
)
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+
)
415415
sol = ExampleSolution2(
416416
sys,
417417
[i * ones(3) for i in 1:5], # u
418418
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,
421420
ParameterTimeseriesCollection([b_c_timeseries, d_timeseries]) # p_ts
422421
)
423422
sol.ps[:a] # returns the value of non-timeseries parameter

0 commit comments

Comments
 (0)