|
|
@@ -76,16 +76,11 @@ class StateEventLocator:
|
|
|
|
|
|
return self.detect(prev, curr, direction)
|
|
|
|
|
|
- def _function(self, output_name, time, level=0.0):
|
|
|
+ def _function(self, output_name, time, level=0.0, noop=True):
|
|
|
"""
|
|
|
The internal function. Whenever an algorithm requires the computation of the
|
|
|
CBD model at another time, this function can be executed.
|
|
|
|
|
|
- Note:
|
|
|
- The CBD will remain at the computed time afterwards. Use
|
|
|
- :meth:`CBD.simulator._rewind` to undo the actions of this
|
|
|
- function.
|
|
|
-
|
|
|
Args:
|
|
|
output_name (str): The output port name for which the crossing point must
|
|
|
be computed.
|
|
|
@@ -96,6 +91,8 @@ class StateEventLocator:
|
|
|
are basically root finders. If the algorithm incorporates
|
|
|
the level itself, keep this value at 0 for correct behaviour.
|
|
|
Defaults to 0.
|
|
|
+ noop (bool): When :code:`True`, this function will be a no-op. Otherwise,
|
|
|
+ the model will remain at the given time.
|
|
|
|
|
|
Returns:
|
|
|
The signal value of the output at the given time, shifted towards 0.
|
|
|
@@ -103,10 +100,19 @@ class StateEventLocator:
|
|
|
if callable(output_name):
|
|
|
return output_name(time) - level
|
|
|
assert time >= self.t_lower
|
|
|
+
|
|
|
+ h = self.sim.model.getClock().getDeltaT()
|
|
|
self.sim._rewind()
|
|
|
self.setDeltaT(time - self.t_lower)
|
|
|
self.sim._lcc_compute()
|
|
|
- return self.sim.model.getSignal(output_name)[-1].value - level
|
|
|
+ s = self.sim.model.getSignal(output_name)[-1].value - level
|
|
|
+
|
|
|
+ if noop:
|
|
|
+ self.sim._rewind()
|
|
|
+ self.setDeltaT(h)
|
|
|
+ if noop:
|
|
|
+ self.sim._lcc_compute()
|
|
|
+ return s
|
|
|
|
|
|
def setDeltaT(self, dt):
|
|
|
"""
|
|
|
@@ -133,16 +139,16 @@ class StateEventLocator:
|
|
|
Returns:
|
|
|
The detected time at which the crossing is suspected to occur.
|
|
|
"""
|
|
|
- h = self.sim.model.getClock().getDeltaT()
|
|
|
|
|
|
sig = self.sim.model.getSignal(output_name)
|
|
|
p1 = sig[-2].time, sig[-2].value - level
|
|
|
p2 = sig[-1].time, sig[-1].value - level
|
|
|
self.t_lower = p1[0]
|
|
|
+
|
|
|
+ # begin the algorithm on the left
|
|
|
+ self.sim._rewind()
|
|
|
t_crossing = self.algorithm(p1, p2, output_name, level, direction)
|
|
|
|
|
|
- # Reset time-delta after crossing
|
|
|
- self.setDeltaT(h)
|
|
|
return t_crossing
|
|
|
|
|
|
def algorithm(self, p1, p2, output_name, level=0.0, direction=Direction.ANY):
|
|
|
@@ -238,7 +244,7 @@ class BisectionStateEventLocator(StateEventLocator):
|
|
|
def algorithm(self, p1, p2, output_name, level=0.0, direction=Direction.ANY):
|
|
|
tc = p1[0]
|
|
|
for i in range(self.n):
|
|
|
- tc = (p1[0] + p2[0]) / 2
|
|
|
+ tc = ((p2[0] - p1[0]) / 2) + p1[0]
|
|
|
yc = self._function(output_name, tc, level)
|
|
|
|
|
|
if self.detect(p1[1], yc, direction):
|