AI摘要:本文讨论了环形活塞声场的计算和仿真。环形活塞声场可以视为大圆形活塞减去小圆形活塞,通过积分计算得到声场表达式。文章还介绍了指向性函数的计算方法,并提供了Python代码进行仿真,绘制了指向性图。最后,文章展示了仿真结果的图像。

Powered by AISummary.

超声——环形活塞声场

远场声压

环形活塞场可以看做是大圆形活塞减去小圆形活塞。

根据圆形活塞声场的推导远场声压公式,有:

$p=j\frac{\rho_0C_0k}{2\pi r} u_a e^{j(wt-kr)} \int \sigma d\sigma \int e^{jk\sigma sin\theta cos\varphi}d\varphi$,其中σ的积分范围为0~a,φ的范围为0~2π。

假设外径是a2,内径是a1,则σ的积分范围为a1~a2。则可以看成是0~a2的积分减去0~a1的积分。

$p_{a1}= j\frac{\rho_0wa_1^2}{2 r} u_a e^{j(wt-kr)}\frac{2J_1(ka_1\sin\theta)}{ka_1\sin\theta}=j\frac{\rho_0w}{r} u_a e^{j(wt-kr)}\frac{a_1J_1(ka_1\sin\theta)}{k\sin\theta}$

$p_{a2}= j\frac{\rho_0wa_2^2}{2 r} u_a e^{j(wt-kr)}\frac{2J_1(ka_2\sin\theta)}{ka_2\sin\theta}=j\frac{\rho_0w}{r} u_a e^{j(wt-kr)}\frac{a_2J_1(ka_2\sin\theta)}{k\sin\theta}$

两者差为:

$p=j\frac{\rho_0w}{r} u_a e^{j(wt-kr)}\frac{[a_2J_1(ka_2\sin\theta)-a_1J_1(ka_1\sin\theta)]}{k\sin\theta}$

指向性

$D(\theta)=\frac{P_a(\theta)}{P_a(\theta)|_{\theta=0}}=\frac{\frac{[a_2J_1(ka_2\sin\theta)-a_1J_1(ka_1\sin\theta)]}{k\sin\theta}}{\frac{[a_2J_1(ka_2\sin\theta)-a_1J_1(ka_1\sin\theta)]}{k\sin\theta}|_{\theta=0}}$

θ=0时,$\frac{J_1(0)}{0}=\frac{1}{2}$

$P_a(\theta)|_{\theta=0}=P_{a_2}(\theta)|_{\theta=0}-P_{a_1}(\theta)|_{\theta=0}=j\frac{\rho_0w}{r} u_a e^{j(wt-kr)}\frac{a_2^2}{2}-j\frac{\rho_0w}{r} u_a e^{j(wt-kr)}\frac{a_1^2}{2}=j\frac{\rho_0w}{r} u_a e^{j(wt-kr)}\frac{a_2^2-a_1^2}{2}$

则上式为:

$D(\theta)=|\frac{\frac{2[a_2J_1(ka_2\sin\theta)-a_1J_1(ka_1\sin\theta)]}{k\sin\theta}}{a_2^2-a_1^2}|=|\frac{2a_2J_1(ka_2\sin\theta)-2a_1J_1(ka_1\sin\theta)}{k\sin\theta(a_2^2-a_1^2)}|$

仿真

import numpy as np
import matplotlib.pyplot as plt
from scipy.special import j1  # 导入一阶贝塞尔函数

# %%
def calculate_D(k, a1, a2, start=-np.pi / 2, stop=np.pi / 2, num=1000):
    """
    计算指向性函数
    参数:
        k: 波数
        a1: 半径1
        a2: 半径2
        start: 起始角度(默认 -π/2)
        stop: 终止角度(默认 π/2)
        num: 采样点数
    返回:
        theta数组和D数组
    """
    theta = np.linspace(start, stop, num)
    numerator = 2 * a2 * j1(k * a2 * np.sin(theta)) - 2 * a1 * j1(k * a1 * np.sin(theta))
    denominator = k * np.sin(theta) * (a2 ** 2 - a1 ** 2)
    # 处理分母为0的情况(使用掩码)
    mask = np.abs(denominator) < 1e-10
    D = np.zeros_like(theta)
    D[~mask] = np.abs(numerator[~mask] / denominator[~mask])
    D[mask] = 0  # 这里简单设为0,实际可根据极限情况调整
    return theta, D

