2017-09-05 130 views
2

我想使用几种不同的方法在数组(EP_G2)中基于.1和.999之间的值在逻辑索引中使用逻辑数组(B) )其中循环2)任何。在Fortran 90基于“查找”的逻辑索引

program flux_3d 

implicit none 
INTEGER :: RMAX, YMAX, ZMAZ, timesteps 
DOUBLE PRECISION, PARAMETER :: pmin=0.1 
DOUBLE PRECISION, PARAMETER :: pmax=0.999 
INTEGER :: sz 
DOUBLE PRECISION, ALLOCATABLE :: EP_G2(:,:), C(:) 
INTEGER, DIMENSION(RMAX*ZMAX*YMAX) :: B 
LOGICAL, DIMENSION(RMAX*ZMAX*YMAX) :: A 
! dimensions of array, 
RMAX = 540 
YMAX = 204 
ZMAX = 54 
timesteps = 1 
!Open ascii array 
OPEN(100, FILE ='EP_G2', form = 'formatted') 
ALLOCATE(EP_G2(RMAX*ZMAX*YMAX, timesteps)) 
READ(100, *) EP_G2 

WHERE(pmin<EP_G2(:,timesteps)<pmax) B = 1 
    ELSEWHERE 
     B = 0 
ENDWHERE 

PRINT*, B 

! SZ # OF POINTS IN B 
sz = count(B.eq.1) 

!alternate way of finding points between pmin and pmax 
A = ANY(pmin<EP_G2(:,t)<pmax) 
print*, sz 

!Then use the logical matrix B (or A) to make new array 
!Basically I want a new array that isolates just the points in array between 
!pmin and pmax 
ALLOCATE(C(sz)) 
C = EP_G2(LOGICAL(B), 1) 

我得到的问题是,我要么得到整个数组或没有和命令逻辑的(B)得到一个错误,这是不正确的那种。我是来自Matlab的Fortran的新手,我只用find。 此外,由于此数组超过5,948,640 x 1,所以计算时间是一个问题。我正在使用英特尔Fortran编译器(我相信15.0)。

基本上,我正在寻找最快的方法来查找两个数字之间的数组中的点的索引。

任何帮助将不胜感激。

+0

只是为了澄清问题。你有一个'DOUBLE PRECISION :: EP_G2'的数组。你需要第二个数组'DOUBLE PRECISION :: C',它只包含特定范围内的值。那是对的吗?你还需要将这些数字的索引存储在'EP_G2'中吗? – Jack

+0

是的。我正在寻找将值存储在一个数组中并将索引存储在单独的数组中。 – akimbo

回答

2

我有点困惑你的代码和问题,但我想你想找到一个数组的元素索引值在0.10.999之间。目前还不完全清楚你想要索引,还是仅仅是元素本身,但是忍耐着我,我会解释如何得到两者。

假设你原来的数组声明类似

real, dimension(10**6) :: values 

,它填充了值。然后,我可能会宣布这样

integer, dimension(10**6) :: indices = [(ix,ix=1,10**6)] 

(显然你需要声明变量ix太)索引阵列。

现在,表达式

pack(indices, values>pmin.and.values<pmax) 

将返回其值处于严格pminpmax之间的indices那些元素。当然,如果你只希望值本身可以用indices免除全部写

pack(values, values>pmin.and.values<pmax) 

这两个pack这些用途将回到1级的数组,你可以返回的数组分配到一个分配, Fortran将为您处理尺寸。

我会让你把这种方法扩展到你实际使用的rank-2数组,但是这样做不应该太困难。如果您需要它,请寻求更多帮助。

这是最快的方法吗?我不确定,但编写起来非常快,如果您对运行时性能感兴趣,我建议您测试一下。顺便提一句,Fortran内部函数logical用于将值从一种类型转换为另一种类型,它并未在整数(或任何其他内在类型)上定义。 Fortran早于关于01作为逻辑值的疯狂。

+0

谢谢你的回答。澄清? 我添加到我的脚本作为 'A = PACK(值,值> pmin.and.values akimbo

+0

编辑你的问题或者要求一个新的。从评论中弄清楚发生了什么实在太难了。 –

1

数组如何可以相同?

直到声明A,B和C之后才知道RMAX,YMAX,ZMAZ和时间步长值 - 所以它们(A和B)不可能是你想要的大小。

implicit none 
INTEGER :: RMAX, YMAX, ZMAZ, timesteps 
DOUBLE PRECISION, PARAMETER :: pmin=0.1 
DOUBLE PRECISION, PARAMETER :: pmax=0.999 
INTEGER :: sz 
DOUBLE PRECISION, ALLOCATABLE :: EP_G2(:,:), C(:) 
INTEGER, DIMENSION(RMAX*ZMAX*YMAX) :: B 
LOGICAL, DIMENSION(RMAX*ZMAX*YMAX) :: A 
! dimensions of array, 
RMAX = 540 
YMAX = 204 
ZMAX = 54 
timesteps = 1 

您可能希望无论是这样的:

implicit none 
INTEGER ,   PARAMETER :: RMAX  = 504 
INTEGER ,   PARAMETER :: YMAX  = 204 
INTEGER ,   PARAMETER :: ZMAZ  = 54 
INTEGER ,   PARAMETER :: timesteps = 1 
DOUBLE PRECISION, PARAMETER :: pmin  = 0.1 
DOUBLE PRECISION, PARAMETER :: pmax  = 0.999 
INTEGER :: sz 
DOUBLE PRECISION, ALLOCATABLE :: EP_G2(:,:), C(:) 
INTEGER, DIMENSION(RMAX*ZMAX*YMAX) :: B 
LOGICAL, DIMENSION(RMAX*ZMAX*YMAX) :: A 
! dimensions of array, 
!RMAX = 540 
!YMAX = 204 
!ZMAX = 54 
!timesteps = 1 

或者这样:

implicit none 
! dimensions of array 
INTEGER ,   PARAMETER :: RMAX  = 504 
INTEGER ,   PARAMETER :: YMAX  = 204 
INTEGER ,   PARAMETER :: ZMAZ  = 54 
INTEGER ,   PARAMETER :: timesteps = 1 

DOUBLE PRECISION, PARAMETER :: pmin  = 0.1 
DOUBLE PRECISION, PARAMETER :: pmax  = 0.999 
INTEGER :: sz 
DOUBLE PRECISION, ALLOCATABLE :: EP_G2(:,:), C(:) 
INTEGER, DIMENSION(:), ALLOCATABLE :: B 
LOGICAL, DIMENSION(:), ALLOCATABLE :: A 
! Then allocate A and B 

而且你可能还需要考虑使用形状或大小,看看等级和尺寸的数组是正确的。

IF(SHAPE(A) /= SHAPE(B)) ... chuck and error message. 
IF(SIZE(A,1) /= SIZE(B,1)) etc