Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.
29246 Discussions

Compile errors for Do-loops that worked fine in CVF

TommyCee
Beginner
2,323 Views
The following snippet is some code that worked fine in CVF.  I'm getting these errors for the last 5 nested Do-loops:

error #8093: A do-variable within a DO body shall not appear in a variable definition context.  
error #6511: This DO variable has already been used as an outer DO variable in the same nesting structure.  

[bash]! DETERMINE PERCENTAGES:
 290 Do I=1,16 
       Do J=1,19 
       WSfreq(I,J)=WSfreq(I,J)/TOTAL 
       DPfreq(I,J)=DPfreq(I,J)/TOTAL 
       DBfreq(I,J)=DBfreq(I,J)/TOTAL 
       VSfreq(I,J)=VSfreq(I,J)/TOTAL
     EndDo

     Do I=1,16 
       Do J=1,11 
       RHfreq(I,J)=RHfreq(I,J)/TOTAL
     EndDo
     
     Do I=1,16 
       Do J=1,7 
       STfreq(I,J)=STfreq(I,J)/TOTAL 
     EndDo

     Do I=1,16 
       Do J=1,18 
       FKfreq(I,J)=FKfreq(I,J)/TOTAL
     EndDo

     Do I=1,16 
       Do J=1,96 
       PLfreq(I,J)=PLfreq(I,J)/TOTAL 
       PHfreq(I,J)=PHfreq(I,J)/TOTAL
     EndDo

     Do I=1,96 
       Do J=1,3 
       Do K=1,3 
       FREQ(I,J,K)=FREQ(I,J,K)/TOTAL
     EndDo[/bash]
I have never seen this before.  'I' is only a dummy variable.  Why is there no complain about the 1st nested Do-loop?  It's practically identical.

Any help is appreciated.
0 Kudos
11 Replies
IanH
Honored Contributor III
2,323 Views
The difference is that the first nested do loop uses J as its index variable.

Re-indenting your code to clarify:

[fortran] 290  Do I=1,16        !## 1
        Do J=1,19 
          WSfreq(I,J)=WSfreq(I,J)/TOTAL 
          DPfreq(I,J)=DPfreq(I,J)/TOTAL 
          DBfreq(I,J)=DBfreq(I,J)/TOTAL 
          VSfreq(I,J)=VSfreq(I,J)/TOTAL
        EndDo

        Do I=1,16     !## 2
          Do J=1,11 
            RHfreq(I,J)=RHfreq(I,J)/TOTAL
          EndDo
     
          Do I=1,16   !## 3
            Do J=1,7 
              STfreq(I,J)=STfreq(I,J)/TOTAL 
            EndDo
[/fortran]
The outer loop starting at ## 1 uses i for an index variable.  You are re-using that variable for the nested loops at ## 2 and ## 3, etc.  The language rules do not permit that - an index variable in a do loop can't be changed by any statements inside the do loop (which includes other do statements). 

Consider using variable names such as i1, i2, i3, etc for each level of nesting.
0 Kudos
DavidWhite
Valued Contributor II
2,323 Views
"End Do" only terminates the current loop, not nested loops.

Should your code really be:

Do I ...
    Do J

    End Do
End Do

etc.

Regards,

David
0 Kudos
TommyCee
Beginner
2,323 Views
Thanks Ian.  I guess I'm a little new to F90 "rules" and I never dreamed of that rule!  I won't even begin to ponder the logic or value of it.  But when you say "which includes other do statements", I guess you mean any others in the present scope.  In other words, this renaming of the outer dummy variable (as you will see below for the prestent case - it compiled OK) applies to all such DO-loops within a given scope, right?

