예제 #1
0
def pdbWrite(paths, fileName, name, value):

    if os.path.isfile(my.configFile(paths[name], fileName + '.pdb')):

        print("################################################################\n" \
              + "Configuration files already exist in:\n" + my.config(paths[name]) + ".\n" \
              + "################################################################\n")

        return

    print("################################################################\n" \
          + "Writing configuration file in:\n" + my.config(paths[name]) + ".\n" \
          + "################################################################\n")

    if not os.path.exists(my.config(paths[name])):
        os.makedirs(my.config(paths[name]))

    # Opening a pipe to VMD in the shell
    logFile = open(my.config(paths[name]) + fileName + ".log", "w")
    VMDin=subprocess.Popen(["vmd", "-dispdev", "none"], stdin=subprocess.PIPE, \
                           stdout=logFile)

    CNTtools = "package require CNTtools 1.0\n"

    tclName = "NT" + name + " " + my.quoted(my.config(paths['solvate']) + fileName) + " " \
        + my.quoted(my.config(paths[name]) + fileName) + " " + str(value) + "\n"

    VMDin.stdin.write(CNTtools)
    VMDin.stdin.write(tclName)
    VMDin.stdin.flush()
    VMDin.stdin.close
    VMDin.communicate()
예제 #2
0
def pdbWrite(paths, fileName, name, value):
    
    if os.path.isfile(my.configFile(paths[name], fileName + '.pdb')):
        
        print("################################################################\n" \
              + "Configuration files already exist in:\n" + my.config(paths[name]) + ".\n" \
              + "################################################################\n")
              
        return

    print("################################################################\n" \
          + "Writing configuration file in:\n" + my.config(paths[name]) + ".\n" \
          + "################################################################\n")
    
    
    if not os.path.exists(my.config(paths[name])):
        os.makedirs(my.config(paths[name]))

    # Opening a pipe to VMD in the shell
    logFile = open(my.config(paths[name]) + fileName + ".log", "w")
    VMDin=subprocess.Popen(["vmd", "-dispdev", "none"], stdin=subprocess.PIPE, \
                           stdout=logFile)

    CNTtools = "package require CNTtools 1.0\n"

    tclName = "NT" + name + " " + my.quoted(my.config(paths['solvate']) + fileName) + " " \
        + my.quoted(my.config(paths[name]) + fileName) + " " + str(value) + "\n"

    VMDin.stdin.write(CNTtools)
    VMDin.stdin.write(tclName)
    VMDin.stdin.flush()
    VMDin.stdin.close
    VMDin.communicate()
예제 #3
0
def makeConfigFiles(paths, pD):
    """ makeConfigFiles makes all the pdb and psf files necessary for the current
    simulation. It makes heavy use of the pdbWrite procedure in myutil.py. It
    does this by constructing a list of commands to be fed to VMD for each of 
    pdb and/or psf files that need to be created."""

    # This is the base name for all the various pdb and psf files we will generate.

    fileName = pD['Config File Name']

    # Create the desired nanotube. The files will be stored in the 'Config Files' folder
    # in the folder pointed to by paths['L'].

    package = "package require CNTtools 1.0\n"
    commands = [ "genNT " \
                + my.quoted(my.configFile(paths['L'], fileName)) + " " \
                + str(pD['L']/10) + " " + str(pD['n']) + " " + str(pD['m']) + "\n" ]
    commands.append("centerNT " +
                    my.quoted(my.configFile(paths['L'], fileName)))

    my.pdbWrite(paths['L'], fileName, package, commands)

    # Join the nanotube to the polymer in single pdb and psf files. The files will be
    # stored in the 'Config Files' folder in the folder pointed to by paths['polymer'].

    package = "package require CNTPoly 1.0\n"
    commands = [ "joinMolecules " \
                + my.quoted(my.configFile(paths['L'], fileName)) + " " \
                + my.quoted(my.configFile(paths['L'], fileName)) + " " \
                + my.quoted(paths['pdb'] + pD['Polymer PSF']) + " " \
                + my.quoted(paths['pdb'] + pD['Polymer PDB']) + " " \
                + my.quoted(my.configFile(paths['polymer'], fileName)) + "\n" ]

    my.pdbWrite(paths['polymer'], fileName, package, commands)

    # Write out the pdb file with the restraint information for the nanotube. The
    # resulting pdb file will be written in the folder pointed to by paths['restraint'].

    package = "package require CNTtools 1.0\n"
    commands = [ "NTrestraint " \
                + my.quoted(my.configFile(paths['polymer'], fileName)) + " " \
                + my.quoted(my.configFile(paths['restraint'], fileName)) + " " \
                + str(pD['Restraint']) + "\n" ]

    my.pdbWrite(paths['restraint'], pD['Config File Name'], package, commands)
