使用物理信息神经网络求解二维热扩散方程实例

二维热扩散方程的pinn解//物理信息神经网络实例

  • 物理信息神经网络
    • 网络构架
  • 简述二维热扩散方程
          • 参数说明
    • 问题描述
  • 效果
  • 总结

最近看了很多偏文献,对物理信息神经网络有一点了解,然后自己也做了一点实例练练手,以下是其中的一个例子,效果一般,如果有大佬觉得我哪里做得不对的话或者哪里需要改进的,希望能给点建议。

物理信息神经网络

物理信息网络,简称PINN,是一种应用神经网络来近似解决物理问题的方法,其独特之处在于将物理原理(通常通过偏微分方程进行数学表达)作为先验知识融入到神经网络的训练中。在训练过程中,PINN不仅会根据数据进行调整,还会受到物理定律的约束,从而确保学习到的结果既能够拟合数据,又能够符合物理定律。下面简单说一下物理信息神经网络的结构。

网络构架

神经网络架构:PINN通常由一个深度神经网络构成,其架构可以根据问题的复杂性进行选择。对于许多PINN应用,一个全连接的深度神经网络足以起始。如果问题涉及到图像或空间数据,可能需要使用卷积神经网络(CNNs)等更复杂的结构。
损失函数:PINN的损失函数是关键部分,它由两个主要组成部分构建:数据驱动损失和物理损失驱动。数据驱动损失用于衡量模型预测与观测数据之间的差异,而物理损失驱动则用于衡量模型预测与物理定律之间的差异。通过最小化这两个损失项,PINN可以确保预测结果既符合数据又符合物理定律。
物理信息网络结构图如下图所示:物理信息网络结构图

简单来说,就是将与物理规律有关的方程作为网络的损失,一般这个方程是偏微分方程。我们知道,对于没有给定初始条件的偏微分方程的解是有无穷多个的,因此,我们在训练的时候,会将一部分初始条件(边界条件,以下称为边界条件)也作为网络的损失,一同优化整个网络。

简述二维热扩散方程

这里我们就直接给出二维热扩散方程的偏微分方程:
∂ T ∂ t = k ( ∂ 2 T ∂ 2 x + ∂ 2 T ∂ 2 y ) \frac{\partial T}{\partial t} = k( \frac{\partial^2 T}{\partial^2 x} + \frac{\partial^2 T}{\partial^2 y}) tT=k(2x2T+2y2T)

参数说明

T:温度场
t:时间
(x,y):空间坐标

问题描述

