Created
April 17, 2018 05:13
-
-
Save machsix/d0853834fa7422c76db60074d497f92f to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
subroutine readin | |
! | |
use param, only: mnmol, mnat, mnsurf, mngauss, mntmod, mntor, & | |
mnfrag, mnmol, mntraj, mnfrag, mnoutcome, & | |
mnbond, pi, amutoau, autoatm, autofs, autoev, kb, & | |
autoang | |
use c_output, only: idebug, minprinticon, minprinttrapz, maxprint, & | |
lwrite, nprint | |
use c_dd, only: lreadin | |
use c_struct, only: cell, nvibmods, bdfmthr, rijco, nattype, xx0, & | |
mm0, symbolm, icharge, imulti, iatom, natom, & | |
nat, nunit, natunit, symbol0, nrotmods, & | |
rotaxis, momiprin, mmofag, symbol0, mmm, xxm, & | |
charge, nmol, ldiat, icell, ldiat, nfrag, & | |
indatom, rij, cvec, xunit, linearmol, bdbrthr, & | |
invcvec, indmm, natoms | |
use c_sys, only: tflag, vfreq, taup, taut, sysfreq, iadjtemp, & | |
rampfact, nequil, n_ramp, nrampstep, e0param, & | |
nsurft, cparam, methflag, repflag, qcpack, & | |
itempzpe, itherm, dimen, p0, intflag, reactcol, & | |
hstep0, temp0, e0param, nramp, vol0, ntraj, & | |
trajlist, periodic, maxtraj, eps, potflag, & | |
ieqtherm, iadjpress | |
use c_initial, only: deltate, lfixte, ifreinitrot, ifnoang, & | |
demax, demin, ipicktrj, pickthr, repflgi, & | |
jjad, equilibrium, vibene, temp0im, ewell, & | |
rotsel, initx, initp, vibsel, ivibdist, & | |
ivibtype, vibdistn, ifeqwithrot, nsurfi, nsurf0, & | |
ifr0eff, vvad, itosave, nsave, ademod, stateselect, & | |
b_fix, bandwd, icompp, itunn, drr, ilinben, ibend, & | |
istr, ntunn, r0effect, r0collision, te0fixed, & | |
admode, nlinben, nimptor, nbend, nstr, ntor, etrans, & | |
qnmvib0, compp, comxx, icomxx, transelect, rran, & | |
eroti, qnmrot0, verte, ecolad, bparam, arrad, rrad0, & | |
itor, b0impact, escatad, imptor, & | |
bmaxad, bminad, phmode,irottemp,iscaleenergy,irotfreeze | |
use atomdata, only: atmradco, atomsymbols | |
use c_traj, only: frusmeth, stodecoflag, lmodpop, ralpha, ntrapz, & | |
ltunn, rbin, icfrag, heatcap, totenergy, potential,& | |
kinetic, cohesive, nstat, nreinit, lzerotrans, lzerocom,& | |
cre, cim, vol, erot, tuntype, ngauss, nvers, prodzpe, & | |
freqlim, tinyrho, eta | |
use c_term, only: nbondform, nbondbreak, agmerge, agdefrag, & | |
attrans, determ, n_frags, n_turn, termflag, & | |
trmax, tibreak, trmin, dihlim, dihd, ntorsion, & | |
tiform, t_gradmax, t_stime, t_nstep, n_atoffr, & | |
termsteps, t_gradmag | |
implicit none | |
include 'c_mopac.f90' | |
! inattmp: number of duplicated atom types in an AG | |
! symtmp: temp storage of atom symbols | |
! mmtmp: temp storage of atom weights | |
! relmu: Reduce mass between AGs | |
! rran(1) rran(1) is the diameter of the sphere | |
! ran random number | |
! ilwrite temp storage of lwrite information | |
! ismb temp storage of atom index | |
! atomdiatom: if a run is atom-diatom calculation. To minimize the | |
! modification to the old program, this is just a local variable | |
! trtype(o) = Bond threshold provided by the user, input in A, | |
! immediately converted to bohr. | |
! titype = atom pairs whose bond distance threshold will be changed | |
! by the user (atom symmbol as input) | |
! nbondtype = Number of bond types whose bond threshold will be changed | |
! initr0col = User provides r0collision for reative collision run | |
! | |
integer :: im,ii,i,j,k,l,ismb(mnoutcome,2),itotline,endreccon, & | |
outflag,ilwrite(1000),inattmp,i1,i2,nbondtype, & | |
ifkeyexist,ierror,ifblank,nmodel | |
integer :: ranseed | |
double precision :: radmin(mnmol),radmax(mnmol),mmtmp,maxtmp,mintmp, & | |
comxxm(3),volm(3,3),detmtbt,tmp, & | |
relmu,trtype(mnoutcome),ran | |
double precision :: small | |
logical :: initr0col,atomdiatom,rotst(mnmol), & | |
roteng(mnmol),ireadchg,find_real | |
character :: records*200,symbtmp*2,chartmp*2,lowercase*200 | |
character*2 :: titype(mnoutcome,2) | |
! Default values set here | |
include 'defaults.f90' | |
! inititial values | |
b0impact=0.d0 | |
initr0col = .false. | |
do i=1,mnat | |
mm0(i)=0.d0 | |
do j=1,3 | |
xx0(j,i)=0.d0 | |
enddo | |
enddo | |
small = 1.d-10 | |
! | |
! Read inputfile into records line by line | |
! lines with the FIRST!!! character as # will be deemed as comment line | |
! and will be ignored | |
! open(10,file='input.txt',status='OLD') | |
! file 12, store the input without comments | |
open(12,status='scratch') | |
! file 13, temporary file used to read in variables | |
open(13,status='scratch') | |
! | |
write(6,*) 'Your inputfile:' | |
do while(.true.) | |
read(5,'(a)',end=100) records | |
if (records(1:1) .ne. '#') then | |
records = lowercase(records) | |
write(12,'(a)') records | |
write(6,'(a)') records | |
endif | |
enddo | |
! | |
100 continue | |
! close(10) | |
write(12,'(a)') 'thend0' | |
rewind(12) | |
! | |
! Read in values | |
! After (length of keywords) + 1 '=' is the value we want. | |
! Write the rest of the line records to a temporary tmptxt | |
! and then read the value we want from the beginning of tmptxt | |
! This is the best way I can think of in Fortran 77 | |
! The input can be written in two formats: | |
! 1. $system var1=1 var2=2 $end | |
! 2. $system var1=1 | |
! var2=2 | |
! $end | |
! | |
read(12,'(a)',end=9999) records | |
! --------------------------------------------------------- | |
! System control keywords and values | |
do 51 while(.true.) | |
if (index(records,'$control') .GT. 0) then | |
endreccon=0 | |
do while(endreccon .ne. 9999) | |
! Reaction collision | |
if (index(records,'reactcol') .GT. 0) reactcol = .true. | |
! Potential used | |
ifkeyexist=index(records,'potflag') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('potflag')+1:) | |
rewind(13) | |
read(13,*) potflag | |
rewind(13) | |
endif | |
! QC package used | |
ifkeyexist=index(records,'qcpack') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('qcpack')+1:) | |
rewind(13) | |
read(13,*) qcpack | |
rewind(13) | |
endif | |
! Temperature desired to run the simulation | |
ifkeyexist=index(records,'temp0') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('temp0')+1:) | |
rewind(13) | |
read(13,*) temp0 | |
rewind(13) | |
! Default temperature for each AG is temp0 | |
do i=1,mnmol | |
temp0im(i) = temp0 | |
enddo | |
endif | |
! Pressure | |
ifkeyexist=index(records,'pressure') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('pressure')+1:) | |
rewind(13) | |
read(13,*) p0 | |
rewind(13) | |
p0=p0/autoatm | |
endif | |
! Diabatic or adiabatic propagation | |
! if (index(records,'diabatic') .GT. 0) repflag = 1 | |
if (index(records,'diabatic').GT.0.AND.index(records, & | |
'adiabatic').EQ.0) repflag = 1 | |
if (index(records,'periodic') .GT. 0) periodic = .true. | |
if (index(records,'nve') .GT. 0) itherm=0 | |
if (index(records,'nvt') .GT. 0) itherm=1 | |
if (index(records,'npt') .GT. 0) itherm=2 | |
! Add zero vibration: at 0 K, the AG has a KE of 0.5 ZPE | |
if (index(records,'izpetemp') .GT. 0) itempzpe=.true. | |
! Integration method | |
! Bulirsch-Stoer integrator method | |
if (index(records,'bulstoint') .GT. 0) intflag=0 | |
! 4th order Runge-Kutta integrator method | |
if (index(records,'runkut4') .GT. 0) intflag=1 | |
! Simple Verlet algorithm | |
if (index(records,'verlet0') .GT. 0) intflag=2 | |
if (index(records,'vverlet') .GT. 0) intflag=3 | |
if (index(records,'beeman') .GT. 0) intflag=4 | |
if (index(records,'liouville') .GT. 0) intflag=5 | |
if (index(records,'bulstointhack') .GT. 0) intflag=6 | |
if (index(records,'fixedte0') .GT. 0) lfixte=.true. | |
! Initial Total energy to be fixed | |
ifkeyexist=index(records,'te0fixed') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('te0fixed')+1:) | |
rewind(13) | |
read(13,*) te0fixed | |
rewind(13) | |
te0fixed=te0fixed/autoev | |
lfixte=.true. | |
endif | |
! The width of the TE can be varied | |
ifkeyexist=index(records,'deltate') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('deltate')+1:) | |
rewind(13) | |
read(13,*) deltate | |
rewind(13) | |
deltate=deltate/autoev | |
endif | |
! hstep0 initial time step | |
ifkeyexist=index(records,'hstep0') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('hstep0')+1:) | |
rewind(13) | |
read(13,*) hstep0 | |
rewind(13) | |
hstep0=hstep0/autofs | |
endif | |
! eps if intflag=1 | |
ifkeyexist=index(records,'eps') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('eps')+1:) | |
rewind(13) | |
read(13,*) eps | |
rewind(13) | |
endif | |
! Random number seed | |
ifkeyexist=index(records,'ranseed') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('ranseed')+1:) | |
rewind(13) | |
read(13,*) ranseed | |
rewind(13) | |
endif | |
! Atom-diatom calculation | |
if (index(records,'atomdiatom') .GT. 0) atomdiatom = .true. | |
! Meet the end of this section | |
if (index(records,'$end') .GT. 0) then | |
endreccon=9999 | |
else | |
read(12,'(a)',end=9999) records | |
endif | |
enddo | |
read(12,'(a)',end=9999) records | |
endif | |
! | |
! --------------------------------------------------------- | |
! Surface information | |
if (index(records,'$surface') .GT. 0) then | |
endreccon=0 | |
do while(endreccon .ne. 9999) | |
! Initial electronic surface | |
ifkeyexist=index(records,'nsurf0') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('nsurf0')+1:) | |
rewind(13) | |
read(13,*) nsurf0 | |
rewind(13) | |
endif | |
! Initial conditions prepared from distribution of NURFI | |
ifkeyexist=index(records,'nsurfi') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('nsurfi')+1:) | |
rewind(13) | |
read(13,*) nsurfi | |
rewind(13) | |
endif | |
! Initial conditions prepared from distribution of | |
! NURFI,RepFlagi | |
ifkeyexist=index(records,'repflgi') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('repflgi')+1:) | |
rewind(13) | |
read(13,*) repflgi | |
rewind(13) | |
endif | |
! Total number of electronic surfaces | |
ifkeyexist=index(records,'nsurft') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('nsurft')+1:) | |
rewind(13) | |
read(13,*) nsurft | |
rewind(13) | |
endif | |
! Surface propagation method | |
ifkeyexist=index(records,'methflag') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('methflag')+1:) | |
rewind(13) | |
read(13,*) methflag | |
rewind(13) | |
endif | |
! Analysis of mode populations ON or OFF | |
if (index(records,'lmodpop') .GT. 0) lmodpop = .true. | |
! Coefficient for the determination of the amount of vibration we want | |
! to keep to calculate mode populations | |
ifkeyexist=index(records,'ralpha') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('ralpha')+1:) | |
rewind(13) | |
read(13,*) ralpha | |
rewind(13) | |
endif | |
! Methods to treat frustrated hops | |
ifkeyexist=index(records,'frusmeth') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('frusmeth')+1:) | |
rewind(13) | |
read(13,*) frusmeth | |
rewind(13) | |
endif | |
! Use of a Projected Hessian or TRAPZ-like methods ? | |
ifkeyexist=index(records,'ntrapz') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('ntrapz')+1:) | |
rewind(13) | |
read(13,*) ntrapz | |
rewind(13) | |
endif | |
if ((ntrapz.eq.2.or.ntrapz.eq.3).and.methflag.ne.1.and. & | |
methflag.ne.5) then | |
write(6,*) 'TRAPZ can only be used with FS, FSTU or FSTU/SD' | |
stop | |
endif | |
! Which version of TRAPZ ? | |
ifkeyexist=index(records,'nvers') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('nvers')+1:) | |
rewind(13) | |
read(13,*) nvers | |
rewind(13) | |
endif | |
! Criterion to avoid entering TRAPZ-like methods | |
ifkeyexist=index(records,'freqlim') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('freqlim')+1:) | |
rewind(13) | |
read(13,*) freqlim | |
rewind(13) | |
endif | |
! Value of the product ZPE for the mTRAPZ* method (nvers = 2) | |
! prodzpe must be expressed in eV in the input file | |
ifkeyexist=index(records,'prodzpe') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('prodzpe')+1:) | |
rewind(13) | |
read(13,*) prodzpe | |
rewind(13) | |
prodzpe = prodzpe/autoev | |
if (nvers.ne.2) then | |
write(6,*) 'mTRAPZ* is not selected: prodzpe is not used' | |
write(6,*) | |
endif | |
endif | |
! Use of stochastic decoherence? | |
ifkeyexist=index(records,'stodecoflag') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('stodecoflag')+1:) | |
rewind(13) | |
read(13,*) stodecoflag | |
rewind(13) | |
endif | |
if (stodecoflag.eq.1.and.methflag.ne.1.and. & | |
methflag.ne.5) then | |
write(6,*) 'Stochastic decoherence can only be used', & | |
' with FS or FSTU' | |
stop | |
endif | |
! Cparam: For CSDM and SCDM methods | |
ifkeyexist=index(records,'cparam') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('cparam')+1:) | |
rewind(13) | |
read(13,*) cparam | |
rewind(13) | |
endif | |
! E0param: For CSDM and SCDM methods | |
ifkeyexist=index(records,'e0param') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('e0param')+1:) | |
rewind(13) | |
read(13,*) e0param | |
rewind(13) | |
endif | |
! tinyrho to avoid dividing by zero in DM methods | |
ifkeyexist=index(records,'tinyrho') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('tinyrho')+1:) | |
rewind(13) | |
read(13,*) tinyrho | |
rewind(13) | |
endif | |
! Meet the end of this section | |
if (index(records,'$end') .GT. 0) then | |
endreccon=9999 | |
else | |
read(12,'(a)',end=9999) records | |
endif | |
enddo | |
read(12,'(a)',end=9999) records | |
endif | |
! | |
! --------------------------------------------------------- | |
! Reaction container information (cell) | |
if (index(records,'$cell') .GT. 0) then | |
endreccon=0 | |
do while(endreccon .ne. 9999) | |
! cubic | |
if (index(records,'cubic') .GT. 0) then | |
read(12,*) cell(1) | |
icell=1 | |
endif | |
! Cuboid | |
if (index(records,'cuboid') .GT. 0) then | |
read(12,*) (cell(j),j=1,3) | |
icell=2 | |
endif | |
! Triclinic | |
if (index(records,'arbitrary') .GT. 0) then | |
read(12,*) (cell(j),j=1,6) | |
icell=3 | |
endif | |
! Triclinic | |
if (index(records,'isolate') .GT. 0) then | |
icell=0 | |
endif | |
! Meet the end of this section | |
if (index(records,'$end') .GT. 0) then | |
endreccon=9999 | |
else | |
read(12,'(a)',end=9999) records | |
endif | |
enddo | |
! Move to next line | |
read(12,'(a)',end=9999) records | |
endif | |
! | |
! --------------------------------------------------------- | |
! Reaction collision parameters | |
if (index(records,'$rxcollision') .GT. 0) then | |
endreccon=0 | |
reactcol=.true. | |
do while(endreccon .ne. 9999) | |
! State select | |
if (index(records,'equilibrium') .GT. 0) stateselect=.false. | |
if (index(records,'stateselect') .GT. 0) stateselect=.true. | |
ifkeyexist=index(records,'b0impact') | |
! Impact parameter. If provided, it would be fixed | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('b0impact')+1:) | |
rewind(13) | |
read(13,*) b0impact | |
rewind(13) | |
b0impact=b0impact/autoang | |
b_fix = .true. | |
endif | |
! If user provide r0collision value, at the same time it means program | |
! will not decide r0collision itself, thus initr0col = 1 | |
! Initial distance information between the two AGs | |
ifkeyexist=index(records,'r0collision') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('r0collision')+1:) | |
rewind(13) | |
read(13,*) r0collision | |
rewind(13) | |
r0collision=r0collision/autoang | |
initr0col = .true. | |
endif | |
! Effective collision radius between two reactants | |
ifkeyexist=index(records,'r0effectcol') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('r0effectcol')+1:) | |
rewind(13) | |
read(13,*) r0effect | |
rewind(13) | |
r0effect=r0effect/autoang | |
ifr0eff=.true. | |
endif | |
! Meet the end of this section | |
if (index(records,'$end') .GT. 0) then | |
endreccon=9999 | |
else | |
read(12,'(a)',end=9999) records | |
endif | |
enddo | |
! Move to next line | |
read(12,'(a)',end=9999) records | |
endif | |
! | |
! --------------------------------------------------------- | |
! Termination condition | |
if (index(records,'$termcon') .GT. 0) then | |
endreccon=0 | |
do while(endreccon .ne. 9999) | |
! Termination Flag | |
ifkeyexist=index(records,'termflag') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('termflag')+1:) | |
rewind(13) | |
read(13,*) termflag | |
rewind(13) | |
endif | |
! For fragment monitoring (termflag=4) only | |
if (index(records,'noagdefrag') .GT. 0) agdefrag=.false. | |
if (index(records,'noagmerge') .GT. 0) agmerge=.false. | |
if (index(records,'noattrans') .GT. 0) attrans=.false. | |
! Number of products to be monitored in unimolecular | |
! fragmentation monintor condition (termflag=7) | |
ifkeyexist=index(records,'n_frags') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('n_frags')+1:) | |
rewind(13) | |
read(13,*) n_frags | |
rewind(13) | |
endif | |
! For termflag =3 4 5 only | |
ifkeyexist=index(records,'termsteps') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('termsteps')+1:) | |
rewind(13) | |
read(13,*) termsteps | |
rewind(13) | |
endif | |
! Maximum number of steps per trajectory | |
ifkeyexist=index(records,'t_nstep') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('t_nstep')+1:) | |
rewind(13) | |
read(13,*) t_nstep | |
rewind(13) | |
! if t_nstep <0, unlimited, set to a very large value | |
if (t_nstep.lt.0) t_nstep=1000000000 | |
endif | |
! Simulation time | |
ifkeyexist=index(records,'t_stime') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('t_stime')+1:) | |
rewind(13) | |
read(13,*) t_stime | |
rewind(13) | |
t_stime = t_stime/autofs | |
endif | |
ifkeyexist=index(records,'t_gradmag') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('t_gradmag')+1:) | |
rewind(13) | |
read(13,*) t_gradmag | |
rewind(13) | |
t_gradmag=t_gradmag*autoang/autoev | |
endif | |
ifkeyexist=index(records,'t_gradmax') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('t_gradmax')+1:) | |
rewind(13) | |
read(13,*) t_gradmax | |
rewind(13) | |
t_gradmax=t_gradmax*autoang/autoev | |
endif | |
! Total energy threshold in termflag=4 if te < determ, term | |
! Currently not used | |
! ifkeyexist=index(records,'determ') | |
! if (ifkeyexist .GT. 0) then | |
! write(13,*) records(ifkeyexist+len('determ')+1:) | |
! rewind(13) | |
! read(13,*) determ | |
! rewind(13) | |
! endif | |
! used for reactcol, if reactant turn n_turn times, reactive | |
ifkeyexist=index(records,'n_turn') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('n_turn')+1:) | |
rewind(13) | |
read(13,*) n_turn | |
rewind(13) | |
endif | |
! Bond forming threshold | |
ifkeyexist=index(records,'bondfmthre') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('bondfmthre')+1:) | |
rewind(13) | |
read(13,*) bdfmthr | |
rewind(13) | |
endif | |
! Bond broken threshold | |
ifkeyexist=index(records,'bondbrthre') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('bondbrthre')+1:) | |
rewind(13) | |
read(13,*) bdbrthr | |
rewind(13) | |
endif | |
ifkeyexist=index(records,'nbondform') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('nbondform')+1:) | |
rewind(13) | |
read(13,*) nbondform | |
rewind(13) | |
! These pair of distances must be written in seperated | |
! lines line by line. | |
do j=1,nbondform | |
! Read from the next line below the line of nbondform | |
read(12,'(a)',end=9999) records | |
write(13,*) records | |
rewind(13) | |
read(13,*) tiform(j,1),tiform(j,2),trmin(j) | |
rewind(13) | |
enddo | |
read(12,'(a)',end=9999) records | |
endif | |
ifkeyexist=index(records,'nbondbreak') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('nbondbreak')+1:) | |
rewind(13) | |
read(13,*) nbondbreak | |
rewind(13) | |
! These pair of distances must be written in separated | |
! lines, line by line. | |
do j=1,nbondbreak | |
! Read from the next line below the line of nbondbreak | |
read(12,'(a)',end=9999) records | |
write(13,*) records | |
rewind(13) | |
read(13,*) tibreak(j,1),tibreak(j,2),trmax(j) | |
rewind(13) | |
enddo | |
read(12,'(a)',end=9999) records | |
endif | |
ifkeyexist=index(records,'nbondtype') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('nbondtype')+1:) | |
rewind(13) | |
read(13,*) nbondtype | |
rewind(13) | |
! These pair of distances must be written in separate | |
! lines, line by line. | |
do j=1,nbondtype | |
! Read from the next line below the line of nbondtype | |
read(12,'(a)',end=9999) records | |
write(13,*) records | |
rewind(13) | |
read(13,*) titype(j,1),titype(j,2),trtype(j) | |
trtype(j)=trtype(j)/autoang | |
do i=1,111 | |
if ( titype(j,1).eq.atomsymbols(i) ) ismb(j,1)=i | |
if ( titype(j,2).eq.atomsymbols(i) ) ismb(j,2)=i | |
enddo | |
rijco( ismb(j,1),ismb(j,2) ) = trtype(j) | |
rijco( ismb(j,2),ismb(j,1) ) = trtype(j) | |
rewind(13) | |
enddo | |
read(12,'(a)',end=9999) records | |
endif | |
! The fragments to be monitored. termflag=7 only | |
ifkeyexist=index(records,'n_atomtypes') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('n_atomtypes')+1:) | |
rewind(13) | |
read(13,*) j | |
rewind(13) | |
n_atoffr=0 | |
do i=1,j | |
! Read from the next line below the line of n_atomtypes | |
read(12,*) k,nattype(mnmol+1,k) | |
n_atoffr=n_atoffr+nattype(mnmol+1,k) | |
enddo | |
read(12,'(a)',end=9999) records | |
endif | |
! | |
! JZ torsion angles | |
ifkeyexist=index(records,'ntorsion') | |
if (ifkeyexist .gt. 0) then | |
write(13,*) records(ifkeyexist+len('ntorsion')+1:) | |
rewind(13) | |
read(13,*) ntorsion | |
rewind(13) | |
do j = 1, ntorsion | |
read(12,'(a)',end=9999) records | |
write(13,*) records | |
rewind(13) | |
read(13,*) dihd(1,j),dihd(2,j),dihd(3,j),dihd(4,j), & | |
dihlim(1,j),dihlim(2,j) | |
rewind(13) | |
if(dihlim(1,j).lt.0.d0.or.dihlim(2,j).lt.0.d0) then !RMP | |
write(6,*) "The values that defined the limits of the" & !RMP | |
,"torsional angles must be positive." !RMP | |
stop | |
endif | |
enddo | |
read(12,'(a)',end=9999) records | |
endif | |
! Meet the end of this section | |
if (index(records,'$end') .GT. 0) then | |
endreccon=9999 | |
else | |
read(12,'(a)',end=9999) records | |
endif | |
enddo | |
! Move to next line | |
read(12,'(a)',end=9999) records | |
endif | |
! | |
! Trajectory control information | |
if (index(records,'$traject') .GT. 0) then | |
endreccon=0 | |
do while(endreccon .ne. 9999) | |
ifkeyexist=index(records,'ntraj') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('ntraj')+1:) | |
rewind(13) | |
read(13,*) ntraj | |
rewind(13) | |
if (ntraj.gt.mntraj) then | |
write(6,111) 'NTRAJ = ',ntraj,' exceeds the maximum', & | |
' number of trajectories the program set: ',mntraj | |
stop | |
endif | |
! default: maxtraj = ntraj | |
maxtraj = ntraj | |
endif | |
ifkeyexist=index(records,'tflag1') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('tflag1')+1:) | |
rewind(13) | |
read(13,*) tflag(1) | |
rewind(13) | |
if (tflag(1).lt.0 .or. tflag(1).gt.5) then | |
write(6,*) 'TFLAG1 != 0, 1, 2, 3, 4, 5 is not supported' | |
stop | |
endif | |
endif | |
! For termflag=7 only. Equilibrium to provide initial Mom and | |
! Structure | |
if (index(records,'noequilibrium') .GT. 0) stateselect=.true. | |
! Save coord. and momentum from itosave'th step | |
ifkeyexist=index(records,'itosave') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('itosave')+1:) | |
rewind(13) | |
read(13,*) itosave | |
rewind(13) | |
endif | |
! Save coord. and momentum every nsave steps | |
! ifkeyexist=index(records,'nsave') | |
! if (ifkeyexist .GT. 0) then | |
! write(13,*) records(ifkeyexist+len('nsave')+1:) | |
! rewind(13) | |
! read(13,*) nsave | |
! rewind(13) | |
! endif | |
! ensemble used for equilibrium run (react col and termflag=7) | |
ifkeyexist=index(records,'ieqtherm') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('ieqtherm')+1:) | |
rewind(13) | |
read(13,*) ieqtherm | |
rewind(13) | |
if (ieqtherm.lt.0 .or. ieqtherm.gt.2) then | |
write(6,*) 'ERROR: IEQTHERM = 0,1,2 only' | |
stop | |
endif | |
endif | |
! Temperature adjusting method | |
ifkeyexist=index(records,'iadjtemp') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('iadjtemp')+1:) | |
rewind(13) | |
read(13,*) iadjtemp | |
rewind(13) | |
if (iadjtemp.lt.0 .or. iadjtemp.gt.3) then | |
write(6,*) 'ERROR: IADJTEMP = 0,1,2,3 only' | |
stop | |
endif | |
endif | |
! Pressure adjusting method | |
ifkeyexist=index(records,'iadjpress') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('iadjpress')+1:) | |
rewind(13) | |
read(13,*) iadjpress | |
rewind(13) | |
endif | |
! Coupling parameter between the bath and the system | |
ifkeyexist=index(records,'taut') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('taut')+1:) | |
rewind(13) | |
read(13,*) taut | |
rewind(13) | |
endif | |
ifkeyexist=index(records,'taup') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('taup')+1:) | |
rewind(13) | |
read(13,*) taup | |
rewind(13) | |
endif | |
!C 'Mass' used for Nose-Hoover thermostat | |
! ifkeyexist=index(records,'qnose1') | |
! if (ifkeyexist .GT. 0) then | |
! write(13,*) records(ifkeyexist+len('qnose1')+1:) | |
! rewind(13) | |
! read(13,*) nh(1,1) | |
! rewind(13) | |
! endif | |
! ifkeyexist=index(records,'qnose2') | |
! if (ifkeyexist .GT. 0) then | |
! write(13,*) records(ifkeyexist+len('qnose2')+1:) | |
! rewind(13) | |
! read(13,*) nh(1,2) | |
! rewind(13) | |
! endif | |
! Charactoristic vibration frequency of the system (1/fs) used | |
! for Nose-Hoover thermostat | |
ifkeyexist=index(records,'sysfreq') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('sysfreq')+1:) | |
rewind(13) | |
read(13,*) sysfreq | |
rewind(13) | |
endif | |
! Collision frequency used by Andersen thermostat | |
ifkeyexist=index(records,'vfreq') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('vfreq')+1:) | |
rewind(13) | |
read(13,*) vfreq | |
rewind(13) | |
endif | |
! If remove CoM angular before entering DRIVER | |
if (index(records,'keepangmom') .GT. 0) ifnoang = .false. | |
if (index(records,'withrotineq') .GT.0) ifeqwithrot= .true. | |
if (index(records,'noreinitrot') .GT.0) ifreinitrot= .false. | |
if (index(records,'scaleenergy') .GT.0) iscaleenergy = .true. | |
! Remove angmom every nreinit steps | |
ifkeyexist=index(records,'nreinit') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('nreinit')+1:) | |
rewind(13) | |
read(13,*) nreinit | |
rewind(13) | |
endif | |
! If reset the CoM to origin | |
if (index(records,'nozerocom') .GT. 0) lzerocom = .false. | |
! If reset the CoM to origin | |
if (index(records,'keeptrans') .GT. 0) lzerotrans = .false. | |
! trajectory picking method | |
ifkeyexist=index(records,'ipicktrj') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('ipicktrj')+1:) | |
rewind(13) | |
read(13,*) ipicktrj | |
rewind(13) | |
if (ipicktrj.lt.0 .or. ipicktrj.gt.2) then | |
write(6,*) 'ERROR: only 3 choices for ipicktrj: 0,1,2' | |
stop | |
endif | |
endif | |
! Probability of choose trajectories in Equil run | |
ifkeyexist=index(records,'pickthr') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('pickthr')+1:) | |
rewind(13) | |
read(13,*) pickthr | |
rewind(13) | |
endif | |
! TE threshold (low) to pick trajectories in Equil run | |
ifkeyexist=index(records,'demin') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('demin')+1:) | |
rewind(13) | |
read(13,*) demin | |
rewind(13) | |
endif | |
! TE threshold (upper) to pick trajectories in Equil run | |
ifkeyexist=index(records,'demax') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('demax')+1:) | |
rewind(13) | |
read(13,*) demax | |
rewind(13) | |
endif | |
! change temperature at ramptime | |
ifkeyexist=index(records,'rampstep0') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('rampstep0')+1:) | |
rewind(13) | |
read(13,*) nrampstep | |
rewind(13) | |
endif | |
ifkeyexist=index(records,'rampfact') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('rampfact')+1:) | |
rewind(13) | |
read(13,*) rampfact | |
rewind(13) | |
endif | |
! ramping time interval | |
ifkeyexist=index(records,'n_ramp') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('n_ramp')+1:) | |
rewind(13) | |
read(13,*) n_ramp | |
rewind(13) | |
endif | |
! equilibrate for tequil time after a ramping interval | |
ifkeyexist=index(records,'nequilramp') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('nequilramp')+1:) | |
rewind(13) | |
read(13,*) nequil | |
rewind(13) | |
endif | |
! ramping times | |
ifkeyexist=index(records,'nramp') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('nramp')+1:) | |
rewind(13) | |
read(13,*) nramp | |
rewind(13) | |
endif | |
! restarting trajectory information | |
if (index(records,'restart') .GT. 0) then | |
tflag(2) = 1 | |
! trajectory list must be from the next line of restart | |
read(12,*) (trajlist(k),k=1,ntraj) | |
maxtraj = trajlist(1) | |
do k=1,ntraj | |
maxtraj = max(maxtraj,trajlist(k)) | |
enddo | |
read(12,'(a)',end=9999) records | |
endif | |
! End of records | |
if (index(records,'$end') .GT. 0) then | |
endreccon=9999 | |
else | |
read(12,'(a)',end=9999) records | |
endif | |
enddo | |
! Move to next line | |
read(12,'(a)',end=9999) records | |
endif | |
! JZ tunneling | |
if(index(records,'$tunneling') .GT.0) then | |
ntunn = 0 | |
endreccon=0 | |
ltunn = .true. | |
do while(endreccon.ne.9999) | |
ifkeyexist=index(records,'eta') | |
if(ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('eta')+1:) | |
rewind(13) | |
read(13,*) eta | |
rewind(13) | |
if (eta.lt.0.d0.or.eta.gt.1.d0) then !RMP | |
write(6,*) "The value of eta must be ",& !RMP | |
"between 0 and 1." !RMP | |
stop !RMP | |
endif !RMP | |
endif | |
! ifkeyexist=index(records,'probthr') | |
! if(ifkeyexist .GT. 0) then | |
! write(13,*) records(ifkeyexist+len('probthr')+1:) | |
! rewind(13) | |
! read(13,*) actint_thr | |
! rewind(13) | |
! actint_thr = -0.5d0*log(actint_thr) | |
! endif | |
ifkeyexist=index(records,'ngauss') | |
if(ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('ngauss')+1:) | |
rewind(13) | |
read(13,*) ngauss | |
rewind(13) | |
if (ngauss.gt.512) then !RMP | |
write(6,*) "Number of Gaussian-quadrature nodes must be ", & | |
"no more than 512." | |
stop | |
endif | |
endif | |
! ifkeyexist=index(records,'ntunn_mode') ! RMP remove this part correspond to the normal modes | |
! if (ifkeyexist .gt. 0) then | |
! write(13,*) records(ifkeyexist+len('ntunn_mode')+1:) | |
! rewind(13) | |
! read(13,*) ntunn_mode | |
! rewind(13) | |
! read(12,'(a)',end=9999) records | |
! write(13,*) records | |
! rewind(13) | |
! read(13,*) (itmod(j),j=1,ntunn_mode) | |
! rewind(13) | |
! endif | |
! streching internal coordinates | |
ifkeyexist=index(records,'nstr') | |
if (ifkeyexist .gt. 0) then | |
write(13,*) records(ifkeyexist+len('nstr')+1:) | |
rewind(13) | |
read(13,*) nstr | |
rewind(13) | |
k = 0 | |
do i = 1, nstr | |
k = k + 1 | |
read(12,'(a)',end=9999) records | |
write(13,*) records | |
rewind(13) | |
if(index(records,'*').gt.0) then | |
ntunn = ntunn + 1 | |
itunn(k) = 1 | |
tuntype = 1 | |
drr(k) = 1d0 | |
read(13,*) (istr(j,i),j=1,2) | |
elseif(index(records,'+').gt.0) then | |
itunn(k) = 1 | |
tuntype = 2 | |
read(13,*) (istr(j,i),j=1,2),chartmp,drr(k) | |
elseif(index(records,'-').gt.0) then | |
itunn(k) = -1 | |
tuntype = 2 | |
read(13,*) (istr(j,i),j=1,2),chartmp,drr(k) | |
drr(k) = -drr(k) | |
else | |
read(13,*) (istr(j,i),j=1,2) | |
endif | |
rewind(13) | |
enddo | |
endif | |
! bond angles | |
ifkeyexist=index(records,'nbend') | |
if (ifkeyexist .gt. 0) then | |
write(13,*) records(ifkeyexist+len('nbend')+1:) | |
rewind(13) | |
read(13,*) nbend | |
rewind(13) | |
do i = 1, nbend | |
k = k + 1 | |
! RMP we should double check all the possible options in the input file | |
read(12,'(a)',end=9999) records | |
if(index(records,'*').gt.0) then | |
ntunn = ntunn + 1 | |
itunn(k) = 1 | |
tuntype = 1 | |
drr(k) = 1d0 | |
! elseif(index(records,'+').gt.0) then ! RMP it is not needed | |
! itunn(k) = 1 | |
! tuntype = 2 | |
! elseif(index(records,'-').gt.0) then | |
! itunn(k) = -1 | |
! tuntype = 2 | |
endif | |
write(13,*) records | |
rewind(13) | |
read(13,*) (ibend(j,i),j=1,3) | |
rewind(13) | |
enddo | |
endif | |
! RMP | |
! linear bendings | |
!integer :: nlinben,ilinben(3,3*mnat) in c_initial.f | |
ifkeyexist=index(records,'linben') | |
if (ifkeyexist .gt. 0) then | |
write(13,*) records(ifkeyexist+len('linben')+1:) | |
read(13,*) nlinben | |
rewind(13) | |
do i = 1, nlinben | |
k = k + 1 | |
read(12,'(a)',end=9999) records | |
if(index(records,'*').gt.0) then | |
ntunn = ntunn + 1 | |
itunn(k) = 1 | |
tuntype = 1 | |
drr(k) = 1d0 | |
! elseif(index(records,'+').gt.0) then !RMP is not needed | |
! itunn(k) = 1 | |
! tuntype = 2 | |
! elseif(index(records,'-').gt.0) then | |
! itunn(k) = -1 | |
! tuntype = 2 | |
endif | |
write(13,*) records | |
rewind(13) | |
read(13,*) (ilinben(j,i),j=1,3) | |
rewind(13) | |
enddo | |
endif | |
! dihedral angles | |
ifkeyexist=index(records,'ntor') | |
if (ifkeyexist .gt. 0) then | |
write(13,*) records(ifkeyexist+len('ntor')+1:) | |
rewind(13) | |
read(13,*) ntor | |
rewind(13) | |
do i = 1, ntor | |
k = k + 1 | |
read(12,'(a)',end=9999) records | |
if(index(records,'*').gt.0) then | |
ntunn = ntunn + 1 | |
itunn(k) = 1 | |
tuntype = 1 | |
drr(k) = 1d0 | |
! elseif(index(records,'+').gt.0) then !RMP is not needed | |
! itunn(k) = 1 | |
! tuntype = 2 | |
! elseif(index(records,'-').gt.0) then | |
! itunn(k) = -1 | |
! tuntype = 2 | |
endif | |
write(13,*) records | |
rewind(13) | |
read(13,*) (itor(j,i),j=1,4) | |
rewind(13) | |
enddo | |
endif | |
! out of plane / improper torsion | |
ifkeyexist=index(records,'nimptor') | |
if (ifkeyexist .gt. 0) then | |
write(13,*) records(ifkeyexist+len('nimptor')+1:) | |
rewind(13) | |
read(13,*) nimptor | |
rewind(13) | |
do i = 1, nimptor | |
k = k + 1 | |
read(12,'(a)',end=9999) records | |
if(index(records,'*').gt.0) then | |
ntunn = ntunn + 1 | |
itunn(k) = 1 | |
tuntype = 1 | |
drr(k) = 1d0 | |
! elseif(index(records,'+').gt.0) then ! RMP is not needed | |
! itunn(k) = 1 | |
! tuntype = 2 | |
! elseif(index(records,'-').gt.0) then | |
! itunn(k) = -1 | |
! tuntype = 2 | |
endif | |
write(13,*) records | |
rewind(13) | |
read(13,*) (imptor(j,i),j=1,4) | |
rewind(13) | |
enddo | |
endif | |
if(index(records,'$end') .GT. 0) then | |
endreccon=9999 | |
else | |
read(12,'(a)',end=9999) records | |
endif | |
enddo | |
! Move to next line | |
read(12,'(a)',end=9999) records | |
endif | |
! | |
! JZ MOPAC | |
if(index(records,'$mopac') .GT.0) then | |
potflag = -2 | |
endreccon=0 | |
read(12,'(a)',end=9999) records | |
do while(endreccon.ne.9999) | |
if(index(records,'$end') .GT. 0) then | |
endreccon=9999 | |
else | |
keywrd = records | |
write(6,*) 'keywrd',keywrd | |
read(12,'(a)',end=9999) records | |
endif | |
enddo | |
! Move to next line | |
read(12,'(a)',end=9999) records | |
endif | |
! | |
! | |
! Output writing list | |
if (index(records,'$output') .GT. 0) then | |
endreccon=0 | |
do while(endreccon .ne. 9999) | |
! Print information every nprint steps | |
ifkeyexist=index(records,'nprint') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('nprint')+1:) | |
rewind(13) | |
read(13,*) nprint | |
rewind(13) | |
endif | |
! maxprint controls if print information in detail | |
if (index(records,'maxprint') .GT. 0) maxprint = .true. | |
! minprinticon removes printing of selection of initial conditions | |
if (index(records,'minprinticon') .GT. 0) & | |
minprinticon = .true. | |
! minprinttrapz removes intermediate information from TRAPZ | |
if (index(records,'minprinttrapz') .GT. 0) & | |
minprinttrapz = .true. | |
! idebug controls if print information in detail | |
if (index(records,'idebug') .GT. 0) then | |
idebug = .true. | |
maxprint = .true. | |
endif | |
! outputflag | |
ifkeyexist=index(records,'outflag') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('outflag')+1:) | |
rewind(13) | |
read(13,*) outflag | |
rewind(13) | |
if (outflag.eq.0) then | |
do j=1,99 | |
lwrite(j)=.true. | |
enddo | |
elseif (outflag.gt.0 .and. outflag.le.99) then | |
do j=1,1000 | |
lwrite(j)=.false. | |
enddo | |
! readin output writting list | |
read(12,*,iostat=ierror) (ilwrite(k),k=1,outflag) | |
if (ierror.ne.0) then | |
write(6,222) 'ERROR: output list reading error.', & | |
' Last read: ',ilwrite(k-1) | |
stop | |
endif | |
do j=1,outflag | |
lwrite(ilwrite(j)) = .true. | |
if (lwrite(48)) lwrite(47)=.true. | |
enddo | |
else | |
write(6,*) 'OUTFLAG= ',outflag,' is not supported' | |
stop | |
endif | |
endif | |
! End of records | |
if (index(records,'$end') .GT. 0) then | |
endreccon=9999 | |
else | |
read(12,'(a)',end=9999) records | |
endif | |
enddo | |
! Move to next line | |
read(12,'(a)',end=9999) records | |
endif | |
! | |
! --------------------------------------------------------- | |
! Atom-diatom section | |
if (index(records,'$atomdiatom') .GT. 0) then | |
! if input for $atomdiatom appears, it is a special triatom run | |
atomdiatom = .true. | |
endreccon=0 | |
do while(endreccon .ne. 9999) | |
! Total energy in eV | |
ifkeyexist=index(records,'escatad') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('escatad')+1:) | |
rewind(13) | |
read(13,*) escatad | |
rewind(13) | |
endif | |
! Initial vibrational quantum number for the diatom | |
ifkeyexist=index(records,'vvad') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('vvad')+1:) | |
rewind(13) | |
read(13,*) vvad | |
rewind(13) | |
endif | |
! Initial rotational quantum number for the diatom | |
ifkeyexist=index(records,'jjad') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('jjad')+1:) | |
rewind(13) | |
read(13,*) jjad | |
rewind(13) | |
endif | |
! Initial atom-diatom separation in Angstrom | |
ifkeyexist=index(records,'rrad0') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('rrad0')+1:) | |
rewind(13) | |
read(13,*) rrad0 | |
rewind(13) | |
endif | |
! Initial molecular arrangement, 1: AB+C, 2: BC+A, 3: AC+B | |
ifkeyexist=index(records,'arrad') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('arrad')+1:) | |
rewind(13) | |
read(13,*) arrad | |
rewind(13) | |
endif | |
! RMP14 | |
! Impact parameter | |
ifkeyexist=index(records,'bparam') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('bparam')+1:) | |
rewind(13) | |
read(13,*) bparam | |
bparam=bparam/autoang | |
rewind(13) | |
endif | |
ifkeyexist=index(records,'bmaxad') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('bmaxad')+1:) | |
rewind(13) | |
read(13,*) bmaxad ! in angstrom | |
bmaxad=bmaxad/autoang | |
rewind(13) | |
endif | |
ifkeyexist=index(records,'bminad') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('bminad')+1:) | |
rewind(13) | |
read(13,*) bminad ! in angstrom | |
bminad=bminad/autoang | |
rewind(13) | |
endif | |
! RMP14 | |
! Atom diatom Modes: | |
ifkeyexist=index(records,'mode') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('mode')+1:) | |
rewind(13) | |
read(13,*) admode | |
if(admode.lt.0.or.admode.gt.3) then | |
write(6,*) "Error in Atom-diatom mode" | |
write(6,*) "Currently only mode=1,2,3 are available." | |
stop | |
endif | |
rewind(13) | |
endif | |
! Atom diatom Phase Modes: | |
ifkeyexist=index(records,'phmode') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('phmode')+1:) | |
rewind(13) | |
read(13,*) phmode | |
if(phmode.lt.1.or.phmode.gt.2) then | |
write(6,*) "Error in Atom-diatom phase mode" | |
write(6,*) "Currently only mode=1,2 are available." | |
stop | |
endif | |
rewind(13) | |
endif | |
! RMP14 | |
! Atom diatom Modes: | |
ifkeyexist=index(records,'emode') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('emode')+1:) | |
rewind(13) | |
read(13,*) ademod | |
if(ademod.lt.1.or.ademod.gt.2) then | |
write(6,*) "Error in Atom-diatom energy mode" | |
write(6,*) "The available options are:" | |
write(6,*) " emode = 1 Scattering energy by input" | |
write(6,*) " emode = 2 Collision energy by input" | |
stop | |
endif | |
rewind(13) | |
endif | |
! RMP14 | |
! Atom diatom Modes: | |
ifkeyexist=index(records,'ecoli') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('ecoli')+1:) | |
rewind(13) | |
read(13,*) ecolad | |
rewind(13) | |
endif | |
! RMP14 | |
! Controls how the diatomic potential is computed | |
ifkeyexist=index(records,'flagdiat') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('flagdiat')+1:) | |
rewind(13) | |
ldiat=.true. | |
endif | |
! Meet the end of this section | |
if (index(records,'$end') .GT. 0) then | |
endreccon=9999 | |
else | |
read(12,'(a)',end=9999) records | |
endif | |
enddo | |
! Move to next line | |
read(12,'(a)',end=9999) records | |
endif | |
! | |
! Results analysis control deck | |
if (index(records,'$analysis') .GT. 0) then | |
endreccon=0 | |
do while(endreccon .ne. 9999) | |
ifkeyexist=index(records,'nstat') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('nstat')+1:) | |
rewind(13) | |
read(13,*) nstat | |
rewind(13) | |
endif | |
if (index(records,'cohesive') .GT. 0) cohesive=.true. | |
if (index(records,'kinetic') .GT. 0) kinetic=.true. | |
if (index(records,'potential') .GT. 0) potential=.true. | |
if (index(records,'totenergy') .GT. 0) totenergy=.true. | |
if (index(records,'fragcon') .GT. 0) icfrag=.true. | |
ifkeyexist=index(records,'heatcapacity') | |
if (ifkeyexist .GT. 0) then | |
heatcap=.true. | |
totenergy=.true. | |
endif | |
! Bin distanc used for the bin | |
ifkeyexist=index(records,'rbin') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('rbin')+1:) | |
rewind(13) | |
read(13,*) rbin | |
rewind(13) | |
rbin = rbin/autoang | |
endif | |
! End of records | |
if (index(records,'$end') .GT. 0) then | |
endreccon=9999 | |
else | |
read(12,'(a)',end=9999) records | |
endif | |
enddo | |
! Move to next line | |
read(12,'(a)',end=9999) records | |
endif | |
! --------------------------------------------------------- | |
! Coordinates and other data for every AG goes here. Here the format is | |
! relatively fixed. No need to use endreccon to judge if the section is | |
! finished | |
if (index(records,'$data') .GT. 0) then | |
! Number of molecules or atom groups (AGs) | |
read(12,'(a)',end=9999) records | |
ifkeyexist=index(records,'nmol') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('nmol')+1:) | |
rewind(13) | |
read(13,*) nmol | |
rewind(13) | |
if (nmol.lt.1 .or. nmol.gt.mnmol) then | |
write(6,222) 'ERROR: number of AGs cant be less than 1', & | |
' or larger than ',mnmol | |
stop | |
elseif (atomdiatom .and. nmol.ne.1) then | |
write(6,108) 'ERROR: atom-diatom calculation cant', & | |
' be used with multi AGs (nmol>1)' | |
stop | |
elseif (reactcol .and. nmol.ne.2) then | |
write(6,108) 'ERROR: currently reactive collision can ', & | |
'only be used with two AGs (nmol=2)' | |
stop | |
else | |
continue | |
endif | |
! Move to the next line after reading nmol | |
read(12,'(a)',end=9999) records | |
endif | |
! | |
! Data for each AG, loop over nmol AGs, had to be formated at present | |
! version of ants | |
! | |
nat = 0 | |
do im=1,nmol | |
! Natom, initx, initp | |
! Input for natom, initx, and initp should be in one line | |
! User can choose not to provide initx and initp, but must for natom | |
ifkeyexist=index(records,'natom') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('natom')+1:) | |
rewind(13) | |
read(13,*) natom(im) | |
rewind(13) | |
if (natom(im).lt.1 .or. natom(im).gt.mnat) then | |
write(6,222)'ERROR: number of atoms cant be less than', & | |
' 1 or larger than ',mnat | |
stop | |
endif | |
endif | |
! read in charge information for each atoms or not | |
if (index(records,'readinchg') .GT. 0) ireadchg=.true. | |
! initx information | |
ifkeyexist=index(records,'initx') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('initx')+1:) | |
rewind(13) | |
read(13,*) initx(im) | |
rewind(13) | |
if (initx(im).lt.0 .or. initx(im).gt.5) then | |
write(6,333) 'ERROR: initial conditions flag = ', & | |
initx(im),' is not supported' | |
stop | |
endif | |
if (initx(im).eq.4) then | |
if (natom(im).ne.3.and.nmol.ne.1) then | |
write(6,108) 'INITx=3 must be used with a triatomic', & | |
' molecule, and only a single AG' | |
write(6,*) '.ie. natom=3 and nmol=1' | |
stop | |
endif | |
endif | |
if ((initx(im).eq.3 .or. initx(im).eq.5) .and. nmol.ne.1) then | |
write(6,444) 'ERROR: randomly generate box only for ', & | |
'single AG run' | |
stop | |
endif | |
endif | |
ifkeyexist=index(records,'initp') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('initp')+1:) | |
rewind(13) | |
read(13,*) initp(im) | |
rewind(13) | |
if (initp(im).lt.-1 .or. initp(im).gt.1) then | |
write(6,333) 'ERROR: initial conditions flag = ', & | |
initp(im),' is not supported' | |
stop | |
endif | |
endif | |
ifkeyexist=index(records,'temp0im') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('temp0im')+1:) | |
rewind(13) | |
read(13,*) temp0im(im) | |
rewind(13) | |
endif | |
! ifkeyexist=index(records,'vibene') | |
! if (ifkeyexist .GT. 0) then | |
! write(13,*) records(ifkeyexist+len('vibene')+1:) | |
! rewind(13) | |
! read(13,*) vibene(im) | |
! rewind(13) | |
! vibene(im) = vibene(im)/autoev | |
! endif | |
ifkeyexist=index(records,'verte') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('verte')+1:) | |
rewind(13) | |
read(13,*) verte(im) | |
rewind(13) | |
verte(im) = verte(im)/autoev | |
endif | |
ifkeyexist=index(records,'bandwd') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('bandwd')+1:) | |
rewind(13) | |
read(13,*) bandwd(im) | |
rewind(13) | |
bandwd(im) = bandwd(im)/autoev | |
endif | |
! Initial relative translation energy between two AGs | |
! (unit: kT) | |
ifkeyexist=index(records,'ereltrans') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('ereltrans')+1:) | |
rewind(13) | |
read(13,*) etrans(im) | |
rewind(13) | |
etrans(im) = etrans(im)*kb*temp0im(im) | |
transelect = .true. | |
endif | |
! Initial vibrational state information | |
ifkeyexist=index(records,'vibselect') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('vibselect')+1:) | |
rewind(13) | |
read(13,*) vibsel(im) | |
rewind(13) | |
endif | |
! coordinate & momentum distribution of vibration | |
ifkeyexist=index(records,'vibdist') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('vibdist')+1:) | |
rewind(13) | |
read(13,*) ivibdist(im) | |
rewind(13) | |
endif | |
! Initial geometry is a minimum or a saddle point | |
ifkeyexist=index(records,'vibtype') | |
if (ifkeyexist .GT. 0) then | |
write(13,*) records(ifkeyexist+len('vibtype')+1:) | |
rewind(13) | |
read(13,*) ivibtype(im) | |
rewind(13) | |
endif | |
! Mode populations were implemented assuming that populations are obtained | |
! from a quasiclassical distribution. So vibdist must equal 0 when lmodpop | |
! is true. | |
if (lmodpop) ivibdist(im) = 0 | |
! Set values for initx and initp according to the specification in the | |
! keyword sections | |
if (atomdiatom) then | |
initx(im) = 4 | |
initp(im) = -1 | |
endif | |
! If the user choose to do a normal mode analysis, | |
! initp should be set as -1 | |
if ( vibsel(im).ne.0 .and. vibsel(im).ne.3) then | |
initp(im) = -1 | |
endif | |
if ( vibsel(im).eq.3) then | |
itempzpe=.true. | |
endif | |
! | |
! iatom(im): the index of the first atom of AG im in all the atoms, | |
! starts from 1. | |
! nat: total number of atoms in a run, sum over natom(im) | |
iatom(im) = nat + 1 | |
nat = nat+natom(im) | |
if (nat.gt.mnat) then | |
write(6,222) 'ERROR: the number of all atoms cant be', & | |
' larger than',mnat | |
stop | |
endif | |
! Since charges, multi, coord. are written in a formatted format, it is | |
! no need to use file 13 to transfer data | |
! Charge and multiplicity, in one line, move to next line after reading | |
read(12,*) icharge(im),imulti(im) | |
! Coordinates (if any) and other information related to coordinates | |
! INITx controls the initial coordinates | |
! read different info depending on the value of INITx(IM) | |
if (initx(im).eq.0) then | |
do i =1,natom(im) | |
ii=iatom(im)+i-1 | |
! read in atomic symbol, mass, and coords | |
if (ireadchg) then | |
read(12,*) symbolm(i),charge(i),mmm(i), & | |
(xxm(k,i),k=1,3) | |
else | |
read(12,*) symbolm(i),mmm(i),(xxm(k,i),k=1,3) | |
endif | |
! convert from amu to au before calculating principal axes of rotation | |
mmm(i) = mmm(i) * amutoau | |
do k =1,3 | |
! convert from angstrom to bohr | |
xxm(k,i) = xxm(k,i)/autoang | |
! put them to global storage | |
enddo | |
mm0(ii) = mmm(i) | |
symbol0(ii) = symbolm(i) | |
enddo | |
! Judge if this molecule is linear or not | |
natoms=natom(im) | |
call comgen(xxm,mmm,natoms,comxxm,mmofag(im)) | |
! Get principal axes of rotation, get rotaxis by calling | |
! rotprin | |
call rotprin(xxm,mmm,natoms,momiprin,rotaxis, & | |
linearmol(im)) | |
! Rot to the principal axes of rotation | |
! not for periodic condition | |
if (.not.periodic) then | |
call rottran(rotaxis,xxm,natoms) | |
endif | |
do i=1,natom(im) | |
ii=iatom(im)+i-1 | |
do k =1,3 | |
xx0(k,ii) = xxm(k,i) | |
enddo | |
enddo | |
if (linearmol(im).eq.0) then | |
nvibmods(im) = 0 | |
nrotmods(im) = 0 | |
elseif (linearmol(im).eq.1) then | |
nvibmods(im) = 3*natom(im) - 5 | |
nrotmods(im) = 2 | |
else | |
nvibmods(im) = 3*natom(im) - 6 | |
nrotmods(im) = 3 | |
endif | |
elseif (initx(im).eq.1 .or. initx(im).eq.2 & | |
.or. initx(im).eq.3) then | |
if (natom(im).le.1) then | |
write(6,108) 'ERROR: Only one atom, no need to', & | |
' generate coordinates by random method.' | |
stop | |
endif | |
if (initx(im).eq.1) read(12,*) rran(1,im) | |
if (initx(im).eq.2.) read(12,*) (rran(j,im),j=1,3) | |
! read in atomic symbol, and mass. User uses, e.g. 1 H 2 C to | |
! input, this is easy if AG contains a large number of atoms | |
! inattmp to store the number of one atom type | |
! j counts the atoms in this AG, sum of inattmp | |
j=0 | |
do while(j.lt.natom(im)) | |
read(12,*) inattmp,symbtmp,mmtmp | |
do k=iatom(im)+j,iatom(im)+j+inattmp-1 | |
symbol0(k) = symbtmp | |
mm0(k) = mmtmp | |
enddo | |
j=j+inattmp | |
enddo | |
if (j.ne.natom(im)) then | |
write(6,108) 'ERROR: sum of atom numbers does not', & | |
' match the total number of atoms for this AG' | |
stop | |
endif | |
! random mol. | |
elseif (initx(im).eq.5) then | |
read(12,*) (rran(j,im),j=1,3) | |
read(12,*) nunit,natunit | |
natom(im)=nunit*natunit | |
do j=1,natunit | |
read(12,*) symbtmp,mmtmp,(xunit(k,j),k=1,3) | |
do k=1,3 | |
xunit(k,j)=xunit(k,j)/autoang | |
enddo | |
do i=1,nunit | |
ii=(i-1)*natunit+j | |
symbol0(ii) = symbtmp | |
mm0(ii) = mmtmp | |
enddo | |
enddo | |
! Atom-diatom calculation | |
elseif (initx(im).eq.4) then | |
do i = iatom(im), iatom(im)+natom(im)-1 | |
! read in atomic symbol, and mass | |
read(12,*) symbol0(i), mm0(i) | |
enddo | |
else | |
write(6,333) 'ERROR: initial conditions initx = ', & | |
initx(im),' is not supported' | |
! this endif ends information on initx | |
endif | |
! Move to next line after readin structures | |
read(12,'(a)',end=9999) records | |
! | |
! Read in vibration quantum numbers the user specify. | |
if (index(records,'vibstate').gt.0) then | |
vibsel(im) = 1 | |
if (natom(im).eq.1) then | |
write(6,108) 'ERROR: there is no vibrational mode ', & | |
'for just one atom' | |
stop | |
endif | |
read(12,*,iostat=ierror) (qnmvib0(k,im), k=1,nvibmods(im)) | |
if (ierror.ne.0) then | |
write(6,222) 'ERROR: reading vibrational quantum ', & | |
'numbers for AG ',im | |
stop | |
endif | |
! RVM | |
if (ivibtype(im).eq.1) then | |
write(6,*)"Initial geometry is a saddle point" | |
write(6,*)"Unbound mode will be assigned an energy of ", & | |
qnmvib0(nvibmods(im),im)," eV" | |
qnmvib0(nvibmods(im),im)=qnmvib0(nvibmods(im),im)/autoev | |
else | |
write(6,*)"Initial geometry is a local minimum" | |
endif | |
! Move to next line after readin vib modes | |
read(12,'(a)',end=9999) records | |
endif | |
! Read in the vibrational energy for each mode | |
if (index(records,'vibene').gt.0) then | |
if (natom(im).eq.1) then | |
write(6,108) 'ERROR: there is no vibrational mode ', & | |
'for just one atom ' | |
stop | |
endif | |
if( vibsel(im).eq.4.or.vibsel(im).eq.6) then | |
read(12,*,iostat=ierror) tmp | |
vibene(:,im) = tmp | |
elseif(vibsel(im).eq.5.or.vibsel(im).eq.7) then | |
read(12,*,iostat=ierror) (vibene(k,im), k=1,nvibmods(im)) | |
else | |
write(6,*)'ERROR: vibene should be used together ', & | |
'with vibselect = 4, 5, 6, or 7' | |
endif | |
vibene(:,im)=vibene(:,im)/autoev | |
if (ierror.ne.0) then | |
write(6,222)'ERROR: reading vibrational energy ', & | |
'for AG ',im | |
stop | |
endif | |
! Move to next line after readin vibene | |
read(12,'(a)',end=9999) records | |
endif | |
! Read in vibdist for each individual mode | |
if (index(records,'vibdistn').gt.0) then | |
if (natom(im).eq.1) then | |
write(6,108) 'ERROR: there is no vibrational mode ', & | |
'for just one atom ' | |
stop | |
endif | |
if(ivibdist(im).ne.9) then | |
write(6,*) 'ERROR: to use vibdistn, the vibdist must',' be 9' | |
stop | |
endif | |
read(12,*,iostat=ierror) (vibdistn(k,im), k=1,nvibmods(im)) | |
! Move to next line after readin vibene | |
read(12,'(a)',end=9999) records | |
endif | |
! Readin rotational quantum numbers if rotselect=1 | |
! and only for linear molecules | |
! Force sample rotational energy based on temp(im) | |
if (index(records,'rottemp') .gt. 0 )then | |
irottemp = .true. | |
read(12,'(a)',end=9999) records | |
else | |
irottemp = .false. | |
endif | |
if (index(records,'rotfreeze') .gt. 0 )then | |
irotfreeze = .true. | |
read(12,'(a)',end=9999) records | |
else | |
irotfreeze = .false. | |
endif | |
if (index(records,'rotstate').gt.0 ) then | |
rotsel(im) = .true. | |
rotst(im) = .true. | |
if (linearmol(im).eq.1) then | |
read(12,*,iostat=ierror) qnmrot0(1,im) | |
if (ierror.ne.0) then | |
write(6,222) 'ERROR: reading rotational quantum ', & | |
'numbers for AG ',im | |
stop | |
endif | |
eroti(1,im)=dble(qnmrot0(1,im)*(qnmrot0(1,im)+1))/ & | |
( 2.d0*momiprin(3) ) | |
erot(im) = eroti(1,im) | |
elseif (linearmol(im).eq.0) then | |
write(6,108) 'ERROR: there is no rotation for', & | |
' just one atom' | |
stop | |
else | |
write(6,108) 'ERROR: Cant deal with nonlinear ', & | |
'molecule for stateselect rotation' | |
stop | |
endif | |
! Move to next line after readin rot modes | |
read(12,'(a)',end=9999) records | |
endif | |
if (index(records,'rotenerg').gt.0 ) then | |
rotsel(im) = .true. | |
roteng(im) = .true. | |
if (linearmol(im).ne.0) then | |
read(12,*,iostat=ierror) (eroti(k,im), k=1,nrotmods(im)) | |
if (ierror.ne.0) then | |
write(6,222) 'ERROR: reading rotational energies ', & | |
'for AG ',im | |
stop | |
endif | |
else | |
write(6,108) 'ERROR: there is no rotation for', & | |
' just one atom' | |
stop | |
endif | |
erot(im)=0.d0 | |
do k=1,nrotmods(im) | |
eroti(k,im) = eroti(k,im)*kb*temp0im(im) | |
erot(im) = erot(im) + eroti(k,im) | |
enddo | |
! Move to next line after readin rot energies | |
read(12,'(a)',end=9999) records | |
endif | |
ireadchg = .false. | |
! this enddo ends the loop over AG data | |
enddo | |
! Move to next line | |
read(12,'(a)',end=9999) records | |
endif | |
! | |
! --------------------------------------------------------- | |
! Initial orientation | |
if (index(records,'$comxx') .GT. 0) then | |
! coordinates start from next line of $comxx | |
icomxx = .true. | |
do im=1,nmol | |
read(12,*) (comxx(k,im),k=1,3) | |
enddo | |
! Meet the end of this section, formated input, no need to find | |
! $end. first line to read $end second line to readin the line | |
! after $end | |
read(12,'(a)',end=9999) records | |
! Move to next line after reading $end | |
read(12,'(a)',end=9999) records | |
! | |
! --------------------------------------------------------- | |
! Initial translation momentum | |
endif | |
if (index(records,'$compp') .GT. 0) then | |
! coordinates start from next line of $compp | |
icompp = .true. | |
transelect = .true. | |
do im=1,nmol | |
read(12,*) (compp(k,im),k=1,3) | |
enddo | |
! Meet the end of this section, formated input, no need to find | |
! $end. first line to read $end second line to readin the line | |
! after $end | |
read(12,'(a)',end=9999) records | |
read(12,'(a)',end=9999) records | |
endif | |
! If a line contains only spaces (blank line), then move to next line | |
! How about a line composed of characters all useless to the program? | |
ifblank=0 | |
do j=1,74 | |
if (records(j:j).eq.' ') then | |
ifblank=ifblank+1 | |
endif | |
enddo | |
if (ifblank.eq.74) then | |
read(12,'(a)',end=9999) records | |
endif | |
if (index(records,'thend0') .GT. 0) goto 9999 | |
51 continue | |
9999 continue | |
close(12) | |
close(13) | |
! | |
! Check for bad combinations | |
if (reactcol) then | |
if (atomdiatom) then | |
write(6,108) 'ERROR: cant run reaction collision and ', & | |
'special atom-diatom at the same time' | |
stop | |
endif | |
if (termflag.eq.2) then | |
write(6,108) 'ERROR: TERMFLAG = 2 cant be used with', & | |
' react collision run' | |
stop | |
endif | |
if (tflag(1).ne.0) then | |
write(6,108) 'ERROR: tflag1 != 0 cant be used with', & | |
' react collision run' | |
stop | |
endif | |
if (termflag.eq.7) then | |
write(6,108) 'ERROR: Monitoring unimolecular fragmentation', & | |
' should not be used with react collision run' | |
stop | |
endif | |
endif | |
if (termflag.eq.6 .and. (.not.reactcol)) then | |
write(6,108) 'ERROR: TERMFLAG = 6 works only for', & | |
' reactive collision run' | |
stop | |
endif | |
if (termflag.eq.7 .and. nmol.ne.1) then | |
write(6,444) 'ERROR: Monitoring fragmentation ', & | |
'works only for 1 AG run (nmol=1)' | |
stop | |
endif | |
if (bdfmthr.gt.bdbrthr) then | |
write(6,*) 'ERROR: Bondbrthre must be larger than bondfmthre' | |
stop | |
endif | |
do im=1,nmol | |
if (vibsel(im).ne.0) then | |
if ((initx(im).ge.1 .and. initx(im).le.3) .or. initx(im).eq.5) then | |
write(6,108) 'ERROR: random structure cant do ', & | |
'normal mode analysis' | |
stop | |
endif | |
endif | |
if (vibsel(im).lt.4.and.vibene(1,im).gt.1d-10) then | |
write(6,*) 'ERROR: Fixed energy for each mode must use ' | |
write(6,*) 'vibsel=4, 5, 6, or 7' | |
endif | |
enddo | |
if (lfixte) then | |
write(6,*) 'Choosing fixed initial total energy' | |
write(6,555) 'Warning: currently only works for initial ', & | |
'conditions prepared with normod analysis', & | |
' without other motions (trans. & rot.)' | |
lzerotrans = .true. | |
ifnoang = .true. | |
if (nmol.ne.1) then | |
write(6,*) 'Currently works only for single AG simulation' | |
stop | |
endif | |
if (deltate.gt.small) then | |
write(6,666) 'TE0 fixed to between ',(te0fixed-deltate)*autoev, & | |
' eV and ',(te0fixed+deltate),' eV' | |
else | |
write(6,*) 'TE0 fixed to ',(te0fixed-deltate)*autoev,' eV' | |
endif | |
endif | |
! | |
! --------------------------------------------------------- | |
! All printout information for the input goes here | |
! Potential | |
write(6,'(1x,74a1)') ('-',i=1,74) | |
write(6,*) 'Potential information' | |
write(6,'(1x,74a1)') ('-',i=1,74) | |
write(6,*) 'POTFLAG = ',potflag | |
call prepot | |
if (potflag.eq.0) then | |
write(6,*) 'Using the POTLIB MM-HO-1 interface' | |
if (nsurft.ne.1) then | |
write(6,108) 'POTLIB MM-HO-1 is for SINGLE surface only, ', & | |
'NSURFT should be 1' | |
stop | |
endif | |
elseif (potflag.eq.1) then | |
write(6,*) 'Using the POTLIB 3-2V interface' | |
if (nat.ne.3) then | |
write(6,*) 'POTLIB 3-2V works only for 3 atoms' | |
stop | |
endif | |
if (nsurft.ne.2) then | |
write(6,*)'NSURFT = ',nsurft,' is not allowed for POTFLAG = 1' | |
stop | |
endif | |
elseif (potflag.eq.2) then | |
write(6,*) 'Using the POTLIB MM-HE-1 interface' | |
if (nsurft.ne.1) then | |
write(6,108) 'POTLIB MM-HE-1 is for SINGLE surface only, ', & | |
'NSURFT should be 1' | |
stop | |
endif | |
elseif (potflag.eq.3) then | |
write(6,*)'Using the NH3 interface' | |
if (nat.ne.4) then | |
write(6,*) 'NH3 potential works only for 4 atoms' | |
stop | |
endif | |
if (nsurft.ne.2) then | |
write(6,*)'NSURFT = ',nsurft,' is not allowed for NH3 potential' | |
stop | |
endif | |
elseif (potflag.eq.4) then | |
write(6,*) 'Using the 4-XS interface' | |
if (nsurft.ne.1) then | |
write(6,108) 'POTLIB 4-XS is for SINGLE surface only, ', & | |
'NSURFT should be 1' | |
stop | |
endif | |
if (nat.gt.4) then | |
write(6,*) 'POTLIB 4-XS is 4 body potential, but nat= ',nat | |
stop | |
endif | |
elseif (potflag.eq.5) then | |
write(6,*) 'Using the POTLIB MM-HE-1 interface' | |
if (nsurft.ne.1) then | |
write(6,108) 'POTLIB MM-HE-1 is for SINGLE surface only, ', & | |
'NSURFT should be 1' | |
stop | |
endif | |
elseif (potflag.eq.6) then | |
write(6,*) 'Using the HBr interface' | |
elseif (potflag.eq.7) then | |
write(6,*) 'Using the CH2BrCl interface' | |
elseif (potflag.eq.8) then | |
write(6,*) 'Using the HN2 interface' | |
elseif (potflag.eq.9) then | |
write(6,*) 'Using the HX2 interface' | |
elseif (potflag.eq.10) then | |
write(6,*) 'Using the Phenol interface' | |
elseif (potflag.eq.11) then | |
write(6,*) 'Using the N4 interface' | |
elseif (potflag.eq.12) then | |
write(6,*) 'Using the HOCO interface' | |
elseif (potflag.eq.-1) then | |
if(qcpack .eq. 1) then | |
write(6,*) ' Direct dynamics with Gaussian package' | |
elseif(qcpack .eq. 2) then | |
write(6,*) ' Direct dynamics with Molpro package ' | |
else | |
write(6,*) ' Direct dynamics with unsupported QC package ' | |
stop | |
endif | |
elseif (potflag.eq.-2) then | |
write(6,*) ' Direct dynamics with MOPAC-mn' | |
else | |
write(6,*) 'POTFLAG = ',potflag,' is not supported' | |
stop | |
endif | |
! Adiabatic or non-adiabatic | |
write(6,*) 'REPFLAG= ',repflag | |
if (repflag.eq.0) then | |
write(6,*) 'The adiabatic representation will be used.' | |
else | |
write(6,*) 'The diabatic representation will be used.' | |
endif | |
! Integrator information | |
write(6,'(1x,74a1)') ('-',i=1,74) | |
write(6,*) 'Integrator information' | |
write(6,'(1x,74a1)') ('-',i=1,74) | |
write(6,*) 'INTFLAG = ',intflag | |
if (intflag.eq.0) then | |
write(6,*) 'Using the Bulirsch-Stoer integrator' | |
write(6,*) 'with initial time step ',hstep0*autofs,' fs' | |
write(6,*) 'and with integrator tolerance ',eps | |
elseif (intflag.eq.1) then | |
write(6,*)'Using the 4th-order Runge-Kutta integrator' | |
write(6,*) 'with time step ',hstep0*autofs,' fs' | |
elseif (intflag.eq.2) then | |
write(6,*)'Using the simplest Verlet integrator' | |
write(6,*) 'with time step ',hstep0*autofs,' fs' | |
elseif (intflag.eq.3) then | |
write(6,*)'Using the velocity Verlet integrator' | |
write(6,*) 'with time step ',hstep0*autofs,' fs' | |
elseif (intflag.eq.4) then | |
write(6,*)'Using the Beeman integrator' | |
write(6,*) 'with time step ',hstep0*autofs,' fs' | |
elseif (intflag.eq.5) then | |
write(6,*)'Using the Liouville approach of velocity Verlet', & | |
' integrator' | |
write(6,*) 'with time step ',hstep0*autofs,' fs' | |
elseif (intflag.eq.6) then | |
write(6,*)'Using the Bulirsch-Stoer integrator with Hack''s ', & | |
'method' | |
write(6,*) 'with initial time step ',hstep0*autofs,' fs' | |
write(6,*) 'and with integrator tolerance ',eps | |
if (intflag.eq.6.and.nsurft.eq.1) then | |
write(6,*) 'BS integrator with Hack''s method is only', & | |
' meaningful for multisurface calculations' | |
write(6,*) 'Choose bulstoint in the input instead' | |
stop | |
endif | |
if (intflag.eq.6.and.methflag.eq.2) then | |
write(6,*) 'BS integrator with Hack''s method is not', & | |
' meaningful for SE calculations' | |
write(6,*) 'Choose bulstoint in the input instead' | |
stop | |
endif | |
else | |
write(6,*)'INTFLAG = ',intflag,' is not supported' | |
stop | |
endif | |
if ( (itherm.ne.0 .or. ieqtherm.ne.0) .and. iadjtemp.eq.3 .and. & | |
intflag.ge.2 .and. intflag.le.4) then | |
write(6,444) 'Nose-Hoover thermostat cant be used with simple-', & | |
', velocity- and Beeman- Verlet integrator' | |
write(6,*)'Use Liouville approach to Velocity Verlet' | |
stop | |
endif | |
! | |
! Some initial conditions related with thermostat | |
if (reactcol .or.atomdiatom) ifnoang=.false. | |
! CoM motion and angular momentum for anderson thermostat (iadjtemp=2) | |
! are not conserved. So do not zero them. | |
if (itherm.ne.0 .and. iadjtemp.eq.2) then | |
! lzerotrans = .false. | |
! ifnoang = .false. | |
! ifeqwithrot=.true. | |
if (lzerotrans) then | |
write(6,444) 'WARNING: You chose to remove CoM in Anderson ', & | |
'thermostat, which is not conserved.' | |
endif | |
if (ifnoang) then | |
write(6,444) 'WARNING: You chose to keep angular momentrum ', & | |
'in Anderson thermostat, which is not conserved.' | |
endif | |
endif | |
! Total number of freedom for the whole run | |
! Periodic running information | |
write(6,*) | |
write(6,'(1x,74a1)') ('-',i=1,74) | |
write(6,*) 'Periodic and cell information' | |
write(6,'(1x,74a1)') ('-',i=1,74) | |
write(6,*) 'Doing a ',nmol,' AG calculation' | |
if (icell.eq.0) then | |
write(6,*) 'Simulation for an isolated AG in vacuum' | |
! periodic condition | |
periodic = .false. | |
! NVT can not be used | |
if (itherm.eq.2) then | |
write(6,444) 'ERROR: Cannot run isolated cluster in vacuum', & | |
' with NVT ensemble' | |
stop | |
endif | |
else | |
if (icell.eq.1) then | |
write(6,777) 'The simulation is in a cubic cell with a = ', & | |
cell(1),' A' | |
cell(2)=cell(1) | |
cell(3)=cell(1) | |
elseif (icell.eq.2) then | |
write(6,888)'The simulation is in a cuboid cell with a b c = ', & | |
(cell(j),j=1,3),' A' | |
elseif (icell.eq.3) then | |
write(6,999) 'The simulation is in an arbitrary cell with', & | |
' a b c = ',(cell(j),j=1,3),' A' | |
write(6,888) 'and with alpha, beta, gamma = ',& | |
(cell(j),j=4,6),' Degree' | |
endif | |
! Convert the cell parameters to cell vectors, with | |
! a (cell(1)) parallel to x axis. cvec(3,3) is a vector matrix, | |
! i.e. the first column is the a vector, second b vector | |
do j=1,3 | |
cell(j) = cell(j)/autoang | |
enddo | |
if (icell.eq.1 .or. icell.eq.2) then | |
do j=4,6 | |
cell(j) = 90.0d0 | |
enddo | |
endif | |
do j=4,6 | |
if (cell(j).gt.180.d0) then | |
write(6,*) 'ERROR: Angles cannot be greater than 180 degree' | |
write(6,*) 'Angles: ',(cell(i),i=4,6) | |
stop | |
endif | |
cell(j) = pi*cell(j)/180.d0 | |
enddo | |
cvec(1,1) = cell(1) | |
cvec(2,1) = 0.0d0 | |
cvec(3,1) = 0.0d0 | |
cvec(1,2) = cell(2)*dcos(cell(6)) | |
cvec(2,2) = cell(2)*dsin(cell(6)) | |
cvec(3,2) = 0.0d0 | |
cvec(1,3) = cell(3)*dcos(cell(5)) | |
! Following equations are incorrect | |
cvec(2,3) = (cell(2)*cell(3)*dcos(cell(4))-cvec(1,2)*cvec(1,3))/cvec(2,2) | |
cvec(3,3) = dsqrt(cell(3)**2-cvec(1,3)**2-cvec(2,3)**2) | |
! Volume of the cell det(cvec) = a(bxc) | |
vol0 = detmtbt(cvec) | |
call invmtbt(cvec,invcvec) | |
vol=vol0 | |
write(6,777) 'The initial volume of the cell = ',& | |
vol0*autoang**3,' A^3' | |
endif | |
write(6,*) | |
! Random seed | |
write(6,'(1x,74a1)') ('-',i=1,74) | |
write(6,*) 'Random number generator information' | |
write(6,'(1x,74a1)') ('-',i=1,74) | |
! RMP14 | |
call seed(ranseed) | |
! if (ranseed.eq.0) then | |
!C If user not to provide ranseed, the program will determine | |
!C one automatically by calling make_sprng_seed() | |
! ranseed = make_sprng_seed() | |
! endif | |
! | |
! write(6,*) 'Random number seed is ',ranseed | |
! write(6,*) | |
! Surface information | |
write(6,'(1x,74a1)') ('-',i=1,74) | |
write(6,*) 'Electronic surfaces' | |
write(6,'(1x,74a1)') ('-',i=1,74) | |
write(6,*) 'Initial electronic suface = ',nsurf0 | |
if (nsurfi.eq.0) then | |
nsurfi=nsurf0 | |
repflgi=repflag | |
else | |
write(6,222) 'Initial condition prepared from electronic ', & | |
' surface ',nsurfi | |
if (repflgi.eq.-1) repflgi=repflag | |
endif | |
if ((nsurfi.ne.nsurf0 .or. repflgi.ne.repflgi) & | |
.and. deltate.lt.small) then | |
write(6,444) 'WARNING: Frank-Condon effect cannot fix the total', & | |
' initial energy exactly' | |
endif | |
write(6,*) 'Number of electronic surfaces = ',nsurft | |
if (methflag.eq.0) then | |
write(6,*) 'METHFLAG = 0: Single surface propagation' | |
elseif (methflag.eq.1) then | |
write(6,108) 'METHFLAG = 1: Electronically nonadiabatic',& | |
' calculation with' | |
write(6,*) 'Tully''s fewest switches method' | |
elseif (methflag.eq.2) then | |
write(6,108) 'METHFLAG = 2: Electronically nonadiabatic', & | |
' calculation with' | |
write(6,*) 'Semiclassical Ehrenfest method' | |
elseif (methflag.eq.3) then | |
write(6,108) 'METHFLAG = 3: Electronically nonadiabatic', & | |
' calculation with' | |
write(6,*) 'Self consistent decay of mixing method' | |
elseif (methflag.eq.4) then | |
write(6,108) 'METHFLAG = 4: Electronically nonadiabatic', & | |
' calculation with' | |
write(6,108) 'Coherent switching with decay of mixing method' | |
elseif (methflag.eq.5) then | |
write(6,108) 'METHFLAG = 5: Electronically nonadiabatic', & | |
' calculation with' | |
write(6,108) 'Fewest switches with time uncertainty method' | |
else | |
write(6,*) 'METHFLAG = ',methflag,' is not allowed' | |
stop | |
endif | |
! RVM Information for Stochastic Decoherence and TRAPZ | |
if (stodecoflag.eq.1) then | |
write(6,*) 'STODECOFLAG = 1: Using Stochastic Decoherence' | |
elseif (stodecoflag.lt.0.or.stodecoflag.gt.1) then | |
write(6,*) 'stodecoflag= ',stodecoflag,' is not allowed' | |
stop | |
endif | |
if (ntrapz.eq.0) then | |
write(6,108) 'Using traditional Hessian for initial normal', & | |
' mode analysis' | |
write(6,*) 'TRAPZ is not used for the dynamics' | |
elseif (ntrapz.eq.1) then | |
write(6,108) 'Using Projected Hessian for initial normal', & | |
' mode analysis' | |
write(6,*) 'TRAPZ is not used for the dynamics' | |
elseif(ntrapz.eq.2) then | |
write(6,108) 'Using traditional Hessian for initial normal', & | |
' mode analysis' | |
write(6,*) 'Using TRAPZ for the dynamics' | |
elseif(ntrapz.eq.3) then | |
write(6,108) 'Using Projected Hessian for initial normal', & | |
' mode analysis' | |
write(6,*) 'Using TRAPZ for the dynamics' | |
elseif(ntrapz.le.0.or.ntrapz.gt.3) then | |
write(6,*) 'ntrapz= ',ntrapz,' is not allowed' | |
stop | |
endif | |
! RVM Information about version of TRAPZ used | |
if (nvers.eq.0) then | |
write(6,*) 'Using general TRAPZ method' | |
elseif (nvers.eq.1) then | |
write(6,108) 'Using the mTRAPZ method' | |
elseif(nvers.eq.2) then | |
write(6,108) 'Using the mTRAPZ* method' | |
elseif(nvers.lt.0.or.nvers.gt.2) then | |
write(6,*) 'nvers= ',nvers,' is not allowed for TRAPZ' | |
stop | |
endif | |
do i=1,nsurft*2 | |
cre(i) = 0.d0 | |
cim(i) = 0.d0 | |
enddo | |
cre(nsurf0) = 1.d0 | |
write(6,*) | |
! | |
! Find out the corresponding index of the atom in the periodic table | |
! Model atoms types are added by J. Zheng May 2013 | |
nmodel = 0 | |
do i=1,nat | |
find_real = .false. | |
do j=1,111 | |
if ( symbol0(i).eq.atomsymbols(j)) then | |
indatom(i)=j | |
find_real=.true. | |
endif | |
enddo | |
if(.not.find_real) then | |
nmodel = nmodel + 1 | |
indatom(i)= nmodel | |
endif | |
enddo | |
! | |
! Count the number of atoms which are the same for different AG | |
do im=1,nmol | |
do j=1,121 | |
nattype(im,j)=0 | |
enddo | |
enddo | |
do im=1,nmol | |
do i=1,natom(im) | |
ii=indatom(iatom(im)+i-1) | |
nattype(im,ii)=nattype(im,ii)+1 | |
enddo | |
enddo | |
! | |
! Atomic group data (initx, initp, coordinates) | |
write(6,'(1x,74a1)') ('-',i=1,74) | |
write(6,*) 'Atom group (AG) specification' | |
write(6,'(1x,74a1)') ('-',i=1,74) | |
! Atom-Diatom information | |
if (atomdiatom .or. initx(1).eq.4) then | |
write(6,*) 'Doing a special atom-diatom simulation' | |
write(6,910) ' # symb','mass (amu)' | |
! atom-diatom has only one AG, so always begin with 1 | |
mmofag(im)=0.d0 | |
do i = 1, natom(1) | |
write(6,920) i,symbol0(i),mm0(i) | |
! Convert from amu to au | |
mm0(i)=mm0(i)*amutoau | |
mmofag(im)=mmofag(im)+mm0(i) | |
enddo | |
if (ademod .eq. 1) then | |
write(6,*) 'Total energy = ',escatad,' eV' | |
else | |
write(6,*) 'Collision energy = ',ecolad,' eV' | |
endif | |
write(6,*) 'Initial vib. quantum number v = ',vvad | |
write(6,*) 'Initial rot. quantum number j = ',jjad | |
write(6,*) 'Initial distance = ',rrad0 | |
if (arrad.eq.1) then | |
write(6,*) 'Initial arrangement = AB + C' | |
elseif (arrad.eq.2) then | |
write(6,*) 'Initial arrangement = BC + A' | |
elseif (arrad.eq.3) then | |
write(6,*) 'Initial arrangement = AC + B' | |
else | |
write(6,*) 'ERROR: arrad = ',arrad,' is not supported' | |
stop | |
endif | |
ecolad=ecolad/autoev | |
escatad=escatad/autoev | |
rrad0=rrad0/autoang | |
! None atom-diatom AG information | |
else | |
! start loop over AG | |
do im=1,nmol | |
write(6,'(1x,74a1)') ('-',i=1,74) | |
write(6,*) 'AG ',im | |
write(6,'(1x,74a1)') ('-',i=1,74) | |
write(6,200) 'This AG has ',natom(im),' atoms (', & | |
'atoms ',iatom(im),' to ',iatom(im)+natom(im)-1,')' | |
write(6,201) 'Initial conditions prepared using INITx = ',& | |
initx(im),' and INITp = ',initp(im) | |
! information on coordinates and initx | |
! Print out initial coordinates and save them to global storage | |
if (initx(im).eq.0) then | |
write(6,910)' # symb','mass (amu)','x (A)','y (A)','z (A)' | |
! do i = iatom(im), iatom(im)+natom(im)-1 | |
do i = 1,natom(im) | |
ii=iatom(im)+i-1 | |
write(6,920) i,symbol0(ii),mm0(ii)/amutoau, & | |
(xx0(k,ii)*autoang,k=1,3) | |
enddo | |
elseif ((initx(im).ge.1 .and. initx(im).le.3) .or. & | |
initx(im).eq.5) then | |
maxtmp=0.d0 | |
mintmp=200.d0 | |
do i=iatom(im),iatom(im)+natom(im)-1 | |
do j=i,iatom(im)+natom(im)-1 | |
maxtmp = max(maxtmp,rijco(indatom(i),indatom(j))) | |
mintmp = min(mintmp,rijco(indatom(i),indatom(j))) | |
enddo | |
enddo | |
if (initx(im).eq.1) then | |
write(6,930) 'Generate random spherical clusters', & | |
' of radius ',rran(1,im),' A' | |
! Judge if this radius is reasonable | |
radmin(im)=mintmp*dble(natom(im))**(1.d0/3.d0)/2.d0 | |
radmax(im)=maxtmp*dble(natom(im))**(1.d0/3.d0)/2.d0 | |
if (radmin(im)*autoang.gt.rran(1,im) ) then | |
write(6,108) 'WARNING: The radius given maybe too ', & | |
'small for the program to get a random structure' | |
endif | |
if (2.0d0*radmax(im)*autoang.lt.rran(1,im) ) then | |
write(6,108) 'WARNING: The radius given maybe too ', & | |
'large to get a spheric cluster' | |
endif | |
elseif (initx(im).eq.2) then | |
write(6,940) 'Generate random atoms in cubic with a,b,c ', & | |
(rran(i,im),i=1,3),' A' | |
k=int((rran(1,im)*rran(2,im)*rran(3,im))/ & | |
(pi*((mintmp*autoang/2.d0)**3.d0)*4.d0/3.d0)) | |
if (k.lt.natom(im)) then | |
write(6,108) 'WARNING: volumn of the cuboid specified', & | |
' maybe too small' | |
endif | |
elseif (initx(im).eq.3) then | |
write(6,108) 'Generate random clusters with arbitrary ', & | |
'shape using default bond threshold' | |
elseif (initx(im).eq.5) then | |
write(6,940) 'Generate random molecules in a box of: ', & | |
(rran(i,im),i=1,3),' A' | |
endif | |
do i=1,3 | |
rran(i,im) = rran(i,im)/autoang | |
enddo | |
write(6,910) ' # symb','mass (amu)' | |
! Calculate total weight of each AG | |
mmofag(im)=0.d0 | |
do i = iatom(im), iatom(im)+natom(im)-1 | |
write(6,920) i,symbol0(i),mm0(i) | |
! Convert from amu to au | |
mm0(i)=mm0(i)*amutoau | |
mmofag(im)=mmofag(im)+mm0(i) | |
enddo | |
else | |
write(6,*) 'ERROR: INITx = ',initx(im),' is not supported' | |
stop | |
endif | |
! information on initp | |
if (initp(im).eq.0) then | |
write(6,*) 'INITp = 0: Initial momenta set to zero' | |
write(6,*) | |
elseif (initp(im).eq.1) then | |
write(6,930) 'Target temperature for random thermal ', & | |
'distribution is ',temp0im(im),' K' | |
write(6,*) | |
elseif (initp(im).eq.-1) then | |
write(6,*) 'INITp =-1: Initial momenta determined by INITx' | |
write(6,*) | |
else | |
write(6,*) 'ERROR: INITp = ',initp(im),' is not supported' | |
stop | |
endif | |
if (vibsel(im).eq.0) then | |
write(6,*) 'Vibrational state determined otherwise' | |
elseif (vibsel(im).eq.1) then | |
write(6,*) 'User provide vibrational states for each AG' | |
write(6,*) 'Initial vibrational quantum numbers:' | |
! RVM | |
if(ivibtype(im).eq.1) then | |
write(6,'(1x,15f4.1/)') (qnmvib0(j,im),j=1,nvibmods(im)-1) | |
else | |
write(6,'(1x,15f4.1/)') (qnmvib0(j,im),j=1,nvibmods(im)) | |
endif | |
elseif (vibsel(im).eq.2) then | |
write(6,*) 'Vibrational state randomly selected' | |
elseif (vibsel(im).eq.3) then | |
write(6,*) 'Do frequency analysis' | |
elseif (vibsel(im).eq.4) then | |
write(6,*) 'Using the same amount of energy for each ' & | |
,'vibrational mode' | |
elseif (vibsel(im).eq.5) then | |
write(6,*) 'Using the individual amount of energy for each ' & | |
,'vibrational mode' | |
elseif (vibsel(im).eq.6) then | |
write(6,*) 'Each vibrational mode has energy as ' & | |
,' min{(0.5*h*nu_m, vibene_1} ' | |
elseif (vibsel(im).eq.7) then | |
write(6,*) 'Each vibrational mode has energy as ' & | |
, ' min{(0.5*h*nu_m, vibene_m} ' | |
else | |
write(6,*) 'ERROR: VIBSELECT = ',vibsel(im),' not supported' | |
stop | |
endif | |
if (vibsel(im).ne.0) then | |
if (ivibdist(im).eq.0) then | |
write(6,444) 'Using classical HO distribution to prepare ', & | |
'initial coordinates and momentum' | |
elseif (ivibdist(im).eq.1) then | |
write(6,444) 'Using HO distribution to prepare ', & | |
'initial coordinates and momentum' | |
elseif (ivibdist(im).eq.2) then | |
write(6,444) 'Using Wigner distribution to prepare ',& | |
'initial coordinates and momentum' | |
elseif (ivibdist(im).eq.9) then | |
write(6,444) 'Each mode using different distributions to ',& | |
'prepare initial coordinates and momentum' | |
j = nvibmods(im) | |
if(ivibtype(im).eq.1) j = nvibmods(im)-1 | |
do i = 1, j | |
if(vibdistn(i,im).lt.0) then | |
write(6,*) 'The distribution method for mode', i, & | |
' is not given. Check vibdistn keyword...' | |
endif | |
enddo | |
else | |
write(6,*) 'ERROR: VIBDIST = ',ivibdist(im),' not supported' | |
stop | |
endif | |
endif | |
if (rotsel(im)) then | |
write(6,*) 'User provide rotational state (energy)' | |
else | |
write(6,*) 'Rotational state (energy) randomly decided' | |
endif | |
if (rotst(im)) then | |
write(6,*) 'Initial rotational quantum numbers:' | |
write(6,'(1x,3i4)') (qnmrot0(j,im),j=1,nrotmods(im)) | |
endif | |
if (roteng(im)) then | |
write(6,*) 'Initial rotational energies (eV) of AG ',im | |
write(6,'(1x,3f12.5)') (eroti(j,im)*autoev,j=1,nrotmods(im)) | |
endif | |
enddo ! End of loop over AG | |
ENDIF ! End of AG section | |
! | |
! Orientation of AGs | |
write(6,'(1x,74a1)') ('-',i=1,74) | |
write(6,*) 'AG initial orientation and translation motion' | |
write(6,'(1x,74a1)') ('-',i=1,74) | |
if (nmol.gt.1) then | |
write(6,*) 'Multi AG simulation' | |
do im=1,nmol | |
write(6,*) 'For AG ',im | |
if (icomxx) then | |
write(6,940) 'Center of mass coords (x,y,z) (A) = ', & | |
(comxx(k,im),k=1,3) | |
else | |
write(6,940) 'Center of mass coords determined otherwise' | |
endif | |
if (icompp) then | |
write(6,940) 'Center of mass motion (x,y,z) (au) = ', & | |
(compp(k,im),k=1,3) | |
! Calculate translational energy | |
etrans(im)=0.d0 | |
do k=1,3 | |
etrans(im)=etrans(im) + compp(k,im)**2/(2.d0*mmofag(im)) | |
enddo | |
else | |
write(6,940) 'Center of mass motion determined otherwise' | |
endif | |
do k=1,3 | |
comxx(k,im) = comxx(k,im)/autoang | |
enddo | |
enddo | |
do im=1,nmol | |
write(6,960) 'Translational energy for AG ',im, & | |
' is ',etrans(im)*autoev,' eV' | |
enddo | |
else | |
write(6,*) 'Single AG simulation. No orientation' | |
! Single AG calculation | |
do k=1,3 | |
comxx(k,1) = 0.d0 | |
compp(k,1) = 0.d0 | |
enddo | |
endif | |
! | |
! Reaction collision information | |
if (reactcol) then | |
write(6,'(1x,74a1)') ('-',i=1,74) | |
write(6,*) 'Reaction collision information' | |
write(6,'(1x,74a1)') ('-',i=1,74) | |
if (.not.stateselect) then | |
write(6,*) 'Do an equilibrium run before collision' | |
write(6,*) 'The probability to pick a configuration is',pickthr | |
else | |
write(6,*) 'Do a state select reaction collision' | |
write(6,*) 'States specified by the user will be fixed' | |
endif | |
if (ipicktrj.ne.0) then | |
if (demin.eq.-1.d50 .and. demax.eq.1.d50) then | |
write(6,*) 'No constraint on the energy of the points picked' | |
elseif (demin.ne.-1.d50) then | |
write(6,*) 'Pick those with energy >= than ',demin,' eV' | |
demin=demin/autoev | |
elseif (demax.ne.1.d50) then | |
write(6,*) 'Pick those with energy < than ',demax,' eV' | |
demax=demax/autoev | |
endif | |
endif | |
if (transelect) then | |
write(6,*) 'User specify relative translation energy' | |
else | |
write(6,*) 'Randomly determined relative translation energy' | |
endif | |
write(6,*) 'Information on initial distance between 2 AGs' | |
if (.not.initr0col) then | |
write(6,108) 'The initial distance between 2 AGs will', & | |
' be calcualted based on covalent ', & | |
'radii of the atoms in the AG.' | |
write(6,108) 'Attention: atomic radii is just a very', & | |
' rough estimation of the size of an atom' | |
! Call a subroutine to provide r0collision here. If random cluster, only | |
! calculate for sphere cluster. It is unlikely that one would like to | |
! run rxcollision using none sphere random clusters | |
r0collision=0.d0 | |
do im=1,nmol | |
natoms=natom(im) | |
if (natoms.eq.1) then | |
radmax(im) = 2.2d0*atmradco(indatom(iatom(im)))/autoang | |
else | |
if (initx(im).eq.0) then | |
do i=1,natoms | |
ii=iatom(im)+i-1 | |
do j=1,3 | |
xxm(j,i) = xx0(j,ii) | |
enddo | |
indmm(i)=indatom(ii) | |
enddo | |
call rijmatr | |
! Find out the largest distance(bohr) in rijmatrix | |
maxtmp=0.d0 | |
do i=1,natoms | |
do j=i+1,natoms | |
maxtmp=dmax1(maxtmp,rij(i,j)) | |
if (rij(i,j).eq.maxtmp) then | |
i1=indmm(i) | |
i2=indmm(j) | |
endif | |
enddo | |
enddo | |
radmax(im)=2.2d0*(maxtmp+rijco(i1,i2))/2.d0 | |
elseif (initx(im).eq.1) then | |
! provided in printing $data out | |
radmax(im)=rran(1,im) | |
else | |
write(6,108) 'ERROR: Program will only decide ', & | |
'r0collision for INITx = 0 or 1' | |
stop | |
endif | |
endif | |
if (idebug) then | |
write(6,*) 'radmax(im)',radmax(im)*autoang | |
endif | |
r0collision=r0collision+radmax(im) | |
enddo | |
else | |
write(6,*) 'User provide initial collision distance' | |
endif | |
write(6,950) 'Initial distance R0Collision = ', & | |
r0collision*autoang,' A' | |
if (b_fix) then | |
write(6,950) 'Initial impact parameter b fixed at ', & | |
b0impact*autoang,' A' | |
else | |
write(6,*) 'Integrate over all impact parameter' | |
endif | |
if (r0collision.le.b0impact) then | |
write(6,*) 'ERROR: R0Collision shorter than b0impact ' | |
stop | |
endif | |
! endif of reaction collision | |
ENDIF | |
! | |
! Trajectory information | |
write(6,'(1x,74a1)') ('-',i=1,74) | |
write(6,*) 'Trajectory control flags' | |
write(6,'(1x,74a1)') ('-',i=1,74) | |
write(6,*) 'Running ',ntraj,' trajectories' | |
if (tflag(1).eq.0) then | |
write(6,*) 'No special options for tflag1' | |
elseif (tflag(1).eq.1) then | |
write(6,108)'TFLAG(1)= 1: Momenta set to zero at every ', & | |
'step, i.e., steepest descent minimization' | |
itherm=0 | |
elseif (tflag(1).eq.2) then | |
write(6,*) 'TFLAG(1) = 2: Temperature ramping' | |
write(6,333) 'The momentum will be ramped at step ', & | |
nrampstep,' by ' | |
write(6,202) 'a factor of RAMPFACT = ',rampfact,' and ', & | |
nramp,' times' | |
write(6,333) 'The momentum will be ramped for ', & | |
n_ramp,' steps and ' | |
write(6,333) 'followed by an equilibrium run of ', & | |
nequil,' steps each time' | |
tmp=dble(nrampstep+nramp*(n_ramp+nequil))*hstep0 | |
if (t_stime.lt.tmp) then | |
write(6,203)'Terminating time too short, it must be longer', & | |
' than ',tmp*autofs,' fs' | |
stop | |
endif | |
elseif (tflag(1).eq.3.or.tflag(1).eq.4.or.tflag(1).eq.5) then | |
if (tflag(1).eq.3) then | |
write(6,*) 'TFLAG(1) = 3: simulated heating/cooling' | |
elseif (tflag(1).eq.4) then | |
write(6,444) 'TFLAG(1) = 4: simulated heating/cooling ', & | |
'followed by additional geometry optimization using BFGS' | |
elseif (tflag(1).eq.5) then | |
write(6,204) 'TFLAG(1) = 4: simulated heating/cooling ', & | |
'do geometry optimization using BFGS at steps with ', & | |
'a frequency of ',pickthr | |
endif | |
if (tflag(1).eq.4 .or. tflag(1).eq.5) then | |
write(6,108) 'Geometry optimization will terminate ', & | |
'when the RMS of the gradient' | |
write(6,*) ' < ',t_gradmag*autoev/autoang,' eV/A' | |
write(6,108) 'and when the maximum of the gradient' | |
write(6,*) ' < ',t_gradmax*autoev/autoang,' eV/A' | |
endif | |
tmp = rampfact/(dble(n_ramp+nequil)*hstep0*autofs/1000.d0) | |
if (rampfact.gt.0.d0) then | |
write(6,*) 'The heating rate is ',tmp,' K/ps ' | |
elseif (rampfact.lt.0.d0) then | |
write(6,*) 'The cooling rate is ',tmp,' K/ps ' | |
endif | |
write(6,777) 'The time interval for the heating/cooling is ', & | |
dble(n_ramp+nequil)*hstep0*autofs,' fs ' | |
write(6,333) 'Properties are averaged over ', & | |
nequil,' steps for each heating/cooling step' | |
tmp = temp0 + dble(nramp)*rampfact | |
write(6,*) 'The ending temperature would be ',tmp,' K' | |
if (tmp.lt.0.d0) then | |
write(6,205)'NRAMP is too large, it must be smaller', & | |
' than ',-int(temp0/rampfact),' times' | |
stop | |
endif | |
tmp = dble(nrampstep+nramp*(n_ramp+nequil))*hstep0 | |
if (t_stime.lt.tmp) then | |
write(6,203)'T_STIME is too short, it must be longer', & | |
' than ',tmp*autofs,' fs' | |
stop | |
endif | |
else | |
write(6,*) 'ERROR: tflag1 = ',tflag(1),' not supported' | |
stop | |
endif | |
! Set nreinit to a very large number if do not zero CoM, CoM motion | |
! and angular momentum | |
if ((.not.lzerocom).and.(.not.lzerotrans).and.(.not.ifnoang))& | |
nreinit = 1000000000 | |
if (lzerotrans) then | |
write(6,*) 'Remove CoM motion every step' | |
lzerocom = .true. | |
endif | |
if (lzerocom) then | |
write(6,*) 'Move the CoM back to origin every step' | |
endif | |
if (nmol.eq.1 .and. ifnoang) ifreinitrot=.false. | |
if ((.not.reactcol).and.(initx(1).ne.4)) & | |
write(333,*) 'Remove overall rotational momentum every ',nreinit, ' steps' | |
if (tflag(2).eq.1) then | |
write(6,*) 'TFLAG(2) = 1: Restart trajectories' | |
write(6,*) 'Restarting trajectories: ',(trajlist(k),k=1,ntraj) | |
endif | |
if (lzerotrans) write(6,444) 'Translation momentum will be ', & | |
'removed before entering DRIVE.' | |
if (ifnoang) write(6,444) 'Overall CoM angular momentum will be ', & | |
'removed before entering DRIVE.' | |
if (ifeqwithrot) write(6,444) 'Overall CoM angular momentum is ', & | |
'kept in equilibrium run.' | |
if (ifreinitrot)write(6,444) 'Overall CoM angular momentum will ', & | |
'reset after equilibrium run.' | |
write(6,*) | |
! | |
! Termination condition | |
write(6,'(1x,74a1)') ('-',i=1,74) | |
write(6,*) 'Termination condition information' | |
write(6,'(1x,74a1)') ('-',i=1,74) | |
if (termflag.eq.0) then | |
write(6,108)'TERMFLAG = 0: Fixed number of steps per ', & | |
'trajectory' | |
elseif (termflag.eq.1) then | |
write(6,777) 'TERMFLAG = 1: Trajectories will run for ', & | |
t_stime*autofs,' fs' | |
t_nstep=1000000000 | |
elseif (termflag.eq.2) then | |
write(6,108) 'TERMFLAG = 2: Trajectories will terminate ', & | |
'when the RMS of the gradient' | |
write(6,*) ' is less than ',t_gradmag*autoev/autoang,' eV/A' | |
write(6,108) 'and when the maximum of the gradient' | |
write(6,*) ' < ',t_gradmax*autoev/autoang,' eV/A' | |
elseif (termflag.eq.3) then | |
write(6,*) 'Outcome label Bond Distance (A)' | |
if (nbondform.gt.0) then | |
write(6,108) 'TERMFLAG = 3: Bond forming termination ', & | |
'conditions' | |
do j=1,nbondform | |
write(6,900) j,tiform(j,1),tiform(j,2),trmin(j) | |
trmin(j)=trmin(j)/autoang | |
enddo | |
endif | |
if (nbondbreak.gt.0) then | |
write(6,108) 'TERMFLAG = 3: Bond breaking termination ', & | |
'conditions' | |
do j=1,nbondbreak | |
write(6,900) j,tibreak(j,1),tibreak(j,2),trmax(j) | |
trmax(j)=trmax(j)/autoang | |
enddo | |
endif | |
elseif (termflag.eq.4) then | |
write(6,108) 'TERMFLAG = 4: Monitor fragments' | |
if (agdefrag) write(6,*) 'Monitor AG fragmentation' | |
if (agmerge) then | |
write(6,*) 'Monitor AG merge' | |
write(6,777) 'Total energy less than ',determ, & | |
' eV is deemed as merge' | |
determ=determ/autoev | |
endif | |
if (attrans) write(6,*) 'Monitor atom/group transfer/exchange' | |
elseif (termflag.eq.5) then | |
write(6,108) 'TERMFLAG = 5: Monitor any bond breaking or', & | |
' forming' | |
elseif (termflag.eq.6) then | |
write(6,108) 'TERMFLAG = 6: Average on sticking time ' | |
elseif (termflag.eq.7) then | |
write(6,*) 'Monitor unimolecular fragmentation probability' | |
t_nstep=1000000000 | |
write(6,*)'Maximum simulation time is ',t_stime*autofs,' fs' | |
if (n_frags.eq.0) then | |
write(6,*) 'Number of products is unlimited' | |
elseif (n_frags.ge.2) then | |
write(6,*) 'Monitor ',n_frags,' product fragmentation' | |
else | |
write(6,*) 'ERROR: n_frags cant be 1 or negative' | |
stop | |
endif | |
if (initx(im).eq.0) then | |
do i=1,natom(1) | |
do j=1,3 | |
xxm(j,i) = xx0(j,i) | |
enddo | |
indmm(i)=indatom(i) | |
enddo | |
call rijmatr | |
call frag | |
if (nfrag.ne.1) then | |
write(6,444) 'ERROR: Monitoring fragmentation ', & | |
'all atoms in the AG must be bonded one another' | |
stop | |
endif | |
endif | |
if (.not.stateselect) then | |
write(6,*) 'Equilibrium run to provide initial conditions' | |
write(6,*) 'Probability to pick a configuration is ',pickthr | |
endif | |
if (ipicktrj.ne.0) then | |
if (demin.eq.-1.d50 .and. demax.eq.1.d50) then | |
write(6,*) 'No constraint on the energy of the points picked' | |
elseif (demin.ne.-1.d50) then | |
write(6,*) 'Pick those with energy >= than ',demin,' eV' | |
demin=demin/autoev | |
elseif (demax.ne.1.d50) then | |
write(6,*) 'Pick those with energy < than ',demax,' eV' | |
demax=demax/autoev | |
endif | |
endif | |
elseif (termflag .eq. 8) then | |
write(6,108) 'TERMFLAG = 8: Trajectories will terminate ', & | |
'when specified dihedral angles rotate' | |
else | |
write(6,*) 'TERMFLAG = ',termflag,' is not supported' | |
stop | |
endif | |
if (t_nstep.ne.1000000000) then | |
write(6,206) 'Maximum number of steps per trajectory is ', & | |
t_nstep | |
else | |
write(6,108) 'Maximum number of steps per trajectory is', & | |
' unlimited' | |
endif | |
if (nstat.gt.t_nstep) then | |
write(6,108) 'Steps used to average properties', & | |
' cant be smaller than the total number of steps' | |
stop | |
endif | |
if (nbondtype.gt.0) then | |
write(6,*) 'Default bond forming/breaking threshold changed' | |
write(6,*) 'Outcome label Bond Distance (A)' | |
do j=1,nbondtype | |
write(6,905) j,titype(j,1),titype(j,2),trtype(j)*autoang | |
enddo | |
else | |
write(6,444) 'Default bond breaking/forming threshold used:', & | |
' 2.5/1.5 times of default atomic covalent bond distance' | |
endif | |
! | |
! Output information | |
write(6,*) | |
write(6,'(1x,74a1)') ('-',i=1,74) | |
write(6,*) 'Output write to units:' | |
write(6,'(1x,74a1)') ('-',i=1,74) | |
if (outflag.eq.0) then | |
write(6,333) 'OUTFLAG= ',outflag, & | |
' : Write output to all units' | |
else | |
write(6,333) 'OUTFLAG= ',outflag,': Write output to units', & | |
' specified by user:' | |
write(6,*) (ilwrite(j),j=1,outflag) | |
endif | |
if (maxprint) write(6,*) 'Print out maximum information' | |
if (minprinticon) write(6,*) 'Minimum printout of initial', & | |
' conditions' | |
if (minprinttrapz) write(6,*) 'Skipping intermediate info', & | |
' in TRAPZ' | |
if (idebug) write(6,108) 'Print out debug information. ',& | |
'WARNING: Very lengthy' | |
write(6,*) 'Print general information every ',nprint,' steps' | |
! | |
! Some values control the program | |
ii=mnmol+1 | |
mmofag(ii)=0.d0 | |
nvibmods(ii)=0 | |
nrotmods(ii)=0 | |
do im=1,nmol | |
if (natom(im).eq.1) then | |
nvibmods(im)=0 | |
nrotmods(im)=0 | |
elseif (natom(im).eq.2) then | |
nvibmods(im)=1 | |
nrotmods(im)=1 | |
else | |
if (nvibmods(im).eq.0 ) nvibmods(im)=3*natom(im)-6 | |
if (nrotmods(im).eq.0 ) nrotmods(im)=3 | |
endif | |
mmofag(ii)=mmofag(ii)+mmofag(im) | |
nvibmods(ii)=nvibmods(ii)+nvibmods(im) | |
nrotmods(ii)=nrotmods(ii)+nrotmods(im) | |
enddo | |
! | |
! | |
! Ensemble information | |
! For reactive collision run, use nve ensemble instead | |
if (itherm.ne.0) then | |
if (reactcol) & | |
write(6,444)'WARNING!!: using NVT or NPT ensemble for reactive', & | |
' collision run' | |
if (initx(1).eq.4) & | |
write(6,444) 'WARNING!!: using NVT or NPT ensemble for atom-', & | |
'diatom run' | |
endif | |
if (itherm.eq.0) then | |
write(6,*) 'NVE ensemble' | |
elseif (itherm.eq.1) then | |
write(6,*) 'NVT ensemble' | |
else | |
write(6,*) 'NPT ensemble' | |
write(6,*) 'Pressure is: ',p0*autoatm,' atm' | |
if (icell.eq.1) then | |
tmp=(dble(nat)*kb*temp0/p0)**(1.d0/3.d0) | |
write(6,*) 'Desired cell should have a box of ',tmp*autoang | |
endif | |
endif | |
if (itherm.ne.0 .or. ieqtherm.ne.0) then | |
tmp=(10.d0/autoang)**2*dsqrt(8.d0*pi*(mmofag(ii)+39.948d0*amutoau) & | |
/(mmofag(ii)*39.948d0*amutoau*kb*temp0))*p0 | |
write(6,*) 'Collision frequency is ',tmp/autofs,' 1/fs' | |
if (taut.ne.0.d0) then | |
taut = taut/autofs | |
else | |
! taut = 1.d0/tmp | |
taut = hstep0/0.0025d0 | |
endif | |
if (taup.ne.0.d0) then | |
taup = taup/(autofs*autoatm) | |
else | |
taup = hstep0*p0/0.0025d0 | |
endif | |
if (vfreq.ne.0.d0) then | |
vfreq = vfreq*autofs | |
else | |
! vfreq = 0.1d0/hstep0 | |
vfreq = tmp | |
endif | |
if (itempzpe) then | |
write(6,*) 'You ve chosen to count ZPE into temperature' | |
write(6,444)'The real average temperature should belower than', & | |
' the calculated temperature by a constant value' | |
endif | |
if (iadjtemp.eq.0) then | |
write(6,203) 'Berendsen thermostat. Coupling parameter tau ', & | |
'is : ',taut*autofs,' fs' | |
elseif (iadjtemp.eq.1) then | |
write(6,444) 'Simplet temperature control scheme: Scaling ',& | |
'momentum by square root of T0/T' | |
elseif (iadjtemp.eq.2) then | |
write(6,777) 'Andersen thermostat. Collision frequency is ',& | |
vfreq/autofs,' 1/fs' | |
elseif (iadjtemp.eq.3) then | |
write(6,203) 'Nose-Hoover thermostat. system vibration ', & | |
'frequency is: ',sysfreq,' 1/fs' | |
! Convert to vibration period ( au ) | |
sysfreq = 1.d0/(sysfreq*autofs) | |
! write(6,*) 'Nose-Hoover thermostat. Q2 used is ',nh(1,2),& | |
! ' eV fs**2' | |
! nh(1,1)=nh(1,1)/(autoev*autofs**2) | |
! nh(1,2)=nh(1,2)/(autoev*autofs**2) | |
else | |
write(6,444) 'ERROR: Other thermostat have not been ', & | |
'implemented yet' | |
stop | |
endif | |
if (itherm.eq.2) then | |
if (iadjpress.eq.0) then | |
write(6,203) 'Berendsen barostat. Coupling parameter tau ', & | |
'is : ',taup*autofs*autoatm,' fs atm' | |
else | |
write(6,444) 'ERROR: Other barostat have not been ', & | |
'implemented yet' | |
stop | |
endif | |
endif | |
endif | |
write(6,*) | |
! All write formats come here | |
900 format(1x,i5,15x,i2,'-',i2,f15.5) | |
905 format(1x,i5,15x,a2,'-',a2,f15.5) | |
910 format(1x,a10,4a12) | |
920 format(1x,i5,a5,4f12.5) | |
930 format(1x,a,a,f12.5,1x,a) | |
940 format(1x,a,3f12.5,a) | |
950 format(1x,a,f12.5,a) | |
960 format(1x,a,i4,a,f12.5,a) | |
108 format(1x,10a) | |
111 format(1x,a,i10,2a,i10) | |
222 format(1x,2a,i10) | |
333 format(1x,a,i10,a) | |
444 format(1x,2a) | |
555 format(1x,3a) | |
666 format(1x,a,e16.8,a,e16.8,a) | |
777 format(1x,a,e16.8,a) | |
888 format(1x,a,3e16.8,a) | |
999 format(1x,2a,3e16.8,a) | |
200 format(1x,a,i10,2a,i10,a,i10) | |
201 format(1x,a,i10,a,i10) | |
202 format(1x,a,e16.8,a,i15,a) | |
203 format(1x,2a,e16.8,a) | |
204 format(1x,3a,e16.8) | |
205 format(1x,2a,i10,a) | |
206 format(1x,a,i15) | |
END subroutine readin | |
! | |
function lowercase (string) | |
! | |
! Function which takes a string of 200 characters and converts the | |
! upper case letters in the string to lower case letters | |
! This function is taken from POLYRATE with a slight modification for | |
! character length. | |
! | |
character*200 :: string, lowercase | |
character*1 :: xlett | |
! | |
do 10 i = 1, 200 | |
xlett = string(i:i) | |
itry = ichar (xlett) | |
if (xlett .ge. 'A' .and. xlett .le. 'Z') then | |
itry = itry + 32 | |
string (i:i) = char (itry) | |
endif | |
10 continue | |
! | |
lowercase = string | |
end function lowercase |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment