crossing

# crossing.py
# ------------------------------------------------------------------------------

 
Classes
       
Crossing

 
class Crossing()
    Class inspired by the GASP IV combined simulation package and intended 
for handling external and internal state-events as well as scheduled and 
unscheduled time-events. It is used the following way (an example):
 
    crossing1 = Crossing(diffunc, mode, t0)
 
where diffunc is a callable function having the time as its argument and 
representing a crossing condition indicated by its changing its sign. This 
may be used to control the flow of computation in combined discrete-dynamic
/continuous simulations.
 
'mode' is the crossing mode related to the search for a crossing point and 
it may be either 'pos' for diffunc going from negative to positive, 'neg' 
for positive to negative, or 'any' that covers both. t0 is the initial
/starting time point.
 
Events that change the course of a simulation may be handled using the 
'crossed' method to look for a crossing point between the present time 
and the next proposed time point in the simulation:
 
    u = crossing1.crossed(t, tnext)
    if not u:
        # No action
    else:
        tcrosslo, tcross, tcrosshi = u
        # Some action depending...
        resetXing(<newmode>)  # Optional (and the "< >" indicates 
                              # that newmode is optional)
 
If no crossing takes place in [t, tnext] then False is returned.
 
If a crossing takes place in [t, tnext] then a three-element tuple is 
returned: tcrosslo, tcross, tcrosshi - i. e. the "best estimate" as to 
the crossing time (the estimate of the root of diffunc = 0.0), surrounded 
by tcross-eps and tcross+eps where eps is the estimated error around the 
root, given the tolerances input to the instance object at initiation.
 
The estimates returned may for instance be used to "tiptoe" very close to 
a crossing and then start over with the overlying computations with new 
circumstances from a time point from where a crossing is certain to have 
taken place. This may include preventing ODE solvers from trying to step 
over discontinuities, triggering discrete events, initiating new objects 
etc. etc.
 
NB. If mode == 'pos' and diffunc > 0.0 at initiation or if mode == 'neg' 
and diffunc < 0.0 at initiation, then crossing is assumed to have taken 
place already and no crossings will be registered. A warning will however 
be issued at initiation.
 
  Methods defined here:
__init__(self, diffunc, mode, t0, solver=zbisect, tolf=8.8817841970012523e-16, tola=1.221338669755462e-77, maxniter=128)
Used to initiate the instance object.
 
The optional input arguments other than diffunc, the crossing mode 
related to the search for a crossing point with the 'crossed' method, 
and the initial time point, are:
 
solver    Solver for finding the zero - based on an initial guess as to 
          a span. zbrent and zbisect are the ones presently available,
 
tolf      Desired fractional accuracy of time point at crossing (a 
          combination of fractional and absolute is actually used: 
          tolf*abs(tcross) + tola),
 
tola      Desired absolute accuracy of time point at crossing (a 
          combination of fractional and absolute is actually used: 
          tolf*abs(tcross) + tola),
 
maxniter  Maximum number of iterations in the search for crossing points
 
(how to control the iterations using tolf, tola and maxniter to reach 
a zero is described in more detail in the solveq module).
crossed(self, t, tnext)
The method used for actually finding a (possible) crossing point between
the present time t and proposed/scheduled next time point tnext. It does
not require that the present time point be the tnext of the previous 
step - it is possible to let t > previous tnext (by a small amount, 
naturally) to allow for "tiptoeing" around discontinuities. It is also 
possible to let t < previous tnext (by a small amount) in order to come 
as close as possible to a discontinuity before passing it. 
 
NB1. mode = 'any' allows for multiple crossings, whereas 'pos' and 
'neg' allows for one crossing only - possible future crossings are not 
registered for 'pos' and 'neg'. 
        
NB2. A warning will be issued if the solver fails to converge for the 
tolerances and maximum number of iterations input at the initiation of 
the instance object, but a result is always returned.
 
NB3. tcrosslo will always be output >=t and tcrosshi will always be 
output <= tnext.
reset_xing(self, newmode=False)
May be used to reset an instance object so that it will register 
crossings again. The mode can also be changed (using 'pos', 'neg' 
or 'any' for newmode).

Data descriptors defined here:
__dict__
dictionary for instance variables (if defined)
__weakref__
list of weak references to the object (if defined)

 
Functions
       
sqrt(...)
sqrt(x)
 
Return the square root of x.

 
Data
        FOURMACHEPS = 8.8817841970012523e-16
SQRTTINY = 1.221338669755462e-77