예제 #4
0
def makeConfigFiles(paths, pD):
    """ makeConfigFiles makes all the pdb and psf files necessary for the current
    simulation. It makes heavy use of the pdbWrite procedure in myutil.py. It
    does this by constructing a list of commands to be fed to VMD for each of 
    pdb and/or psf files that need to be created."""
    
    # This is the base name for all the various pdb and psf files we will generate.
    
    fileName = pD['Config File Name']

    # Create the desired nanotube. The files will be stored in the 'Config Files' folder
    # in the folder pointed to by paths['L'].
    
    package = "package require CNTtools 1.0\n"
    commands = [ "genNT " \
                + my.quoted(my.configFile(paths['L'], fileName)) + " " \
                + str(pD['L']/10) + " " + str(pD['n']) + " " + str(pD['m']) + "\n" ]
    commands.append("centerNT " + my.quoted(my.configFile(paths['L'], fileName)))
   
    my.pdbWrite(paths['L'], fileName, package, commands)
    
    # Join the nanotube to the polymer in single pdb and psf files. The files will be
    # stored in the 'Config Files' folder in the folder pointed to by paths['polymer'].
    
    package = "package require CNTPoly 1.0\n"
    commands = [ "joinMolecules " \
                + my.quoted(my.configFile(paths['L'], fileName)) + " " \
                + my.quoted(my.configFile(paths['L'], fileName)) + " " \
                + my.quoted(paths['pdb'] + pD['Polymer PSF']) + " " \
                + my.quoted(paths['pdb'] + pD['Polymer PDB']) + " " \
                + my.quoted(my.configFile(paths['polymer'], fileName)) + "\n" ]
    
    my.pdbWrite(paths['polymer'], fileName, package, commands)
    
    # Write out the pdb file with the restraint information for the nanotube. The
    # resulting pdb file will be written in the folder pointed to by paths['restraint'].
    
    package = "package require CNTtools 1.0\n"
    commands = [ "NTrestraint " \
                + my.quoted(my.configFile(paths['polymer'], fileName)) + " " \
                + my.quoted(my.configFile(paths['restraint'], fileName)) + " " \
                + str(pD['Restraint']) + "\n" ]
    
    my.pdbWrite(paths['restraint'], pD['Config File Name'], package, commands)
예제 #5
0
def waterWrite(paths, fileName, N0, S):
    """ waterWrite adds N0 + S water molecules to the inside of the nanotube,
        then write out new psf and pdb files for the nanotube. """

    if not my.needConfigFiles(paths['solvate'], fileName):
        return
    
    # Opens input nanotube psf and pdb files, and reads all the lines of each file into lists

    with open(my.configFile(paths['pbc'], fileName + '.psf')) as psfFile:
        psfLines = psfFile.readlines()
    with open(my.configFile(paths['pbc'], fileName + '.pdb')) as pdbFile:
        pdbLines = pdbFile.readlines()

    # Grabs the lengths of each of the lists

    lenPsf = len(psfLines)
    lenPdb = len(pdbLines)

    # String formats for the PSF and PDB file writing
    # PDB

    dampingCoeff = 0.00
    oxygen = "ATOM{0:>7}  OH2 TIP3 {1:4.0f}       0.000   0.000{2:>8.3f}  0.00  0.00      WTR  O\n"
    hydro1 = "ATOM{0:>7}  H1  TIP3 {1:4.0f}       0.000   0.766{2:>8.3f}  0.00  0.00      WTR  H\n"
    hydro2 = "ATOM{0:>7}  H2  TIP3 {1:4.0f}       0.000  -0.766{2:>8.3f}  0.00  0.00      WTR  H\n"

    # Psf
    
    opsf  = "   {0:>5} WTR  {1:<4} TIP3 OH2  OT    -0.834000       15.9994           0\n"
    h1psf = "   {0:>5} WTR  {1:<4} TIP3 H1   HT     0.417000        1.0080           0\n"
    h2psf = "   {0:>5} WTR  {1:<4} TIP3 H2   HT     0.417000        1.0080           0\n"

    # String format for the bonds and angles in the psf file

    sBondFormat  = " {0: >8}{1: >8}{2: >8}{3: >8}{4: >8}{5: >8}{6: >8}{7: >8}\n"
    sAngleFormat = " {0: >8}{1: >8}{2: >8}{3: >8}{4: >8}{5: >8}{6: >8}{7: >8}{8: >8}\n"

    # Initializing lists used below

    atoms = []
    bonds = []
    angles = []
    preAtoms = []    
    postAngles = []

    intBonds = []
    bondsFinal = []
    intAngles = []
    anglesFinal = []

    # Finds the original number of atoms in the Pdb file

    nAtoms = lenPdb-2

    # Calculates the new number of atoms after solvating

    newAtoms = nAtoms + (3*(N0+S)) 

    # Calculates the new number of bonds and angles after solvating

    newBonds = int(nAtoms*(3./2)) + 2*(N0+S)
    newAngles = nAtoms*3 + (N0+S)

    # Iterates through all of the lines of the input Psf file, and records the
    # index of the lines that contain the string !NATOM, !NBOND, and !NTHETA,
    # as well as changes the line to update the new number of each

    for i in range(0, lenPsf):
        if "!NATOM" in psfLines[i]:
            psfLines[i] = "     {:3d} !NATOM\n".format( newAtoms )
            atomIndex = i
        elif "!NBOND" in psfLines[i]:
            psfLines[i] = "     {:3d} !NBOND: bonds\n".format( newBonds )
            bondIndex = i
        elif "!NTHETA" in psfLines[i]:
            psfLines[i] = "     {:3d} !NTHETA: angles\n".format( newAngles )
            angleIndex = i

    # Stores all of the original text lines that come before the atom section into a list

    for i in range(0, atomIndex):
        preAtoms.append(psfLines[i])

    # Stores the atoms into a list

    count = 1
    while psfLines[atomIndex+count].strip():
        atoms.append( psfLines[atomIndex+count] )
        count+=1

    # Stores the bonds into a list

    count = 1
    while psfLines[bondIndex+count].strip():
        bonds.append( psfLines[bondIndex+count] )
        count+=1

    # Stores the angles into a list

    count = 1
    while psfLines[angleIndex+count].strip():
        angles.append( psfLines[angleIndex+count] )
        count+=1

    # Stores all the text lines after the angles into a list

    for i in range(angleIndex+count, lenPsf):
        postAngles.append(psfLines[i])

    # Takes the bonds and angles in the original file and splits each line into individual numbers

    for bond in bonds:
        intBonds.append( bond.strip("\n").split() )
    for angle in angles:
        intAngles.append( angle.strip("\n").split() )

    # Compresses the list of lists into a single list of all of the angles and bonds in the original file

    intBonds = list(chain.from_iterable(intBonds))
    intAngles = list(chain.from_iterable(intAngles))    

    # Adds the new atoms to the original list of atoms

    for i in range(nAtoms+1, (3*(N0+S)) + nAtoms+1, 3):

        atoms.append(opsf.format(i, int((i-nAtoms)/3)+2))
        atoms.append(h1psf.format(i+1, int((i-nAtoms)/3)+2))
        atoms.append(h2psf.format(i+2, int((i-nAtoms)/3)+2))

        intAngles.append(str(i+1))
        intAngles.append(str(i))
        intAngles.append(str(i+2))

        intBonds.append(str(i))
        intBonds.append(str(i+1))
        intBonds.append(str(i))
        intBonds.append(str(i+2))

    # Formats the list of bonds into the psf format with 8 columns

    for i in range(0,len(intBonds),8):

        try:
            bondsFinal.append( sBondFormat.format(intBonds[i], intBonds[i+1],
                intBonds[i+2], intBonds[i+3], intBonds[i+4], intBonds[i+5],
                intBonds[i+6], intBonds[i+7]) )

        except:
            diff = len(intBonds) - i
            tempStr = ""
            for j in range(i, i+diff):
                tempStr = tempStr + "{:>8}".format(intBonds[j])

            bondsFinal.append( " " + tempStr + "\n" )

    # Formates the list of angles into the psf format with 9 columns

    for i in range(0, len(intAngles), 9):

        try:
            anglesFinal.append( sAngleFormat.format(intAngles[i], intAngles[i+1],
                intAngles[i+2], intAngles[i+3], intAngles[i+4], intAngles[i+5],
                intAngles[i+6], intAngles[i+7], intAngles[i+8]) )
    
        except:
            diff = len(intAngles) - i
            tempStr = ""
            for j in range(i, i+diff):
                tempStr = tempStr + "{:>8}".format(intAngles[j])

            anglesFinal.append( " " + tempStr + "\n" )

    oxZ = waterZ(N0, S)

    for i in range(0, N0+S):

        hyZ = oxZ[i] + 0.570
        if i == 0:
            pdbLines[lenPdb-1] = oxygen.format(nAtoms+1, 2, oxZ[i])
            pdbLines.append( hydro1.format(nAtoms+2, 2, hyZ) )
            pdbLines.append( hydro2.format(nAtoms+3, 2, hyZ) )
        else:
            pdbLines.append( oxygen.format(nAtoms + 3*i+1, i+2, oxZ[i]) )
            pdbLines.append( hydro1.format(nAtoms + (3*i+2), i+2, hyZ) )
            pdbLines.append( hydro2.format(nAtoms + (3*i+3), i+2, hyZ) )

    # Writes the new pdb lines to a new pdb file

    pdbLines.append("END\n")
    pdbOut = open(my.configFile(paths['solvate'], fileName + '-temp.pdb'), 'w')
    pdbOut.writelines(pdbLines)
    pdbOut.close()

    # Writes the new psf lines to a new psf file

    psfOut = open(my.configFile(paths['solvate'], fileName + '-temp.psf'), 'w')
    psfOut.writelines(preAtoms)
    psfOut.writelines(psfLines[atomIndex])
    psfOut.writelines(atoms)
    psfOut.writelines("\n" + psfLines[bondIndex])
    psfOut.writelines(bondsFinal)
    psfOut.writelines("\n" + psfLines[angleIndex])
    psfOut.writelines(anglesFinal)
    psfOut.writelines(postAngles)
    psfOut.close()

    print("################################################################\n" \
        + "Post-processing the CNT and rewriting configuration files.\n" \
        + "################################################################\n")

    package = "package require CNTtools 1.0\n"
    commands = [ "centerNT " + my.quoted(my.configFile(paths['solvate'], fileName)) + "\n" ]
    my.pdbWrite(my.config(paths['solvate']), fileName, package, commands) 

    # Delete the now-uneeded -temp pdb and psf files.
    
    os.remove(my.config(paths['solvate']) + fileName + "-temp.pdb")
    os.remove(my.config(paths['solvate']) + fileName + "-temp.psf")