# %%
# 创建极坐标绘图画布
fig = plt.figure()
ax = fig.add_subplot(111, projection='polar')  # 通过projection='polar'创建极坐标系

# 计算并处理数据
theta, D = calculate_D(k=3, a1=0.5, a2=1.0)  # 修正参数传递方式
D = np.abs(D)                       # 取绝对值确保指向性值为正


# 绘制极坐标图
ax.plot(theta, D)                    # 在极坐标系中绘制角度-指向性曲线
ax.set_xlabel(r'$\theta$')          # 设置角度轴标签,使用LaTeX数学符号
ax.set_title(r'$ka=3$', loc='left')  # 左对齐标题,显示当前ka乘积值
ax.grid(True)                       # 开启极坐标网格
plt.show()                           # 显示完整图形

# %%
# 绘图
fig, axes = plt.subplots(2, 2, figsize=(12, 12),  # 新增figsize参数调整整体尺寸
                        subplot_kw={'projection': 'polar'})
# 固定 a1 和 a2 的值
a1 = 0.5
a2 = 1.0
k_values = [1, 3, 4, 10]

for ax, k in zip(axes.ravel(), k_values):
    # 修正参数传递,传入 k、a1 和 a2
    theta, D = calculate_D(k=k, a1=a1, a2=a2)
    D = np.abs(D)
    ax.plot(theta, D)
    ax.set_title(f'k={k}', pad=15, loc='left')  # 修改标题显示 k 值
    ax.grid(True)

plt.tight_layout()
plt.show()



# %%
# 新增笛卡尔坐标系绘图
plt.figure(figsize=(8, 6))  # 新建画布
# 定义 ka_values
ka_values = [1, 3, 4, 10]
# 固定 a1 和 a2 的值
a1 = 0.5
a2 = 1.0

for ka in ka_values:
    # 计算 k 值,假设 a = 1
    k = ka
    # 修正参数传递,传入 k、a1 和 a2
    theta, D = calculate_D(k=k, a1=a1, a2=a2, start=0.0001, stop=np.pi*2, num=1000)
    x = np.abs(ka * np.sin(theta))
    plt.plot(x, D, label=f'ka={ka}')
   
    # 新增过零点检测
    zero_crossings = np.where(np.diff(np.sign(D)))[0]  # 检测符号变化点
    if len(zero_crossings) > 0:
        x_zeros = x[zero_crossings] + np.diff(x)[zero_crossings] * (-D[zero_crossings]/(D[zero_crossings+1] - D[zero_crossings]))
        plt.scatter(x_zeros, np.zeros_like(x_zeros), color='red', marker='x', s=50, zorder=5, label='Zero Crossing')
        
        # 新增数值标注
        for xz in x_zeros:
            plt.text(xz, -0.05, f'{xz:.2f}',  # 向下偏移0.05避免重叠
                    ha='center', va='top', 
                    rotation=45, fontsize=8,
                    color='red')

# 添加图例去重处理
handles, labels = plt.gca().get_legend_handles_labels()
by_label = dict(zip(labels, handles))
plt.xlabel(r'kasin($\theta$)')
plt.ylabel(r'$\frac{2J_1(kasin(\theta))}{kasin(\theta)}$', rotation=0)
plt.legend(by_label.values(), by_label.keys())
plt.grid(True)  
plt.tight_layout()
plt.show()

指向性图如下所示。

近场声压

参考圆形活塞声场的处理,不是一般性的,研究的是中心轴上的声场,即x轴。观察点P在x轴上,不再是xoz平面上。则θ=0。

近场时,r不是远大于a,使用z表示r。

$p=j\frac{\rho_0C_0k}{2\pi h}\int dQ_0e^{j(wt-kh)}=j\frac{\rho_0C_0k}{2\pi h} \int u_a dS e^{j(wt-kh)}=j\frac{\rho_0C_0k}{2\pi h} u_a e^{j(wt-kh)} \int dS $

