ROW and Gauss-Legendre implicit method

ROW and Gauss-Legendre implicit method#

import numpy as np
import matplotlib.pyplot as plt

# Define a sample nonlinear system of ODEs for testing
def nonlinear_system(t, y):
    return np.array([y[1], -y[0] + 0.1 * y[0] * (1 - y[0]**2)])
def row2_step(f, t, y, h):
    """Performs a single integration step using ROW2 method."""
    # ROW2 Butcher coefficients
    a21 = 1 / (2 - np.sqrt(2))
    b1 = 1 / (2 - np.sqrt(2))
    b2 = 1 - b1

    # Calculate intermediate steps
    k1 = f(t, y)
    k2 = f(t + h / (2 - np.sqrt(2)), y + h * a21 * k1)
    
    # Update solution
    y_next = y + h * (b1 * k1 + b2 * k2)
    return y_next
def gauss_legendre_step(f, t, y, h):
    """Performs a single integration step using the two-stage Gauss-Legendre method."""
    # Gauss-Legendre coefficients for 2-stage method
    c1 = 0.5 - np.sqrt(3) / 6
    c2 = 0.5 + np.sqrt(3) / 6
    a11 = 0.25
    a12 = 0.25 - np.sqrt(3) / 6
    a21 = 0.25 + np.sqrt(3) / 6
    a22 = 0.25
    b1 = 0.5
    b2 = 0.5

    # Initial guesses for k1 and k2
    k1 = f(t + c1 * h, y)
    k2 = f(t + c2 * h, y)
    
    # Fixed-point iteration (or nonlinear solver) would be used here for a real implicit method.
    for _ in range(5):  # Iterate to refine k1 and k2
        k1 = f(t + c1 * h, y + h * (a11 * k1 + a12 * k2))
        k2 = f(t + c2 * h, y + h * (a21 * k1 + a22 * k2))
    
    # Update solution
    y_next = y + h * (b1 * k1 + b2 * k2)
    return y_next
# Set initial condition, time step, and time range
y0 = [1.0, 0.0]  # Initial values
t0 = 0.0
tf = 20.0
h = 0.01
n_steps = int((tf - t0) / h)

# Prepare storage for results
t_values = [t0]
y_values_row2 = [y0]
y_values_gauss = [y0]

# Perform integration using ROW2 and Gauss-Legendre
y_row2 = np.array(y0)
y_gauss = np.array(y0)
t = t0

for _ in range(n_steps):
    y_row2 = row2_step(nonlinear_system, t, y_row2, h)
    y_gauss = gauss_legendre_step(nonlinear_system, t, y_gauss, h)
    
    t += h
    t_values.append(t)
    y_values_row2.append(y_row2)
    y_values_gauss.append(y_gauss)

# Convert results to arrays for plotting
t_values = np.array(t_values)
y_values_row2 = np.array(y_values_row2)
y_values_gauss = np.array(y_values_gauss)

# Plot the results
plt.figure(figsize=(10, 6))
plt.plot(t_values, y_values_row2[:, 0], label='ROW2 Method (y1)')
plt.plot(t_values, y_values_gauss[:, 0], label='Gauss-Legendre Method (y1)', linestyle='--')
plt.plot(t_values, y_values_row2[:, 1], label='ROW2 Method (y2)')
plt.plot(t_values, y_values_gauss[:, 1], label='Gauss-Legendre Method (y2)', linestyle='--')
plt.xlabel('Time')
plt.ylabel('Solution')
plt.title('Integration of Nonlinear System with ROW2 and Gauss-Legendre Methods')
plt.legend()
plt.show()
../_images/5bb47a383280dc6127ec7dcc6f19c916e6ebe82aa82b19e1faee59e94f4f8e4e.png