예제 #6
0
def cntWrite(paths, fileName, N0, n, m):
    """ cntWrite creates a periodic nanotube with the following input parameters:
    fileName is the name of the initial nanotube with number of rings N0 and
    dimensions n x m."""

    # Bonds lengths of different armchair nanotubes in nanometers
    s0 = 0.1418
    # calculates the length of the nanotube based on bond lengths
    l = float(N0-0.75) * s0 * np.sqrt(3)

    if os.path.isfile(my.configFile(paths['pbc'], fileName + '.psf')) \
        and os.path.isfile(my.configFile(paths['pbc'], fileName + '.pdb')):

        
        print("################################################################\n" \
            + "Configuration files already exist in:\n" + my.config(paths['pbc']) + ".\n" \
            + "################################################################\n")

        return

    print("################################################################\n" \
        + "Running VMD to generate nanotube configuration files.\n" \
        + "################################################################\n")

    if not os.path.exists(my.config(paths['N0'])):
        os.makedirs(my.config(paths['N0']))
    if not os.path.exists(my.config(paths['pbc'])):
        os.makedirs(my.config(paths['pbc']))
        
    # Create the nanotube in VMD

    logFile = open(my.config(paths['N0']) + fileName + ".log", "w")

    # Opening a pipe to VMD in the shell
    VMDin=subprocess.Popen(["vmd", "-dispdev", "none"], stdin=subprocess.PIPE, \
                       stdout=logFile)

    CNTtools = "package require CNTtools 1.0\n"

    genNT = "genNT " + my.quoted(fileName) + " " + my.quoted(my.config(paths['N0'])) + " " \
        + str(l) + " " + str(n) + " " + str(m) + "\n"

    # run commands through pipe and saves to file
    VMDin.stdin.write(CNTtools)
    VMDin.stdin.write(genNT)
    VMDin.stdin.flush()
    VMDin.stdin.close
    VMDin.communicate()

    # Make the nanotube periodic in VMD

    logFile = open(my.config(paths['pbc']) + fileName + ".log", "w")

    # Opening a pipe to VMD in the shell
    VMDin=subprocess.Popen(["vmd", "-dispdev", "none"], stdin=subprocess.PIPE, \
                       stdout=logFile)

    CNTtools = "package require CNTtools\n"
    pbcNT = "pbcNT " + my.quoted(my.config(paths['N0']) + fileName) + " " \
        + my.quoted(my.config(paths['pbc']) + fileName) + " default\n"

    # run commands through pipe and saves to file
    VMDin.stdin.write(CNTtools)
    VMDin.stdin.write(pbcNT)
    VMDin.stdin.flush()
    VMDin.stdin.close
    VMDin.communicate()
    
    # Delete the now-uneeded -prebond pdb and psf files
    os.remove(my.config(paths['pbc']) + fileName + "-prebond.pdb")
    os.remove(my.config(paths['pbc']) + fileName + "-prebond.psf")
    
    # Read back in the pdb file and make sure the z-coordinate spacing is regular
    
    alignCNT(my.config(paths['pbc']) + fileName + ".pdb")