这里环元面积变为外径圆和内径圆的差:$p=j\frac{\rho_0C_0k}{2\pi h} u_a e^{j(wt-kh)}\int_{a_1}^{a_2} 2\pi\sigma d\sigma$

那么环元到观察点的距离分别为:(z为轴向的圆点到观察点的距离)

$h_1=\sqrt{z^2+{a_1}^2}$

$h_2=\sqrt{z^2+{a_2}^2}$

由于$dS=2\pi\sigma d\sigma=2\pi h\partial h$,σ=a1时,h=h1;σ=a2时,h=h2。

故p为:

$p=j\frac{\rho_0C_0k}{2\pi h} u_a e^{j(wt-kh)}\int_0^{a} 2\pi\sigma d\sigma=j\rho_0C_0ku_ae^{jwt}\int_{h_1}^{h_2}e^{-jkh}dh$

$p=j\rho_0C_0ku_ae^{jwt}[\frac{1}{-jk}e^{-jkh}|_z^R]=-\rho_0C_0u_ae^{jwt}[e^{-jkh_2}-e^{-jkh_1}]=-\rho_0C_0u_ae^{jwt}[e^{-jk \sqrt{z^2+{a_2}^2}}-e^{-jk \sqrt{z^2+{a_1}^2}}]$

仿真

# 定义常量(水介质)
rho0 = 998  # 水密度(kg/m³)
C0 = 1480  # 水中声速(m/s)
ua = 1  # 速度幅值(假设值)
f = 10e3  # 频率(Hz)
w = 2 * np.pi * f  # 角频率
k = 2 * np.pi * f / C0  # 波数

# 半径假设值
a1 = 0.5
a2 = 1

def near_field_pressure(z, k, a1, a2):
    """
    根据给定的近场声压公式计算声压
    :param z: 轴向距离
    :param k: 波数
    :param a1: 半径1
    :param a2: 半径2
    :return: 声压值
    """
    h1 = np.sqrt(z ** 2 + a1 ** 2)
    h2 = np.sqrt(z ** 2 + a2 ** 2)
    p = -rho0 * C0 * ua * np.exp(1j * w * 0) * (np.exp(-1j * k * h2) - np.exp(-1j * k * h1))
    return p

# 轴向距离范围(调整为更适合水中高频的尺度)
z_values = np.linspace(0.1, 50, 1000)  # 从0.1mm到10mm

# 计算声压
pressure_values = np.array([near_field_pressure(z, k, a1, a2) for z in z_values])
pressure_magnitude = np.abs(pressure_values)

# 找到最后一个极大值的索引
diff_signal = np.diff(np.sign(np.diff(pressure_magnitude)))
maxima_indices = np.where(diff_signal == -2)[0] + 1  # 极大值点索引
if len(maxima_indices) > 0:
    last_max_index = maxima_indices[-1]
    last_max_x = z_values[last_max_index]
    last_max_y = pressure_magnitude[last_max_index]
    print(f"最后一个极大值的x坐标: {last_max_x}")
    print(f"最后一个极大值的y坐标: {last_max_y}")

# 绘图
plt.figure(figsize=(10, 6))  # 调整图表大小
plt.plot(z_values, pressure_magnitude)

# 标记最后一个极大值点
if len(maxima_indices) > 0:
    # 绘制极大值点
    plt.scatter(last_max_x, last_max_y, color='r', marker='o', s=80)
    
    # 在右侧添加文本注释
    plt.annotate(
        f'({last_max_x:.2f}m, {last_max_y/1e6:.2f}MPa)',
        xy=(last_max_x, last_max_y),
        xytext=(15, 0),  # 文本相对于点的偏移量(向右15个点)
        textcoords='offset points',
        fontsize=10,
        color='red',
        ha='left',  # 水平对齐方式:左对齐
        va='center',  # 垂直对齐方式:居中
        bbox=dict(boxstyle='round,pad=0.3', fc='yellow', alpha=0.7)  # 添加黄色半透明背景
    )

plt.xlabel('Axial Distance z (m)')
plt.ylabel('Sound Pressure Magnitude (MPa)')
plt.title('Near - field Sound Pressure Distribution')
plt.grid(True)
plt.tight_layout()  # 确保标签不被截断
plt.show()

Last modification:June 2, 2025
If you think my article is useful to you, please feel free to appreciate