使用Python仿真波的叠加

本文介绍了一种使用Python和NumPy库进行波动仿真的方法,通过创建波动类来模拟不同特性的波在空间中的传播和叠加,展示了相干相长和相干相消的现象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

1.波动知识
波动是一种传递能量的方式,根据物理学的知识,波动具有独立性,叠加性和相干性。独立性是指当若干个波相遇于同一区域时,可以各自保持自己的特性(频率、振幅和振动方向等),按照原来的传播方向继续前进,彼此不受影响。叠加性是指在相遇区域内,介质质点的合位移是各波分别单独传播时在该点引起位移的矢量和。这种叠加性是以独立性为基础的线性叠加。
叠加分为相干叠加和非相干叠加,这取决于各波的特性,以两个沿同一直线的且频率相同简谐波为例,在这里插入图片描述
其中:
中括号括起来的便是干涉项,干涉的结果取决于各波的初始相位,只有具有固定相位差的波才能发生干涉。

2.图像与数组
图像其实就是数组,比如,彩色的图像可以表示为一个三维数组(M,N,C),其中M和N表示分辨率,C表示颜色通道[R,G,B],利用python的numpy库可以很方便地实现对数组的访问和修改,基于这一点,想到了使用一个二维数组(灰度图)表示一个空间,图上每一点代表空间的坐标(x,y),当波在该空间传播时,会引起质点的振动,导致每一点的灰度值发生变化(灰度值相当于质点的位移),同时,利用numpy数组的广播机制可以轻松实现波的叠加。

正文:

需要的库:

import numpy as np
from matplotlib import pyplot as plt
from scipy import sparse

没有的话可以使用pip安装(pip install xxx)。

首先编写描述波的类,初始化函数要覆盖波的特性:振幅、频率、波数、初始相位。我们用1,2,3,4表示波源的位置,1是左上角,2是右上角,3是右下角,4是左下角。我们使用函数sparse.coo_matrix(space)获取空间上每一点的坐标(这里需要用到元组拆包的技巧),获取到坐标后,计算每一点与波源的距离,然后计算波源在该点引起的振动,振动的大小与该点灰度值的大小一一对应,也就是说,颜色越深的点,位移越大。
此外,波还随时间变化,我们定义一个函数,当调用这个函数时,时间会自加若干秒,同时质点空间振动的分布发生改变。

class Wave():
    def __init__(self,A,W,K,φ,corner):
        self.A = A
        self.W = W
        self.K = K
        self.φ= φ
        self.corner = corner
        self.t = 0.0
        self.space = None
        
    def spread(self,space):
        self.space = space.copy()
        coo = sparse.coo_matrix(space)
        if self.corner == 1:
            for (x,y) in zip(coo.col,coo.row):
                r = (x**2+y**2)**(1/2)
                self.space[y][x] = self.A*np.cos(self.W*self.t-self.K*r+self.φ) +  self.A             
        elif self.corner == 2:
            for (x,y) in zip(coo.col,coo.row):
                r = ((space.shape[1]-x)**2+y**2)**(1/2)
                self.space[y][x] = self.A*np.cos(self.W*self.t-self.K*r+self.φ) +  self.A            
        elif self.corner == 3:
            for (x,y) in zip(coo.col,coo.row):
                r = ((space.shape[1]-x)**2+(space.shape[0]-y)**2)**(1/2)
                self.space[y][x] = self.A*np.cos(self.W*self.t-self.K*r+self.φ) +  self.A 
        elif self.corner == 4:
            for (x,y) in zip(coo.col,coo.row):
                r = (x**2+(space.shape[0]-y)**2)**(1/2)
                self.space[y][x] = self.A*np.cos(self.W*self.t-self.K*r+self.φ) +  self.A 
        else:
            raise Exception('Corner must be 1,2,3,4,please check your param')
            
    def move(self):
        self.t += 5
        self.spread(self.space)

定义一个空间(100*100),初始化四个波,输入各自的参数,让各个波在空间传播,并可视化

space = np.ones(shape=(100,100),dtype='float32')

#振幅、频率、波数、初始相位、波源位置
wave_1 = Wave(100,1*np.pi/3,5,0,1) 
wave_2 = Wave(100,2*np.pi/3,5,0,2) 
wave_3 = Wave(100,3*np.pi/3,5,0,3) 
wave_4 = Wave(100,4*np.pi/3,5,0,4)

for wave in [wave_1,wave_2,wave_3,wave_4]:
	wave.spread(space)
        
while True:
	plt.subplot(2,2,1)
	plt.imshow(wave_1.space)

	plt.subplot(2,2,2)
	plt.imshow(wave_2.space)

	plt.subplot(2,2,4)
	plt.imshow(wave_3.space)

	plt.subplot(2,2,3)
	plt.imshow(wave_4.space)

	for wave in [wave_1,wave_2,wave_3,wave_4]:
		wave.move()
	plt.pause(0.1)

效果如图(实际是动态的)中间形状就像水的波纹,两侧像是山脊。:在这里插入图片描述

利用numpy数组的广播机制可以轻松实现波的叠加:

wave_space = wave_1.space+wave_2.space+wave_3.space+wave_4.space
wave_space /= np.max(wave_space)

