SymPy

Implementing the Galerkin Method for solving differential equations

Note

This material was taken from a presentation of the Technical University Bochum, from Yijian Zhan and Ning Ma

Consider the following differential equation:

D(y(x)) = y''(x) + y(x) + 2x(1-x) = 0

with boundary conditions:

y(0) = 0
\\
y(1) = 0

One can choose the approximation functions that will cope with the boundary conditions:

y(x) \approx \phi_0(x) + \sum_i^n{c_i \phi_i (x)}

In the Galerkin approach the following integral is solved:

\int_a^b \phi_i[D(u)]dx = 0
\\
\int_a^b \phi_i(x) D[\phi_0(x) + \sum_j^n{c_j\phi_j(x)}]dx = 0

Since the current differential equation can be written as:

D_{left} = D_{right}
\\
D_{left} = y''(x) + y(x)
\\
D_{right} = -2x(1-x)

The Galerkin’n integral may be rearranged as:

\int_a^b \phi_i[D_{left}(u)]dx = \int_a^b \phi_i[D_{right}(u)]dx

which, when substituting the approximations, will result in the following system of equations:

A_{ij} c_j = B{i}

Using the following approximation function:

y(x) \approx 0 + \sum_i^n{c_i x^i (x-1)^i}

the following Python code can be used:

import numpy as np
import sympy
from sympy.abc import y, x
import matplotlib.pyplot as plt

c = sympy.var('c1, c2, c3')

A = np.zeros((len(c), len(c)))
B = np.zeros(len(c))
for i in range(len(c)):
    weights = x**(i+1)*(x-1)**(i+1)
    b = -2*x*(1-x)
    B[i] = sympy.integrate(weights*b, [x, 0, 1]).simplify()
    for j in range(len(c)):
        y = x**(j+1)*(x-1)**(j+1)
        yx = y.diff(x)
        yxx = yx.diff(x)
        a = yxx + y
        A[i, j] = sympy.integrate(weights*a, [x, 0, 1]).simplify()

csol = np.linalg.solve(A, B)

x = np.linspace(0, 1.)
y = 0
for i, ci in enumerate(csol):
    y += ci*x**(i+1)*(x-1)**(i+1)

plt.plot(x, y, 'k-')
plt.savefig('galerkin_example.png', bbox_inches='tight')

giving:

../../_images/galerkin_example.png

Table Of Contents

Previous topic

Python

This Page