예제 #7
0
def run(pD):
    """ This is the main entry point for performing simulations with a carbon nanotube
    and water. It takes a python dictionary of simulation parameters as its
    argument. Before calling run, you must call myutil.setWaterParamDefaults()
    to create the dictionary."""
    
    # The paths dictionary holds the path name to each tier of the data hierarchy.
    
    paths = my.makeWaterPaths(pD)
    
    # Find the hostname and set the name of the wisdom file used by PME.
    
    hostname = socket.gethostname().partition('.')[0]
    wisdomFile = "FFTW_NAMD_2.11_" + hostname + ".txt"

    # If we're doing a production run (not a minimization) on nanotube, we want to
    # use the GPU, so we run the CUDA version of namd2. The CUDA version of namd seems
    # to give errors occasionally when minimizing, so we don't use it for that.
    
    if pD['Run Type'] == 'Minimize':
        executable = 'namd2'
    else:
        if hostname == 'nanotube':
            executable = 'namd2-cuda'
        else:
            executable = 'namd2'
        
    # If the data folder for the simulation already exists, abort, under the assumption
    # that this is an accidental duplicate of an earlier run. New runs should go into
    # their own folders.
    
    if os.path.exists(paths['data']):
        print("################################################################\n" \
              + "Data folder for " + pD['Run Type'] + " run already exists ... aborting.\n" \
              + "################################################################\n")
        return

    # This is the base name for all the various pdb and psf files we will generate.
    
    fileName = pD['Config File Name']

    # Bonds lengths of armchair nanotubes in nanometers. From this we'll calculate the
    # actual length of the nanotube in nanometers to feed to VMD.
    
    s0 = 0.1418
    l = float(pD['N0']-0.75) * s0 * np.sqrt(3)

    # Create the desired nanotube. The files will be stored in the 'Config Files' folder
    # in the folder pointed to by paths['N0'].
    
    package = "package require CNTtools 1.0\n"
    commands = [ "genNT " \
                + my.quoted(my.configFile(paths['N0'], fileName)) + " " \
                + str(l) + " " + str(pD['n']) + " " + str(pD['m']) + "\n" ]
   
    my.pdbWrite(paths['N0'], fileName, package, commands)
    
    # Now we'll make the nanotube periodic in the z direction.
    
    commands = [ "pbcNT " + my.quoted(my.configFile(paths['N0'], fileName)) + " " \
                + my.quoted(my.configFile(paths['pbc'], fileName)) + " default\n" ]

    my.pdbWrite(paths['pbc'], fileName, package, commands)  
    
    # Delete the now-uneeded -prebond pdb and psf files.
    
    if os.path.exists(my.config(paths['pbc']) + fileName + "-prebond.pdb"):
        os.remove(my.config(paths['pbc']) + fileName + "-prebond.pdb")
    if os.path.exists(my.config(paths['pbc']) + fileName + "-prebond.psf"):
        os.remove(my.config(paths['pbc']) + fileName + "-prebond.psf")
    
    # Read back in the pdb file and make sure the z-coordinate spacing is regular.
    
    alignCNT(my.config(paths['pbc']) + fileName + ".pdb")

    # cntWrite(paths, pD['Config File Name'], pD['N0'], pD['n'], pD['m'])
    
    # Add the water to the carbon nanotube, and center the nanotube in the box.
    
    waterWrite(paths, pD['Config File Name'], pD['N0'], pD['S'])
    
    # Write the restraint pdb file.
    
    commands = [ "NTrestraint " \
                + my.quoted(my.configFile(paths['solvate'], fileName)) + " " \
                + my.quoted(my.configFile(paths['restraint'], fileName)) + " " \
                + str(pD['Restraint']) + "\n" ]
    my.pdbWrite(paths['restraint'], fileName, package, commands)
    
    # If the simulation is a New (not Minimization) run, we need to set the forcing
    # and the thermostat parameters, and preheat the water.
    
    if pD['Run Type'] == 'New':
    
        # Write the forcing pdb file.
    
        commands = [ "NTforcing " \
                    + my.quoted(my.configFile(paths['solvate'], fileName)) + " " \
                    + my.quoted(my.configFile(paths['forcing'], fileName)) + " " \
                    + str(pD['Force (pN)']) + "\n" ]
        my.pdbWrite(paths['forcing'], fileName, package, commands)

        # Write the Langevin pdb file.
    
        commands = [ "NTtemperature " \
                    + my.quoted(my.configFile(paths['solvate'], fileName)) + " " \
                    + my.quoted(my.configFile(paths['temperature'], fileName)) + " " \
                    + str(pD['Damping']) + "\n" ]
        my.pdbWrite(paths['temperature'], fileName, package, commands)

        # Set up the temporary folder for the simulation.
        
        paths['run'] = os.getenv('HOME') + '/' + pD['Data Folder'] + '/Preheat/'
        
        # Create a NAMD configuration file for the preheating run.
        
        preheatConfFile = confWrite(paths, pD, hostname, wisdomFile, preheat = True)
        
        # Link all the necessary files back to the temporary run folder.
        
        linkFiles(paths, pD, wisdomFile, preheat = True)
        
        # Do the preheating run.
        
        result, runTime = runSim(executable, paths['run'], preheatConfFile, \
            pD['Config File Name'], hostname)
    
    # Set up a temporary run folder. This is either for a production run or for a
    # minimization run.
    
    paths['run'] = os.getenv('HOME') + '/' + pD['Data Folder'] + '/'
    
    # Create the NAMD configuration file for the run. Again, this is a production run
    # or a minimization run.
    
    confFile = confWrite(paths, pD, hostname, wisdomFile)
    
    # Link all the necessary files back to the temporary run folder.

    linkFiles(paths, pD, wisdomFile)

    # Do the simulation!!
    
    result, runTime = runSim(executable, paths['run'], confFile, pD['Config File Name'], hostname)
    
    # If the run succeeded, log it to the appropriate spreadsheet.
    
    if result == 0:
    
        if not os.path.isfile(hostname + '.csv'):
        
            print("################################################################\n" \
                + "Creating file " + hostname + ".csv." + "\n" \
                + "################################################################\n")
        
            outFile = open(hostname + '.csv', "w")
            outFile.write("Date,Run Time (h),File Name,Folder,Run Type,N0,S,n,m," \
                + "Temperature (K),Damping,Thermostat," \
                + "Force (pN),PME,Restraint,Duration,Min Duration,dt (fs),outputFreq\n")
                
        print("################################################################\n" \
              + "Writing to file " + hostname + ".csv." + "\n" \
              + "################################################################\n")
              
        outFile = open(hostname + '.csv', "a")
        outFile.write(str(datetime.date.today()) + ',' \
            + "{:.5f}".format(runTime) + ',' \
            + pD['Data Folder'] + ',' \
            + pD['Top Folder'] + ',' \
            + pD['Run Type'] + ',' \
            + str(pD['N0']) + ',' \
            + str(pD['S']) + ',' \
            + str(pD['n']) + ',' \
            + str(pD['m']) + ',' \
            + str(pD['Temperature (K)']) + ',' \
            + str(pD['Damping']) + ',' \
            + pD['Thermostat'] + ',' \
            + str(pD['Force (pN)']) + ',' \
            + pD['PME'] + ','
            + str(pD['Restraint']) + ',' \
            + str(pD['Duration']) + ',' \
            + str(pD['Min Duration']) + ',' \
            + str(pD['dt (fs)']) + ',' \
            + str(pD['outputFreq']) + '\n')
    
    print("################################################################\n" \
          + "Finished writing to file " + hostname + ".csv." + "\n" \
          + "################################################################\n")
    print("################################################################\n" \
          + "Moving " + paths['run'] + " to " + paths['data'] + ".\n" \
          + "################################################################\n")
    
    # Move the temporary run file to the appropriate place in the data hierarchy.
    
    shutil.move(paths['run'], paths['data'])