效果如图(实际是动态的):可见相干相长的点(颜色较深的点)和相干相消的点(颜色较浅的点)在空间有规律的分布在这里插入图片描述

完整代码如下所示:

import numpy as np
from matplotlib import pyplot as plt
from scipy import sparse

class Wave():
    def __init__(self,A,W,K,φ,corner):
        self.A = A
        self.W = W
        self.K = K
        self.φ= φ
        self.corner = corner
        self.t = 0.0
        self.space = None
             
    def spread(self,space):
        self.space = space.copy()
        coo = sparse.coo_matrix(space)
        if self.corner == 1:
            for (x,y) in zip(coo.col,coo.row):
                r = (x**2+y**2)**(1/2)
                self.space[y][x] = self.A*np.cos(self.W*self.t-self.K*r+self.φ) +  self.A             
        elif self.corner == 2:
            for (x,y) in zip(coo.col,coo.row):
                r = ((space.shape[1]-x)**2+y**2)**(1/2)
                self.space[y][x] = self.A*np.cos(self.W*self.t-self.K*r+self.φ) +  self.A            
        elif self.corner == 3:
            for (x,y) in zip(coo.col,coo.row):
                r = ((space.shape[1]-x)**2+(space.shape[0]-y)**2)**(1/2)
                self.space[y][x] = self.A*np.cos(self.W*self.t-self.K*r+self.φ) +  self.A 
        elif self.corner == 4:
            for (x,y) in zip(coo.col,coo.row):
                r = (x**2+(space.shape[0]-y)**2)**(1/2)
                self.space[y][x] = self.A*np.cos(self.W*self.t-self.K*r+self.φ) +  self.A 
        else:
            raise Exception('Corner must be 1,2,3,4,please check your param')     
            
    def move(self):
        self.t += 5
        self.spread(self.space)
        
if __name__=='__main__':

    space = np.ones(shape=(100,100),dtype='float32')
    
    wave_1 = Wave(100,1*np.pi/3,5,0,1) 
    wave_2 = Wave(100,2*np.pi/3,5,0,2) 
    wave_3 = Wave(100,3*np.pi/3,5,0,3) 
    wave_4 = Wave(100,4*np.pi/3,5,0,4)
    
    for wave in [wave_1,wave_2,wave_3,wave_4]:
        wave.spread(space)
        
    while True:             
        plt.subplot(2,2,1)
        plt.imshow(wave_1.space)
        
        plt.subplot(2,2,2)
        plt.imshow(wave_2.space)
        
        plt.subplot(2,2,4)
        plt.imshow(wave_3.space)
        
        plt.subplot(2,2,3)
        plt.imshow(wave_4.space)
        
        for wave in [wave_1,wave_2,wave_3,wave_4]:
            wave.move()
                    
        plt.pause(0.1)
        
        '''Superposition of waves
        wave_space = wave_1.space+wave_2.space+wave_3.space+wave_4.space
        wave_space /= np.max(wave_space)
        for wave in [wave_1,wave_2,wave_3,wave_4]:
            wave.move()
        plt.imshow(wave_space)
        plt.pause(0.1)
        '''
Python可以用于仿真建模低通滤器,这是一种信号处理技术,主要用于允许低于特定频率的信号通过,同时衰减高于该截止频率的高频成分。利用NumPySciPy等库能够完成这一任务。 ### 实现步骤: 1. **定义采样率和时间向量** 首先需要明确模拟数据的时间分辨率以及对应的离散点数。 2. **生成输入信号** 构造包含多种频率分量的混合测试信号(如正弦叠加),以便观察滤效果。 3. **设计低通滤器** 使用`scipy.signal`模块提供的函数创建巴特沃斯(Butterworth)或其他类型的数字低通滤器,并指定其阶数及归一化后的截至角频率。 4. **应用滤器到原始信号上** 调用`lfilter()`函数对上述合成信号实施实际过滤操作。 5. **绘图比较结果** 借助Matplotlib将原信号及其经过滤之后的新形式分别可视化出来,直观感受高低频分离状况。 以下是示例代码片段: ```python import numpy as np from scipy import signal import matplotlib.pyplot as plt # 参数设置 fs = 1000 # Sampling rate (Hz) t = np.linspace(0, 1, fs, endpoint=False) frequencies = [2, 60] # Signal frequencies in Hz amplitudes = [1, 0.5] x = sum([amp * np.sin(2 * np.pi * freq * t) for amp, freq in zip(amplitudes, frequencies)]) cutoff_freq = 10 # Cutoff frequency of the filter nyquist_rate = fs / 2 normalized_cutoff = cutoff_freq / nyquist_rate b, a = signal.butter(5, normalized_cutoff, btype='low', analog=False) y_filtered = signal.lfilter(b, a, x) plt.figure(figsize=(8, 4)) plt.plot(t[:int(fs*0.2)], x[:int(fs*0.2)], label="Original") plt.plot(t[:int(fs*0.2)], y_filtered[:int(fs*0.2)], label="Filtered", linestyle="--") plt.legend() plt.show() ``` 此段程序展示了如何从头开始构建并验证简单的LPF功能。当然,在真实项目里还需要考虑更多因素比如噪声特性分析等等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值