Context: I have the intention to put a certain Fortran subroutine to some tests to see what is wrong with it. It's a numerical simulation and the results are not matching with theory. I use the write statement to do some simple debugging.
The problem: While a file is open in my main routine, I can't seem to write anything to the screen (so I can't check which stuff are being incorrectly passed to a certain chain of subroutines and etc.). It writes all fine when I do it before opening the file, but not inside it (after opening and after closing it).
Here is the code I'm referring to:
WRITE(*,*) 'BLA !<---------------------------------------
WRITE(*,*) 'BLA BLA' !<---------------------------------------
do p=1,N !open files
write(posvel, "(a,i0,a)") "1Dposveldatacomelasticaxy1", p, ".dat"
OPEN(unit=p, file=trim(posvel), status="unknown")
end do
WRITE(*,*) 'bla' !<---------------------------------------
t = tmin
cont = 0
do while ((t + dt) < (tmax))
t = t+dt
cont = cont+1
do i = 1, N
forcax(i) = 0.0d0
forcay(i) = flagy(i)*gravidade(m(i))
do j = 1, N
call coefficients(m(i), m(j), gama_n, k_n)
Fx_elastica(j,i) = 0.0d0
Fy_elastica(j,i) = 0.0d0
Fx_viscosa(j,i) = 0.0d0
Fy_viscosa(j,i) = 0.0d0
WRITE(*,*) 'inside j loop' !<---------------------------------------
if (i .NE. j) then
if ( (abs(sqrt(((xold(i)-xold(j))**2)+(yold(i)-yold(j))**2))).LE. (a(i)+a(j)) ) then
WRITE(*,*) 'inside collision' !<---------------------------------------
call forca_elastica(k_n, a(i), a(j), xold(i), xold(j), yold(i), yold(j), Fx_elastica(j,i),&
Fy_elastica(j,i))
if (Fx_elastica(j,i) .GT. 0.0d0) then
Fx_elastica(i,j) = -Fx_elastica(j,i)
WRITE(*,*) 'elastic x is being passed' !<---------------------------------------
end if
if (Fy_elastica(j,i) .GT. 0.0d0) then
Fy_elastica(i,j) = -Fy_elastica(j,i)
WRITE(*,*) 'elastic y is being passed' !<---------------------------------------
end if
forcax(i) = forcax(i) + flagex(i)*Fx_elastica(j,i)
forcay(i) = forcay(i) + flagey(i)*Fy_elastica(j,i)
end do
call integracao_Euler_xy (xold(i),xnew(i),vxold(i),vxnew(i),forcax(i),yold(i),ynew(i),vyold(i),vynew(i),forcay(i),m(i))
if (mod (cont,5000).eq. 0) then
WRITE(p, *) int(cont/5000), t, xold(i), yold(i), forcax(i), forcay(i) !<---------------------------------------
end if
end do
end do
do p = 1,N !close files
close(unit=p)
end do
Just look at the WRITE statements. The first two appear on the screen alright. After OPENing the files, though... It doesn't. The WRITE statements that depend on conditions are the ones I want to see, but Fortran is not even writing the ones that don't depend on those conditions. Also, take a look at the last WRITE statement - it writes to the file with no problems.
Any ideas on how to fix/contour this problem?
I'm using Fortran 90.
You should not use small numbers for unit numbers. You are looping from 1 with a step of 1. You are almost guaranteed to hit the pre-connected units for standard output and standard input. See also Standard input and output units in Fortran 90?
Loop from some larger number, say from 100, or use newunit= and store the unit numbers in some array.
Also note that p has value N+1 at WRITE(p, *) ....
Related
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.
The code consists of a do-loop and creates arrays of data as long as running. I need these arrays added to a file as new columns.
The first column is fixed (wavelengths) and the second is generated within the first run:
OPEN (unit=11,file=filename // '.csv')
WRITE(11,'(i4,A1,f10.6)') (lambda(ii),tab,resv(ii), ii=1,nw)
CLOSE(11)
lambda are the wavelengths (4 digits), tab is declared as char(9) and resv are my data (floating). The array consists of nw=2000 items.
First time running the script gives me a nice output which I can load into MS Excel as .csv
However, the script is to return to the beginning of the loop, calculate new data and store the changed "resv" items into a new column.
But when I go like
WRITE(11,'(T17,i4,A1,f10.6)') (lambda(ii),tab,resv(ii), ii=1,nw)
the new data is indeed stored into column 17, but all the data before is being removed!
So how can I tell Fortran to "add" a new column?
Try a variant of this. Have a look at the code in addcolumn. The restriction is that your line can't be more than 1024 characters long. You can increase the size of the array to suit your needs.
module mod_helper
integer, parameter:: AMAX = 10
integer, dimension(AMAX):: coldata
integer:: revision
contains
subroutine init
revision = 0
do ii = 1, AMAX
coldata(ii) = ii
end do
end subroutine init
subroutine increment(howmuch)
integer, intent(in):: howmuch
coldata = coldata + howmuch
end subroutine
subroutine addcolumn(csvname)
character*(*), intent(in) csvname
integer(kind=2):: status
integer:: prevlen
character(1024):: prev, oldname, newname
integer, parameter:: oldfile = 20, newfile = 30
write(oldname, "(A,I3.3,'.csv')") csvname, revision
revision = revision + 1
write(newname, "(A,I3.3,'.csv')") csvname, revision
if (revision .gt. 1) then
! Open the old file
open(oldfile, file=oldname, access="sequential", status="old")
end if
open(newfile, file=newname, access="sequential", status="new", action="write")
prev = ' '
do ii = 1, AMAX
if (revision .gt. 1) then
! read previous contents as a string
read(oldfile, "(A)") prev
prevlen = len(trim(prev))
else
prevlen = 1
end if
! write previous and new contents
write(newfile, "(A, I4, ',')") prev(1:prevlen), coldata(ii)
end do
! delete the previous file
if (revision .gt. 1) close(oldfile, status='delete')
close(newfile)
end subroutine
end module
program main
use mod_helper
call init
call addcolumn('col')
call increment(1)
call addcolumn('col')
call increment(20)
call addcolumn('col')
end program
I have a fortran project linked to various subroutines, which are called from the main program. Variables are passed using modules. I can compile the code without any error. When I run the code, during the subroutine call i get an error "attempt to call a routine with argument number three as a real(kind =1) when procedure was required. I am not sure where i am going wrong. Can someone point out the error? Your help is very much appreciated. The error appears when the subroutine 'ncalc' is called inside the loop
program partbal
use const
use times
use density
use parameters
use rateconst
use ploss
implicit none
integer :: i
real :: nclp_init, ncl2p_init, ncln_init, ne_init
real :: ncl_init, ncl2_init, Te_init, neTe_init
open (10,file='in.dat')
read (10,*)
read (10,*) pressure
read (10,*)
read (10,*) P, pfreq, duty
read (10,*)
read (10,*) nclp_init, ncl2p_init, ncln_init, Te_init, Ti
pi = 3.14159265
R = 0.043
L = 0.1778
Al = 2*pi*R*R
Ar = 2*pi*R*L
V = pi*R*R*L
S = 0.066
e = 1.6e-19
me = 9.1e-31
mCl = 35.5/(6.023e26)
mCl2 = 2*mCl
k = 1.3806e-23
vi = (3*Ti*e/(53.25/6.023e26))**0.5
ncl2_init = pressure*0.1333/(1.3806e-23*298)/2
ncl_init = ncl2_init
ne_init = nclp_init + ncl2p_init - ncln_init
tot_time = 1/(pfreq*1000)
off_time = duty*tot_time
npoints = 10000
dt = tot_time/npoints
neTe_init = ne_init*Te_init
t_step = 0
call kcalc(Te_init)
call param(nclp_init, ncl2p_init, ncln_init, ne_init, ncl_init,ncl2_init, Te_init, Ti)
do i = 1, npoints, 1
t_step = i*dt + t_step
if (t_step > 0 .and. t_step <= 500) then
Pabs = 500
else if (t_step > 500) then
Pabs = 0
end if
if (i <= 1) then
call ncalc(ne_init, ncl_init, ncl2_init, nclp_init, ncln_init, ncl2p_init)
call powerloss(ne_init, ncl_init, ncl2_init, Pabs, neTe_init)
Te = neTe/ne
call kcalc(Te)
call param(nclp, ncl2p, ncln, ne, ncl, ncl2, Te, Ti)
else
call ncalc(ne, ncl, ncl2, nclp, ncln, ncl2p)
call powerloss(ne, ncl, ncl2, Pabs, neTe)
Te = neTe/ne
call kcalc(Te)
call param(nclp, ncl2p, ncln, ne, ncl, ncl2, Te, Ti)
end if
!open( 70, file = 'density.txt' )
!open( 80, file = 'Te.txt')
!do i = 1, 1001, 1
! np(i) = ncl2p(i) + nclp(i)
!write (70, *) ncl(i), ncl2(i), ncl2p(i), nclp(i), np(i), ncln(i), ne(i)
!close(70)
!write (80, *) Te(i), phi(i)
!close(80)
!end do
end do
end program partbal
subroutine ncalc(n_e, n_cl, n_cl2, n_clp, n_cln, n_cl2p)
use parameters
use const
use density
use rateconst
use times
implicit none
real :: n_e, n_cl, n_cl2, n_clp, n_cln, n_cl2p
nclp = (((kCliz*n_e*n_cl)+((kpair+kdisiz)*n_e*n_cl2)-(5e-14*n_clp*n_cln)-(S*n_clp/V)-((hlclp*Al+hrclp*Ar)*n_clp*ubclp))*dt)+n_clp
ncl2p = (((kCl2iz*n_e*n_cl2)-(5e-14*n_cl2p*n_cln) - (((hlcl2p*Al + hrcl2p*Ar)*n_cl2p*ubcl2p)/V)-(S*n_cl2p/V))*dt)+n_cl2p
ncln = ((((katt+kpair)*n_e*n_cl2)-(5e-14*n_clp*n_cln)-(5e-14*n_cl2p*n_cln)-(kdet*n_e*n_cln)-(S*n_cln/V)-(taun*(Al+Ar)/V))*dt)+n_cln
ne = ncl2p+nclp-ncln
ncl = ((((2*kdis+katt+kdisiz)*n_e*n_cl2)-(kCliz*n_e*n_cl)+(5e-14*n_cl2p *n_cln)+(2*5e-14*n_clp*n_cln)+ (kdet*n_e*n_cln) - (300*n_cl) + ((hlclp*Al + hrclp*Ar)*n_clp*ubclp/V)-(S*n_cl/V))*dt)+n_cl
ncl2 = ((n_cl2(1) + (5e-14*n_cl2p*n_cln) - ((kCl2iz+kdis+katt+kpair+kdisiz)*n_e*n_cl2) + (0.5*300*n_cl) + ((hlcl2p*Al + hrcl2p*Ar)*n_cl2p*ubcl2p/V)-(S*n_cl2/V))*dt)+n_cl2
return
end subroutine ncalc
In the line in subroutine ncalc immediately before the return statement, you have a reference to n_cl2(1) very early in the right hand side of the assignment statement. n_cl2 has not been declared as an array, therefore the compiler assumes that it must be a reference to a function that takes a single default integer argument. Because n_cl2 is a dummy argument, the it then expects you to provide a function for the corresponding actual argument when the routine is called.
(How your compiler manages to compile the preceding references to n_cl2 is a bit of a mystery - I suspect this error violates the syntax rules and hence you should see some sort of compile time diagnostic.)
Given you are using modules, it seems odd that you have not placed the ncalc routine in a module. If you did so, the error would probably become a compile time error rather than a runtime.
I wrote a fortran code to read data from a file stored as 2D array of complex variables and output on screen. But during execution an error message Error 57: Attempt to read past end-of-file.
PROGRAM IMPORTFILE
IMPLICIT NONE
INTEGER, PARAMETER :: DP = SELECTED_REAL_KIND(15,60)
COMPLEX(DP),DIMENSION(:,:),ALLOCATABLE :: A,B
INTEGER :: I,J,M,N
N = 12; M = 3
ALLOCATE(A(N,N),B(N,M))
OPEN(UNIT = 20, FILE ='C:\Users\Hp\Desktop\A_matrix.dat', &
ACCESS='SEQUENTIAL', STATUS='OLD', FORM='FORMATTED')
DO I = 1,N
READ(20,FMT = '(2F20.10)')(A(I,J),J = 1,N)
END DO
OPEN(UNIT = 30, FILE ='C:\Users\Hp\Desktop\B_vector.dat',&
ACCESS='SEQUENTIAL', STATUS='OLD', FORM='FORMATTED')
DO I = 1, N
READ(30,FMT = '(2F20.10)')(B(I,J),J = 1, M)
END DO
DO J = 1, N
WRITE(*,*) (B(J,I), I = 1,M)
END DO
DO J = 1, N
WRITE(*,*) (A(J,I), I = 1,N)
END DO
CLOSE(20)
CLOSE(30)
END PROGRAM IMPORTFILE
This format
'(2F20.10)'
Says to read only 2 values. You need to put a repeat specifier as large or larger than your array,
eg:
'(144F20.10)'
Too big is ok.., put 10000f20.10 if you need.
In f2008 you can specify unlimited repeat with *F20.10
(..about time..)
If that doesn't do the trick you should post a sample of what the data file looks like.
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