Skip to content

Commit ca46720

Browse files
committed
change L to rateinterval
1 parent f513ec9 commit ca46720

File tree

2 files changed

+95
-47
lines changed

2 files changed

+95
-47
lines changed

src/SSA_stepper.jl

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
"""
22
$(TYPEDEF)
33
4-
Highly efficient integrator for pure jump problems that involve only
5-
`ConstantRateJump`s and/or `MassActionJump`s.
4+
Highly efficient integrator for pure jump problems that involve only `ConstantRateJump`s,
5+
`MassActionJump`s, and/or `VariableRateJump`s *with rate bounds*.
66
77
## Notes
8-
- Only works with `JumProblem`s defined from `DiscreteProblem`s.
9-
- Only works with collections of `ConstantRateJump`s, `VariableRateJump`s and `MassActionJump`s.
8+
- Only works with `JumpProblem`s defined from `DiscreteProblem`s.
9+
- Only works with collections of `ConstantRateJump`s, `MassActionJump`s, and
10+
`VariableRateJump`s with rate bounds.
1011
- Only supports `DiscreteCallback`s for events.
1112
1213
## Examples

src/jumps.jl

Lines changed: 90 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -33,51 +33,79 @@ end
3333
"""
3434
$(TYPEDEF)
3535
36-
Defines a jump process with a rate (i.e. hazard, intensity, or propensity) that
37-
may explicitly depend on time. More precisely, one where the rate function is
38-
allowed to change *between* the occurrence of jumps. For detailed examples and
39-
usage information see the
36+
Defines a jump process with a rate (i.e. hazard, intensity, or propensity) that may
37+
explicitly depend on time. More precisely, one where the rate function is allowed to change
38+
*between* the occurrence of jumps. For detailed examples and usage information see the
4039
- [Tutorial](https://docs.sciml.ai/JumpProcesses/stable/tutorials/discrete_stochastic_example/)
4140
41+
Note that two types of `VariableRateJump`s are currently supported, with different
42+
performance charactertistics.
43+
- A general `VariableRateJump` or `VariableRateJump` will refer to one in which only `rate`
44+
and `affect` functions are specified.
45+
46+
* These are the most general in what they can represent, but require the use of an
47+
`ODEProblem` or `SDEProblem` whose underlying timestepper handles their evolution in
48+
time (via the callback interface).
49+
* This is the least performant jump type in simulations.
50+
51+
- Bounded `VariableRateJump`s require passing the keyword arguments `urate` and
52+
`rateinterval`, corresponding to functions `urate(u, p, t)` and `rateinterval(u, p, t)`,
53+
see below. These must calculate a time window over which the rate function is bounded by a
54+
constant (as long as any components of the state on which the upper bound function depends
55+
do not change). One can also optionally provide a lower bound function, `lrate(u, p, t)`
56+
via the `lrate` keyword argument, that can lead to increased performance.
57+
58+
* Bounded `VariableRateJump`s can currently be used in the `Coevolve` aggregator, and
59+
can therefore be efficiently simulated in pure-jump `DiscreteProblem`s using the
60+
`SSAStepper` time-stepper.
61+
* These can be substantially more performant than general `VariableRateJump`s without
62+
the rate bound functions.
63+
64+
The additional user provided functions leveraged by bounded `VariableRateJumps`, `urate(u,
65+
p, t)`, `rateinterval(u, p, t)`, and the optional `lrate(u, p, t)` require that
66+
- For `s` in `[t, t + rateinterval(u, p, t)]`, we should have that `lrate(u, p, t) <=
67+
rate(u, p, s) <= urate(u, p, t)` provided any components of `u` on which these functions
68+
depend remain unchanged.
69+
4270
## Fields
4371
4472
$(FIELDS)
4573
4674
## Examples
47-
Suppose `u[1]` gives the amount of particles and `t*p[1]` the probability per
48-
time each particle can decay away. A corresponding `VariableRateJump` for this
49-
jump process is
75+
Suppose `u[1]` gives the amount of particles and `t*p[1]` the probability per time each
76+
particle can decay away. A corresponding `VariableRateJump` for this jump process is
5077
```julia
5178
rate(u,p,t) = t*p[1]*u[1]
5279
affect!(integrator) = integrator.u[1] -= 1
5380
vrj = VariableRateJump(rate, affect!)
5481
```
5582
56-
In case we want to use the `Coevolve` aggregator, we need to pass the rate
57-
boundaries and interval for which the rates apply. The `Coevolve` aggregator
58-
allow us to perform discrete steps with `SSAStepper()`.
83+
In case we want to use the `Coevolve` aggregator, we need to pass the rate boundaries and
84+
interval for which the rates apply. The `Coevolve` aggregator allow us to perform discrete
85+
steps with `SSAStepper()`.
5986
```julia
60-
L(u,p,t) = (1/p[1])*2
61-
rate(u,p,t) = t*p[1]*u[1]
87+
rateinterval(u,p,t) = (1 / p[1]) * 2
88+
rate(u,p,t) = t * p[1] * u[1]
6289
lrate(u, p, t) = rate(u, p, t)
63-
urate(u,p,t) = rate(u, p, t + L(u,p,t))
90+
urate(u,p,t) = rate(u, p, t + rateinterval(u,p,t))
6491
affect!(integrator) = integrator.u[1] -= 1
65-
vrj = VariableRateJump(rate, affect!; lrate=lrate, urate=urate, L=L)
92+
vrj = VariableRateJump(rate, affect!; lrate = lrate, urate = urate,
93+
rateinterval = rateinterval)
6694
```
6795
6896
## Notes
69-
- When using the `Coevolve` aggregator, `DiscreteProblem` can be used.
70-
Otherwise, `ODEProblem` or `SDEProblem` must be used to be correctly simulated.
71-
- **When not using the `Coevolve` aggregator, `VariableRateJump`s result in
72-
`integrator`s storing an effective state type that wraps the main state
73-
vector.** See [`ExtendedJumpArray`](@ref) for details on using this object. Note
74-
that the presence of *any* `VariableRateJump`s will result in all
75-
`ConstantRateJump`, `VariableRateJump` and callback `affect!` functions
76-
receiving an integrator with `integrator.u` an [`ExtendedJumpArray`](@ref).
77-
- Salis H., Kaznessis Y., Accurate hybrid stochastic simulation of a system of
78-
coupled chemical or biochemical reactions, Journal of Chemical Physics, 122
79-
(5), DOI:10.1063/1.1835951 is used for calculating jump times with
80-
`VariableRateJump`s within ODE/SDE integrators.
97+
- When using the `Coevolve` aggregator, `DiscreteProblem` can be used. Otherwise,
98+
`ODEProblem` or `SDEProblem` must be used to be correctly simulated.
99+
- **When not using the `Coevolve` aggregator, `VariableRateJump`s result in `integrator`s
100+
storing an effective state type that wraps the main state vector.** See
101+
[`ExtendedJumpArray`](@ref) for details on using this object. Note that the presence of
102+
*any* `VariableRateJump`s will result in all `ConstantRateJump`, `VariableRateJump` and
103+
callback `affect!` functions receiving an integrator with `integrator.u` an
104+
[`ExtendedJumpArray`](@ref).
105+
- Salis H., Kaznessis Y., Accurate hybrid stochastic simulation of a system of coupled
106+
chemical or biochemical reactions, Journal of Chemical Physics, 122 (5),
107+
DOI:10.1063/1.1835951 is used for calculating jump times with `VariableRateJump`s within
108+
ODE/SDE integrators.
81109
"""
82110
struct VariableRateJump{R, F, R2, R3, R4, I, T, T2} <: AbstractJump
83111
"""Function `rate(u,p,t)` that returns the jump's current rate given state
@@ -86,21 +114,29 @@ struct VariableRateJump{R, F, R2, R3, R4, I, T, T2} <: AbstractJump
86114
"""Function `affect!(integrator)` that updates the state for one occurrence
87115
of the jump given `integrator`."""
88116
affect!::F
89-
"""When planning to use the `Coevolve` aggregator, function `lrate(u, p,
90-
t)` that computes the lower bound of the rate in interval `t` to `t + L` at time
91-
`t` given state `u`, parameters `p`. This is not required if using another
92-
aggregator."""
117+
"""Optional function `lrate(u, p, t)` that computes a lower bound on the rate in the
118+
interval `t` to `t + rateinterval(u, p, t)` at time `t` given state `u` and parameters
119+
`p`. The bound should hold over this time interval as long as components of `u` for
120+
which the rate functions are dependent do not change. When using aggregators that
121+
support bounded `VariableRateJump`s, currently only `Coevolve`, providing a lower-bound
122+
can lead to improved performance.
123+
"""
93124
lrate::R2
94-
"""When planning to use the `Coevolve` aggregator, function `urate(u, p,
95-
t)` that computes the upper bound of the rate in interval `t` to `t + L` at time
96-
`t` given state `u`, parameters `p`. This is not required if using another
97-
aggregator."""
125+
"""Optional function `urate(u, p, t)` for general `VariableRateJump`s, but is required
126+
to define a bounded `VariableRateJump`, which can be used with supporting aggregators,
127+
currently only `Coevolve`, and offers improved computational performance. Computes an
128+
upper bound for the rate in the interval `t` to `t + rateinterval(u, p, t)` at time `t`
129+
given state `u` and parameters `p`. The bound should hold over this time interval as
130+
long as components of `u` for which the rate functions are dependent do not change. """
98131
urate::R3
99-
"""When planning to use the `Coevolve` aggregator, function `L(u, p,
100-
t)` that computes the interval length `L` starting at time `t` given state
101-
`u`, parameters `p` for which the rate is bounded between `lrate` and
102-
`urate`. This is not required if using another aggregator."""
103-
L::R4
132+
"""Optional function `rateinterval(u, p, t)` for general `VariableRateJump`s, but is
133+
required to define a bounded `VariableRateJump`, which can be used with supporting
134+
aggregators, currently only `Coevolve`, and offers improved computational performance.
135+
Computes the time interval from time `t` over which the `urate` and `lrate` bounds will
136+
hold, `t` to `t + rateinterval(u, p, t)`, given state `u` and parameters `p`. The bound
137+
should hold over this time interval as long as components of `u` for which the rate
138+
functions are dependent do not change. """
139+
rateinterval::R4
104140
idxs::I
105141
rootfind::Bool
106142
interp_points::Int
@@ -109,22 +145,33 @@ struct VariableRateJump{R, F, R2, R3, R4, I, T, T2} <: AbstractJump
109145
reltol::T2
110146
end
111147

148+
"""
149+
```
150+
function VariableRateJump(rate, affect!; lrate = nothing, urate = nothing,
151+
rateinterval = nothing, rootfind = true,
152+
idxs = nothing,
153+
save_positions = (false, true),
154+
interp_points = 10,
155+
abstol = 1e-12, reltol = 0)
156+
```
157+
"""
112158
function VariableRateJump(rate, affect!;
113159
lrate = nothing, urate = nothing,
114-
L = nothing, rootfind = true,
160+
rateinterval = nothing, rootfind = true,
115161
idxs = nothing,
116162
save_positions = (false, true),
117163
interp_points = 10,
118164
abstol = 1e-12, reltol = 0)
119-
if !(urate !== nothing && L !== nothing) && !(urate === nothing && L === nothing)
120-
error("Either `urate` and `L` must be nothing, or both of them must be defined.")
165+
if !(urate !== nothing && rateinterval !== nothing) &&
166+
!(urate === nothing && rateinterval === nothing)
167+
error("`urate` and `rateinterval` must both be `nothing`, or must both be defined.")
121168
end
122169

123170
if (urate !== nothing && lrate === nothing)
124171
lrate = (u, p, t) -> zero(typeof(t))
125172
end
126173

127-
VariableRateJump(rate, affect!, lrate, urate, L, idxs, rootfind,
174+
VariableRateJump(rate, affect!, lrate, urate, rateinterval, idxs, rootfind,
128175
interp_points, save_positions, abstol, reltol)
129176
end
130177

0 commit comments

Comments
 (0)