Related
I am creating a linked list from the input file. Each node in the linked list includes the information in each block of the input.
When I try to get value from input file, I assigned multiple lines (4 lines each time) into a 1D array "tmp". I think the DO-loop I used in the "input:DO" loop is wrong. But I do not know how to solve.
I use gfortran to compile and no mistake come out for compiling.
I have tried WRITE for testing in the "input:DO" loop for testing. The result shows that I can open the input file successfully.
PROGRAM read
IMPLICIT NONE
INTEGER,PARAMETER :: nat=4
character(len=20) :: filename
!Derived types to store atom data
TYPE :: atom
CHARACTER(LEN=2) :: atom_name
REAL, DIMENSION(3) :: coord
END TYPE atom
!The array info stores info of all atom in one time step
type :: atom_seq
type(atom),dimension(nat):: info
type(atom_seq),pointer :: p
end type atom_seq
TYPE (atom_seq), POINTER :: head
TYPE (atom_seq), POINTER :: tail
type(atom), dimension(nat) :: temp
! Declare variable
INTEGER :: istat
INTEGER :: i=0, n=0
! Open input data file
WRITE(*,*) 'ENTER the file name with the data to be read: '
READ(*,'(A20)') filename
NULLIFY(head)
OPEN( UNIT=9, FILE=TRIM(filename), STATUS="OLD", ACTION="READ", IOSTAT=istat)
! Was the open successful
fileopen: IF (istat == 0) THEN
input: DO
!WRITE(*,*) "OPEN done " ! for testing
READ(9,*) ! <--when run, error is in this line
READ(9,*)
DO i = 1, nat
READ(9,*,IOSTAT=istat) temp(i)%atom_name, temp(i)%coord(1), temp(i)%coord(2), temp(i)%coord(3)
ENDDO
IF (istat /= 0) EXIT
n = n + 1 ! Bump count
IF (.NOT. ASSOCIATED(head) ) THEN ! No values in list
ALLOCATE(head, STAT=istat) ! Allocate new value
tail => head ! Tail points to new value
NULLIFY(tail%p) ! Nullify p in new value
DO i = 1, nat ! Store number
tail%info(i)%atom_name = temp(i)%atom_name
tail%info(i)%coord(1) = temp(i)%coord(1)
tail%info(i)%coord(2) = temp(i)%coord(2)
tail%info(i)%coord(3) = temp(i)%coord(3)
ENDDO
ELSE ! Values already in list
ALLOCATE(tail%p, STAT=istat) ! Allocate new value
tail => tail%p
NULLIFY(tail%p)
DO i = 1, nat ! Store number
tail%info(i)%atom_name = temp(i)%atom_name
tail%info(i)%coord(1) = temp(i)%coord(1)
tail%info(i)%coord(2) = temp(i)%coord(2)
tail%info(i)%coord(3) = temp(i)%coord(3)
ENDDO
END IF
END DO input
ELSE fileopen
WRITE(*,1030) istat
1030 FORMAT ('File open failed --status = ', I6)
END IF fileopen
END PROGRAM read
The input file: inp
4
Particles:1_0
O 0.8050005000 0.7000000000 3.2350000000
H 1.4750005000 1.2800000000 2.8650000000
H 0.8550005000 -0.0900000000 2.7150000000
O 0.4050005000 0.7500000000 -4.1350000000
4
Particles:1_5
O 0.8799478358 0.6383317306 3.1569568025
H 1.4046592860 1.2232485826 2.4978364665
H 1.1472783731 -0.2687458123 3.0229092093
O 0.5392992531 0.6047144782 -4.0811918365
4
Particles:1_10
O -3.8021765454 3.1600783692 -4.5455655916
H -4.5320715486 3.0937504111 4.9514896261
H -3.5088238380 4.0613340230 -4.5394597924
O -3.3469012765 -0.7064128847 1.2465212113
and the error is
hg#xi /home/hg/pole $ ./read
ENTER the file name with the data to be read:
inp
At line XXX of file read.f95 (unit = 9, file = 'inp')
Fortran runtime error: End of file
Error termination. Backtrace:
#0 0x7f1c1fdbb31a
#1 0x7f1c1fdbbec5
#2 0x7f1c1fdbc68d
#3 0x7f1c1ff32a33
#4 0x7f1c1ff364b7
#5 0x7f1c1ff365b8
#6 0x5566d3dc9daf
#7 0x5566d3dca9ed
#8 0x7f1c1f9d0b96
#9 0x5566d3dc9a79
#10 0xffffffffffffffff
I hope to fix the problem. If my idea is wrong, please give some suggestions to design a better data structure to save data in the input (The input file may have thousands of blocks, instead of 3. It is big and the number of blocks is unknown before running the code. )
There is a test on the IOSTAT missing with the first executed READ in the loop. When the result is not OK the loop can be terminated e.g. change:
fileopen: IF (istat == 0) THEN
input: DO
!WRITE(*,*) "OPEN done " ! for testing
READ(9,*) ! <--when run, error is in this line
READ(9,*)
in
fileopen: IF (istat == 0) THEN
input: DO
!WRITE(*,*) "OPEN done " ! for testing
READ(9,*,IOSTAT=istat)
IF (istat /=0) EXIT
READ(9,*)
I have 4 .mtx files that I am reading the values from. Two of them run perfectly when read from with no issues and produce the correct outputs into a .DAT file. However, the last 2 are extremely large files; it appears the code correctly reads from the files and runs, but I get no outputs and no errors when reading from these 2...not even the code timer prints the time. Any help is much appreciated! Here is the code:
program proj2matrixC40
implicit none
integer,parameter::dp=selected_real_kind(15,307)
! Set Global Variables
real(kind=dp), allocatable::Ax(:,:),A(:,:),Iglobal(:,:)
integer::At(1,3)
integer::nnz,w,n,k,ii,ff,kk
real(kind=dp)::t1,t2
call cpu_time(t1)
open(unit=78,file="e40r5000.mtx",status='old')
read(78,*) At
close(unit=78)
nnz = At(1,3)
n = At(1,1)
k = 40
kk = 35
allocate(Ax(nnz+1,3),A(nnz,3),Iglobal(k,k))
open(unit=61,file="e40r5000.mtx",status='old')
do w=1,nnz+1
read(61,*) Ax(w,:)
end do
open (unit = 53, file = "proj2matrixC40points.dat")
do ff=1,k
do ii=1,k
Iglobal(ii,ff) = (ii/ff)*(ff/ii)
end do
end do
A(1:nnz,:) = Ax(2:nnz+1,:)
call Arno(A)
call cpu_time(t2)
print '("Time elapsed = ",f10.8," seconds")', (t2 - t1)
contains
subroutine Arno(a)
real(kind=dp), intent(in)::a(:,:)
real(kind=dp),dimension(k,k)::H
real(kind=dp),dimension(k,k+1)::u,q,qconj
real(kind=dp),dimension(k,1)::x0
integer::j,f
call random_number(x0)
q(:,1) = x0(:,1)/norm2(x0(:,1))
do f=1,k
call spmat(a,q(:,f),u(:,f))
do j=1,f
qconj(j,:) = (q(:,j))
H(j,f) = dot_product(qconj(j,:),u(:,f))
u(:,f) = u(:,f) - H(j,f)*q(:,j)
end do
if (f.lt.k) then
H(f+1,f) = norm2(u(:,f))
if (H(f+1,f)==0) then
print *, "Matrix is reducible"
stop
end if
q(:,f+1) = u(:,f)/H(f+1,f)
end if
if (f==k) then
call qrit(H)
end if
end do
end subroutine
! QR Iteration with Shifts Subroutine
subroutine qrit(a)
real(kind=dp), intent(in)::a(:,:)
real(kind=dp)::sigmak
real(kind=dp),dimension(kk,k)::dia
real(kind=dp),dimension(k,k)::Qfinal,Rfinal,HH
real(kind=dp),dimension(k,k,kk)::H0,needQR
integer::v,z
HH = a
H0(:,:,1) = HH
do v=1,kk
sigmak = H0(k,k,v)
if (v-1==0) then
needQR(:,:,v) = HH - sigmak*Iglobal
else
needQR(:,:,v) = H0(:,:,v-1) - sigmak*Iglobal
end if
call givens2(needQR(:,:,v),Rfinal,Qfinal)
H0(:,:,v) = matmul(Rfinal,Qfinal) + sigmak*Iglobal
do z = 1,k
dia(v,z) = H0(z,z,v)
write(53,*) v," ", dia(v,z) ! Write values to .DAT file
end do
end do
end subroutine
! Sparse Matrix Vector Multiplication Subroutine
subroutine spmat(a,b,c)
real(kind=dp), intent(in)::a(:,:)
real(kind=dp), intent(in), dimension(k,1)::b
real(kind=dp), intent(out), dimension(k,1)::c
integer::m,rowi,columni
real(kind=dp), dimension(k,1)::x,y
x = b
y(:,1) = 0
do m = 1,nnz
rowi = a(m,1)
columni = a(m,2)
y(rowi,1) = y(rowi,1) + a(m,3)*x(columni,1)
end do
c(:,1) = y(:,1)
end subroutine
! QR Factorization Givens Rotations Subroutine
subroutine givens2(a,Rfinal,Qfinal)
real(kind=dp), intent(in)::a(:,:)
real(kind=dp), dimension(k,k,(k*k))::G,QQ
real(kind=dp), dimension(k,k), intent(out)::Rfinal,Qfinal
real(kind=dp), dimension(k,k)::I2,y,aa
real(kind=dp), dimension(1,k)::ek1,ek2
real(kind=dp)::c,s
integer::kt,m,nn,j,i,l,p
m = size(a,1)
nn = size(a,2)
aa = a
i = 1
do kt=1,nn-1
do j=m,kt+1,-1
if (aa(j,kt).eq.0) then
continue
else
ek1(1,:) = 0
ek2(1,:) = 0
do p=1,m
do l=1,m
I2(l,p) = (l/p)*(p/l)
end do
end do
c = aa(kt,kt)/sqrt(aa(kt,kt)**2 + aa(j,kt)**2)
s = aa(j,kt)/sqrt(aa(kt,kt)**2 + aa(j,kt)**2)
ek1(1,kt) = c
ek1(1,j) = s
ek2(1,kt) = -s
ek2(1,j) = c
I2(kt,:) = ek1(1,:)
I2(j,:) = ek2(1,:)
G(:,:,i) = I2
if (i.eq.1) then
QQ(:,:,i) = G(:,:,i)
else
QQ(:,:,i) = matmul(G(:,:,i),QQ(:,:,i-1))
end if
y = matmul(G(:,:,i),aa)
aa = y
if (kt.eq.nn-1) then
if (j.eq.kt+1) then
Qfinal = transpose(QQ(:,:,i))
Rfinal = aa
end if
end if
i = i + 1
end if
end do
end do
end subroutine
end program proj2matrixC40
A couple notes. The line which I put asterisks around (for this question) call mat_print('H',H) can't be deleted otherwise I get the wrong answers (this is strange...thoughts?). Also so your computer won't freeze opening the big files, their names are 'e40r5000.mtx' and 's3dkt3m2.mtx' (these are the two I have issues with). I am using gfortran version 8.1.0
Here is the link to the files
https://1drv.ms/f/s!AjG0dE43DVddaJfY62ABE8Yq3CI
When you need to add a call to a subroutine that shouldn't actually change anything in order to get things working, you probably have a memory corruption. This happens most often when you access arrays outside of their boundaries.
I have compiled it with some run time checks:
gfortran -o p2m -g -O0 -fbacktrace -fcheck=all -Wall proj2mat.f90
And it's already giving me some issues:
It's warning me about implicit type conversions. That shouldn't be too much of an issue if you trust your data.
In line 46 you have an array length mismatch (x0(:, 1) has length 40, q(:,1) is 41)
Similarly on line 108 (x=b) x is really large, but b is only 41 long.
I have stopped now, but I implore you to go through your code and clean it up. Use the compiler options above which will let you know when and where there is an array bound violation.
I'm trying to open 6 different files (at least) and then read the number of lines in each file, which should be about 20,000 lines each. I've read some posts on this forum about how to do that as I'm a newbie, and I've tried to implement it for my purposes.
I can do this individually without any problem, but when I try to read in all the files, I get an error message. I get either the "Killed: 9" error message or a malloc error:
malloc: *** mach_vm_map(size=63032829050880) failed (error code=3)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
What does this error mean regarding memory allocation? What am I doing wrong? How do I go about correcting this?
PROGRAM X
IMPLICIT NONE
INTEGER :: J,IO,NFILES,NLINES
CHARACTER (LEN=128) :: FILENAME
NFILES = 6
NLINES = 0
DO J = 0,NFILES-1
WRITE(FILENAME,'(A,I7.7,A)') 'data_',J*200,'.txt'
OPEN(1,FILE='FILENAME',FORM='FORMATTED')
DO
READ(1,*,IOSTAT=IO)
IF (IO/=0) EXIT
NLINES = NLINES + 1
END DO
WRITE(*,*) NLINES
CLOSE(1)
END DO
END PROGRAM X
I am using gfortran to compile.
UPDATE
I created 6 test files, data_0000000.txt, data_0000200.txt, ..., data_0001000.txt, each with less than 10 lines where there are less than 100 characters in each line. Unfortunately, I get the same error.
Obligatory disclaimer: If you just want to know the number of lines in a file, use wc -l <filename>. Don't reinvent the wheel if you don't have to.
I write this not necessarily because I think you didn't know that, but because someone else might come along, and think they need to write their own program to get the number of lines of files.
As for your question: I don't know why you get a malloc error. Maybe tell us which compiler and system you're using (including versions)? That said, there are three things that I noticed when reading your code:
You create a variable FILENAME, but then you don't use it. You're quoting it: FILE='FILENAME' which means that the open command looks for a file literally called FILENAME, not for a file with the name stored in the variable FILENAME. Remove the quotes:
OPEN(1, FILENAME=FILENAME, FORM='FORMATTED')
You use the unit number 1 -- that is dangerous. Different version of Fortran use specific unit numbers for specific uses. Use a handle far larger (at least 10, or more), or, even better, use the newunit descriptor in the open statement:
INTEGER :: u
OPEN(NEWUNIT=u, FILE=FILENAME, ACTION='READ', FORM='FORMATTED')
READ(u, *, IOSTAT=IO)
CLOSE(u)
You're not resetting the NLINES variable to 0 between files. The program will print a cumulative sum, not the number of lines for each file directly.
Adding to #chw21's response, if your sole purpose is to count the number of records (lines) in a file, here is a modular solution and a test program along with it (the counting is done inside subroutine getNumRecordInFile()):
module NumRecord_mod
implicit none
type :: Err_type
logical :: occurred = .false.
integer :: stat = -huge(0)
character(:), allocatable :: msg
end type Err_type
contains
! returns the number of lines in a file.
subroutine getNumRecordInFile(filePath,numRecord,Err)
implicit none
character(len=*), intent(in) :: filePath
integer, intent(out) :: numRecord
type(Err_type), intent(out) :: Err
character(len=8) :: record
integer :: fileUnit
logical :: fileExists, isOpen
integer :: iostat
character(*), parameter :: PROCEDURE_NAME = "#getNumRecordInFile()"
Err%occurred = .false.
Err%msg = ""
! Check if file exists
inquire( file=filePath, exist=fileExists, opened=isOpen, number=fileUnit, iostat=Err%stat )
if (Err%stat/=0) then
Err%occurred = .true.
Err%msg = PROCEDURE_NAME // ": Error occurred while inquiring the status of file='" // filePath // "'."
return
end if
if (.not.fileExists) then
Err%occurred = .true.
Err%msg = PROCEDURE_NAME // ": The input file='" // filePath // "' does not exist."
return
end if
if (isOpen) close(unit=fileUnit,iostat=Err%stat)
if (Err%stat>0) then
Err%occurred = .true.
Err%msg = PROCEDURE_NAME // ": Error occurred while attempting to close the open input file='" // filePath // "'."
return
end if
open(newunit=fileUnit,file=filePath,status="old",iostat=Err%stat)
if (Err%stat>0) then
Err%occurred = .true.
Err%msg = PROCEDURE_NAME // ": Error occurred while opening input file='" // filePath // "'."
return
end if
numRecord = 0
do
read(fileUnit,'(A)',iostat=iostat) record
if(iostat==0) then
numRecord = numRecord + 1
cycle
elseif(is_iostat_end(iostat)) then
exit
else
Err%occurred = .true.
Err%stat = iostat
Err%msg = PROCEDURE_NAME // ": Error occurred while reading input file='" // filePath // "'."
return
end if
end do
close(fileUnit,iostat=Err%stat)
if (Err%stat>0) then
Err%occurred = .true.
Err%msg = PROCEDURE_NAME // ": Error occurred while attempting to close the open input file='" // &
filePath // "' after counting the number of records in file."
return
end if
end subroutine getNumRecordInFile
end module NumRecord_mod
program test_numRecord
use NumRecord_mod
implicit none
type(Err_type) :: Err
integer :: numRecord
character(:), allocatable :: filePath
filePath = "main.f95"
call getNumRecordInFile(filePath=filePath,numRecord=numRecord,Err=Err)
if (Err%occurred) then
write(*,*) Err%msg
write(*,*) Err%stat
error stop
else
write(*,*) "Total number of records in file='" // filePath // "': ", numRecord
end if
end program test_numRecord
Now if you put this code in a file named "main.f95" and compile it under Fortran 2008 standard, then it should output the number of lines in your "main.f95" file, which should be something like the following:
$gfortran -std=f2008 *.f95 -o main
$main
Total number of records in file='main.f95': 98
For testing, you can simply copy paste the entire code in the online Fortran compiler here: https://www.tutorialspoint.com/compile_fortran_online.php
But keep in mind to change the compile option -std=f95 to -std=f2008 by going to Project -> Compile Options before executing the code.
Try this change (declaration and read line), there was no variable specified where the line contents shall go, here insert now dummy...
character(len=1000) :: dummy
...
READ(u, '(a)' , IOSTAT=IO) dummy
....
I am attempting read a large data file into Fortran it contains about 40960000 rows, I later convert it to a matrix so it would be 6400 * 6400. When I try my code using a much smaller data set it works fine. However, it tells me that there is a segmentation fault, when I use my larger dataset. I suspect that it is a memory allocation issue. Is there a way to allocate more memory or otherwise correct this problem.
program infectgrid
implicit none
integer :: i, individual, nedge,&
tempinfect_tim_err, dumnum_infalpha0, dumnum_infalpha1, alpha0counter, &
alpha1counter, obsrand, minvalshift
character (LEN = 50) :: parameterfilelabel, parameterfile, networkfilelabel, infectfilenamelabel, networkfile, infectfilename
!allocatable to allow for reading in of individuals and time periods
integer, dimension(:) , allocatable :: xcord, ycord, dummy3, recover_tim1, recover_tim2, &
recover_tim3, recover_tim4, recover_tim5, sampleadjshort, shortsamplecount, &
cov1dum, covlog, covvect1uni
character, dimension (:), allocatable :: rec
integer, dimension (:, :) , allocatable :: link
real, dimension(:) , allocatable :: alphavect
call random_seed
open(12, file = "filenamesinfection.txt", status = "old")
read(12, *) parameterfile, networkfile, infectfilename
close(12)
open(12, file = parameterfile, status = "old")
read(12, *) individualname, alpha0name, alpha1name
read(12, *) individual, alpha0, alpha1
nedge = individual*individual
allocate(rec(1:nedge))
allocate(xcord(1:nedge))
allocate(ycord(1:nedge))
allocate(dummy3(1:nedge))
allocate(sampleadjshort(1:nedge))
allocate(shortsamplecount(1:nedge))
allocate(covlog(1:nedge))
allocate(cov1dum(1:nedge))
allocate(link(1:individual, 1:individual))
link = 0
covlog = 0
print *, individual, alpha0, alpha1
print *, link(individual, individual)
print *, "test"
open(10, file = networkfile, status = "old")
print *, networkfile
print *, "test"
do i = 1, nedge
read ( 10, *) rec(i), xcord(i), ycord(i), dummy3(i), cov1dum(i), sampleadjshort(i), shortsamplecount(i)
if (dummy3(i) == 1) then
link(xcord(i), ycord(i)) = 1
end if
if (xcord(i) == ycord(i)) then
covlog(i) = 1
end if
end do
close(10)
covvect1uni = pack(cov1dum, covlog == 1)
print *, "xcord", xcord(nedge), "ycord", ycord(nedge)
print *, link(individual, individual)
print *, "test"
The file prints out the first and second "test" but does not print out the link statement nor the line starting with "xcord" and soon after gives me a segmentation fault i.e. Segmentation fault nohup ./swnetworkinfectrecoveralpha05covgeo2.out
as to compiler options, I think that I am using most of what is available: ifort -free -O2 -stand f03 -check bounds -traceback -warn all -fstack-protector -assume protect_parens -implicitnone -o swnetworkinfectrecoveralpha05covgeo2.out swnetworkinfectrecoveralpha05covgeo2.f90
Dear All, I am writing a code that writes the out put in multiple files named as 1.dat, 2.dat, ..... Here is my code but it gives some unusual output. May you tell me what is wrong in my code please? Basically I could not get the correct syntax to open multiple files, write on them and close before the next file is opened. Thank you. My Code:
implicit double precision (a-h,o-z),integer(i-n)
dimension b(3300,78805),bb(78805)
character*70,fn
character*80,fnw
nf = 3600 ! NUMBER OF FILES
nj = 360 ! Number of rows in file.
do j = 1, nj
bb(j) = 0.0
end do
c-------!Body program-----------------------------------------------
iout = 0 ! Output Files upto "ns" no.
DO i= 1,nf ! LOOP FOR THE NUMBER OF FILES
if(mod(i,180).eq.0.0) then
open(unit = iout, file = 'formatted')
x = 0.0
do j = 1, nj
bb(j) = sin(x)
write(iout,11) int(x),bb(j)
x = x + 1.0
end do
close(iout)
iout = iout + 1
end if
END DO
11 format(i0,'.dat')
END
So there are a few things not immediately clear about your code, but I think here the most relevant bits are that you want to specify the filename with file = in the open statement, not the formatting, and looping over units with iout is problematic because you'll eventually hit system-defined units for stdin and stdout. Also, with that format line it looks like you're getting ready to create the filename, but you never actually use it.
I'm not sure where you're; going with the mod test, etc, but below is a stripped down version of above which just creates the files ina loop:
program manyfiles
implicit none
character(len=70) :: fn
integer, parameter :: numfiles=40
integer, parameter :: outunit=44
integer :: filenum, j
do filenum=1,numfiles
! build filename -- i.dat
write(fn,fmt='(i0,a)') filenum, '.dat'
! open it with a fixed unit number
open(unit=outunit,file=fn, form='formatted')
! write something
write(outunit, *) filenum
! close it
close(outunit)
enddo
end program manyfiles
In my case, I want the file name have an prefix likedyn_
program manyfiles
implicit none
character(len=70) :: filename
integer, parameter :: numfiles=40
integer, parameter :: outunit=44
integer :: filenum, j
do filenum=1,numfiles
write(filename,'("dyn_",i0,".dat")') filenum
open(unit=outunit,file=filename, form='formatted')
write(outunit, *) filenum
close(outunit)
enddo
end program manyfiles