方程自己解(3)——deepXDE解Burgers方程


Cite:
【1】 维基百科.伯格斯方程
【2】 DeepXDE.伯格斯方程求解

1. what‘s Burgers equation

在这里插入图片描述

2. Solve Burgers equation by DeepXDE

Burgers equation:
d u d t + u d u d x = v d 2 u d x 2 ,    x ∈ [ − 1 , 1 ] ,    t ∈ [ 0 , 1 ] (1) \frac{du}{dt} + u\frac{du}{dx} = v\frac{d^2u}{dx^2} ,\; x\in [-1,1] , \; t \in [0,1] \tag{1} dtdu+udxdu=vdx2d2u,x[1,1],t[0,1](1)
Dirichlet boundary conditions and initial conditions
u ( − 1 , t ) = u ( 1 , t ) = 0 ,    u ( x , 0 ) = − s i n ( π x ) u(-1,t) = u(1,t) = 0, \; u(x,0) = -sin(\pi x) u(1,t)=u(1,t)=0,u(x,0)=sin(πx)
reference solution: here

import deepxde as dde
import numpy as np
import matplotlib.pyplot as plt 
def gen_testdata():
    """ 
        generate test data with react synthetic result
    """
    data = np.load("../deepxde/examples/dataset/Burgers.npz")
    t, x, exact = data["t"], data["x"], data["usol"].T
    xx, tt = np.meshgrid(x, t)
    X = np.vstack((np.ravel(xx), np.ravel(tt))).T
    y = exact.flatten()[:, None]
    return X, y


def pde(x, y):
    dy_x = dde.grad.jacobian(y, x, i=0, j=0)
    dy_t = dde.grad.jacobian(y, x, i=0, j=1)
    dy_xx = dde.grad.hessian(y, x, i=0, j=0)
    return dy_t + y * dy_x - 0.01 / np.pi * dy_xx
geom = dde.geometry.Interval(-1, 1)
timedomain = dde.geometry.TimeDomain(0, 0.99)
# define Geometry and time domain,and we combine both the domain using GeometryXTime
geomtime = dde.geometry.GeometryXTime(geom, timedomain) 
bc = dde.DirichletBC(geomtime, lambda x: 0, lambda _, on_boundary: on_boundary)
ic = dde.IC(
    geomtime, lambda x: -np.sin(np.pi * x[:, 0:1]), lambda _, on_initial: on_initial
)
data = dde.data.TimePDE(
    geomtime, pde, [bc, ic], num_domain=2540, num_boundary=80, num_initial=160
)
net = dde.maps.FNN([2] + [20] * 3 + [1], "tanh", "Glorot normal")
model = dde.Model(data, net)
# Now, we have the PDE problem and the network. We bulid a Model and choose the optimizer and learning rate
model.compile("adam", lr=1e-3)

# We then train the model for 15000 iterations:
model.train(epochs=15000)
# After we train the network using Adam, we continue to train the network using L-BFGS to achieve a smaller loss:
model.compile("L-BFGS")
losshistory, train_state = model.train()

dde.saveplot(losshistory, train_state, issave=True, isplot=True)
X, y_true = gen_testdata()
y_pred = model.predict(X)
f = model.predict(X, operator=pde)
print("Mean residual:", np.mean(np.absolute(f)))
print("L2 relative error:", dde.metrics.l2_relative_error(y_true, y_pred))
np.savetxt("test.dat", np.hstack((X, y_true, y_pred)))
Mean residual: 0.033188015
L2 relative error: 0.17063112901692742
%matplotlib notebook
import matplotlib.pyplot as plt
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.plot3D(X[:,0].reshape(-1),X[:,1].reshape(-1),y_true.reshape(-1),'red')
ax.plot3D(X[:,0].reshape(-1),X[:,1].reshape(-1),y_pred.reshape(-1),'blue',alpha=0.5)
plt.show()

2. Burgers RAR

函数定义和上面是一样的,这里地RAR地目的在于不断减小函数拟合地误差到一个指定地误差范围之下。控制误差的大小。

import deepxde as dde
import numpy as np


def gen_testdata():
    data = np.load("../deepxde/examples/dataset/Burgers.npz")
    t, x, exact = data["t"], data["x"], data["usol"].T
    xx, tt = np.meshgrid(x, t)
    X = np.vstack((np.ravel(xx), np.ravel(tt))).T
    y = exact.flatten()[:, None]
    return X, y


def pde(x, y):
    dy_x = dde.grad.jacobian(y, x, i=0, j=0)
    dy_t = dde.grad.jacobian(y, x, i=0, j=1)
    dy_xx = dde.grad.hessian(y, x, i=0, j=0)
    return dy_t + y * dy_x - 0.01 / np.pi * dy_xx


geom = dde.geometry.Interval(-1, 1)
timedomain = dde.geometry.TimeDomain(0, 0.99)
geomtime = dde.geometry.GeometryXTime(geom, timedomain)

