Python——一维波动方程求解

1、一维波动方程简介

     以线的横振动方程作为一维波动方程的例子,其运动学方程满足:

 

     在上式中为线密度;T为张力;代表强迫力的大小。当没有外力,且线的密度均匀等于,我们可以取,将一维波动方程化简为:

2、一维波动方程的差分解法

     在给定的初始条件:

 

     以及给定的边界条件:

     我们可以使用差分的方法将一维波动方程写为两种差分格式:

     第一种差分格式:

     第二种差分格式:   

   两种差分收敛条件:

 

2、问题

     用一种差分格式计算波动方程混合问题:

  1. α=1,h=0.2,计算k=1,2,3,4层的值;
  2. α=1,h=0.05,分别用两种差分格式计算k=1,2,20层的近似值。

 3、程序

#python
import numpy as np
import math as ma
from matplotlib import pyplot as plt
#问题1算法
def n1(a,h,N,v):
    def f1(x,h,t):
        y=ma.sin(x*h*ma.pi)+x*h*t*(1-x*h)
        return y
    def f2(x,h):
        y=ma.sin(x*h*ma.pi)
        return y
    def f3(x1,x2,x3):
        y=x1+x2-x3
        return y
    t=a*h/v
    y_t=np.zeros((N-1,N))
    for i in range(N-1):
        if i==0:
            for j in range(N-1):
                y_t[i,j]=f2(j,h)
        if i==1:
            for j in range(N-1):
                y_t[i,j]=f1(j,h,t)
        if i>1:
            for j in range(1,N-1):
                y_t[i,j]=f3(y_t[i-1,j+1],y_t[i-1,j-1],y_t[i-2,j])
    return y_t
#问题2算法
def n2(a,h,N,v):
    def f1(x,h,t):
        y=1/2*(ma.sin((x+1)*h*ma.pi)+ma.sin((x-1)*h*ma.pi)+x*h*t*(1-x*h))
        return y
    def f2(x,h):
        y=ma.sin(x*h*ma.pi)
        return y
    def f3(x1,x2,x3):
        y=x1+x2-x3
        return y
    t=a*h/v;
    y_t=np.zeros((N-1,N));
    for i in range(N-1):
        if i==0:
            for j in range(N-1):
                y_t[i,j]=f2(j,h);
        if i==1:
            for j in range(1,N-1):
                y_t[i,j]=f1(j,h,t)
        if i>1:
            for j in range(1,N-2):
                y_t[i,j]=f3(y_t[i-1,j+1],y_t[i-1,j-1],y_t[i-2,j])
    return y_t
#问题1答案
a1=1;h1=0.2;N1=6;v1=1;
y1=n1(a1,h1,N1,v1)
#问题2答案
a2=1;h2=0.05;v2=1;N2=21
y2=n1(a2,h2,N2,v2)
a3=1;h3=0.05;v3=1;N3=21
y3=n2(a3,h3,N3,v3);
#结果展示
x1=[];t1=[]
for n in range(0,6):
    x1.append(n)
for m in range(0, 5):
    t1.append(m*0.05)
x1=np.array(x1)
t1=np.array(t1)
x,y=np.meshgrid(x1,t1)
z=y1
d3=plt.axes(projection='3d')
d3.plot_surface(x,y,z,cmap='rainbow')
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
d3.set_zlabel('Z(y方向位移)/m')
d3.set_xlabel('X(位置)/m')
d3.set_ylabel('T(时间)/s')
d3.set_title('一维波动方程')
plt.show()
x2=[];t2=[];t_m2=a2*h2/v2
for n in range(0,N2):
    x2.append(n)
for m in range(0,N2-1):
    t2.append(m*t_m2)
x2=np.array(x2)
t2=np.array(t2)
x,y=np.meshgrid(x2,t2)
z=y2
d3=plt.axes(projection='3d')
d3.plot_surface(x,y,z,cmap='rainbow')
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
d3.set_zlabel('Z(y方向位移)/m')
d3.set_xlabel('X(位置)/m')
d3.set_ylabel('T(时间)/s')
d3.set_title('一维波动方程')
plt.show()
x3=[];t3=[];t_m3=a3*h2/v2
for n in range(0,N3):
    x3.append(n)
for m in range(0,N3-1):
    t3.append(m*t_m3)
x3=np.array(x3)
t3=np.array(t3)
x,y=np.meshgrid(x3,t3)
z=y3
d3=plt.axes(projection='3d')
d3.plot_surface(x,y,z,cmap='rainbow')
plt.rcParams['font.sans-serif']=['SimHei']
plt.rcParams['axes.unicode_minus'] = False
d3.set_zlabel('Z(y方向位移)/m')
d3.set_xlabel('X(位置)/m')
d3.set_ylabel('T(时间)/s')
d3.set_title('一维波动方程')
plt.show()

