-
Notifications
You must be signed in to change notification settings - Fork 4
RateSystem #117
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
RateSystem #117
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for working on this!
I very much like the idea of starting with the general mathematical formulation \dot x = f(x(t), lambda(t))
, and have made a suggestion of how this could be reflected more in the way a user would define a RateSystem
.
One thing I am unsure about is whether we just need a constructor function RateSystem
that returns either a CoupledODEs
or CoupledSDEs
, or whether we need an additional type in order to pass the necessary information about the rate system to the methods we want to add.
Maybe we can brainstorm the methods we would like to add here and think about whether they work with a CoupledODEs
or whether we need more.
src/RateSys.jl
Outdated
# t_i autonomous t_ni non-autonomous t_nf autonomous t_f | ||
# | | | | | ||
|
||
using DynamicalSystems |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be sufficient to use DynamicalSystemsBase
.
src/RateSys.jl
Outdated
|
||
# we write | ||
|
||
function RateSyst(tni,tnf,f,λ,p_λ,initvals) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In my opinion, these are quite many positional arguments, which makes it less user-friendly. What do you think of reorganising this in the following structure:
RateSystem(ds::ContinuousTimeDynamicalSystem, rate_protocol::function)
where ds
can be a CoupledODEs
or a CoupledSDEs
and rate_protocol
is your λ
function that determines how the parameters change over time. This function could have the structure
rate_protocol(u, p_lambda, t; t_start=0.0, t_end=Inf, kwargs...)
i.e. it would contain all the input arguments needed to define the rate forcing function. Behind the scenes, this would then create and return a new CoupledODEs
or CoupledSDEs
with the explicit time dependence specified by rate_protocol
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The naming here is just a suggestion, but generally I think we should give more descriptive names than just lambda
or tnf
(clarity over brevity!)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This sounds great, thanks Reyk! However, rate_protocol should not depend on u, in my opinion.
Hey, what's the status on this @raphael-roemer @ryandeeley ? |
Hello, Raphael and I met again last week to pick this up again. We agree that it would be nice to pass some used-defined
We are proposing that As I've written it, the positional arguments of
The first two arguments are hopefully clear. The argument One keyword argument of Note that there are two non-user-level functions I tested this proposed I've attached a |
Hey @ryandeeley, thanks for the update! Could you push your proposed changes to this branch? This is what git is designed for, and pushing here will automatically run the tests. (The idea is that this draft pull request is continuously developed until we are happy to merge it with the main branch) |
Yes, we can do that, although I only wrote this yesterday and haven't explicitly discussed it with Raphael yet, who is also drafting some |
…l script, created a dev folder, updated src/CriticalTransitions.jl file.
…itions.jl file to be in line with that of the main branch.
Hi @raphael-roemer - I thought some more about this yesterday evening and I think I'm in a position to have a go at updating the |
So I've just pushed some changes to the Please let me know your thoughts on the I haven't yet altered any test files in correspondence with this yet, so that's still to do... |
src/r_tipping/RateSystem.jl
Outdated
- p_parameters: the vector of parameters which are associated with p | ||
- t_pstart: the parameter values of the past limit system are given by p(p_parameteters,t_pstart) | ||
- t_pend: the parameter values of the future limit system are given by p(p_parameters,t_pend) | ||
- t_start: the explicit value of time at which the nonautonomous dynamics starts |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, it seems redundant (and a bit confusing) to have all these different time inputs (t_pstart
, t_start
, ...). I am worried that we are making things too complicated.
To me, the most straight forward would be: you define a forcing function p(t)
and a tuple (p_start, p_end)
. For all t
, the parameters are then given by:
-
p(t_start)
for$t \leq t_{start}$ -
p(t)
for$t_{start} < t < t_{end}$ -
p(t_end)
for$t \geq t_{end}$
This ensures the forcing is continuous. Its derivative might not be, but okay. If you have a tanh forcing on [t_start, t_end]
and want the past and future limits to be closer to the 'true' limits of the tanh, just widen the interval [t_start, t_end]
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
P.S. I am thinking that one applies the scaling (dp
and rate
) to the forcing first and then evaluates the start and end values of that rescaled forcing function using the specified t_start
and t_end
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would disagree that it's redundant and will try to dispel any possible confusion. One needs p
, p_parameters
, t_pstart
and t_pend
to define a function with piecewise constant tail ends that the R-tipping experiments are taken with respect to (see p_piecewise_scaled
, here the dp
simply scales the difference in parameter values across [t_pstart,t_pend]
) . You need to fix a t_pstart
and t_pend
to fix the past and future limit systems. These have to be finite, because [t_pstart,t_pend]
is rescaled into the finite interval [t_start,t_start+t_ramp_length]
; this is the rescaling that was once associated with r
(stretching / squeezing). If as you propose one simply transforms a rescaled forcing function into a function with piecewise constant tail ends from fixed t = t_start
and t = t_end
each time, then this is going to change the past and future limit systems depending on the rescaling (and could do so drastically if you consider a very shallow rate
).
The parameter t_start
in the current RateConfig
struct is in my opinion unnecessary, since we could always fix t_start = -t_ramp_length/2
and have that the nonautonomous dynamics occurs in a symmetric window around t = 0
.
Note also that for this formulation, it is less useful to think about r
, and more useful to think about t_ramp_length
(because these notions are only equivalent when the function has piecewise constant tail ends). Note that with the exception of dp
, the code and system construction here is precisely the same as it was to before, except r
has been replaced with t_ramp_length
(thereby, restricting to cases where the time-dependent dynamics occurs over a finite time-interval, but since this is numerical, this restriction is not problematic).
Regarding the normalization of the forcing function: what is your solution for the case that My opinion is: it's not necessary to normalize. What is now called |
why are you not making |
In such cases no scaling is performed to those parameters - see the
I agree that the normalisation is specific here, and to reiterate it assumes monotonicity. The problem with simply scaling the whole function, i.e. via The way it works right now is admittedly a specific case but it captures the idea that Perhaps there is no simple universal and helpful interpretation of "scaling" the amplitude of the parameter functions, which I think has been part of the issue in unanimously understanding this so far... Maybe George's idea to leave the interpretation of the |
This is an option. I believe Raphael and I attempted to write this explicitly because it gives a clear interpretation of what function unscaled_ramping(p,t,dp,t_pstart,t_pend)
# p is a function of t and dp
if t<= t_pstart
return p(t_tpstart,dp)
elseif t < t_pend
return p(t,dp)
else
return p(t_pend,dp)
end
end This would then later gets stretched / squeezed from Note that we already have the Of course, the additional inclusion of |
Generally, I am finding this rather time-consuming and I think it would be more helpful to wrap this up and move on to writing more functionality for the |
In my experience the most difficult, most time consuming, and most important part of a scientific software is designing a good interface. So I think better get this one clean. Looking at the PR right now it isn't particularly clean, with some reduntant fields and documentation scattered throughout different functions. The functionality we discussed in the videocall is also missing, particularly the generic case of mapping parameter indices to time dependent functions |
I think we need one more video call; for me at least it is difficult to track the discussion here across different line-comments and different source code files. |
I'm not sure I understand this...
I'm not sure about the |
Exactly! |
#modifiedtruscottbrindleywithdimensions!, modifiedtruscottbrindleywithdimensions | ||
#originaltruscottbrindley!, originaltruscottbrindley | ||
#rampedoriginaltruscottbrindley!, rampedoriginaltruscottbrindley |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
these are commented out here, how come?
src/r_tipping/RateSystem.jl
Outdated
Fields | ||
============== | ||
|
||
- p: monotonic function which describes the time-dependent parametric forcing |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a function but what are the inputs and what are the outputs?
src/r_tipping/RateSystem.jl
Outdated
============== | ||
|
||
- p: monotonic function which describes the time-dependent parametric forcing | ||
- p_parameters: the vector of parameters which are associated with p |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why does this have to be a vector? what is this in general? still not convinced why it should exist.
src/r_tipping/RateSystem.jl
Outdated
- t_pstart = -100 | ||
- t_pend = 100 | ||
- p_parameters = [] | ||
- t_start = -t_ramp_length/2 | ||
- dp = 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think these defaults make sense. Unless there is a singular unambiguous value, like 0 for starting time, you should not have defaults and request the user to provide them.
p_parameters
should be nothing
by default as with the rest of DynamicalSYstems.jl
src/r_tipping/RateSystem.jl
Outdated
|
||
q̃ = q(time_shift) | ||
|
||
return dynamic_rule(ds)(u, q̃, t) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what do you do for in-place systems here?
src/r_tipping/RateSystem.jl
Outdated
|
||
time_shift = ((t_pend-t_pstart)/t_ramp_length)*(t-t_start)+t_pstart # such that [t_start,t_start+t_ramp_length] is shifted into [t_pstart,t_pend] | ||
|
||
q̃ = q(time_shift) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure what this is. But importantly, something happens you that you don't discolse in the documentation. The function p
the user provides must coincide with the parameter container of the original dynamical system. Is this really desirable?
We would like to add functionality for Rate dependent forcing functionality and easy system creation of non-autonomous systems