针对L型区域的椭圆方程的差分法

35 篇文章 17 订阅 ¥199.90 ¥99.00

#采用五点差分格式,首先给出精确解和右端项的定义。

'''
def UU(X, order):
    temp = 10*(X[:,0]+X[:,1])**2 + (X[:,0]-X[:,1])**2 + 0.5
    if order[0]==0 and order[1]==0:
        return torch.log(temp)
    if order[0]==1 and order[1]==0:
        return temp**(-1) * (20*(X[:,0]+X[:,1]) + 2*(X[:,0]-X[:,1]))
    if order[0]==0 and order[1]==1:
        return temp**(-1) * (20*(X[:,0]+X[:,1]) - 2*(X[:,0]-X[:,1]))
    if order[0]==2 and order[1]==0:
        return - temp**(-2) * (20*(X[:,0]+X[:,1])+2*(X[:,0]-X[:,1])) ** 2 \
               + temp**(-1) * (22)
    if order[0]==0 and order[1]==2:
        return - temp**(-2) * (20*(X[:,0]+X[:,1])-2*(X[:,0]-X[:,1])) ** 2 \
               + temp**(-1) * (22)
'''
def UU(X,order):
    if order == [0,0]:
        return X[:,0]**2 + X[:,1]**2
    if order == [2,0]:
        return 2*torch.ones(X.shape[0])
    if order == [0,2]:
        return 2*torch.ones(X.shape[0])

def FF(X):
    return -UU(X,[2,0]) - UU(X,[0,2])

针对L型区域而言,一共有6个点控制边界,x轴有3个控制点,y轴有3个控制点。给出边界bounds = [[xa,xb,xc],[ya,yb,yc]],例如以下这个L型区域,xa =-1,xb = 0,xc = 1;ya = -1,yb = 0,yc = 1。
在这里插入图片描述
##下面重点介绍区域点采样以及矩阵和右端项的构建。

