Related
Recently I want to reproduce the Fig.1(a) of Edge States and Topological Invariants of Non-Hermitian Systems.I used cgeev to solve eigenvalue of non-Hermitian Hamiltonian matrices,I found the solution become wired.
Here is my Fortran code,the result to Fig1.(a) correspond the abs.dat.
module pub
implicit none
complex,parameter::im = (0.0,1.0)
real,parameter::pi = 3.1415926535
integer xn,N,en,kn
parameter(xn = 100,N = xn*2,en = 100)
complex Ham(N,N)
real t1,t2,t3,gam
!-----------------
integer::lda = N
integer,parameter::lwmax=2*N + N**2
complex,allocatable::w(:) ! store eigenvalues
complex,allocatable::work(:)
real,allocatable::rwork(:)
integer lwork
integer info
integer LDVL, LDVR
parameter(LDVL = N, LDVR = N )
complex VL( LDVL, N ), VR( LDVR, N )
end module pub
!=====================================================
program sol
use pub
! Physics memory allocate
allocate(w(N))
allocate(work(lwmax))
allocate(rwork(2*N))
!-----------------
t2 = 1.0
t3 = 0.0
gam = 3.0/4.0
call band()
end program sol
!======================================================
subroutine band()
use pub
integer m1,i
open(11,file="real.dat")
open(12,file="imag.dat")
open(13,file="abs.dat")
do m1 = -en,en
t1 = 3.0*m1/en
call matset()
call eigsol()
write(11,999)t1,(real(w(i)),i = 1,N)
write(12,999)t1,(aimag(w(i)),i = 1,N)
write(13,999)t1,(abs(w(i)),i = 1,N)
end do
close(11)
close(12)
close(13)
999 format(201f11.6)
end subroutine band
!======================================================
subroutine matset()
use pub
real kx
complex sx(2,2),sy(2,2),sz(2,2)
integer k,m1,m2
sx(1,2) = 1.0
sx(2,1) = 1.0
sy(1,2) = -im
sy(2,1) = im
sz(1,1) = 1.0
sz(2,2) = -1.0
!--------
Ham = 0.0
do k = 0,xn-1
if(k == 0)then
do m1 = 1,2
do m2 = 1,2
ham(m1,m2) = t1*sx(m1,m2) + im*gam/2.0*sy(m1,m2)
ham(m1,m2 + 2) = (t2 + t3)/2.0*sx(m1,m2) - im*(t2 - t3)/2.0*sy(m1,m2)
end do
end do
elseif(k == xn-1)then
do m1 = 1,2
do m2 = 1,2
ham(k*2 + m1,k*2 + m2) = t1*sx(m1,m2) + im*gam/2.0*sy(m1,m2)
ham(k*2 + m1,k*2 + m2 - 2) = (t2 + t3)/2.0*sx(m1,m2) + im*(t2 - t3)/2.0*sy(m1,m2)
end do
end do
else
do m1 = 1,2
do m2 = 1,2
ham(k*2 + m1,k*2 + m2) = t1*sx(m1,m2) + im*gam/2.0*sy(m1,m2)
! right hopping
ham(k*2 + m1,k*2 + m2 + 2) = (t2 + t3)/2.0*sx(m1,m2) - im*(t2 - t3)/2.0*sy(m1,m2)
! left hopping
ham(k*2 + m1,k*2 + m2 - 2) = (t2 + t3)/2.0*sx(m1,m2) + im*(t2 - t3)/2.0*sy(m1,m2)
end do
end do
end if
end do
return
end subroutine matset
!==============================================================================
subroutine eigsol()
use pub
! Query the optimal workspace.
LWORK = -1
CALL cgeev( 'Vectors', 'Vectors', N, Ham, LDA, W, VL, LDVL, VR, LDVR, WORK, LWORK, RWORK, INFO)
LWORK = MIN( LWMAX, INT( WORK( 1 ) ) )
! Solve eigenproblem.
CALL cgeev( 'Vectors', 'Vectors', N, Ham, LDA, W, VL, LDVL,VR, LDVR, WORK, LWORK, RWORK, INFO)
! Check for convergence.
IF( INFO.GT.0 ) THEN
WRITE(*,*)'The algorithm failed to compute eigenvalues.'
STOP
END IF
! open(120,file="eigval.dat")
! do m = 1,N
! write(120,*)m,w(m)
! end do
! close(120)
return
end subroutine eigsol
If I used wrong function from Lapack or my code isn't correct.
I use intel fortran,complie command is
*ifort -mkl file.f90 -o a.out
Run program ./a.out&*
I was writing code to use Fortran Eispack routines (compute eigenvalues and eigenvectors, just to check if the values would be different from the ones I got from Matlab), but every time it calls the qzhes subroutine the program hangs.
I load matrixes from files.
Tried commenting the call, and it works without an issue.
I just learned Fortran, and with the help of the internet I wrote this code (which compiles and run):
program qz
IMPLICIT NONE
INTEGER:: divm, i, divg
INTEGER(kind=4) :: dimen
LOGICAL :: matz
REAL(kind = 8), DIMENSION(:,:), ALLOCATABLE:: ma
REAL(kind = 8), DIMENSION(:), ALLOCATABLE:: tabm
REAL(kind = 8), DIMENSION(:,:), ALLOCATABLE:: ga
REAL(kind = 8), DIMENSION(:), ALLOCATABLE:: tabg
REAL(kind = 8), DIMENSION(:,:), ALLOCATABLE:: zet
divm = 1
divg = 2
dimen = 20
matz = .TRUE.
ALLOCATE(ma(1:dimen,1:dimen))
ALLOCATE(tabm(1:dimen))
ALLOCATE(ga(1:dimen,1:dimen))
ALLOCATE(tabg(1:dimen))
OPEN(divm, FILE='Em.txt')
DO i=1,dimen
READ (divm,*) tabm
ma(1:dimen,i)=tabm
END DO
CLOSE(divm)
OPEN(divg, FILE='Gje.txt')
DO i=1,dimen
READ (divg,*) tabg
ga(1:dimen,i)=tabg
END DO
CLOSE(divg)
call qzhes(dimen, ma, ga, matz, zet)
OPEN(divm, FILE='Em2.txt')
DO i=1,dimen
tabm = ma(1:dimen,i)
WRITE (divm,*) tabm
END DO
CLOSE(divm)
OPEN(divg, FILE='Gje2.txt')
DO i=1,dimen
tabg = ga(1:dimen,i)
WRITE (divg,*) tabg
END DO
CLOSE(divg)
end program qz
...//EISPACK subrotines//...
Matrixes:
Gje.txt:https://drive.google.com/file/d/0BxH3QOkswLy_c2hmTGpGVUI3NzQ/view?usp=sharing
Em.txt:https://drive.google.com/file/d/0BxH3QOkswLy_OEtJUGQwN3ZXX2M/view?usp=sharing
Edit:
subroutine qzhes ( n, a, b, matz, z )
!*****************************************************************************80
!
!! QZHES carries out transformations for a generalized eigenvalue problem.
!
! Discussion:
!
! This subroutine is the first step of the QZ algorithm
! for solving generalized matrix eigenvalue problems.
!
! This subroutine accepts a pair of real general matrices and
! reduces one of them to upper Hessenberg form and the other
! to upper triangular form using orthogonal transformations.
! it is usually followed by QZIT, QZVAL and, possibly, QZVEC.
!
! Licensing:
!
! This code is distributed under the GNU LGPL license.
!
! Modified:
!
! 18 October 2009
!
! Author:
!
! Original FORTRAN77 version by Smith, Boyle, Dongarra, Garbow, Ikebe,
! Klema, Moler.
! FORTRAN90 version by John Burkardt.
!
! Reference:
!
! James Wilkinson, Christian Reinsch,
! Handbook for Automatic Computation,
! Volume II, Linear Algebra, Part 2,
! Springer, 1971,
! ISBN: 0387054146,
! LC: QA251.W67.
!
! Brian Smith, James Boyle, Jack Dongarra, Burton Garbow,
! Yasuhiko Ikebe, Virginia Klema, Cleve Moler,
! Matrix Eigensystem Routines, EISPACK Guide,
! Lecture Notes in Computer Science, Volume 6,
! Springer Verlag, 1976,
! ISBN13: 978-3540075462,
! LC: QA193.M37.
!
! Parameters:
!
! Input, integer ( kind = 4 ) N, the order of the matrices.
!
! Input/output, real ( kind = 8 ) A(N,N). On input, the first real general
! matrix. On output, A has been reduced to upper Hessenberg form. The
! elements below the first subdiagonal have been set to zero.
!
! Input/output, real ( kind = 8 ) B(N,N). On input, a real general matrix.
! On output, B has been reduced to upper triangular form. The elements
! below the main diagonal have been set to zero.
!
! Input, logical MATZ, should be TRUE if the right hand transformations
! are to be accumulated for later use in computing eigenvectors.
!
! Output, real ( kind = 8 ) Z(N,N), contains the product of the right hand
! transformations if MATZ is TRUE.
!
implicit none
integer ( kind = 4 ) n
real ( kind = 8 ) a(n,n)
real ( kind = 8 ) b(n,n)
integer ( kind = 4 ) i
integer ( kind = 4 ) j
integer ( kind = 4 ) k
integer ( kind = 4 ) l
integer ( kind = 4 ) l1
integer ( kind = 4 ) lb
logical matz
integer ( kind = 4 ) nk1
integer ( kind = 4 ) nm1
real ( kind = 8 ) r
real ( kind = 8 ) rho
real ( kind = 8 ) s
real ( kind = 8 ) t
real ( kind = 8 ) u1
real ( kind = 8 ) u2
real ( kind = 8 ) v1
real ( kind = 8 ) v2
real ( kind = 8 ) z(n,n)
!
! Set Z to the identity matrix.
!
if ( matz ) then
z(1:n,1:n) = 0.0D+00
do i = 1, n
z(i,i) = 1.0D+00
end do
end if
!
! Reduce B to upper triangular form.
!
if ( n <= 1 ) then
return
end if
nm1 = n - 1
do l = 1, n - 1
l1 = l + 1
s = sum ( abs ( b(l+1:n,l) ) )
if ( s /= 0.0D+00 ) then
s = s + abs ( b(l,l) )
b(l:n,l) = b(l:n,l) / s
r = sqrt ( sum ( b(l:n,l)**2 ) )
r = sign ( r, b(l,l) )
b(l,l) = b(l,l) + r
rho = r * b(l,l)
do j = l + 1, n
t = dot_product ( b(l:n,l), b(l:n,j) )
b(l:n,j) = b(l:n,j) - t * b(l:n,l) / rho
end do
do j = 1, n
t = dot_product ( b(l:n,l), a(l:n,j) )
a(l:n,j) = a(l:n,j) - t * b(l:n,l) / rho
end do
b(l,l) = - s * r
b(l+1:n,l) = 0.0D+00
end if
end do
!
! Reduce A to upper Hessenberg form, while keeping B triangular.
!
if ( n == 2 ) then
return
end if
do k = 1, n - 2
nk1 = nm1 - k
do lb = 1, nk1
l = n - lb
l1 = l + 1
!
! Zero A(l+1,k).
!
s = abs ( a(l,k) ) + abs ( a(l1,k) )
if ( s /= 0.0D+00 ) then
u1 = a(l,k) / s
u2 = a(l1,k) / s
r = sign ( sqrt ( u1**2 + u2**2 ), u1 )
v1 = - ( u1 + r) / r
v2 = - u2 / r
u2 = v2 / v1
do j = k, n
t = a(l,j) + u2 * a(l1,j)
a(l,j) = a(l,j) + t * v1
a(l1,j) = a(l1,j) + t * v2
end do
a(l1,k) = 0.0D+00
do j = l, n
t = b(l,j) + u2 * b(l1,j)
b(l,j) = b(l,j) + t * v1
b(l1,j) = b(l1,j) + t * v2
end do
!
! Zero B(l+1,l).
!
s = abs ( b(l1,l1) ) + abs ( b(l1,l) )
if ( s /= 0.0 ) then
u1 = b(l1,l1) / s
u2 = b(l1,l) / s
r = sign ( sqrt ( u1**2 + u2**2 ), u1 )
v1 = -( u1 + r ) / r
v2 = -u2 / r
u2 = v2 / v1
do i = 1, l1
t = b(i,l1) + u2 * b(i,l)
b(i,l1) = b(i,l1) + t * v1
b(i,l) = b(i,l) + t * v2
end do
b(l1,l) = 0.0D+00
do i = 1, n
t = a(i,l1) + u2 * a(i,l)
a(i,l1) = a(i,l1) + t * v1
a(i,l) = a(i,l) + t * v2
end do
if ( matz ) then
do i = 1, n
t = z(i,l1) + u2 * z(i,l)
z(i,l1) = z(i,l1) + t * v1
z(i,l) = z(i,l) + t * v2
end do
end if
end if
end if
end do
end do
return
end
I would expand the allocation Process
integer :: status1, status2, status3, status4, status5
! check the allocation, returnvalue 0 means ok
ALLOCATE(ma(1:dimen,1:dimen), stat=status1)
ALLOCATE(tabm(1:dimen), stat=status2)
ALLOCATE(ga(1:dimen,1:dimen), stat=status3)
ALLOCATE(tabg(1:dimen), stat=status4)
ALLOCATE(zet(1:dimen,1:dimen), stat=status5)
And at the end of the Program deallocate all arrays, because, you maybe have no memoryleak now, but if you put this program into a subroutine and use it several time with big matricies during a programrun, the program could leak some serious memory.
....
DO i=1,dimen
tabg = ga(1:dimen,i)
WRITE (divg,*) tabg
END DO
CLOSE(divg)
DEALLOCATE(ma, stat=status1)
DEALLOCATE(tabm, stat=status2)
DEALLOCATE(ga, stat=status3)
DEALLOCATE(tabg, stat=status4)
DEALLOCATE(zet, stat=status5)
You can check again with the status integer, if the deallocation was ok, returnvalue again 0.
I am trying to run a stress autocorrelation function code to calculate the stress autocorrelation function,then from there I would like to calculate viscosity using Green -Kubo equation. Now the Fortran code I have does not read out my stress data in order to calculate stress auot-correlarion function. Anyone can please help me with this. I have attached my code and data I want to correlate. Hope to here from you soon.
Here is the error
./a.out
**** Program Stress_autocorrelation ****
Calculation of time Correlation Functions
Enter data file name
DFILE
Enter results file name
RFILE
0.00000000
0.00000000
0.00000000
0.00000000
0.00000000
0.00000000
0.00000000
0.00000000
At line 106 of file main.f95 (unit = 10, file = 'DFILE')
Fortran runtime error: Bad value during floating point read
Code and below is Input data:
! Program to claculate pressure autocorrelation function
program stress_autocorrelation
implicit none
common / block1 / STORA, STORB, STORC, STORD,STORE,STORF,STORG, STORH, STORI
common / block2 / PA, PB, PC, PD, PE, PF, PG, PH , PI
common / block3 / PACF, ANORM
! *******************************************************************
! ............ PRINCIPAL VARIABLES............
!
! ** integer N Number of atoms
! ** integer NSTEP Number of steps on the tape
! ** integer IOR Interval for time origins
! ** integer NT Correlation length, Including T=0
! ** integer NTIMOR Number of time origin
! ** integer NLABEL Label for step (1,2,3.....Nstep)
!
!
! ** real PACF(NT) The pressure correlation function
! ** NSTEP and NT should be multiples of IOR.
! ** PA,PB,PC = Pxx,Pxy,Pxz
! ** PD,PE,PF = Pyx,Pyy,Pyz
! ** PG,PH,PI = Pzx,Pzy,Pzz
!
!
! ...............ROUTINES REFERENCED..........................
!
! ....Subroutine Store (J1)..........
!Routine to store the data for correlation
! .....Subroutine Corr (J1,J2,IT).........
!Routine to correlate the stored time origin
!
!
! .....................USAGE..............................
!
! Data in file DFILE on fortrran UNIT DUNIT
! Results in File RFILE on fortran UNIT RUNIT
! *******************************************************************
integer N, NSTEP, IOR, NT, NDIM, DUNIT, RUNIT, NTIMOR
integer FULLUP
parameter ( N = 78, NSTEP = 10, IOR = 4, NT = 8 )
parameter ( DUNIT = 10, RUNIT = 11 )
parameter ( NDIM = NT / IOR + 1, NTIMOR = NSTEP / IOR )
parameter ( FULLUP = NDIM - 1 )
real PA(N), PB(N), PC(N), PD(N), PE(N), PF(N), PG(N), PH(N), PI(N)
real STORA(NDIM,N), STORB(NDIM,N), STORC(NDIM,N),STORD(NDIM,N), STORE(NDIM,N),STORF(NDIM,N),STORG(NDIM,N),STORH(NDIM,N)
real STORI(NDIM,N)
REAL PACF(NT), ANORM(NT)
integer S(NTIMOR), TM(NTIMOR)
integer TS, TSS, L, NINCOR, K, R, JA, IB, IN, IA, JO, I
integer NLABEL
character DUMMY * 5
character DFILE * 115
character RFILE * 115
! *******************************************************************
write(*,'('' **** Program Stress_autocorrelation **** '')')
write(*,'('' Calculation of time Correlation Functions '')')
!.....READ IN FILE NAMES.........
write(*,'('' Enter data file name'')')
read (*,'(A)') DFILE
write (*,'('' Enter results file name'')')
read (*,'(A)') RFILE
!......INITIALIZE COUNTERS.......
NINCOR = FULLUP
JA = 1
IA = 1
IB = 1
!........ZERO ARRAYS.............
do 5 I = 1, NT
PACF(I) = 0.0
ANORM(I) = 0.0
write(*,*) PACF(I)
5 continue
!..........OPEN DATA FILE AND RESULTS FILE...........
open ( UNIT = DUNIT, FILE = DFILE, STATUS = 'OLD', FORM = 'FORMATTED')
open ( UNIT = RUNIT, FILE = RFILE, STATUS = 'NEW' )
!.........CALCULATION BEGINS............
do 40 L = 1, NTIMOR
JA = JA + 1
S(L) = JA - 1
read ( DUNIT, '(A5,I4)') DUMMY, NLABEL
do 7 R = 1, N
read (DUNIT,'(F9.6,8(9X,F9.6))')PA(R),PB(R),PC(R),PD(R),PE(R),PF(R),PG(R),PH(R),PI(R)
7 continue
TM(L) = NLABEL
write(*,*) TM(L)
!.......STORE STEP AS A TIME ORIGIN......
call STOREE ( JA )
!........CORRELATE THE ORIGINS IN STORE......
do 10 IN = IA, L
TSS = TM(L) - TM(IN)
TS = TSS + 1
JO = S(IN) + 1
call CORR ( JO, JA, TS )
10 continue
!Read IN data between time origins. This can
!Be conveniently stored IN element 1 of the
!Array storx etc. and can then ben correlated
!With the time origins
do 30 K = 1, IOR - 1
read ( DUNIT, '(A5,I4)') DUMMY, NLABEL
do 15 R = 1, N
read ( DUNIT,'(F17.14,8(13X,F17.14))')PA(R),PB(R),PC(R),PD(R),PE(R),PF(R),PG(R),PH(R),PI(R)
15 continue
call STOREE ( 1 )
do 20 IN = IA, L
TSS = NLABEL - TM(IN)
TS = TSS + 1
JO = S(IN) + 1
call CORR ( JO, 1, TS )
20 continue
30 continue
if ( L .GE. FULLUP ) then
if ( L .EQ. NINCOR ) then
NINCOR = NINCOR + FULLUP
JA = 1
endif
IA = IA + 1
endif
40 continue
close ( DUNIT )
!.....NORMALISE CORRELATION FUNCTIONS.......
PACF(1) = PACF(1) / ANORM(1) / REAL ( N )
do 50 I = 2, NT
PACF(I) = PACF(I) / ANORM(I) / REAL ( N ) / PACF(1)
50 continue
write ( RUNIT, '('' Pressure ACF '')')
write ( RUNIT, '(I6,E15.6)') ( I, PACF(I), I = 1, NT )
close ( RUNIT )
stop
end
subroutine STOREE ( J1 )
common / BLOCK1 / STORA, STORB, STORC, STORD,STORE,STORF,STORG,STORH,STORI
common/ BLOCK2 / PA, PB, PC, PD, PE, PF, PG, PH, PI
! *******************************************************************
!.........SUBROUTINE TO STORE TIME ORIGINS..............
! *******************************************************************
integer J1
integer N, NT, IOR, NDIM
parameter ( N = 78, NT = 8, IOR =4 )
parameter ( NDIM = NT / IOR + 1 )
real STORA(NDIM,N), STORB(NDIM,N), STORC(NDIM,N),STORD(NDIM,N)
real STORE(NDIM,N),STORF(NDIM,N),STORG(NDIM,N),STORH(NDIM,N),STORI(NDIM,N)
real PA(N), PB(N), PC(N), PD(N), PE(N), PF(N),PG(N), PH(N), PI(N)
integer I
do 10 I = 1, N
STORA(J1,I) = PA(I)
STORB(J1,I) = PB(I)
STORC(J1,I) = PC(I)
STORD(J1,I) = PD(I)
STORE(J1,I) = PE(I)
STORF(J1,I) = PF(I)
STORG(J1,I) = PG(I)
STORH(J1,I) = PH(I)
STORI(J1,I) = PI(I)
10 continue
return
end
subroutine CORR ( J1, J2, IT )
common / block1 / STORA, STORB, STORC, STORD,STORE,STORF,STORG,STORH,STORI
common/ block3 / PACF, ANORM
! *******************************************************************
!......SUBROUTINE TO CORRELATE TIME ORIGINS....
! *******************************************************************
integer J1, J2, IT
integer N, NT, IOR, NDIM
parameter ( N = 78, NT = 8, IOR = 4 )
parameter ( NDIM = NT / IOR + 1 )
real STORA(NDIM,N), STORB(NDIM,N), STORC(NDIM,N),STORD(NDIM,N)
real STORE(NDIM,N),STORF(NDIM,N),STORG(NDIM,N),STORH(NDIM,N),STORI(NDIM,N)
real PACF(NT), ANORM(NT)
integer I
!********************************************************************
do 10 I = 1, N
PACF(IT) = PACF(IT) + STORA(J1,I) * STORA(J2,I) &
+ STORB(J1,I) * STORB(J2,I) &
+ STORC(J1,I) * STORC(J2,I) &
+ STORD(J1,I) * STORD(J2,I) &
+ STORE(J1,I) * STORE(J2,I) &
+ STORF(J1,I) * STORF(J2,I) &
+ STORG(J1,I) * STORG(J2,I) &
+ STORH(J1,I) * STORH(J2,I) &
+ STORI(J1,I) * STORI(J2,I)
10 continue
ANORM(IT) = ANORM(IT) + 1.0
return
end
Data: has 9 columns
-9.568336E+00 -1.615161E+00 1.042644E+00 -1.615161E+00 -1.131916E+01 -6.979813E-01 1.042644E+00 -6.979813E-01 -1.182917E+01
-4.765572E-01 9.005122E-01 -2.282920E+00 9.005122E-01 -3.827857E+00 -3.206736E+00 -2.282920E+00 -3.206736E+00 -6.252462E+00
-1.012710E+01 4.672368E-01 8.791873E-02 4.672368E-01 -4.680832E+00 -5.271814E-01 8.791873E-02 -5.271814E-01 -1.898345E-01
-7.699012E+00 -9.906154E-01 7.450304E-01 -9.906154E-01 -1.061230E+00 -3.546956E+00 7.450304E-01 -3.546956E+00 -6.843898E+00
-3.544260E+00 4.254020E+00 -1.963602E+00 4.254020E+00 3.740858E+00 -4.587760E+00 -1.963602E+00 -4.587760E+00 -6.776258E+00
1.755595E-01 -9.625855E-01 -2.395960E+00 -9.625855E-01 -1.701399E+00 -8.483695E-01 -2.395960E+00 -8.483695E-01 -4.165223E+00
-3.244186E+00 5.540608E+00 -4.951768E-01 5.540608E+00 3.068601E+00 -1.613010E-01 -4.951768E-01 -1.613010E-01 -5.641277E+00
-8.985849E+00 1.870244E+00 -2.295795E-01 1.870244E+00 -4.635924E+00 -4.787461E+00 -2.295795E-01 -4.787461E+00 -3.014272E+00
-1.651073E-01 -6.326584E-01 -3.028051E+00 -6.326584E-01 -2.621833E+00 -2.640439E+00 -3.028051E+00 -2.640439E+00 1.668877E+00
1.250349E+00 3.054784E+00 -2.898975E+00 3.054784E+00 8.419503E-01 9.620184E-01 -2.898975E+00 9.620184E-01 1.479256E+00
-7.796195E-01 1.942983E+00 -2.736569E+00 1.942983E+00 6.073043E+00 -2.520281E+00 -2.736569E+00 -2.520281E+00 -9.600832E-01
4.697066E-01 3.138124E+00 -1.092573E+00 3.138124E+00 -2.099285E+00 -1.581031E+00 -1.092573E+00 -1.581031E+00 -6.285002E-01
3.017532E-01 -9.701574E-02 1.611936E+00 -9.701574E-02 -1.762075E+00 -3.401961E+00 1.611936E+00 -3.401961E+00 -6.889746E-01
1.177410E-01 5.090611E-01 1.452691E-01 5.090611E-01 5.695570E+00 -3.573245E+00 1.452691E-01 -3.573245E+00 -1.099615E+00
-5.180126E+00 -1.876409E-01 -2.067182E+00 -1.876409E-01 1.611177E+00 5.458450E-01 -2.067182E+00 5.458450E-01 1.026071E+00
1.477567E+00 1.598949E+00 -1.577546E+00 1.598949E+00 3.933810E+00 -2.698132E+00 -1.577546E+00 -2.698132E+00 3.485029E+00
-2.533324E+00 1.753033E+00 1.425241E-01 1.753033E+00 2.406501E+00 -1.147217E+00 1.425241E-01 -1.147217E+00 3.065603E-01
-2.360274E+00 1.312721E+00 -3.711419E-01 1.312721E+00 2.556935E+00 3.152605E-01 -3.711419E-01 3.152605E-01 3.378170E+00
-1.698217E+00 1.105760E+00 3.780822E-01 1.105760E+00 2.736574E+00 7.920578E-01 3.780822E-01 7.920578E-01 -6.596856E-01
-5.099544E+00 1.647542E-01 -1.036544E+00 1.647542E-01 3.845429E+00 -1.034068E+00 -1.036544E+00 -1.034068E+00 -3.152053E+00
-2.686567E+00 1.335786E+00 -1.889911E-01 1.335786E+00 9.755267E-01 9.322043E-01 -1.889911E-01 9.322043E-01 3.229615E-01
1.542994E-01 3.104663E+00 -1.634353E-01 3.104663E+00 4.090105E+00 -1.128244E+00 -1.634353E-01 -1.128244E+00 -2.909383E-01
-4.235419E-01 1.554157E+00 3.475430E+00 1.554157E+00 4.701173E+00 -1.789414E+00 3.475430E+00 -1.789414E+00 1.517218E+00
-8.054924E-01 -1.167935E+00 -1.123460E+00 -1.167935E+00 1.169303E+00 -2.171076E+00 -1.123460E+00 -2.171076E+00 -5.636150E+00
This is the program I wrote to calculate the distance between carbon and hydrogen atom coordinates as a practice. But some errors occurred and I don't know how to fix them.
program C_H_bdlength
implicit none
integer :: ia ! integer atoms number
integer :: na ! number of atoms
real*8 :: x , y , z ! x y z coordinates of all atoms
real*8 :: x1 , y1 , z1 ! x y z coordinates of C atoms
real*8 :: x2 , y2 , z2 ! x y z coordinates of H atoms
character(len=2) :: ele ! element name
real*8 :: dis ! distance between C and H
open(100,file='cnt.ini',action='read',status='old')
na = 0
do
read(100,*,end=101)
na = na + 1
end do
101 continue
open(200, file='cnt.ini',action='wtire',status='replace')
rewind(100)
write(200,*)
do ia = 1 , na
read(100,*) ele, x, y, z
if ele == 'C' then x1 = x, y1 = y, z1 = z
do ia = ia , na
read(100,*) ele, x, y, z
if ele == 'H' then x2 = x, y2 = y, z2 = z
dis = sqrt((x1 - x2)**2 + (y1 - y2)**2 + (z1 - z2)**2)
write(200,*) dis
end if
end do
end if
end do
end program C_H_bdlength
Errors:
In file C_H_bdlength.f90:26
if ele == 'C' then x1 = x, y1 = y, z1 = z
1
Error: Unclassifiable statement at (1)
In file C_H_bdlength.f90:27
do ia = ia , na
1
In file C_H_bdlength.f90:24
do ia = 1 , na
2
Error: Variable 'ia' at (1) cannot be redefined inside loop beginning at (2)
In file C_H_bdlength.f90:29
if ele == 'H' then x2 = x, y2 = y, z2 = z
1
Error: Unclassifiable statement at (1)
In file C_H_bdlength.f90:33
end if
1
Error: Expecting END DO statement at (1)
In file C_H_bdlength.f90:35
end if
1
Error: Expecting END DO statement at (1)
You have a nested loop, and are using the same variable (ia) to control both the inner and outer loop. Use a variable with a different name in the inner loop.
The if <condition> then construct cannot have additional operations following the then on the same line.
In addition to #Peter's answer, another (not syntactic) problem is that your DO loops do not take into account all the C-H pairs. For example, if "cnt.ini" contains the following data
O 1.0 1.0 1.0
H 8.0 1.0 6.0 # ia=2
C 2.0 3.0 1.0 # ia=3
N 3.0 3.0 3.0
H 4.0 1.0 6.0 # ia=5
O 5.0 5.0 5.0
C 1.0 7.0 8.0 # ia=7
it only takes into account ia = 3 and 5 pair. Further, because you are writing output data onto the input file (cnt.ini) while reading the input from the latter, data transfer may be broken. So I suggest first reading in the input data into arrays, calculate C-H distances, and then write the result onto a different file. For example, the code may look like this.
integer :: ia, ja, na
real*8 :: dist
real*8, allocatable :: pos(:,:)
character(len=2), allocatable :: ele(:)
open(100,file='cnt.ini',status='old')
!! First, determine the number of atoms in the file.
na = 0
do
read( 100, *, end=101 )
na = na + 1
end do
101 continue
!! Then, allocate necessary arrays for atomic positions and element names.
allocate( pos( 3, na ), ele( na ) )
!! Now read the actual data in the file.
rewind( 100 )
do ia = 1, na
read( 100, * ) ele( ia ), pos( 1:3, ia )
! Alternative way using implied DO-loop.
! read( 100, * ) ele( ia ), ( pos( k, ia ), k = 1, 3 )
enddo
close( 100 )
!! Now calculate C-H distances.
open(200, file='dist.dat')
!! Loop over unique atom pairs.
do ia = 1 , na - 1
do ja = ia + 1, na
if ( ( ele(ia) == 'C' .and. ele(ja) == 'H' ) .or. &
( ele(ia) == 'H' .and. ele(ja) == 'C' ) ) then
dist = norm2( pos( :, ia ) - pos( :, ja ) )
! dist = sqrt( sum( (pos(:,ia) - pos(:,ja))**2 ) ) !! if norm2() not available
write(200,*) ia, ja, dist
endif
enddo
enddo
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 4 years ago.
Improve this question
Recently, I started to lean fortran programming. I have seen the following code at youtube without any error it is compiled. But I have got some errors.
I appreciate any help
program
implicit none
real, parameter :: pi=4*atan(1.0)
integer, parameter :: n = 100
real :: dimension(1:n) :: x, y
real :: a=0.0, b = 2*pi
real :: increment
integer :: i
increment = (b-a)/(real(n)-1)
x(1)=0.0
do i =2,n
x(i) = x(i-1) + increment
end do
y = sin(x)
print *, x(1:5)
print *, y(1:5)
end program
real :: dimension(1:n) :: x, y is a syntax error. Replace the first :: with a comma. You may need to give a name on the program statement.
You also have mixed-mode arithmetic in line
increment = (b-a)/(real(n)-1)
It will probably compile, and it may not even affect the program, but you should never, never have mixed-mode arithmetic in any programming language as it can cause strange, hard to find bugs.
It should look like this:
increment = (b-a)/(real(n)-1.0)
Here are the results of a working example which addresses the concerns of #High Performance Mark.
host system = (redacted)
compiler version = GCC version 5.1.0
compiler options = -fPIC -mmacosx-version-min=10.9.4 -mtune=core2 -Og -Wall -Wextra -Wconversion -Wpedantic -fmax-errors=5
execution command = ./a.out
Compare mesh points
1.57017982 1.57080817 1.57143652
1.57016802 1.57079625 1.57142460
Compare function values at these mesh points
1622.04211 -84420.7344 -1562.01758
1591.57471 13245402.0 -1591.65527
There is a bad programming practice in the demo you found: moving through the mesh by adding steps (+ increment) instead of counting them (k * increment). The problem is widespread and appears with severe consequences (https://www.ima.umn.edu/~arnold/disasters/patriot.html).
For demonstration on your code, the size of the mesh was boosted to 10K points. Also the sample function changed from cos x to tan x and we examine points near the singularity at pi/2 = 1.57079633. While the novitiate may find the discrepancies in mesh values trivial, the difference in function values is significant.
(Mesh errors can be reduced by using increments which have exact binary representation like 2^(-13) = 1 / 8192.)
The code is shown here. The compilation command is gfortran -Wall -Wextra -Wconversion -Og -pedantic -fmax-errors=5 demo.f95. The run command is ./a.out.
program demo
use iso_fortran_env
implicit none
real, parameter :: pi = acos ( -1.0 )
integer, parameter :: n = 10001
real, dimension ( 1 : n ) :: x, y, z
real :: a = 0.0, b = 2 * pi
real :: increment
integer :: k, quarter, status
character ( len = * ), parameter :: c_options = compiler_options( )
character ( len = * ), parameter :: c_version = compiler_version( )
character ( len = 255 ) :: host = " ", cmd = " "
! queries
call hostnm ( host, status )
call get_command ( cmd )
! write identifiers
write ( *, '( /, "host system = ", g0 )' ) trim ( host )
write ( *, '( "compiler version = ", g0 )' ) c_version
write ( *, '( "compiler options = ", g0 )' ) trim ( c_options )
write ( *, '( "execution command = ", g0, / )' ) trim ( cmd )
increment = ( b - a ) / ( n - 1 )
quarter = n / 4
! mesh accumulates errors
x ( 1 ) = 0.0
do k = 2, n
x ( k ) = x ( k - 1 ) + increment
end do
y = tan ( x )
print *, 'Compare mesh points'
print *, x ( quarter : quarter + 2 )
! better mesh
x ( 1 ) = 0.0
do k = 2, n
x ( k ) = ( k - 1 ) * increment
end do
z = tan ( x )
print *, x ( quarter : quarter + 2 )
print *, 'Compare function values at these mesh points'
print *, y ( quarter : quarter + 2 )
print *, z ( quarter : quarter + 2 )
end program demo