2017-09-05 7 views
2

J'essaie de faire un tableau logique (B) à utiliser dans l'indexation logique basée sur des valeurs comprises entre .1 et .999 dans un tableau (EP_G2) en utilisant un couple de méthodes différentes 1) où boucle 2) ANY.Indexation logique basée sur "trouver" dans 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) 

La question que je reçois est que je reçois soit le tableau tout ou rien et la commande LOGIQUE (B) obtient une erreur qu'il n'est pas le bon type. Je suis nouveau à Fortran venant de Matlab où j'utiliserais simplement trouver. En outre, puisque ce tableau est plus de 5,948,640 x 1 temps de calcul est un problème. J'utilise le compilateur Intel Fortran (15.0 je crois). Fondamentalement, je cherche le moyen le plus rapide de trouver les index de points dans un tableau entre deux nombres.

Toute aide serait très appréciée.

+0

Juste pour clarifier la question. Vous avez un tableau de 'DOUBLE PRECISION :: EP_G2'. Vous voulez un deuxième tableau, 'DOUBLE PRECISION :: C', qui contient uniquement les valeurs d'une plage particulière. Est-ce exact? Avez-vous également besoin de stocker les index de ces nombres dans 'EP_G2'? – Jack

+0

Oui. Je cherche à stocker les valeurs dans un tableau ET les index dans un tableau séparé. – akimbo

Répondre

2

Je suis un peu confus par votre code et question mais je pense que vous voulez trouver les indices d'éléments dans un tableau dont les valeurs se situent entre 0.1 et 0.999. Il n'est pas tout à fait clair que vous voulez les indices, ou seulement les éléments eux-mêmes, mais supportez-moi et je vais vous expliquer comment obtenir les deux.

Supposons que votre tableau d'origine est déclaré quelque chose comme

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

et qu'il est peuplé de valeurs. Ensuite, je pourrais déclarer un tableau d'index comme celui-ci

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

(évidemment, vous devrez déclarer aussi la ix variable).

Maintenant, l'expression

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

retournera les éléments de indices dont les valeurs se trouvent strictement entre pmin et pmax. Bien sûr, si vous ne souhaitez que les valeurs elles-mêmes, vous pouvez renoncer à indices entièrement et écrire

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

Ces deux utilisations de pack retourne un tableau de rang 1, et vous pouvez attribuer le tableau retourné à un allocatable, Fortran prendra soin de la taille pour vous.

Je vous laisse le soin d'étendre cette approche au tableau de rang 2 avec lequel vous travaillez, mais cela ne devrait pas être trop difficile. Demandez plus d'aide si vous en avez besoin.

Et est-ce l'approche la plus rapide? Je ne suis pas sûr, mais c'était très rapide à écrire et si vous êtes intéressé par sa performance d'exécution, je vous suggère de tester cela. Incidemment, la fonction intrinsèque logical de Fortran sert à transformer logical valeurs d'un type à un autre, elle n'est pas définie sur les entiers (ou tout autre type intrinsèque). Fortran est antérieure à la folie de considérer 0 et 1 comme des valeurs logiques.

+0

Merci pour la réponse. Clarification? je l'ai ajouté dans mon script comme 'A = PACK (valeurs, valeurs> pmin.and.values ​​ akimbo

+0

Modifiez votre question ou demandez-en un nouveau. Il est trop difficile de comprendre ce qui se passe dans les commentaires. –

1

Comment les tableaux peuvent-ils être identiques?

Les valeurs RMAX, YMAX, ZMAZ et timesteps ne sont pas connues avant que A, B et C ne soient déclarées - Donc, elles (A et B) n'auront probablement pas la taille désirée.

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 

Vous voulez probablement soit ceci:

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 

Ou ceci:

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 

Et vous pouvez également envisager l'utilisation de forme ou de taille pour voir si le rang et la taille du tableau sont corrects.

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