[bash]! DETERMINE PERCENTAGES:
 290 Do I=1,16 
       Do J=1,19 
       WSfreq(I,J)=WSfreq(I,J)/TOTAL 
       DPfreq(I,J)=DPfreq(I,J)/TOTAL 
       DBfreq(I,J)=DBfreq(I,J)/TOTAL 
       VSfreq(I,J)=VSfreq(I,J)/TOTAL
     EndDo

     Do I1=1,16 
       Do J=1,11 
       RHfreq(I1,J)=RHfreq(I1,J)/TOTAL
     EndDo
     
     Do I2=1,16 
       Do J=1,7 
       STfreq(I2,J)=STfreq(I2,J)/TOTAL 
     EndDo

     Do I3=1,16 
       Do J=1,18 
       FKfreq(I3,J)=FKfreq(I3,J)/TOTAL
     EndDo

     Do I4=1,16 
       Do J=1,96 
       PLfreq(I4,J)=PLfreq(I4,J)/TOTAL 
       PHfreq(I4,J)=PHfreq(I4,J)/TOTAL
     EndDo

     Do I5=1,96 
       Do J=1,3 
       Do K=1,3 
       FREQ(I5,J,K)=FREQ(I5,J,K)/TOTAL
     EndDo

     Do 360 I6=1,10 
       Fogs(I6)=Fogs(I6)/TOTAL
 360 EndDo[/bash]
0 Kudos
John_Campbell
New Contributor II
2,323 Views
I don't think your original code worked fine with CVF. Note the changes so that each DO start is terminated by it's own END DO.  Using array syntax might simplify your code and remove the multiple DO loops.
[bash]! DETERMINE PERCENTAGES:
 290 Do I=1,16 
       Do J=1,19 
         WSfreq(I,J)=WSfreq(I,J)/TOTAL 
         DPfreq(I,J)=DPfreq(I,J)/TOTAL 
         DBfreq(I,J)=DBfreq(I,J)/TOTAL 
         VSfreq(I,J)=VSfreq(I,J)/TOTAL
       EndDo
     END DO

     Do I=1,16 
       Do J=1,11 
         RHfreq(I,J)=RHfreq(I,J)/TOTAL
       EndDo
     END DO
     
     Do I=1,16 
       Do J=1,7 
         STfreq(I,J)=STfreq(I,J)/TOTAL 
       EndDo
     END DO

     Do I=1,16 
       Do J=1,18 
         FKfreq(I,J)=FKfreq(I,J)/TOTAL
       EndDo
     END DO

     Do I=1,16 
       Do J=1,96 
         PLfreq(I,J)=PLfreq(I,J)/TOTAL 
         PHfreq(I,J)=PHfreq(I,J)/TOTAL
       EndDo
     END DO

     Do I=1,96 
       Do J=1,3 
         Do K=1,3 
           FREQ(I,J,K)=FREQ(I,J,K)/TOTAL
         EndDo
       END DO
     END DO


[/bash]
0 Kudos
IanH
Honored Contributor III
2,323 Views
I meant other do statements using i that are in the same scope that are nested inside a do that uses i as the control variable. 

So your latest snippet is ok - you don't re-use i as a control variable inside the construct that starts with the statement labelled 290.  Similarly, all the do loops that use j are not nested inside each other.

This isn't new to F90 - Fortran 66 and Fortran 77 have the same restriction.  What's changed is the compiler's ability to detect mistakes made by the programmer.
0 Kudos
jimdempseyatthecove
Honored Contributor III
2,323 Views

Tommy,

I think your first issue derived from you making a conversion from F77:

        Do 5000 I=1,96
          Do 5000 J=1,3
          Do 5000 K=1,3
          FREQ(I,J,K)=FREQ(I,J,K)/TOTAL   
5000 CONTINUE

And replaced the one CONTINUE statement with one ENDDO statement.

The above loop in f90 form using ENDDO requires no lable number (5000) and one ENDDO per DO.

Jim Dempsey

0 Kudos
TommyCee
Beginner
2,323 Views
All very interesting.

John, I assure you that this worked perfectly w/ CVF.  Of the 2 avenues for remedy here, John's seemed the simplest.  However, I tried it and got the same compiler errors!

The only remedy that worked was Ian's.  It appears that the nested DO-loops can share the same EndDo.

As I say, I have never seen this kind of conflict before among independent (self-contained) nested DO-loops within a scoping unit - in this case, a subroutine.  But I'll do what I have to do to make the compiler happy.

BTW, the I-index for another Do-loop shown in L42-44 (not a nested DO-loop) also had to be renamed, as follows:

[bash]! DETERMINE PERCENTAGES:
 290 Do I=1,16 
       Do J=1,19 
       WSfreq(I,J)=WSfreq(I,J)/TOTAL 
       DPfreq(I,J)=DPfreq(I,J)/TOTAL 
       DBfreq(I,J)=DBfreq(I,J)/TOTAL 
       VSfreq(I,J)=VSfreq(I,J)/TOTAL
     EndDo

     Do I1=1,16 
       Do J=1,11 
       RHfreq(I1,J)=RHfreq(I1,J)/TOTAL
       EndDo
     EndDo
     
     Do I2=1,16 
       Do J=1,7 
       STfreq(I2,J)=STfreq(I2,J)/TOTAL
       EndDo
     EndDo

     Do I3=1,16 
       Do J=1,18 
       FKfreq(I3,J)=FKfreq(I3,J)/TOTAL
       EndDo
     EndDo

     Do I4=1,16 
       Do J=1,96 
       PLfreq(I4,J)=PLfreq(I4,J)/TOTAL 
       PHfreq(I4,J)=PHfreq(I4,J)/TOTAL
       EndDo
     EndDo

     Do I5=1,96 
       Do J=1,3 
       Do K=1,3 
       FREQ(I5,J,K)=FREQ(I5,J,K)/TOTAL
       EndDo
     EndDo

     Do 360 I6=1,10 
       Fogs(I6)=Fogs(I6)/TOTAL
 360 EndDo[/bash]
0 Kudos
TommyCee
Beginner
2,323 Views
I take one thing back:
"It appears that the nested DO-loops can share the same EndDo."

This appears not to be the case after all w/ F90.
0 Kudos
Arjen_Markus
Honored Contributor II
2,323 Views
If it were, then this code would be ambiguous:

do i = 1,10
    do j = 1,20
         write(*,*) i+j
    enddo

    do j = 1,20
         write(*,*) i-j
    enddo

Where should the first loop be terminated?

With FORTRAN 77 there is an indication of the label that the do-loop ends with.
That label can be shared, as it is the do statement that determines the end, not the label.

Regards,

Arjen
0 Kudos
Steven_L_Intel1
Employee
2,323 Views
CVF does not accept the code in the original post.

[plain]C:Projects>df -c t.f90
Compaq Visual Fortran Optimizing Compiler Version 6.6 (Update C)
Copyright 2003 Compaq Computer Corp. All rights reserved.

t.f90
t.f90(14) : Error: This DO variable has already been used as an outer DO variabl
e in the same nesting structure.   
     Do I=1,16
--------^
t.f90(19) : Error: This DO variable has already been used as an outer DO variabl
e in the same nesting structure.   
     Do I=1,16
--------^
t.f90(24) : Error: This DO variable has already been used as an outer DO variabl
e in the same nesting structure.   
     Do I=1,16
--------^
t.f90(29) : Error: This DO variable has already been used as an outer DO variabl
e in the same nesting structure.   
     Do I=1,16
--------^
t.f90(35) : Error: This DO variable has already been used as an outer DO variabl
e in the same nesting structure.   
     Do I=1,96
--------^
t.f90(36) : Error: An unterminated block exists.
       Do J=1,3
^
t.f90(35) : Error: An unterminated block exists.
     Do I=1,96
^
t.f90(29) : Error: An unterminated block exists.
     Do I=1,16
^
t.f90(24) : Error: An unterminated block exists.
     Do I=1,16
^
t.f90(19) : Error: An unterminated block exists.
     Do I=1,16
^
t.f90(14) : Error: An unterminated block exists.
     Do I=1,16
^
t.f90(6) : Error: An unterminated block exists.
 290 Do I=1,16
^
[/plain]
0 Kudos
TommyCee
Beginner
2,323 Views
Thanks for your response, Arjen.  In CVF, the answer to you question would implicitly be L4 (see below).  I believe I have seen this behavior work fine over and over again but I stress - not appling strict F90 standards.  In IVF, especially applying F90 standards (Project|Properties|Fortran|Diagnostics: Warn for Non-standard Fortran - Fortran 90), each DO-loop must have its own termination.

[bash]do i = 1,10
    do j = 1,20
         write(*,*) i+j
    enddo

    do j = 1,20
         write(*,*) i-j
    enddo[/bash]

To take it a bit further, your original code using statement labels might look like this, where termination is unambigous:

[bash]     do 20, i = 1,10
        do 20, j = 1,20
          write(*,*) i+j
20  enddo

     do 30, j = 1,20
       write(*,*) i-j
30  enddo[/bash]
I think this was your point.
0 Kudos
Reply