def countWaterCNT(bgf_file, trj_file, silent=False): # init timestep = 0 l_timestep = [] myBGF = bgf.BgfFile(bgf_file) myTRJ = open(trj_file) myDAT = open(bgf_file[:-4] + ".count.dat", "w") myDAT.write("Time\tHeight\tRadius\tNumber\n") # extract aNos of CNT in the BGF file aNo_CNT = [] aNo_MtOH_C = [] for atom in myBGF.a: # Carbons in CNT if "CNT" in atom.rName: aNo_CNT.append(atom.aNo) # Carbons in MeOH if "MET" in atom.rName and "C" in atom.aName: aNo_MtOH_C.append(atom.aNo) N_CNT = len(aNo_CNT) # the number of CNT atoms # for every shot in the trajectory file update BGF and manipulate myDUMP = dump.dump(trj_file, 0) # sequential reading while 1: aNo_MtOH_C_in_CNT = copy.deepcopy(aNo_MtOH_C) # initialize for the moment of inertia and the center of mass calculation U = 0 Ut = 0 Uv = 0 Ixx = 0 Ixy = 0 Ixz = 0 Iyx = 0 Iyy = 0 Iyz = 0 Izx = 0 Izy = 0 Izz = 0 Mx = 0 My = 0 Mz = 0 time = myDUMP.next() sys.stdout.write('\r' + "Reading timestep.. " + str(time)) sys.stdout.flush() #print("Timestep: " + str(time)) if time == -1: break nu.shutup() myDUMP.sort() nu.say() l_timestep = myDUMP.time() # timesteps are 'appended' incrementally atoms = myDUMP.viz(len(l_timestep) - 1)[ 2] # atom coordinate info: id,type,x,y,z for each atom as 2d array box = myDUMP.viz(len(l_timestep) - 1)[1] # [xlo, ylo, zlo, xhi, yhi, zhi] box = [float(i) for i in box] boxsize = [box[3] - box[0], box[4] - box[1], box[5] - box[1]] # simbox size myBGF.CRYSTX = [ boxsize[0], boxsize[1], boxsize[2], myBGF.CRYSTX[3], myBGF.CRYSTX[4], myBGF.CRYSTX[5] ] #print("l_atoms " + str(len(atoms))) # update the coordinates in the bgf file for atom in atoms: bgfatom = myBGF.getAtom(atom[0]) bgfatom.x = float(atom[2]) bgfatom.y = float(atom[3]) bgfatom.z = float(atom[4]) """ # com of CNT for atom in myBGF.a: if "CNT" in atom.rName: Mx += atom.x / N_CNT My += atom.y / N_CNT Mz += atom.z / N_CNT """ myBGF = bgftools.periodicMoleculeSort(myBGF) #print(Mx, My, Mz) # transpose for "all atoms in BGF" for atom in myBGF.a: atom.x -= Mx atom.y -= My atom.z -= Mz # calculate the moment of inertia (MI) and the center of mass (COM) of CNT from "myBGF" for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) Ixx += (atom.y**2 + atom.z**2) / N_CNT Iyy += (atom.x**2 + atom.z**2) / N_CNT Izz += (atom.x**2 + atom.y**2) / N_CNT Ixy -= (atom.x * atom.y) / N_CNT Ixz -= (atom.x * atom.z) / N_CNT Iyz -= (atom.y * atom.z) / N_CNT # the moment of inertia tensor I = numpy.array([[Ixx, Ixy, Ixz], [Ixy, Iyy, Iyz], [Ixz, Iyz, Izz]]) # eigenvalue & eigenvector calculation eigval, eigvec = numpy.linalg.eig( I) # eigval[0] is the minimum among the values. # rearrange the U vector U = numpy.matrix(eigvec) Ut = U.T # "myBGF" transform for atom in myBGF.a: v = numpy.matrix([atom.x, atom.y, atom.z]).T Uv = Ut * v atom.x = float(Uv[0]) atom.y = float(Uv[1]) atom.z = float(Uv[2]) # com of CNT Mx = 0 My = 0 Mz = 0 for atom in myBGF.a: if "CNT" in atom.rName: Mx += atom.x / N_CNT My += atom.y / N_CNT Mz += atom.z / N_CNT #print(Mx, My, Mz) # transpose for "all atoms in BGF" for atom in myBGF.a: atom.x -= Mx atom.y -= My atom.z -= Mz """ ### THIS PART (UPDATING LAMMPSTRJ) DOES NOT WORK ### myDUMP.aselect.all(time) # all atoms should be selected to be changed myDUMP.tselect.one(time) coordx = []; coordy = []; coordz = [] for atom in myBGF.a: coordx.append(atom.x) coordy.append(atom.y) coordz.append(atom.z) myDUMP.setv("xu", coordx) myDUMP.setv("yu", coordy) myDUMP.setv("zu", coordz) """ """ ### CHECKING ORIGIN by adding an atom at (0, 0, 0) and is okay. 110914 inkim origin = bgf.BgfAtom() origin.aTag = 0 origin.aName = "ORIG" origin.ffType = "Ar" origin.chain = "A" origin.x = 0.0 origin.y = 0.0 origin.z = 0.0 origin.rName = "ORG" myBGF.addAtom(origin) """ # for CNT atoms, calculate some properties min_x_CNT = 0.0 max_x_CNT = 0.0 radius_CNT = 0.0 height_CNT = 0.0 for aNo in aNo_CNT: atom = myBGF.getAtom(aNo) # minimum and maximum x coord of CNT: this will be the height of CNT if atom.x < min_x_CNT: min_x_CNT = atom.x if atom.x > max_x_CNT: max_x_CNT = atom.x radius_CNT += math.sqrt(atom.y**2 + atom.z**2) # average radius of CNT radius_CNT = radius_CNT / N_CNT height_CNT = max_x_CNT - min_x_CNT # determine whether C in MtOH is in the CNT Cylinder for aNo in aNo_MtOH_C: atom = myBGF.getAtom(aNo) dist = math.sqrt(atom.y**2 + atom.z**2) if atom.x > min_x_CNT \ and atom.x < max_x_CNT \ and dist < radius_CNT: pass else: aNo_MtOH_C_in_CNT.remove(aNo) #print("Height of CNT: " + str(height_CNT) + " " + str(min_x_CNT) + " " + str(max_x_CNT)) #print("Average radius of CNT: " + str(radius_CNT)) #print("Average number of methanols in CNT: " + str(len(aNo_MtOH_C_in_CNT))) myDAT.write(str(time) + "\t") myDAT.write(str("{0:<8.3f}".format(height_CNT))) myDAT.write(str("{0:<8.3f}".format(radius_CNT))) myDAT.write(str(len(aNo_MtOH_C_in_CNT)) + "\n") # write output myBGF.saveBGF(bgf_file[:-4] + "." + str(time) + ".bgf") #myDUMP.write(trj_file.split(".")[0] + "_mod." + trj_file.split(".")[1]) print('') return 1
def crosslink(bgf_file, ff_file, suffix, init_script_original_file, crosslink_script_original_file, t, ratio, out_file): # *** variables *** # used for calculating the number of 1", 2", and 3" amines l_init_amines = [] l_amines = [] # used for log file output output = "" # used for storing number of cross_linking per each cycle n_crosslink_per_cycle = [] # used for storing cumulative number of crosslink type n_crosslink_pripri = 0 n_crosslink_prisec = 0 n_crosslink_secsec = 0 # initialization f_out_file = open(out_file, 'w') t1 = 0 t2 = 0 # clock for measuring time for a cycle f_out_file.write("crosslink.py: version " + str(version) + "\n") f_out_file.write("" + "\n") f_out_file.write("Job started at " + time.asctime(time.gmtime()) + " on " + os.environ["HOSTNAME"] + " by " + os.environ["USER"] + "\n") f_out_file.write("Command executed at " + os.getcwd() + "\n") f_out_file.write("Requested options: " + str(sys.argv) + "\n") f_out_file.write("" + "\n") f_out_file.write("Using MPI: " + str(mpi_command) + "\n") f_out_file.write("Using LAMMPS: " + str(lammps_command) + "\n") f_out_file.write("Using Initial input script: " + str(init_script_original_file) + "\n") f_out_file.write("Using Crosslinking input script: " + str(crosslink_script_original_file) + "\n") curr_dir = os.path.abspath(".") temp_dir = scratch_dir + "/" + suffix initial_bgf_file = bgf_file # LAMMPS executive command: defined in ~/scripts/clusterSettings.py lammps_parallel = mpi_command + " " + lammps_command n_crosslink = 0 f_out_file.flush() f_out_file.write("\n* Initialization" + "\n") # determine the initial numbers of primary, secondary, and tertiary amines l_init_amines = bgftools.getAmineGroupInfo(initial_bgf_file) f_out_file.write( "\tNumber of primary, secondary, and tertiary amine groups: " + str(l_init_amines) + "\n") AmineGroupInfo = bgftools.setAmineGroupInfo(initial_bgf_file, initial_bgf_file) f_out_file.write( "\tNumber of primary, secondary, and tertiary amine groups are investigated and updated: " + str(AmineGroupInfo) + "\n") # check ratio n_initAvailAmineSites = AmineGroupInfo[0] + AmineGroupInfo[1] f_out_file.write("Requested ratio: " + str(ratio) + "\n") # scratch setting and file copy f_out_file.write("\tCreating scratch directory: " + temp_dir + "\n") if not os.path.isdir(temp_dir): os.makedirs(temp_dir) # managing hostfile: "COMMENTED" # Important Note: assume that "cat $PBS_NODEFILE > hostfile" is already executed in the .pbs file #hostfile = open(temp_dir + "/hostfile", 'w') #for i in range(0, 12): hostfile.write(os.environ["HOST"] + "\n") #hostfile.close() #shutil.copy("hostfile", temp_dir) #shutil.copy(initial_bgf_file, temp_dir) shutil.copy(ff_file, temp_dir) os.chdir(temp_dir) # LAMMPS input script files for crosslinking #init_script_original_file = "/home/noische/research/dendrimer/simulation/600/procedures/in.noinit" #init_script_original_file = "/home/noische/research/dendrimer/simulation/600/procedures/in.initialize" #crosslink_script_original_file = "/home/noische/research/dendrimer/simulation/procedures/in.xlnk_nvt_1ps_k1.0_r6_0ps" #crosslink_script_original_file = "/home/noische/research/dendrimer/simulation/600/procedures/in.xlnk_npt_1ps_k16_r28" #crosslink_script_original_file = "/home/noische/research/dendrimer/simulation/600/procedures/in.xlnk_npt_1ps_k8_r28" #crosslink_script_original_file = "/home/noische/research/dendrimer/simulation/600/procedures/in.xlnk_npt_1ps_k16_r35" shutil.copy(init_script_original_file, temp_dir) shutil.copy(crosslink_script_original_file, temp_dir) init_script_filename = init_script_original_file.split("/")[ -1] # initial script filename crosslink_script_filename = crosslink_script_original_file.split("/")[ -1] # crosslinking script filename createLammpsInput = "createLammpsInput.pl -b " + bgf_file + " -f " + ff_file + " -s " + suffix + " -o 'no shake' -t " + init_script_filename + " > /dev/null" os.system(createLammpsInput) initial_in_file = "in." + suffix # apply a patch for initialization patch_crosslink.pair_coeff_patch_wo_xlinker(initial_in_file, False) # first run t1 = time.time() runLammpsParallel = lammps_parallel + " -screen none -in " + initial_in_file + " -log " + os.path.join( temp_dir, suffix + ".log") f_out_file.write("\tRunning Lammps: see " + str(os.path.join(temp_dir, suffix + ".log")) + "\n") os.system(runLammpsParallel) t2 = time.time() f_out_file.write("\tElapsed time for the initialization: " + str(t2 - t1) + " sec\n") f_out_file.flush() # update coordinates initial_trj_file = suffix + "_init.lammpstrj" f_out_file.write("\tUpdating the BGF file " + initial_bgf_file + " with LAMMPS trajectory file to _trj_updated.bgf" + "\n") #updatebgf(initial_bgf_file, initial_trj_file, "_trj_updated.bgf", True, silent=True); LAMMPS_trj2bgf.getLAMMPSTrajectory(initial_bgf_file, initial_trj_file, "_trj_updated.bgf", -1, False, True) f_out_file.write("\tReassigning the origin of " + "_trj_updated.bgf" + " and saving " + "_centered.bgf" + "\n") #nu.shutup(); centerbgf("_trj_updated.bgf", "_centered.bgf", "", "com_center"); nu.say() nu.shutup() os.system("~tpascal/scripts/centerBGF.pl -b _trj_updated.bgf -f " + ff_file + " -s _centered.bgf -c com_center") nu.say() bgf_file = suffix + "1.bgf" shutil.copy("_centered.bgf", bgf_file) f_out_file.flush() # repeat if t == 0: t = 10 n_process = 0 endFlag = False # crosslinking start! for i in range(1, t + 1): print("====== " + str(i) + " ======") n_process = i t1 = time.time() N_prisecter = [0, 0, 0] # N counter init. f_out_file.write("\n\n====== Cycle " + str(i) + " ======" + "\n") sname = suffix + str(i) bgf_file = sname + ".bgf" input_file = "in." + sname f_out_file.flush() # create input f_out_file.write( "\n* Minimization, heating, and NVT dynamics for 1ps" + "\n") f_out_file.write("\tCreating Lammps input for " + bgf_file + "\n") ################## IMPORTANT: min heat nvt -> min nvt for crosslinking ##################### 2011.4.20. # crosslinking with spring createLammpsInput = "createLammpsInput.pl -b " + bgf_file + " -f " + ff_file + " -s " + sname + " -o 'no shake' -t 'min " + crosslink_script_filename + "' > /dev/null" nu.shutup() os.system(createLammpsInput) nu.say() ##### apply a patch after the first step if n_crosslink != 0: patch_crosslink.pair_coeff_patch_w_xlinker("in." + sname, False) else: patch_crosslink.pair_coeff_patch_wo_xlinker("in." + sname, False) f_out_file.flush() # run lammps f_out_file.write("\tRunning LAMMPS simulation on " + sname + "\n") f_out_file.write("\tRunning Lammps: see " + str(os.path.join(temp_dir, sname + ".log")) + "\n") runLammpsParallel = lammps_parallel + " -screen none -in " + input_file + " -log " + sname + ".log" os.system(runLammpsParallel) # load trajectory f_out_file.write("\tLoading Trajectory." + "\n") initial_trj_file = sname + "_nvt.lammpstrj" # update bgf f_out_file.write("\tUpdating BGF file from trajectory." + "\n") ######updatebgf(bgf_file, temp_trj_file, "_trj_updated.bgf", True, silent=True) #updatebgf(bgf_file, initial_trj_file, "_trj_updated.bgf", True, silent=True) LAMMPS_trj2bgf.getLAMMPSTrajectory(bgf_file, initial_trj_file, "_trj_updated.bgf", -1, False, True) ## align bgf periodic box ### added at 110719 #bgftools.periodicMoleculeSort("_trj_updated.bgf", "_aligned.bgf", silent=True) #bgftools.periodicMoleculeSort("_trj_updated.bgf", "_trj_updated.bgf", [], silent=True) # center bgf #nu.shutup(); centerbgf("_trj_updated.bgf", "_centered.bgf", "", "com_center"); nu.say() nu.shutup() os.system("~tpascal/scripts/centerBGF.pl -b _trj_updated.bgf -f " + ff_file + " -s _centered.bgf -c com_center") nu.say() shutil.copy("_centered.bgf", bgf_file) f_out_file.flush() # check the criteria from BGF file ### 1. open the BGF file f_out_file.write("\n* Crosslinking module execution" + "\n") clusterBGF = BgfFile(bgf_file) clusterBGF.renumber() f_out_file.write("\tChecking the connectivities in " + bgf_file + "\n") ### 2. list up all N atoms N_index = [] # REMARK: actually, this is aNo NN_dist_ok = [] for atom in clusterBGF.a: if string.strip(atom.ffType) == "N_3": N_index.append(atom.aNo) """ if "PRI" in atom.rName: N_prisecter[0] += 1 elif "SEC" in atom.rName: N_prisecter[1] += 1 elif "TER" in atom.rName: N_prisecter[2] += 1 """ N_prisecter = bgftools.getAmineGroupInfo(clusterBGF, silent=True) f_out_file.write("\tThe number of 1', 2', and 3' amine: " + str(N_prisecter) + "\n") N_number = len(N_index) criteria = 5.0 ### 3. find N-N pairs which meet # 1st criteria: distance is between 5 and 6 # 2nd criteria: only PRI or SEC amine # 3rd criteria: avoid repeating (removed) for x in range(N_number): for y in range(x + 1, N_number): if clusterBGF.distance(clusterBGF.a2i[N_index[x]], clusterBGF.a2i[N_index[y]]) < 6.0 \ and clusterBGF.distance(clusterBGF.a2i[N_index[x]], clusterBGF.a2i[N_index[y]]) > 5.0 \ and clusterBGF.getAtom(N_index[x]).rName != "TER" \ and clusterBGF.getAtom(N_index[y]).rName != "TER": NN_dist_ok.append([N_index[x], N_index[y]]) if not NN_dist_ok == []: f_out_file.write("\tCrosslinking candidate site: " + str(NN_dist_ok) + "\n" + "\tNow filtering out the candidate.\n") ##### Filtering out the nearest adjacent and the second nearst adjacent cross-linking if NN_dist_ok != []: f_out_file.write( "\tDeleting the nearest adjacent or second nearest adjacent from cross-link candidate site.\n" ) f_out_file.write("\t\tConnectivity test 1:\n") for pair in NN_dist_ok: amine1 = clusterBGF.getAtom(pair[0]) amine2 = clusterBGF.getAtom(pair[1]) amine1_conect = dict() amine2_conect = dict() amine1_conect[amine1.aNo] = amine1.CONECT amine2_conect[amine2.aNo] = amine2.CONECT # 4-step connection for amine1 for j in range(0, 4): d_temp = copy.deepcopy(amine1_conect) for ano in d_temp: for conect_ano in d_temp[ano]: tempatom = clusterBGF.getAtom(conect_ano) amine1_conect[tempatom.aNo] = tempatom.CONECT # 4-step connection for amine2 for j in range(0, 4): d_temp = copy.deepcopy(amine2_conect) for ano in d_temp: for conect_ano in d_temp[ano]: tempatom = clusterBGF.getAtom(conect_ano) amine2_conect[tempatom.aNo] = tempatom.CONECT # now we get a small map for determining the connectivity amine1_conect.update(amine2_conect) # check the connectivity between two N atoms f_out_file.write("\t\t\t* Checking " + str(pair) + " (in residue " + str(amine1.rNo) + " and " + str(amine2.rNo) + "): ") amine1_to_amine2 = bgftools.findShortestPath( amine1_conect, amine1.aNo, amine2.aNo) if not type(amine1_to_amine2) is NoneType: if len(amine1_to_amine2) < 10: f_out_file.write( str(amine1_to_amine2) + "\tAdjacent pair.. will not be cross-linked.\n") NN_dist_ok.remove(pair) else: f_out_file.write( str(amine1_to_amine2) + "\tNot an Adjacent pair.. can be cross-linked.\n") else: f_out_file.write(str(amine1_to_amine2) + ": No path.\n") # if they have same residue then test again f_out_file.write("\tFiltered pair list from test 1: " + str(NN_dist_ok) + "\n") f_out_file.write("\t\tConnectivity test 2:\n") for pair in NN_dist_ok: amine1 = clusterBGF.getAtom(pair[0]) amine2 = clusterBGF.getAtom(pair[1]) amine1_aNo = amine1.aNo amine2_aNo = amine2.aNo amine1_rNo = amine1.rNo amine2_rNo = amine2.rNo tempBGF = bgf.BgfFile() for atom in clusterBGF.a: if atom.rNo == amine1_rNo or atom.rNo == amine2_rNo: tempBGF.addAtom(atom) amine1_to_amine2 = bgftools.getShortestPath( tempBGF, amine1_aNo, amine2_aNo) f_out_file.write("\t\t\t* " + str(pair) + " ( in residue " + str(amine1.rNo) + " and " + str(amine2.rNo) + "): ") if not type(amine1_to_amine2) is NoneType: if len(amine1_to_amine2) < 10: f_out_file.write( str(amine1_to_amine2) + "\tAdjacent pair.. will not be cross-linked.\n") NN_dist_ok.remove(pair) else: f_out_file.write( str(amine1_to_amine2) + "\tNot an Adjacent pair.. can be cross-linked.\n") else: f_out_file.write(str(amine1_to_amine2) + "\n") ##### Filtering out the repeat # Tested with pair_candidate = [[1, 2], [1, 3], [1, 4], [3, 4], [3, 5], [5, 6], [7, 8], [9, 10], [9, 11]] if NN_dist_ok != []: f_out_file.write( "\tRemoving repeated crosslink candidate site: \n") result = [] pair_candidate = copy.deepcopy(NN_dist_ok) pair_candidate_flatten = cu.flatten(pair_candidate) for pair in pair_candidate: if pair_candidate_flatten.count( pair[0]) == 1 and pair_candidate_flatten.count( pair[1]) == 1: # unique pair in the candidate list result.append(pair) pair_candidate.remove( pair ) # unique pairs will be deleted from pair_candidate if pair_candidate != []: # grouping x = pair_candidate[0][0] templist = [] grouped = [] for pair in pair_candidate: if pair[0] == x: templist.append(pair) else: grouped.append(templist) templist = [] x = pair[0] templist.append(pair) grouped.append(templist) # shuffle pairs for group in grouped: random.shuffle(group) random.shuffle(grouped) # selecting a pair from group for group in grouped: pair = random.choice(group) result.append(pair) # removing repeats temp_repeated = [] result_flatten = cu.flatten(result) for element in result_flatten: if result_flatten.count(element) != 1: # if repeated.. temp_repeated.append(element) for element in temp_repeated: templist = [] for pair in result: if element in pair: templist.append(pair) result.remove(pair) if templist != []: selected = random.choice(templist) result.append(selected) NN_dist_ok = result ##### end of filtering f_out_file.write("\t" + str(len(NN_dist_ok)) + " N-N pairs which meets the criteria ( " + str(criteria) + "A ) are found." + "\n") f_out_file.write("\t" + "The following N-N pairs will be crosslinked: " + str(NN_dist_ok) + "\n") f_out_file.flush() ### 4. attach crosslinker # NN_dist_ok is the list that will be get crosslinked if len(NN_dist_ok) > 0: # used for counting intra- and inter-molecular cross-linking during cycle n_intra = 0 n_inter = 0 n_crosslink_in_cycle = 0 # if the required ratio reached, stop cross-linking r = float(n_crosslink) / float(n_initAvailAmineSites) f_out_file.write("degree of crosslinking: " + str(n_crosslink) + " / " + str(n_initAvailAmineSites) + " = " + str(r) + '\n') if r > ratio: f_out_file.write( "************* Requested degree of cross-link reached: EXITING ************" ) NN_dist_ok = [] endFlag = True f_out_file.write("\n* Attaching the crosslinker to " + bgf_file + "\n") for pair in NN_dist_ok: f_out_file.write("\tLinking " + str(pair) + " Nitrogens: ") ##### a) load a crosslinker xlinkerBGF_file = "/home/noische/research/dendrimer/xlinker/20111129/xlinker_new.bgf" #xlinkerBGF = BgfFile("/home/noische/research/dendrimer/structure/xlinker/xlnker.bgf") xlinkerBGF = BgfFile(xlinkerBGF_file) f_out_file.write("\tLoaded the crosslinker file " + str(xlinkerBGF_file) + "\n") head_xlnk = xlinkerBGF.a[0] # head C of xlnk tail_xlnk = xlinkerBGF.a[2] # tail C of xlnk ##### b) select a hydrogen to be detached # /- head_detach_H(M) /- head_xlnk_detach_H(H) /- tail_detach_H(N) # head_N(O) --- head_xlnk(J) --- tail_xlnk(K) --- tail_N(P) # \- tail_xlnk_detach_H(I) # Detach one H atom at random connected with J which is marked as X # Detach one H atom at random connected with K which is marked as Xmar head_N = clusterBGF.getAtom(pair[0]) tail_N = clusterBGF.getAtom(pair[1]) head_N.chain = "O" tail_N.chain = "P" head_N_rNo = head_N.rNo tail_N_rNo = tail_N.rNo # check whether intra- or inter-molecular crosslinking if head_N_rNo == tail_N_rNo: #f_out_file.write("\t\tintra-molecular crosslinking between ") f_out_file.write( "\t\tintra-molecular crosslinking between resNo " + str(head_N.rNo) + " " + str(head_N.rName) + " and " + "resNo " + str(head_N.rNo) + " " + str(tail_N.rName) + " amines\n") f_out_file.write( "\t\tintra-molecular crosslinking will be passed.") n_intra += 1 continue # intramolecular crosslinking is prohibited else: f_out_file.write( "\t\tinter-molecular crosslinking between ") f_out_file.write("resNo " + str(head_N.rNo) + " " + str(head_N.rName) + " and " + "resNo " + str(head_N.rNo) + " " + str(tail_N.rName) + " amines\n") n_inter += 1 n_crosslink_in_cycle += 1 #f_out_file.write("resNo " + str(head_N.rNo) + " " + str(head_N.rName) + " and " + "resNo " + str(head_N.rNo) + " " + str(tail_N.rName) + " amines\n") # intramolecular prohibition # count pri-pri, pri-sec, sec-sec crosslinking number if "PRI" in head_N.rName and "PRI" in tail_N.rName: n_crosslink_pripri += 1 elif "PRI" in head_N.rName and "SEC" in tail_N.rName: n_crosslink_prisec += 1 elif "SEC" in head_N.rName and "PRI" in tail_N.rName: n_crosslink_prisec += 1 elif "SEC" in head_N.rName and "SEC" in tail_N.rName: n_crosslink_secsec += 1 f_out_file.write( "\t\tCumulative PRI-PRI crosslinking number: " + str(n_crosslink_pripri) + "\n") f_out_file.write( "\t\tCumulative PRI-SEC crosslinking number: " + str(n_crosslink_prisec) + "\n") f_out_file.write( "\t\tCumulative SEC-SEC crosslinking number: " + str(n_crosslink_secsec) + "\n") f_out_file.write("\n") f_out_file.write("\t\tChoosing atoms..\n") # change the crosslinker's rNo as same as head_N for atom in xlinkerBGF.a: atom.rNo = head_N_rNo # choose which H atom will be detached from head_N temp_list = [] for ano in head_N.CONECT: if clusterBGF.getAtom(ano).is_hydrogen(): temp_list.append(ano) if temp_list == []: continue head_H_detach_candidate_id = random.choice(temp_list) f_out_file.write("\t\t\tChoosing the hydrogen " + str(head_H_detach_candidate_id) + " from " + str(temp_list) + " attached to " + str(head_N.aNo) + "\n") # choose which H atom will be detached from tail_N temp_list = [] for ano in tail_N.CONECT: if clusterBGF.getAtom(ano).is_hydrogen(): temp_list.append(ano) if temp_list == []: continue tail_H_detach_candidate_id = random.choice(temp_list) f_out_file.write("\t\t\tChoosing the hydrogen " + str(tail_H_detach_candidate_id) + " from " + str(temp_list) + " attached to " + str(tail_N.aNo) + "\n") head_detach_H = clusterBGF.getAtom( head_H_detach_candidate_id) # H which will be detached tail_detach_H = clusterBGF.getAtom( tail_H_detach_candidate_id) # also head_detach_H.chain = "M" tail_detach_H.chain = "N" head_detach_H_charge = head_detach_H.charge tail_detach_H_charge = tail_detach_H.charge # choose which hydrogen will be detached from J temp_list = [] for atom in xlinkerBGF.a: if atom.chain == "X": temp_list.append(atom.aNo) head_xlnk_detach_H_aNo = random.choice(temp_list) head_xlnk_detach_H = xlinkerBGF.getAtom(head_xlnk_detach_H_aNo) head_xlnk_detach_H.chain = "H" head_xlnk_detach_H_charge = head_xlnk_detach_H.charge f_out_file.write("\t\t\tH atom " + str(head_xlnk_detach_H_aNo) + " in the cross-linker will be deleted.\n") ##### c) move xlinker near to the place: let N-H bond is 1.0 A: move C to 1.4 * N-H bond #delta = [ head_detach_H.x - head_xlnk.x, head_detach_H.y - head_xlnk.y, head_detach_H.z - head_xlnk.z ] # old method: moves head_xlnk to head_detach_H #deltax = 1.4 * head_detach_H.x - 0.4 * head_N.x - head_xlnk.x #deltay = 1.4 * head_detach_H.y - 0.4 * head_N.y - head_xlnk.y #deltaz = 1.4 * head_detach_H.z - 0.4 * head_N.z - head_xlnk.z #delta = [deltax, deltay, deltaz] delta = (1.4 * head_detach_H.x - 0.4 * head_N.x - head_xlnk.x, 1.4 * head_detach_H.y - 0.4 * head_N.y - head_xlnk.y, 1.4 * head_detach_H.z - 0.4 * head_N.z - head_xlnk.z ) # new method #moveBGF(xlinkerBGF, -deltax, -deltay, -deltaz ) ##### c2) rotate xlinker toward tail_N and move vec = (tail_N.x - head_N.x, tail_N.y - head_N.y, tail_N.z - head_N.z) xlinkerBGF = rotateBGF(xlinkerBGF, 1, 3, vec, 0) # 0 means return as BgfFile moveBGF(xlinkerBGF, delta[0], delta[1], delta[2]) ##### c3) find which tail_detach_H is the nearst to tail_N temp_list = [] temp_dist = 100 for atom in xlinkerBGF.a: if atom.chain == "Y": temp_list.append(atom.aNo) tail_xlnk_detach_H_aNo = 0 for ano in temp_list: temp = clusterBGF.distance(clusterBGF.a2i[tail_N.aNo], xlinkerBGF.a2i[ano]) if temp < temp_dist: temp_dist = temp tail_xlnk_detach_H_aNo = ano tail_xlnk_detach_H = xlinkerBGF.getAtom(tail_xlnk_detach_H_aNo) tail_xlnk_detach_H.chain = "I" tail_xlnk_detach_H_charge = tail_xlnk_detach_H.charge ##### d) merge clusterBGF = clusterBGF.merge(xlinkerBGF, True) clusterBGF.saveBGF("_xlnk_temp.bgf") clusterBGF = BgfFile("_xlnk_temp.bgf") ##### e) detach head_detach_H and connect head_N-head_xlnk and tail_N-tail_xlnk for atom in clusterBGF.a: if atom.chain == "O": head_N = atom if atom.rName == "XLK": if atom.chain == "J": head_xlnk = atom if atom.chain == "P": tail_N = atom if atom.rName == "XLK": if atom.chain == "K": tail_xlnk = atom if atom.chain == "H": head_xlnk_detach_H = atom if atom.chain == "I": tail_xlnk_detach_H = atom # disconnect Hydrogens from head_N and tail_N f_out_file.write("\t\t\tDisconnecting Hydrogen(aNo: " + str(head_detach_H.aNo) + ") from Nitrogen(aNo: " + str(head_N.aNo) + ") - Head" + "\n") f_out_file.write("\t\t\tDisconnecting Hydrogen(aNo: " + str(tail_detach_H.aNo) + ") from Nitrogen(aNo: " + str(tail_N.aNo) + ") - Tail" + "\n") clusterBGF.disconnect(clusterBGF.a2i[head_N.aNo], clusterBGF.a2i[head_detach_H.aNo]) clusterBGF.disconnect(clusterBGF.a2i[tail_N.aNo], clusterBGF.a2i[tail_detach_H.aNo]) # detach Hydrogens from head_N and tail_N if head_detach_H.aNo > tail_detach_H.aNo: f_out_file.write("\t\t\tDetaching Hydrogen atom: " + str(head_detach_H.aNo) + "\n") clusterBGF.delAtom(clusterBGF.a2i[head_detach_H.aNo]) f_out_file.write("\t\t\tDetaching Hydrogen atom: " + str(tail_detach_H.aNo) + "\n") clusterBGF.delAtom(clusterBGF.a2i[tail_detach_H.aNo]) else: f_out_file.write("\t\t\tDetaching Hydrogen atom: " + str(tail_detach_H.aNo) + "\n") clusterBGF.delAtom(clusterBGF.a2i[tail_detach_H.aNo]) f_out_file.write("\t\t\tDetaching Hydrogen atom: " + str(head_detach_H.aNo) + "\n") clusterBGF.delAtom(clusterBGF.a2i[head_detach_H.aNo]) # disconnect H-J and delete H clusterBGF.disconnect(clusterBGF.a2i[head_xlnk.aNo], clusterBGF.a2i[head_xlnk_detach_H.aNo]) clusterBGF.delAtom(clusterBGF.a2i[head_xlnk_detach_H.aNo]) # disconnect K-I and delete I clusterBGF.disconnect(clusterBGF.a2i[tail_xlnk.aNo], clusterBGF.a2i[tail_xlnk_detach_H.aNo]) clusterBGF.delAtom(clusterBGF.a2i[tail_xlnk_detach_H.aNo]) # connect O-J clusterBGF.connect( clusterBGF.a2i[head_N.aNo], clusterBGF.a2i[head_xlnk.aNo]) # O-J connection # connect K-P clusterBGF.connect( clusterBGF.a2i[tail_N.aNo], clusterBGF.a2i[tail_xlnk.aNo]) # K-P connection # residue update f_out_file.write("\t\t\tUpdating residue information." + "\n") if head_N.rName == "PRI": head_N.rName = "SEC" elif head_N.rName == "SEC": head_N.rName = "TER" if tail_N.rName == "PRI": tail_N.rName = "SEC" elif tail_N.rName == "SEC": tail_N.rName = "TER" # chain update f_out_file.write("\t\t\tUpdating chain information." + "\n") head_N.chain = "V" tail_N.chain = "V" head_xlnk.chain = "A" tail_xlnk.chain = "A" f_out_file.write("\n") # charge f_out_file.write("\t\tCalculating charges..\n") f_out_file.write("\t\t\tCharge of the amine group 1: " + str("{0:8.5f}".format(head_N.charge)) + "\n") f_out_file.write("\t\t\tCharge of the amine group 2: " + str("{0:8.5f}".format(tail_N.charge)) + "\n") f_out_file.write( "\t\t\tCharge of the head C in the cross-link: " + str("{0:8.5f}".format(head_xlnk.charge)) + "\n") f_out_file.write( "\t\t\tCharge of the tail C in the cross-link: " + str("{0:8.5f}".format(tail_xlnk.charge)) + "\n") f_out_file.write( "\t\t\tCharge of the H detached from amine group 1: " + str("{0:8.5f}".format(head_detach_H_charge)) + "\n") f_out_file.write( "\t\t\tCharge of the H detached from amine group 2: " + str("{0:8.5f}".format(tail_detach_H_charge)) + "\n") f_out_file.write( "\t\t\tCharge of the H detached from head C in the cross-link: " + str("{0:8.5f}".format(head_xlnk_detach_H_charge)) + "\n") f_out_file.write( "\t\t\tCharge of the H detached from tail C in the cross-link: " + str("{0:8.5f}".format(tail_xlnk_detach_H_charge)) + "\n") #head_N.charge += head_detach_H_charge #tail_N.charge += tail_detach_H_charge #tail_xlnk.charge += tail_xlnk_detach_H_charge #head_xlnk.charge += head_xlnk_detach_H_charge head_xlnk.charge += head_detach_H_charge tail_xlnk.charge += tail_detach_H_charge head_N.charge += head_xlnk_detach_H_charge tail_N.charge += tail_xlnk_detach_H_charge #leftoverCharge = clusterBGF.charge() / 2.0 #head_N.charge -= leftoverCharge #tail_N.charge -= leftoverCharge leftoverCharge = clusterBGF.charge() f_out_file.write("\t\t\tExcess Charge: " + str("{0:8.5f}".format(leftoverCharge)) + "\n") f_out_file.write( "\t\t\tExcess Charge will be added to head N atom.\n") head_N.charge -= leftoverCharge f_out_file.write("\t\tModified charge of the amine group 1: " + str("{0:8.5f}".format(head_N.charge)) + "\n") f_out_file.write("\t\tModified charge of the amine group 2: " + str("{0:8.5f}".format(tail_N.charge)) + "\n") f_out_file.write("\t\tThe charge of the system is " + str("{0:8.5f}".format(clusterBGF.charge())) + "\n") f_out_file.write("" + "\n") n_crosslink += 1 f_out_file.flush() ##### The end of the crosslinking step ##### Minimization f_out_file.flush() clusterBGF.renumber() f_out_file.write("\tSaving the crosslinked file to " + "_linked.bgf" + "\n") clusterBGF.saveBGF("_linked.bgf") f_out_file.write( "\n* Crosslinking step is finished. Entering minimizing step." + "\n") # remove bad contacts #f_out_file.write("\tRemoving bad contacts after crosslinking." + "\n") #nu.shutup(); removebadcontacts("_linked.bgf", "_removed.bgf", 2.0); nu.say(); # create input for minimization #createLammpsInput = "createLammpsInput.pl -b _removed.bgf -f " + ff_file + " -s minimization -o 'no shake' -t 'min' > /dev/null" createLammpsInput = "createLammpsInput.pl -b _linked.bgf -f " + ff_file + " -s minimization -o 'no shake' -t 'min' > /dev/null" runLammpsParallel = lammps_parallel + " -screen none -in in.minimization -log minimization.log" f_out_file.write("\tMaking LAMMPS input script for minimization." + "\n") nu.shutup() os.system(createLammpsInput) nu.say() # patch for minimization ## added at 110524 if n_crosslink != 0: patch_crosslink.pair_coeff_patch_w_xlinker( "in.minimization", False) else: patch_crosslink.pair_coeff_patch_wo_xlinker( "in.minimization", False) f_out_file.write("\tApplied a patch on in.minimization file.\n") # run lammps f_out_file.write("\tMinimizing the structure." + "\n") f_out_file.write("\tRunning Lammps: see " + str(os.path.join(temp_dir, "minimization.log")) + "\n") os.system(runLammpsParallel) # load trajectory f_out_file.write( "\tLoading Trajectory from the minimization result." + "\n") update_trj_file = "minimization.min.lammpstrj" # update bgf f_out_file.write( "\tUpdating BGF file from the minimization result." + "\n") ###updatebgf("_removed.bgf", "_temp.lammpstrj", "_trj_updated.bgf", silent=True) ###updatebgf("_linked.bgf", "_temp.lammpstrj", "_trj_updated.bgf", True, silent=True) #updatebgf("_linked.bgf", "minimization_min.lammpstrj", "_trj_updated.bgf", True, silent=True) LAMMPS_trj2bgf.getLAMMPSTrajectory("_linked.bgf", "minimization_min.lammpstrj", "_trj_updated.bgf", -1, False, True) # align bgf periodic box ### added at 110719 #bgftools.periodicMoleculeSort("_trj_updated.bgf", "_trj_updated.bgf", [], silent=True) # center bgf f_out_file.write("\tAligning BGF file." + "\n") #nu.shutup(); centerbgf("_trj_updated.bgf", "_centered.bgf", "", "com_center"); nu.say() nu.shutup() os.system("~tpascal/scripts/centerBGF.pl -b _trj_updated.bgf -f " + ff_file + " -s _centered.bgf -c com_center") nu.say() shutil.copy("_centered.bgf", suffix + str(i + 1) + ".bgf") # store the number of cross-link n_crosslink_per_cycle.append([i, len(NN_dist_ok)]) f_out_file.write("" + "\n") f_out_file.write("--- " + str(len(NN_dist_ok)) + " times of crosslinking occured at the cycle " + str(i) + "\n") f_out_file.write( "--- " + str(n_intra) + " times of intra-molecular crosslinking occured at the cycle " + str(i) + "\n") f_out_file.write( "--- " + str(n_inter) + " times of inter-molecular crosslinking occured at the cycle " + str(i) + "\n") f_out_file.write("--- End of the crosslinking process for cycle " + str(i) + "\n") f_out_file.write("--- See " + suffix + str(i + 1) + ".bgf for output. \n" + "\n") f_out_file.flush() if endFlag: break else: n_crosslink_per_cycle.append([i, 0]) f_out_file.write("--- Passing the crosslinking step in cycle " + str(i) + "\n" + "\n") f_out_file.write( "--- 0 times of crosslinking occured at the cycle " + str(i) + "\n") f_out_file.write( "--- 0 times of intra-molecular crosslinking occured at the cycle " + str(i) + "\n") f_out_file.write( "--- 0 times of inter-molecular crosslinking occured at the cycle " + str(i) + "\n") shutil.copy(bgf_file, suffix + str(i + 1) + ".bgf") f_out_file.flush() if endFlag: break t2 = time.time() f_out_file.write("Elapsed time for the cycle: " + str(t2 - t1) + " sec\n") ##### The end of the crosslinking cycle (1ps) f_out_file.write("\n\nJob completed at " + time.asctime(time.gmtime()) + "\n") f_out_file.write("Output structure on " + suffix + "_out.bgf" + "\n") f_out_file.write("The number of crosslinking through this job: " + str(n_crosslink) + "\n") f_out_file.write("\n\n*** Statistics for Crosslinking ***\n") f_out_file.write("Cycle\tFrequency\n") for i in n_crosslink_per_cycle: f_out_file.write(str(i[0]) + "\t" + str(i[1]) + "\n") f_out_file.close() shutil.copy(suffix + str(t + 1) + ".bgf", suffix + "_out.bgf")
# minimization nu.shutup() createLammpsInput = "~tpascal/scripts/createLammpsInput.pl" + " -b temp.bgf " + " -f /home/noische/ff/DREIDING2.21.ff" + " -s temp " + " -o 'no shake' -t min " + " > /dev/null" _ = os.system(createLammpsInput) in_file = "in.temp" data_file = "data.temp" os.system("sed -i 's/dielectric 1/dielectric 72/' " + in_file) os.system("sed -i 's/kspace_style pppm 0.0001/kspace_style none/' " + in_file) os.system("sed -i 's/boundary p p p/boundary s s s/' " + in_file) os.system("sed -i 's/1.0e-4 1.0e-4 500 5000/1.0e-6 1.0e-6 5000 50000/' " + in_file) #os.system("sed -i 's/2.0 multi/5.0 multi/' " + in_file) os.system( "sed -i 's/lj\/charmm\/coul\/long\/opt 7.5 8.50000/lj\/cut\/coul\/debye 0.142 10/' " + in_file) os.system("sed -i 's/every 2 delay 4/every 1 delay 0/' " + in_file) #os.system("sed -i 's/0.000000 50.000000/-10.000000 10.000000/' " + data_file) os.system("sed -i 's/0 # X/0 0 # X/' " + data_file) os.system("sed -i 's/Impropers//' " + data_file) runLammps = mpi_command + lammps_command + " -in in.temp -log lammps.log >> temp.log" _ = os.system(runLammps) LAMMPS_trj2bgf.getLAMMPSTrajectory("temp.bgf", "temp.min.lammpstrj", "temp.bgf", -1, False, True) mybgf = bgf.BgfFile('temp.bgf') nu.say() mybgf.saveBGF(out_file)
def anneal(bgf_dir, ff_file, suffix, out_file): # *** variables *** # used for log file output output = "" # initialization #t1 = 0; t2 = 0; # clock for measuring time for a cycle curr_dir = os.path.abspath(bgf_dir) temp_dir = curr_dir + "/anneal/" # LAMMPS executive command: defined in ~/scripts/clusterSettings.py #lammps_parallel = mpi_command + " -np 8 " + lammps_command lammps_parallel = "/home/tpascal/codes/openmpi/1.4.3/bin/mpirun -np 8 " + lammps_command # Annealing procedure anneal_proc = "/home/noische/script/dat/in.lammps.anneal" # get BGF file list in the directory pei_files = glob.glob(bgf_dir + "/*.bgf") pei_files.sort() os.chdir(bgf_dir) #print("pei_files: ", pei_files) # for file in the directory for file in pei_files: ### working filename print("*** Working on %s" % file) filename = file.split(".bgf")[0] print("filename: " + filename) # centerBGF print("Centering %s" % file) cmd_centerbgf = "/home/tpascal/scripts/centerBGF.pl -b " + file + " -f " + ff_file + " -s " + filename + ".center.bgf" + " -c com_center" nu.shutup() os.system(cmd_centerbgf) nu.say() filename = filename.split("/")[-1] print("filename: " + filename) # createLammps: with finite options # Note that the script refers /home/noische/script/data/in.lammps.anneal for the annealing process cmd_createLammpsInput = "/home/tpascal/scripts/createLammpsInput.pl -b " + filename + ".center.bgf" + " -f " + ff_file + " -t /home/noische/script/data/in.lammps.anneal " + " -s " + filename + " -o finite " nu.shutup() os.system(cmd_createLammpsInput) nu.say() # patch in.lammps file print("Patching infile") cmd_sed = "sed -i 's/2 5.0 90/2 4.5 5.0 90/' in." + filename nu.shutup() os.system(cmd_sed) nu.say() # patch data.lammps file print("Patching datafile") cmd_mv = "mv data." + filename + " data." + filename + ".bak" os.system(cmd_mv) file1 = open("data." + filename, "w") file2 = open("data." + filename + ".bak") while 1: line = file2.readline() if not line: break if "xlo" in line: line = "-50.0 50.0 xlo xhi\n" file1.write(line) elif "ylo" in line: line = "-50.0 50.0 ylo yhi\n" file1.write(line) elif "zlo" in line: line = "-50.0 50.0 zlo zhi\n" file1.write(line) elif "# X N_3 C_3 X" in line: line = line.replace("# X N_3 C_3 X", "0 # X N_3 C_3 X") file1.write(line) elif "# X C_3 C_3 X" in line: line = line.replace("# X C_3 C_3 X", "0 # X C_3 C_3 X") file1.write(line) else: file1.write(line) # run print("Running simulation") lammps_thermo_log_file = filename + ".anneal.log" cmd_lammps = lammps_parallel + " -log " + lammps_thermo_log_file nu.shutup() os.system(cmd_lammps) nu.say() # read potential energy from file # in in.lammps.anneal: "poteng" is the averaged value of potential energy after cooldown print("Treating Potential Energy") poteng = [] poteng_files = glob.glob(filename + "*poteng") for poteng_file in poteng_files: f_poteng_file = open(poteng_file) while 1: line = f_poteng_file.readline() if not line: break if not line[0] == "#": parse = line.split() poteng.append([parse[0], float(parse[1])]) poteng = nu.removeRepeat(poteng) ### print potential energy for i in poteng: print(i) # when is the minimum energy during annealing? min_poteng = 0 min_poteng_step = 0 # usually poteng < 0 for i in poteng: if i[1] < min_poteng: min_poteng_step = i[0] min_poteng = i[1] # convert that timestep into BGF trj_file = filename + ".lammpstrj" anneal_output_bgf_file = filename + ".annealed.bgf" result = LAMMPS_trj2bgf.getLAMMPSTrajectory(pei_file, trj_file, anneal_output_bgf_file, min_poteng_step, False) print("The lowest potential energy structure found") # create LAMMPS input for annealed BGF file # run the NVT simulation at 300 K # average the potential energy # average Rg # write data: filename, the minimum structure, avr_poteng, avr_Rg """