创建一维数组,其中元素是存储函数的二维 numpy 数组的总和

Creating 1D array where elements are the sum of a 2D numpy array of stored functions

如果之前有人问过这个问题,我深表歉意。我是 python 和一般编程的新手,所以如果有人问我,请指出正确的方向。我正在使用 python 3.7.

我有一个二维 numpy 数组,其中每个元素都是一个存储函数。我想在每一列中添加函数以获得一维数组,其中一维数组的元素是单个函数。我不确定为什么 np.sum() 函数无法执行此操作。我得到一个一维数组,但函数仅来自 "npwavefxns" 数组的第一列。

[[X00,X01,...,X0n]

[X10, X11,...,X1n]

...

[Xn0,Xn1,...[Xnn]]

-> [[X00+X10+...+Xn0, X01+X11+...+Xn1, X0n+X1n+...+Xnn]]

np.sum() 函数似乎适用于整数,所以我不确定为什么当元素是函数时它不起作用。下面给出了我的代码示例。如果此代码正常工作,我怀疑在使用“4”基函数时会得到这 4 个图。

from scipy import mat, matrix, integrate
from scipy.integrate import quad
import numpy as np
from numpy import linalg as la
import os
from matplotlib import pyplot as plt

# Defining variables and functions
MP=float(9.10938356e-31)    #mass of electron in kg
WL=float(1e-10) #length of well in meters
CON=float(1.60218e-19)  #constant height in joules
Hb = float(1.054571726e-34) #reduced planck's constant in J s
NB=int(input("Number of basis functions ")) #define number of basis sets to be used

#####Potential energy of initial state#####
PE=[]
for j in range(1,NB+1):
    alist=[]
    for k in range(1,NB+1):
        F1=integrate.quad(lambda x:((2/WL)*np.sin((k*np.pi*x)/WL)*
        ((-CON)*np.sin(np.pi*x/WL))*np.sin((j*np.pi*x)/WL)),0,WL)[0]
        if F1 < -1e-25:
            F1=F1
        elif F1 > 1e-25:
            F1=F1
        else:
            F1=0
        alist.append(F1)
    PE.append(alist)
PEarray=np.asarray(PE)

#####Kinetic Energy of initial state#####
KE=[]
for j in range(1,NB+1):
    blist=[]
    for k in range(1,NB+1):
        F2=integrate.quad(lambda x:(((((Hb**2)*(j**2)*(np.pi**2))/(MP*(WL**3)))*
        ((np.sin(j*np.pi*x/WL))*(np.sin(k*np.pi*x/WL))))),0,WL)[0]
        if F2 < -1e-25:
            F2=F2
        elif F2 > 1e-25:
            F2=F2
        else:
            F2=0
        blist.append(F2)
    KE.append(blist)
KEarray=np.asarray(KE)

#####Adding PE and KE to give the full hamiltonian of the initial state#####
#####Then convert the list to a numpy array#####
sum=[0]*NB
for i in range(NB):
    sum[i]=[0]*NB
for y in range(len(PEarray)):
    for z in range(len(PEarray[0])):
        sum[y][z]=PEarray[y][z]+KEarray[y][z]
npsum=np.asarray(sum)

EVal, EVec=la.eigh(npsum)

wavefxns=[]
for j in range(1,NB+1):
    clist=[]
    for k in range(1,NB+1):
        F3 = (lambda x: ((EVec.item(k-1, j-1))*
        (np.sin((((k+1)*np.pi)/WL)*x))))
        clist.append(F3)
    wavefxns.append(clist)
npwavefxns=np.asarray(wavefxns)

EQS=[]
for j in range(0,NB):
    F4=np.sum(npwavefxns.item(j))
    EQS.append(F4)
npEQS=np.asarray(EQS)

for j in range(0,NB):
    wfxn1=(lambda x: ((npEQS.item(j))(x)))
    plt.xlabel("Box length")
    plt.ylabel("energy")
    x = np.linspace(0,WL,500)
    plt.plot(x, wfxn1(x), '--m')
    plt.show()

好的,据我所知,您运行遇到了两个问题。其中之一是您试图接管一组函数(以及与 npwavefxns 相关的所有其他内容)的总和。

另一个问题是一个真正的问题,结果导致返回到您分配给 F3lambda。简短的版本是您在 lambda 中使用了循环变量 jklambdas "capture" 变量,以便您稍后调用 lambda 时可以使用它们。要注意的是,这些变量的值可能会发生变化,就像循环的每次迭代中 jk 的值一样。当你真正调用那些 lambdas 时,它们最终都使用了完全相同的 jk 的值(在这种情况下,这是它们各自在最后一个循环)。

我使用称为闭包的技术解决了 lambda 问题(请参阅 this thread for more details)。简短的解释是它允许您显式捕获变量的当前值以备后用。

无论如何,这是您的代码的完整工作示例。 wavefxns=[] 行上方的所有内容都保持不变:

from scipy import mat, matrix, integrate
from scipy.integrate import quad
import numpy as np
from numpy import linalg as la
import os
from matplotlib import pyplot as plt

# Defining variables and functions
MP=float(9.10938356e-31)    #mass of electron in kg
WL=float(1e-10) #length of well in meters
CON=float(1.60218e-19)  #constant height in joules
Hb = float(1.054571726e-34) #reduced planck's constant in J s
NB=int(input("Number of basis functions ")) #define number of basis sets to be used

#####Potential energy of initial state#####
PE=[]
for j in range(1,NB+1):
    alist=[]
    for k in range(1,NB+1):
        F1=integrate.quad(lambda x:((2/WL)*np.sin((k*np.pi*x)/WL)*
        ((-CON)*np.sin(np.pi*x/WL))*np.sin((j*np.pi*x)/WL)),0,WL)[0]
        if F1 < -1e-25:
            F1=F1
        elif F1 > 1e-25:
            F1=F1
        else:
            F1=0
        alist.append(F1)
    PE.append(alist)
PEarray=np.asarray(PE)

#####Kinetic Energy of initial state#####
KE=[]
for j in range(1,NB+1):
    blist=[]
    for k in range(1,NB+1):
        F2=integrate.quad(lambda x:(((((Hb**2)*(j**2)*(np.pi**2))/(MP*(WL**3)))*
        ((np.sin(j*np.pi*x/WL))*(np.sin(k*np.pi*x/WL))))),0,WL)[0]
        if F2 < -1e-25:
            F2=F2
        elif F2 > 1e-25:
            F2=F2
        else:
            F2=0
        blist.append(F2)
    KE.append(blist)
KEarray=np.asarray(KE)

#####Adding PE and KE to give the full hamiltonian of the initial state#####
#####Then convert the list to a numpy array#####
sum=[0]*NB
for i in range(NB):
    sum[i]=[0]*NB
for y in range(len(PEarray)):
    for z in range(len(PEarray[0])):
        sum[y][z]=PEarray[y][z]+KEarray[y][z]
npsum=np.asarray(sum)

EVal, EVec=la.eigh(npsum)

wavefxns=[]
for j in range(0,NB):
    clist=[]
    for k in range(0,NB):
        F3 = (lambda a,b: (lambda x: ((EVec.item(b-1, a-1)) * (np.sin((((b+1)*np.pi)/WL)*x)))))(j,k)
        clist.append(F3)
    wavefxns.append(clist)

gridspec_kw = {'wspace': 0, 'hspace': 0}
fig,axarr = plt.subplots(NB, sharex=True, squeeze=False, gridspec_kw=gridspec_kw, figsize=(3,7.5))
fig.subplots_adjust(left=0, bottom=0, right=1, top=1)

for j,ax in zip(range(0,NB), axarr.ravel()):
    wfxn = lambda x: np.sum([wavefxns[i][j](x) for i in range(len(wavefxns))], axis=0)
    if j==(NB - 1):
        ax.set_xlabel("Box length")
    ax.set_ylabel("energy")
    x = np.linspace(0,WL,500)
    ax.plot(x, wfxn(x), '--m')

其中(当您 运行 它并输入 4 时)产生输出:

我调整了绘图例程,以便所有波函数都绘制到一个图形上(因此我只有一个图形 copy/paste 进入这个答案)。