您需要先阅读本书才能回答我的问题。
-背景- 我正在尝试学习《分子动力学》,并且从应该被介绍的书籍开始,但是在理解方程式或它们的解释时遇到了很多麻烦。我已经尝试了6到7本书,从介绍性章节开始,然后翻阅本书中的代码,我可以复制这些代码,以便为方程提供一些上下文,因为我无法理解它们。很明显,他们希望您具有很多先决的物理知识(似乎特别是MD知识),以了解方程式如何转换为一段代码。我参加了物理课程和3D物理引擎课程,但是这些知识对这项工作没有帮助。我唯一能找到的代码在“了解分子模拟:从算法到应用程序” 中,我对此有一些疑问,我在书中找不到答案。 如果您有任何对初学者更友好的先决条件书籍或课程,可以帮助我了解本书的背景材料,那就太棒了-背景知识-
这正是代码在书中的显示方式,我读到您应该在主程序结束后放置子例程,这就是我所做的。因为我只能找到处理非常小的代码段的fortran教程,所以我不确定是否应该在所有地方都使用stop
,end
和return
它显示在这里,如果implicit none
应该在其中,并且我应该将每个子例程放在不同的文件或类似的文件中。
循环与python中的循环基本相同,因此我已经可以理解一些代码了,但是我看不到大图。
我面临的主要问题是,我在书中的任何地方都没有声明过我使用的许多变量(尽管我找到了关于它们代表某些变量的解释),这可能就是程序无法运行的原因。我收到此错误消息“启动失败。找不到二进制文件。”
如何声明变量delt
,tmax
,f
(force),en
(energy),ranf
,lattice_pos
,x
,v
,temp
,xm
,dt
,xr
,box
,r2i
,{ {1}},r6i
,ff
和xx
?其中一些甚至可能不是变量,但我不认为它们是内置在fortran中的,因为我找不到关于它们的任何信息。另外我猜tmax与npart(N个粒子)的数目相同,所以为什么他们要使用2个不同的变量?
这些变量是什么意思? (我可以找到的vi
和f
除外)
每个原子的x,y,z坐标存储在哪里?我假设它们将存储在1个列表(或fortran中的等效项)中,每个列表包含3个值(对于x,y,z)或3个包含每个列表中所有x,y,z坐标的列表,在en
子例程中。但是,情况并非如此,因为仅init
和x
被循环通过。
在子例程的开头立即将v
设置为0时,为什么en
是force()
的输入?您不能在没有输入的情况下在函数内部声明它吗?
program main
call init
t=0
do while (t.lt.tmax)
call force(f,en)
call integrate(f,en)
t=t+delt
call sample
enddo
stop
end
subroutine init
sumv=0
sumv2=0
do i=1, npart
x(i)=lattice_pos(i)
v(i)=(ranf()-0.5)
sumv=sumv+v(1)
sumv2=sumv2+v(i)**2
enddo
sumv=sumv/npart
sumv2=sumv2/npart
fs=sqrt(3*temp/sumv2)
do i=1,npart
v(i)=(v(i)-sumv)*fs
xm(i)=x(i)-v(i)*dt
enddo
return
subroutine force(f, en)
en=0
do i=1, npart-1
do j=i+1, npart
xr=xr-box*nint(xr/box)
r2=xr**2
if (r2.lt.rc2) then
r2i=1/r2
r6i=r2i**3
ff=48*r2i*r6i*(r6i-0.5)
f(i)=f(i)+ff*xr
f(j)=f(j)-ff*xr
en=en+4*r6i*(r6i-1)-ecut
endif
enddo
enddo
return
end
subroutine integrate(f,en)
sumv=0
sumv2=0
dp i=1,npart
xx=2*x(i)-xm(i)+delt**2*f(i)
vi=(xx-xm(i))/(2*delt)
sumv=sumv+vi
sumv2=sumv2+vi**2
xm(i)=x(i)
x(i)=xx
enddo
temp=sumv2/(3*npart)
etot=(en+0.5*sumv2)/npart
return
end
implicit none
end program main
答案 0 :(得分:3)
与许多其他教科书一样,“理解分子模拟:从算法到应用程序”中的示例代码是伪代码。它不完整(例如,缺少声明),并且比“仅是数学”要更明确地说明算法。本书令人困惑,因为他们为伪代码编写了不完整的Fortran。
这仍然是一个很好的“一般问题”:了解如何使用带有Fortran的老式教科书材料:-)
在http://www.acmm.nl/molsim/frenkel_smit/index.html(阿姆斯特丹多尺度建模中心网站)上,您可以找到本书http://www.acmm.nl/molsim/frenkel_smit/README.html的实际Fortran代码,正如伊恩·布什(Ian Bush)所写的那样,该代码是老式的,艾伦和蒂尔德斯利本书有更新的和更新的代码:https://github.com/Allen-Tildesley/
关于您的问题:
如何声明变量delt,tmax,f(force),en(energy),ranf,lattice_pos,x,v,temp,xm,dt,xr,box,r2i,r6i,ff, xx和vi?其中一些甚至可能不是变量,但我不认为它们是内置在fortran中的,因为我找不到关于它们的任何信息。另外我猜tmax与npart(N个粒子)的数目相同,所以为什么他们要使用2个不同的变量?
您必须阅读有关算法的章节才能理解变量。但是,它们的列表在本书的“ xxi”页面上。
每个原子的x,y,z坐标存储在哪里?我假设它们将存储在1个列表(或fortran中的等效项)中,每个列表包含3个值(对于x,y,z)或3个包含每个列表中所有x,y,z坐标的列表,在init子例程中。但是事实并非如此,因为只有x和v循环通过。
在这里,伪代码还是有限制的。您可以使用多个选项来声明变量:(i)作者(请参见上面的文件链接)使用“公共块”,这是Fortran特定类型的全局变量。 (ii)在Fortran 90及更高版本中可用的模块变量是“更好的全局变量”。 (iii)将所有数据封装为可在主程序中声明的派生类型中,然后传递给子例程。
位置(在示例中)存储为数组x(npmax)
,y(npmax)
和z(npmax)
。 npmax
是最大粒子数。伪代码中未显示。请注意,在最新版本的Fortran(90及更高版本)中,您可以编写矢量操作,例如x = x + v*dt
(其中x和v是 all 粒子的位置和速度,而dt是标量时间步)。
当在子例程开始时立即将其设置为0时,为什么要输入force()?您不能在没有输入的情况下在函数内部声明它吗?
在Fortran中,传递需要更新的变量作为子例程的参数是常见的,但不是强制性的。编程样式各不相同。