예제 #8
0
def waterWrite(paths, fileName, N0, S):
    """ waterWrite adds N0 + S water molecules to the inside of the nanotube,
        then write out new psf and pdb files for the nanotube. """

    if not my.needConfigFiles(paths['solvate'], fileName):
        return

    # Opens input nanotube psf and pdb files, and reads all the lines of each file into lists

    with open(my.configFile(paths['pbc'], fileName + '.psf')) as psfFile:
        psfLines = psfFile.readlines()
    with open(my.configFile(paths['pbc'], fileName + '.pdb')) as pdbFile:
        pdbLines = pdbFile.readlines()

    # Grabs the lengths of each of the lists

    lenPsf = len(psfLines)
    lenPdb = len(pdbLines)

    # String formats for the PSF and PDB file writing
    # PDB

    dampingCoeff = 0.00
    oxygen = "ATOM{0:>7}  OH2 TIP3 {1:4.0f}       0.000   0.000{2:>8.3f}  0.00  0.00      WTR  O\n"
    hydro1 = "ATOM{0:>7}  H1  TIP3 {1:4.0f}       0.000   0.766{2:>8.3f}  0.00  0.00      WTR  H\n"
    hydro2 = "ATOM{0:>7}  H2  TIP3 {1:4.0f}       0.000  -0.766{2:>8.3f}  0.00  0.00      WTR  H\n"

    # Psf

    opsf = "   {0:>5} WTR  {1:<4} TIP3 OH2  OT    -0.834000       15.9994           0\n"
    h1psf = "   {0:>5} WTR  {1:<4} TIP3 H1   HT     0.417000        1.0080           0\n"
    h2psf = "   {0:>5} WTR  {1:<4} TIP3 H2   HT     0.417000        1.0080           0\n"

    # String format for the bonds and angles in the psf file

    sBondFormat = " {0: >8}{1: >8}{2: >8}{3: >8}{4: >8}{5: >8}{6: >8}{7: >8}\n"
    sAngleFormat = " {0: >8}{1: >8}{2: >8}{3: >8}{4: >8}{5: >8}{6: >8}{7: >8}{8: >8}\n"

    # Initializing lists used below

    atoms = []
    bonds = []
    angles = []
    preAtoms = []
    postAngles = []

    intBonds = []
    bondsFinal = []
    intAngles = []
    anglesFinal = []

    # Finds the original number of atoms in the Pdb file

    nAtoms = lenPdb - 2

    # Calculates the new number of atoms after solvating

    newAtoms = nAtoms + (3 * (N0 + S))

    # Calculates the new number of bonds and angles after solvating

    newBonds = int(nAtoms * (3. / 2)) + 2 * (N0 + S)
    newAngles = nAtoms * 3 + (N0 + S)

    # Iterates through all of the lines of the input Psf file, and records the
    # index of the lines that contain the string !NATOM, !NBOND, and !NTHETA,
    # as well as changes the line to update the new number of each

    for i in range(0, lenPsf):
        if "!NATOM" in psfLines[i]:
            psfLines[i] = "     {:3d} !NATOM\n".format(newAtoms)
            atomIndex = i
        elif "!NBOND" in psfLines[i]:
            psfLines[i] = "     {:3d} !NBOND: bonds\n".format(newBonds)
            bondIndex = i
        elif "!NTHETA" in psfLines[i]:
            psfLines[i] = "     {:3d} !NTHETA: angles\n".format(newAngles)
            angleIndex = i

    # Stores all of the original text lines that come before the atom section into a list

    for i in range(0, atomIndex):
        preAtoms.append(psfLines[i])

    # Stores the atoms into a list

    count = 1
    while psfLines[atomIndex + count].strip():
        atoms.append(psfLines[atomIndex + count])
        count += 1

    # Stores the bonds into a list

    count = 1
    while psfLines[bondIndex + count].strip():
        bonds.append(psfLines[bondIndex + count])
        count += 1

    # Stores the angles into a list

    count = 1
    while psfLines[angleIndex + count].strip():
        angles.append(psfLines[angleIndex + count])
        count += 1

    # Stores all the text lines after the angles into a list

    for i in range(angleIndex + count, lenPsf):
        postAngles.append(psfLines[i])

    # Takes the bonds and angles in the original file and splits each line into individual numbers

    for bond in bonds:
        intBonds.append(bond.strip("\n").split())
    for angle in angles:
        intAngles.append(angle.strip("\n").split())

    # Compresses the list of lists into a single list of all of the angles and bonds in the original file

    intBonds = list(chain.from_iterable(intBonds))
    intAngles = list(chain.from_iterable(intAngles))

    # Adds the new atoms to the original list of atoms

    for i in range(nAtoms + 1, (3 * (N0 + S)) + nAtoms + 1, 3):

        atoms.append(opsf.format(i, int((i - nAtoms) / 3) + 2))
        atoms.append(h1psf.format(i + 1, int((i - nAtoms) / 3) + 2))
        atoms.append(h2psf.format(i + 2, int((i - nAtoms) / 3) + 2))

        intAngles.append(str(i + 1))
        intAngles.append(str(i))
        intAngles.append(str(i + 2))

        intBonds.append(str(i))
        intBonds.append(str(i + 1))
        intBonds.append(str(i))
        intBonds.append(str(i + 2))

    # Formats the list of bonds into the psf format with 8 columns

    for i in range(0, len(intBonds), 8):

        try:
            bondsFinal.append(
                sBondFormat.format(intBonds[i], intBonds[i + 1],
                                   intBonds[i + 2], intBonds[i + 3],
                                   intBonds[i + 4], intBonds[i + 5],
                                   intBonds[i + 6], intBonds[i + 7]))

        except:
            diff = len(intBonds) - i
            tempStr = ""
            for j in range(i, i + diff):
                tempStr = tempStr + "{:>8}".format(intBonds[j])

            bondsFinal.append(" " + tempStr + "\n")

    # Formates the list of angles into the psf format with 9 columns

    for i in range(0, len(intAngles), 9):

        try:
            anglesFinal.append(
                sAngleFormat.format(intAngles[i], intAngles[i + 1],
                                    intAngles[i + 2], intAngles[i + 3],
                                    intAngles[i + 4], intAngles[i + 5],
                                    intAngles[i + 6], intAngles[i + 7],
                                    intAngles[i + 8]))

        except:
            diff = len(intAngles) - i
            tempStr = ""
            for j in range(i, i + diff):
                tempStr = tempStr + "{:>8}".format(intAngles[j])

            anglesFinal.append(" " + tempStr + "\n")

    oxZ = waterZ(N0, S)

    for i in range(0, N0 + S):

        hyZ = oxZ[i] + 0.570
        if i == 0:
            pdbLines[lenPdb - 1] = oxygen.format(nAtoms + 1, 2, oxZ[i])
            pdbLines.append(hydro1.format(nAtoms + 2, 2, hyZ))
            pdbLines.append(hydro2.format(nAtoms + 3, 2, hyZ))
        else:
            pdbLines.append(oxygen.format(nAtoms + 3 * i + 1, i + 2, oxZ[i]))
            pdbLines.append(hydro1.format(nAtoms + (3 * i + 2), i + 2, hyZ))
            pdbLines.append(hydro2.format(nAtoms + (3 * i + 3), i + 2, hyZ))

    # Writes the new pdb lines to a new pdb file

    pdbLines.append("END\n")
    pdbOut = open(my.configFile(paths['solvate'], fileName + '-temp.pdb'), 'w')
    pdbOut.writelines(pdbLines)
    pdbOut.close()

    # Writes the new psf lines to a new psf file

    psfOut = open(my.configFile(paths['solvate'], fileName + '-temp.psf'), 'w')
    psfOut.writelines(preAtoms)
    psfOut.writelines(psfLines[atomIndex])
    psfOut.writelines(atoms)
    psfOut.writelines("\n" + psfLines[bondIndex])
    psfOut.writelines(bondsFinal)
    psfOut.writelines("\n" + psfLines[angleIndex])
    psfOut.writelines(anglesFinal)
    psfOut.writelines(postAngles)
    psfOut.close()

    print("################################################################\n" \
        + "Post-processing the CNT and rewriting configuration files.\n" \
        + "################################################################\n")

    package = "package require CNTtools 1.0\n"
    commands = [
        "centerNT " + my.quoted(my.configFile(paths['solvate'], fileName)) +
        "\n"
    ]
    my.pdbWrite(my.config(paths['solvate']), fileName, package, commands)

    # Delete the now-uneeded -temp pdb and psf files.

    os.remove(my.config(paths['solvate']) + fileName + "-temp.pdb")
    os.remove(my.config(paths['solvate']) + fileName + "-temp.psf")