给定初始的温度分布图如下,方框大小为1×1:
初始温度场分布
在y=0以及x=0的位置上温度为100°,其他地方均为0°,取k=1。
因此,对于物理场T(x,y,t)可知边界条件为
T ( 0 , y , 0 ) = 100 , T ( x , 0 , 0 ) = 100 T ( x , y , 0 ) = 0 , x , y ∈ ( 0 , 1 ) T(0,y,0)=100,T(x,0,0)=100\\T(x,y,0)=0,x,y \in (0,1) T(0,y,0)=100,T(x,0,0)=100T(x,y,0)=0,x,y(0,1)
使用神经网络f(x,y,t)去逼近温度场T,网络层数为5层隐藏层,每层隐藏层神经元100个,输入神经元3个,对应输入空间坐标(x,y),和时间t,输出为单个T。基于以上信息可知网络损失为
S S E = S S E f + S S E b SSE =SSE_f + SSE_b SSE=SSEf+SSEb
其中 S S E f SSE_f SSEf为偏微分损失, S S E b SSE_b SSEb为边界损失
由已知信息定义为:
偏微分损失:
S S E f = 1 N ∑ ∣ ∂ f ∂ t − ( ∂ 2 f ∂ 2 x + ∂ 2 f ∂ 2 y ) ∣ 2 SSE_f =\frac{1}{N}\sum|\frac{\partial f}{\partial t}-( \frac{\partial^2 f}{\partial^2 x} + \frac{\partial^2 f}{\partial^2 y})|^2 SSEf=N1tf(2x2f+2y2f)2
边界损失:
S S E b = { 1 N ∑ ∣ f ( x , y , 0 ) − 100 ∣ 2 , x = 0 或 y = 0 1 N ∑ ∣ f ( x , y , 0 ) − 0 ∣ 2 , x , y ∈ ( 0 , 1 ) SSE_b=\left\{\begin{matrix} &\frac{1}{N}\sum|f(x,y,0)-100|^2 ,x=0或y=0\\ &\frac{1}{N}\sum|f(x,y,0)-0|^2 ,x,y \in(0,1) \end{matrix}\right. SSEb={N1f(x,y,0)1002,x=0y=0N1f(x,y,0)02,x,y(0,1)

效果

与FDTD所计算的效果进行对比,FDTD方法可参考链接:基于MATLAB的有限差分法求解二维瞬态热传导方程,所得结果为最终稳态温度场状态,如图:FDTD所计算的二维热传导方程稳态温度场
对于PINN可以得到关于1秒钟内的温度变化场,效果如下图:
PINN所计算的二维热传导方程效果
最终稳态效果为:
pinn计算的二维热传导方程稳态温度场
与FDTD所计算的误差图为:
误差图

总结

可以看出,效果一般,是因为训练次数有限,理论上来讲,训练次数达到一定程度时,pinn解可以无限逼近真实解。与其他方法对比,pinn是无网络方法,可以用少量的数据点得到更广泛的效果图。
以上是这篇博客内容,需要代码的可以联系我(不是买课的!!!!遇到好多博主说是可以免费分享代码,结果后面都是买课的。。。。)。

<think>嗯,用户想要一个关于用物理信息神经网络(PINN)求解二维热传导方程的代码示。我需要先回顾一下二维热传导方程的基本形式。这个方程通常写成 ∂u/∂t = α(∂²u/∂x² + ∂²u/∂y²),其中α是热扩散系数,u是温度场,x和y是空间坐标,t是时间变量。 接下来,我需要考虑PINN的基本结构。PINN通过神经网络近似解u,并将PDE作为损失函数的一部分来训练网络。因此,代码的大致步骤应该包括:定义神经网络结构,设置训练数据(包括初始条件、边界条件和域内的残差点),定义损失函数(包含PDE残差、初始和边界条件),以及训练过程。 首先,用户可能需要一个简单的示,所以应该选择一个常用的深度学习框架,比如TensorFlow或者PyTorch。这里可能更倾向于PyTorch,因为它在科研中更常用,而且自动微分更方便。 然后,定义神经网络结构。通常使用全连接网络,激活函数如tanh或sigmoid。输入层有3个节点(x, y, t),输出层是u的值。隐藏层的数量和节点数需要合理设置,比如4层,每层20个节点。 接下来是损失函数的构成。需要计PDE的残差,也就是∂u/∂t - α(∂²u/∂x² + ∂²u/∂y²)。这需要用到自动微分来计梯度。同时,初始条件和边界条件的损失也要考虑进去。比如,初始时刻t=0时,u的值应该满足某个初始条件u0(x,y),边界上的u值也应该符合给定的边界条件。 生成训练数据时,可能需要使用随机采样点。初始条件的数据点是在t=0时整个空间域采样;边界条件则是在各个边(x=0, x=L, y=0, y=W)的不同时间点采样;而残差点的采样是在整个时空域内随机选择。 训练过程中,需要将各个损失项加权求和。可能需要调整权重,比如让边界和初始条件的权重更高,以确保这些条件被满足。优化器通常选择Adam,学习率适当设置,比如0.001,迭代次数比如10000次。 另外,需要注意代码的正确性。比如,在计二阶导数时,要确保正确使用自动微分,可能需要先计一阶导数,再求导一次。同时,数据点的坐标需要合理归一化,避免输入范围过大导致训练困难。 可能的陷阱包括:网络结构不够深导致无法逼近解,学习率不合适导致收敛慢,损失项权重不平衡导致某些条件不满足。因此,在代码示中需要给出一些调参的建议,比如调整网络层数、节点数,或者调整权重系数。 最后,示代码可能需要一个具体的问题设定,比如设定α的值,定义初始条件和边界条件。如,假设α=0.1,初始条件u0(x,y)=sin(πx)sin(πy),边界条件u=0。然后通过PINN求解这个特定问题。 用户可能还需要知道如何验证结果,比如与解析解比较,或者可视化温度场的分布。这部分可以在代码中添加,比如使用matplotlib绘制某个时刻的u分布。 总结下来,代码示应该包括以下几个部分: 1. 导入必要的库(PyTorch, numpy, matplotlib等)。 2. 定义神经网络结构。 3. 生成训练数据(初始、边界、残差点)。 4. 定义损失函数,包括各个部分。 5. 训练循环。 6. 结果验证和可视化。 需要确保代码中的LaTeX公式正确使用$$和$符号,比如在注释或说明中正确呈现方程。同时,保持代码简洁,注释清晰,方便用户理解和修改参数进行实验。</think>以下是一个基于PyTorch实现PINN求解二维非稳态热传导方程的代码示,包含详细的中文注释和关键公式说明: ```python import torch import torch.nn as nn import numpy as np import matplotlib.pyplot as plt # 二维热传导方程:∂u/∂t = α(∂²u/∂x² + ∂²u/∂y²) # 定义参数 alpha = 0.1 # 热扩散系数 L, W = 1.0, 1.0 # 空间域范围 T = 1.0 # 时间范围 # 定义神经网络结构 class PINN(nn.Module): def __init__(self): super(PINN, self).__init__() self.net = nn.Sequential( nn.Linear(3, 20), # 输入(x,y,t) nn.Tanh(), nn.Linear(20, 20), nn.Tanh(), nn.Linear(20, 20), nn.Tanh(), nn.Linear(20, 1) # 输出u ) def forward(self, x, y, t): inputs = torch.cat([x, y, t], dim=1) return self.net(inputs) # 初始化模型和优化器 model = PINN() optimizer = torch.optim.Adam(model.parameters(), lr=0.001) # 生成训练数据 def generate_data(num_samples=100): # 初始条件(t=0) x_ic = torch.rand(num_samples, 1) * L y_ic = torch.rand(num_samples, 1) * W t_ic = torch.zeros(num_samples, 1) u_ic = torch.sin(np.pi * x_ic) * torch.sin(np.pi * y_ic) # 示初始条件 # 边界条件(假设Dirichlet边界u=0) x_bc = torch.cat([torch.zeros(num_samples//4,1), torch.ones(num_samples//4,1), torch.rand(num_samples//4,1)*L, torch.rand(num_samples//4,1)*L], 0) y_bc = torch.cat([torch.rand(num_samples//4,1)*W, torch.rand(num_samples//4,1)*W, torch.zeros(num_samples//4,1), torch.ones(num_samples//4,1)], 0) t_bc = torch.rand(num_samples, 1) * T u_bc = torch.zeros(num_samples, 1) # 残差采样点 x_res = torch.rand(num_samples, 1) * L y_res = torch.rand(num_samples, 1) * W t_res = torch.rand(num_samples, 1) * T return (x_ic, y_ic, t_ic, u_ic), (x_bc, y_bc, t_bc, u_bc), (x_res, y_res, t_res) # 定义损失函数 def compute_loss(model, ic_data, bc_data, res_data): # 初始条件损失 x_ic, y_ic, t_ic, u_ic = ic_data u_pred_ic = model(x_ic, y_ic, t_ic) loss_ic = torch.mean((u_pred_ic - u_ic)**2) # 边界条件损失 x_bc, y_bc, t_bc, u_bc = bc_data u_pred_bc = model(x_bc, y_bc, t_bc) loss_bc = torch.mean((u_pred_bc - u_bc)**2) # PDE残差损失 x_res, y_res, t_res = res_data x_res.requires_grad_(True) y_res.requires_grad_(True) t_res.requires_grad_(True) u = model(x_res, y_res, t_res) # 计梯度 grad_u = torch.autograd.grad(u, [x_res, y_res, t_res], grad_outputs=torch.ones_like(u), create_graph=True)[0] u_t = grad_u[:, 2:3] # ∂u/∂t # 计二阶导数 u_x = grad_u[:, 0:1] u_y = grad_u[:, 1:2] u_xx = torch.autograd.grad(u_x, x_res, torch.ones_like(u_x), create_graph=True)[0][:, 0:1] u_yy = torch.autograd.grad(u_y, y_res, torch.ones_like(u_y), create_graph=True)[0][:, 0:1] # PDE残差 residual = u_t - alpha*(u_xx + u_yy) loss_res = torch.mean(residual**2) # 总损失 total_loss = loss_ic + loss_bc + loss_res return total_loss # 训练循环 ic_data, bc_data, res_data = generate_data(1000) for epoch in range(10000): optimizer.zero_grad() loss = compute_loss(model, ic_data, bc_data, res_data) loss.backward() optimizer.step() if epoch % 1000 == 0: print(f"Epoch {epoch}, Loss: {loss.item():.4e}") # 结果可视化(示) def plot_solution(model, t=0.5): x = np.linspace(0, L, 100) y = np.linspace(0, W, 100) X, Y = np.meshgrid(x, y) T = np.full_like(X, t) with torch.no_grad(): u_pred = model(torch.tensor(X.reshape(-1,1), dtype=torch.float32), torch.tensor(Y.reshape(-1,1), dtype=torch.float32), torch.tensor(T.reshape(-1,1), dtype=torch.float32)) plt.contourf(X, Y, u_pred.numpy().reshape(100,100)) plt.colorbar() plt.title(f"Temperature Distribution at t={t}") plt.show() plot_solution(model, t=0.5) ``` **关键数学公式说明:** 1. **控制方程**(PDE残差项): $$ \frac{\partial u}{\partial t} = \alpha\left( \frac{\partial^2 u}{\partial x^2} + \frac{\partial^2 u}{\partial y^2} \right) $$ 对应代码中残差计: ```python residual = u_t - alpha*(u_xx + u_yy) ``` 2. **初始条件**(示): $$ u(x,y,0) = \sin(\pi x)\sin(\pi y) $$ 对应代码中的`u_ic`计 **代码特点说明:** 1. 使用全连接神经网络构建PINN,输入为$(x,y,t)$,输出为温度$u$ 2. 通过自动微分计偏导数(`torch.autograd.grad`) 3. 损失函数包含三部分: - 初始条件损失(均方误差) - 边界条件损失(均方误差) - PDE残差损失(均方误差) 4. 可视化函数展示特定时刻的温度分布 **改进建议:** 1. 增加自适应权重平衡不同损失项 2. 使用更复杂的网络结构(如残差连接) 3. 引入硬约束条件处理边界 4. 采用自适应采样策略 建议先运行此基础版本,再逐步添加高级功能。可通过调整网络深度/宽度、学习率、采样点数量等参数观察收敛效果。
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小佈要早睡

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

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

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

打赏作者

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

抵扣说明:

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

余额充值