Ejemplo n.º 1
0
def adaptive_step_integration(method: OneStepMethod, func, y_start, t_span,
                              adapt_type: AdaptType,
                              atol, rtol):
    """
    performs adaptive-step integration using one-step method
    t_span: (t0, t1)
    adapt_type: Runge or Embedded
    tolerances control the error:
        err <= atol
        err <= |y| * rtol
    return: list of t's, list of y's
    """
    y = y_start
    t, t_end = t_span

    ts = [t]
    ys = [y]
    p = method.p

    delta = (1 / max(np.abs(t), np.abs(t_end))) ** (p + 1) + np.linalg.norm(func(t, y)) ** (p + 1)
    h1 = (atol / delta) ** (1 / (p + 1))
    yh = y + h1 * func(t, y)
    delta = (1 / max(np.abs(t), np.abs(t_end))) ** (p + 1) + np.linalg.norm(func(t + h1, yh)) ** (p + 1)
    h2 = (atol / delta) ** (1 / (p + 1))
    h = min(h1, h2)

    while t < t_end:
        t = ts[-1]
        y = ys[-1]
        h = min(t_end - t, h)

        if adapt_type == AdaptType.RUNGE:
            y1 = method.step(func, t, y, h)
            y2 = method.step(func, t + h / 2, method.step(func, t, y, h / 2), h / 2)
            error = (y2 - y1) / (1 - 2 ** (-p))
        else:
            y1, error = method.embedded_step(func, t, y, h)

        error = np.linalg.norm(error)
        tol = min(rtol * np.linalg.norm(y1), atol)

        if error > tol:
            h *= 0.5

        elif error < tol * 1 / 2 ** (p + 1):
            ts.append(t + h)
            ys.append(y1)
            h *= 2

        else:
            ts.append(t + h)
            ys.append(y1)

    return ts, ys
Ejemplo n.º 2
0
def adaptive_step_integration(method: OneStepMethod, func, y_start, t_span,
                              adapt_type: AdaptType, atol, rtol):
    """
    performs adaptive-step integration using one-step method
    t_span: (t0, t1)
    adapt_type: Runge or Embedded
    tolerances control the error:
        err <= atol
        err <= |y| * rtol
    return: list of t's, list of y's
    """
    y = y_start
    t, t_end = t_span

    ys = [y]
    ts = [t]

    p = method.p + 1
    tol = atol + np.linalg.norm(y) * rtol
    rside0 = func(t, y)
    delta = (1 / max(abs(t), abs(t_end)))**(p + 1) + np.linalg.norm(rside0)**(
        p + 1)
    h1 = (tol / delta)**(1 / (p + 1))
    u1 = ExplicitEulerMethod().step(func, t, y, h1)
    tnew = t + h1
    rside0 = func(tnew, u1)
    delta = (1 / max(abs(t), abs(t_end)))**(p + 1) + np.linalg.norm(rside0)**(
        p + 1)
    h1new = (tol / delta)**(1 / (p + 1))
    h = min(h1, h1new)
    while t < t_end:
        if t + h > t_end:
            h = t_end - t

        if adapt_type == AdaptType.RUNGE:
            y1 = method.step(func, t, y, h)
            yhalf = method.step(func, t, y, h / 2)
            y2 = method.step(func, t + h / 2, yhalf, h / 2)
            error = (y2 - y1) / (2**p - 1)
            ybetter = y2 + error
        else:
            ybetter, error = method.embedded_step(func, t, y, h)

        if np.linalg.norm(error) < tol:
            ys.append(ybetter)
            ts.append(t + h)
            y = ybetter
            t += h
            print(t)

        h *= (tol / np.linalg.norm(error))**(1 / (p + 1)) * 0.9
    return ts, ys
Ejemplo n.º 3
0
def fix_step_integration(method: OneStepMethod, func, y_start, ts):
    """
    performs fix-step integration using one-step method
    ts: array of timestamps
    return: list of t's, list of y's
    """
    ys = [y_start]

    for i, t in enumerate(ts[:-1]):
        y = ys[-1]

        y1 = method.step(func, t, y, ts[i + 1] - t)
        ys.append(y1)

    return ts, ys
Ejemplo n.º 4
0
def fix_step_integration(method: OneStepMethod, func, y_start, ts):
    """
    Выполняем интегрирование одношаговм метдом с фиксированным шагом
    ts: набор значений t
    returns: list of t, list of y
    """
    ys = [y_start]

    for i, t in enumerate(ts[:-1]):
        y = ys[-1]

        y1 = method.step(func, t, y, ts[i + 1] - t)
        ys.append(y1)

    return ts, ys
Ejemplo n.º 5
0
def adams(func, y_start, T, coeffs, one_step_method: OneStepMethod):
    """
    T: list of timestamps
    coeffs: list of coefficients
    one_step_method: method for initial steps
    return list of t (same as T), list of y
    """
    h = np.abs(T[1] - T[0])
    y = [y_start]
    rightside = [func(T[0], y_start)]
    for i in range(1, len(T)):
        if i < len(coeffs):
            y.append(one_step_method.step(func, T[i - 1], y[i - 1], h))
        else:
            y.append(y[i - 1] +
                     coeffs @ (h * np.array(rightside[-len(coeffs):])))
        rightside.append(func(T[i], y[i]))
    return T, y
Ejemplo n.º 6
0
def adams(func, y_start, T, coeffs, one_step_method: OneStepMethod):
    """
    T: list of timestamps
    coeffs: list of coefficients
    one_step_method: method for initial steps
    return list of t (same as T), list of y
    """
    n = len(T)
    h = np.abs(T[1] - T[0])
    k = len(coeffs)
    y = [y_start]
    for i in range(1, k):
        y.append(one_step_method.step(func, T[i - 1], y[i - 1], h))
    q = [h * func(T[i], y[i]) for i in range(k)]
    for m in range(k, n):
        y.append(y[m - 1] + np.dot(coeffs, q[m - k:m]))
        q.append(h * func(T[m], y[m]))
    return T, y
Ejemplo n.º 7
0
def fix_step_integration(method: OneStepMethod, ode: ODE, y_start, ts):
    """
    Интегрирование одношаговым методом с фиксированным шагом

    :param method:  одношаговый метод
    :param ode:     СОДУ
    :param y_start: начальное значение
    :param ts:      набор значений t
    :return:        список значений t (совпадает с ts), список значений y
    """
    ys = [y_start]

    for i, t in enumerate(ts[:-1]):
        y = ys[-1]

        y1 = method.step(ode, t, y, ts[i + 1] - t)
        ys.append(y1)

    return ts, ys