Ejemplo n.º 1
0
    def __init__(self, fun, t0, y0, t_bound, max_step=np.inf, rtol=1e-3,
                 atol=1e-6, vectorized=False, first_step=None,
                 const_jac=False, rho_jac=None, **extraneous):
        warn_extraneous(extraneous)
        super(SSV2stab, self).__init__(
            fun, t0, y0, t_bound, vectorized, support_complex=False)
        if first_step is None:
            self.absh = None
        else:
            self.absh = validate_first_step(first_step, t0, t_bound)
        self.hold = None
        if not isinstance(const_jac, bool):
            raise TypeError('`const_jac` should be True or False')
        if rho_jac is not None:
            if not callable(rho_jac):
                raise TypeError(
                    '`rho_jac` should be None or a function: '
                    '`sprad = rho_jac(t, y)`')
            elif not isinstance(rho_jac(self.t, self.y), float):
                raise TypeError('`rho_jac` should return a float')
            elif rho_jac(self.t, self.y) <= 0:
                raise ValueError('`rho_jac` should return a positive float')
        self.const_jac = const_jac
        self.rho_jac = rho_jac
        self.max_step = validate_max_step(max_step)
        self.rtol, self.atol = validate_tol(rtol, atol, self.y)
        self.uround = np.nextafter(np.finfo(self.y.dtype).epsneg, 1)
        self.sqrtu = sqrt(self.uround)
        self.sqrtmin = sqrt(np.finfo(self.y.dtype).tiny)
        self.W = np.empty((4, self.n), self.y.dtype)
        self.V = None       # eigenvector for spectral radius estimation. It
        #                     was WORK(5) in Fortran. Init in self._rho().

        # reset counters
        nrejct[()] = 0
        nfesig[()] = 0
        maxm[()] = 0
        self.nstsig = 0
        self.mlim = 0                            # added, for stiffness warning

        # Initialize on the first call.
        mmax = int(round(sqrt(self.rtol/(10.0 * self.uround))))
        self.mmax = max(mmax, 2)
        self.newspc = True
        self.jacatt = False
        self.W[0] = self.y
        self.W[1] = self.fun(self.t, self.y)                         # evaluate
        max_step = min(self.max_step, abs(self.t_bound - self.t))
        self.max_step = min(max_step, sqrt(np.finfo(self.y.dtype).max))
        hmin = abs(self.t)
        if self.t_bound != np.inf:
            hmin = max(hmin, abs(self.max_step))
        self.hmin = max(self.sqrtmin, 10.0 * self.uround * hmin)
Ejemplo n.º 2
0
    def __init__(self,
                 fun,
                 t0,
                 y0,
                 t_bound,
                 max_step=np.inf,
                 rtol=1e-3,
                 atol=1e-6,
                 vectorized=False,
                 first_step=None,
                 nfev_stiff_detect=5000,
                 sc_params=None,
                 **extraneous):
        warn_extraneous(extraneous)
        super(RungeKutta, self).__init__(fun,
                                         t0,
                                         y0,
                                         t_bound,
                                         vectorized,
                                         support_complex=True)
        self.max_step = validate_max_step(max_step)
        self.rtol, self.atol = validate_tol(rtol, atol, self.y)
        self.f = self.fun(self.t, self.y)
        if self.f.dtype != self.y.dtype:
            raise TypeError('dtypes of solution and derivative do not match')
        self.error_exponent = -1 / (self.error_estimator_order + 1)
        self._init_stiffness_detection(nfev_stiff_detect)
        self.h_min_a, self.h_min_b = self._init_min_step_parameters()
        self._init_sc_control(sc_params)

        # size of first step:
        if first_step is None:
            b = self.t + self.direction * min(abs(self.t_bound - self.t),
                                              self.max_step)
            self.h_abs = abs(
                h_start(self.fun, self.t, b, self.y, self.f,
                        self.error_estimator_order, self.rtol, self.atol))
        else:
            self.h_abs = validate_first_step(first_step, t0, t_bound)

        self.K = np.empty((self.n_stages + 1, self.n), self.y.dtype)
        self.FSAL = 1 if self.E[self.n_stages] else 0
        self.h_previous = None
        self.y_old = None
        NFS[()] = 0  # global failed step counter
