# -*- coding: utf-8 -*-"""
Created on Tue Mar 31 22:11:52 2020
@author: Mr.Yang
""""""
函数形如
a(x)u''(x)+b(x)u'(x)+c(x)u(x)=f(x)
u(a)=A
u(b)=B
例题1:u''(x)=sin(x)
u(0)=
u(1)=
例题2:u''(x)=x*x*exp(x)
u(0)=
u(1)=
f(x)=x*x*exp(x)
例题3:
The PDE is defined for 0 < x < 1:
# -u'' = f
# with right hand side
# f(x) = -(exact(x)'')
# and boundary conditions
# u(0) = exact(0),
# u(1) = exact(1).
#
# The exact solution is:解析解
# exact(x) = x * ( 1 - x ) * exp ( x )
# The boundary conditions are
# u(0) = 0.0 = exact(0.0),
# u(1) = 0.0 = exact(1.0).
# The right hand side is:
# f(x) = x * ( x + 3 ) * exp ( x ) = - ( exact''(x) )
"""import matplotlib.pyplot as plt
import numpy as np
import scipy.linalg as la
import time
#---------------------------------------------------------------------#定义函数 先定义后调用
es=0.01#奇异摄动二阶非齐次deff_x(x):#f=-np.sin(x) # u''(x)=sin(x) u'=-cos(x) u=-sin(x) #f=-x * ( x + 3 ) * np.exp ( x ) #注意这里的正负号和有限元不一样#f=np.exp(x)*(np.cos(x)-2*np.sin(x)-x*np.cos(x)-x*np.sin(x)) #注意这里的正负号和有限元不一样 #方程3#f=np.sin(np.pi*x)
f=-1/es # 作业 return(f)defe_fn(x):#f1=np.sin(x)#f1=x * ( 1 - x ) * np.exp ( x )#f=x*np.cos(x) #方程3#f1=-1/np.pi**2*np.sin(np.pi*x)
f=(np.exp(1/es)-2)/(np.exp(1/es)-1)+(np.exp(1/es*x))/(np.exp(1/es)-1)+x # 作业 https://wenku.baidu.com/view/cde993ba4028915f814dc24e.html 解析解 求解网址return(f)#-------------------------------------------------------------------------defa_f(x):#f=1 #方程3
f=1# 作业 return(f)defb_f(x):#f=0 #方程3
f=-1/es # 作业 return(f)defc_f(x):
f=0return(f)#-------------------------------------------------------------------------defFdm_cd_1d(a,b,n):
m_a=a
m_b=b
m=n #区间【a,b】之间有10个点即有U1 U2 U3 U4 U5 ...U8 U9 U10
h=1/(m+1)
x = np.linspace ( m_a, m_b, m +2)#生成等差数列 x=jh#第一项为 m_a #最后一项为 m_b#共有 m+2 项print(x)#系数矩阵A的赋值处理方法如下:
A=np.zeros((m,m))
b=np.zeros((m))#print(b)print('原始矩阵A如下\n')print(A)for l inrange(0,m-1):#for i in range(0,2):
A[l][l]= A[l][l]+ h*h*c_f(x[l+1])-2*a_f(x[l+1])
A[l][l+1]=A[l][l+1]+a_f(x[l+1])+h*b_f(x[l+1])/2
A[l+1][l]=A[l+1][l]+a_f(x[l+2])-h*b_f(x[l+2])/2
A[l+1][l+1]=A[l+1][l+1]+0print('赋值后的矩阵A如下\n')print(A)
A[m-1][m-1]=h*h*c_f(x[m])-2*a_f(x[m])
A=A/(h*h)print('最终所得的矩阵A如下:\n')print(A)#方程右端系数矩阵b的赋值处理方法如下for i inrange(0,m):#if(i==0):# b[i]=b[i]+f_x(x[i+1])-(e_fn(m_a)/(h*h))#elif(i==m-1):# b[i]=b[i]+f_x(x[i+1])-(e_fn(m_b)/(h*h))#else:
b[i]=b[i]+f_x(x[i+1])print(b)
b[0]=b[0]-(a_f(x[1])/(h*h)-b_f(x[1])/(2*h))*e_fn(m_a)# 边值的处理
b[m-1]=b[m-1]-(a_f(x[m])/(h*h)+b_f(x[m])/(2*h))*e_fn(m_b)print('最终所得的矩阵b如下:\n')print(b)
b=b.T
u = la.solve ( A, b)#b1=b.T 转置与否,结果 都一样 print('数值解计算结果u如下:')print(u)#u1 = la.solve ( A, b1)#print(u1)
npp = n+2#51
xp = np.linspace (m_a,m_b,npp)
up = np.zeros ( npp )for i inrange(0, npp):
up[i]= e_fn ( xp[i])
U=np.zeros((m+2))for j inrange(0,m+2):if(j==0):
U[j]=e_fn(m_a)elif(j==m+1):
U[j]=e_fn(m_b)else:
U[j]=u[j-1]print('')print('已知有m个U的值,再加上左端点值,右端点值')print(U)
uex = np.zeros ( m +2)for i inrange(0, m +2):
uex[i]= e_fn(x[i])## Compare the solution and the error at the nodes.#print('')print(' Node Numer True Error')print('')
err=np.zeros(m+2)#是在使用范数时才零为数组的 不然 使用常数也可以解决for i inrange(0, m +2):
err[i]=abs( uex[i]- U[i])print(' %4d %14.6g %14.6g %14.6g'%( i, U[i], uex[i], err[i]))#plt.plot ( x, U, 'bo-',xp, up, 'r.')
plt.plot( x, U,'bo-',lw=1,label="Numerical ")
plt.plot( xp, up,'r+',lw=6,label="Real")
plt.fill_between(x,U ,up, color ='green')
plt.savefig ('fem1d.png')
plt.xlabel('$x$', fontsize=14,color='blue')
plt.ylabel('$F(x)$', fontsize=14,color='blue')
plt.legend(fontsize=14)## Terminate.#
plt.show ()print('<--------------------------------------------------->')print('使用误差证明该方法是二阶的即 O(h^2)')print('Under inf Norm:')#print(abs(err))
norm1=max(abs(err))print('The error of under inf Norm:%14.6g'%(norm1))print('<--------------------------------------------------->')print('Under 1 Norm:')
norm2=sum(abs(err))*h
print('The error of under 1 Norm:%14.6g'%(norm2))print('<--------------------------------------------------->')print('Under 2 Norm:')
norm3=np.sqrt(sum(abs(err)*(abs(err)).T)*h)print('The error of under 2 Norm:%14.6g'%(norm3))print('PDE——有限差分:中心差商求解::1D 狄利克雷边值 问题')print(' Normal end of execution.')
a,b,n=map(int,input('请输入左端点a,右端点b,单元格个数m:等3个系数:各数字之间空格键隔开\n').split())
start = time.clock()#输入系数 Enter 后开始计时
Fdm_cd_1d(a,b,n)
end = time.clock()print('计算程序运行的时间\n')print(end-start)print('')
Node Numer True Error
011011.00991.0099021.01981.01982.22045e-1631.02971.02972.22045e-1641.03961.03964.44089e-1651.04951.04954.44089e-1661.059411.059416.66134e-1671.069311.069318.88178e-1681.079211.079211.11022e-1591.089111.089111.77636e-15101.099011.099011.9984e-15111.108911.108912.44249e-15121.118811.118812.88658e-15131.128711.128712.88658e-15141.138611.138613.10862e-15151.148511.148513.10862e-15161.158421.158423.33067e-15171.168321.168323.77476e-15181.178221.178223.9968e-15191.188121.188123.9968e-15201.198021.198024.44089e-15211.207921.207924.66294e-15221.217821.217824.88498e-15231.227721.227725.32907e-15241.237621.237625.32907e-15251.247521.247525.55112e-15261.257431.257435.77316e-15271.267331.267335.9952e-15281.277231.277236.43929e-15291.287131.287136.88338e-15301.297031.297037.32747e-15311.306931.306937.77156e-15321.316831.316837.99361e-15331.326731.326738.21565e-15341.336631.336638.43769e-15351.346531.346538.88178e-15361.356441.356448.88178e-15371.366341.366349.32587e-15381.376241.376249.99201e-15391.386141.386141.06581e-14401.396041.396041.11022e-14411.405941.405941.15463e-14421.415841.415841.22125e-14431.425741.425741.26565e-14441.435641.435641.33227e-14451.445541.445541.37668e-14461.455451.455451.44329e-14471.465351.465351.4877e-14481.475251.475251.53211e-14491.485151.485151.62093e-14501.495051.495051.66533e-14511.504951.504951.70974e-14521.514851.514851.77636e-14531.524751.524751.84297e-14541.534651.534651.88738e-14551.544551.544551.93179e-14561.554461.554461.9762e-14571.564361.564362.04281e-14581.574261.574262.10942e-14591.584161.584162.15383e-14601.594061.594062.19824e-14611.603961.603962.26485e-14621.613861.613862.30926e-14631.623761.623762.37588e-14641.633661.633662.42029e-14651.643561.643562.4869e-14661.653471.653472.64233e-14671.663371.663372.86438e-14681.673271.673273.30846e-14691.683171.683174.44089e-14701.693071.693077.28306e-14711.702971.702971.4766e-13721.712871.712873.475e-13731.722771.722778.79741e-13741.732671.732672.29972e-12751.742571.742576.08713e-12761.752481.752481.61811e-11771.762381.762384.30553e-11781.772281.772281.1452e-10791.782181.782183.04303e-10801.792081.792088.07511e-10811.801981.801982.13942e-09821.811881.811885.65771e-09831.821781.821781.49302e-08841.831681.831683.93037e-08851.841581.841581.03178e-07861.851491.851492.69982e-07871.861391.861397.03796e-07881.871291.871291.82658e-06891.881191.88124.71583e-06901.89111.891111.20993e-05911.901011.901043.08084e-05921.910951.911037.77191e-05931.920961.921160.00019378941.931191.931670.00047596951.942081.943220.00114604961.954891.957570.00268483971.973411.979450.0060427982.008832.021590.0127598992.094272.118240.0239681002.327852.361640.0337916101330
<--------------------------------------------------->
使用误差证明该方法是二阶的即 O(h^2)
Under inf Norm:
The error of under inf Norm: 0.0337916<--------------------------------------------------->
Under 1 Norm:
The error of under 1 Norm: 0.00080387<--------------------------------------------------->
Under 2 Norm:
The error of under 2 Norm: 0.00436509
PDE——有限差分:中心差商求解::1D 狄利克雷边值 问题
Normal end of execution.
计算程序运行的时间
0.33772579999958907