对于具有多个变量的循环-Python
我试图编写一个特定的算法,称为Verlet算法,它基本上会在每次算法运行时更新某些变量的值,称为x、v和E对于具有多个变量的循环-Python,python,arrays,algorithm,list,for-loop,Python,Arrays,Algorithm,List,For Loop,我试图编写一个特定的算法,称为Verlet算法,它基本上会在每次算法运行时更新某些变量的值,称为x、v和E import matplotlib.pyplot as plt import numpy as np # set constants k = 1 m = 1 #Set the number of iterations to be used in the for loop no_of_iterations=1001 # make arrays to define the data
import matplotlib.pyplot as plt
import numpy as np
# set constants
k = 1
m = 1
#Set the number of iterations to be used in the for loop
no_of_iterations=1001
# make arrays to define the data
t = np.zeros(no_of_iterations)
x = np.zeros(no_of_iterations)
v = np.zeros(no_of_iterations)
E = np.zeros(no_of_iterations)
# set initial conditions
t[0] = 0
x[0] = 0
v[0] = 1
E[0] = 0
# make arrays to store data
x1=[]
v1=[]
E1=[]
'''N = 4 Loops'''
#loop for dt = 0.1,N = 4,j=1
for N in range(1,5,1):
for i in range(1,no_of_iterations):
j = 1
x[0]= np.sin((np.pi*j*k)/(N+1))
t_max = 100.0
dt = t_max/no_of_iterations #time step
t[i] = dt * i
v[i] = v[i-1] - ((dt *k/m*(x[N]-x[N-1]))/2)
x[i] = x[i-1] + dt * v[i]
E[i] = ((((v[i])**2)/2) + (x[N]-x[N-1]))
x1.append(x[i])
v1.append(v[i])
E1.append(E[i])
基本上,这是在给定某些初始条件的情况下,将x、v和E的更新值附加到空列表中
现在我的问题来自这样一个事实,我循环的变量有很多不同的值:
N=4,16128:dt=0.1,0.01:j=1,N/2
我应该绘制我创建的每个数组,其示例如下所示:
N=4,dt=0.1,j=1的绘图
(使用我的N=4循环)
一个问题是,我将N=1,2,3,4的所有值存储到一个名为x1的列表中,而实际上我希望有4个单独的列表,每个N值对应一个列表,即x1_N1,x2_N2,x3_N3,x4_N4
但即使我这样做,事情也会很快变得一团糟。例如,对于N=128,我应该有4个图((dt=0.1和j=1),(dt=0.01和j=1),(dt=0.01和j=N/2),(dt=0.01和j=N/2))每个图都有128个列表。因此,我必须为N=4的循环创建8个
那么,有没有一种方法可以在for循环内部创建一个新列表并附加它,而不必在它外部定义一个空列表
编辑:谢谢你们的评论
我使用Verlet算法来求解许多耦合振子的运动方程:
H是代码中的变量E。N是振荡器的数目。Dv/Dx=x_n-x_n-1是力
实际算法由以下步骤完成:
其中τ在我的代码中是dt
现在我用这段代码实际做的是:
老实说,我不完全确定j是什么!我想这只是一个变量,用来改变位置变量x的初始条件
再次感谢您的帮助 我对print语句进行了注释,但它们在提供的示例中没有用处,因为有许多迭代和组合,终端将溢出。如果将列表修改为只有一个可能的组合,并稍微减少迭代次数,则取消注释将显示每个步骤。不要忘记取消注释
np。然后设置打印选项()
我还对matplotlib的图例进行了注释,因为129个图例太多,无法正确显示。我正在用E
绘制所有x
s,用E
绘制所有v
s
j=0
是一种特殊情况,其中除x_u2;(N/2)=1外,所有初始条件均为0。j
的其余部分将作为您编写的第二个初始条件案例
import matplotlib.pyplot as plt
import numpy as np
#np.set_printoptions(precision=3, suppress=True)
combinations = []
for no_iterations in [1000]:
for t_end in [10, 100]:
for N in [4, 16, 128]:
for j in [0, 1, N//2]:
combinations.append({
"no_iterations": no_iterations,
"t_end": t_end,
"N": N,
"j": j,
})
for vars_dict in combinations:
''' Extract the vars from the dict '''
no_iterations = vars_dict["no_iterations"]
t_end = vars_dict["t_end"]
dt = t_end / no_iterations
N = vars_dict["N"]
j = vars_dict["j"]
''' Print the variables '''
print(" N = {:3} | dt = {:.2f} | j = {:2}".format(N, dt, j))
#print("-"*80)
''' Create the arrays for the different values '''
v = np.zeros( (no_iterations + 1, N) )
x = np.zeros( (no_iterations + 1, N) )
E = np.zeros(no_iterations + 1)
''' Initial conditions (t=0) '''
if j == 0:
x[0][N//2 - 1] = 1
else:
for k in range(1, N+1):
x[0][k-1] = np.sin(np.pi*j*k/(N+1))
E[0] = 0.5 * (sum(map(lambda x: x**2, v[0])) + sum(map(lambda x, y: x - y, x[0][1:], x[0][:-1])))
#print("t={:4} x={} v={} E={:+.4f}".format(0, x[0], v[0], E[0]))
''' Loop (t=1..no_iterations) '''
for t in range(1, no_iterations+1):
for k in range(1, N+1):
if k == 1:
u = x[t-1][0] - x[t-1][1]
elif k == N:
u = x[t-1][N-1] - x[t-1][N-2]
else:
u = 2* x[t-1][k-1] - x[t-1][k-2] - x[t-1][k]
v[t][k-1] = v[t-1][k-1] - dt * u/2
x[t][k-1] = x[t-1][k-1] + dt * v[t][k-1]
E[t] = 0.5 * (sum(map(lambda x: x**2, v[t])) + sum(map(lambda x, y: x - y, x[t][1:], x[t][:-1])))
#print("t={:4} x={} v={} E={:+.4f}".format(t, x[t], v[t], E[t]))
''' The x axis for plotting '''
t = np.linspace(0, t_end, no_iterations+1)
fig, (ax1, ax2) = plt.subplots(2, 1)
for k in range(1, N+1):
ax1.plot(t, x[:,k-1], label="x_{}".format(k))
ax2.plot(t, v[:,k-1], label="v_{}".format(k))
pass
ax1.plot(t, E, label="Energy")
ax2.plot(t, E, label="Energy")
# ax1.legend()
# ax2.legend()
plt.show()
print("-"*80)
print()
首先,我创建一个名为combines
的列表,该列表具有一个dict
s,其中所有可能的变量组合都是从四个循环中的4个列表中提取出来的。我试图在脚本开始时使用常量来表示用户可以编辑它们,但最后一个列表取决于N
,这只能在第三个循环中知道,因此我将它们全部保留在循环中
然后,下一个循环迭代所有组合,并从dict
中提取变量,以获得更清晰的语法。我也在计算dt
我正在创建两个矩阵,其中第一个索引表示时间瞬间,第二个是x\u n
和v\u n
情况下的子索引,以及E
的向量。该矩阵/向量的第一个瞬间如您所述启动,对于您提到的特殊情况,使用j==0的特殊情况
然后进入一个循环,对所有剩余的瞬间进行迭代,然后首先计算所有的x_n(t)
,v_n(t)
,这样我们就可以计算E(t)
。这可能是错误的部分,因为我做了一个假设,u
是从上一个瞬间计算出来的。如果你知道如何手工解决这类问题,你也许能够在假设错误的情况下纠正这一部分
然后,我们用np.linspace(start,end,number)
为x轴的末尾创建t
向量(正如我们在上一个循环中使用变量t
),它给出了一个包含从start
到end
两个元素的number
向量
我们使用两行图在顶部打印x\u n
和E
,在底部打印v\u n
和E
。您能解释一下每个变量的含义吗N
是要绘制的序列数,dt
是时间增量,但是j
是什么?我还认为在计算v[I]
时,您在使用x[N]
进行计算时会遇到一些算法问题。请仅就问题的物理性做一节。什么是能量函数,力,加速度,为什么它是保守的。似乎您想要实现Leapfrog-Verlet方法,但似乎做得不对。如果初始化错误,将得到一阶辛欧拉方法。不同的运行到底是为了什么,你在比较什么?根据你发布的Verlet算法实现,v(t)和x(t)都依赖于它们自己的值,因此这些值必须从上一次迭代中获得,但它们也相互依赖(v(t)依赖于u,u依赖于x(t),x(t)直接依赖于v(t))因此,其中一个必须从上一次迭代中获得。我将发布一个解决方案,从上一次迭代中计算出u,然后解析其余的。编辑以包含OPC中给出的新信息非常感谢您的帮助!里面有很多很酷的代码!今天花了一段时间破译它,我学到了很多!我真的