2017-09-05 2 views
2

Ich versuche ein logisches Array (B) für die logische Indizierung basierend auf Werten zwischen .1 und .999 in einem Array (EP_G2) mit ein paar verschiedenen Methoden zu erstellen 1) wo Schleife 2) ANY.Logische Indizierung basierend auf "find" in 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) 

Die Frage, die ich bekommen habe ist, dass ich entweder das gesamte Array oder nichts bekommen und den Befehl LOGISCH (B) bekommt einen Fehler, dass es nicht die richtige Art ist. Ich bin neu in Fortran, komme aus Matlab, wo ich nur finden würde. Da dieses Array über 5.948.640 x 1 Rechenzeit ist ein Problem. Ich benutze den Intel Fortran Compiler (15.0 glaube ich).

Grundsätzlich suche ich nach dem schnellsten Weg, um die Indizes von Punkten in einem Array zwischen zwei Zahlen zu finden.

Jede Hilfe wäre sehr willkommen.

+0

Nur um die Frage zu klären. Sie haben eine Reihe von 'DOUBLE PRECISION :: EP_G2'. Sie möchten ein zweites Array, "DOUBLE PRECISION :: C", das nur die Werte in einem bestimmten Bereich enthält. Ist das korrekt? Müssen Sie auch die Indizes dieser Nummern in 'EP_G2' speichern? – Jack

+0

Ja. Ich suche, um die Werte in einem Array UND die Indizes in einem separaten Array zu speichern. – akimbo

Antwort

2

Ich bin ein wenig verwirrt durch Ihren Code und Frage, aber ich denke, dass Sie die Indizes von Elementen in einem Array finden möchten, deren Werte zwischen 0.1 und 0.999 liegen. Es ist nicht ganz klar, dass Sie die Indizes oder nur die Elemente selbst wollen, aber tragen Sie mit mir und ich werde erklären, wie Sie beide erhalten.

Angenommen, Ihr Original-Array so etwas wie

erklärt
real, dimension(10**6) :: values 

und dass es mit Werten gefüllt wird. Dann könnte ich einen Index-Array wie diese

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

erklären (natürlich müssen Sie die Variable ix erklären). Jetzt

der Ausdruck

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

werden diese Elemente von indices deren Werte zurück liegen streng zwischen pmin und pmax. Natürlich, wenn Sie nur die Werte wollen sich Sie mit indices ganz verzichtet werden kann und

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

diese beiden Verwendungen von pack wird eine Reihe von Rang 1, schreiben zurück, und Sie können mit einem zuweisbaren die zurückgegebene Array zuweisen, Fortran kümmert sich um die Dimensionierung für Sie.

Ich überlasse es Ihnen, diesen Ansatz auf das Rang-2-Array, mit dem Sie tatsächlich arbeiten, zu erweitern, aber es sollte nicht zu schwierig sein, das zu tun. Fordern Sie nach mehr Hilfe, wenn Sie es brauchen.

Und ist das der schnellste Ansatz? Ich bin mir nicht sicher, aber es war sehr schnell zu schreiben und wenn Sie an der Laufzeit Leistung interessiert sind, schlage ich vor, dass Sie das testen.

Übrigens ist die Fortran intrinsische Funktion logical für die Umwandlung logical Werte von einer Art in eine andere, es ist nicht auf ganze Zahlen (oder andere intrinsische Art) definiert. Fortran ist älter als der Wahnsinn, 0 und 1 als logische Werte zu betrachten.

+0

Vielen Dank für die Antwort. Klärung? ich es in meinem Skript als 'A = PACK hinzugefügt (Werte, Werte> pmin.and.values ​​

akimbo

+0

Bearbeiten Sie Ihre Frage oder fragen Sie eine neue. Es ist zu schwierig herauszufinden, was in Kommentaren passiert. –

1

Wie können die Arrays gleich sein?

RMAX-, YMAX-, ZMAZ- und Zeitschrittwerte sind erst bekannt, nachdem A, B und C deklariert wurden - also werden sie (A und B) wahrscheinlich nicht die gewünschte Größe haben.

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 

Sie wollen wahrscheinlich entweder das:

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 

Oder diese:

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 

Und Sie können auch die Verwendung von Form oder Größe zu prüfen, ob der Rang und Größe zu sehen des Arrays sind korrekt.

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