bc = dde.DirichletBC(geomtime, lambda x: 0, lambda _, on_boundary: on_boundary)
ic = dde.IC(
    geomtime, lambda x: -np.sin(np.pi * x[:, 0:1]), lambda _, on_initial: on_initial
)

data = dde.data.TimePDE(
    geomtime, pde, [bc, ic], num_domain=2500, num_boundary=100, num_initial=160
)
net = dde.maps.FNN([2] + [20] * 3 + [1], "tanh", "Glorot normal")
model = dde.Model(data, net)

model.compile("adam", lr=1.0e-3)
model.train(epochs=10000)
model.compile("L-BFGS")
model.train()
X = geomtime.random_points(100000)
err = 1
while err > 0.005:
    f = model.predict(X, operator=pde)
    err_eq = np.absolute(f)
    err = np.mean(err_eq)
    print("Mean residual: %.3e" % (err))

    x_id = np.argmax(err_eq)
    print("Adding new point:", X[x_id], "\n")
    data.add_anchors(X[x_id])
    early_stopping = dde.callbacks.EarlyStopping(min_delta=1e-4, patience=2000)
    model.compile("adam", lr=1e-3)
    model.train(epochs=10000, disregard_previous_best=True, callbacks=[early_stopping])
    model.compile("L-BFGS")
    losshistory, train_state = model.train()
dde.saveplot(losshistory, train_state, issave=True, isplot=True)

X, y_true = gen_testdata()
y_pred = model.predict(X)
print("L2 relative error:", dde.metrics.l2_relative_error(y_true, y_pred))
np.savetxt("test.dat", np.hstack((X, y_true, y_pred)))
L2 relative error: 0.009516824350586142
%matplotlib notebook
import matplotlib.pyplot as plt
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.plot3D(X[:,0].reshape(-1),X[:,1].reshape(-1),y_true.reshape(-1),'red')
ax.plot3D(X[:,0].reshape(-1),X[:,1].reshape(-1),y_pred.reshape(-1),'blue',alpha=0.5)
plt.show()

4. summary

  1. 迭代更多的次数,在方程拟合的过程中可能会获得更好的结果,但是也可能陷入一些局部最优值,LR的影响还是挺大的
  2. 两次对比,第二次固定一个最大容忍误差值进行判断,最终得到一个误差非常小的模型。这对于PINN的训练而言似乎是一个可行的方案,因为一般不存在过拟合的问题。
  3. 注意我们的PINN方法是一个无监督学习过程。
  4. 对于二维的Burgers方程的训练和预测速度都还是非常快的,尽管我的GPU非常普通。暂时对于我是可以容忍的!!!
  • 10
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 23
    评论
首先,我们需要导入所需的库:numpy、matplotlib和scipy。 ```python import numpy as np import matplotlib.pyplot as plt from scipy.integrate import solve_ivp ``` 然后,我们定义Burgers方程及其初始条件。 ```python def burgers(t, u): return np.concatenate((u[1:], -u[1:] * (u[1:] - u[:-1]) / dx + nu * (u[2:] - 2 * u[1:-1] + u[:-2]) / dx ** 2)) nx = 101 L = 2 * np.pi dx = L / (nx - 1) nu = 0.07 nt = 100 dt = 0.1 x = np.linspace(0, L, nx) u0 = -np.sin(x) ``` 在这里,我们使用了solve_ivp函数来决初始值问题。我们将方程、初始条件、时间间隔和时间步数作为参数传递给该函数。 ```python u = solve_ivp(burgers, (0, nt * dt), u0, t_eval=np.linspace(0, nt * dt, nt)) ``` 最后,我们可以绘制结果。 ```python plt.figure(figsize=(8, 6)) plt.plot(x, u0, 'k', lw=2) plt.plot(x, u.y[:, -1], 'r', lw=2) plt.xlabel('x') plt.ylabel('u') plt.legend(['Initial', 'Solution']) plt.grid(True) plt.show() ``` 完整的代码如下: ```python import numpy as np import matplotlib.pyplot as plt from scipy.integrate import solve_ivp def burgers(t, u): return np.concatenate((u[1:], -u[1:] * (u[1:] - u[:-1]) / dx + nu * (u[2:] - 2 * u[1:-1] + u[:-2]) / dx ** 2)) nx = 101 L = 2 * np.pi dx = L / (nx - 1) nu = 0.07 nt = 100 dt = 0.1 x = np.linspace(0, L, nx) u0 = -np.sin(x) u = solve_ivp(burgers, (0, nt * dt), u0, t_eval=np.linspace(0, nt * dt, nt)) plt.figure(figsize=(8, 6)) plt.plot(x, u0, 'k', lw=2) plt.plot(x, u.y[:, -1], 'r', lw=2) plt.xlabel('x') plt.ylabel('u') plt.legend(['Initial', 'Solution']) plt.grid(True) plt.show() ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 23
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

留小星

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

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

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

打赏作者

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

抵扣说明:

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

余额充值