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