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
Related
I am using fortran. I want to write some information to a file, and here is my code:
open(unit=114514, position="append", file="msst_info.txt")
write(114514, 100) "step =", step
write(114514, 200) "A =", A
write(114514, 200) "omega =", omega(sd)
write(114514, 300) "dilation =", dilation(sd)
write(114514, 200) "p_msst =", p_msst / (kBar * 10)
write(114514, 300) "vol =", vol / Ang**3
write(114514, 300) "temp =", temperature
write(114514, 400) "+++++++++++++++++++++++++++"
100 format(A10, i8)
200 format(A10, e12.4)
300 format(A10, f12.4)
400 format(A)
close(114514)
I wish it can append the information to this file after each step. But the result is very strange:
dilation = 0.9999
p_msst = 0.3619E+02
vol = 10 A = -0.1041E-23
omega = -0.2290E-15
dilation = 0.9999
p_msst = 0.3619E+02
vol A = -0.1041E-23
omega = -0.2290E-15
dilation = 0.9999
p_msst = 0.3619E+02
vol = 1053.0452
temp = 195.9830
+++++++++++++++++++++++++++
step = 6
A = -0.1041E-23
omega = -0.2290E-15
dilation = 0.9999
p_msst = 0.3619E+02
vol = 1053.0452
temp = 195.9830
+++++++++++++++++++++++++++
step = 7
A = -0.1249E step = 7
A = -0.1249E-23
omega = -0.2290E-15
dilation = 0.9999
p_msst = 0.4342E+02
vol = 1052.8163
temp = 198.4668
+++++++++++++++++++++++++++
the format of step 6 is what i want. but in step 7, some text is written multiple times, and their position is completely wrong. I wonder why it happens.
the whole code:
module msst
use poscar_struct_def
use dynconstr
use prec
use reader_tags
use poscar
implicit none
contains
subroutine msst_step(dyn, latt_cur, t_info, tsif, tifor, io, niond, nionpd, ntypd, ntyppd)
! =======================================================================
! Written by S. Pan 2021/5/28
! This subroutine calculate a msst step. (Evan J. Reed 2003 PRL)
! I refer to fix_msst.cpp in LAMMPS when writing this code.
! The v(t-dt/2) is needed for velocity verlet algo.
! Two step: first, calculate the velocity v(t) with the a(t) and v(t-dt/2).
! second: give the position of ion and cell x(t+dt), and v(t+dt/2).
! The parameter mu is neglected since it makes the process complex.
! dyn: the struct for some MD variables, such as x, v, force.
! t_info: the struct for type information, such as number of ions.
! step: the current number of step. Init if step == 1.
! =======================================================================
! the dyn info will be changed
type(dynamics), intent(in out) :: dyn
type(latt), intent(in out) :: latt_cur
type(type_info), intent(in out) :: t_info
! these are inputs, should not be modified
type(in_struct), intent(in) :: io
real(q), dimension(3, t_info%nions), intent(in) :: tifor ! force on ions
real(q), dimension(3, 3), intent(in) :: tsif ! stress
! some units
real(q), parameter :: eV = 1.60218e-19, Ang = 1e-10, fs = 1e-15, &
amu = 1.66053886e-27, kBar = 1e5, kB = 1.38064852e-23
! energy in J, length in meter, time in s, mass in kg
! stress in Pa
! internal variables
real(q), save :: dt, dthalf, tscale, qmass, vs, total_mass=0, vol0
real(q), dimension(3, t_info%nions) :: velocity_before_half_dt, velocity_now, velocity_after_half_dt, &
C_force, x
real(q), dimension(3), save :: omega = [0, 0, 0] ! the time derivative of cell
real(q), dimension(3) :: dilation = [1, 1, 1]
integer :: ierr, ii, ni, nt, niond, nionpd, ntypd, ntyppd
integer, save :: sd, step = 0
real(q), dimension(3, 3) :: kinetic_stress, total_stress
real(q), dimension(3, 3), save :: p0
real(q) :: p_msst, A, vol, vol1, vol2, fac1, sqrt_initial_temperature_scaling, temperature, ekin
if (step .eq. 0) then
dyn%init = 0
call rd_poscar(latt_cur, t_info, dyn, &
& niond, nionpd, ntypd, ntyppd, &
& io%iu0, io%iu6)
end if
dyn%posioc = dyn%posion
step = step + 1
dt = dyn%potim * fs
dthalf = dt/2
! convert x to cartsian coordination. x and velocity use standard unit.
do ii = 1, 3
x(ii, :) = dyn%posion(ii, :) * latt_cur%a(ii, ii) * Ang
end do
! there isn't anything in dyn%pomass. so must use t_info%pomass
ni=1
do nt=1,t_info%ntyp
do ni=ni,t_info%nityp(nt)+ni-1
C_force(:, ni) = tifor(:, ni)/t_info%pomass(nt)
total_mass = total_mass + t_info%pomass(nt)
enddo
enddo
C_force = C_force * (eV/Ang/amu)
total_mass = total_mass * amu
if (step .eq. 1) then
! read these tags from INCAR
call process_incar(io%lopen, io%iu0, io%iu5, 'qmass', qmass, ierr, .true.)
call process_incar(io%lopen, io%iu0, io%iu5, 'tscale', tscale, ierr, .true.)
call process_incar(io%lopen, io%iu0, io%iu5, 'shock_direction', sd, ierr, .true.)
call process_incar(io%lopen, io%iu0, io%iu5, 'shock_velocity', vs, ierr, .true.)
! use tscale to give a initial cell velocity, or the cell will stay still forever
do ii = 1, 3
velocity_now(ii, :) = dyn%vel(ii, :) * latt_cur%a(ii, ii) * (Ang/fs) / dyn%potim
end do
CALL EKINC(EKIN,T_INFO%NIONS,T_INFO%NTYP,T_INFO%ITYP,T_INFO%POMASS,DYN%POTIM,LATT_CUR%A,DYN%VEL)
temperature = 2 * ekin * eV / (kB * t_info%nions * 3 )
fac1 = tscale*total_mass/qmass*temperature
omega(sd) = -sqrt(fac1)
sqrt_initial_temperature_scaling = sqrt(1.0-tscale)
velocity_now = velocity_now * sqrt_initial_temperature_scaling
else
! =======================================================================
! 2nd half of Verlet update. this part get current velocity from t-dt/2.
! =======================================================================
! propagate particle velocities 1/2 step, it should not be done on the first step of MD.
do ii = 1, 3
velocity_before_half_dt(ii, :) = dyn%vel(ii, :) * latt_cur%a(ii, ii) * (Ang/fs) / dyn%potim
end do
velocity_now = velocity_before_half_dt + C_force*dthalf
end if
! compute new pressure and volume and temperature
call compute_kinetic_stress(t_info, latt_cur, dyn, kinetic_stress, tsif, -1)
total_stress = tsif + kinetic_stress
total_stress = total_stress * kBar
vol = latt_cur%a(1, 1) * latt_cur%a(2, 2) * latt_cur%a(3, 3) * (Ang**3)
if (step .eq. 1) then
p0 = total_stress
vol0 = vol
end if
p_msst = vs**2 * total_mass * (vol0 - vol)/vol0**2
A = total_mass * (total_stress(sd, sd) - p0(sd, sd) - p_msst) / qmass
! qmass is in mass(kg)**2 / length(m)**4
if (step .ne. 1) then
! propagate the time derivative of the volume 1/2 step at fixed V, r, rdot
! it should not be done on the first step of MD.
omega(sd) = omega(sd) + A*dthalf ! this is the current omega
end if
! =======================================================================
! 1st half of Verlet update
! in VASP, the 1st half of Verlet update cannot be performed before
! compute force and stress. So it must be placed here.
! =======================================================================
! propagate the time derivative of the volume 1/2 step at fixed vol, r, rdot
omega(sd) = omega(sd) + A*dthalf ! this is omega(t+dt/2)
! propagate velocities 1/2 step
velocity_after_half_dt = velocity_now + C_force*dthalf
! now, we need to compute the vol and pos for next step:
! propagate the volume 1/2 step
vol1 = vol + omega(sd)*dthalf
! rescale positions and change box size
dilation(sd) = vol1/vol
call remap(latt_cur, sd, x, velocity_after_half_dt, dilation,t_info)
! propagate particle positions 1 time step
x = x + dt * velocity_after_half_dt
! propagate the volume 1/2 step
vol2 = vol1 + omega(sd)*dthalf
! rescale positions and change box size
dilation(sd) = vol2/vol1
call remap(latt_cur, sd, x, velocity_after_half_dt, dilation,t_info)
do ii = 1, 3
dyn%posion(ii, :) = x(ii, :) / latt_cur%a(ii, ii) / Ang
dyn%vel(ii, :) = velocity_after_half_dt(ii, :) / latt_cur%a(ii, ii) / (Ang/fs) * dyn%potim
end do
t_info%posion = dyn%posion
CALL EKINC(EKIN,T_INFO%NIONS,T_INFO%NTYP,T_INFO%ITYP,T_INFO%POMASS,DYN%POTIM,LATT_CUR%A,DYN%VEL)
temperature = 2 * ekin * eV / (kB * t_info%nions * 3 )
! this block for debug. write the information to a file
if (.true.) then
open(unit=114514, position="append", file="msst_info.txt")
write(114514, 100) "step =", step
write(114514, 200) "A =", A
write(114514, 200) "omega =", omega(sd)
write(114514, 300) "dilation =", dilation(sd)
write(114514, 200) "p_msst =", p_msst / (kBar * 10)
write(114514, 300) "vol =", vol / Ang**3
write(114514, 300) "temp =", temperature
write(114514, 400) "+++++++++++++++++++++++++++"
100 format(A10, i8)
200 format(A10, e12.4)
300 format(A10, f12.4)
400 format(A)
close(114514)
end if
end subroutine msst_step
! change the shape of cell, along with ion pos and vel.
subroutine remap(latt_cur, sd, x, v, dilation,t_info)
integer, intent(in):: sd
type(type_info), intent(in) :: t_info
real(q), dimension(3), intent(in) :: dilation
real(q), dimension(3, t_info%nions), intent(in out) :: x, v
type(latt), intent(in out) :: latt_cur
latt_cur%a(sd, sd) = dilation(sd) * latt_cur%a(sd, sd)
x(sd, :) = dilation(sd) * x(sd, :)
v(sd, :) = dilation(sd) * v(sd, :)
end subroutine remap
end module msst
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.
implicit none
character*20 fflname, oflname, oflname2
integer i, length, rn, s(100)
real*8 phase_shift
parameter ( length = 32768, phase_shift = 0.02 )
real*8 num, real_coeff, imag_coeff
real*8 amplitude(length), phase(length)
& ,imag_coeff_ps(length), real_coeff_ps(length)
oflname = "wvlt_coeff.data"
oflname2 = "selection.data"
fflname = "wvlt_coeff_ps.data"
open(12, file = oflname)
do i=1, length
read(12, *) num, real_coeff, imag_coeff
real_coeff_ps(i) = real_coeff
imag_coeff_ps(i) = imag_coeff
enddo
close(12)
open(13, file = oflname2)
do i=1, 100
read(13, *) rn
s(i) = rn
enddo
close(13)
do i=1, 100
amplitude(i) = sqrt( real_coeff(s(i))**2 + imag_coeff(s(i))**2 )
phase(i) = atan( imag_coeff(s(i))/real_coeff(s(i)) ) + phase_shift
real_coeff_ps(s(i)) = amplitude(i) * cos( phase(i) )
imag_coeff_ps(s(i)) = amplitude(i) * sin( phase(i) )
enddo
open(15, file = fflname)
do i=1, length
write(15, *) i, real_coeff_ps(i), imag_coeff_ps(i)
enddo
close(15)
stop
end
Errors:
hyxie#ubuntu:~$ gfortran '/home/hyxie/Documents/20161012/phase_shift2.f'
/home/hyxie/Documents/20161012/phase_shift2.f:35:40:
amplitude(i) = sqrt( real_coeff(s(i))**2 + imag_coeff(s(i))**2 )
1
Error: Syntax error in argument list at (1)
/home/hyxie/Documents/20161012/phase_shift2.f:36:36:
phase(i) = atan( imag_coeff(s(i))/real_coeff(s(i)) ) + phase_shift
1
Error: Syntax error in argument list at (1)
What is wrong with my coding?
real_coeff and image_coeff are not arrays, but you are accessing them as if they were. This results in a syntax error. Perhaps you intended to use real_coeff_ps and image_coeff_ps instead.
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