From ac887d189651b6841a1c56b44facd1abcf45e4be Mon Sep 17 00:00:00 2001 From: Chris Maffeo <cmaffeo2@illinois.edu> Date: Tue, 21 Aug 2018 16:01:58 -0500 Subject: [PATCH] Fixed psf writer for atomsitic simulations; add NAMD configuration writer; fixed bug with ENM --- arbdmodel.py | 152 ++++++++++++++++++++++++++++++++++++++++++++++-- segmentmodel.py | 16 ++++- 2 files changed, 161 insertions(+), 7 deletions(-) diff --git a/arbdmodel.py b/arbdmodel.py index 4d0a60c..a270c5b 100644 --- a/arbdmodel.py +++ b/arbdmodel.py @@ -545,7 +545,7 @@ class PdbModel(Transformable, Parent): counter = 0 else: fh.write(" ") - fh.write("\n") + fh.write("\n" if counter == 0 else "\n\n") ## Write out angles angles = self.get_angles() @@ -559,7 +559,7 @@ class PdbModel(Transformable, Parent): counter = 0 else: fh.write(" ") - fh.write("\n") + fh.write("\n" if counter == 0 else "\n\n") ## Write out dihedrals dihedrals = self.get_dihedrals() @@ -572,8 +572,8 @@ class PdbModel(Transformable, Parent): fh.write("\n") counter = 0 else: - fh.write(" ") - fh.write("\n") + fh.write(" ") + fh.write("\n" if counter == 0 else "\n\n") ## Write out impropers impropers = self.get_impropers() @@ -587,7 +587,17 @@ class PdbModel(Transformable, Parent): counter = 0 else: fh.write(" ") - fh.write("\n") + fh.write("\n" if counter == 0 else "\n\n") + + fh.write("\n{:>8d} !NDON: donors\n\n\n".format(0)) + fh.write("\n{:>8d} !NACC: acceptors\n\n\n".format(0)) + fh.write("\n 0 !NNB\n\n") + natoms = len(self.particles) + for i in range(natoms//8): + fh.write(" 0 0 0 0 0 0 0 0\n") + for i in range(natoms-8*(natoms//8)): + fh.write(" 0") + fh.write("\n\n 1 0 !NGRP\n\n") class ArbdModel(PdbModel): @@ -960,6 +970,137 @@ component "data" value 3 item = tuple(int(p.idx) for p in ex) fh.write("EXCLUDE %d %d\n" % item) + def set_dimensions_from_structure( self, padding_factor=1.5, isotropic=False ): + ## TODO: cache coordinates using numpy arrays for quick min/max + raise(NotImplementedError) + + def write_namd_configuration( self, output_prefix, num_steps = 1e6, + output_directory = 'output', + update_dimensions=True, extrabonds=True ): + + format_data = self.__dict__.copy() # get parameters from System object + + format_data['extrabonds'] = """extraBonds on +extraBondsFile $prefix.exb +""" if extrabonds else "" + + if self.useTclForces: + format_data['margin'] = "" + format_data['tcl_forces'] = """tclForces on +tclForcesScript $prefix.forces.tcl +""" + else: + format_data['margin'] = """margin 30 +""" + format_data['tcl_forces'] = "" + + if update_dimensions: + self.set_dimensions_from_structure() + + for k,v in zip('XYZ', self.dimensions): + format_data['origin'+k] = -v*0.5 + format_data['cell'+k] = v + + format_data['prefix'] = output_prefix + format_data['num_steps'] = int(num_steps//12)*12 + format_data['output_directory'] = output_directory + filename = '{}.namd'.format(output_prefix) + + with open(filename,'w') as fh: + fh.write(""" +set prefix {prefix} +set nLast 0; # increment when continueing a simulation +set n [expr $nLast+1] +set out {output_directory}/$prefix-$n +set temperature 300 + +structure $prefix.psf +coordinates $prefix.pdb + +outputName $out +XSTfile $out.xst +DCDfile $out.dcd + +############################################################# +## SIMULATION PARAMETERS ## +############################################################# + +# Input +paraTypeCharmm on +parameters charmm36.nbfix/par_all36_na.prm +parameters charmm36.nbfix/par_water_ions_na.prm + +wrapAll off + +# Force-Field Parameters +exclude scaled1-4 +1-4scaling 1.0 +switching on +switchdist 8 +cutoff 10 +pairlistdist 12 +{margin} + +# Integrator Parameters +timestep 2.0 ;# 2fs/step +rigidBonds all ;# needed for 2fs steps +nonbondedFreq 1 +fullElectFrequency 3 +stepspercycle 12 + +# PME (for full-system periodic electrostatics) +PME no +PMEGridSpacing 1.2 + +# Constant Temperature Control +langevin on ;# do langevin dynamics +# langevinDamping 1 ;# damping coefficient (gamma); used in original study +langevinDamping 0.1 ;# less friction for faster relaxation +langevinTemp $temperature +langevinHydrogen off ;# don't couple langevin bath to hydrogens + +# output +useGroupPressure yes +xstFreq 4800 +outputEnergies 4800 +dcdfreq 4800 +restartfreq 48000 + +############################################################# +## EXTRA FORCES ## +############################################################# + +# ENM and intrahelical extrabonds +{extrabonds} +{tcl_forces} + +############################################################# +## RUN ## +############################################################# + +# Continuing a job from the restart files +cellBasisVector1 {cellX} 0 0 +cellBasisVector2 0 {cellY} 0 +cellBasisVector3 0 0 {cellZ} + +if {{$nLast == 0}} {{ + temperature 300 + fixedAtoms on + fixedAtomsForces on + fixedAtomsFile $prefix.pdb + fixedAtomsCol B + minimize 2400 + + fixedAtoms off + minimize 2400 +}} else {{ + bincoordinates {output_directory}/$prefix-$nLast.restart.coor + binvelocities {output_directory}/$prefix-$nLast.restart.vel +}} + +run {num_steps:d} +""".format(**format_data)) + def atomic_simulate(self, outputPrefix, outputDirectory='output'): if self.cacheUpToDate == False: # TODO: remove cache? self._countParticleTypes() @@ -968,4 +1109,5 @@ component "data" value 3 if outputDirectory == '': outputDirectory='.' self.writePdb( outputPrefix + ".pdb" ) self.writePsf( outputPrefix + ".psf" ) + self.write_namd_configuration( outputPrefix, output_directory = outputDirectory ) os.sync() diff --git a/segmentmodel.py b/segmentmodel.py index bd12bac..3a6a458 100644 --- a/segmentmodel.py +++ b/segmentmodel.py @@ -30,7 +30,7 @@ TODO: + remove performance bottlenecks - test for large systems + assign sequence - - ENM + + ENM - rework Location class - remove recursive calls - document @@ -2244,7 +2244,7 @@ class SegmentModel(ArbdModel): if nt2 is not None: other.append((nt2,'stack')) nt2 = nt2.basepair - if nt2 is not None: + if nt2 is not None and strand_piece.is_fwd: other.append((nt2,'cross')) for nt2,key in other: @@ -2392,6 +2392,18 @@ proc calcforces {} { } """) + def set_dimensions_from_structure( self, padding_factor=1.5, isotropic=False ): + positions = [] + for s in self.segments: + positions.append(s.contour_to_position(0)) + positions.append(s.contour_to_position(0.5)) + positions.append(s.contour_to_position(1)) + positions = np.array(positions) + dx,dy,dz = [(np.max(positions[:,i])-np.min(positions[:,i])+30)*padding_factor for i in range(3)] + if isotropic: + dx = dy = dz = max((dx,dy,dz)) + self.dimensions = [dx,dy,dz] + def _generate_atomic_model(self, scale=1): self.children = self.strands first_atomic_index = 0 -- GitLab