首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何使用变量赋值构造多维数组

如何使用变量赋值构造多维数组
EN

Stack Overflow用户
提问于 2018-03-29 08:24:19
回答 1查看 115关注 0票数 0

所以我遇到了一个数组do循环的问题。

我有一个976个原子的X,Y,Z坐标数组列表。在另一个文本文件中,我有一个数组,每个原子有976个电荷。此外,我还有Xo,Yo,Zo的2,971个点(13x13,x13)的数组。我需要计算的是原子的实际X,Y,Z坐标和2,197个网格点之间的距离。最初,我用33个原子做的计算是这样的。

代码语言:javascript
运行
复制
  do i=1,2197
 D1(i) = (((X(1)-Xi(i))**2 + (Y(1)-Yi(i))**2 + (Z(1)-Zi(i))**2)**0.5)*10E-10
 D2(i) = (((X(2)-Xi(i))**2 + (Y(2)-Yi(i))**2 + (Z(2)-Zi(i))**2)**0.5)*10E-10
 D3(i) = (((X(3)-Xi(i))**2 + (Y(3)-Yi(i))**2 + (Z(3) Zi(i))**2)**0.5)*10E-10
 D4(i) = (((X(4)-Xi(i))**2 + (Y(4)-Yi(i))**2 + (Z(4)- 
   Zi(i))**2)**0.5)*10E-10 

....etc等

但由于我现在有976个原子,手动做这件事将是一场噩梦。我的问题是:由于我需要为每个原子创建一个包含2197个点的数组,有没有一种方法可以在不手动写出的情况下生成这个数组?

我尝试了下面这样的方法:

代码语言:javascript
运行
复制
do i=1,2197
    Do n=1,976
        DO j=1,976
D(j,i) = (((X(n)-Xi(i))**2 + (Y(n)-Yi(i))**2 + (Z(n)- 
Zi(i))**2)**0.5)*10E-10
        End do
    End Do
Enddo

我的逻辑基本上是计算每个原子的2,197个距离点,这样它们将像这样存储,其中j将表示它是数字1-976中的哪个原子,变量i将是通过公式计算的2197个不同的点。我们的想法是拥有967个原子,其中每个原子都有2197个点,我可以在以后使用它来计算其他东西。然后将电荷除以距离,得到电压电位,因此基本上我需要能够将距离称为D(atom#,charge.)

我对此的逻辑是否正确,或者我是否应该使用其他数组组合以不同的方式处理此问题?

EN

回答 1

Stack Overflow用户

发布于 2018-03-29 10:44:45

你的问题很难理解,至少对我来说是这样,但假设这不是一个家庭作业问题,假设你只是一名Fortran爱好者或新开发人员,下面是一个非面向对象但现代高效的解决方案:

代码语言:javascript
运行
复制
program confusingQuestion

use, intrinsic :: iso_fortran_env, only: int32,real64
implicit none

integer(int32), parameter :: nAtom = 976
integer(int32), parameter :: nGrid = 2197
real(real64)              :: AtomCrd(3,nAtom), AtomCharge(nAtom)
real(real64)              :: GridCrd(3,nGrid), Atom2GridDistance(nGrid,nAtom)
integer(int32)            :: iAtom,iGrid

! for demonstration purposes, I assign random values to variables
call random_number(AtomCrd)
call random_number(GridCrd)
call random_number(AtomCharge)

do concurrent (iAtom = 1:nAtom,iGrid=1:nGrid)
  Atom2GridDistance(iGrid,iAtom) = norm2( AtomCrd(:,iAtom)-GridCrd(:,iGrid) )
end do

! print a sample:
write(*,'(*(g0.4,","))') Atom2GridDistance(:,1) ! print distances for the first atom
end program confusingQuestion

注意,我在这里有目的地使用了do concurrent构造。与一个接一个地串行执行常规do循环不同,do concurrent告诉编译器循环中的所有元素级计算都是相互独立的,并且可以并行计算。因此,根据您的编译器,此代码可以并行执行,这将提高代码的速度。

此外,也不需要在代码中手动实现L2-norm。Fortran已经有多个计算L2范数的方法,其中之一是norm2 (x [ , dim ] ),它返回实数组x的L2范数;结果是与x相同的实标量。请注意,您需要使用Fortran 2008编译器来编译此代码。这是一个在线2008编译器,您可以使用它来尝试代码https://www.tutorialspoint.com/compile_fortran_online.php

请记住,为了让编译器自动并行化并发循环,您很可能需要使用O2或更好的O3优化标志以及自动并行化标志(例如在英特尔的ifort中)来编译代码。我不确定do concurrent在GNU gfortran中的状态。但是,在使用英特尔ifort编译器时,我发现它的性能有明显的差异。下面是关于这个主题的一个相关但古老的主题:https://stackoverflow.com/a/25860047/2088694

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49546198

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档