4、结果

Fig1.问题1

Fig2.问题2-1

Fig3.问题2-2

Fig4.N=40

Fig5.N=60

 

  • 2
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
好的,以下是使用基于物理神经网络(PINN)方法求解一维Sod问题的代码示例。在这个示例中,我们使用Python编写代码,使用TensorFlow库来实现PINN方法: 首先,导入必要的库: ```python import tensorflow as tf import numpy as np import matplotlib.pyplot as plt ``` 接下来,我们定义Sod问题的初始条件和边界条件: ```python # 定义Sod问题的初始条件和边界条件 # 初始条件 rho_left = 1.0 # 左侧密度 u_left = 0.0 # 左侧速度 p_left = 1.0 # 左侧压力 rho_right = 0.125 # 右侧密度 u_right = 0.0 # 右侧速度 p_right = 0.1 # 右侧压力 # 定义计算区域 x_start = 0.0 # 区域起点 x_end = 1.0 # 区域终点 # 边界条件 def bc(x, t, input_x, u_model, rho_model, p_model): # 左边界条件 if x[0] == x_start: return np.array([rho_left, u_left, p_left]) # 右边界条件 elif x[0] == x_end: return np.array([rho_right, u_right, p_right]) # 内部点 else: x_tf = tf.convert_to_tensor(x) u = u_model(x_tf, t) rho = rho_model(x_tf, t) p = p_model(x_tf, t) return np.array([rho, u, p]) ``` 然后,我们定义神经网络模型和PINN方法: ```python # 定义神经网络模型 class SodNet(tf.keras.Model): def __init__(self): super(SodNet, self).__init__() self.dense1 = tf.keras.layers.Dense(64, activation='tanh') self.dense2 = tf.keras.layers.Dense(64, activation='tanh') self.dense_rho = tf.keras.layers.Dense(1) self.dense_u = tf.keras.layers.Dense(1) self.dense_p = tf.keras.layers.Dense(1) def call(self, inputs): x = self.dense1(inputs) x = self.dense2(x) rho = self.dense_rho(x) u = self.dense_u(x) p = self.dense_p(x) return rho, u, p # 定义PINN方法 class SodPINN: def __init__(self, net): self.net = net # 定义损失函数 def loss_fn(self, x, t): x_tf = tf.convert_to_tensor(x) with tf.GradientTape(persistent=True) as tape: tape.watch(x_tf) rho, u, p = self.net(x_tf) u_t = tape.gradient(u, t) rho_t = tape.gradient(rho, t) p_t = tape.gradient(p, t) u_x = tape.gradient(u, x_tf) rho_x = tape.gradient(rho, x_tf) p_x = tape.gradient(p, x_tf) p_x2 = tape.gradient(p_x, x_tf) a = tf.sqrt(p_x2 / rho + 1e-6) f_u = rho * a f_rho = u * rho_x + rho * u_x f_p = u * p_x + gamma * p * u_x loss = tf.reduce_mean(tf.square(rho_t + f_rho) + tf.square(u_t + f_u) + tf.square(p_t + f_p)) return loss # 定义训练函数 def train(self, x_data, t_data, epochs=1000, lr=0.001): optimizer = tf.optimizers.Adam(lr) for epoch in range(epochs): with tf.GradientTape() as tape: loss = self.loss_fn(x_data, t_data) grads = tape.gradient(loss, self.net.trainable_variables) optimizer.apply_gradients(zip(grads, self.net.trainable_variables)) if epoch % 100 == 0: print('Epoch {}/{}: Loss = {}'.format(epoch, epochs, loss.numpy())) ``` 最后,我们使用上述定义的模型和方法来求解Sod问题: ```python # 定义计算区域 x = np.linspace(x_start, x_end, 1000) t = np.linspace(0.0, 0.2, 100) # 创建神经网络模型和PINN方法 net = SodNet() pinn = SodPINN(net) # 训练模型 pinn.train(x, t, epochs=5000) # 使用模型求解Sod问题 x_test = np.linspace(x_start, x_end, 100) t_test = np.linspace(0.0, 0.2, 100) x_test, t_test = np.meshgrid(x_test, t_test) u_pred = net(tf.convert_to_tensor(np.hstack((x_test.flatten()[:, None], t_test.flatten()[:, None])), dtype=tf.float32))[1].numpy().reshape(*x_test.shape) # 绘制结果 plt.figure(figsize=(10, 6)) plt.pcolor(x_test, t_test, u_pred, cmap='jet') plt.colorbar() plt.xlabel('x') plt.ylabel('t') plt.title('Sod Problem') plt.show() ``` 这样,就可以使用基于物理神经网络(PINN)方法求解一维Sod问题了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Eyu.sir

谢谢。

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

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

打赏作者

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

抵扣说明:

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

余额充值