2

There are several threads with similar titles of mine, but I do not believe they are the same. One was very similar fortran pass allocated array to main procedure, but the answer required Fortran 2008. I am after a Fortran 90/95 solution.

Another very good, and quite similar thread is Dynamic array allocation in fortran90. However in this method while they allocate in the subroutine, they don't ever appear to deallocate, which seems odd. My method looks on the surface at least to be the same, yet when I print the array in the main program, only blank spaces are printed. When I print in the subroutine itself, the array prints to screen the correct values, and the correct number of values.

In the following a MAIN program calls a subroutine. This subroutine reads data into an allocatable array, and passes the array back to the main program. I do this by using small subroutines each designed to look for specific terms in the input file. All of these subroutines are in one module file. So there are three files: Main.f90, input_read.f90 and filename.inp.

It seems then that I do not know how to pass an array that is allocatable in program Main.f90 as well as in the called subroutine where it is actually allocated, sized, and then deallocated before being passed to program Main. This perhaps sounds confusing, so here is the code for all three programs. I apologize for the poor formatting when I pasted it. I tried to separate all the rows.

main.f90:

Program main 

use input_read ! the module with the subroutines used for reading filename.inp 
implicit none  
REAL, Allocatable            :: epsilstar(:)  
INTEGER                      :: natoms 

call Obtain_LJ_Epsilon(epsilstar, natoms)

print*, 'LJ Epsilon     : ', epsilstar 

END Program main

Next is the module with a subroutine (I removed all but the necessary one for space), input_read.f90:

module input_read  
contains  
!===============================================================  
!===============================================================    
Subroutine Obtain_LJ_Epsilon(epsilstar,natoms)  
! Reads epsilon and sigma parameters for Lennard-Jones Force-Field and also
! counts the number of types of atoms in the system
!===============================================================
!===============================================================  
 INTEGER                                :: error,line_number,natoms_eps,i  
 CHARACTER(120)                         :: string, next_line, next_next_line,dummy_char  
 CHARACTER(8)                           :: dummy_na,dummy_eps      
 INTEGER,intent(out)                    :: natoms  
 LOGICAL                                :: Proceed  
 real, intent(out), allocatable       :: epsilstar(:)  

 error = 0  
 line_number = 0  
 Proceed = .true.  

 open(10,file='filename.inp',status='old')

 !=============================================  
 !          Find key word LJ_Epsilon  
 !============================================= 

 DO 
     line_number = line_number + 1  

     Read(10,'(A120)',iostat=error) string  

     IF (error .NE. 0) THEN  
     print*, "Error, stopping read input due to an error reading line"  
     exit  
     END IF  

     IF (string(1:12) == '$ LJ_epsilon') THEN  

        line_number = line_number + 1  
        exit  

     ELSE IF (string(1:3) == 'END' .or. line_number > 2000) THEN  

         print*, "Hit end of file before reading '$ LJ_epsilon' "  
         Proceed = .false.  
         exit  

    ENDIF  
ENDDO 

!========================================================  
! Key word found, now determine number of parameters
! needing to be read 
!========================================================

  natoms_eps = -1  
dummy_eps = 'iii'

do while ((dummy_eps(1:1) .ne. '$') .and. (dummy_eps(1:1) .ne. ' '))  

        natoms_eps = natoms_eps + 1  
        read(10,*) dummy_eps  

enddo !we now know the number of atoms in the system (# of parameters) 

close(10)

Allocate(epsilstar(natoms_eps))
epsilstar = 0.0
!============================================================  
! Number of parameters found, now read their values  
!============================================================
if(Proceed) then

    open(11,file='filename.inp',status='old')

    do i = 1,line_number-1  
        read(11,*) ! note it is not recording anything for this do loop  
    enddo  

    do i = 1,natoms_eps  

        read(11,*) dummy_char  
        read(dummy_char,*) epsilstar(i) ! convert string read in to real, and store in epsilstar  

    enddo  

    close(11)   

    PRINT*, 'LJ_epsilon: ', epsilstar ! printing to make sure it worked  
endif 

deallocate(epsilstar)
END Subroutine Obtain_LJ_Epsilon

end module input_read  

And finally the input file: filename.inp

# Run_Type  
NVT

# Run_Name  
Test_Name

# Pressure  
1.0

# Temperature  
298.15

# Number_Species 

# LJ_epsilon  
117.1  
117.1  
117.1  

# LJ_sigma  
3.251  
3.251  
3.251  

END

And again, I can't figure out how to pass the allocated epsilstar array to the main program. I have tried passing an unallocated array to the subroutine from the main.f90, allocating it inside, passing it back, and deallocating it in the main.f90, but that did not work. I have tried it as the code currently is... the code works (i.e. is bug free) but it does not pass epsilstar from the subroutine where it correctly finds it and creates an array.

Community
  • 1
  • 1
Charlie Crown
  • 1,071
  • 2
  • 11
  • 28
  • Note that allocatable arguments, as you are using in your code, are a Fortran 2003 standard feature. – IanH Apr 21 '17 at 21:54
  • That is good to know. Thanks! Is there an easy description of how to pass pass the array in Fortran 90/95? One way that I don't really like is to first have a subroutine that goes through and gets the sizes of the things I am after, then there is no need for allocation. Would that be the Fortran 90/95 method? – Charlie Crown Apr 21 '17 at 22:19

1 Answers1

1

It turns out that the mistake I made was in deallocating the array in the subroutine before passing it to the main program. By NOT deallocating, the array was sent back fine. Also, I do not deallocate in the main program either.

Charlie Crown
  • 1,071
  • 2
  • 11
  • 28
  • 1
    Notice how little feedback you received. No comments or answers. Try to make your questions more consise. It is fine that you included all the code, don't change that, but try to make a shorter code that still exhibits the problem (a [mcve]). Delete parts of the code until it stops doing what you need. And the *most important* thing: don't include that much text, go straight to the point. – Vladimir F Героям слава Apr 21 '17 at 19:39
  • I am curious if I should even keep it up since I solved it myself a while after posting it. It seems redundant. Perhaps it would be useful for others, but like you said, it is kind of bulky. – Charlie Crown Apr 21 '17 at 20:04