Fredholm第二类积分方程的Python代码实现(4)

这是《The Numerical Solution of Integral Equations of the Second Kind》书上的例题代码实现(Galerkin方法),P66-P68,P74-77

# -*- coding: utf-8 -*-
"""
Created on Fri Jun  1 19:45:59 2018

@author: shaowu


本代码主要运用Galerkin method实现Fredholm integral equations of the second kind的求解,方程如下:
    lamda*x(t)-integrate(K(t,s)*x(s))ds=y(t),a=0<=t<=b,K(t,s)取exp(s*t)
首先,我们给定两个精确解exp(t),求出其对应的y(t),然后再来反解x(t).更详细说明可
参见《The Numerical Solution of Integral Equations of the Second Kind》P66-P68,P74-77.
"""
import sympy as sp
import scipy as scp
import numpy as np
import pandas as pd
import numpy.linalg as LA
import matplotlib.pyplot as plt
from scipy.special.orthogonal import p_roots
import time
start_time=time.time()

def function_x(t):
    return scp.exp(t)

def function_k(s,t):
    return scp.exp(s*t)

def gauss_xw(m=100):
    """
    默认用100个点求高斯——勒让德节点xi和权weight,并返回x和w数组
    """
    x,w=p_roots(m+1)
    return x,w

def gauss_solve_f(x,w,lamda,a,b,n): #参数n>=1
    """
    求解课本3.3.67式中的右端项,记为f
    参数:
    x,w为高斯点和对应的权,
    a,b 对应于区间[a,b],
    n 子区间的个数
    返回的是一个n+1维的列表
    """
    c=(b-a)/2
    s=(b-a)/2*x+(a+b)/2 #把区间[a,b]变化到[-1,1]
    h=(b-a)/(n)
    t=[a+i*h for i in range(0,n+1)] #等距划分a=t0<t1<...<tn=b
    return [sum([c*w[k]*lamda*function_x(s[k])*hat_f(i,s[k],a,b)-
            c*w[k]*sum([c*w[j]*function_k(s[j],s[k])*function_x(s[j])*hat_f(i,s[k],a,b)\
            for j in range(len(s))]) for k in range(len(s))])\
            for i in range(len(t))]

def hat_f(j,x,a,b):
    """
    定义hat函数
    """
    h=(b-a)/(n)
    t=[a+i*h for i in range(0,n+1)]
    if j==0:
        if x>=t[0] and x<=t[1]:
            return 1-abs(x-t[0])/h
        else:
            return 0
    if j==n:
        if t[n-1]<=x and x<=t[n]:
            return 1-abs(x-t[n])/h
        else:
            return 0
    if j>0 and j<n:
        if t[j-1]<=x and x<=t[j+1]:
            return 1-abs(x-t[j])/h
        else:
            return 0
def elements_of_matrix(x,w,a,b,lamda,n):
    """
    求方程(3.3.67)中的系数矩阵;
    返回的是一个数,即对应系数矩阵中的一个元素
    """
    c=(b-a)/2
    s=(b-a)/2*x+(a+b)/2 #把区间[a,b]变化到[-1,1]
    h=(b-a)/(n)
    t=[a+i*h for i in range(0,n+1)] #等距划分a=t0<t1<...<tn=b
    A=[]
    for i in range(len(t)):
        A.append([scp.integrate.quad(lambda x: lamda*hat_f(i,x,a,b)*hat_f(j,x,a,b),a,b)[0]-\
                sum([c*w[k]*sum([c*w[e]*function_k(s[e],s[k])*hat_f(i,s[e],a,b)*hat_f(j,s[k],a,b)\
            for e in range(len(s))]) for k in range(len(s))]) for j in range(len(t))])

    return np.array(A)
def solve_c(A,f):
    """
    计算c
    """
    return np.linalg.solve(A,f)
def solve_xn(c,a,b,n):
    """
    计算xn
    """
    h=(b-a)/(n)
    t=[a+i*h for i in range(0,n+1)] #等距划分a=t0<t1<...<tn=b
    xn=[sum([c[j]*hat_f(j,i,a,b) for j in range(len(t))]) for i in t]
    error=function_x(t)-xn
    #print(LA.norm(error,np.inf))
    return xn,LA.norm(error,np.inf)
if __name__ == '__main__':
    
    print('******************************程序入口*******************************')
    lamda=int(input('pleas input lambda:'))
    n=int(input('please input n:')) 
    a=int(input('please input the left value of interval:'))
    b=int(input('please input the right value of interval:'))
    m=int(input('please input the node of Gauss_Legendre:'))
    print('计算中...')
    
    x,w=gauss_xw(m)
    f=gauss_solve_f(x,w,lamda,a,b,n)
    A=elements_of_matrix(x,w,a,b,lamda,n)
    c=solve_c(A,f)
    xn,error=solve_xn(c,a,b,n)
    print('the error is:',error)
    print('all_cost_time:',time.time()-start_time)
   

运行结果:

******************************程序入口*******************************
pleas input lambda:50
please input n:8
please input the left value of interval:0
please input the right value of interval:1
please input the node of Gauss_Legendre:400
计算中...
the error is: 0.00360146251855
all_cost_time: 188.2648663520813

猜你喜欢

转载自blog.csdn.net/wushaowu2014/article/details/80581253
今日推荐