lammps/tools/chain.f

322 lines
8.1 KiB
Fortran

c Create LAMMPS data file for collection of
c polymer bead-spring chains of various lengths and bead sizes
c Syntax: chain < def.chain > data.file
c def.chain is input file that specifies the chains
c data.file is output file that will be input for LAMMPS
c includes image flags in data file so chains can be unraveled later
program chain
integer swaptype
integer, allocatable :: nchain(:),nmonomer(:)
integer, allocatable :: ntype(:),nbondtype(:)
integer, allocatable :: type(:),molecule(:)
integer, allocatable :: imagex(:),imagey(:),imagez(:)
real*8, allocatable :: x(:),y(:),z(:)
real*8, allocatable :: bondlength(:),restrict(:)
common xprd,yprd,zprd,xboundlo,xboundhi,
$ yboundlo,yboundhi,zboundlo,zboundhi
real*8 random
900 format(a)
901 format(2f10.6,a)
902 format(i3,f5.1)
903 format(i10,i8,i8,3f10.4,3i4)
904 format(i6,i3,2i6)
c read chain definitions
read (5,*)
read (5,*)
read (5,*) rhostar
read (5,*) iseed
read (5,*) nsets
read (5,*) swaptype
allocate(nchain(nsets))
allocate(nmonomer(nsets))
allocate(ntype(nsets))
allocate(nbondtype(nsets))
allocate(bondlength(nsets))
allocate(restrict(nsets))
do iset = 1,nsets
read (5,*)
read (5,*) nchain(iset)
read (5,*) nmonomer(iset)
read (5,*) ntype(iset)
read (5,*) nbondtype(iset)
read (5,*) bondlength(iset)
read (5,*) restrict(iset)
enddo
c natoms = total # of monomers
natoms = 0
do iset = 1,nsets
natoms = natoms + nchain(iset)*nmonomer(iset)
enddo
allocate(x(natoms))
allocate(y(natoms))
allocate(z(natoms))
allocate(type(natoms))
allocate(molecule(natoms))
allocate(imagex(natoms))
allocate(imagey(natoms))
allocate(imagez(natoms))
c setup box size (sigma = 1.0)
volume = natoms/rhostar
xprd = volume**(1.0/3.0)
yprd = xprd
zprd = xprd
xboundlo = -xprd/2.0
xboundhi = -xboundlo
yboundlo = xboundlo
yboundhi = xboundhi
zboundlo = xboundlo
zboundhi = xboundhi
c generate random chains
c loop over sets and chains in each set
n = 0
nmolecule = 0
do iset = 1,nsets
do ichain = 1,nchain(iset)
nmolecule = nmolecule + 1
c random starting point for the chain in the box
x1 = 0.0
y1 = 0.0
z1 = 0.0
x2 = xboundlo + random(iseed)*xprd
y2 = yboundlo + random(iseed)*yprd
z2 = zboundlo + random(iseed)*zprd
c store 1st monomer of chain
c 1st monomer is always in original box (image = 0)
call pbc(x2,y2,z2)
n = n + 1
x(n) = x2
y(n) = y2
z(n) = z2
type(n) = ntype(iset)
imagex(n) = 0
imagey(n) = 0
imagez(n) = 0
if (swaptype == 0) then
molecule(n) = nmolecule
else
molecule(n) = 1
endif
c generate rest of monomers in this chain
do imonomer = 2,nmonomer(iset)
x0 = x1
y0 = y1
z0 = z1
x1 = x2
y1 = y2
z1 = z2
c random point inside sphere of unit radius
10 xinner = 2.0*random(iseed) - 1.0
yinner = 2.0*random(iseed) - 1.0
zinner = 2.0*random(iseed) - 1.0
rsq = xinner*xinner + yinner*yinner + zinner*zinner
if (rsq > 1.0) goto 10
c project point to surface of sphere of unit radius
r = sqrt(rsq)
xsurf = xinner/r
ysurf = yinner/r
zsurf = zinner/r
c create new point by scaling unit offsets by bondlength (sigma = 1.0)
x2 = x1 + xsurf*bondlength(iset)
y2 = y1 + ysurf*bondlength(iset)
z2 = z1 + zsurf*bondlength(iset)
c check that new point meets restriction requirement
c only for 3rd monomer and beyond
dx = x2 - x0
dy = y2 - y0
dz = z2 - z0
r = sqrt(dx*dx + dy*dy + dz*dz)
if (imonomer > 2 .and. r <= restrict(iset)) goto 10
c store new point
c if delta to previous bead is large, then increment/decrement image flag
call pbc(x2,y2,z2)
n = n + 1
x(n) = x2
y(n) = y2
z(n) = z2
type(n) = ntype(iset)
if (abs(x(n)-x(n-1)) < 2.0*bondlength(iset)) then
imagex(n) = imagex(n-1)
else if (x(n) - x(n-1) < 0.0) then
imagex(n) = imagex(n-1) + 1
else if (x(n) - x(n-1) > 0.0) then
imagex(n) = imagex(n-1) - 1
endif
if (abs(y(n)-y(n-1)) < 2.0*bondlength(iset)) then
imagey(n) = imagey(n-1)
else if (y(n) - y(n-1) < 0.0) then
imagey(n) = imagey(n-1) + 1
else if (y(n) - y(n-1) > 0.0) then
imagey(n) = imagey(n-1) - 1
endif
if (abs(z(n)-z(n-1)) < 2.0*bondlength(iset)) then
imagez(n) = imagez(n-1)
else if (z(n) - z(n-1) < 0.0) then
imagez(n) = imagez(n-1) + 1
else if (z(n) - z(n-1) > 0.0) then
imagez(n) = imagez(n-1) - 1
endif
if (swaptype == 0) then
molecule(n) = nmolecule
else if (swaptype == 1) then
molecule(n) = imonomer
else if (swaptype == 2) then
if (imonomer <= nmonomer(iset)/2) then
molecule(n) = imonomer
else
molecule(n) = nmonomer(iset)+1-imonomer
endif
endif
enddo
enddo
enddo
c compute quantities needed for LAMMPS file
nbonds = 0
ntypes = 0
nbondtypes = 0
do iset = 1,nsets
nbonds = nbonds + nchain(iset)*(nmonomer(iset)-1)
if (ntype(iset) > ntypes) ntypes = ntype(iset)
if (nbondtype(iset) > nbondtypes)
$ nbondtypes = nbondtype(iset)
enddo
c write out LAMMPS file
write (6,900) 'LAMMPS FENE chain data file'
write (6,*)
write (6,*) natoms,' atoms'
write (6,*) nbonds,' bonds'
write (6,*) 0,' angles'
write (6,*) 0,' dihedrals'
write (6,*) 0,' impropers'
write (6,*)
write (6,*) ntypes,' atom types'
write (6,*) nbondtypes,' bond types'
write (6,*) 0,' angle types'
write (6,*) 0,' dihedral types'
write (6,*) 0,' improper types'
write (6,*)
write (6,901) xboundlo,xboundhi,' xlo xhi'
write (6,901) yboundlo,yboundhi,' ylo yhi'
write (6,901) zboundlo,zboundhi,' zlo zhi'
write (6,*)
write (6,900) 'Masses'
write (6,*)
do i = 1,ntypes
write (6,902) i,1.0
enddo
write (6,*)
write (6,900) 'Atoms'
write (6,*)
do i = 1,natoms
write (6,903) i,molecule(i),type(i),x(i),y(i),z(i),
$ imagex(i),imagey(i),imagez(i)
enddo
if (nbonds > 0) then
write (6,*)
write (6,900) 'Bonds'
write (6,*)
n = 0
m = 0
do iset = 1,nsets
do ichain = 1,nchain(iset)
do imonomer = 1,nmonomer(iset)
n = n + 1
if (imonomer /= nmonomer(iset)) then
m = m + 1
write (6,904) m,nbondtype(iset),n,n+1
endif
enddo
enddo
enddo
endif
end
c ************
c Subroutines
c ************
c periodic boundary conditions - map atom back into periodic box
subroutine pbc(x,y,z)
common xprd,yprd,zprd,xboundlo,xboundhi,
$ yboundlo,yboundhi,zboundlo,zboundhi
if (x < xboundlo) x = x + xprd
if (x >= xboundhi) x = x - xprd
if (y < yboundlo) y = y + yprd
if (y >= yboundhi) y = y - yprd
if (z < zboundlo) z = z + zprd
if (z >= zboundhi) z = z - zprd
return
end
c RNG from Numerical Recipes
real*8 function random(iseed)
real*8 aa,mm,sseed
parameter (aa=16807.0D0,mm=2147483647.0D0)
sseed = iseed
sseed = mod(aa*sseed,mm)
random = sseed/mm
iseed = sseed
return
end