def main(): print("Reading the PSF file"); # Read the PSF file psf = app.CharmmPsfFile('g1_25mm.psf'); boxsize = 5 # Boxsize in nm psf.setBox(boxsize*nanometer, boxsize*nanometer, boxsize*nanometer); print("Reading the pdb file") pdb = app.PDBFile('g1_25mm.pdb'); # Load the parameter set lib = 'toppar/' #params = app.CharmmParameterSet('toppar/top_all36_cgenff.rtf','toppar/par_all36_cgenff.prm','toppar/cgenff3.0.1/top_all36_cgenff.rtf','toppar/cgenff3.0.1/par_all36_cgenff.prm','g1_new.str','toppar_water_ions.str') params = app.CharmmParameterSet('toppar/cgenff3.0.1/top_all36_cgenff.rtf','toppar/cgenff3.0.1/par_all36_cgenff.prm','g1_new.str','toppar_water_ions.str') #platform = openmm.Platform.getPlatformByName('CUDA'); platform = openmm.Platform.getPlatformByName('Reference'); # Creating the system system = psf.createSystem(params, nonbondedMethod=app.PME, nonbondedCutoff=1.2*nanometer, switchDistance=1.0*nanometer, ewaldErrorTolerance= 0.0001, constraints=app.HBonds); # Thermostat @ 298 K system.addForce(openmm.AndersenThermostat(298*kelvin, 1/picosecond)) # adding the barostat for now system.addForce(openmm.MonteCarloBarostat(1*bar, 298*kelvin)); integrator = openmm.VerletIntegrator(0.001*picoseconds) simulation = app.Simulation(psf.topology, system, integrator, platform) simulation.context.setPositions(pdb.getPositions()) simulation.minimizeEnergy(maxIterations = 500) #nsavcrd = 10000 # save coordinates every 10 ps #nstep = 2000000 # write dcd files every 2 ps #nprint = 2000 # report every 2 ps nsavcrd = 10 # save coordinates every 10 ps nstep = 200 # write dcd files every 2 ps nprint = 20 # report every 2 ps firstDcdStep = nsavcrd ; # Reporters dcd = app.DCDReporter('g1_new.dcd', nsavcrd) dcd._dcd = app.DCDFile(dcd._out, simulation.topology, simulation.integrator.getStepSize(), firstDcdStep, nsavcrd) simulation.reporters.append(dcd) simulation.reporters.append(app.StateDataReporter('g1_new.out', nprint, step=True, kineticEnergy=True, potentialEnergy=True, totalEnergy=True, temperature=True, volume=True, speed=True)) simulation.step(nstep) simulation.reporters.pop() simulation.reporters.pop() dcd._out.close()
def readCharmmParameters(folder, listfile=None): from glob import glob import os if listfile is None: files = glob(os.path.join(folder, '*')) elif isinstance(listfile, list): files = [os.path.join(folder, f) for f in listfile] return app.CharmmParameterSet(*files)
def main(): print("Reading the PSF file"); # Read the PSF file psf = app.CharmmPsfFile('holo_neutr.psf'); boxsize = 4.895883 # Boxsize in nm psf.setBox(boxsize*nanometer, boxsize*nanometer, boxsize*nanometer); print("Reading the pdb file") pdb = app.PDBFile('holo_neutr.pdb') # Load the parameter set lib = 'toppar/' params = app.CharmmParameterSet( 'toppar/cgenff3.0.1/top_all36_cgenff.rtf', 'toppar/cgenff3.0.1/par_all36_cgenff.prm', 'g1_new.str','oah_groups.str', 'toppar_water_ions.str' ) platform = openmm.Platform.getPlatformByName('CUDA'); #isPeriodic = False #isShortSim = False isShortSim = True isPeriodic = False #if not isPeriodic : # isShortSim = True; # Creating the system if (isPeriodic) : system = psf.createSystem(params, nonbondedMethod=app.PME, nonbondedCutoff=1.2*nanometer, switchDistance=1.0*nanometer, ewaldErrorTolerance= 0.0001, constraints=app.HBonds ); else : system = psf.createSystem(params, # nonbondedMethod=app.PME, nonbondedCutoff=1.2*nanometer, switchDistance=1.0*nanometer, ewaldErrorTolerance= 0.0001, constraints=app.HBonds ); #Retrieve the nonbonded force forces = { force.__class__.__name__ : for force in system.getForces()}: nbforce = forces['NonbondedForce']
def _read_charmm_params(filename): charmmExt = ['rtf', 'prm', 'str'] paramFiles = () for line in open(filename, 'r'): if line.find("#") >= 0: line = line.split("#")[0] parfile = line.strip() if len(parfile) > 0: ext = parfile.lower().split('.')[-1] if ext in charmmExt: paramFiles += (parfile,) return app.CharmmParameterSet(*paramFiles)
b = float(tokens[3]) * u.angstroms if tokens[1] == 'C': c = float(tokens[3]) * u.angstroms if tokens[1] == 'FFTX': fftx = int(tokens[3]) if tokens[1] == 'FFTY': ffty = int(tokens[3]) if tokens[1] == 'FFTZ': fftz = int(tokens[3]) psf = app.CharmmPsfFile(os.path.join(prefix, 'step3_pbcsetup.psf')) # Taken from output of CHARMM run psf.setBox(a, b, c) crd = app.CharmmCrdFile(os.path.join(prefix, 'step3_pbcsetup.crd')) params = app.CharmmParameterSet( os.path.join(prefix, 'toppar/par_all36_prot.prm'), os.path.join(prefix, 'toppar/par_all36_na.prm'), os.path.join(prefix, 'toppar/toppar_water_ions.str')) system = psf.createSystem(params, nonbondedMethod=app.PME, nonbondedCutoff=12 * u.angstroms, switchDistance=10 * u.angstroms) for force in system.getForces(): if isinstance(force, mm.CustomNonbondedForce): #print('CustomNonbondedForce: %s' % force.getUseSwitchingFunction()) #print('LRC? %s' % force.getUseLongRangeCorrection()) force.setUseLongRangeCorrection(False) elif isinstance(force, mm.NonbondedForce): #print('NonbondedForce: %s' % force.getUseSwitchingFunction()) #print('LRC? %s' % force.getUseDispersionCorrection())
# load the charmm file for the topology psf = omma.CharmmPsfFile(charmm_psf_path) # load the coordinates pdb = mdj.load_pdb(pdb_path) # convert the mdtraj topology to a json one top_str = mdtraj_to_json_topology(pdb.topology) # write the JSON topology out with open(json_top_path, mode='w') as json_wf: json_wf.write(top_str) # to use charmm forcefields get your parameters params = omma.CharmmParameterSet(*charmm_param_paths) # set the box size lengths and angles lengths = [8.2435*unit.nanometer for i in range(3)] angles = [90*unit.degree for i in range(3)] psf.setBox(*lengths, *angles) # create a system using the topology method giving it a topology and # the method for calculation system = psf.createSystem(params, nonbondedMethod=omma.CutoffPeriodic, nonbondedCutoff=1.0 * unit.nanometer, constraints=omma.HBonds) # we want to have constant pressure barostat = omm.MonteCarloBarostat(1.0*unit.atmosphere, 300.0*unit.kelvin, 50)
def main(n_runs, n_cycles, steps, n_walkers, n_workers=1, debug_prints=False, seed=None): ## Load objects needed for various purposes # load a json string of the topology with open(json_top_path, mode='r') as rf: sEH_TPPU_system_top_json = rf.read() # an openmm.State object for setting the initial walkers up with open(omm_state_path, mode='rb') as rf: omm_state = pickle.load(rf) ## set up the OpenMM Runner # load the psf which is needed for making a system in OpenMM with # CHARMM force fields psf = omma.CharmmPsfFile(charmm_psf_path) # set the box size lengths and angles lengths = [CUBE_LENGTH for i in range(3)] angles = [CUBE_ANGLE for i in range(3)] psf.setBox(*lengths, *angles) # charmm forcefields parameters params = omma.CharmmParameterSet(*charmm_param_paths) # create a system using the topology method giving it a topology and # the method for calculation system = psf.createSystem(params, nonbondedMethod=omma.CutoffPeriodic, nonbondedCutoff=NONBONDED_CUTOFF, constraints=omma.HBonds) # make this a constant temperature and pressure simulation at 1.0 # atm, 300 K, with volume move attempts every 50 steps barostat = omm.MonteCarloBarostat(PRESSURE, TEMPERATURE, VOLUME_MOVE_FREQ) # add it as a "Force" to the system system.addForce(barostat) # make an integrator object that is constant temperature integrator = omm.LangevinIntegrator(TEMPERATURE, FRICTION_COEFFICIENT, STEP_SIZE) # set up the OpenMMRunner with the system runner = OpenMMRunner(system, psf.topology, integrator, platform=PLATFORM) # the initial state, which is used as reference for many things init_state = OpenMMState(omm_state) ## Make the distance Metric # load the crystal structure coordinates crystal_traj = mdj.load_pdb(pdb_path) # get the atoms in the binding site according to the crystal structure bs_idxs = binding_site_atoms(crystal_traj.top, LIG_RESID, crystal_traj.xyz[0]) lig_idxs = ligand_idxs(crystal_traj.top, LIG_RESID) prot_idxs = protein_idxs(crystal_traj.top) # make the distance metric with the ligand and binding site # indices for selecting atoms for the image and for doing the # alignments to only the binding site. All images will be aligned # to the reference initial state unb_distance = UnbindingDistance(lig_idxs, bs_idxs, init_state) ## Make the resampler # make a Wexplore resampler with default parameters and our # distance metric resampler = WExploreResampler(distance=unb_distance, init_state=init_state, max_n_regions=MAX_N_REGIONS, max_region_sizes=MAX_REGION_SIZES, pmin=PMIN, pmax=PMAX) ## Make the Boundary Conditions # makes ref_traj and selects lingand_atom and protein atom indices # instantiate a revo unbindingboudaryconditiobs ubc = UnbindingBC(cutoff_distance=CUTOFF_DISTANCE, initial_state=init_state, topology=crystal_traj.topology, ligand_idxs=lig_idxs, receptor_idxs=prot_idxs) ## make the reporters # WepyHDF5 # make a dictionary of units for adding to the HDF5 # open it in truncate mode first, then switch after first run hdf5_reporter = WepyHDF5Reporter( hdf5_path, mode='w', # the fields of the State that will be saved in the HDF5 file save_fields=SAVE_FIELDS, # the topology in a JSON format topology=sEH_TPPU_system_top_json, # the resampler and boundary # conditions for getting data # types and shapes for saving resampler=resampler, boundary_conditions=ubc, # the units to save the fields in units=dict(UNITS), # sparse (in time) fields sparse_fields=dict(SPARSE_FIELDS), # sparse atoms fields main_rep_idxs=np.concatenate((lig_idxs, prot_idxs)), all_atoms_rep_freq=ALL_ATOMS_SAVE_FREQ) dashboard_reporter = WExploreDashboardReporter( dashboard_path, mode='w', step_time=STEP_SIZE.value_in_unit(unit.second), max_n_regions=resampler.max_n_regions, max_region_sizes=resampler.max_region_sizes, bc_cutoff_distance=ubc.cutoff_distance) setup_reporter = SetupReporter(setup_state_path, mode='w') restart_reporter = RestartReporter(restart_state_path, mode='w') reporters = [ hdf5_reporter, dashboard_reporter, setup_reporter, restart_reporter ] ## The work mapper # we use a mapper that uses GPUs work_mapper = WorkerMapper(worker_type=OpenMMGPUWorker, num_workers=n_workers) ## Combine all these parts and setup the simulation manager # set up parameters for running the simulation # initial weights init_weight = 1.0 / n_walkers # a list of the initial walkers init_walkers = [ Walker(OpenMMState(omm_state), init_weight) for i in range(n_walkers) ] # Instantiate a simulation manager sim_manager = Manager(init_walkers, runner=runner, resampler=resampler, boundary_conditions=ubc, work_mapper=work_mapper, reporters=reporters) ### RUN the simulation for run_idx in range(n_runs): print("Starting run: {}".format(run_idx)) sim_manager.run_simulation(n_cycles, steps, debug_prints=True) print("Finished run: {}".format(run_idx))
def run_simulation(gro_file='conf.gro', psf_file='topol.psf', prm_file='ff.prm', dt=0.001, T=300, P=1, tcoupl='langevin', pcoupl='iso', cos=0, restart=None): print('Building system...') gro = oh.GroFile(gro_file) psf = oh.OplsPsfFile(psf_file, periodicBoxVectors=gro.getPeriodicBoxVectors()) prm = app.CharmmParameterSet(prm_file) system = psf.createSystem(prm, nonbondedMethod=app.PME, nonbondedCutoff=1.2 * nm, constraints=app.HBonds, rigidWater=True, verbose=True) is_drude = any(type(f) == mm.DrudeForce for f in system.getForces()) ### apply TT damping for CLPol force field donors = [atom.idx for atom in psf.atom_list if atom.attype == 'HO'] if is_drude and len(donors) > 0: print('Add TT damping between HO and Drude dipoles') ttforce = oh.CLPolCoulTT(system, donors) print(ttforce.getEnergyFunction()) print('Initializing simulation...') if tcoupl == 'langevin': if is_drude: print('Drude Langevin thermostat: 5.0 /ps, 20 /ps') integrator = mm.DrudeLangevinIntegrator(T * kelvin, 5.0 / ps, 1 * kelvin, 20 / ps, dt * ps) integrator.setMaxDrudeDistance(0.02 * nm) else: print('Langevin thermostat: 1.0 /ps') integrator = mm.LangevinIntegrator(T * kelvin, 1.0 / ps, dt * ps) elif tcoupl == 'nose-hoover': if is_drude: print( 'Drude temperature-grouped Nose-Hoover thermostat: 10 /ps, 40 /ps' ) else: print('Nose-Hoover thermostat: 10 /ps') from velocityverletplugin import VVIntegrator integrator = VVIntegrator(T * kelvin, 10 / ps, 1 * kelvin, 40 / ps, dt * ps) integrator.setUseMiddleScheme(True) integrator.setMaxDrudeDistance(0.02 * nm) else: raise Exception('Available thermostat: langevin, nose-hoover') if pcoupl != 'no': oh.apply_mc_barostat(system, pcoupl, P, T) if cos != 0: try: integrator.setCosAcceleration(cos) except: raise Exception( 'Cosine acceleration not compatible with this integrator') _platform = mm.Platform.getPlatformByName('CUDA') _properties = {'CudaPrecision': 'mixed'} sim = app.Simulation(psf.topology, system, integrator, _platform, _properties) if restart: sim.loadCheckpoint(restart) sim.currentStep = round( sim.context.getState().getTime().value_in_unit(ps) / dt / 10) * 10 sim.context.setTime(sim.currentStep * dt) append = True else: sim.context.setPositions(gro.positions) sim.context.setVelocitiesToTemperature(T * kelvin) append = False sim.reporters.append( app.DCDReporter('dump.dcd', 10000, enforcePeriodicBox=False, append=append)) sim.reporters.append(oh.CheckpointReporter('cpt.cpt', 10000)) sim.reporters.append( oh.GroReporter('dump.gro', 1000, logarithm=True, append=append)) sim.reporters.append( oh.StateDataReporter(sys.stdout, 1000, box=False, volume=True, append=append)) if is_drude: sim.reporters.append( oh.DrudeTemperatureReporter('T_drude.txt', 10000, append=append)) if cos != 0: sim.reporters.append( oh.ViscosityReporter('viscosity.txt', 1000, append=append)) return sim
def init_openmm(self, integrator_params=None, create_system_params=None): """ Method that initiates OpenMM by creating Parameters ---------- integrator_params : dict Keyword arguments passed to the simtk.openmm.openmm.LangevinIntegrator create_system_params : dict Keyword arguments passed to simtk.openmm.app.amberprmtopfile.createSystem Returns ------- system : simtk.openmm.openmm.System OpenMM system created. """ from simtk.openmm import XmlSerializer assert self.topology_format is not None, "No topology format was provided." assert self.crd_format is not None, "No coordinate format was provided." if self.topology_format.upper() in ["AMBER", "GROMACS", "CHARMM"]: assert self.top_file is not None, "Topology format is {} but no topology file was provided.".format( self.topology_format) else: raise NotImplementedError( "Topology format {} is not known.".format( self.topology_format)) assert self.crd_file is not None, "create_system flag is True but no crd_file was provided." if self.platform_name is None: logging.info("No platform set. Will use reference.") self.platform_name = "Reference" else: assert self.platform_name in [ "Reference", "CPU", "OpenCL", "CUDA" ], """create_system flag is True but no correct platform was provided.""" # Read topology if self.topology_format.upper() == "AMBER": if self.topology is None: top = app.AmberPrmtopFile(self.top_file) self.topology = top.topology elif self.topology_format.upper() == "GROMACS": if self.topology is None: top = app.GromacsTopFile(self.top_file) self.topology = top.topology elif self.topology_format.upper() == "CHARMM": if self.topology is None: top = app.CharmmPsfFile(self.top_file) self.topology = top.topology charmm_params = app.CharmmParameterSet('charmm.rtf', self.charmm_param_file) else: raise NotImplementedError( "Topology format {} is not currently supported.".format( self.topology_format)) # Read coordinate file if self.crd_format.upper() == "AMBER": crd = app.AmberInpcrdFile(self.crd_file) elif self.crd_format.upper() == "GROMACS": crd = app.GromacsGroFile(self.crd_file) elif self.crd_format.upper() == "CHARMM": crd = app.CharmmCrdFile(self.crd_file) elif self.crd_format.upper() == "PDB": crd = app.PDBFile(self.crd_file) else: raise NotImplementedError( "Coordinate format {} is not currently supported.".format( self.crd_format)) if self.system is None: if self.xml_file is None: assert create_system_params is not None, "No settings to create the system were provided." logging.info("Creating OpenMM System from {} file.".format( self.topology_format)) if self.topology_format.upper() == "CHARMM": self.system = top.createSystem(charmm_params, **create_system_params) else: self.system = top.createSystem(**create_system_params) else: logging.info("Creating OpenMM System from XML file.") xml_file = open(self.xml_file) self.system = XmlSerializer.deserializeSystem(xml_file.read()) xml_file.close() if self.integrator is None: assert integrator_params is not None, "No settings to create the integrator were provided." self.integrator = openmm.LangevinIntegrator( integrator_params['temperature'], integrator_params["frictionCoeff"], integrator_params["stepSize"]) logging.info("Creating OpenMM integrator.") if self.platform is None: self.platform = openmm.Platform.getPlatformByName( self.platform_name) logging.info("Creating OpenMM platform.") if self.context is None: self.context = openmm.Context(self.system, self.integrator, self.platform) logging.info("Creating OpenMM Context.") # Set positions in context self.context.setPositions(crd.positions) return self.system
paralib = '/pubhome/qyfu02/lck_drude/run1/drude_toppar_2018_10/' if ftype == 'c36': timestep = 0.002 paralib = '/home/qiuzy/paralib/charmm/toppar_c36_jul17/' # Read PSF File psf = app.CharmmPsfFile(chfpre + '.psf') psf.setBox(latta, lattb, lattc, 90.00 * degree, 90.00 * degree, 90.00 * degree) # crd = app.CharmmCrdFile(chfpre+'.crd') crd = PDBFile(chfpre + '.pdb') # Load the parameter set. if ftype == 'drude': params = app.CharmmParameterSet(paralib + 'toppar_drude_master_protein_2013f.str') if ftype == 'c36': params = app.CharmmParameterSet(paralib + 'top_all36_prot.rtf', paralib + 'par_all36_prot.prm', paralib + 'toppar_water_ions.str') # Instantiate the system platform = mm.Platform.getPlatformByName('CUDA') if ftype == 'drude': system = psf.createSystem(params, nonbondedMethod=ff.PME, nonbondedCutoff=1.20, switchDistance=1.00, ewaldErrorTolerance=0.0001, constraints=ff.HBonds)
def compare_energies(system_name, pdb_filename, psf_filename, ffxml_filenames, toppar_filenames, box_vectors_filename=None, system_kwargs=None, tolerance=1e-5, units=u.kilojoules_per_mole, write_serialized_xml=False): """ Compare energies between (pdb, psf, toppar) loaded via ParmEd and (pdb, ffxml) loaded by OpenMM ForceField Parameters ---------- system_name : str Name of the test system pdb_filename : str Name of PDB file that should contain CRYST entry and PDB format compliant CONECT records for HETATM residues. psf_filename : str CHARMM PSF file ffxml_filenames : list of str List of OpenMM ffxml files toppar_filenames : list of CHARMM toppar filenames to load into CharmmParameterSet List of CHARMM toppar files box_vectors_filename : str, optional, default=None If specified, read box vectors from a file like step2.1_waterbox.prm system_kwargs : dict, optional, default=None Keyword arguments to pass to CharmmPsfFile.createSystem() and ForceField.CreateSystem() when constructing System objects for energy comparison tolerance : float, optional, default=1e-5 Relative energy discrepancy tolerance units : simtk.unit.Unit Unit to use for energy comparison write_serialized_xml : bool, optional, default=False If True, will write out serialized System XML files for OpenMM systems to aid debugging. """ is_periodic = False if (system_kwargs is not None) and ('nonbondedMethod' in system_kwargs) and ( system_kwargs['nonbondedMethod'] in [app.CutoffPeriodic, app.PME]): is_periodic = True # Load PDB file pdbfile = app.PDBFile(pdb_filename) # Read box vectors if box_vectors_filename: box_vectors = read_box_vectors(box_vectors_filename) pdbfile.topology.setPeriodicBoxVectors(box_vectors) else: box_vectors = pdbfile.topology.getPeriodicBoxVectors() # Load CHARMM system through OpenMM openmm_toppar = app.CharmmParameterSet(*toppar_filenames) openmm_psf = app.CharmmPsfFile(psf_filename) # Set box vectors if is_periodic: openmm_psf.setBox(box_vectors[0][0], box_vectors[1][1], box_vectors[2][2]) openmm_system = openmm_psf.createSystem(openmm_toppar, **system_kwargs) openmm_structure = openmm.load_topology(openmm_psf.topology, openmm_system, xyz=pdbfile.positions) #openmm_energies = openmm.energy_decomposition_system(openmm_structure, openmm_system, nrg=units) #print('OpenMM CHARMM loader energy components : %s' % str(openmm_energies)) openmm_total_energy = compute_potential(openmm_system, pdbfile.positions) / units # Load CHARMM system through ParmEd parmed_toppar = CharmmParameterSet(*toppar_filenames) parmed_structure = CharmmPsfFile(psf_filename) #structure.load_parameters(toppar) parmed_structure.positions = pdbfile.positions # Set box vectors if is_periodic: parmed_structure.box = (box_vectors[0][0] / u.angstroms, box_vectors[1][1] / u.angstroms, box_vectors[2][2] / u.angstroms, 90, 90, 90) parmed_system = parmed_structure.createSystem(parmed_toppar, **system_kwargs) #parmed_energies = openmm.energy_decomposition_system(parmed_structure, parmed_system, nrg=units) #print('ParmEd CHARMM loader energy components : %s' % str(parmed_energies)) parmed_total_energy = compute_potential(parmed_system, pdbfile.positions) / units # Delete H-H bonds from waters and retreive updated topology and positions modeller = app.Modeller(openmm_psf.topology, pdbfile.positions) hhbonds = [ b for b in modeller.topology.bonds() if b[0].element == app.element.hydrogen and b[1].element == app.element.hydrogen ] modeller.delete(hhbonds) ffxml_topology = modeller.topology # OpenMM system with ffxml ff = app.ForceField(*ffxml_filenames) ffxml_system = ff.createSystem(ffxml_topology, **system_kwargs) ffxml_structure = openmm.load_topology(ffxml_topology, ffxml_system, xyz=pdbfile.positions) #ffxml_energies = openmm.energy_decomposition_system(ffxml_structure, ffxml_system, nrg=units) #print('ffxml energy components : %s' % str(ffxml_energies)) ffxml_total_energy = compute_potential(ffxml_system, pdbfile.positions) / units write_serialized_xml = True # DEBUG if write_serialized_xml: print('Writing serialized XML files...') write_serialized_system(system_name + '.charmm.system.xml', openmm_system) write_serialized_system(system_name + '.parmed.system.xml', parmed_system) write_serialized_system(system_name + '.openmm.system.xml', ffxml_system) print('-' * 100) print('') print('OpenMM CHARMM reader total energy: %14.3f' % openmm_total_energy) print('ParmEd CHARMM reader total energy: %14.3f' % parmed_total_energy) print('OPENMM ffxml total energy: %14.3f' % ffxml_total_energy) print('TOTAL ERROR: %14.3f' % (ffxml_total_energy - openmm_total_energy)) print('') print('-' * 100) # TODO : Automate comparison return # calc rel energies and assert rel_energies = [] for i, j in zip(ffxml_energies, parmed_energies): if i[0] != j[0]: raise Exception('Mismatch in energy tuples naming.') if abs(i[1]) > NEARLYZERO: rel_energies.append((i[0], abs((i[1] - j[1]) / i[1]))) else: if abs(j[1]) > NEARLYZERO: raise AssertionError( 'One of the CHARMM %s energies (%s) for %s is zero, ' 'while the corresponding OpenMM energy is non-zero' % (system_name, i[0], ffxml)) rel_energies.append((i[0], 0)) dihedrals_done = False for i in rel_energies: if i[0] != 'PeriodicTorsionForce': if i[1] > tolerance: raise AssertionError( '%s energies (%s, %f) outside of allowed tolerance (%f) for %s' % (system_name, i[0], i[1], tolerance, ffxml)) else: if not dihedrals_done: if i[1] > tolerance: raise AssertionError( '%s energies (%s, %f) outside of allowed tolerance (%f) for %s' % (system_name, i[0], i[1], tolerance, ffxml)) dihedrals_done = True else: #impropers if i[1] > improper_tolerance: raise AssertionError( '%s energies (%s-impropers, %f) outside of allowed tolerance (%f) for %s' % (system_name, i[0], i[1], improper_tolerance, ffxml)) # logging if not no_log: charmm_energies_log = dict() omm_energies_log = dict() rel_energies_log = dict() charmm_energies_log['ffxml_name'] = ffxml charmm_energies_log['test_system'] = system_name charmm_energies_log['data_type'] = 'CHARMM' charmm_energies_log['units'] = units omm_energies_log['ffxml_name'] = ffxml omm_energies_log['test_system'] = system_name omm_energies_log['data_type'] = 'OpenMM' omm_energies_log['units'] = units rel_energies_log['ffxml_name'] = ffxml rel_energies_log['test_system'] = system_name rel_energies_log['data_type'] = 'abs((CHARMM-OpenMM)/CHARMM)' dihedrals_done = False for item in amber_energies: if item[0] == 'PeriodicTorsionForce' and not dihedrals_done: charmm_energies_log['PeriodicTorsionForce_dihedrals'] = item[1] dihedrals_done = True elif item[0] == 'PeriodicTorsionForce' and dihedrals_done: charmm_energies_log['PeriodicTorsionForce_impropers'] = item[1] elif item[0] == 'CMMotionRemover': continue else: charmm_energies_log[item[0]] = item[1] dihedrals_done = False for item in omm_energies: if item[0] == 'PeriodicTorsionForce' and not dihedrals_done: omm_energies_log['PeriodicTorsionForce_dihedrals'] = item[1] dihedrals_done = True elif item[0] == 'PeriodicTorsionForce' and dihedrals_done: omm_energies_log['PeriodicTorsionForce_impropers'] = item[1] elif item[0] == 'CMMotionRemover': continue else: omm_energies_log[item[0]] = item[1] dihedrals_done = False for item in rel_energies: if item[0] == 'PeriodicTorsionForce' and not dihedrals_done: rel_energies_log['PeriodicTorsionForce_dihedrals'] = item[1] dihedrals_done = True elif item[0] == 'PeriodicTorsionForce' and dihedrals_done: rel_energies_log['PeriodicTorsionForce_impropers'] = item[1] elif item[0] == 'CMMotionRemover': continue else: rel_energies_log[item[0]] = item[1] logger.log(charmm_energies_log) logger.log(omm_energies_log) logger.log(rel_energies_log)
prefix = '/tmp/' # temporary directory to write dcd # Read the CHARMM PSF file psf = app.CharmmPsfFile('csptm.psf') boxsize = 6.9 # boxsize in nanometer psf.setBox(boxsize * nanometer, boxsize * nanometer, boxsize * nanometer) # Get the coordinates from the CHARMM crd file crd = app.CharmmCrdFile('csptm.crd') # pdb = app.PDBFile('csptm.pdb') # in case a pdb file instead of crd is used # Load the parameter set. lib = 'toppar/' # path of force field topology and parameter files params = app.CharmmParameterSet(lib + 'top_all36_prot.rtf', lib + 'par_all36m_prot.prm', lib + 'toppar_water_ions.str') # params = app.CharmmParameterSet(lib+'top_all36_prot.rtf', lib+'par_all36m_prot.prm', lib+'toppar_n010water_ions.str') # in case alternative water model is used to sample more extended states of IDPs platform = mm.Platform.getPlatformByName('CUDA') # make sure the GPU is used system = psf.createSystem(params, nonbondedMethod=app.PME, nonbondedCutoff=1.2 * nanometer, switchDistance=1.0 * nanometer, ewaldErrorTolerance=0.0001, constraints=app.HBonds) system.addForce(mm.AndersenThermostat(300 * kelvin, 1 / picosecond)) # thermostat system.addForce(mm.MonteCarloBarostat(1 * bar, 300 * kelvin)) # barostat
Because we are using OpenMM as our MD engine, we need to setup the MD molecular system in the format required by OpenMM. The format/object used by OpenMM for a molecular system happens to be a class called System. Therefore, we will prepare our MD molecular system as an OpenMM System. When we prepare the OpenMM system, we will add two CustomTorsionForces so that we can add biasing potentials to the system in the following umbrella sampling. ''' import simtk.openmm.app as omm_app import simtk.openmm as omm import simtk.unit as unit import math ## read CHARMM force field for proteins charmm_toppar = omm_app.CharmmParameterSet("./data/top_all36_prot.rtf", "./data/par_all36_prot.prm") ## read psf and pdb file of dialanine psf = omm_app.CharmmPsfFile("./output/dialanine.psf") pdb = omm_app.PDBFile('./data/dialanine.pdb') ## create a OpenMM system based on psf of dialanine and CHARMM force field system = psf.createSystem(charmm_toppar, nonbondedMethod=omm_app.NoCutoff) ## add harmonic biasing potentials on two dihedrals of dialanine (psi, phi) in the OpenMM system ## for dihedral psi bias_torsion_psi = omm.CustomTorsionForce( "0.5*k_psi*dtheta^2; dtheta = min(tmp, 2*pi-tmp); tmp = abs(theta - psi)") bias_torsion_psi.addGlobalParameter("pi", math.pi) bias_torsion_psi.addGlobalParameter("k_psi", 1.0) bias_torsion_psi.addGlobalParameter("psi", 0.0)
def gen_simulation(gro_file, psf_file, prm_file, T, P, pcoupl='iso'): print('Building system...') gro = app.GromacsGroFile(gro_file) psf = OplsPsfFile(psf_file, periodicBoxVectors=gro.getPeriodicBoxVectors()) prm = app.CharmmParameterSet(prm_file) system = psf.createSystem(prm, nonbondedMethod=app.PME, ewaldErrorTolerance=1E-5, nonbondedCutoff=1.2 * nm, constraints=app.HBonds, rigidWater=True, verbose=True) if not psf.is_drude: print('\tLangevin thermostat: 1.0/ps') integrator = mm.LangevinIntegrator(T * kelvin, 1.0 / ps, 0.001 * ps) else: print('\tDual Langevin thermostat: 10/ps, 50/ps') integrator = mm.DrudeLangevinIntegrator(T * kelvin, 10 / ps, 1 * kelvin, 50 / ps, 0.001 * ps) integrator.setMaxDrudeDistance(0.02 * nm) if pcoupl == 'iso': print('\tIsotropic barostat') system.addForce(mm.MonteCarloBarostat(P * bar, T * kelvin, 25)) elif pcoupl == 'xyz': print('\tAnisotropic barostat') system.addForce( mm.MonteCarloAnisotropicBarostat([P * bar] * 3, T * kelvin, True, True, True, 25)) elif pcoupl == 'xy': print('\tAnisotropic Barostat only for X and Y') system.addForce( mm.MonteCarloAnisotropicBarostat([P * bar] * 3, T * kelvin, True, True, False, 25)) else: print('\tNo barostat') print('Initializing simulation...') platform = mm.Platform.getPlatformByName('CUDA') properties = {'CudaPrecision': 'mixed'} sim = app.Simulation(psf.topology, system, integrator, platform, properties) sim.context.setPositions(gro.positions) sim.context.setVelocitiesToTemperature(T * kelvin) sim.reporters.append(GroReporter('dump.gro', 10000)) sim.reporters.append(app.DCDReporter('dump.dcd', 1000)) sim.reporters.append( app.StateDataReporter(sys.stdout, 500, step=True, temperature=True, potentialEnergy=True, kineticEnergy=True, volume=True, density=True, elapsedTime=True, speed=True, separator='\t')) state = sim.context.getState(getEnergy=True) print('Energy: ' + str(state.getPotentialEnergy())) return sim
def run_omm(options): inp = Config(options.input) dt = float(inp.getWithDefault("timestep", 4)) * u.femtosecond temperature = float(inp.getWithDefault("temperature", 300)) * u.kelvin thermostattemperature = float( inp.getWithDefault("thermostattemperature", 300)) * u.kelvin logPeriod = 1 * u.picosecond trajectoryPeriod = int(inp.getWithDefault("trajectoryperiod", 25000)) * dt run_steps = int(inp.run) basename = "output" trajectory_file = basename + ".dcd" if 'PME' in inp and not inp.getboolean('PME'): nonbondedMethod = app.NoCutoff else: nonbondedMethod = app.PME nonbondedCutoff = float(inp.getWithDefault("cutoff", 9.0)) * u.angstrom switchDistance = float(inp.getWithDefault("switchdistance", 7.5)) * u.angstrom frictionCoefficient = float(inp.getWithDefault("thermostatdamping", 0.1)) / u.picosecond endTime = run_steps * dt util.check_openmm() if options.platform is None: print("Selecting best platform:") req_platform_name = util.get_best_platform() else: print(f"Requesting platform {options.platform}") req_platform_name = options.platform req_platform = mm.Platform.getPlatformByName(req_platform_name) req_properties = {} # {'UseBlockingSync':'true'} if options.device is not None and 'DeviceIndex' in req_platform.getPropertyNames( ): print(" Setting DeviceIndex = " + options.device) req_properties['DeviceIndex'] = options.device if options.precision is not None and 'Precision' in req_platform.getPropertyNames( ): print(" Setting Precision = " + options.precision) req_properties['Precision'] = options.precision # Same logic as https://software.acellera.com/docs/latest/acemd3/reference.html if dt > 2 * u.femtosecond: hydrogenMass = 4 * u.amu constraints = app.AllBonds rigidWater = True elif dt > 0.5 * u.femtosecond: hydrogenMass = None constraints = app.HBonds rigidWater = True else: hydrogenMass = None constraints = None rigidWater = False print(f""" Host: {socket.gethostname()} Date: {datetime.datetime.now().ctime()} Timestep: {dt} Constraints: {constraints} Rigid water: {rigidWater} Nonbonded: {nonbondedMethod} Hydrogen mass repartitioning: {hydrogenMass} """) _printPluginInfo() if 'parmfile' in inp: print(f"Creating an AMBER system...") if 'structure' in inp: print("Warning: 'structure' given but ignored for AMBER") prmtop = app.AmberPrmtopFile(inp.parmfile) system = prmtop.createSystem(nonbondedMethod=nonbondedMethod, nonbondedCutoff=nonbondedCutoff, switchDistance=switchDistance, constraints=constraints, hydrogenMass=hydrogenMass, rigidWater=rigidWater) topology = prmtop.topology else: print(f"Creating a CHARMM system...") psf = app.CharmmPsfFile(inp.structure) params = app.CharmmParameterSet(inp.parameters, permissive=True) psf.setBox(50. * u.angstrom, 50. * u.angstrom, 50. * u.angstrom) # otherwise # refuses # PME system = psf.createSystem(params, nonbondedMethod=nonbondedMethod, nonbondedCutoff=nonbondedCutoff, switchDistance=switchDistance, constraints=constraints, hydrogenMass=hydrogenMass, rigidWater=rigidWater) topology = psf.topology if 'barostat' in inp and inp.getboolean('barostat'): pressure = float(inp.barostatpressure) * u.bar print(f"Enabling barostat at {pressure}...") system.addForce(mm.MonteCarloBarostat(pressure, thermostattemperature)) if 'plumedfile' in inp: print("Attempting to load PLUMED plugin...") from openmmplumed import PlumedForce plines = util.plumed_parser(inp.plumedfile) system.addForce(PlumedForce(plines)) integrator = mm.LangevinIntegrator(thermostattemperature, frictionCoefficient, dt) integrator.setConstraintTolerance(1e-5) simulation = app.Simulation(topology, system, integrator, req_platform, req_properties) ctx = simulation.context platform = ctx.getPlatform() print(f"Got platform {platform.getName()} with properties:") for prop in platform.getPropertyNames(): print(f" {prop}\t\t{platform.getPropertyValue(ctx,prop)}") print("") resuming = False if os.path.exists(checkpoint_file): with open(checkpoint_file, 'rb') as cf: ctx.loadCheckpoint(cf.read()) # ctx.loadCheckpoint(str(checkpoint_file)) util.round_state_time(ctx, 10 * dt) print(f"Successfully loaded {checkpoint_file}, resuming simulation...") resuming = True else: print( f"File {checkpoint_file} absent, starting simulation from the beginning..." ) coords = util.get_coords(inp) ctx.setPositions(coords) if not resuming: (boxa, boxb, boxc) = util.get_box_size(inp) ctx.setPeriodicBoxVectors(boxa, boxb, boxc) if 'minimize' in inp: print(f'Minimizing for max {inp.minimize} iterations...') simulation.minimizeEnergy(maxIterations=int(inp.minimize)) simulation.saveState(f"miniomm_minimized.xml") else: if 'binvelocities' in inp: print(f"Reading velocities from NAMDBin: " + inp.binvelocities) vels = NAMDBin(inp.binvelocities).getVelocities() ctx.setVelocities(vels) else: print(f"Resetting thermal velocities at {temperature}") ctx.setVelocitiesToTemperature(temperature) # ------------------------------------------------------- print("") inp.printWarnings() # ------------------------------------------------------- print("") startTime = ctx.getState().getTime() startTime_f = startTime.in_units_of(u.nanoseconds).format("%.3f") endTime_f = endTime.in_units_of(u.nanoseconds).format("%.3f") remaining_steps = round((endTime - startTime) / dt) remaining_ns = remaining_steps * dt.value_in_unit(u.nanosecond) print( f"Current simulation time is {startTime_f}, running up to {endTime_f}." ) print( f"Will run for {remaining_steps} timesteps = {remaining_ns:.3f} ns...") print("") log_every = util.every(logPeriod, dt) save_every = util.every(trajectoryPeriod, dt) if remaining_steps % save_every != 0: raise ValueError( "Remaining steps is not a multiple of trajectoryperiod") util.add_reporters(simulation, trajectory_file, log_every, save_every, remaining_steps, resuming, checkpoint_file) # ---------------------------------------- simulation.saveState(f"miniomm_pre.xml") # ---------------------------------------- simulation.step(remaining_steps) # ---------------------------------------- simulation.saveState(f"miniomm_post.xml") final_state = simulation.context.getState(getPositions=True, getVelocities=True) final_coor = final_state.getPositions(asNumpy=True) NAMDBin(final_coor).write_file(f"{basename}.coor") final_box = final_state.getPeriodicBoxVectors(asNumpy=True) write_xsc(f"{basename}.xsc", remaining_steps, final_state.getTime(), final_box) # ---------------------------------------- print('Done!') return
import simtk.openmm as mm import simtk.openmm.app as app from simtk import unit # input topology, psf, and force field files generated from CHARMM-GUI Solution Builder print('Parsing system topology') topology = app.CharmmPsfFile('step3_charmm2omm.psf') parameters = app.CharmmParameterSet('top_all36_prot.rtf',\ 'par_all36_prot.prm' ,'toppar_water_ions.str') print('Parsing system coordinates') # for using PBC in OpenMM, we need to make sure that # the origin of the sytem is at (0,0,0) # and that the extremum of the system is at (Lx, Ly, Lz) coord = app.PDBFile('step3_pbcsetup.pdb') # translate the coordinates, we'll use numpy here. import numpy as np xyz = np.array(coord.positions/unit.nanometer) xyz[:,0] -= np.amin(xyz[:,0]) xyz[:,1] -= np.amin(xyz[:,1]) xyz[:,2] -= np.amin(xyz[:,2]) coord.positions = xyz*unit.nanometer print('Constructing sytem') # set periodic box vectors topology.setBox(7.5*unit.nanometer, 7.5*unit.nanometer, 7.5*unit.nanometer) # use PME for long-range electrostatics, cutoff for short-range interactions # constrain H-bonds with RATTLE, constrain water with SETTLE system = topology.createSystem(parameters, nonbondedMethod=app.PME, nonbondedCutoff=1.2*unit.nanometers, constraints=app.HBonds, rigidWater=True, ewaldErrorTolerance=0.0005)
def main(): print("Reading the PSF file") # Read the PSF file #psf = app.CharmmPsfFile('g1_25mm.psf'); psf = app.CharmmPsfFile('holo_neutr.psf') boxsize = 4.895883 # Boxsize in nm psf.setBox(boxsize * nanometer, boxsize * nanometer, boxsize * nanometer) print("Reading the pdb file") #pdb = app.PDBFile('g1_25mm.pdb'); #pdb = app.PDBFile('md_298k_100ns.pdb') pdb = app.PDBFile('holo_neutr.pdb') # Load the parameter set lib = 'toppar/' #params = app.CharmmParameterSet('toppar/top_all36_cgenff.rtf','toppar/par_all36_cgenff.prm','toppar/cgenff3.0.1/top_all36_cgenff.rtf','toppar/cgenff3.0.1/par_all36_cgenff.prm','g1_new.str','toppar_water_ions.str') #params = app.CharmmParameterSet('toppar/cgenff3.0.1/top_all36_cgenff.rtf','toppar/cgenff3.0.1/par_all36_cgenff.prm','g1_new.str','toppar_water_ions.str') params = app.CharmmParameterSet('toppar/cgenff3.0.1/top_all36_cgenff.rtf', 'toppar/cgenff3.0.1/par_all36_cgenff.prm', 'g1_new.str', 'oah_groups.str', 'toppar_water_ions.str') platform = openmm.Platform.getPlatformByName('CUDA') isShortSim = False #isShortSim = True isPeriodic = True #isPeriodic = False #if not isPeriodic : # isShortSim = True; # Creating the system if (isPeriodic): print("PME is being used") system = psf.createSystem(params, nonbondedMethod=app.PME, nonbondedCutoff=1.2 * nanometer, switchDistance=1.0 * nanometer, ewaldErrorTolerance=0.0001, constraints=app.HBonds) else: print("PME is not being used") system = psf.createSystem( params, # nonbondedMethod=app.PME, nonbondedCutoff=1.2 * nanometer, switchDistance=1.0 * nanometer, ewaldErrorTolerance=0.0001, constraints=app.HBonds) #for force in system.getForces(): # print(force, force.usesPeriodicBoundaryConditions()) # Thermostat @ 298 K #system.addForce(openmm.AndersenThermostat(298*kelvin, 1/picosecond)) # adding the barostat for now #system.addForce(openmm.MonteCarloBarostat(1*bar, 298*kelvin)); # adding positional restriants if isPeriodic: force = openmm.CustomExternalForce( "k*periodicdistance(x, y, z, x0, y0, z0)^2") else: force = openmm.CustomExternalForce("k*((x-x0)^2+(y-y0)^2+(z-z0)^2)") #force = openmm.CustomExternalForce("k*periodicdistance(x, y, z, x0, y0, z0)^2"); force.addGlobalParameter("k", 0.1 * kilocalories_per_mole / angstroms**2) force.addPerParticleParameter("x0") force.addPerParticleParameter("y0") force.addPerParticleParameter("z0") topology = pdb.getTopology() positions = pdb.getPositions() #for atom in topology.atoms(): # print(atom) host = [] guest = [] for res in topology.residues(): if res.name == 'OAH': for atom in res.atoms(): host.append(atom.index) force.addParticle(atom.index, positions[atom.index]) #force.addParticle(atom.index, (0, 0, 0)*nanometers) if res.name == 'GOA': for atom in res.atoms(): guest.append(atom.index) system.addForce(force) print("Does customExternalForce use periodic boundary condition : ", force.usesPeriodicBoundaryConditions()) # adding restraint between the host and guest # this will be inside the umbrella sampling loop host_guest_centroid_force = openmm.CustomCentroidBondForce( 2, "0.5*k*(distance(g1,g2)-d0)^2") host_guest_centroid_force.addGlobalParameter( "k", 10.0 * kilocalories_per_mole / angstroms**2) #d0_global_parameter_index = force.addGlobalParameter("d0", 2.0*angstroms); #d0_perBond_parameter_index = force.addPerBondParameter("d0", 2.0*angstroms); d0_perBond_parameter_index = host_guest_centroid_force.addPerBondParameter( "d0") group1 = host_guest_centroid_force.addGroup(host) group2 = host_guest_centroid_force.addGroup(guest) host_guest_bond = host_guest_centroid_force.addBond([group1, group2]) host_guest_centroid_force.setBondParameters(host_guest_bond, [group1, group2], [20 * angstroms]) system.addForce(host_guest_centroid_force) #sys.exit(0) """ # Restrain along z axis # adding positional restriants if isPeriodic : z_force = openmm.CustomExternalForce("k*periodicdistance(x, x0)^2"); else : z_force = openmm.CustomExternalForce("k*((x-x0)^2+(y-y0)^2)"); #force = openmm.CustomExternalForce("k*periodicdistance(x, y, z, x0, y0, z0)^2"); z_force.addGlobalParameter("k", 0.1*kilocalories_per_mole/angstroms**2); z_force.addPerParticleParameter("x0"); z_force.addPerParticleParameter("y0"); for res in topology.residues(): if res.name == 'GOA' : for atom in res.atoms(): pos = list(positions[atom.index]) print(pos[2]) z_force.addParticle(atom.index, [pos[0], pos[1]]) system.addForce(z_force) """ # langevin integrator integrator = openmm.LangevinIntegrator( 298 * kelvin, # Temperature 1.0 / picoseconds, # Friction coefficient 0.001 * picoseconds # Time step ) #integrator = openmm.VerletIntegrator(0.001*picoseconds); simulation = app.Simulation(psf.topology, system, integrator, platform) simulation.context.setPositions(pdb.getPositions()) #currentState = simulation.context.getState(getPositions=True) #pdbr = app.PDBReporter("pdbreport.pdb",1); #pdbr.report(simulation, currentState) print("Minimizing...") simulation.minimizeEnergy(maxIterations=2000) print("Equilibrating...") simulation.context.setVelocitiesToTemperature(298 * kelvin) #currentState = simulation.context.getState(getPositions=True) #pdbr = app.PDBReporter("pdbreport_after_min.pdb",1); #pdbr.report(simulation, currentState) #pdbr = app.PDBReporter("pdbreport_after_step1.pdb",1); nsavcrd = 10000 # save coordinates every 10 ps nprint = 2000 # report every 2 ps if isShortSim: nstep = 20000 # run the simulation for 0.2ns else: nstep = 2000000 # run the simulation for 2ns firstDcdStep = nsavcrd # Reporters dcdReportInterval = 10000 # save coordinates every 10 ps dcd = app.DCDReporter('umb_3.dcd', dcdReportInterval) dcd._dcd = app.DCDFile(dcd._out, simulation.topology, simulation.integrator.getStepSize(), firstDcdStep, nsavcrd) stateReporter = app.StateDataReporter('umb_3.out', nprint, step=True, kineticEnergy=True, potentialEnergy=True, totalEnergy=True, temperature=True, volume=True, speed=True) simulation.reporters.append(dcd) simulation.reporters.append(stateReporter) #simulation.reporters.append(pdbr); #simulation.reporters.append(app.StateDataReporter('umb.out', nprint, step=True, kineticEnergy=True, potentialEnergy=True, totalEnergy=True, temperature=True, volume=True, speed=True)) # Run the simulation print("Simulation begins ...") #simulation.step(1) #sys.exit(0) for i in range(15): print("Simulation for umbrella : ", i) host_guest_centroid_force.setBondParameters(host_guest_bond, [group1, group2], [(5 + 3 * i) * angstroms]) #force.setGlobalParameterDefaultValue(d0_global_parameter_index, (2+i)*angstroms) host_guest_centroid_force.updateParametersInContext(simulation.context) print("host guest bond parameters", host_guest_centroid_force.getBondParameters(host_guest_bond)) #serialized = openmm.XmlSerializer.serialize(simulation.system) #of = open("serial_sim_"+str(i)+".xml",'w'); #of.write(serialized); #of.close(); #simulation.saveState("state_"+str(i)+".xml"); simulation.step(nstep) simulation.reporters.pop() simulation.reporters.pop() dcd._out.close()
def run_simulation(nstep, gro_file='conf.gro', psf_file='topol.psf', prm_file='ff.prm', dt=0.001, T=333, voltage=0, screen=0, restart=None): print('Building system...') gro = oh.GroFile(gro_file) lz = gro.getUnitCellDimensions()[2].value_in_unit(nm) psf = oh.OplsPsfFile(psf_file, periodicBoxVectors=gro.getPeriodicBoxVectors()) prm = app.CharmmParameterSet(prm_file) system = psf.createSystem(prm, nonbondedMethod=app.PME, nonbondedCutoff=1.2 * nm, constraints=app.HBonds, rigidWater=True, verbose=True) nbforce = next(f for f in system.getForces() if type(f) == mm.NonbondedForce) ljforce = next(f for f in system.getForces() if type(f) == mm.CustomNonbondedForce) bforce = next(f for f in system.getForces() if type(f) == mm.HarmonicBondForce) is_drude = any(type(f) == mm.DrudeForce for f in system.getForces()) ### assign groups atoms = list(psf.topology.atoms()) group_mos = [atom.index for atom in atoms if atom.residue.name == 'MoS2'] group_mos_core = [ i for i in group_mos if not atoms[i].name.startswith('D') ] group_img = [atom.index for atom in atoms if atom.residue.name == 'IMG'] group_ils = [ atom.index for atom in atoms if atom.residue.name not in ['MoS2', 'IMG'] ] group_ils_drude = [i for i in group_ils if atoms[i].name.startswith('D')] image_pairs = list(zip(group_ils, group_img)) print('Assigning groups...') print(' Number of atoms in group %10s: %i' % ('mos', len(group_mos))) print(' Number of atoms in group %10s: %i' % ('ils', len(group_ils))) print(' Number of atoms in group %10s: %i' % ('img', len(group_img))) print(' Number of atoms in group %10s: %i' % ('mos_core', len(group_mos_core))) ### apply TT damping for CLPol force field donors = [atom.idx for atom in psf.atom_list if atom.attype == 'HO'] if is_drude and len(donors) > 0: print('Add TT damping between HO and Drude dipoles') ttforce = oh.CLPolCoulTT(system, donors) print(ttforce.getEnergyFunction()) ### assign image charges for parent, image in image_pairs: q, _, _ = nbforce.getParticleParameters(parent) nbforce.setParticleParameters(image, -q, 1, 0) ### eliminate the interactions between images and MoS2 ljforce.addInteractionGroup(set(group_img), set(group_ils)) ljforce.addInteractionGroup(set(group_mos + group_ils), set(group_mos + group_ils)) ### apply screening between ils and images if screen != 0: print('Add screening between ILs and images...') tforce = mm.CustomNonbondedForce( '-%.6f*q1*q2/r*(1+0.5*screen*r)*exp(-screen*r);' 'screen=%.4f' % (oh.CONST.ONE_4PI_EPS0, screen)) print(tforce.getEnergyFunction()) tforce.addPerParticleParameter('q') for i in range(system.getNumParticles()): q, _, _ = nbforce.getParticleParameters(i) tforce.addParticle([q]) tforce.setNonbondedMethod(mm.CustomNonbondedForce.CutoffPeriodic) tforce.setCutoffDistance(1.2 * nm) tforce.addInteractionGroup(set(group_ils), set(group_img)) tforce.setForceGroup(9) system.addForce(tforce) ### restrain the movement of MoS2 cores (Drude particles are free if exist) print('Add restraint for MoS2...') oh.spring_self(system, gro.positions.value_in_unit(nm), group_mos_core, [0.01, 0.01, 5.0] * kcal_mol / angstrom**2) ### in case Drude particles kiss their images print('Add wall for Drude particles of ILs...') wall = oh.wall_lj126(system, group_ils_drude, 'z', [0, lz / 2], epsilon=0.5 * kcal_mol, sigma=0.15 * nm) print(wall.getEnergyFunction()) ### randomlize particle positions to get ride of overlap random.seed(0) for i in range(system.getNumParticles()): gro.positions[i] += (random.random(), random.random(), random.random()) * nm / 1000 ### velocity-Verlet-middle integrator from velocityverletplugin import VVIntegrator integrator = VVIntegrator(T * kelvin, 10 / ps, 1 * kelvin, 40 / ps, dt * ps) integrator.setUseMiddleScheme(True) integrator.setMaxDrudeDistance(0.02 * nm) ### thermostat MoS2 by Langevin dynamics for i in group_mos: integrator.addParticleLangevin(i) ### assign image pairs integrator.setMirrorLocation(lz / 2 * nm) for parent, image in image_pairs: integrator.addImagePair(image, parent) # add fake bond between image and parent so that they are always in the same periodic cell bforce.addBond(image, parent, 0, 0) ### apply electric field on ils if voltage != 0: integrator.setElectricField(voltage / lz * 2 * volt / nm) for i in group_ils: integrator.addParticleElectrolyte(i) print('Initializing simulation...') _platform = mm.Platform.getPlatformByName('CUDA') _properties = {'CudaPrecision': 'mixed'} sim = app.Simulation(psf.topology, system, integrator, _platform, _properties) if restart: sim.loadCheckpoint(restart) sim.currentStep = round( sim.context.getState().getTime().value_in_unit(ps) / dt / 10) * 10 sim.context.setTime(sim.currentStep * dt) append = True else: sim.context.setPositions(gro.positions) sim.context.setVelocitiesToTemperature(T * kelvin) append = False sim.reporters.append( app.DCDReporter('dump.dcd', 10000, enforcePeriodicBox=False, append=append)) sim.reporters.append(oh.CheckpointReporter('cpt.cpt', 10000)) sim.reporters.append( oh.GroReporter('dump.gro', 1000, logarithm=True, subset=group_mos + group_ils, append=append)) sim.reporters.append( oh.StateDataReporter(sys.stdout, 10000, box=False, append=append)) sim.reporters.append( oh.DrudeTemperatureReporter('T_drude.txt', 100000, append=append)) print('Running...') oh.energy_decomposition(sim) sim.runForClockTime(99.9, 'rst.cpt', 'rst.xml', 1) print( '# clock time limit: step= %i time= %f' % (sim.currentStep, sim.context.getState().getTime().value_in_unit(ps)))
def gen_simulation( gro_file="conf.gro", psf_file="topol.psf", prm_file="ff.prm", dt=0.001, T=300, P=1, tcoupl="langevin", pcoupl="iso", cos=0, field=0, restart=None, ): print("Building system...") gro = oh.GroFile(gro_file) psf = oh.OplsPsfFile(psf_file, periodicBoxVectors=gro.getPeriodicBoxVectors()) prm = app.CharmmParameterSet(prm_file) system = psf.createSystem( prm, nonbondedMethod=app.PME, nonbondedCutoff=1.2 * nm, constraints=app.HBonds, rigidWater=True, verbose=True, ) is_drude = any(type(f) == mm.DrudeForce for f in system.getForces()) ### apply TT damping for CLPol force field # donors = [atom.idx for atom in psf.atom_list if atom.attype == "HO"] # all HO atoms, even those with numbers after. # i.e. HO for choline, but also HO3 / HO5 for DHP donors = [ atom.idx for atom in psf.atom_list if atom.attype.startswith("HO") or atom.attype.startswith("HW") ] if is_drude and len(donors) > 0: print("Add TT damping between HO/HW and Drude dipoles") ttforce = oh.CLPolCoulTT(system, donors) print(ttforce.getEnergyFunction()) print("Initializing simulation...") if tcoupl == "langevin": if is_drude: print("Drude Langevin thermostat: 5.0 /ps, 20 /ps") integrator = mm.DrudeLangevinIntegrator(T * kelvin, 5.0 / ps, 1 * kelvin, 20 / ps, dt * ps) integrator.setMaxDrudeDistance(0.02 * nm) else: print("Langevin thermostat: 1.0 /ps") integrator = mm.LangevinIntegrator(T * kelvin, 1.0 / ps, dt * ps) elif tcoupl == "nose-hoover": if is_drude: print( "Drude temperature-grouped Nose-Hoover thermostat: 10 /ps, 40 /ps" ) else: print("Nose-Hoover thermostat: 10 /ps") from velocityverletplugin import VVIntegrator print("using nose-hoover") integrator = VVIntegrator(T * kelvin, 10 / ps, 1 * kelvin, 40 / ps, dt * ps) integrator.setUseMiddleScheme(True) integrator.setMaxDrudeDistance(0.02 * nm) else: raise Exception("Available thermostat: langevin, nose-hoover") if pcoupl != "no": oh.apply_mc_barostat(system, pcoupl, P, T) if cos != 0: try: integrator.setCosAcceleration(cos) except: raise Exception( "Cosine acceleration not compatible with this integrator") if field != 0: try: print( f"Electric field strength of {field} applied in the y-direction, acting on all atoms" ) # apply field to all atoms atoms = [a.index for a in psf.topology.atoms()] # field applied in y-direction elecfield = oh.electric_field(system, atoms, [0, field, 0]) except: raise Exception("Electric field cannot be used with this setup") _platform = mm.Platform.getPlatformByName("CUDA") _properties = {"CudaPrecision": "mixed"} sim = app.Simulation(psf.topology, system, integrator, _platform, _properties) if restart: sim.loadCheckpoint(restart) sim.currentStep = (round( sim.context.getState().getTime().value_in_unit(ps) / dt / 10) * 10) sim.context.setTime(sim.currentStep * dt) else: sim.context.setPositions(gro.positions) sim.context.setVelocitiesToTemperature(T * kelvin) # For each reporter, check if we should append to the file - allows for restart files to # be used in another directory append_dcd = "dump.dcd" in os.listdir(".") sim.reporters.append( app.DCDReporter("dump.dcd", 10000, enforcePeriodicBox=True, append=append_dcd)) sim.reporters.append(oh.CheckpointReporter("cpt.cpt", 10000)) append_gro = "dump.gro" in os.listdir(".") sim.reporters.append( oh.GroReporter("dump.gro", 1000, logarithm=True, append=append_gro)) # if appending to dumps, also append here sim.reporters.append( oh.StateDataReporter(sys.stdout, 1000, box=False, volume=True, append=append_dcd)) if is_drude: append_drude = "T_drude.txt" in os.listdir(".") sim.reporters.append( oh.DrudeTemperatureReporter("T_drude.txt", 10000, append=append_drude)) if cos != 0: append_cos = "viscosity.txt" in os.listdir(".") sim.reporters.append( oh.ViscosityReporter("viscosity.txt", 1000, append=append_cos)) return sim
''' import simtk.openmm.app as omm_app import simtk.openmm as omm import simtk.unit as unit import math import os import numpy as np from sys import exit ## read psf and pdb file of butane psf = omm_app.CharmmPsfFile('./data/butane.psf') pdb = omm_app.PDBFile('./data/butane.pdb') ## read CHARMM force field for butane params = omm_app.CharmmParameterSet('./data/top_all35_ethers.rtf', './data/par_all35_ethers.prm') ## create a OpenMM system based on psf of butane and CHARMM force field system = psf.createSystem(params, nonbondedMethod=omm_app.NoCutoff) ## add a harmonic biasing potential on butane dihedral to the OpenMM system bias_torsion = omm.CustomTorsionForce( "0.5*K*dtheta^2; dtheta = min(diff, 2*Pi-diff); diff = abs(theta - theta0)" ) bias_torsion.addGlobalParameter("Pi", math.pi) bias_torsion.addGlobalParameter("K", 1.0) bias_torsion.addGlobalParameter("theta0", 0.0) ## 3, 6, 9, 13 are indices of the four carton atoms in butane, between which ## the dihedral angle is biased. bias_torsion.addTorsion(3, 6, 9, 13) system.addForce(bias_torsion)
# vector of all lengths LENGTHS = [CUBE_LENGTH for i in range(3)] ANGLES = [CUBE_ANGLE for i in range(3)] # method for nonbonded interactions NONBONDED_METHOD = omma.CutoffPeriodic # distance cutoff for non-bonded interactions NONBONDED_CUTOFF = 1.0 * unit.nanometer # constraints on MD calculations MD_CONSTRAINTS = omma.HBonds # force field parameters FORCE_FIELD = omma.CharmmParameterSet(*charmm_param_paths) # Monte Carlo Barostat # pressure to be maintained PRESSURE = 1.0*unit.atmosphere # temperature to be maintained TEMPERATURE = 300.0*unit.kelvin # frequency at which volume moves are attempted VOLUME_MOVE_FREQ = 50 # Platform used for OpenMM which uses different hardware computation # kernels. Options are: Reference, CPU, OpenCL, CUDA. # CUDA is the best for NVIDIA GPUs PLATFORM = 'OpenCL'
def run_simulation(nstep, gro_file='conf.gro', psf_file='topol.psf', prm_file='ff.prm', dt=0.001, T=333, thole=0, restart=None): print('Building system...') gro = oh.GroFile(gro_file) lz = gro.getUnitCellDimensions()[2].value_in_unit(nm) psf = oh.OplsPsfFile(psf_file, periodicBoxVectors=gro.getPeriodicBoxVectors()) prm = app.CharmmParameterSet(prm_file) system = psf.createSystem(prm, nonbondedMethod=app.PME, nonbondedCutoff=1.2 * nm, constraints=app.HBonds, rigidWater=True, verbose=True) nbforce = next(f for f in system.getForces() if type(f) == mm.NonbondedForce) is_drude = any(type(f) == mm.DrudeForce for f in system.getForces()) ### assign groups atoms = list(psf.topology.atoms()) group_mos = [atom.index for atom in atoms if atom.residue.name == 'MoS2'] group_mos_core = [ i for i in group_mos if not atoms[i].name.startswith('D') ] group_img = [atom.index for atom in atoms if atom.residue.name == 'IMG'] group_ils = [ atom.index for atom in atoms if atom.residue.name not in ['MoS2', 'IMG'] ] group_ils_not_H = [ i for i in group_ils if not atoms[i].name.startswith('H') ] print('Assigning groups...') print(' Number of atoms in group %10s: %i' % ('mos', len(group_mos))) print(' Number of atoms in group %10s: %i' % ('ils', len(group_ils))) print(' Number of atoms in group %10s: %i' % ('img', len(group_img))) print(' Number of atoms in group %10s: %i' % ('mos_core', len(group_mos_core))) print(' Number of atoms in group %10s: %i' % ('ils_not_H', len(group_ils_not_H))) ### apply TT damping for CLPol force field donors = [atom.idx for atom in psf.atom_list if atom.attype == 'HO'] if is_drude and len(donors) > 0: print('Add TT damping between HO and Drude dipoles') ttforce = oh.CLPolCoulTT(system, donors) print(ttforce.getEnergyFunction()) ### apply Thole screening between ILs and MoS2 if thole != 0: print('Add Thole screening between ILs and MoS2...') parent_drude_dict = dict(psf.drudepair_list) drude_parent_dict = {pair[1]: pair[0] for pair in psf.drudepair_list} tforce = mm.CustomNonbondedForce( '-%.6f*q1*q2/r*(1+0.5*screen*r)*exp(-screen*r);' 'screen=%.4f*(alpha1*alpha2)^(-1/6)' % (oh.CONST.ONE_4PI_EPS0, thole)) print(tforce.getEnergyFunction()) tforce.addPerParticleParameter('q') tforce.addPerParticleParameter('alpha') for i in range(system.getNumParticles()): if i in parent_drude_dict: q, _, _ = nbforce.getParticleParameters(parent_drude_dict[i]) q = -q alpha, _ = psf.drudeconsts_list[i] elif i in drude_parent_dict: q, _, _ = nbforce.getParticleParameters(i) alpha, _ = psf.drudeconsts_list[drude_parent_dict[i]] else: q = 0 * qe alpha = -1 q = q.value_in_unit(qe) alpha = -alpha / 1000 # convert from A^3 to nm^3 tforce.addParticle([q, alpha]) tforce.setNonbondedMethod(mm.CustomNonbondedForce.CutoffPeriodic) tforce.setCutoffDistance(1.2 * nm) tforce.addInteractionGroup(set(group_mos), set(group_ils_not_H)) tforce.setForceGroup(9) system.addForce(tforce) ### apply slab correction, need to move all atoms to primary cell print('Add dipole slab correction...') for i in range(system.getNumParticles()): gro.positions[i] += (0, 0, 1) * nm oh.slab_correction(system) ### restrain the movement of MoS2 cores (Drude particles are free if exist) print('Add restraint for MoS2 cores...') oh.spring_self(system, gro.positions.value_in_unit(nm), group_mos_core, [0.01, 0.01, 5.0] * kcal_mol / angstrom**2) ### velocity-Verlet-middle integrator # from velocityverletplugin import VVIntegrator # integrator = VVIntegrator(T * kelvin, 10 / ps, 1 * kelvin, 40 / ps, dt * ps) # integrator.setUseMiddleScheme(True) # integrator.setMaxDrudeDistance(0.02 * nm) ### thermostat MoS2 by Langevin dynamics # for i in group_mos: # integrator.addParticleLangevin(i) ### Langevin thermostat integrator = mm.DrudeLangevinIntegrator(T * kelvin, 5 / ps, 1 * kelvin, 20 / ps, dt * ps) integrator.setMaxDrudeDistance(0.02 * nm) print('Initializing simulation...') _platform = mm.Platform.getPlatformByName('CUDA') _properties = {'CudaPrecision': 'mixed'} sim = app.Simulation(psf.topology, system, integrator, _platform, _properties) if restart: sim.loadCheckpoint(restart) sim.currentStep = round( sim.context.getState().getTime().value_in_unit(ps) / dt / 10) * 10 sim.context.setTime(sim.currentStep * dt) append = True else: sim.context.setPositions(gro.positions) sim.context.setVelocitiesToTemperature(T * kelvin) append = False sim.reporters.append( app.DCDReporter('dump.dcd', 10000, enforcePeriodicBox=False, append=append)) sim.reporters.append(oh.CheckpointReporter('cpt.cpt', 10000)) sim.reporters.append( oh.GroReporter('dump.gro', 1000, logarithm=True, subset=group_mos + group_ils, append=append)) sim.reporters.append( oh.StateDataReporter(sys.stdout, 10000, append=append, box=False)) sim.reporters.append( oh.DrudeTemperatureReporter('T_drude.txt', 100000, append=append)) print('Running...') oh.energy_decomposition(sim) sim.runForClockTime(31.9, 'rst.cpt', 'rst.xml', 1) print( '# clock time limit: step= %i time= %f' % (sim.currentStep, sim.context.getState().getTime().value_in_unit(ps)))