You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

循环中函数返回数组致if判断报错,求解决(Use a.any()/a.all())

修复中子滴线绘制代码中的数组比较错误

我要绘制原子核的中子滴线(neutron drip line),这条线代表每个原子序数(Z)对应的中子数(N)极限值,超过该值添加中子会使原子核不稳定,表现为分离能为负(分离能是(Z,N)与(Z,N+1)的结合能差值)。

实现步骤:

  • 从A值列表生成Z值数组和N值数组,通过zmin()函数获取Z值,N值由A与Z的差值得到。
  • 遍历每个Z值,递增计算一系列N值的结合能,直到结合能差为负,记录此时的N值,完成所有Z值的处理后绘图。

原代码

import numpy as np
import matplotlib.pyplot as plt

avol = 15.5  # Initializing the coefficients
asurf = 16.8
acol = 0.72
asym = 23

def bind_en (Z, N):  #Defining a function to calculate binding energy 
                    #curve using semi-emperical mass formulae
    if ((Z+N)%2)!=0 and (Z%2)==0:
        apar=0
    elif ((Z+N)%2)==0 and (Z%2)!=0:
        apar=0
    elif ((Z+N)%2)==0 and (Z%2)==0:
        apar=34
    elif ((Z+N)%2)!=0 and (Z%2)!=0:
        apar=-34
          
    b = avol*(Z+N)-asurf*((Z+N)**(2/3))-(acol*Z*(Z-1))/((Z+N)**(1/3))-asym*(((Z+N)-2*Z)**2)/(Z+N)+apar/((Z+N)**(3/4))  
    
    return b/A

def zmin(A):
    z = (A / 2) * (1 / (1 + 0.25 * (A ** (2 / 3)) * (acol / asym)))
    z = int(z)
    return z

A = np.arange(1, 261, 1)
Z = []
N = []
NM=[]

for i in range(len(A)):
    Z.append(zmin(A[i]))
    N.append(A[i]-Z[i])

flag=False

for j in range(len(Z)):
    for k in range(len(N)):
        s=bind_en(Z[j],N[k+1])-bind_en(Z[j],N[k])
        '''if isinstance(s, np.ndarray):
            print("s is an array.")'''
        if s<0:
            NM.append(N[k])
            flag=True
            break         
    if flag:
        break

plt.plot(NM, Z)
plt.xlabel('Number of Neutrons (N)')
plt.ylabel('Number of Protons (Z)')
plt.grid(True)
plt.show()

运行错误信息

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[27], line 45
     42 s=bind_en(Z[j],N[k+1])-bind_en(Z[j],N[k])
     43 '''if isinstance(s, np.ndarray):
     44     print("s is an array.")'''
---> 45 if s<0:
     46     NM.append(N[k])
     47     flag=True

ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

问题原因分析

错误核心在于bind_en函数的返回值:你在函数里返回了b/A,这里的A是全局定义的numpy数组np.arange(1, 261, 1),所以每次调用bind_en都会返回一个长度为260的数组,而非单个数值。后续计算s时自然得到数组,无法直接和0比较,导致报错。

另外原代码的遍历逻辑也有问题:flag=True后直接跳出所有循环,只能处理第一个Z值,无法完成所有Z的计算。

修复后的代码

import numpy as np
import matplotlib.pyplot as plt

avol = 15.5  # 初始化半经验质量公式系数
asurf = 16.8
acol = 0.72
asym = 23

def bind_en(Z, N):  # 计算单个原子核的核子结合能
    A_val = Z + N
    # 简化对能项判断逻辑
    if (A_val % 2) != 0:
        apar = 0
    else:
        apar = 34 if (Z % 2) == 0 else -34
          
    b = (avol * A_val 
         - asurf * (A_val ** (2/3)) 
         - (acol * Z * (Z - 1)) / (A_val ** (1/3)) 
         - asym * ((A_val - 2 * Z) ** 2) / A_val 
         + apar / (A_val ** (3/4)))  
    
    return b / A_val  # 返回单个数值:每个核子的结合能

def zmin(A):
    z = (A / 2) * (1 / (1 + 0.25 * (A ** (2/3)) * (acol / asym)))
    return int(z)

# 提取所有唯一的Z值,避免重复计算
unique_Z = sorted(list(set(zmin(a) for a in np.arange(1, 261, 1))))
NM = []

for z in unique_Z:
    n = z  # 从N=Z开始逐步递增,寻找滴线位置
    while True:
        # 计算中子分离能:S_n = B(Z,N+1) - B(Z,N)
        s = bind_en(z, n+1) - bind_en(z, n)
        if s < 0:
            NM.append(n)
            break
        n += 1

plt.plot(NM, unique_Z)
plt.xlabel('Number of Neutrons (N)')
plt.ylabel('Number of Protons (Z)')
plt.title('Neutron Drip Line')
plt.grid(True)
plt.show()

关键修复点

  1. 修正结合能返回值:将return b/A改为return b/(Z+N),确保返回单个数值而非全局数组。
  2. 简化对能项判断:优化apar的条件逻辑,提升可读性。
  3. 重构遍历逻辑:
    • 提取唯一Z值,避免重复处理相同原子序数。
    • 对每个Z从N=Z开始逐步递增,直到分离能为负,确保所有Z都能找到对应的极限N。
  4. 移除错误终止逻辑:删除原代码中导致提前终止循环的flag,保证遍历完整。

内容的提问来源于stack exchange,提问作者Ashik Lal Krishna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 00:05:06