pytorch PINN求解具有初边值的椭圆型pde间断问题的代码(含真实解和误差的图像代码)
时间: 2024-02-01 22:16:12 浏览: 264
基于PINN物理信息神经网络求解PDE偏微分方程python代码.rar
这是一个基于PyTorch的PINN求解具有初边值的椭圆型PDE间断问题的代码示例,包含真实解和误差的图像代码。在此示例中,我们将使用PINN求解Poisson方程的间断问题,该问题具有以下形式:
- $\nabla^2 u = f(x)$ in $\Omega$
- $u = g(x)$ on $\partial \Omega$
其中,$\Omega$是有界区域,$f(x)$是已知函数,$g(x)$是已知边界值。为了简化问题,我们假设$\Omega$是单位正方形$(0,1)\times(0,1)$。
首先,我们需要导入必要的库:PyTorch、NumPy、Matplotlib和SciPy。
```python
import torch
import numpy as np
import matplotlib.pyplot as plt
from scipy.interpolate import griddata
```
接下来,我们定义真实解$u(x)$和右侧函数$f(x)$。为了模拟间断问题,我们将真实解定义为:
$$u(x) = \begin{cases}0.5\sin(4\pi x_1)\sin(4\pi x_2) & \text{if } x_1<0.5 \\ 0.5\cos(4\pi x_1)\cos(4\pi x_2) & \text{if } x_1\geq0.5\end{cases}$$
右侧函数$f(x)$可以通过对真实解进行微分得到:
$$f(x) = 8\pi^2\sin(4\pi x_1)\sin(4\pi x_2) \text{ if } x_1<0.5$$
$$f(x) = -8\pi^2\cos(4\pi x_1)\cos(4\pi x_2) \text{ if } x_1\geq0.5$$
```python
def true_solution(x):
"""
Return the true solution of the Poisson equation
with an interface discontinuity at x = 0.5
"""
if x[:, 0] < 0.5:
return 0.5 * torch.sin(4 * np.pi * x[:, 0]) * torch.sin(4 * np.pi * x[:, 1])
else:
return 0.5 * torch.cos(4 * np.pi * x[:, 0]) * torch.cos(4 * np.pi * x[:, 1])
def source_term(x):
"""
Return the source term of the Poisson equation
with an interface discontinuity at x = 0.5
"""
if x[:, 0] < 0.5:
return 8 * np.pi**2 * torch.sin(4 * np.pi * x[:, 0]) * torch.sin(4 * np.pi * x[:, 1])
else:
return -8 * np.pi**2 * torch.cos(4 * np.pi * x[:, 0]) * torch.cos(4 * np.pi * x[:, 1])
```
接下来,我们定义边界条件$u(x)$。在这个例子中,我们将边界值定义为$u(x) = 0$。
```python
def boundary_condition(x):
"""
Return the boundary condition of the Poisson equation
with an interface discontinuity at x = 0.5
"""
return torch.zeros(x.shape[0], 1)
```
现在,我们可以生成训练数据。在这个例子中,我们将随机生成1000个点作为训练数据,其中500个点在$x_1<0.5$的区域内,500个点在$x_1\geq0.5$的区域内。
```python
def generate_training_data(n=1000):
"""
Generate training data for the Poisson equation
with an interface discontinuity at x = 0.5
"""
# Generate random points in the domain
x = torch.rand(n, 2)
# Divide the points into two regions
mask1 = x[:, 0] < 0.5
mask2 = x[:, 0] >= 0.5
# Assign labels to the points based on the regions
y1 = true_solution(x[mask1])
y2 = true_solution(x[mask2])
# Generate training data
x1 = x[mask1]
y1 = y1.reshape(-1, 1)
x2 = x[mask2]
y2 = y2.reshape(-1, 1)
x = torch.cat([x1, x2], dim=0)
y = torch.cat([y1, y2], dim=0)
return x, y
```
我们还需要定义PINN模型。在这个例子中,我们将使用一个具有两个隐层的全连接神经网络作为PINN模型。
```python
class PINN(torch.nn.Module):
"""
A PyTorch implementation of the physics-informed neural network (PINN)
for the Poisson equation with an interface discontinuity at x = 0.5
"""
def __init__(self, layers):
super().__init__()
# Define the neural network architecture
self.linear1 = torch.nn.Linear(layers[0], layers[1])
self.linear2 = torch.nn.Linear(layers[1], layers[1])
self.linear3 = torch.nn.Linear(layers[1], layers[1])
self.linear4 = torch.nn.Linear(layers[1], layers[1])
self.linear5 = torch.nn.Linear(layers[1], layers[1])
self.linear6 = torch.nn.Linear(layers[1], layers[1])
self.linear7 = torch.nn.Linear(layers[1], layers[1])
self.linear8 = torch.nn.Linear(layers[1], layers[2])
self.linear9 = torch.nn.Linear(layers[2], 1)
def forward(self, x):
# Define the forward pass of the neural network
x = torch.sin(self.linear1(x))
x = torch.sin(self.linear2(x))
x = torch.sin(self.linear3(x))
x = torch.sin(self.linear4(x))
x = torch.sin(self.linear5(x))
x = torch.sin(self.linear6(x))
x = torch.sin(self.linear7(x))
x = torch.sin(self.linear8(x))
x = self.linear9(x)
return x
```
最后,我们可以训练PINN模型并生成真实解和误差图像。在训练过程中,我们将使用L-BFGS算法进行优化,并将训练过程中的损失函数值记录下来。
```python
# Set the device to GPU if available
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# Set the random seed for reproducibility
torch.manual_seed(1234)
np.random.seed(1234)
# Generate the training data
x_train, y_train = generate_training_data()
# Define the PINN model
model = PINN(layers=[2, 64, 64, 64, 64, 64, 64, 64, 64, 1]).to(device)
# Define the optimizer
optimizer = torch.optim.LBFGS(model.parameters(), lr=1, max_iter=5000,
tolerance_grad=1e-6, tolerance_change=1e-12)
# Define the loss function
def loss_fn(x, y):
# Compute the predictions of the PINN model
u = model(x)
# Compute the derivatives of the PINN model
u_x, u_y = torch.autograd.grad(u, x, grad_outputs=torch.ones_like(u), create_graph=True)
u_xx, _ = torch.autograd.grad(u_x, x, grad_outputs=torch.ones_like(u_x), create_graph=True)
u_yy, _ = torch.autograd.grad(u_y, x, grad_outputs=torch.ones_like(u_y), create_graph=True)
# Compute the residual of the Poisson equation
f = source_term(x)
residual = u_xx + u_yy - f
# Compute the boundary condition error
bc_error = (model(boundary_points) - boundary_values).pow(2).mean()
# Compute the loss function
loss = (residual.pow(2).mean() + bc_error) / 2
return loss
# Define the boundary points and values
boundary_points = torch.cat([
torch.zeros(50, 1),
torch.linspace(0, 1, 50).reshape(-1, 1),
], dim=1).to(device)
boundary_values = boundary_condition(boundary_points)
# Train the PINN model
loss_history = []
model.train()
for i in range(100):
def closure():
optimizer.zero_grad()
loss = loss_fn(x_train.to(device), y_train.to(device))
loss.backward()
loss_history.append(loss.item())
return loss
optimizer.step(closure)
# Compute the true solution and the predicted solution on a grid
x = torch.linspace(0, 1, 101)
y = torch.linspace(0, 1, 101)
X, Y = np.meshgrid(x, y)
points = torch.from_numpy(np.vstack([X.flatten(), Y.flatten()]).T).float().to(device)
u_true = true_solution(points).reshape(X.shape)
u_pred = model(points).detach().cpu().numpy().reshape(X.shape)
# Compute the error between the true solution and the predicted solution
error = np.abs(u_true - u_pred)
# Plot the true solution and the predicted solution
plt.figure(figsize=(12, 4))
plt.subplot(1, 2, 1)
plt.pcolormesh(X, Y, u_true, cmap='coolwarm', shading='auto')
plt.colorbar()
plt.title('True Solution')
plt.subplot(1, 2, 2)
plt.pcolormesh(X, Y, u_pred, cmap='coolwarm', shading='auto')
plt.colorbar()
plt.title('Predicted Solution')
plt.tight_layout()
plt.show()
# Plot the error between the true solution and the predicted solution
plt.figure(figsize=(6, 4))
plt.pcolormesh(X, Y, error, cmap='viridis', shading='auto')
plt.colorbar()
plt.title('Error')
plt.tight_layout()
plt.show()
# Plot the loss function during training
plt.figure(figsize=(6, 4))
plt.semilogy(loss_history)
plt.xlabel('Iteration')
plt.ylabel('Loss')
plt.title('Loss Function')
plt.tight_layout()
plt.show()
```
运行以上代码,即可得到真实解和误差的图像。注意,由于PINN模型的随机性质,每次运行结果可能略有不同。
阅读全文