iofortranmodelingnumerical

Fortran-Segmentation Fault Upon Closing an Input File


Hopefully, someone can help me out with this problem. It would be greatly appreciated.

Background. I am working on extending a piece of Legacy code for our research group that does some heat transfer, thermal convection, etc. type of numerical modeling. What I am trying to do is read in a temperature input file so that I can adjust the temperature of the model as it model progresses in time. While that info is largely irrelevant. I keep getting a segmentation fault upon trying to close a file I opened and am reading from. I have attached the code below along with what a typical temperature input file may look like (but greatly simplified since there will be thousands of data points). Any help would be appreciated in eliminating the segmentation fault and/or correcting the code to make it more efficient.

subroutine Read_Temp_Input(Temp_in)!(dt)!(filename)!,dt,Temp_out)
implicit none

character*80                                :: filename
integer, parameter                          :: dp = selected_real_kind(15)
real(kind=dp), allocatable, dimension(:,:)  :: Temp_in, Temp_out
integer                                     :: i,j,ierror,n
real (kind=dp)                              :: in_time, in_temp, dt, inter_time, inter_temp, max_time
character*80                                :: line


!Variable definitions
!in_time is the time given from the input file
!in_temp is the temp given from the input file
!inter_time is the interpolated time using dt, max_time, and linear interpolation
!inter_temp is the interpolated temp using dt, max_time, and linear interpolation
!max_time is the largest time value in the input file
!dt is the time step utilized in the simulation, provided by main routine

!read in the temperature input file
filename = "temps.txt"
Open(UNIT=1,FILE=filename,ACTION="Read")

!Determine the size of the necessary allocation
n = 0
do
    Read(1,*,iostat=ierror) in_time, in_temp
    if (ierror.ne.0) then
        exit
    else
        print*, in_time, in_temp
        n = n + 1
    endif
enddo

!Allocate the Temp_in array to a n x 2 array.
allocate(Temp_in(n,2))

close(unit=1)
Open(UNIT=1,FILE=filename,ACTION="Read")

n = 0

do
    Read(1,*,iostat=ierror) in_time, in_temp
    if (n.ne.0) then
        if (ierror.ne.0) then
            exit
        else
            Temp_in(n-1,0) = in_time
            Temp_in(n-1,1) = in_temp
        endif
    endif
    n = n + 1
enddo

dt = 0.5_dp
print*, 'is the fault before here?'
close(1)
print*, 'is the fault here?'
end subroutine

Temperature File

 Time  Temp
 1     300
 2     400
 3     500
 5     600

Attached is also an output I have been getting. I will get rid of the random print statements in time, just using them as a way to test where my code is breaking.

enter image description here

Thank you for your help, it is greatly appreciated.


Solution

  • Fortran arrays are 1-based by default, and so is Temp_in in your example. So the lines

    Temp_in(n-1,0) = in_time
    Temp_in(n-1,1) = in_temp
    

    will write out of bounds (for n=1, both are out of bounds and the first one is always out of bounds).

    You can make the compiler check that for you by using the --check=bounds flag, it will then throw a runtime error if you attempt to access an array in that manner.

    So either allocate Temp_in as

     allocate(Temp_in(0:n-1,0:1))
    

    or use 1-based indices for writing as a solution.


    UPDATE

    Also, reading the first line of the example temps.txt file will fail when determining the number of entries, as it tries to read two real but instead finds something else. So you will need to do a dummy read after opening the file to read in the first line (or use the same additional check as in the second loop)

    Open(UNIT=1,FILE=filename,ACTION="Read")
    ! read in the first line and throw it away
    read(1,*)
    ! go on