예제 #9
0
def cntWrite(paths, fileName, N0, n, m):
    """ cntWrite creates a periodic nanotube with the following input parameters:
    fileName is the name of the initial nanotube with number of rings N0 and
    dimensions n x m."""

    # Bonds lengths of different armchair nanotubes in nanometers
    s0 = 0.1418
    # calculates the length of the nanotube based on bond lengths
    l = float(N0 - 0.75) * s0 * np.sqrt(3)

    if os.path.isfile(my.configFile(paths['pbc'], fileName + '.psf')) \
        and os.path.isfile(my.configFile(paths['pbc'], fileName + '.pdb')):


        print("################################################################\n" \
            + "Configuration files already exist in:\n" + my.config(paths['pbc']) + ".\n" \
            + "################################################################\n")

        return

    print("################################################################\n" \
        + "Running VMD to generate nanotube configuration files.\n" \
        + "################################################################\n")

    if not os.path.exists(my.config(paths['N0'])):
        os.makedirs(my.config(paths['N0']))
    if not os.path.exists(my.config(paths['pbc'])):
        os.makedirs(my.config(paths['pbc']))

    # Create the nanotube in VMD

    logFile = open(my.config(paths['N0']) + fileName + ".log", "w")

    # Opening a pipe to VMD in the shell
    VMDin=subprocess.Popen(["vmd", "-dispdev", "none"], stdin=subprocess.PIPE, \
                       stdout=logFile)

    CNTtools = "package require CNTtools 1.0\n"

    genNT = "genNT " + my.quoted(fileName) + " " + my.quoted(my.config(paths['N0'])) + " " \
        + str(l) + " " + str(n) + " " + str(m) + "\n"

    # run commands through pipe and saves to file
    VMDin.stdin.write(CNTtools)
    VMDin.stdin.write(genNT)
    VMDin.stdin.flush()
    VMDin.stdin.close
    VMDin.communicate()

    # Make the nanotube periodic in VMD

    logFile = open(my.config(paths['pbc']) + fileName + ".log", "w")

    # Opening a pipe to VMD in the shell
    VMDin=subprocess.Popen(["vmd", "-dispdev", "none"], stdin=subprocess.PIPE, \
                       stdout=logFile)

    CNTtools = "package require CNTtools\n"
    pbcNT = "pbcNT " + my.quoted(my.config(paths['N0']) + fileName) + " " \
        + my.quoted(my.config(paths['pbc']) + fileName) + " default\n"

    # run commands through pipe and saves to file
    VMDin.stdin.write(CNTtools)
    VMDin.stdin.write(pbcNT)
    VMDin.stdin.flush()
    VMDin.stdin.close
    VMDin.communicate()

    # Delete the now-uneeded -prebond pdb and psf files
    os.remove(my.config(paths['pbc']) + fileName + "-prebond.pdb")
    os.remove(my.config(paths['pbc']) + fileName + "-prebond.psf")

    # Read back in the pdb file and make sure the z-coordinate spacing is regular

    alignCNT(my.config(paths['pbc']) + fileName + ".pdb")
