Asif17
Asif17

Reputation: 11

Fortran Arrays change values automatically

I am doing my maser thesis on WIND turbine simulation On ANSYS CFX.To calculate a parameter I have to use a code written in FORTRAN. I am facing a very weird type of problem and need your help.The complete fortran code is quite long but I will only post the subroutine in the code that is causing problem.

I am using a subroutine to divide the blade in a no of radial elements.Two types of division is used and the radial positions of the elements are then stored in two 1-D arrays RI and RJ.

Later in the code, I got some error and I traced it back to this subroutine that it is not giving me correct values of RJ .The subroutine is giving correct values of RI. Then I displayed the results of RJ using the same loop in which it is calculated correct values of RJ. Fortunately the values of RJ were correct. Then in the same subroutine, immediately after that loop, I started another loop to display the values of RJ again and unfortunately this time they were not correct incorrect values of RJ even there is nothing between the two loops that could change the values of RJ. seemingly every element of RJ is replaced with the next element of RI. Hence I came to know that here is the error originating. I have rechecked the program and seemingly there is no error and the error is originating somewhere inside the subroutine. I am using another program on fortran without ANSYS CFX to calculate wind turbine performance using same subroutine and this problem is NOT coming in that program although the two subroutines in the two programs are exactly same. I need help in this matter as I am stuck in it for past few days. I am using Intel fortran compiler that comes with INTEL COMPOSER.

The subroutinea are as follows

CALL INIT(M,PI,PREC,R,HUBRAD,RI,RJ)

SUBROUTINE INIT(M,PI,PREC,R,HUBRAD,RI,RJ)


  INTEGER:: M
  REAL:: PI,PREC,R,HUBRAD
  REAL:: RI(41),RJ(41)
  !,RRI,RRJ)

    CALL LLPOINTS (PI,PREC,R,HUBRAD,M,RI,RJ)


    return
    End Subroutine

    SUBROUTINE LLPOINTS (PI,PREC,R,HUBRAD,M,RI,RJ)

  !Input arguments: M,Pi, PREC, R, HUBRAD 
  !Output arguments : RI, RJ

  INTEGER:: M
  REAL::PREC,R,HUBRAD
  REAL:: RI(41),RJ(41)
  INTEGER :: J
  character*100 ::string1, string2, string3

  CALL MESAGE( 'WRITE', 'subroutine INIT START' )  

  CALL MESAGE( 'WRITE', "RI   RJ    DJ")

  DO J=1,M+1   


        IF (J.LT.M+1) THEN   
        RI(J)=0.5E+00*(1.E+00+HUBRAD/R)-0.5E+00*(1.E+00-HUBRAD/R)
       &*COS((J-0.5E+00)*PI/M)

        RJ(J)=0.5E+00*(1.E+00+HUBRAD/R)-0.5E+00*(1.E+00-HUBRAD/R)
       &*COS((J-1.E+00)*PI/M)


        IF (ABS(RI(J)).LT.(1/PREC)) THEN

              STOP 
        ENDIF

        ELSE
           RJ(J)=1.E+00

          END IF


          write (string1,*) RI(J)
          write (string2,*) RJ(J)


          CALL MESAGE( 'WRITE', string1//' '//string2) 

      END DO

      CALL MESAGE( 'WRITE','ri     rj')
      do j =1,m

          write (string1,*) RI(J)
          write (string2,*) RJ(J)
          CALL MESAGE( 'WRITE', string1//' '//string2 ) 

      end do
      CALL MESAGE( 'WRITE', 'subroutine LLINE OK' )  

  END SUBROUTINE

You would be wondering why LLPOINTS is INSIDE INIT subroutine without any reason. Actually in the original program the subroutine INIT has a lot of other subroutines. I used only LLPOINTS and discarded rest of them as I did not need them

I have checked that my program does not have implicit none in any of the subroutines which according to my limited knowledge should be present. When I added implicit none to all subroutines, a number of compilation errors have occurred and seemingly in those errors, I have found that there were problems related to the declarations of a number of variables . I have resolved these issues and now when all issues are resolved, I have got the following error in compilation which was not coming before implicit none.

Error:unresolved external symbol LLINE referenced in function ACD_Dp.

I dont know how to deal with this error

Upvotes: 1

Views: 1486

Answers (2)

roygvib
roygvib

Reputation: 7395

The weird behavior might originate from some (incorrect) actual arguments rather than subroutines themselves. To explain this, we first consider a simplified version of INIT() and LLPOINTS() as follows:

subroutine INIT ( a, b )
    implicit none
    real :: a( 5 ), b( 5 )

    call LLPOINTS ( a, b )
end subroutine

subroutine LLPOINTS ( a, b )
    implicit none
    real :: a( 5 ), b( 5 )
    integer :: i

    print *, "output (1):"
    do i = 1, 5
        a( i ) = i                !! set some values to a(:) and b(:)
        b( i ) = i * 100
        print *, a( i ), b( i )   !! check the values
    enddo

    print *, "output (2):"
    do i = 1, 4
        print *, a( i ), b( i )   !! check the values again
    enddo
end subroutine

This program sets some values to a(:) and b(:) and prints their values twice for double check (as in the OP's program). Now we consider the main program:

program main
    real :: a( 5 ), b( 5 )
    call INIT ( a, b )
end

which gives the expected result (with ifort test.f90 with v14.0):

 output (1):
   1.000000       100.0000
   2.000000       200.0000
   3.000000       300.0000
   4.000000       400.0000
   5.000000       500.0000
 output (2):
   1.000000       100.0000
   2.000000       200.0000
   3.000000       300.0000
   4.000000       400.0000

Next, let us suppose that a and b are declared erroneously as scalar variables

program main
    real :: a, b
    call INIT ( a, b )
end

or even with no declaration (i.e., with default implicit real(a-h,o-z) rule)

program main
    call INIT ( a, b )
end

We then obtain

 output (1):
   1.000000       100.0000
   2.000000       200.0000
   3.000000       300.0000
   4.000000       400.0000
   5.000000       500.0000
 output (2):
   1.000000       2.000000
   2.000000       3.000000
   3.000000       4.000000
   4.000000       5.000000

whose pattern seems to be very similar to that of the OP's output (i.e., all the elements are shifted by 1 in output (2)). That is, the reason for this weird behavior might be that we are passing scalars and accessing an invalid memory region (assuming that a and b are aligned contiguously in memory, with some trailing memory area). If so, memory mapping between main() and LLPOINTS() may look like this:

a       b      NG     NG     NG     NG
---------------------------------------
a(1)    a(2)   a(3)   a(4)   a(5)
        b(1)   b(2)   b(3)   b(4)   b(5)

If this is the case, since a(i+1) = b(i), we obtain the weird result in output (2) above. We can confirm this by inserting lines like

if ( loc( a(2) ) == loc( b(1) ) ) stop "trapped (ifort)"

in LLPOINTS(). And more importantly, if we attach

ifort -check test.f90

option, we can detect this automatically (with segmentation fault). So could you try this option to see whether this is the case...?

Upvotes: 1

Asif17
Asif17

Reputation: 11

Yes you are right. I have put the following lines

If ( loc( RJ(1) ) == loc( RI(2) ) ) then
call mesage ('write','trapped (ifort)')

stop

End If

and I have got the error , printing trapped (ifort). But the thing is , I have not declared scalar arguments RI, RJ anywhere. I have always declared them as vectors RI(41) and RJ(41)

Upvotes: 0

Related Questions