IF-block syntax - if-statement

I'm trying to compare a month array to check whether each number is a odd month or even month so that I can make files labelled as the month//date//year.txt and upload lines matching the date from another files into the respective .txt file.
My output should be 90 .txt files, each containing the lines matching the particular date from APM_FORMATTED.txt.
PROGRAM APM_TEST
IMPLICIT NONE
INTEGER :: READSTATUS, YEAR_MIN, MONTH_MIN, DAY_MIN, YEAR_MAX, MONTH_MAX, DAY_MAX, I, IND, IND1, D, D1, D2
CHARACTER(13) :: DATE_INPUT
CHARACTER(2) :: FILE_DAY, FILE_MONTH, FILE_YEAR, CURRENT_DAY, CURRENT_MONTH
CHARACTER(632) :: ROW1
INTEGER, DIMENSION(1,6) :: M
INTEGER, DIMENSION(1,6) :: N
INTEGER, DIMENSION(1,3) :: MON
WRITE(*,'(" ENTER DATE RANGE OF FILE (E.G. 010413-010713):")', ADVANCE = "NO")
READINT : DO
READ (*,*,IOSTAT=READSTATUS) DATE_INPUT
IF (READSTATUS==0) THEN
EXIT READINT
ELSE
WRITE(*,'(/"READ ERROR. PLEASE RE-INPUT:")')
ENDIF
ENDDO READINT
READ(DATE_INPUT(5:6), '(I2)') YEAR_MIN
READ(DATE_INPUT(3:4), '(I2)') MONTH_MIN
READ(DATE_INPUT(1:2), '(I2)') DAY_MIN
READ(DATE_INPUT(12:13), '(I2)') YEAR_MAX
READ(DATE_INPUT(10:11), '(I2)') MONTH_MAX
READ(DATE_INPUT(8:9), '(I2)') DAY_MAX
IND=1
IND1=1
M=(/1,3,5,7,9,11/)
N=(/4,6,8,10,12/)
36 DO MON=MONTH_MIN, MONTH_MAX
IF (ANY(M.EQ.MON(IND))) THEN
DO D=DAY_MIN,31
FILE_DAY=DATE_INPUT(1:2)
FILE_MONTH=DATE_INPUT(3:4)
FILE_YEAR=DATE_INPUT(5:6)
OPEN(UNIT=201, FILE="APM_FORMATTED.TXT")
OPEN(IND1, FILE=(FILE_MONTH//FILE_DAY//FILE_YEAR//".TXT"), ACTION="WRITE", STATUS="NEW")
45 DO I=1,200000
READ(201,'(A632)') ROW1
IF (ROW1(1:3).EQ.'APM') THEN
READ(ROW1(41:42), '(I2)') CURRENT_DAY
READ(ROW1(43:44), '(I2)') CURRENT_MONTH
IF (CURRENT_MONTH.EQ.MON .AND. CURRENT_DAY.EQ.D) THEN
WRITE(IND1,*) ROW1
ELSE
GOTO 45
ENDIF
ELSE
ENDIF
ENDDO
IND1=IND1+1
CLOSE(IND1)
CLOSE(201)
ENDDO
ELSEIF (ANY(N.EQ.MON)) THEN
DO D1=DAY_MIN,30
FILE_DAY=DATE_INPUT(1:2)
FILE_MONTH=DATE_INPUT(3:4)
FILE_YEAR=DATE_INPUT(5:6)
OPEN(UNIT=201, FILE="APM_FORMATTED.TXT")
OPEN(IND1, FILE=(FILE_MONTH//FILE_DAY//FILE_YEAR//".TXT"), ACTION="WRITE", STATUS="NEW")
73 DO I=1,200000
READ(201,'(A632)') ROW1
IF (ROW1(1:3).EQ.'APM') THEN
READ(ROW1(41:42), '(I2)') CURRENT_DAY
READ(ROW1(43:44), '(I2)') CURRENT_MONTH
IF (CURRENT_MONTH.EQ.MON .AND. CURRENT_DAY.EQ.D1) THEN
WRITE(IND1,*) ROW1
ELSE
GOTO 73
ENDIF
ELSE
ENDIF
ENDDO
IND1=IND1+1
CLOSE(IND1)
CLOSE(201)
ENDDO
ELSEIF (ANY(M.EQ.4)) THEN
DO D2=DAY_MIN,28
FILE_DAY=DATE_INPUT(1:2)
FILE_MONTH=DATE_INPUT(3:4)
FILE_YEAR=DATE_INPUT(5:6)
OPEN(UNIT=201, FILE="APM_FORMATTED.TXT")
OPEN(IND1, FILE=(FILE_MONTH//FILE_DAY//FILE_YEAR//".TXT"), ACTION="WRITE", STATUS="NEW")
101 DO I=1,200000
READ(201,'(A632)') ROW1
IF (ROW1(1:3).EQ.'APM') THEN
READ(ROW1(41:42), '(I2)') CURRENT_DAY
READ(ROW1(43:44), '(I2)') CURRENT_MONTH
IF (CURRENT_MONTH.EQ.MON .AND. CURRENT_DAY.EQ.D2) THEN
WRITE(IND1,*) ROW1
ELSE
GOTO 101
ENDIF
ELSE
ENDIF
ENDDO
IND1=IND1+1
CLOSE(IND1)
CLOSE(201)
ENDDO
ELSE
GOTO 36
ENDIF
IND=IND+1
DAY_MIN=1
ENDDO
END PROGRAM APM_TEST
Errors:
error FOR2614: assignment between arrays of differing rank
error FOR2614: assignment between arrays of differing rank
error FOR2799: DO control variable MON is not scalar
error FOR2979: expected 2 subscripts but found 1 for array MON
error FOR3041: operands to relational operator .EQ. are of incompatible data type
error FOR3041: operands to relational operator .EQ. are of incompatible data type
error FOR3048: illegal data type to binary logical operator .AND.
error FOR3156: array shapes differ in dimension 2 (extent 6 and 3)
error FOR3041: operands to relational operator .EQ. are of incompatible data type
error FOR3041: operands to relational operator .EQ. are of incompatible data type
error FOR3048: illegal data type to binary logical operator .AND.
error FOR3041: operands to relational operator .EQ. are of incompatible data type
error FOR3041: operands to relational operator .EQ. are of incompatible data type
error FOR3048: illegal data type to binary logical operator .AND.

You have syntax errors on lines 38 and 45 (and very likely other lines as well). Look into your favorite book or online tutorial about correct IF block and statement syntax. The basic IF-block syntax in Fortran is in the form:
IF(scalar-logical-expr)THEN
...
ELSEIF(scalar-logical-expr)THEN
...
ELSE
...
ENDIF

Related

Error: Unclassifiable statement at (1) in Fortran for calculations [duplicate]

This program:
C This program calculates cos(x**2)
PROGRAM COSX_SQUARE
IMPLICIT NONE
INTEGER a
REAL y, r
PRINT*, 'INPUT THE DEGREE'
PRINT*, 'BETWEEN 0 AND 360'
READ*, a
a*(3.141592/180) = y
C This part determines minus sign and calculates the function
IF (a .GT. 90) THEN
r = -(1-(y**4)/2+(y**8)/24-(y**12)/720+(y**16)/40320)
ELSEIF (a .GE. 270) THEN
r = 1-(y**4)/2+(y**8)/24-(y**12)/720+(y**16)/40320
ELSEIF (a .GT. 360) THEN
PRINT*, 'INVALID DEGREE'
PRINT*, 'DEGREE MUST BE BETWEEN 0 AND 360'
ELSEIF (a .LT. 0) THEN
PRINT*, 'INVALID DEGREE'
PRINT*, 'DEGREE MUST BE BETWEEN 0 AND 360'
END IF
PRINT*, 'THE RESULT OF COS', a, 'SQUARE IS = ', r
STOP
END
Gives this error:
a*(3.141592/180)=y
1
Error: Unclassifiable statement at (1)
I already defined a as INTEGER. Why this error keeps coming?
Yep. It is an expression which begins a statement. Maybe change it to
y = a*(3.141592/180)
if that is what you really meant.

An error combining DO and IF in Fortran

This is a part of code that I am writing in Visual FORTRAN 6.6A:
.
.
.
DO 24 I=1,80
24 IF ((NODNUM(1) .EQ. I) .AND. (CAUCHY(3,2) .LT. CTI(I+12))) THEN
ARRAY(1)=C1*0.99
END IF
.
.
.
and this error occurs when I compile it:
*--------------------Configuration: ovl30u_moon1 - Win32 Debug--------------------
Compiling Fortran...
C:\Documents and Settings\XPMUser\Desktop\ovl30u_moon1.f
C:\Documents and Settings\XPMUser\Desktop\ovl30u_moon1.f(567) : Error: This is not a valid termination statement for a DO construct.
24 IF ((NODNUM(1) .EQ. I) .AND. (CAUCHY(3,2) .LT. CTI(I+12))) THEN
---^
C:\Documents and Settings\XPMUser\Desktop\ovl30u_moon1.f(569) : Error: An ENDIF occurred without a corresponding IF THEN or ELSE statement.
END IF
-----------^
Error executing df.exe.
ovl30u_moon1.obj - 2 error(s), 0 warning(s)*
I also tried this but error exists yet:
DO 24 I=1,80
24 IF ((NODNUM(1) .EQ. I) .AND. (CAUCHY(3,2) .LT. CTI(I+12))) THEN
ARRAY(1)=C1*0.99
END IF
END DO
Any advice appreciated.
The termination of a do loop using a label is not valid the way you specify it. For FORTRAN 77 use:
DO 24 I=1,80
IF ((NODNUM(1) .EQ. I) .AND. (CAUCHY(3,2) .LT. CTI(I+12))) THEN
ARRAY(1)=C1*0.99
END IF
24 CONTINUE
In Fortran 90+ you could simply leave out the label:
DO I=1,80
IF ((NODNUM(1) .EQ. I) .AND. (CAUCHY(3,2) .LT. CTI(I+12))) THEN
ARRAY(1)=C1*0.99
END IF
END DO
Or, if you depend on the label, you could use
label: DO I=1,80
IF ((NODNUM(1) .EQ. I) .AND. (CAUCHY(3,2) .LT. CTI(I+12))) THEN
ARRAY(1)=C1*0.99
END IF
END DO label
To add to Alexander Vogt's answer there is another way to restate your particular case.
While it is not allowed to use an if construct as the termination of the non-block (labelled) do it is possible to use an if statement:
DO 24 I=1,80
24 IF ((NODNUM(1) .EQ. I) .AND. (CAUCHY(3,2) .LT. CTI(I+12))) ARRAY(1)=C1*0.99
You can, but you really shouldn't: use the block construct as in the other anwer.
For more detail, see Fortran 2008 8.1.6.3 and R214.

FORTRAN 77 "Error: Unclassifiable statement at (1)"

This program:
C This program calculates cos(x**2)
PROGRAM COSX_SQUARE
IMPLICIT NONE
INTEGER a
REAL y, r
PRINT*, 'INPUT THE DEGREE'
PRINT*, 'BETWEEN 0 AND 360'
READ*, a
a*(3.141592/180) = y
C This part determines minus sign and calculates the function
IF (a .GT. 90) THEN
r = -(1-(y**4)/2+(y**8)/24-(y**12)/720+(y**16)/40320)
ELSEIF (a .GE. 270) THEN
r = 1-(y**4)/2+(y**8)/24-(y**12)/720+(y**16)/40320
ELSEIF (a .GT. 360) THEN
PRINT*, 'INVALID DEGREE'
PRINT*, 'DEGREE MUST BE BETWEEN 0 AND 360'
ELSEIF (a .LT. 0) THEN
PRINT*, 'INVALID DEGREE'
PRINT*, 'DEGREE MUST BE BETWEEN 0 AND 360'
END IF
PRINT*, 'THE RESULT OF COS', a, 'SQUARE IS = ', r
STOP
END
Gives this error:
a*(3.141592/180)=y
1
Error: Unclassifiable statement at (1)
I already defined a as INTEGER. Why this error keeps coming?
Yep. It is an expression which begins a statement. Maybe change it to
y = a*(3.141592/180)
if that is what you really meant.

Fortran 90: Assigning a character to a real kind in Fortran

Apologies for inconvenience , I have resubmitted the code now.
Problem: I am trying to write a program that reads the precipitation from a binary (.DAT) file. It calculates the value of precipitation at each grid and for every grid the maximum value month is returned as output. For example if there was a value of 25 highest in the month of June then our output value should be "Jun".
implicit none
integer,parameter :: ix=44,iy=27,nyr=12
integer :: ntot
real :: v_obs(ix,iy,nyr),TestVal,b(ix,iy,nyr),wet(ix,iy)
real:: Mon(12),Y(12),missing_obs,missing_mod,missing
integer :: ii,jj,i,j,k,ik,jk,irec,m,n
character (130) dir,jan,feb,mar,apr,may,jun,jul,aug,sep,oct,nov,dec
data missing_obs/-999000000/
data missing/-999./
open(21,file='C:/Fortran/test-dat.dat',access='direct',recl=ix*iy*nyr,form='unformatted')
open(23,file='C:/wet-month.dat',access='direct',recl=ix*iy*nyr,form='unformatted')
irec=1
Do j=1,nyr
read(21,rec=irec) ((v_obs(ii,jj,j),ii=1,ix),jj=1,iy)
ntot=0
do ik=1,nyr
ntot=ntot+1
Y(ik)=v_obs(ii,jj,ik)
enddo
if (Y(ik) .eq. missing_obs)then
wet=-999
go to 199
endif
enddo
Mon(1)=v_obs(ii,jj,1)
Mon(2)=v_obs(ii,jj,2)
Mon(3)=v_obs(ii,jj,3)
Mon(4)=v_obs(ii,jj,4)
Mon(5)=v_obs(ii,jj,5)
Mon(6)=v_obs(ii,jj,6)
Mon(7)=v_obs(ii,jj,7)
Mon(8)=v_obs(ii,jj,8)
Mon(9)=v_obs(ii,jj,9)
Mon(10)=v_obs(ii,jj,10)
Mon(11)=v_obs(ii,jj,11)
Mon(12)=v_obs(ii,jj,12)
TestVal=MAXVAL(Mon)
If (TestVal .eq. Mon(1)) then
wet=jan
else if (TestVal .eq. Mon(2)) Then
wet=feb
else if (TestVal .eq. Mon(3)) Then
wet=mar
else if (TestVal .eq. Mon(4)) Then
wet=apr
else if (TestVal .eq. Mon(5)) Then
wet=may
else if (TestVal .eq. Mon(6)) Then
wet=jun
else if (TestVal .eq. Mon(7)) Then
wet=jul
else if (TestVal .eq. Mon(8)) Then
wet=aug
else if (TestVal .eq. Mon(9)) Then
wet=sep
else if (TestVal .eq. Mon(10)) Then
wet=oct
else if (TestVal .eq. Mon(11)) Then
wet=nov
else if (TestVal .eq. Mon(12)) Then
wet=dec
endif
199 continue
irec=1
do k=1,nyr
write(23,rec=irec)((wet(ii,jj),ii=1,ix),jj=1,iy)
irec=irec+1
enddo
close(21)
close(22)
end
The compliation error says
You cannot assign an expression of type CHARACTER(LEN=130) to a variable of type REAL(KIND=1)" i.e: "wet=jan".
But I want to save data as character for each grid point.Please help to resolve this error.
The problem is all those lines wet=jan, wet=feb, etc.
As I read from your code wet is real,dimension(44,27). jan and feb are of type character(130). Those are incompatible (as the compiler says).

Syntax error, found .and. and .or.

I just wanted to modify a small part of a very old program and I can't for the life of me figure out what I've done to anger the Fortran gods.
The original code has the following line:
if (r.gt.rstep) xappad = xappad*fakm
which I have modified to:
if (r.gt.0.58*rstep .and. r.lt.1.42*rstep) .or. (r.gt.2.08*rstep
: .and. r.lt.2.92*rstep) xappad = xappad*fakm
Which gives me the errors:
sp-co-2-MODIFIED.for(785): error #5082: Syntax error, found '.OR.'
when expecting one of: BLOCK BLOCKDATA PROGRAM MODULE TYPE COMPLEX
BYTE CHARACTER DOUBLE DOUBLECOMPLEX ...
if (r.gt.0.58*rstep .and. r.lt.1.42*rstep) .or. (r.gt.2.08*rstep
-------------------------------------------------------------------------^
sp-co-2-MODIFIED.for(786): error #6090: An array-valued operand is required in this context.
: .and. r.lt.2.92*rstep) xappad = xappad*fakm
------^
sp-co-2-MODIFIED.for(786): error #6087: An array assignment statement
is required in this context.
: .and. r.lt.2.92*rstep) xappad = xappad*fakm
-------------------------------------------^
I really don't know much FORTRAN, but it looks to me like you're missing a pair of parentheses around the conditional:
if ((r.gt.0.58*rstep .and. r.lt.1.42*rstep) .or. (r.gt.2.08*rstep .and. r.lt.2.92*rstep)) xappad = xappad*fakm