使用Python仿真波的叠加

前言

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)
        '''
  • 3
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值