def simulate_implicit(model_directory, variants=None, gpuid=0, rank=0): print "-------------------------------------------------------------------------" print "gpuid %d rank %d directory %s" % (gpuid, rank, model_directory) print "-------------------------------------------------------------------------" # Choose platform. platform = mm.Platform.getPlatformByName(platform_name) # Set GPU id. platform.setPropertyDefaultValue('CudaDeviceIndex', '%d' % gpuid) platform.setPropertyDefaultValue('OpenCLDeviceIndex', '%d' % gpuid) # Only simulate models that are unique following filtering by clustering. unique_by_clustering = os.path.exists( os.path.join(model_directory, 'unique_by_clustering')) if not unique_by_clustering: return os.chdir(model_directory) # Check to make sure the initial model file is present. model_filename = os.path.join(model_directory, 'model.pdb') if not os.path.exists(model_filename): return # Pass if this simulation has already been run. pdb_filename = os.path.join(model_directory, 'implicit-refined.pdb') if os.path.exists(pdb_filename): return if verbose: print "Reading model..." pdb = app.PDBFile(model_filename) # Add missing protons. modeller = app.Modeller(pdb.topology, pdb.positions) modeller.addHydrogens(forcefield, pH=pH, variants=variants) topology = modeller.getTopology() positions = modeller.getPositions() if verbose: print "Constructing System object..." if cutoff is None: system = forcefield.createSystem(topology, nonbondedMethod=app.NoCutoff, constraints=app.HBonds) else: system = forcefield.createSystem(topology, nonbondedMethod=app.CutoffNonPeriodic, nonbondedCutoff=cutoff, constraints=app.HBonds) if verbose: print "Creating Context..." integrator = mm.LangevinIntegrator(temperature, collision_rate, timestep) context = mm.Context(system, integrator, platform) context.setPositions(positions) if verbose: print "Minimizing structure..." mm.LocalEnergyMinimizer.minimize(context, minimization_tolerance, minimization_steps) if write_trajectory: # Open trajectory for writing. if verbose: print "Opening trajectory for writing..." trajectory_filename = os.path.join(model_directory, 'implicit-trajectory.pdb') trajectory_outfile = open(trajectory_filename, 'w') app.PDBFile.writeHeader(topology, file=trajectory_outfile) # Open energy trajectory for writing energy_filename = os.path.join(model_directory, 'implicit-energies.txt') energy_outfile = open(energy_filename, 'w') energy_outfile.write( '# iteration | simulation time (ps) | potential_energy (kT) | kinetic_energy (kT) | ns per day\n' ) if verbose: print "Running dynamics..." import time initial_time = time.time() for iteration in range(niterations): # integrate dynamics integrator.step(nsteps_per_iteration) # get current state state = context.getState(getEnergy=True, getPositions=True) simulation_time = state.getTime() potential_energy = state.getPotentialEnergy() kinetic_energy = state.getKineticEnergy() final_time = time.time() elapsed_time = (final_time - initial_time) * units.seconds ns_per_day = (simulation_time / elapsed_time) / (units.nanoseconds / units.day) if verbose: print " %8.1f ps : potential %8.3f kT | kinetic %8.3f kT | %.3f ns/day | %.3f s remain" % ( simulation_time / units.picoseconds, potential_energy / kT, kinetic_energy / kT, ns_per_day, elapsed_time * (niterations - iteration - 1) / (iteration + 1) / units.seconds) # Check energies are still finite. import numpy if numpy.isnan(potential_energy / kT) or numpy.isnan( kinetic_energy / kT): raise Exception("Potential or kinetic energies are nan.") if write_trajectory: app.PDBFile.writeModel(topology, state.getPositions(), file=trajectory_outfile, modelIndex=iteration) # write data energy_outfile.write( " %8d %8.1f %8.3f %8.3f %.3f\n" % (iteration, simulation_time / units.picoseconds, potential_energy / kT, kinetic_energy / kT, ns_per_day)) energy_outfile.flush() if write_trajectory: app.PDBFile.writeFooter(topology, file=trajectory_outfile) trajectory_outfile.close() energy_outfile.close() # Write final PDB file. pdb_outfile = open(pdb_filename, 'w') app.PDBFile.writeHeader(topology, file=pdb_outfile) app.PDBFile.writeFile(topology, state.getPositions(), file=pdb_outfile) app.PDBFile.writeFooter(topology, file=pdb_outfile) pdb_outfile.close() os.chdir(original_directory)
def test_install(): eps = np.finfo(float).eps print() print("openmm version:", mm.Platform.getOpenMMVersion()) print('openmm git revision:', mm.version.git_revision) print("Meld Version:", meld.__version__) print("meldplugin version:", meldplugin.__version__) print() system, coords = create_test_system_and_coords() n_platform = mm.Platform.getNumPlatforms() print("There are", n_platform, "platforms available:") print() forces = [None] * n_platform energies = [None] * n_platform platform_errors = dict() for i in range(n_platform): platform = mm.Platform.getPlatform(i) print(i+1, platform.getName(), end=" ") integrator = mm.LangevinIntegrator(300., 1.0, 0.002) try: context = mm.Context(system, integrator, platform) context.setPositions(coords) state = context.getState(getForces=True, getEnergy=True) forces[i] = state.getForces(asNumpy=True).value_in_unit(u.kilojoule_per_mole / u.nanometer) energies[i] = state.getPotentialEnergy().value_in_unit(u.kilojoule_per_mole) print("- successfully computed forces.") except: print("- failed.") platform_errors[platform.getName()] = sys.exc_info()[1] for platform, error in platform_errors.items(): print() print(platform, "platform error:", error) if n_platform > 1: print() print("Median differences between platforms:") print() for i in range(n_platform): if forces[i] is None: continue for j in range(i+1, n_platform): if forces[j] is None: continue forces_close = np.allclose(forces[i], forces[j], atol=1e-4, rtol=1e-4) median_force_error = np.median(np.abs(forces[i] - forces[j])) max_force_error = np.max(np.abs(forces[i] - forces[j])) energies_close = np.allclose(energies[i], energies[j]) energy_error = np.abs(energies[i] - energies[j]) name_i = mm.Platform.getPlatform(i).getName() name_j = mm.Platform.getPlatform(j).getName() if not forces_close or not energies_close: msg = "** LARGE DIFFERENCE **" else: msg = "** OK **" print(f"{name_i} vs {name_j}") print(f"\tenergy diff: {energy_error:g}") print(f"\tenegy good: {energies_close}") print(f"\tmedian force diff: {median_force_error:g}") print(f"\tmax force diff: {max_force_error:g}") print(f"\tforce good: {forces_close}") print(f"\t{msg}") print()
def overlap_check(): """ BUGS TO REPORT: * Even if epsilon = 0, energy of two overlapping atoms is 'nan'. * Periodicity in 'nan' if dr = 0.1 even in nonperiodic system """ # Create a reference system. logger.info("Creating Lennard-Jones cluster system...") #[reference_system, positions] = testsystems.LennardJonesFluid() #receptor_atoms = [0] #ligand_atoms = [1] system_container = testsystems.LysozymeImplicit() (reference_system, positions) = system_container.system, system_container.positions receptor_atoms = range(0, 2603) # T4 lysozyme L99A ligand_atoms = range(2603, 2621) # p-xylene unit = positions.unit positions = units.Quantity(np.array(positions / unit), unit) factory = AbsoluteAlchemicalFactory(reference_system, ligand_atoms=ligand_atoms) alchemical_state = AlchemicalState(0.00, 0.00, 0.00, 1.0) # Create the perturbed system. logger.info("Creating alchemically-modified state...") alchemical_system = factory.createPerturbedSystem(alchemical_state) # Compare energies. timestep = 1.0 * units.femtosecond logger.info("Computing reference energies...") integrator = openmm.VerletIntegrator(timestep) context = openmm.Context(reference_system, integrator) context.setPositions(positions) state = context.getState(getEnergy=True) reference_potential = state.getPotentialEnergy() del state, context, integrator logger.info(reference_potential) logger.info("Computing alchemical energies...") integrator = openmm.VerletIntegrator(timestep) context = openmm.Context(alchemical_system, integrator) dr = 0.1 * units.angstroms # TODO: Why does 0.1 cause periodic 'nan's? a = receptor_atoms[-1] b = ligand_atoms[-1] delta = positions[a, :] - positions[b, :] for k in range(3): positions[ligand_atoms, k] += delta[k] for i in range(30): r = dr * i positions[ligand_atoms, 0] += dr context.setPositions(positions) state = context.getState(getEnergy=True) alchemical_potential = state.getPotentialEnergy() logger.info("%8.3f A : %f " % (r / units.angstroms, alchemical_potential / units.kilocalories_per_mole)) del state, context, integrator return
def relax_structure(temperature, system, positions, nequil=1000, n_steps_per_iteration=250, platform_name='OpenCL', timestep=2. * unit.femtosecond, collision_rate=90. / unit.picosecond): """ arguments temperature : simtk.unit.Quantity with units compatible with kelvin temperature of simulation system : openmm.System system object for simulation positions : simtk.unit.Quantity of shape (natoms,3) with units compatible with nanometers Positions of the atoms in the system nequil : int, default = 1000 number of equilibration applications n_steps_per_iteration : int, default = 250 numper of steps per nequil platform name : str default='OpenCL' platform to run openmm on. OpenCL is best as this is what is used on FAH timestep : simtk.unit.Quantity, default = 2*unit.femtosecond timestep for equilibration NOT for production collision_rate : simtk.unit.Quantity, default=90./unit.picosecond return state : openmm.State state of simulation (getEnergy=True, getForces=True, getPositions=True, getVelocities=True, getParameters=True) """ from openmmtools.integrators import LangevinIntegrator _logger.info(f'Starting to relax') integrator = LangevinIntegrator(temperature=temperature, timestep=timestep, collision_rate=collision_rate) platform = openmm.Platform.getPlatformByName(platform_name) # prepare the plaform if platform_name in ['CUDA', 'OpenCL']: platform.setPropertyDefaultValue('Precision', 'mixed') if platform_name in ['CUDA']: platform.setPropertyDefaultValue('DeterministicForces', 'true') context = openmm.Context(system, integrator, platform) context.setPeriodicBoxVectors(*system.getDefaultPeriodicBoxVectors()) context.setPositions(positions) _logger.info(f'Starting to minimise') openmm.LocalEnergyMinimizer.minimize(context) # Equilibrate _logger.info(f'set velocities to temperature') context.setVelocitiesToTemperature(temperature) _logger.info( f'Starting to equilibrate for {nequil*n_steps_per_iteration*timestep}') integrator.step(nequil * n_steps_per_iteration) context.setVelocitiesToTemperature(temperature) state = context.getState(getEnergy=True, getForces=True, getPositions=True, getVelocities=True, getParameters=True) _logger.info(f'Relax done') del context, integrator return state
def run_alchemical_langevin_integrator(nsteps=0, splitting="O { V R H R V } O"): """Check that the AlchemicalLangevinSplittingIntegrator reproduces the analytical free energy difference for a harmonic oscillator deformation, using BAR. Up to 6*sigma is tolerated for error. The total work (protocol work + shadow work) is used. """ #max deviation from the calculated free energy NSIGMA_MAX = 6 n_iterations = 100 # number of forward and reverse protocols # These are the alchemical functions that will be used to control the system temperature = 298.0 * unit.kelvin sigma = 1.0 * unit.angstrom # stddev of harmonic oscillator kT = kB * temperature # thermal energy beta = 1.0 / kT # inverse thermal energy K = kT / sigma**2 # spring constant corresponding to sigma mass = 39.948 * unit.amu period = unit.sqrt(mass / K) # period of harmonic oscillator timestep = period / 20.0 collision_rate = 1.0 / period dF_analytical = 1.0 parameters = dict() parameters['testsystems_HarmonicOscillator_x0'] = (0 * sigma, 2 * sigma) parameters['testsystems_HarmonicOscillator_U0'] = (0 * kT, 1 * kT) forward_functions = { name: '(1-lambda)*%f + lambda*%f' % (value[0].value_in_unit_system(unit.md_unit_system), value[1].value_in_unit_system(unit.md_unit_system)) for (name, value) in parameters.items() } reverse_functions = { name: '(1-lambda)*%f + lambda*%f' % (value[1].value_in_unit_system(unit.md_unit_system), value[0].value_in_unit_system(unit.md_unit_system)) for (name, value) in parameters.items() } # Create harmonic oscillator testsystem testsystem = testsystems.HarmonicOscillator(K=K, mass=mass) system = testsystem.system positions = testsystem.positions # Get equilibrium samples from initial and final states burn_in = 5 * 20 # 5 periods thinning = 5 * 20 # 5 periods # Collect forward and reverse work values w_f = np.zeros([n_iterations], np.float64) w_r = np.zeros([n_iterations], np.float64) platform = openmm.Platform.getPlatformByName("Reference") for direction in ['forward', 'reverse']: positions = testsystem.positions for iteration in range(n_iterations): # Generate equilibrium sample equilibrium_integrator = GHMCIntegrator( temperature=temperature, collision_rate=collision_rate, timestep=timestep) equilibrium_context = openmm.Context(system, equilibrium_integrator, platform) for (name, value) in parameters.items(): if direction == 'forward': equilibrium_context.setParameter( name, value[0].value_in_unit_system(unit.md_unit_system)) else: equilibrium_context.setParameter( name, value[1].value_in_unit_system(unit.md_unit_system)) equilibrium_context.setPositions(positions) equilibrium_integrator.step(thinning) positions = equilibrium_context.getState( getPositions=True).getPositions(asNumpy=True) del equilibrium_context, equilibrium_integrator # Generate nonequilibrium work sample if direction == 'forward': alchemical_functions = forward_functions else: alchemical_functions = reverse_functions nonequilibrium_integrator = AlchemicalNonequilibriumLangevinIntegrator( temperature=temperature, collision_rate=collision_rate, timestep=timestep, alchemical_functions=alchemical_functions, splitting=splitting, nsteps_neq=nsteps, measure_shadow_work=True) nonequilibrium_context = openmm.Context(system, nonequilibrium_integrator, platform) nonequilibrium_context.setPositions(positions) if nsteps == 0: nonequilibrium_integrator.step( 1) # need to execute at least one step else: nonequilibrium_integrator.step(nsteps) if direction == 'forward': w_f[iteration] = nonequilibrium_integrator.get_total_work( dimensionless=True) else: w_r[iteration] = nonequilibrium_integrator.get_total_work( dimensionless=True) del nonequilibrium_context, nonequilibrium_integrator dF, ddF = pymbar.BAR(w_f, w_r) nsigma = np.abs(dF - dF_analytical) / ddF print( "analytical DeltaF: {:12.4f}, DeltaF: {:12.4f}, dDeltaF: {:12.4f}, nsigma: {:12.1f}" .format(dF_analytical, dF, ddF, nsigma)) if nsigma > NSIGMA_MAX: raise Exception( "The free energy difference for the nonequilibrium switching for splitting '%s' and %d steps is not zero within statistical error." % (splitting, nsteps))
ncfile.variables['positions'][iteration - 1, :, :], units.angstroms) # Continue print timestep.in_units_of(units.femtosecond) print temperature.in_units_of(units.kelvin) print collision_rate.in_units_of(units.picosecond**-1) ghmc_integrator = GHMCIntegrator(timestep=timestep, temperature=temperature, collision_rate=collision_rate) ghmc_global_variables = { ghmc_integrator.getGlobalVariableName(index): index for index in range(ghmc_integrator.getNumGlobalVariables()) } context = openmm.Context(system, ghmc_integrator, platform) context.setPositions(coordinates) state = context.getState(getPositions=True) while (iteration < niterations): # DEBUG context.setVelocitiesToTemperature(temperature) print "iteration %5d / %5d" % (iteration, niterations) print 'coordinates: ', coordinates[0, :] / units.angstrom initial_time = time.time() # Generate a new configuration. initial_distance = norm(coordinates[1, :] - coordinates[0, :])
def validate_rjmc_work_variance(top_prop, positions, geometry_method=0, num_iterations=10, md_steps=250, compute_timeseries=False, md_system=None, prespecified_conformers=None): """ Arguments ---------- top_prop : perses.rjmc.topology_proposal.TopologyProposal object topology_proposal md_system : openmm.System object, default None system from which md is conducted; the default is the top_prop._old_system geometry_method : int which geometry proposal method to use 0: neglect_angles = True (this is supposed to be the zero-variance method) 1: neglect_angles = False (this will accumulate variance) 2: use_sterics = True (this is experimental) num_iterations: int number of times to run md_steps integrator md_steps: int number of md_steps to run in each num_iteration compute_timeseries = bool (default False) whether to use pymbar detectEquilibration and subsampleCorrelated data from the MD run (the potential energy is the data) prespecified_conformers = None or unit.Quantity(np.array([num_iterations, system.getNumParticles(), 3]), unit = unit.nanometers) whether to input a unit.Quantity of conformers and bypass the conformer_generation/pymbar stage; None will default conduct this phase Returns ------- conformers : unit.Quantity(np.array([num_iterations, system.getNumParticles(), 3]), unit = unit.nanometers) decorrelated positions of the md run rj_works : list work from each conformer proposal """ from openmmtools import integrators from perses.utils.openeye import smiles_to_oemol import simtk.unit as unit import simtk.openmm as openmm from openmmtools.constants import kB from perses.rjmc.geometry import FFAllAngleGeometryEngine import tqdm temperature = 300.0 * unit.kelvin # unit-bearing temperature kT = kB * temperature # unit-bearing thermal energy beta = 1.0 / kT # unit-bearing inverse thermal energy #first, we must extract the top_prop relevant quantities topology = top_prop._old_topology if md_system == None: system = top_prop._old_system else: system = md_system if prespecified_conformers == None: #now we can specify conformations from MD integrator = integrators.LangevinIntegrator( collision_rate=1.0 / unit.picosecond, timestep=4.0 * unit.femtosecond, temperature=temperature) context = openmm.Context(system, integrator) context.setPositions(positions) openmm.LocalEnergyMinimizer.minimize(context) minimized_positions = context.getState(getPositions=True).getPositions( asNumpy=True) print(f"completed initial minimization") context.setPositions(minimized_positions) zeros = np.zeros([num_iterations, int(system.getNumParticles()), 3]) conformers = unit.Quantity(zeros, unit=unit.nanometers) rps = np.zeros((num_iterations)) print(f"conducting md sampling") for iteration in tqdm.trange(num_iterations): integrator.step(md_steps) state = context.getState(getPositions=True, getEnergy=True) new_positions = state.getPositions(asNumpy=True) conformers[iteration, :, :] = new_positions rp = state.getPotentialEnergy() * beta rps[iteration] = rp del context, integrator if compute_timeseries: print(f"computing production and data correlation") from pymbar import timeseries t0, g, Neff = timeseries.detectEquilibration(rps) series = timeseries.subsampleCorrelatedData(np.arange( t0, num_iterations), g=g) print(f"production starts at index {t0} of {num_iterations}") print(f"the number of effective samples is {Neff}") indices = t0 + series print(f"the filtered indices are {indices}") else: indices = range(num_iterations) else: conformers = prespecified_conformers indices = range(len(conformers)) #now we can define a geometry_engine if geometry_method == 0: geometry_engine = FFAllAngleGeometryEngine( metadata=None, use_sterics=False, n_bond_divisions=1000, n_angle_divisions=180, n_torsion_divisions=360, verbose=True, storage=None, bond_softening_constant=1.0, angle_softening_constant=1.0, neglect_angles=True) elif geometry_method == 1: geometry_engine = FFAllAngleGeometryEngine( metadata=None, use_sterics=False, n_bond_divisions=1000, n_angle_divisions=180, n_torsion_divisions=360, verbose=True, storage=None, bond_softening_constant=1.0, angle_softening_constant=1.0, neglect_angles=False) elif geometry_method == 2: geometry_engine = FFAllAngleGeometryEngine( metadata=None, use_sterics=True, n_bond_divisions=1000, n_angle_divisions=180, n_torsion_divisions=360, verbose=True, storage=None, bond_softening_constant=1.0, angle_softening_constant=1.0, neglect_angles=False) else: raise Exception(f"there is no geometry method for {geometry_method}") rj_works = [] print(f"conducting geometry proposals...") for indx in tqdm.trange(len(indices)): index = indices[indx] print(f"index {indx}") new_positions, logp_forward = geometry_engine.propose( top_prop, conformers[index], beta) logp_backward = geometry_engine.logp_reverse(top_prop, new_positions, conformers[index], beta) print( f"\tlogp_forward, logp_backward: {logp_forward}, {logp_backward}") added_energy = geometry_engine.forward_final_context_reduced_potential - geometry_engine.forward_atoms_with_positions_reduced_potential subtracted_energy = geometry_engine.reverse_final_context_reduced_potential - geometry_engine.reverse_atoms_with_positions_reduced_potential print( f"\tadded_energy, subtracted_energy: {added_energy}, {subtracted_energy}" ) work = logp_forward - logp_backward + added_energy - subtracted_energy rj_works.append(work) print(f"\ttotal work: {work}") return conformers, rj_works
UNITS = UNIT_NAMES # orchestration parameters N_WALKERS = 48 ## System and OpenMMRunner # make the test system from openmmtools test_sys = LennardJonesPair() # make the integrator integrator = omm.LangevinIntegrator(TEMPERATURE, FRICTION_COEFFICIENT, STEP_SIZE) # make a context and set the positions context = omm.Context(test_sys.system, copy(integrator)) context.setPositions(test_sys.positions) # get the data from this context so we have a state to start the # simulation with get_state_kwargs = dict(GET_STATE_KWARG_DEFAULTS) init_sim_state = context.getState(**get_state_kwargs) init_state = OpenMMState(init_sim_state) # initialize the runner runner = OpenMMRunner(test_sys.system, test_sys.topology, integrator, platform=PLATFORM)
testsystem = testsystems.DHFRExplicit(hydrogenMass=hydrogenMass, cutoff=cutoff) system, positions = testsystem.system, testsystem.positions positions = lb_loader.pre_equil(system, positions, temperature) platform_properties = dict(CudaPrecision="mixed") steps_per_hmc = 17 timestep = 1.5 * u.femtoseconds hmc_integrators.guess_force_groups(system, nonbonded=1, fft=1, others=0) factor = 1 groups = [(0, 2), (1, 1)] integrator = hmc_integrators.GHMCRESPA(temperature, steps_per_hmc, timestep, collision_rate, groups) context = mm.Context(system, integrator, platform, platform_properties) context.setPositions(positions) context.setVelocitiesToTemperature(temperature) integrator.step(1) integrator.step(n_steps) integrator.vstep(5) platform_properties = dict(CudaPrecision="single") steps_per_hmc = 17 timestep = 1.5 * u.femtoseconds hmc_integrators.guess_force_groups(system, nonbonded=1, fft=1, others=0) factor = 1 groups = [(0, 2), (1, 1)] integrator = hmc_integrators.GHMCRESPA(temperature, steps_per_hmc, timestep,
def openmm_energy(prm, structure, coords, box=None, cutoff=None, switch_dist=None): import parmed from simtk import unit from simtk import openmm from simtk.openmm import app from parmed.amber import AmberParm if box is not None and not np.all(box == 0): if cutoff is None: raise RuntimeError( "You need to provide a cutoff when passing a box") a = unit.Quantity( (box[0] * unit.angstrom, 0 * unit.angstrom, 0 * unit.angstrom)) b = unit.Quantity( (0 * unit.angstrom, box[1] * unit.angstrom, 0 * unit.angstrom)) c = unit.Quantity( (0 * unit.angstrom, 0 * unit.angstrom, box[2] * unit.angstrom)) structure.box_vectors = (a, b, c) if isinstance(structure, AmberParm): system = structure.createSystem( nonbondedMethod=app.CutoffPeriodic, nonbondedCutoff=0 if cutoff is None else cutoff * unit.angstrom, switchDistance=0 if switch_dist is None else switch_dist * unit.angstrom, ) else: system = structure.createSystem( prm, nonbondedMethod=app.CutoffPeriodic, nonbondedCutoff=0 if cutoff is None else cutoff * unit.angstrom, switchDistance=0 if switch_dist is None else switch_dist * unit.angstrom, ) system.setDefaultPeriodicBoxVectors(a, b, c) else: if isinstance(structure, AmberParm): system = structure.createSystem() else: system = structure.createSystem(prm) disableDispersionCorrection(system) integrator = openmm.LangevinIntegrator(300 * unit.kelvin, 1 / unit.picoseconds, 2 * unit.femtoseconds) platform = openmm.Platform.getPlatformByName("CUDA") properties = {"CudaPrecision": "double"} context = openmm.Context(system, integrator, platform, properties) # Run OpenMM with given coordinates context.setPositions(coords * unit.angstrom) energies = parmed.openmm.energy_decomposition(structure, context) state = context.getState(getForces=True) forces = state.getForces(asNumpy=True).value_in_unit( unit.kilocalories_per_mole / unit.angstrom) if "angle" not in energies: energies["angle"] = 0 if "dihedral" not in energies: energies["dihedral"] = 0 if "improper" not in energies: energies["improper"] = 0 return energies, forces
e_l, e_k, a_l, a_k, tf.constant([0.0], dtype=tf.float32), tf.constant([0.0], dtype=tf.float32), bond_idxs, angle_idxs, tf.constant([[0, 0, 0, 0]], dtype=tf.int64), xyz) jacobian_hat = tape.gradient(u, xyz) ''' for idx in range(sys.getNumForces()): force = sys.getForce(idx) force.setForceGroup(idx) context = openmm.Context(sys, openmm.VerletIntegrator(0.001)) context.setPositions(xyz * 1.0) force = sys.getForce(2) force.setNonbondedMethod(openmm.NonbondedForce.NoCutoff) force.updateParametersInContext(context) # print(context.getState(getEnergy=True, groups=1<<2).getPotentialEnergy()) traj = tf.concat([ traj, tf.concat([ context.getState(getVelocities=True, getForces=True).getForces( asNumpy=True)._value, jacobian ], axis=1)
def compare_energies(mol_name="naphthalene", ref_mol_name="benzene"): """ Make an atom map where the molecule at either lambda endpoint is identical, and check that the energies are also the same. """ from perses.rjmc.topology_proposal import SmallMoleculeSetProposalEngine, TopologyProposal from perses.annihilation.new_relative import HybridTopologyFactory import simtk.openmm as openmm from perses.tests.utils import createOEMolFromIUPAC, createSystemFromIUPAC mol_name = "naphthalene" ref_mol_name = "benzene" mol = createOEMolFromIUPAC(mol_name) m, system, positions, topology = createSystemFromIUPAC(mol_name) refmol = createOEMolFromIUPAC(ref_mol_name) #map one of the rings atom_map = SmallMoleculeSetProposalEngine._get_mol_atom_map(mol, refmol) #now use the mapped atoms to generate a new and old system with identical atoms mapped. This will result in the #same molecule with the same positions for lambda=0 and 1, and ensures a contiguous atom map effective_atom_map = {value: value for value in atom_map.values()} #make a topology proposal with the appropriate data: top_proposal = TopologyProposal(new_topology=topology, new_system=system, old_topology=topology, old_system=system, new_to_old_atom_map=effective_atom_map, new_chemical_state_key="n1", old_chemical_state_key='n2') factory = HybridTopologyFactory(top_proposal, positions, positions) alchemical_system = factory.hybrid_system alchemical_positions = factory.hybrid_positions integrator = openmm.VerletIntegrator(1) platform = openmm.Platform.getPlatformByName("Reference") context = openmm.Context(alchemical_system, integrator, platform) context.setPositions(alchemical_positions) functions = { 'lambda_sterics': '2*lambda * step(0.5 - lambda) + (1.0 - step(0.5 - lambda))', 'lambda_electrostatics': '2*(lambda - 0.5) * step(lambda - 0.5)', 'lambda_bonds': 'lambda', 'lambda_angles': 'lambda', 'lambda_torsions': 'lambda' } #set all to zero for parm in functions.keys(): context.setParameter(parm, 0.0) initial_energy = context.getState(getEnergy=True).getPotentialEnergy() #set all to one for parm in functions.keys(): context.setParameter(parm, 1.0) final_energy = context.getState(getEnergy=True).getPotentialEnergy() if np.abs(final_energy - initial_energy) > 1.0e-6 * unit.kilojoule_per_mole: raise Exception( "The energy at the endpoints was not equal for molecule %s" % mol_name)
def runOneTest(testName, options): """Perform a single benchmarking simulation.""" explicit = (testName in ('rf', 'pme', 'amoebapme')) amoeba = (testName in ('amoebagk', 'amoebapme')) hydrogenMass = None print() if amoeba: print('Test: %s (epsilon=%g)' % (testName, options.epsilon)) elif testName == 'pme': print('Test: pme (cutoff=%g)' % options.cutoff) else: print('Test: %s' % testName) platform = mm.Platform.getPlatformByName(options.platform) # Create the System. if amoeba: constraints = None epsilon = float(options.epsilon) if epsilon == 0: polarization = 'direct' else: polarization = 'mutual' if explicit: ff = app.ForceField('amoeba2009.xml') pdb = app.PDBFile('5dfr_solv-cube_equil.pdb') cutoff = 0.7*unit.nanometers vdwCutoff = 0.9*unit.nanometers system = ff.createSystem(pdb.topology, nonbondedMethod=app.PME, nonbondedCutoff=cutoff, vdwCutoff=vdwCutoff, constraints=constraints, ewaldErrorTolerance=0.00075, mutualInducedTargetEpsilon=epsilon, polarization=polarization) else: ff = app.ForceField('amoeba2009.xml', 'amoeba2009_gk.xml') pdb = app.PDBFile('5dfr_minimized.pdb') cutoff = 2.0*unit.nanometers vdwCutoff = 1.2*unit.nanometers system = ff.createSystem(pdb.topology, nonbondedMethod=app.NoCutoff, constraints=constraints, mutualInducedTargetEpsilon=epsilon, polarization=polarization) dt = 0.001*unit.picoseconds else: if explicit: ff = app.ForceField('amber99sb.xml', 'tip3p.xml') pdb = app.PDBFile('5dfr_solv-cube_equil.pdb') if testName == 'pme': method = app.PME cutoff = options.cutoff else: method = app.CutoffPeriodic cutoff = 1*unit.nanometers else: ff = app.ForceField('amber99sb.xml', 'amber99_obc.xml') pdb = app.PDBFile('5dfr_minimized.pdb') method = app.CutoffNonPeriodic cutoff = 2*unit.nanometers if options.heavy: dt = 0.005*unit.picoseconds constraints = app.AllBonds hydrogenMass = 4*unit.amu else: dt = 0.002*unit.picoseconds constraints = app.HBonds hydrogenMass = None system = ff.createSystem(pdb.topology, nonbondedMethod=method, nonbondedCutoff=cutoff, constraints=constraints, hydrogenMass=hydrogenMass) print('Step Size: %g fs' % dt.value_in_unit(unit.femtoseconds)) properties = {} if options.device is not None: if platform.getName() == 'CUDA': properties['CudaDeviceIndex'] = options.device elif platform.getName() == 'OpenCL': properties['OpenCLDeviceIndex'] = options.device if options.precision is not None: if platform.getName() == 'CUDA': properties['CudaPrecision'] = options.precision elif platform.getName() == 'OpenCL': properties['OpenCLPrecision'] = options.device # Run the simulation. integ = mm.LangevinIntegrator(300*unit.kelvin, 91*(1/unit.picoseconds), dt) integ.setConstraintTolerance(1e-5) if len(properties) > 0: context = mm.Context(system, integ, platform, properties) else: context = mm.Context(system, integ, platform) context.setPositions(pdb.positions) context.setVelocitiesToTemperature(300*unit.kelvin) steps = 20 while True: time = timeIntegration(context, steps) if time >= 0.5*options.seconds: break if time < 0.5: steps = int(steps*1.0/time) # Integrate enough steps to get a reasonable estimate for how many we'll need. else: steps = int(steps*options.seconds/time) print('Integrated %d steps in %g seconds' % (steps, time)) print('%g ns/day' % (dt*steps*86400/time).value_in_unit(unit.nanoseconds))
def __init__(self, modelName='Dimer'): self.energy_unit = unit.kilojoule_per_mole self.modelName = modelName if (self.modelName == 'Dimer'): self.testsystem = self.createDimer() name = self.testsystem self.modelname = str(name) elif (self.modelName == 'Lemon'): self.testsystem = self.createLemon() name = self.testsystem self.modelname = str(name) elif (self.modelName == 'Thomson'): self.testsystem = self.createThomson() name = self.testsystem self.modelname = str(name) elif (self.modelName == 'Alanine'): #AlanineDipeptideVacuum from openmmtools.testsystems import AlanineDipeptideVacuum #TolueneVacuum#SrcImplicit#AlanineDipeptideVacuum#LennardJonesCluster#AlanineDipeptideVacuum#HarmonicOscillator#Diatom #AlanineDipeptideVacuum#Diatom name = AlanineDipeptideVacuum self.modelname = str(name) #ala2 self.testsystem = name(constraints=None) elif (self.modelName == 'LJCluster'): ## LJ cluster from openmmtools.testsystems import LennardJonesCluster name = LennardJonesCluster self.testsystem = name(nx=2, ny=2, nz=1, constraints=None) else: print("In class Model(): modelName not found") (self.system, self.positions) = self.testsystem.system, self.testsystem.positions dummy_integrator = openmm.VerletIntegrator(1.0 * unit.femtoseconds) self.context = openmm.Context(self.system, dummy_integrator) self.context.setPositions(self.positions) if (self.modelName == 'Alanine'): # adjust periodic box ## TBD this should be moved inside the integrator class maxval = np.max( np.abs( np.vstack(self.positions.value_in_unit( self.positions.unit)))) self.boxsize = 10.0 * maxval print('Maximal position value in one direction is ' + repr(maxval)) print('PBC box size set to ' + repr(self.boxsize)) self.edge = self.boxsize * self.testsystem.positions.unit self.testsystem.system.setDefaultPeriodicBoxVectors( [self.edge, 0, 0], [0, self.edge, 0], [0, 0, self.edge]) # if(relax == 1): # self.context.minimizeEnergy(tolerance=2.0) self.x_unit = self.positions.unit self.force_unit = unit.kilocalorie_per_mole / self.x_unit self.time_unit = unit.femtosecond self.velocity_unit = self.x_unit / self.time_unit self.mass_unit = unit.amu self.temperature_unit = unit.kelvin self.kB_const = kB self.masses = 1.0 * self.mass_unit self.fixOneParticle = 0 #save Topology openmm.app.PDBFile.writeFile(self.testsystem.topology, self.positions, open(self.modelName + '.pdb', 'w'))
langevin = integrators.LangevinIntegrator(splitting=splitting, temperature=temperature, timestep=timestep, collision_rate=collision_rate, measure_shadow_work=False, measure_heat=False) ncmc_langevin = integrators.ExternalPerturbationLangevinIntegrator(splitting=splitting, temperature=temperature, timestep=timestep, collision_rate=collision_rate, measure_shadow_work=False, measure_heat=False) integrator = openmm.CompoundIntegrator() integrator.addIntegrator(langevin) integrator.addIntegrator(ncmc_langevin) # Create context if args.platform == 'CUDA': platform = openmm.Platform.getPlatformByName('CUDA') platform.setPropertyDefaultValue('DeterministicForces', 'true') properties = {'CudaPrecision': 'mixed'} context = openmm.Context(wbox.system, integrator, platform, properties) elif args.platform == 'OpenCL': platform = openmm.Platform.getPlatformByName('OpenCL') properties = {'OpenCLPrecision': 'mixed'} context = openmm.Context(wbox.system, integrator, platform, properties) elif args.platform == 'CPU': platform = openmm.Platform.getPlatformByName('CPU') context = openmm.Context(wbox.system, integrator, platform) else: raise Exception('Platform name {0} not recognized.'.format(args.platform)) context.setPositions(wbox.positions) context.setVelocitiesToTemperature(temperature) # Create the salinator object for the insertion and deletion of salt salinator = wrappers.Salinator(context=context, system=wbox.system, topology=wbox.topology,
def setup_fah_run(destination_path, protein_pdb_filename, oemol=None, cache=None, restrain_rmsd=False, biounit='monomer'): """ Prepare simulation Parameters ---------- destination_path : str The path to the RUN to be created protein_pdb_filename : str Path to protein PDB file oemol : openeye.oechem.OEMol, optional, default=None The molecule to parameterize, with SDData attached If None, don't include the small molecule restrain_rmsd : bool, optional, default=False If True, restrain RMSD during first equilibration phase biounit : str, optional, default='monomer' 'monomer' or 'dimer' """ # Parameters from simtk import unit, openmm protein_forcefield = 'amber14/protein.ff14SB.xml' solvent_forcefield = 'amber14/tip3p.xml' small_molecule_forcefield = 'openff-1.3.0' water_model = 'tip3p' solvent_padding = 10.0 * unit.angstrom ionic_strength = 70 * unit.millimolar # assay buffer: 20 mM HEPES pH 7.3, 1 mM TCEP, 50 mM NaCl, 0.01% Tween-20, 10% glycerol pressure = 1.0 * unit.atmospheres collision_rate = 1.0 / unit.picoseconds temperature = 300.0 * unit.kelvin timestep = 4.0 * unit.femtoseconds iterations = 1000 # 1 ns equilibration nsteps_per_iteration = 250 nsteps_per_snapshot = 250000 # 1 ns nsnapshots_per_wu = 20 # number of snapshots per WU # Prepare phases import os system_xml_filename = os.path.join(destination_path, 'system.xml.bz2') integrator_xml_filename = os.path.join(destination_path, 'integrator.xml.bz2') state_xml_filename = os.path.join(destination_path, 'state.xml.bz2') # Check if we can skip setup openmm_files_exist = os.path.exists( system_xml_filename) and os.path.exists( state_xml_filename) and os.path.exists(integrator_xml_filename) if openmm_files_exist: return # Create barostat barostat = openmm.MonteCarloBarostat(pressure, temperature) # Create RUN directory if it does not yet exist os.makedirs(destination_path, exist_ok=True) # Load any molecule(s) molecule = None molecules = [] if oemol is not None: from openforcefield.topology import Molecule molecule = Molecule.from_openeye(oemol, allow_undefined_stereo=True) molecule.name = 'MOL' # Ensure residue is MOL print([res for res in molecule.to_topology().to_openmm().residues()]) molecules = [molecule] # Create SystemGenerator import os from simtk.openmm import app forcefield_kwargs = { 'removeCMMotion': False, 'hydrogenMass': 3.0 * unit.amu, 'constraints': app.HBonds, 'rigidWater': True } periodic_kwargs = { 'nonbondedMethod': app.PME, 'ewaldErrorTolerance': 2.5e-04 } forcefields = [protein_forcefield, solvent_forcefield] from openmmforcefields.generators import SystemGenerator openmm_system_generator = SystemGenerator( forcefields=forcefields, molecules=molecules, small_molecule_forcefield=small_molecule_forcefield, cache=cache, barostat=barostat, forcefield_kwargs=forcefield_kwargs, periodic_forcefield_kwargs=periodic_kwargs) # Read protein print(f'Reading protein from {protein_pdb_filename}...') pdbfile = app.PDBFile(protein_pdb_filename) modeller = app.Modeller(pdbfile.topology, pdbfile.positions) if oemol is not None: # Add small molecule to the system modeller.add(molecule.to_topology().to_openmm(), molecule.conformers[0]) # Extract protein and molecule chains and indices before adding solvent import mdtraj as md mdtop = md.Topology.from_openmm( modeller.topology) # excludes solvent and ions protein_atom_indices = mdtop.select('protein and (mass > 1)') molecule_atom_indices = mdtop.select( '(not protein) and (not water) and (mass > 1)') protein_chainids = list( set([ atom.residue.chain.index for atom in mdtop.atoms if atom.index in protein_atom_indices ])) n_protein_chains = len(protein_chainids) protein_chain_atom_indices = dict() for chainid in protein_chainids: protein_chain_atom_indices[chainid] = mdtop.select( f'protein and chainid {chainid}') # Add solvent print('Adding solvent...') kwargs = {'padding': solvent_padding} modeller.addSolvent(openmm_system_generator.forcefield, model='tip3p', ionicStrength=ionic_strength, **kwargs) # Write initial model and select atom subsets and chains import bz2 with bz2.open(os.path.join(destination_path, 'initial-model.pdb.bz2'), 'wt') as outfile: app.PDBFile.writeFile(modeller.topology, modeller.positions, outfile, keepIds=True) # Create an OpenMM system print('Creating OpenMM system...') system = openmm_system_generator.create_system(modeller.topology) # # Add virtual bonds to ensure protein subunits and ligand are imaged together # virtual_bond_force = openmm.CustomBondForce('0') system.addForce(virtual_bond_force) # Add a virtual bond between protein chains if (n_protein_chains > 1): chainid = protein_chainids[0] iatom = protein_chain_atom_indices[chainid][0] for chainid in protein_chainids[1:]: jatom = protein_chain_atom_indices[chainid][0] print(f'Creating virtual bond between atoms {iatom} and {jatom}') virtual_bond_force.addBond(int(iatom), int(jatom), []) # Add a virtual bond between protein and ligand to make sure they are not imaged separately if oemol is not None: ligand_atom_indices = mdtop.select( '((resname MOL) and (mass > 1))') # ligand heavy atoms protein_atom_index = int(protein_atom_indices[0]) ligand_atom_index = int(ligand_atom_indices[0]) print( f'Creating virtual bond between atoms {protein_atom_index} and {ligand_atom_index}' ) virtual_bond_force.addBond(int(protein_atom_index), int(ligand_atom_index), []) # Add RMSD restraints if requested if restrain_rmsd: print('Adding RMSD restraint...') kB = unit.AVOGADRO_CONSTANT_NA * unit.BOLTZMANN_CONSTANT_kB kT = kB * temperature rmsd_atom_indices = mdtop.select( '(protein and (name CA)) or ((resname MOL) and (mass > 1))' ) # CA atoms and ligand heavy atoms rmsd_atom_indices = [int(index) for index in rmsd_atom_indices] custom_cv_force = openmm.CustomCVForce('(K_RMSD/2)*RMSD^2') custom_cv_force.addGlobalParameter('K_RMSD', kT / unit.angstrom**2) rmsd_force = openmm.RMSDForce(modeller.positions, rmsd_atom_indices) custom_cv_force.addCollectiveVariable('RMSD', rmsd_force) force_index = system.addForce(custom_cv_force) # Create OpenM Context platform = openmm.Platform.getPlatformByName('OpenCL') platform.setPropertyDefaultValue('Precision', 'mixed') from openmmtools import integrators integrator = integrators.LangevinIntegrator(temperature, collision_rate, timestep) context = openmm.Context(system, integrator, platform) context.setPositions(modeller.positions) # Report initial potential energy state = context.getState(getEnergy=True) print( f'Initial potential energy is {state.getPotentialEnergy()/unit.kilocalories_per_mole:.3f} kcal/mol' ) # Store snapshots in MDTraj trajectory to examine RMSD import mdtraj as md import numpy as np mdtop = md.Topology.from_openmm(pdbfile.topology) atom_indices = mdtop.select('all') # all solute atoms protein_atom_indices = mdtop.select( 'protein and (mass > 1)') # heavy solute atoms if oemol is not None: ligand_atom_indices = mdtop.select( '(resname MOL) and (mass > 1)') # ligand heavy atoms trajectory = md.Trajectory( np.zeros([iterations + 1, len(atom_indices), 3], np.float32), mdtop) trajectory.xyz[0, :, :] = context.getState(getPositions=True).getPositions( asNumpy=True)[atom_indices] / unit.nanometers # Minimize print('Minimizing...') openmm.LocalEnergyMinimizer.minimize(context) # Equilibrate (with RMSD restraint if needed) import numpy as np from rich.progress import track import time initial_time = time.time() for iteration in track(range(iterations), 'Equilibrating...'): integrator.step(nsteps_per_iteration) trajectory.xyz[iteration + 1, :, :] = context.getState( getPositions=True).getPositions( asNumpy=True)[atom_indices] / unit.nanometers elapsed_time = (time.time() - initial_time) * unit.seconds ns_per_day = (context.getState().getTime() / elapsed_time) / (unit.nanoseconds / unit.day) print(f'Performance: {ns_per_day:8.3f} ns/day') if restrain_rmsd: # Disable RMSD restraint context.setParameter('K_RMSD', 0.0) print('Minimizing...') openmm.LocalEnergyMinimizer.minimize(context) for iteration in track(range(iterations), 'Equilibrating without RMSD restraint...'): integrator.step(nsteps_per_iteration) # Retrieve state state = context.getState(getPositions=True, getVelocities=True, getEnergy=True, getForces=True) system.setDefaultPeriodicBoxVectors(*state.getPeriodicBoxVectors()) modeller.topology.setPeriodicBoxVectors(state.getPeriodicBoxVectors()) print( f'Final potential energy is {state.getPotentialEnergy()/unit.kilocalories_per_mole:.3f} kcal/mol' ) # Equilibrate again if we restrained the RMSD if restrain_rmsd: print('Removing RMSD restraint from system...') system.removeForce(force_index) #if oemol is not None: # # Check final RMSD # print('checking RMSD...') # trajectory.superpose(trajectory, atom_indices=protein_atom_indices) # protein_rmsd = md.rmsd(trajectory, trajectory[-1], atom_indices=protein_atom_indices)[-1] * 10 # Angstroms # oechem.OESetSDData(oemol, 'equil_protein_rmsd', f'{protein_rmsd:.2f} A') # ligand_rmsd = md.rmsd(trajectory, trajectory[-1], atom_indices=ligand_atom_indices)[-1] * 10 # Angstroms # oechem.OESetSDData(oemol, 'equil_ligand_rmsd', f'{ligand_rmsd:.2f} A') # print('RMSD after equilibration: protein {protein_rmsd:8.2f} A | ligand {ligand_rmsd:8.3f} A') # Save as OpenMM print('Exporting for OpenMM FAH simulation...') import bz2 with bz2.open(integrator_xml_filename, 'wt') as f: f.write(openmm.XmlSerializer.serialize(integrator)) with bz2.open(state_xml_filename, 'wt') as f: f.write(openmm.XmlSerializer.serialize(state)) with bz2.open(system_xml_filename, 'wt') as f: f.write(openmm.XmlSerializer.serialize(system)) with bz2.open(os.path.join(destination_path, 'equilibrated-all.pdb.bz2'), 'wt') as f: app.PDBFile.writeFile(modeller.topology, state.getPositions(), f, keepIds=True) with open(os.path.join(destination_path, 'equilibrated-solute.pdb'), 'wt') as f: import mdtraj mdtraj_topology = mdtraj.Topology.from_openmm(modeller.topology) mdtraj_trajectory = mdtraj.Trajectory( [state.getPositions(asNumpy=True) / unit.nanometers], mdtraj_topology) selection = mdtraj_topology.select('not water') mdtraj_trajectory = mdtraj_trajectory.atom_slice(selection) app.PDBFile.writeFile(mdtraj_trajectory.topology.to_openmm(), mdtraj_trajectory.openmm_positions(0), f, keepIds=True) with open(os.path.join(destination_path, 'core.xml'), 'wt') as f: f.write(f'<config>\n') f.write( f' <numSteps>{nsteps_per_snapshot * nsnapshots_per_wu}</numSteps>\n' ) f.write(f' <xtcFreq>{nsteps_per_snapshot}</xtcFreq>\n') f.write(f' <precision>mixed</precision>\n') f.write( f' <xtcAtoms>{",".join([str(index) for index in selection])}</xtcAtoms>\n' ) f.write(f'</config>\n') if oemol is not None: # Write molecule as SDF, SMILES, and mol2 for extension in ['sdf', 'mol2', 'smi', 'csv']: filename = os.path.join(destination_path, f'molecule.{extension}') with oechem.oemolostream(filename) as ofs: oechem.OEWriteMolecule(ofs, oemol) # Clean up del context, integrator
def run(): # Create initial model system, topology, and positions. smiles_list = ["CC", "CCC", "CCCC"] initial_molecule = smiles_to_oemol("CC") molecules = [Molecule.from_openeye(initial_molecule)] system_generator = SystemGenerator(molecules=molecules) initial_sys, initial_pos, initial_top = OEMol_to_omm_ff( initial_molecule, system_generator) smiles = "CC" stats = {ms: 0 for ms in smiles_list} # Run parameters temperature = 300.0 * unit.kelvin # temperature pressure = 1.0 * unit.atmospheres # pressure collision_rate = 5.0 / unit.picoseconds # collision rate for Langevin dynamics # Create proposal metadata, such as the list of molecules to sample (SMILES here) # proposal_metadata = {"smiles_list": smiles_list} list_of_oemols = [] for smile in smiles_list: oemol = smiles_to_oemol(smile) list_of_oemols.append(oemol) transformation = topology_proposal.SmallMoleculeSetProposalEngine( list_of_oemols=list_of_oemols, system_generator=system_generator) # transformation = topology_proposal.SingleSmallMolecule(proposal_metadata) # Initialize weight calculation engine, along with its metadata bias_calculator = bias_engine.MinimizedPotentialBias(smiles_list) # Initialize NCMC engines. switching_timestep = (1.0 * unit.femtosecond ) # Timestep for NCMC velocity Verlet integrations switching_nsteps = 10 # Number of steps to use in NCMC integration switching_functions = { # Functional schedules to use in terms of `lambda`, which is switched from 0->1 for creation and 1->0 for deletion "lambda_sterics": "lambda", "lambda_electrostatics": "lambda", "lambda_bonds": "lambda", "lambda_angles": "sqrt(lambda)", "lambda_torsions": "lambda", } ncmc_engine = ncmc_switching.NCMCEngine( temperature=temperature, timestep=switching_timestep, nsteps=switching_nsteps, functions=switching_functions, ) # Initialize GeometryEngine geometry_metadata = {"data": 0} # currently ignored geometry_engine = geometry.FFAllAngleGeometryEngine(geometry_metadata) # Run a number of iterations. niterations = 50 system = initial_sys topology = initial_top positions = initial_pos current_log_weight = bias_calculator.g_k(smiles) n_accepted = 0 propagate = True for i in range(niterations): # Store old (system, topology, positions). # Propose a transformation from one chemical species to another. state_metadata = {"molecule_smiles": smiles} top_proposal = transformation.propose( system, topology, positions, state_metadata) # Get a new molecule # QUESTION: What about instead initializing StateWeight once, and then using # log_state_weight = state_weight.computeLogStateWeight(new_topology, new_system, new_metadata)? log_weight = bias_calculator.g_k( top_proposal.metadata["molecule_smiles"]) # Perform alchemical transformation. # Alchemically eliminate atoms being removed. [ncmc_old_positions, ncmc_elimination_logp] = ncmc_engine.integrate(top_proposal, positions, direction="delete") # Generate coordinates for new atoms and compute probability ratio of old and new probabilities. # QUESTION: Again, maybe we want to have the geometry engine initialized once only? geometry_proposal = geometry_engine.propose( top_proposal.new_to_old_atom_map, top_proposal.new_system, system, ncmc_old_positions, ) # Alchemically introduce new atoms. [ncmc_new_positions, ncmc_introduction_logp ] = ncmc_engine.integrate(top_proposal, geometry_proposal.new_positions, direction="insert") # Compute total log acceptance probability, including all components. logp_accept = (top_proposal.logp_proposal + geometry_proposal.logp + ncmc_elimination_logp + ncmc_introduction_logp + log_weight / log_weight.unit - current_log_weight / current_log_weight.unit) # Accept or reject. if ((logp_accept >= 0.0) or (np.random.uniform() < np.exp(logp_accept))) and not np.any( np.isnan(ncmc_new_positions)): # Accept. n_accepted += 1 (system, topology, positions, current_log_weight, smiles) = ( top_proposal.new_system, top_proposal.new_topology, ncmc_new_positions, log_weight, top_proposal.metadata["molecule_smiles"], ) else: # Reject. logging.debug("reject") stats[smiles] += 1 print(positions) if propagate: p_system = copy.deepcopy(system) integrator = openmm.LangevinIntegrator(temperature, collision_rate, switching_timestep) context = openmm.Context(p_system, integrator) context.setPositions(positions) print(context.getState(getEnergy=True).getPotentialEnergy()) integrator.step(1000) state = context.getState(getPositions=True) positions = state.getPositions(asNumpy=True) del context, integrator, p_system print("The total number accepted was %d out of %d iterations" % (n_accepted, niterations)) print(stats)
n_steps = 3000 temperature = 300. * u.kelvin collision_rate = 1.0 / u.picoseconds timestep = 2.0 * u.femtoseconds steps_per_hmc = 12 k_max = 2 testsystem = testsystems.WaterBox( box_edge=3.18 * u.nanometers) # Around 1060 molecules of water system = testsystem.system positions = testsystem.positions integrator = mm.LangevinIntegrator(temperature, 1.0 / u.picoseconds, 0.25 * u.femtoseconds) context = mm.Context(testsystem.system, integrator) context.setPositions(testsystem.positions) context.setVelocitiesToTemperature(temperature) integrator.step(5000) positions = context.getState(getPositions=True).getPositions() integrator = hmc_integrators.GHMC2(temperature, steps_per_hmc, timestep, collision_rate) context = mm.Context(system, integrator) context.setPositions(positions) context.setVelocitiesToTemperature(temperature) for i in range(1000): data = [] for j in range(10): integrator.step(1)
#platform = cpu #platform = opencl platform = cuda n_steps = 5000 temperature = 300. * u.kelvin #testsystem = testsystems.WaterBox(box_edge=3.18 * u.nanometers) # Around 1060 molecules of water testsystem = testsystems.FlexibleWaterBox(box_edge=3.18 * u.nanometers) # Around 1060 molecules of water #testsystem = testsystems.AlanineDipeptideExplicit() system = testsystem.system integrator = mm.LangevinIntegrator(temperature, 0.25 / u.picoseconds, 0.25 * u.femtoseconds) #integrator = hmc_integrators.RandomTimestepGHMC(temperature, 12, 0.25 * u.femtoseconds) context = mm.Context(testsystem.system, integrator, platform) context.setPositions(testsystem.positions) context.setVelocitiesToTemperature(temperature) integrator.step(5000) positions = context.getState(getPositions=True).getPositions() def test_hmc(timestep, steps_per_hmc): timestep = timestep * u.femtoseconds integrator = hmc_integrators.RandomTimestepGHMC(temperature, steps_per_hmc, timestep) context = mm.Context(system, integrator, platform) context.setPositions(positions) context.setVelocitiesToTemperature(temperature) integrator.step(n_steps) return integrator.acceptance_rate #timestep_list = np.linspace(1.5, 2.25, 2)
def _computeStandardStateCorrection(self): """ Compute the standard state correction for the arbitrary restraint energy function. RETURN VALUES DeltaG (float) - computed standard-state correction in dimensionless units (kT); NOTE Equivalent to the free energy of releasing restraints and confining into a box of standard state size. """ r_min = 0 * units.nanometers r_max = 100 * units.nanometers # TODO: Use maximum distance between atoms? # Create a System object containing two particles connected by the reference force system = openmm.System() system.addParticle(1.0 * units.amu) system.addParticle(1.0 * units.amu) force = self._createRestraintForce(0, 1) system.addForce(force) # Create a Reference context to evaluate energies on the CPU. integrator = openmm.VerletIntegrator(1.0 * units.femtoseconds) platform = openmm.Platform.getPlatformByName('Reference') context = openmm.Context(system, integrator, platform) # Set default positions. positions = units.Quantity(numpy.zeros([2, 3]), units.nanometers) context.setPositions(positions) # Create a function to compute integrand as a function of interparticle separation. beta = self.beta def integrand(r): """ ARGUMENTS r (float) - interparticle separation in nanometers RETURNS dI (float) - contribution to integrand (in nm^2) """ positions[1, 0] = r * units.nanometers context.setPositions(positions) state = context.getState(getEnergy=True) potential = state.getPotentialEnergy() dI = 4.0 * math.pi * r**2 * math.exp(-beta * potential) return dI (shell_volume, shell_volume_error) = scipy.integrate.quad( lambda r: integrand(r), r_min / units.nanometers, r_max / units.nanometers) * units.nanometers**3 # integrate shell volume logger.debug("shell_volume = %f nm^3" % (shell_volume / units.nanometers**3)) # Compute standard-state volume for a single molecule in a box of size (1 L) / (avogadros number) liter = 1000.0 * units.centimeters**3 # one liter box_volume = liter / (units.AVOGADRO_CONSTANT_NA * units.mole ) # standard state volume logger.debug("box_volume = %f nm^3" % (box_volume / units.nanometers**3)) # Compute standard state correction for releasing shell restraints into standard-state box (in units of kT). DeltaG = -math.log(box_volume / shell_volume) logger.debug("Standard state correction: %.3f kT" % DeltaG) # Return standard state correction (in kT). return DeltaG
# Add a barostat # print('Adding barostat...') # barostat = openmm.MonteCarloBarostat(pressure, temperature) # system.addForce(barostat) # Serialize integrator print('Serializing integrator to %s' % integrator_xml_filename) integrator = openmm.LangevinIntegrator(temperature, collision_rate, timestep) with open(integrator_xml_filename, 'w') as outfile: xml = openmm.XmlSerializer.serialize(integrator) outfile.write(xml) # Minimize print('Minimizing energy...') context = openmm.Context(system, integrator) context.setPositions(modeller.positions) print(' initial : %8.3f kcal/mol' % (context.getState(getEnergy=True).getPotentialEnergy()/unit.kilocalories_per_mole)) openmm.LocalEnergyMinimizer.minimize(context) print(' final : %8.3f kcal/mol' % (context.getState(getEnergy=True).getPotentialEnergy()/unit.kilocalories_per_mole)) with open(minimized_pdb_filename, 'w') as outfile: app.PDBFile.writeFile(modeller.topology, context.getState(getPositions=True,enforcePeriodicBox=True).getPositions(), file=outfile, keepIds=True) # Equilibrate print('Equilibrating...') initial_time = time.time() for iteration in progressbar.progressbar(range(niterations)): integrator.step(nsteps) elapsed_time = (time.time() - initial_time) * unit.seconds simulation_time = niterations * nsteps * timestep print(' Equilibration took %.3f s for %.3f ns (%8.3f ns/day)' % (elapsed_time / unit.seconds, simulation_time / unit.nanoseconds, simulation_time / elapsed_time * unit.day / unit.nanoseconds))
def __init__(self, topology, system, integrator, platform=None, platformProperties=None, state=None): """Create a Simulation. Parameters ---------- topology : Topology A Topology describing the the system to simulate system : System or XML file name The OpenMM System object to simulate (or the name of an XML file with a serialized System) integrator : Integrator or XML file name The OpenMM Integrator to use for simulating the System (or the name of an XML file with a serialized System) platform : Platform=None If not None, the OpenMM Platform to use platformProperties : map=None If not None, a set of platform-specific properties to pass to the Context's constructor state : XML file name=None The name of an XML file containing a serialized State. If not None, the information stored in state will be transferred to the generated Simulation object. """ self.topology = topology ## The System being simulated if isinstance(system, string_types): with open(system, 'r') as f: self.system = mm.XmlSerializer.deserialize(f.read()) else: self.system = system ## The Integrator used to advance the simulation if isinstance(integrator, string_types): with open(integrator, 'r') as f: self.integrator = mm.XmlSerializer.deserialize(f.read()) else: self.integrator = integrator ## The index of the current time step self.currentStep = 0 ## A list of reporters to invoke during the simulation self.reporters = [] if platform is None: ## The Context containing the current state of the simulation self.context = mm.Context(self.system, self.integrator) elif platformProperties is None: self.context = mm.Context(self.system, self.integrator, platform) else: self.context = mm.Context(self.system, self.integrator, platform, platformProperties) if state is not None: with open(state, 'r') as f: self.context.setState(mm.XmlSerializer.deserialize(f.read())) ## Determines whether or not we are using PBC. Try from the System first, ## fall back to Topology if that doesn't work try: self._usesPBC = self.system.usesPeriodicBoundaryConditions() except Exception: # OpenMM just raises Exception if it's not implemented everywhere self._usesPBC = topology.getUnitCellDimensions() is not None
def test_ncmc_update_parameters_in_context(self): """ Testing that the protocol work is correctly calculated in cases when the parameters are updated using context.updateParametersInContext() and the integrator is a compound integrator. The NCMC scheme tested below is based on the one used by the saltswap and protons code-bases. """ from simtk.openmm import app from openmmtools.constants import kB size = 20.0 temperature = 298.0 * unit.kelvin kT = kB * temperature nonbonded_method = 'CutoffPeriodic' platform_name = 'CPU' timestep = 1. * unit.femtoseconds collision_rate = 90. / unit.picoseconds wbox = testsystems.WaterBox(box_edge=size * unit.angstrom, cutoff=9. * unit.angstrom, nonbondedMethod=getattr( app, nonbonded_method)) integrator = integrators.ExternalPerturbationLangevinIntegrator( splitting="V R O R V", temperature=temperature, timestep=timestep, collision_rate=collision_rate) # Create context platform = openmm.Platform.getPlatformByName(platform_name) context = openmm.Context(wbox.system, integrator, platform) context.setPositions(wbox.positions) context.setPositions(wbox.positions) context.setVelocitiesToTemperature(temperature) def switchoff(force, context, frac=0.9): force.setParticleParameters(0, charge=-0.834 * frac, sigma=0.3150752406575124 * frac, epsilon=0.635968 * frac) force.setParticleParameters(1, charge=0.417 * frac, sigma=0, epsilon=1 * frac) force.setParticleParameters(2, charge=0.417 * frac, sigma=0, epsilon=1 * frac) force.updateParametersInContext(context) def switchon(force, context): force.setParticleParameters(0, charge=-0.834, sigma=0.3150752406575124, epsilon=0.635968) force.setParticleParameters(1, charge=0.417, sigma=0, epsilon=1) force.setParticleParameters(2, charge=0.417, sigma=0, epsilon=1) force.updateParametersInContext(context) force = wbox.system.getForce(2) # Non-bonded force. # Number of NCMC steps nsteps = 20 niterations = 3 for i in range(niterations): external_protocol_work = 0.0 integrator.reset_protocol_work() integrator.step(1) for step in range(nsteps): fraction = float(step + 1) / float(nsteps) initial_energy = context.getState( getEnergy=True).getPotentialEnergy() switchoff(force, context, frac=fraction) final_energy = context.getState( getEnergy=True).getPotentialEnergy() external_protocol_work += (final_energy - initial_energy) / kT integrator.step(1) integrator_protocol_work = integrator.get_protocol_work( dimensionless=True) assert abs(external_protocol_work - integrator_protocol_work) < 1.E-5 # Return to unperturbed state switchon(force, context)
def createContext(self, integrator=None, platform=None): """ Create an OpenMM Context object from the current sampler state. Parameters ---------- integrator : simtk.openmm.Integrator, optional, default=None The integrator to use for Context creation. If not specified, a VerletIntegrator with 1 fs timestep is created. platform : simtk.openmm.Platform, optional, default=None If specified, the Platform to use for context creation. Returns ------- context : simtk.openmm.Context The created OpenMM Context object Notes ----- If the selected or default platform fails, the CPU and Reference platforms will be tried, in that order. Examples -------- Create a context for a system with periodic box vectors. >>> # Create a test system >>> from openmmtools import testsystems >>> test = testsystems.LennardJonesFluid() >>> # Create a sampler state manually. >>> box_vectors = test.system.getDefaultPeriodicBoxVectors() >>> sampler_state = SamplerState(positions=test.positions, box_vectors=box_vectors, system=test.system) >>> # Create a Context. >>> import simtk.openmm as mm >>> import simtk.unit as u >>> integrator = mm.VerletIntegrator(1.0*u.femtoseconds) >>> context = sampler_state.createContext(integrator) >>> # Clean up. >>> del context Create a context for a system without periodic box vectors. >>> # Create a test system >>> from openmmtools import testsystems >>> test = testsystems.LennardJonesCluster() >>> # Create a sampler state manually. >>> sampler_state = SamplerState(positions=test.positions, system=test.system) >>> # Create a Context. >>> import simtk.openmm as mm >>> import simtk.unit as u >>> integrator = mm.VerletIntegrator(1.0*u.femtoseconds) >>> context = sampler_state.createContext(integrator) >>> # Clean up. >>> del context TODO ---- * Generalize fallback platform order to [CUDA, OpenCL, CPU, Reference] ordering. """ if not self.system: raise Exception( "SamplerState must have a 'system' object specified to create a Context" ) # Use a Verlet integrator if none is specified. if integrator is None: integrator = mm.VerletIntegrator(1.0 * u.femtoseconds) # Create a Context. if platform: context = mm.Context(self.system, integrator, platform) else: context = mm.Context(self.system, integrator) # Set box vectors, if specified. if (self.box_vectors is not None): try: # try tuple of box vectors context.setPeriodicBoxVectors(self.box_vectors[0], self.box_vectors[1], self.box_vectors[2]) except: # try numpy 3x3 matrix of box vectors context.setPeriodicBoxVectors(self.box_vectors[0, :], self.box_vectors[1, :], self.box_vectors[2, :]) # Set positions. context.setPositions(self.positions) # Set velocities, if specified. if (self.velocities is not None): context.setVelocities(self.velocities) return context
import simtk.openmm as mm from simtk import unit as u from openmmtools import hmc_integrators, testsystems pd.set_option('display.width', 1000) collision_rate = 10000.0 / u.picoseconds temperature = 25. * u.kelvin testsystem = testsystems.LennardJonesFluid() system, positions = testsystem.system, testsystem.positions system.addForce(mm.MonteCarloBarostat(1.0 * u.atmospheres, temperature, 50)) integrator = mm.LangevinIntegrator(temperature, 1.0 / u.picoseconds, 0.5 * u.femtoseconds) context = mm.Context(system, integrator) context.setPositions(positions) context.setPeriodicBoxVectors(*boxes) context.setVelocitiesToTemperature(temperature) integrator.step(25000) positions = context.getState(getPositions=True).getPositions() x = [] for i in range(1000): state = context.getState(getParameters=True, getPositions=True) positions = state.getPositions(asNumpy=True) / u.nanometers boxes = state.getPeriodicBoxVectors(asNumpy=True) / u.nanometers x.append(boxes[0][0] / u.nanometer) print(x[-1]) integrator.step(1000)
# Creación del sistema. system = mm.System() for ii in range(n_particles): system.addParticle(mass) # Creación del integrador. friction = 5.0 / unit.picosecond # fricción del sistema (0.0/unit.picoseconds si no queremos fricción) integrator = mm.LangevinIntegrator(temperature, friction, integration_timestep) # Creación de la plataforma. platform_name = 'CUDA' platform = mm.Platform.getPlatformByName(platform_name) # Creación del contexto. context = mm.Context(system, integrator, platform) context.setPositions(initial_positions) context.setVelocities(initial_velocities) # Creación de arrays reporteros del tiempo, la posición y la velocidad. times = np.zeros([n_cicles], np.float32) * unit.picoseconds positions = np.zeros([n_cicles, n_particles, 3], np.float32) * unit.nanometers velocities = np.zeros([n_cicles, n_particles, 3], np.float32) * unit.nanometers / unit.picosecond kinetic_energy = np.zeros([n_cicles], np.float32) * unit.kilocalories_per_mole potential_energy = np.zeros([n_cicles], np.float32) * unit.kilocalories_per_mole # Almacenamiento en reporteros de las condiciones iniciales para tiempo 0 state = context.getState(getPositions=True, getVelocities=True, getEnergy=True) times[0] = state.getTime()
def benchmark(reference_system, positions, receptor_atoms, ligand_atoms, platform_name=None, annihilate_electrostatics=True, annihilate_sterics=False, nsteps=500): """ Benchmark performance relative to unmodified system. ARGUMENTS reference_system (simtk.openmm.System) - the reference System object to compare with positions - the positions to assess energetics for receptor_atoms (list of int) - the list of receptor atoms ligand_atoms (list of int) - the list of ligand atoms to alchemically modify """ # Create a factory to produce alchemical intermediates. logger.info("Creating alchemical factory...") initial_time = time.time() factory = AbsoluteAlchemicalFactory( reference_system, ligand_atoms=ligand_atoms, annihilate_electrostatics=annihilate_electrostatics, annihilate_sterics=annihilate_sterics) final_time = time.time() elapsed_time = final_time - initial_time logger.info("AbsoluteAlchemicalFactory initialization took %.3f s" % elapsed_time) # Create an alchemically-perturbed state corresponding to nearly fully-interacting. # NOTE: We use a lambda slightly smaller than 1.0 because the AlchemicalFactory does not use Custom*Force softcore versions if lambda = 1.0 identically. lambda_value = 1.0 - 1.0e-6 alchemical_state = AlchemicalState(0.00, lambda_value, lambda_value, lambda_value) platform = None if platform_name: platform = openmm.Platform.getPlatformByName(platform_name) # Create the perturbed system. logger.info("Creating alchemically-modified state...") initial_time = time.time() alchemical_system = factory.createPerturbedSystem(alchemical_state) final_time = time.time() elapsed_time = final_time - initial_time # Compare energies. timestep = 1.0 * units.femtosecond logger.info("Computing reference energies...") reference_integrator = openmm.VerletIntegrator(timestep) if platform: reference_context = openmm.Context(reference_system, reference_integrator, platform) else: reference_context = openmm.Context(reference_system, reference_integrator) reference_context.setPositions(positions) reference_state = reference_context.getState(getEnergy=True) reference_potential = reference_state.getPotentialEnergy() logger.info("Computing alchemical energies...") alchemical_integrator = openmm.VerletIntegrator(timestep) if platform: alchemical_context = openmm.Context(alchemical_system, alchemical_integrator, platform) else: alchemical_context = openmm.Context(alchemical_system, alchemical_integrator) alchemical_context.setPositions(positions) alchemical_state = alchemical_context.getState(getEnergy=True) alchemical_potential = alchemical_state.getPotentialEnergy() delta = alchemical_potential - reference_potential # Make sure all kernels are compiled. reference_integrator.step(1) alchemical_integrator.step(1) # Time simulations. logger.info("Simulating reference system...") initial_time = time.time() reference_integrator.step(nsteps) reference_state = reference_context.getState(getEnergy=True) reference_potential = reference_state.getPotentialEnergy() final_time = time.time() reference_time = final_time - initial_time logger.info("Simulating alchemical system...") initial_time = time.time() alchemical_integrator.step(nsteps) alchemical_state = alchemical_context.getState(getEnergy=True) alchemical_potential = alchemical_state.getPotentialEnergy() final_time = time.time() alchemical_time = final_time - initial_time logger.info("TIMINGS") logger.info( "reference system : %12.3f s for %8d steps (%12.3f ms/step)" % (reference_time, nsteps, reference_time / nsteps * 1000)) logger.info( "alchemical system : %12.3f s for %8d steps (%12.3f ms/step)" % (alchemical_time, nsteps, alchemical_time / nsteps * 1000)) logger.info( "alchemical simulation is %12.3f x slower than unperturbed system" % (alchemical_time / reference_time)) return delta
def run(platform_name, deviceid, two): not_obs = [True, True] system, coordinates = wcadimer.WCADimer() print("Time step: ", (wcadimer.stable_timestep * 2.0).in_units_of(units.femtoseconds)) # Minimization platform = openmm.Platform.getPlatformByName('Reference') print('Minimizing energy...') coordinates = minimize(platform, system, coordinates) print('Separation distance: {}'.format( norm(coordinates[1, :] - coordinates[0, :]) / units.angstroms)) print('Equilibrating...') platform = openmm.Platform.getPlatformByName(platform_name) if platform_name == 'CUDA': platform.setPropertyDefaultValue('CudaDeviceIndex', '%d' % deviceid) platform.setPropertyDefaultValue('CudaPrecision', 'mixed') elif platform_name == 'OpenCL': platform.setPropertyDefaultValue('OpenCLDeviceIndex', '%d' % deviceid) platform.setPropertyDefaultValue('OpenCLPrecision', 'mixed') integrator = openmm.LangevinIntegrator(wcadimer.temperature, wcadimer.collision_rate, 2.0 * wcadimer.stable_timestep) context = openmm.Context(system, integrator, platform) context.setPositions(coordinates) context.setVelocitiesToTemperature(wcadimer.temperature) if two: while not_obs[0] or not_obs[1]: integrator.step(5000) state = context.getState(getPositions=True) coordinates = state.getPositions(asNumpy=True) sep_dist = norm(coordinates[1, :] - coordinates[0, :]) / units.angstroms print('Separation distance: {}'.format(sep_dist)) if sep_dist < 5.7: not_obs[0] = False tag = '_a' sep_dist_a = sep_dist else: not_obs[1] = False tag = '_b' sep_dist_b = sep_dist if not os.path.isdir('bstates'): os.makedirs('bstates') np.savez_compressed('bstates/init_coords{}.npz'.format(tag), coord=coordinates / units.nanometers) print(sep_dist_a, sep_dist_b) else: integrator.step(5000) state = context.getState(getPositions=True) coordinates = state.getPositions(asNumpy=True) print('Separation distance: {}'.format( norm(coordinates[1, :] - coordinates[0, :]) / units.angstroms)) if not os.path.isdir('bstates'): os.makedirs('bstates') np.save('bstates/init_coords.npy', coordinates / units.nanometers)
def addMissingAtoms(self): """Add all missing heavy atoms, as specified by the missingAtoms, missingTerminals, and missingResidues fields.""" # Create a Topology that 1) adds missing atoms, 2) removes all hydrogens, and 3) removes unknown molecules. (newTopology, newPositions, newAtoms, existingAtomMap) = self._addAtomsToTopology(True, True) if len(newAtoms) > 0: # Create a System for energy minimizing it. res = list(newTopology.residues()) forcefield = self._createForceField(newTopology, False) system = forcefield.createSystem(newTopology) # Set any previously existing atoms to be massless, they so won't move. for atom in existingAtomMap.itervalues(): system.setParticleMass(atom.index, 0.0) # If any heavy atoms were omitted, add them back to avoid steric clashes. nonbonded = [f for f in system.getForces() if isinstance(f, mm.CustomNonbondedForce)][0] for atom in self.topology.atoms(): if atom.element not in (None, hydrogen) and atom not in existingAtomMap: system.addParticle(0.0) nonbonded.addParticle([]) newPositions.append(self.positions[atom.index]) # For efficiency, only compute interactions that involve a new atom. nonbonded.addInteractionGroup([atom.index for atom in newAtoms], range(system.getNumParticles())) # Do an energy minimization. integrator = mm.LangevinIntegrator(300*unit.kelvin, 10/unit.picosecond, 5*unit.femtosecond) context = mm.Context(system, integrator) context.setPositions(newPositions) mm.LocalEnergyMinimizer.minimize(context) state = context.getState(getPositions=True) nearest = self._findNearestDistance(context, newTopology, newAtoms) if nearest < 0.15: # Some atoms are very close together. Run some dynamics while slowly increasing the strength of the # repulsive interaction to try to improve the result. for i in range(10): context.setParameter('C', 0.15*(i+1)) integrator.step(200) d = self._findNearestDistance(context, newTopology, newAtoms) if d > nearest: nearest = d state = context.getState(getPositions=True) if nearest >= 0.15: break context.setState(state) state = context.getState(getPositions=True) # Now create a new Topology, including all atoms from the original one and adding the missing atoms. (newTopology2, newPositions2, newAtoms2, existingAtomMap2) = self._addAtomsToTopology(False, False) # Copy over the minimized positions for the new atoms. for a1, a2 in zip(newAtoms, newAtoms2): newPositions2[a2.index] = state.getPositions()[a1.index] self.topology = newTopology2 self.positions = newPositions2
def run(): import sys if sys.argv[1] == 'dhfr': [system, positions, testsystem_name] = dhfr() elif sys.argv[1] == 'tip3p': [system, positions, testsystem_name] = tip3p() precision = sys.argv[2] platform_name = sys.argv[3] print('%s %s : contains %d particles' % (testsystem_name, precision, system.getNumParticles())) print('') # Remove CMMotionRemover and barostat indices_to_remove = list() for index in range(system.getNumForces()): force = system.getForce(index) force_name = force.__class__.__name__ print(force_name) if force_name in ['MonteCarloBarostat', 'CMMotionRemover']: print('Removing %s (force index %d)' % (force_name, index)) indices_to_remove.append(index) indices_to_remove.reverse() for index in indices_to_remove: system.removeForce(index) print('') # Add barostat barostat = openmm.MonteCarloBarostat(pressure, temperature, frequency) # Create OpenMM context print('Creating context...') from openmmtools import integrators integrator = integrators.VelocityVerletIntegrator(timestep) integrator.setConstraintTolerance(1.0e-8) platform = openmm.Platform.getPlatformByName(platform_name) platform.setPropertyDefaultValue('Precision', precision) if platform_name == 'CUDA': platform.setPropertyDefaultValue('DeterministicForces', 'true') print('Using deterministic forces...') context = openmm.Context(system, integrator, platform) context.setPositions(positions) print('') # Get PME parameters print('Retrieving PME parameters...') for force in system.getForces(): if force.__class__.__name__ == 'NonbondedForce': nbforce = force break pme_parameters = nbforce.getPMEParametersInContext(context) print(pme_parameters) # Flush sys.stdout.flush() # Equilibrate with barostat print('equilibrating...') barostat.setFrequency(frequency) from progressbar import Percentage, Bar, ETA, RotatingMarker widgets = [ 'equilibration: ', Percentage(), ' ', Bar(marker=RotatingMarker()), ' ', ETA() ] progress = ProgressBar(widgets=widgets) for iteration in progress(range(nequil)): context.setVelocitiesToTemperature(temperature) integrator.step(nequilsteps) # Get positions, velocities, and box vectors print('') state = context.getState(getPositions=True, getVelocities=True) box_vectors = state.getPeriodicBoxVectors() positions = state.getPositions(asNumpy=True) velocities = state.getVelocities(asNumpy=True) del context, integrator # Remove CMMotionRemover and barostat indices_to_remove = list() for index in range(system.getNumForces()): force = system.getForce(index) force_name = force.__class__.__name__ print(force_name) if force_name in ['MonteCarloBarostat', 'CMMotionRemover']: print('Removing %s (force index %d)' % (force_name, index)) indices_to_remove.append(index) indices_to_remove.reverse() for index in indices_to_remove: system.removeForce(index) # integrator = integrators.VelocityVerletIntegrator(timestep) integrator.setConstraintTolerance(1.0e-8) context = openmm.Context(system, integrator, platform) context.setPeriodicBoxVectors(*box_vectors) context.setPositions(positions) context.setVelocities(velocities) # Open NetCDF file for writing. ncfile = netcdf.Dataset( 'work-%s-%s-%s.nc' % (testsystem_name, precision, platform_name), 'w') ncfile.createDimension('nwork', 0) # extensible dimension ncfile.createDimension('nworkvals', nworkvals + 1) ncfile.createVariable('work', np.float32, ('nwork', 'nworkvals')) work = np.zeros([nwork, nworkvals + 1], np.float32) for i in range(nwork): context.setVelocitiesToTemperature(temperature) integrator.step(nequilsteps) # equilibrate state = context.getState(getEnergy=True) initial_energy = state.getPotentialEnergy() + state.getKineticEnergy() widgets = [ 'Work %5d / %5d: ' % (i, nwork), Percentage(), ' ', Bar(marker=RotatingMarker()), ' ', ETA() ] progress = ProgressBar(widgets=widgets) for workval in progress(range(nworkvals)): integrator.step(nworksteps) state = context.getState(getEnergy=True) current_energy = state.getPotentialEnergy( ) + state.getKineticEnergy() work[i, workval + 1] = (current_energy - initial_energy) / kT ncfile.variables['work'][i, workval + 1] = work[i, workval + 1] print(work[i, :]) ncfile.sync()