PINN:物理信息神经网络求解微分方程
FreeGuideOnline
最新
2026-06-20
python import torch import torch.nn as nn import numpy as np import matplotlib.pyplot as plt
### 3.2 定义神经网络结构
```python
class PINN(nn.Module):
def __init__(self, layers):
super(PINN, self).__init__()
self.net = nn.Sequential()
for i in range(len(layers)-1):
self.net.add_module(f'linear_{i}', nn.Linear(layers[i], layers[i+1]))
if i < len(layers)-2:
self.net.add_module(f'tanh_{i}', nn.Tanh())
# 权重初始化(常用 Xavier 均匀分布)
for m in self.net.modules():
if isinstance(m, nn.Linear):
nn.init.xavier_normal_(m.weight)
nn.init.constant_(m.bias, 0.0)
def forward(self, x, t):
# 输入形状 (N, 1) 的 x 和 t,拼接后送入网络
inputs = torch.cat([x, t], dim=1)
return self.net(inputs)
这里我们设计网络层数为 [2, 20, 20, 20, 1],采用 Tanh 激活函数。Xavier 初始化有助于加快训练。
3.3 定义损失函数
def compute_loss(model, x_f, t_f, x_b, t_b, u_b,
x_0, t_0, u_0, nu=0.01/torch.pi):
# PDE 残差损失
x_f.requires_grad = True
t_f.requires_grad = True
u = model(x_f, t_f)
# 一阶导数
u_t = torch.autograd.grad(u, t_f, grad_outputs=torch.ones_like(u),
create_graph=True)[0]
u_x = torch.autograd.grad(u, x_f, grad_outputs=torch.ones_like(u),
create_graph=True)[0]
# 二阶导数
u_xx = torch.autograd.grad(u_x, x_f, grad_outputs=torch.ones_like(u_x),
create_graph=True)[0]
f = u_t + u * u_x - nu * u_xx
loss_pde = torch.mean(f ** 2)
# 边界损失
u_pred_b = model(x_b, t_b)
loss_bc = torch.mean((u_pred_b - u_b) ** 2)
# 初始条件损失
u_pred_0 = model(x_0, t_0)
loss_ic = torch.mean((u_pred_0 - u_0) ** 2)
return loss_pde + loss_bc + loss_ic
3.4 生成训练数据
# 配置点(域内)
N_f = 10000
x_f = torch.rand(N_f, 1) * 2 - 1 # [-1,1]
t_f = torch.rand(N_f, 1)
# 边界点
N_b = 500
x_b_left = -1 + torch.zeros(N_b//2, 1)
t_b_left = torch.rand(N_b//2, 1)
x_b_right = 1 + torch.zeros(N_b//2, 1)
t_b_right = torch.rand(N_b//2, 1)
x_b = torch.cat([x_b_left, x_b_right], 0)
t_b = torch.cat([t_b_left, t_b_right], 0)
u_b = torch.zeros(N_b, 1) # Dirichlet BC = 0
# 初始点
N_0 = 500
x_0 = torch.rand(N_0, 1) * 2 - 1
t_0 = torch.zeros(N_0, 1)
u_0 = -torch.sin(torch.pi * x_0)
3.5 训练模型
model = PINN([2, 20, 20, 20, 1])
optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
for epoch in range(10001):
optimizer.zero_grad()
loss = compute_loss(model, x_f, t_f, x_b, t_b, u_b, x_0, t_0, u_0)
loss.backward()
optimizer.step()
if epoch % 1000 == 0:
print(f'Epoch {epoch}, Loss: {loss.item():.3e}')
3.6 结果可视化
# 在均匀网格上预测
X = torch.linspace(-1, 1, 256)
T = torch.linspace(0, 1, 100)
X, T = torch.meshgrid(X, T, indexing='ij')
x_flat = X.reshape(-1, 1)
t_flat = T.reshape(-1, 1)
with torch.no_grad():
u_pred = model(x_flat, t_flat).numpy().reshape(256, 100)
plt.pcolormesh(T.numpy(), X.numpy(), u_pred, shading='auto', cmap='jet')
plt.colorbar(label='u')
plt.xlabel('t')
plt.ylabel('x')
plt.title('PINN solution for Burgers equation')
plt.show()