Ejemplo n.º 3
0
 def __init__(self, fun, t0, y0, t_bound, max_step=np.inf,
              rtol=1e-3, atol=1e-6, min_step=0, vectorized=False,
              first_step=None, **extraneous):
     warn_extraneous(extraneous)
     super(RungeKutta, self).__init__(fun, t0, y0, t_bound, vectorized,
                                      support_complex=True)
     self.min_step_user = min_step
     self.y_old = None
     self.max_step = validate_max_step(max_step)
     self.rtol, self.atol = validate_tol(rtol, atol, self.n)
     self.f = self.fun(self.t, self.y)
     if first_step is None:
         self.h_abs = select_initial_step(
             self.fun, self.t, self.y, self.f, self.direction,
             self.order, self.rtol, self.atol)
     else:
         self.h_abs = validate_first_step(first_step, t0, t_bound)
     self.K = np.empty((self.n_stages + 1, self.n), dtype=self.y.dtype)
Ejemplo n.º 4
0
    def __init__(self, fun, t0, y0, t_bound, max_step=np.inf, rtol=1e-3,
                 atol=1e-6, vectorized=False, first_step=None, k_max=12,
                 **extraneous):
        if not (isinstance(k_max, int) and k_max > 0 and k_max < 13):
            raise ValueError("`k_max` should be an integer between 1 and 12.")
        warn_extraneous(extraneous)
        super(SWAG, self).__init__(
            fun, t0, y0, t_bound, vectorized, support_complex=True)
        self.max_step = validate_max_step(max_step)
        self.rtol, self.atol = validate_tol(rtol, atol, self.y)

        # starting step size
        self.yp = self.fun(self.t, self.y)                 # initial evaluation
        if first_step is None:
            b = self.t + copysign(min(abs(self.t_bound - self.t),
                                      self.max_step), self.direction)
            self.h = h_start(self.fun, self.t, b, self.y, self.yp,
                             1, self.rtol, self.atol)
        else:
            h_abs = validate_first_step(first_step, t0, t_bound)
            self.h = copysign(h_abs, self.direction)

        # constants
        small = np.nextafter(np.finfo(self.y.dtype).epsneg, 1)
        self.twou = 2.0 * small
        self.fouru = 4.0 * small
        self.two = (2.0, 4.0, 8.0, 16.0, 32.0, 64.0, 128.0, 256.0, 512.0,
                    1024.0, 2048.0, 4096.0, 8192.0)
        self.gstr = (0.5, 0.0833, 0.0417, 0.0264, 0.0188, 0.0143, 0.0114,
                     0.00936, 0.00789, 0.00679, 0.00592, 0.00524, 0.00468)
        iq = np.arange(1, k_max + 2)
        self.iqq = 1.0 / (iq * (iq + 1))                                # added
        self.k_max = k_max                                              # added
        self.eps = 1.0                                       # tolerances in wt
        self.p5eps = 0.5                                     # tolerances in wt

        # allocate arrays
        self.phi = np.empty((self.n, k_max + 2), self.y.dtype, 'F')
        self.psi = np.empty(k_max)
        self.alpha = np.empty(k_max)
        self.beta = np.empty(k_max)
        self.sig = np.empty(k_max + 1)
        self.v = np.empty(k_max)
        self.w = np.empty(k_max)
        self.g = np.empty(k_max + 1)
        self.gi = np.empty(k_max - 1)
        self.iv = np.zeros(max(0, k_max - 2), np.short)

        # Tolerances are dealt with like in scipy: wt is like scipy's scale
        # and will be update each step.  This is only the initial value:
        self.wt = self.atol + self.rtol * 0.5*(
            np.abs(self.y) + np.abs(self.y - self.h*self.yp))

        # initialization
        # from  *** block 0 ***  of dsteps.f, under IF START:
        _round = 0.0
        if self.y.size:                            # to pass scipy's unit tests
            _round = self.twou * norm(self.y / self.wt)
        if self.p5eps < 100.0 * _round:
            # The compensated summation of the original code that would be
            # executed if nornd == False has been removed.  Instead, this
            # warning is given to the user.
            warn("Numerical rounding may limit the accuracy "
                 "at this tolerance.")
        self.phi[:, 0] = self.yp
        self.phi[:, 1] = 0.0
        self.sig[0] = 1.0
        self.g[0] = 1.0
        self.g[1] = 0.5
        self.hold = 0.0
        self.k = 1
        self.kold = 0
        self.kprev = 0
        self.phase1 = True
        self.ivc = 0
        self.kgi = 0
        self.ns = 0

        # from ddes.f, for stiffness detection
        self.kle4 = 0