class FENET():
    def __init__(self,bounds,hx):
        self.bounds = bounds
        self.dim = 2
        self.hx = hx
        nx = [[int((bounds[0,1] - bounds[0,0])/hx[0]),
               int((bounds[0,2] - bounds[0,1])/hx[0])],
              [int((bounds[1,2] - bounds[1,0])/hx[1]),
               int((bounds[1,1] - bounds[1,0])/hx[1])]]
        self.nx = torch.tensor(nx)
        
        self.Node()
        self.u_acc = UU(self.Nodes,[0,0]).view(-1,1)
    def Node(self):#生成网格点(M + 1)*(N + 1)
        self.Nodes_size = (self.nx[0,0] + 1)*(self.nx[1,0] + 1) + self.nx[0,1]*(self.nx[1,1] + 1)
        self.Nodes = torch.zeros(self.Nodes_size,self.dim)
        m = 0
        for i in range(self.nx[0,0] + 1):
            for j in range(self.nx[1,0] + 1):
                self.Nodes[m,0] = self.bounds[0,0] + i*self.hx[0]
                self.Nodes[m,1] = self.bounds[1,0] + j*self.hx[1]
                m = m + 1
        for i in range(self.nx[0,1]):
            for j in range(self.nx[1,1] + 1):
                self.Nodes[m,0] = self.bounds[0,1] + (i + 1)*self.hx[0]
                self.Nodes[m,1] = self.bounds[1,0] + j*self.hx[1]
                m = m + 1
    def matrix(self):
        self.A = torch.zeros(self.Nodes_size,self.Nodes_size)
        m = 0
        for i in range(self.nx[0,0] + 1):
            for j in range(self.nx[1,0] + 1):
                dx = self.hx[0];dy = self.hx[1]
                if i == 0 or j == 0 or j == self.nx[1,0]:
                    self.A[m,m] = 1
                    plt.plot(self.Nodes[m,0],self.Nodes[m,1],'r*')
                elif (i == self.nx[0,0] and self.Nodes[m,1] >= self.bounds[1,1]):
                    self.A[m,m] = 1
                    plt.plot(self.Nodes[m,0],self.Nodes[m,1],'r*')
                else:
                    self.A[m,i*(self.nx[1,0] + 1) + j] = 2*(dx/dy + dy/dx)
                    self.A[m,(i - 1)*(self.nx[1,0] + 1) + j] = -dy/dx
                    self.A[m,(i + 1)*(self.nx[1,0] + 1) + j] = -dy/dx
                    self.A[m,i*(self.nx[1,0] + 1) + j - 1] = -dx/dy
                    self.A[m,i*(self.nx[1,0] + 1) + j + 1] = -dx/dy
                m = m + 1
        n = 0
        for i in range(self.nx[0,1]):
            for j in range(self.nx[1,1] + 1):
                dx = self.hx[0];dy = self.hx[1]
                if i == self.nx[0,1] - 1 or j == self.nx[1,1] or j == 0:
                    self.A[m + n,m + n] = 1
                    plt.plot(self.Nodes[m + n,0],self.Nodes[m + n,1],'r*')
                else:
                    self.A[m + n,m + n] = 2*(dx/dy + dy/dx)
                    self.A[m + n,m + (i - 1)*(self.nx[1,1] + 1) + j] = -dy/dx
                    self.A[m + n,m + (i + 1)*(self.nx[1,1] + 1) + j] = -dy/dx
                    self.A[m + n,m + i*(self.nx[1,1] + 1) + j - 1] = -dx/dy
                    self.A[m + n,m + i*(self.nx[1,1] + 1) + j + 1] = -dx/dy
                n = n + 1
    def right(self,UU,FF):
        self.b = torch.zeros(self.Nodes_size,1)
        m = 0
        for i in range(self.nx[0,0] + 1):
            for j in range(self.nx[1,0] + 1):
                dx = self.hx[0];dy = self.hx[1]
                if i == 0 or j == 0 or j == self.nx[1,0]:
                    self.b[m] = UU(self.Nodes[m:m + 1,:],[0,0])
                    plt.plot(self.Nodes[m,0],self.Nodes[m,1],'r*')
                elif (i == self.nx[0,0] and self.Nodes[m,1] >= self.bounds[1,1]):
                    self.b[m] = UU(self.Nodes[m:m + 1,:],[0,0])
                    plt.plot(self.Nodes[m,0],self.Nodes[m,1],'r*')
                else:
                    self.b[m] = dx*dy*FF(self.Nodes[m:m + 1,:])
                m = m + 1
        n = 0
        for i in range(self.nx[0,1]):
            for j in range(self.nx[1,1] + 1):
                dx = self.hx[0];dy = self.hx[1]
                if i == self.nx[0,1] - 1 or j == self.nx[1,1] or j == 0:
                    self.b[m + n] = UU(self.Nodes[m + n:m + n + 1,:],[0,0])
                    plt.plot(self.Nodes[m + n,0],self.Nodes[m + n,1],'r*')
                else:
                    self.b[m + n] = dx*dy*FF(self.Nodes[m + n:m + n + 1,:])
                n = n + 1
    def solve(self,UU,FF):
        self.matrix()
        self.right(UU,FF)
        u_pred,lu = torch.solve(self.b,self.A)
        return u_pred
def error(u_pred,u_acc):
    fenzi = ((u_pred - u_acc)**2).sum()
    fenmu = (u_acc**2 + 1e-8).sum()
    return (fenzi/fenmu)**(0.5)
bounds = torch.tensor([[-2,0,2],[-1,0,1]]).float()
hx = [0.1,0.1]
fenet = FENET(bounds,hx)
u_pred = fenet.solve(UU,FF)
print('the error of FD method on L-square is %.3e'%(error(u_pred,fenet.u_acc)))

这个Node()函数,给出了采样点self.Nodes,以及采样点的数目self.Nodes_size,self.nx[0,0],self.nx[0,1]分别表示x轴上的两个区间[xa,xb],[xb,xc]上的分划数目(注意x轴上的网格点数目为分划数目+1),self.nx[1,0],self.nx[1,1]分别表示x轴上的两个区间[ya,yc],[yc,yb]上的分划数目(注意y轴上的网格点数目为分划数目+2),所以总共有网格点数目(self.nx[0,0] + 1)(self.nx[1,0] + 1) + self.nx[0,1](self.nx[1,1] + 1)。给出采样点的取点顺序以后,后面构建矩阵A的元素就和正常的矩形区域一样,在边界上A[i,i]=1。这里重点就是边界点的索引,为了检查边界点是否取正确,为此我在循环中加入了plt.plot(self.Nodes[m,0],self.Nodes[m,1],‘r*’),将对应的边界点以图像方式画出来。矩阵A构建成功以后,右端项都是一样的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Galerkin码农选手

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值