예제 #10
0
def run(pD):
    """ This is the main entry point for performing simulations with a carbon nanotube
    and water. It takes a python dictionary of simulation parameters as its
    argument. Before calling run, you must call myutil.setWaterParamDefaults()
    to create the dictionary."""

    # The paths dictionary holds the path name to each tier of the data hierarchy.

    paths = my.makeWaterPaths(pD)

    # Find the hostname and set the name of the wisdom file used by PME.

    hostname = socket.gethostname().partition('.')[0]
    wisdomFile = "FFTW_NAMD_2.11_" + hostname + ".txt"

    # If we're doing a production run (not a minimization) on nanotube, we want to
    # use the GPU, so we run the CUDA version of namd2. The CUDA version of namd seems
    # to give errors occasionally when minimizing, so we don't use it for that.

    if pD['Run Type'] == 'Minimize':
        executable = 'namd2'
    else:
        if hostname == 'nanotube':
            executable = 'namd2-cuda'
        else:
            executable = 'namd2'

    # If the data folder for the simulation already exists, abort, under the assumption
    # that this is an accidental duplicate of an earlier run. New runs should go into
    # their own folders.

    if os.path.exists(paths['data']):
        print("################################################################\n" \
              + "Data folder for " + pD['Run Type'] + " run already exists ... aborting.\n" \
              + "################################################################\n")
        return

    # This is the base name for all the various pdb and psf files we will generate.

    fileName = pD['Config File Name']

    # Bonds lengths of armchair nanotubes in nanometers. From this we'll calculate the
    # actual length of the nanotube in nanometers to feed to VMD.

    s0 = 0.1418
    l = float(pD['N0'] - 0.75) * s0 * np.sqrt(3)

    # Create the desired nanotube. The files will be stored in the 'Config Files' folder
    # in the folder pointed to by paths['N0'].

    package = "package require CNTtools 1.0\n"
    commands = [ "genNT " \
                + my.quoted(my.configFile(paths['N0'], fileName)) + " " \
                + str(l) + " " + str(pD['n']) + " " + str(pD['m']) + "\n" ]

    my.pdbWrite(paths['N0'], fileName, package, commands)

    # Now we'll make the nanotube periodic in the z direction.

    commands = [ "pbcNT " + my.quoted(my.configFile(paths['N0'], fileName)) + " " \
                + my.quoted(my.configFile(paths['pbc'], fileName)) + " default\n" ]

    my.pdbWrite(paths['pbc'], fileName, package, commands)

    # Delete the now-uneeded -prebond pdb and psf files.

    if os.path.exists(my.config(paths['pbc']) + fileName + "-prebond.pdb"):
        os.remove(my.config(paths['pbc']) + fileName + "-prebond.pdb")
    if os.path.exists(my.config(paths['pbc']) + fileName + "-prebond.psf"):
        os.remove(my.config(paths['pbc']) + fileName + "-prebond.psf")

    # Read back in the pdb file and make sure the z-coordinate spacing is regular.

    alignCNT(my.config(paths['pbc']) + fileName + ".pdb")

    # cntWrite(paths, pD['Config File Name'], pD['N0'], pD['n'], pD['m'])

    # Add the water to the carbon nanotube, and center the nanotube in the box.

    waterWrite(paths, pD['Config File Name'], pD['N0'], pD['S'])

    # Write the restraint pdb file.

    commands = [ "NTrestraint " \
                + my.quoted(my.configFile(paths['solvate'], fileName)) + " " \
                + my.quoted(my.configFile(paths['restraint'], fileName)) + " " \
                + str(pD['Restraint']) + "\n" ]
    my.pdbWrite(paths['restraint'], fileName, package, commands)

    # If the simulation is a New (not Minimization) run, we need to set the forcing
    # and the thermostat parameters, and preheat the water.

    if pD['Run Type'] == 'New':

        # Write the forcing pdb file.

        commands = [ "NTforcing " \
                    + my.quoted(my.configFile(paths['solvate'], fileName)) + " " \
                    + my.quoted(my.configFile(paths['forcing'], fileName)) + " " \
                    + str(pD['Force (pN)']) + "\n" ]
        my.pdbWrite(paths['forcing'], fileName, package, commands)

        # Write the Langevin pdb file.

        commands = [ "NTtemperature " \
                    + my.quoted(my.configFile(paths['solvate'], fileName)) + " " \
                    + my.quoted(my.configFile(paths['temperature'], fileName)) + " " \
                    + str(pD['Damping']) + "\n" ]
        my.pdbWrite(paths['temperature'], fileName, package, commands)

        # Set up the temporary folder for the simulation.

        paths['run'] = os.getenv(
            'HOME') + '/' + pD['Data Folder'] + '/Preheat/'

        # Create a NAMD configuration file for the preheating run.

        preheatConfFile = confWrite(paths,
                                    pD,
                                    hostname,
                                    wisdomFile,
                                    preheat=True)

        # Link all the necessary files back to the temporary run folder.

        linkFiles(paths, pD, wisdomFile, preheat=True)

        # Do the preheating run.

        result, runTime = runSim(executable, paths['run'], preheatConfFile, \
            pD['Config File Name'], hostname)

    # Set up a temporary run folder. This is either for a production run or for a
    # minimization run.

    paths['run'] = os.getenv('HOME') + '/' + pD['Data Folder'] + '/'

    # Create the NAMD configuration file for the run. Again, this is a production run
    # or a minimization run.

    confFile = confWrite(paths, pD, hostname, wisdomFile)

    # Link all the necessary files back to the temporary run folder.

    linkFiles(paths, pD, wisdomFile)

    # Do the simulation!!

    result, runTime = runSim(executable, paths['run'], confFile,
                             pD['Config File Name'], hostname)

    # If the run succeeded, log it to the appropriate spreadsheet.

    if result == 0:

        if not os.path.isfile(hostname + '.csv'):

            print("################################################################\n" \
                + "Creating file " + hostname + ".csv." + "\n" \
                + "################################################################\n")

            outFile = open(hostname + '.csv', "w")
            outFile.write("Date,Run Time (h),File Name,Folder,Run Type,N0,S,n,m," \
                + "Temperature (K),Damping,Thermostat," \
                + "Force (pN),PME,Restraint,Duration,Min Duration,dt (fs),outputFreq\n")

        print("################################################################\n" \
              + "Writing to file " + hostname + ".csv." + "\n" \
              + "################################################################\n")

        outFile = open(hostname + '.csv', "a")
        outFile.write(str(datetime.date.today()) + ',' \
            + "{:.5f}".format(runTime) + ',' \
            + pD['Data Folder'] + ',' \
            + pD['Top Folder'] + ',' \
            + pD['Run Type'] + ',' \
            + str(pD['N0']) + ',' \
            + str(pD['S']) + ',' \
            + str(pD['n']) + ',' \
            + str(pD['m']) + ',' \
            + str(pD['Temperature (K)']) + ',' \
            + str(pD['Damping']) + ',' \
            + pD['Thermostat'] + ',' \
            + str(pD['Force (pN)']) + ',' \
            + pD['PME'] + ','
            + str(pD['Restraint']) + ',' \
            + str(pD['Duration']) + ',' \
            + str(pD['Min Duration']) + ',' \
            + str(pD['dt (fs)']) + ',' \
            + str(pD['outputFreq']) + '\n')

    print("################################################################\n" \
          + "Finished writing to file " + hostname + ".csv." + "\n" \
          + "################################################################\n")
    print("################################################################\n" \
          + "Moving " + paths['run'] + " to " + paths['data'] + ".\n" \
          + "################################################################\n")

    # Move the temporary run file to the appropriate place in the data hierarchy.

    shutil.move(paths['run'], paths['data'])