Bootstrap

python 代码使用 DeepXDE 库实现了一个求解二维非线性偏微分方程(PDE)的功能

import deepxde as dde
import numpy as np
import matplotlib.pyplot as plt
import tensorflow as tf

# 设置时空计算域
Lx = 1  # x 范围从 0 到 1
Ly = 1  # y 范围从 0 到 1
Lt = 0.05  # t 范围从 0 到 0.05
geom = dde.geometry.Rectangle([0, 0], [Lx, Ly])  # 空间域
timedomain = dde.geometry.TimeDomain(0, Lt)  # 时间域
geomtime = dde.geometry.GeometryXTime(geom, timedomain)


# 设置 PDE 方程
def pde(x, y):
    u = y[:, 0:1]  # 提取 u(x, y, t)
    u_x = dde.grad.jacobian(y, x, i=0, j=0)  # u 对 x 的一阶导数
    u_y = dde.grad.jacobian(y, x, i=0, j=1)  # u 对 y 的一阶导数
    u_t = dde.grad.jacobian(y, x, i=0, j=2)  # u 对 t 的一阶导数

    # 计算 u 对 x 和 y 的梯度
    grad_u = tf.concat([u_x, u_y], axis=1)  # 使用 TensorFlow 的 concat 函数拼接张量

    # 计算 (u^2 - u + 1) * 梯度项
    term = u ** 2 - u + 1  # 计算 (u^2 - u + 1)
    A = term * grad_u  # 乘以梯度

    # 计算散度:对 (A) 进行求导,即计算 (A_x + A_y)
    A_x = dde.grad.jacobian(A, x, i=0, j=0)  # A 对 x 的导数
    A_y = dde.grad.jacobian(A, x, i=0, j=1)  # A 对 y 的导数

    # 散度 = A_x + A_y
    div_A = A_x + A_y

    # 返回 PDE 方程 u_t - div((u^2 - u + 1) * grad(u)) = 0
    return u_t - div_A


# 边界条件:u = 0,在边界上
def boundary(x, on_boundary):
    return on_boundary


bc = dde.icbc.DirichletBC(geomtime, lambda x: 0, boundary, component=0)


# 初始条件:u = sin(pi * x) * sin(pi * y)
def ic_func(x):
    return np.sin(np.pi * x[:, 0:1]) * np.sin(np.pi * x[:, 1:2])


ic = dde.icbc.IC(geomtime, ic_func, lambda x, on_initial: on_initial, component=0)

# 创建数据对象
data = dde.data.TimePDE(
    geomtime,
    pde,
    [bc, ic],
    num_domain=10000,  # 训练样本数量
    num_boundary=8000,  # 边界上的训练样本数量
    num_initial=5000,  # 初始条件上的训练样本数量
    num_test=10000,  # 测试样本数量
)

# 设置神经网络架构
layer_size = [3] + [50] * 3 + [1]  # 输入层(3维:x, y, t),4个隐藏层,每层80个神经元,输出层(u)
activation = "tanh"  # 激活函数
initializer = "Glorot uniform"  # 权重初始化方法

net = dde.nn.FNN(layer_size, activation, initializer)

# 创建模型并训练
model = dde.Model(data, net)
model.compile("adam", lr=1e-3)  # 使用 Adam 优化器,学习率为 1e-3
losshistory, train_state = model.train(iterations=3000, display_every=200)

# 保存训练历史和状态
dde.saveplot(losshistory, train_state, issave=False, isplot=True)

# 可视化结果,绘制 t=0.05 时刻的 u(x, y)
xx, yy = np.meshgrid(np.linspace(0, 1, 28), np.linspace(0, 1, 28))
xy = np.vstack((xx.ravel(), yy.ravel())).T
t = np.ones((xy.shape[0], 1)) * 0.05  # 设置 t=0.05
xy_t = np.hstack((xy, t))  # 合并 x, y, t

u_pred = model.predict(xy_t)  # 预测 u(x, y, t) 在 t=0.05 时的值
u_pred = u_pred.reshape(xx.shape)  # 重塑为网格形状

# 筛选 u >= 0
u_pred = np.maximum(u_pred, 0)

# 绘制 u(x, y) 的 3D 图
fig = plt.figure(figsize=(10, 6))
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(xx, yy, u_pred, cmap="viridis")
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('u(x, y, t=0.05)')
ax.set_title('u(x, y, t=0.05)')

plt.show()

这段代码使用 DeepXDE 库实现了一个求解二维非线性偏微分方程(PDE)的功能。以下是对代码功能的详细解释:

  1. 设置时空计算域

    • 定义了空间范围 LxLy 分别为 1,时间范围 Lt 为 0.05。
    • 创建了空间域 geom(一个矩形)、时间域 timedomain 以及时空域 geomtime
  2. 设置 PDE 方程

    • 定义了一个函数 pde 来描述 PDE 方程。
    • 计算了函数 uxyt 的一阶导数。
    • 计算了 u 的梯度和 (u^2 - u + 1) * 梯度 项。
    • 计算了上述项的散度,并构建了 PDE 方程 u_t - div((u^2 - u + 1) * grad(u)) = 0
  3. 定义边界条件和初始条件

    • 边界条件:定义了一个函数 boundary 来判断点是否在边界上,并设置边界条件为 u = 0
    • 初始条件:定义了一个函数 ic_func 来描述初始条件 u = sin(pi * x) * sin(pi * y)
  4. 创建数据对象

    • 使用 dde.data.TimePDE 创建了一个数据对象 data,包含了 PDE 方程、边界条件和初始条件。
    • 定义了训练样本、边界样本、初始条件样本和测试样本的数量。
  5. 设置神经网络架构

    • 定义了神经网络的层结构,包括输入层(3 维:xyt)、4 个隐藏层(每层 50 个神经元)和输出层(1 维:u)。
    • 选择了激活函数 tanh 和权重初始化方法 Glorot uniform
  6. 创建模型并训练

    • 使用 dde.Model 创建了一个模型,将数据对象和神经网络传入。
    • 使用 Adam 优化器,学习率为 1e-3 对模型进行编译。
    • 训练模型,迭代 3000 次,并每 200 次迭代显示一次训练信息。
  7. 保存和可视化结果

    • 使用 dde.saveplot 保存训练历史和状态,并绘制损失曲线。
    • t = 0.05 时刻,生成网格点 xxyy,并将其与 t 合并为 xy_t
    • 使用训练好的模型预测 u(x, y, t)t = 0.05 时的值,并重塑为网格形状。
    • 筛选出 u >= 0 的值。
    • 绘制 u(x, y, t = 0.05) 的 3D 图。

综上所述,这段代码实现了使用深度学习方法求解二维非线性 PDE 的功能,并对结果进行了可视化展示。

;