1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
| class HeatEquationPINN(PINN): """ 一维热传导方程: ∂u/∂t = α * ∂²u/∂x² 边界条件:u(0,t) = u(1,t) = 0 初始条件:u(x,0) = sin(πx) """ def __init__(self, alpha=0.01): super().__init__(input_dim=2, output_dim=1) self.alpha = alpha def pde_residual(self, x, t, u): """ PDE残差: ∂u/∂t - α * ∂²u/∂x² = 0 """ u_t = torch.autograd.grad( u, t, grad_outputs=torch.ones_like(u), create_graph=True )[0] u_x = torch.autograd.grad( u, x, grad_outputs=torch.ones_like(u), create_graph=True, retain_graph=True )[0] u_xx = torch.autograd.grad( u_x, x, grad_outputs=torch.ones_like(u_x), create_graph=True )[0] return u_t - self.alpha * u_xx def train(self, num_epochs=10000, lr=1e-3): """训练PINN""" optimizer = torch.optim.Adam(self.parameters(), lr=lr) scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau( optimizer, patience=500, factor=0.5 ) x_coll = torch.rand(1000, 1) * 1.0 t_coll = torch.rand(1000, 1) * 1.0 x_bc = torch.tensor([[0.0], [1.0]]).repeat(100, 1) t_bc = torch.rand(200, 1) x_ic = torch.rand(100, 1) t_ic = torch.zeros(100, 1) for epoch in range(num_epochs): optimizer.zero_grad() x = torch.cat([x_coll, x_bc, x_ic]) t = torch.cat([t_coll, t_bc, t_ic]) inputs = torch.cat([x, t], dim=1) inputs.requires_grad = True u = self.forward(inputs) residual = self.pde_residual(x, t, u) loss_pde = torch.mean(residual ** 2) u_bc_pred = self.forward(torch.cat([x_bc, t_bc], dim=1)) loss_bc = torch.mean(u_bc_pred ** 2) u_ic_pred = self.forward(torch.cat([x_ic, t_ic], dim=1)) u_ic_true = torch.sin(np.pi * x_ic) loss_ic = torch.mean((u_ic_pred - u_ic_true) ** 2) loss = loss_pde + loss_bc + loss_ic loss.backward() optimizer.step() scheduler.step(loss) if epoch % 1000 == 0: print(f"Epoch {epoch}, Loss: {loss.item():.6f}") return self
|