Source code for irfpy.asperacommon.domain_common
import logging as _logging
[docs]def bisect_boundary_crossing(t0, t1, inside_function, tolerance=0.1):
""" A function that returns the boundary crossing time.
.. todo::
This function may go to irfpy.util
:param t0: Time to start to examine.
:param t1: Time to stop to examine.
:param inside_function: A function that receive a single time, returning the boolean.
Examples are :func:`inside_icb` or :func:`inside_bowshock`.
:keyword tolerance: Tolerance in seconds.
:return: The boundary crossing time.
The crossing time in between ``t0`` and ``t1`` is returned.
1. ``inside_function(t0)`` and ``inside_function(t1)`` should not be the same value.
2. Boundary crossing between t0 and t1 should be once. If multiple crossings exist,
only a single crossing is returned, and we do not know which crossing is the returned.
"""
logger = _logging.getLogger(__name__)
c0 = inside_function(t0)
c1 = inside_function(t1)
dt = (t1 - t0).total_seconds()
if c0 is c1: # If the same condition
raise RuntimeError('The domain at t0 and t1 must differ.\n' +
' t0={}, domain={}\n'.format(t0, c0) +
' t1={}, domain={}\n'.format(t1, c1))
while dt >= tolerance:
tc = t0 + (t1 - t0) / 2 # Central time
cc = inside_function(tc) # Central domain
logger.debug('T0={}: {}'.format(t0, c0))
logger.debug('TC={}: {}'.format(tc, cc))
logger.debug('T1={}: {}'.format(t1, c1))
logger.debug('DT={}'.format(dt))
if c0 is cc: # Centeral domain is the same as outside
t0 = tc
c0 = cc
logger.debug('T0 is now {}'.format(t0))
else:
t1 = tc
c1 = cc
logger.debug('T1 is now {}'.format(t1))
dt = (t1 - t0).total_seconds()
# return tc
return t0 + (t1 - t0) / 2 # Maybe better