module mod_memory

  use global
  contains

    subroutine memory
      implicit none
      integer :: totalchange,i
      integer :: nummol,numat
      integer :: alloc
      
      !---lets perform some initial allocation
       allocate(ff(np))
     
      allocate(position(np))
      allocate(q(np),qs(np))
      allocate(v(np),vs(np))
      allocate(drx(np),dry(np),drz(np))
      allocate(ps(np))
      allocate(specbond(12,np),specbond_ss(12,np))
      allocate(num1bond(np),num2bond(np),num3bond(np))
      allocate(num1bondss(np),num2bondss(np),num3bondss(np))
      allocate(tt(np))
      allocate(ttb(np))
      allocate(mol(2,np))
      allocate(molsort(2,np))
      allocate(pdp(np))
      allocate(ffdp(np))
      allocate(qdp(np))


      nummol = numMolArray(1)
      numat  = numMolAtom(1)
      densvlalloc = 12*nummol
      allocate(com(nummol))
      allocate(scom(nummol))
      allocate(mttb(numMolArray(1)))
      allocate(pbcshift(3,nummol))
      allocate(xyzf(3,nummol))
      allocate(pruned(numatompertemp*nummol))
      allocate(denstrack(nummol))
      allocate(minrmsd(nummol))
      allocate(belongsto(nummol))
      allocate(densvl(12*nummol))
      allocate(densnn(nummol))
      allocate(ptta(nummol*numatns))
      allocate(clusterhisto(300))


      delta = 0.1
      leftend = -10; rightend = 10
      totalchange = rightend-leftend
      change = int(real(totalchange)/delta)
      allocate(vhisto(change))
      vhisto(:) = 0


      !---allocate clustering neighbor arrays
      mol_alloc    = numMolArray(1)
      xyz_alloc    = mol_alloc*numatompertemp
      xyzcom_alloc = mol_alloc
      allocate( mvl(mol_alloc*numMolArray(1)   ) )
      allocate( shift(mol_alloc*numMolArray(1)) )
      allocate( mnum( numMolArray(1)) )
      allocate( xyz(3, xyz_alloc))
      allocate( xyzcom(3, xyzcom_alloc))
      allocate( xyzcom2match(2,xyzcom_alloc))
      allocate( sortcom(xyzcom_alloc))
      allocate( mll(numMolArray(1)))
      allocate( mHOC(0:mncellT-1))
      allocate( mstart(0:mncellT-1))
      allocate( mendposit(0:mncellT-1))
      allocate( mcnum(0:26*mncellT))



      !---allocate verlet lists 
      if(vlist_flag.ne.0)then
         allocate(ll(np))
         allocate(HOC(0:ncellT-1))
         allocate(start(0:ncellT-1))
         allocate(endposit(0:ncellT-1))


         if(newton3rd_flag.eq.1)then
            allocate(cnum(0:13*ncellT))
         elseif(newton3rd_flag.eq.0)then
            allocate(cnum(0:26*ncellT))
         endif
         !allocate(vlist(neigh_alloc,np))
         !allocate(numneigh(np))
         allocate(nnfirst(np),nnlast(np))
         allocate(nlist(1000*np))
      endif


    end subroutine memory
    
    
    
    
    
    subroutine moltype_memory
      implicit none
      integer :: i,j
      allocate(FC(numMolType))
      allocate(numMolArray(numMolType))
      allocate(numMolAtom(numMolType))
      allocate(Mol2NumBonds(numMolType))
      allocate(Mol2SpecTotal(numMolType))
  
      
    end subroutine moltype_memory


    subroutine moltype_datatype_memory(i)
      integer :: i

      allocate(FC(i)%coords(numMolAtom(i)))
      allocate(Mol2NumBonds(i)%numbonds(4,numMolAtom(i)))
      allocate(Mol2specTotal(i)%specbond(16,numMolAtom(i)))

    end subroutine moltype_datatype_memory

    
    subroutine atomtype_memory
      implicit none
      !---allocate arrays that are atom type look ups
      allocate(eps(numAtomType),sig(numAtomType),qtype(numAtomType))
      allocate(ltype2ftype(numAtomType))
      allocate(type1(numAtomType*numAtomType))
      allocate(type2(numAtomType*numAtomType))
      allocate(mass(numAtomType))
      allocate(type2string(numAtomType))
      allocate(lj1(numAtomType*numAtomType))
      allocate(lj2(numAtomType*numAtomType))
      allocate(lj3(numAtomType*numAtomType))
      allocate(lj4(numAtomType*numAtomType))
      allocate(lj1dp(numAtomType*numAtomType))
      allocate(lj2dp(numAtomType*numAtomType))
      allocate(lj3dp(numAtomType*numAtomType))
      allocate(lj4dp(numAtomType*numAtomType))

      allocate(lj14_1(numAtomType,numAtomType))
      allocate(lj14_2(numAtomType,numAtomType))
      allocate(lj14_3(numAtomType,numAtomType))
      allocate(lj14_4(numAtomType,numAtomType))
      
    end subroutine atomtype_memory
    
    
    subroutine bondtype_memory
      implicit none
      
      allocate(bondcoeff(2,numbondtype))
      allocate(Bond2atypes(numbondtype))
      
    end subroutine bondtype_memory
    
    
    subroutine angletype_memory
      implicit none
      
      allocate(anglecoeff(4,numangletype))
      allocate(angle2atypes(numangletype))
    end subroutine angletype_memory
    
    
    subroutine dihedtype_memory
      implicit none
      allocate(dihedcoeff(5,numdihedtype))
    end subroutine dihedtype_memory

    subroutine improdihedtype_memory
      implicit none
      allocate(improcoeff(2,numimprotype))
    end subroutine improdihedtype_memory



    subroutine totalbond_memory
      implicit none
      allocate(bondlist(3,numbond))
    end subroutine totalbond_memory


    subroutine totalangle_memory
      implicit none
      allocate(anglelist(4,numangle))
    end subroutine totalangle_memory

    subroutine totaldihed_memory
      implicit none
      allocate(dihedlist(5,numdihed))
    end subroutine totaldihed_memory


    subroutine improdihed_memory
      implicit none
      allocate(improlist(5,numimpro))
    end subroutine improdihed_memory
  end module mod_memory
  