Ejemplo n.º 5
0
    def __init__(self,
                 fun,
                 t0,
                 y0,
                 t_bound,
                 max_step=np.inf,
                 rtol=1e-3,
                 atol=1e-6,
                 jac=None,
                 jac_sparsity=None,
                 vectorized=False,
                 first_step=None,
                 mass=None,
                 bPrint=False,
                 newton_tol=None,
                 constant_dt=False,
                 bPrintProgress=False,
                 **extraneous):
        warn_extraneous(extraneous)
        super(RadauDAE, self).__init__(fun, t0, y0, t_bound, vectorized)
        self.y_old = None
        self.max_step = validate_max_step(max_step)
        self.rtol, self.atol = validate_tol(rtol, atol, self.n)
        self.f = self.fun(self.t, self.y)
        # Select initial step assuming the same order which is used to control
        # the error.
        if first_step is None:
            self.h_abs = select_initial_step(self.fun, self.t, self.y, self.f,
                                             self.direction, 3, self.rtol,
                                             self.atol)
        else:
            self.h_abs = validate_first_step(first_step, t0, t_bound)
        self.h_abs_old = None
        self.error_norm_old = None

        if newton_tol is None:
            self.newton_tol = max(10 * EPS / rtol, min(0.03, rtol**0.5))
        else:
            self.newton_tol = newton_tol
        self.sol = None
        self.constant_dt = constant_dt

        self.jac_factor = None
        self.jac, self.J = self._validate_jac(jac, jac_sparsity)

        self.nlusove = 0

        self.bPrintProgress = bPrintProgress
        global BPRINT
        BPRINT = bPrint
        if BPRINT:
            zzzjac = self.jac

            def debugJacprint(t, y, f):
                print('\tupdating jacobian')
                return zzzjac(t, y, f)

            self.jac = debugJacprint

        if issparse(self.J):

            def lu(A):
                self.nlu += 1
                return splu(A)

            def solve_lu(LU, b):
                self.nlusove += 1
                return LU.solve(b)

            I = eye(self.n, format='csc')
        else:

            def lu(A):
                self.nlu += 1
                return lu_factor(A, overwrite_a=True)

            def solve_lu(LU, b):
                self.nlusove += 1
                return lu_solve(LU, b, overwrite_b=True)

            I = np.identity(self.n)

        self.lu = lu
        self.solve_lu = solve_lu
        self.I = I

        if not (mass is None):
            if issparse(mass):
                self.mass_matrix = csc_matrix(mass)
                self.index_algebraic_vars = np.where(
                    np.all(self.mass_matrix.toarray() == 0,
                           axis=1))[0]  # TODO: avoid the toarray()
            else:
                self.mass_matrix = mass
                self.index_algebraic_vars = np.where(
                    np.all(self.mass_matrix == 0, axis=1))[0]
            self.nvars_algebraic = self.index_algebraic_vars.size
        else:
            self.mass_matrix = None
            self.index_algebraic_vars = None
            self.nvars_algebraic = 0

        self.current_jac = True
        self.LU_real = None
        self.LU_complex = None
        self.Z = None

        self.info = {
            'cond': {
                'LU_real': [],
                'LU_complex': [],
                't': [],
                'h': []
            }
        }