def add_interactions(self, state: interfaces.IState, system: mm.System, topology: app.Topology) -> mm.System: if self.active: if self.use_pbc: cartesian_force = mm.CustomExternalForce( "0.5 * cart_force_const * r_eff^2;" "r_eff = max(0.0, r - cart_delta);" "r = periodicdistance(x, y, z, cart_x, cart_y, cart_z)") else: cartesian_force = mm.CustomExternalForce( "0.5 * cart_force_const * r_eff^2;" "r_eff = max(0.0, r - cart_delta);" "r = sqrt(dx*dx + dy*dy + dz*dz);" "dx = x - cart_x;" "dy = y - cart_y;" "dz = z - cart_z;") cartesian_force.addPerParticleParameter("cart_x") cartesian_force.addPerParticleParameter("cart_y") cartesian_force.addPerParticleParameter("cart_z") cartesian_force.addPerParticleParameter("cart_delta") cartesian_force.addPerParticleParameter("cart_force_const") # add the atoms for r in self.restraints: weight = r.force_const cartesian_force.addParticle(r.atom_index, [r.x, r.y, r.z, r.delta, weight]) system.addForce(cartesian_force) self.force = cartesian_force return system
def attraction_to_the_core(sim_object, k, r0, coreParticles=[]): """Attracts a subset of particles to the core, repells the rest from the core""" attractForce = openmm.CustomExternalForce( " COREk * ((COREr - CORErn) ^ 2) ; " "COREr = sqrt(x^2 + y^2 + COREtt^2)") attractForce.addGlobalParameter( "COREk", k * sim_object.kT / (sim_object.conlen * sim_object.conlen)) attractForce.addGlobalParameter("CORErn", r0 * sim_object.conlen) attractForce.addGlobalParameter("COREtt", 0.001 * sim_object.conlen) sim_object.force_dict["CoreAttraction"] = attractForce for i in coreParticles: attractForce.addParticle(int(i), []) if r0 > 0.1: excludeForce = openmm.CustomExternalForce( " CORE2k * ((CORE2r - CORE2rn) ^ 2) * step(CORE2rn - CORE2r) ;" "CORE2r = sqrt(x^2 + y^2 + CORE2tt^2)") excludeForce.addGlobalParameter( "CORE2k", k * sim_object.kT / (sim_object.conlen * sim_object.conlen)) excludeForce.addGlobalParameter("CORE2rn", r0 * sim_object.conlen) excludeForce.addGlobalParameter("CORE2tt", 0.001 * sim_object.conlen) sim_object.force_dict["CoreExclusion"] = excludeForce for i in range(sim_object.N): excludeForce.addParticle(i, [])
def add_interactions( self, state: interfaces.IState, system: mm.System, topology: app.Topology ) -> mm.System: if self.active: # create the confinement force if self.use_pbc: confinement_force = mm.CustomExternalForce( "step(r - radius) * force_const * (radius - r)^2;" "r = periodicdistance(x, y, z, 0, 0 ,0)" ) else: confinement_force = mm.CustomExternalForce( "step(r - radius) * force_const * (radius - r)^2;" "r=sqrt(x*x + y*y + z*z)" ) confinement_force.addPerParticleParameter("radius") confinement_force.addPerParticleParameter("force_const") # add the atoms for r in self.restraints: weight = r.force_const confinement_force.addParticle(r.atom_index, [r.radius, weight]) system.addForce(confinement_force) self.force = confinement_force return system
def gravity(sim_object, k=0.1, cutoff=None): """adds force pulling downwards in z direction When using cutoff, acts only when z>cutoff""" sim_object.metadata["gravity"] = repr({"k": k, "cutoff": cutoff}) if cutoff is None: gravity = openmm.CustomExternalForce("kG * z") else: gravity = openmm.CustomExternalForce( "kG * (z - cutoffG) * step(z - cutoffG)") gravity.addGlobalParameter("cutoffG", cutoff * nm) gravity.addGlobalParameter("kG", k * sim_object.kT / (nm)) for i in range(sim_object.N): gravity.addParticle(i, []) sim_object.force_dict["Gravity"] = gravity
def restraint_force(self, indices=None, strength=5.0): """ Force that restrains atoms to fix their positions, while allowing tiny movement to resolve severe clashes and so on. Returns ------- force : simtk.openmm.CustomExternalForce A custom force to restrain the selected atoms """ if self.system.usesPeriodicBoundaryConditions(): expression = 'k*periodicdistance(x, y, z, x0, y0, z0)^2' else: expression = 'k*((x-x0)^2 + (y-y0)^2 + (z-z0)^2)' force = mm.CustomExternalForce(expression) force.addGlobalParameter('k', strength*u.kilocalories_per_mole/u.angstroms**2) force.addPerParticleParameter('x0') force.addPerParticleParameter('y0') force.addPerParticleParameter('z0') positions = self.positions if self.positions is not None else self.handler.positions if indices is None: indices = range(self.handler.topology.getNumAtoms()) for index in indices: force.addParticle(int(index), positions[index].value_in_unit(u.nanometers)) return force
def make_harmonic_context(self, K): """ Create the system in openmm with for a specified force constant. """ # Create the system and harmonic force system = openmm.System() system.addParticle(self.mass) energy_expression = '(K/2.0) * (x^2 + y^2 + z^2);' force = openmm.CustomExternalForce(energy_expression) force.addGlobalParameter('K', K.in_unit_system(unit.md_unit_system)) force.addParticle(0, []) system.addForce(force) # Create the integrator and context integrator = openmm.LangevinIntegrator(self.temperature, self.collision_rate, self.timestep) platform = openmm.Platform.getPlatformByName(self.platform_name) context = openmm.Context(system, integrator, platform) # Set the positions and velocities. positions = unit.Quantity(self.position, unit.angstroms) context.setPositions(positions) if self.velocity is None: context.setVelocitiesToTemperature(self.temperature) else: context.setVelocities(self.velocity) return context, integrator, system
def _create_openmm_system(self): self._log('In create_openmm_system ') atoms = self.atoms self._particle_positions = atoms.coords bonds = self.structure.bonds self._topology = openmm_topology(atoms, bonds) from simtk.openmm import app forcefield = app.ForceField(*self._forcefields) # self._add_hydrogens(pdb, forcefield) self._system = system = self._create_system(forcefield) # path = '/Users/goddard/ucsf/amber/sustiva_tutorial/1FKO_sus.prmtop' # crd_path = path[:-7] + '.rst7' # path = '/Users/goddard/ucsf/amber/gfp_tutorial/gfp.parm7' # crd_path = '/Users/goddard/ucsf/amber/gfp_tutorial/min1.rst7' # self._system_from_prmtop(path, crd_path) from simtk import openmm as mm platform = mm.Platform.getPlatformByName(self._platform_name) self._platform = platform # Setup pulling force e = 'k*((x-x0)^2+(y-y0)^2+(z-z0)^2)' self._force = force = mm.CustomExternalForce(e) force.addPerParticleParameter('k') for p in ('x0', 'y0', 'z0'): force.addGlobalParameter(p, 0.0) system.addForce(force)
def _interpolation_grid_force(self): self._widths = [] self._bounds = [] self._extra_points = [] for v in self.bias_variables: extra_points = min(self.grid_expansion, v.grid_size) if v.periodic else 0 extra_range = extra_points*v._range/(v.grid_size - 1) self._widths.append(v.grid_size + 2*extra_points) self._bounds += [v.min_value - extra_range, v.max_value + extra_range] self._extra_points.append(extra_points) self._bias = np.zeros(np.prod(self._widths)) num_bias_variables = len(self.bias_variables) if num_bias_variables == 1: self._table = openmm.Continuous1DFunction(self._bias, *self._bounds) elif num_bias_variables == 2: self._table = openmm.Continuous2DFunction(*self._widths, self._bias, *self._bounds) else: self._table = openmm.Continuous3DFunction(*self._widths, self._bias, *self._bounds) expression = f'bias({",".join(v.id for v in self.bias_variables)})' for i, v in enumerate(self.bias_variables): expression += f';{v.id}={v._get_energy_function(i+1)}' force = openmm.CustomCVForce(expression) for i in range(num_bias_variables): x = openmm.CustomExternalForce('x') x.addParticle(0, []) force.addCollectiveVariable(f'x{i+1}', x) force.addTabulatedFunction('bias', self._table) force.addGlobalParameter('Lx', 0) return force
def __init__(self, system, volume): """Construct a velocity Verlet integrator with canonical velocity rescaling thermostat. Parameters ---------- temperature : np.unit.Quantity compatible with kelvin, default=298*unit.kelvin The temperature of the fictitious bath. collision_rate : np.unit.Quantity compatible with 1/picoseconds, default=10/unit.picoseconds The collision rate with fictitious bath particles. timestep : np.unit.Quantity compatible with femtoseconds, default=1*unit.femtoseconds The integration timestep. ndf : integer, default=0 (ignore constraints) The number of degrees of freedom to be used to calculate the temperature. useBerendsen : boolean, default=False Whether use Berendsen thermostat instead of the canonical velocity rescaling thermostat. """ nbondedForce = [ f for f in [system.getForce(i) for i in range(system.getNumForces())] if type(f) == NonbondedForce ][0] cvdipole = mm.CustomExternalForce('q*z') cvdipole.addPerParticleParameter('q') for i in range(system.getNumParticles()): (q, sig, eps) = nbondedForce.getParticleParameters(i) idxres = cvdipole.addParticle(i, [q]) cvforce = CustomCVForce("twopioverV*(muz)^2") cvforce.addCollectiveVariable("muz", cvdipole) cvforce.addGlobalParameter("twopioverV", ONE_4PI_EPS0 * 2 * np.pi / volume) system.addForce(cvforce)
def _restrain_protein(self, protein_atoms_to_restrain): """ Restrain protein atoms in system to keep protein from moving from reference position. Parameters ---------- protein_atoms_to_restrain : list of int List of atom indices to restraint """ # TODO: Allow sigma_protein to be configured print('Adding restraints to protein...') sigma_protein = 2.0 * unit.angstroms # stddev of fluctuations of protein atoms K_protein = self.kT / (sigma_protein**2) # spring constant energy_expression = '(K_protein/2)*((x-x0)^2 + (y-y0)^2 + (z-z0)^2);' force = openmm.CustomExternalForce(energy_expression) force.addGlobalParameter('K_protein', K_protein) force.addPerParticleParameter('x0') force.addPerParticleParameter('y0') force.addPerParticleParameter('z0') for particle_index in protein_atoms_to_restrain: x0, y0, z0 = self._get_reference_coordinates( particle_index) / unit.nanometers force.addParticle(int(particle_index), [x0, y0, z0]) self.system.addForce(force)
def spherical_well(sim_object, r=10, depth=1): """pushes particles towards a boundary of a cylindrical well to create uniform well coverage""" extforce4 = openmm.CustomExternalForce( "WELLdepth * (((sin((WELLr * 3.141592 * 0.5) / WELLwidth)) ^ 10) -1) * step(-WELLr + WELLwidth);" "WELLr = sqrt(x^2 + y^2 + z^2 + WELLtt^2)") sim_object.force_dict["Well attraction"] = extforce4 # adding all the particles on which force acts for i in range(sim_object.N): if sim_object.domains[i] > 0.5: extforce4.addParticle(i, []) if r is None: try: r = sim_object.sphericalConfinementRadius * 0.5 except: exit("No spherical confinement radius defined yet." " Apply spherical confinement first!") if sim_object.verbose == True: print("Well attraction added with r = %d" % r) # assigning parameters of the force extforce4.addGlobalParameter("WELLwidth", r * nm) extforce4.addGlobalParameter("WELLdepth", depth * sim_object.kT) extforce4.addGlobalParameter("WELLtt", 0.01 * nm)
def create_walls(sim_object, left=None, right=None, k=0.5): "creates walls at x = left, x = right, x direction only" if left is None: left = sim_object.data[0][0] + 1.0 * nm else: left = 1.0 * nm * left if right is None: right = sim_object.data[-1][0] - 1.0 * nm else: right = 1.0 * nm * right if sim_object.verbose == True: print("left wall created at ", left / (1.0 * nm)) print("right wall created at ", right / (1.0 * nm)) extforce2 = openmm.CustomExternalForce( " WALLk * (sqrt((x - WALLright) * (x-WALLright) + WALLa * WALLa ) - WALLa) * step(x-WALLright) " "+ WALLk * (sqrt((x - WALLleft) * (x-WALLleft) + WALLa * WALLa ) - WALLa) * step(WALLleft - x) " ) extforce2.addGlobalParameter("WALLk", k * sim_object.kT / nm) extforce2.addGlobalParameter("WALLleft", left) extforce2.addGlobalParameter("WALLright", right) extforce2.addGlobalParameter("WALLa", 1 * nm) for i in range(sim_object.N): extforce2.addParticle(i, []) sim_object.force_dict["WALL Force"] = extforce2
def __init__(self, n_workers=1, n_simulation_steps=0): try: with warnings.catch_warnings(): warnings.simplefilter( "ignore", DeprecationWarning) # ignore warnings inside OpenMM from simtk import openmm, unit except ImportError: pytest.skip("Test requires OpenMM.") # a system with one particle and an external dummy force system = openmm.System() system.addParticle(1.0 * unit.amu) force = openmm.CustomExternalForce("x") force.addParticle(0) system.addForce(force) super(OneParticleTestBridge, self).__init__( system, openmm.LangevinIntegrator(300 * unit.kelvin, 1.0 / unit.picoseconds, 1.0 * unit.femtoseconds), n_workers=n_workers, n_simulation_steps=n_simulation_steps, )
def _addPositionalHarmonicFlatBottomRestraints(self, sys): go = [] for (fcounter,conn,tables,offset) in self._localVars(): if not self._hasTable('posre_harmflatbottom_term',tables): go.append(False) else: go.append(True) if go[fcounter] and (not self._hasTable('posre_harmflatbottom_param',tables)): raise IOError('DMS file lacks posre_harmflatbottom_param table even though posre_harm_term table is present.') return if not any(go): return if self._verbose: print("Using positional harmonic flat bottom restraints.") #flat-bottom harmonic potential, #select() is to avoid the singularity at zero distance if self.pbc: force = mm.CustomExternalForce("hk*select(step(dist-tol), (dist-tol)^2, 0); dist = periodicdistance(x,y,z,x0,y0,z0)") else: force = mm.CustomExternalForce("hk*select(step(dist-tol), (dist-tol)^2, 0); dist = sqrt((x-x0)^2+(y-y0)^2+(z-z0)^2)") force.addPerParticleParameter("x0") force.addPerParticleParameter("y0") force.addPerParticleParameter("z0") force.addPerParticleParameter("hk") force.addPerParticleParameter("tol") sys.addForce(force) force.setForceGroup(self._bonded_force_group) q = """SELECT p0, x0, y0, z0, fc, tol FROM posre_harmflatbottom_term INNER JOIN posre_harmflatbottom_param ON posre_harmflatbottom_term.param=posre_harmflatbottom_param.id""" for (fcounter,conn,tables,offset) in self._localVars(): if not go[fcounter]: continue for p0, x0, y0, z0, fc, tol in conn.execute(q): p0 += offset x0d = (x0*angstrom).value_in_unit(nanometer) y0d = (y0*angstrom).value_in_unit(nanometer) z0d = (z0*angstrom).value_in_unit(nanometer) hfcd = (0.5*fc*kilocalorie_per_mole/angstrom**2).value_in_unit(kilojoule_per_mole/(nanometer**2)) told = (tol*angstrom).value_in_unit(nanometer) force.addParticle(int(p0),np.array([ x0d, y0d, z0d, hfcd, told]))
def tether_particles(sim_object, particles, k=30, positions="current", name="Tethers"): """tethers particles in the 'particles' array. Increase k to tether them stronger, but watch the system! Parameters ---------- particles : list of ints List of particles to be tethered (fixed in space). Negative values are allowed. k : int, optional The steepness of the tethering potential. Values >30 will require decreasing potential, but will make tethering rock solid. Can be provided as a vector [kx, ky, kz]. """ energy = "kx * (x - x0)^2 + ky * (y - y0)^2 + kz * (z - z0)^2" force = openmm.CustomExternalForce(energy) force.name = name # assigning parameters of the force if isinstance(k, Iterable): k = list(k) if len(k) != 3: raise ValueError("k must either be a scalar or a 3D vector!") kx, ky, kz = k else: kx, ky, kz = k, k, k nm2 = simtk.unit.nanometer * simtk.unit.nanometer force.addGlobalParameter("kx", kx * sim_object.kT / nm2) force.addGlobalParameter("ky", ky * sim_object.kT / nm2) force.addGlobalParameter("kz", kz * sim_object.kT / nm2) force.addPerParticleParameter("x0") force.addPerParticleParameter("y0") force.addPerParticleParameter("z0") particles = [sim_object.N + i if i < 0 else i for i in particles] if positions == "current": positions = [sim_object.data[i] for i in particles] else: positions = simtk.unit.Quantity(positions, simtk.unit.nanometer) # adding all the particles on which force acts for i, pos in zip(particles, positions): i = int(i) force.addParticle(i, list(pos)) if sim_object.verbose == True: print("particle %d tethered! " % i) return force
def setRestraints(self, restrained_sets): #=['protein and backbone'], #forces=[100*kilojoules_per_mole/angstroms]): """ Set position restraints on atom set(s). Parameters ---------- restrained_sets : list of str, optional Selection(s) (MDTraj). The default is ['protein and backbone']. forces : list of int, optional The force applied in kilojoules_per_mole/angstroms. The default is 100. Returns ------- system : TYPE DESCRIPTION. """ #('protein and name CA and not chainid 1', 'chainid 3 and resid 0') #trajectory_out_atoms = 'protein or resname SAM or resname ZNB' topology = md.Topology().from_openmm(self.topology) equation="(k/2)*periodicdistance(x, y, z, x0, y0, z0)^2" print('Applying potential: ', equation) if len(restrained_sets['selections']) == len(restrained_sets['forces']): for restrained_set, force_value in zip(restrained_sets['selections'], restrained_sets['forces']): force = omm.CustomExternalForce(equation) force.addGlobalParameter("k", force_value*kilojoules_per_mole/angstroms**2) force.addPerParticleParameter("x0") force.addPerParticleParameter("y0") force.addPerParticleParameter("z0") print(f'Restraining set ({force_value*kilojoules_per_mole/angstroms**2}): {len(topology.select(restrained_set))}') for res_atom_index in topology.select(restrained_set): force.addParticle(int(res_atom_index), self.positions[int(res_atom_index)].value_in_unit(unit.nanometers)) # TODO: Decide wether to spawn system reps. Streamlined now. Legacy removes later. self.system.addForce(force) return self.system else: print('Inputs for restrained sets are not the same length.')
def minimization(prmtop, inpcrd, PLATFORM, constraints, parameters, platformProperties): """ Function that runs a minimization of the system it uses the VerletIntegrator and applys to the heavy atoms of the protein and ligand. :param prmtop: OpenMM Topology object :param inpcrd: OpenMM Positions object :param PLATFORM: platform in which the minimization will run :type PLATFORM: str :param constraints: strength of the constrain (units: Kcal/mol) :type constraints: int :param parameters: Object with the parameters for the simulation :type parameters: :py:class:`/simulationrunner/SimulationParameters` -- SimulationParameters object :param platformProperties: Properties specific to the OpenMM platform :type platformProperties: dict :return: The minimized OpenMM simulation object """ # Thermostat system = prmtop.createSystem(nonbondedMethod=app.PME, nonbondedCutoff=parameters.nonBondedCutoff * unit.angstroms, constraints=app.HBonds) # system.addForce(mm.AndersenThermostat(parameters.Temperature * unit.kelvin, 1 / unit.picosecond)) integrator = mm.VerletIntegrator(parameters.timeStep * unit.femtoseconds) if constraints: # Add positional restraints to protein backbone force = mm.CustomExternalForce(str("k*((x-x0)^2+(y-y0)^2+(z-z0)^2)")) force.addGlobalParameter( str("k"), constraints * unit.kilocalories_per_mole / unit.angstroms**2) force.addPerParticleParameter(str("x0")) force.addPerParticleParameter(str("y0")) force.addPerParticleParameter(str("z0")) for j, atom in enumerate(prmtop.topology.atoms()): if (atom.name in ('CA', 'C', 'N', 'O') and atom.residue.name != "HOH") or (atom.residue.name == parameters.ligandName and atom.element.symbol != "H"): force.addParticle( j, inpcrd.positions[j].value_in_unit(unit.nanometers)) system.addForce(force) simulation = app.Simulation(prmtop.topology, system, integrator, PLATFORM, platformProperties=platformProperties) if inpcrd.boxVectors is not None: simulation.context.setPeriodicBoxVectors(*inpcrd.boxVectors) simulation.context.setPositions(inpcrd.positions) simulation.minimizeEnergy(maxIterations=parameters.minimizationIterations) return simulation
def initialize_tugging_force(self, potential_equation, g_params, g_vals, pp_params): from simtk import openmm as mm f = self._tugging_force = mm.CustomExternalForce(potential_equation) if g_params is not None: for p, v in zip(g_params, g_vals): f.addGlobalParameter(g, v) if pp_params is not None: for p in pp_params: f.addPerParticleParameter(p) return f
def make_harmonic_system(n_particles, force_constant): """System with one harmonic oscillator.""" system = mm.System() harmonic = mm.CustomExternalForce("0.5 * force_constant * (x-0.5)^2") harmonic.addGlobalParameter("force_constant", force_constant) system.setDefaultPeriodicBoxVectors(mm.Vec3(1, 0, 0), mm.Vec3(0, 1, 0), mm.Vec3(0, 0, 1)) for i in range(n_particles): system.addParticle(1.0) harmonic.addParticle(i) system.addForce(harmonic) return system
def cylindrical_confinement(sim_object, r, bottom=None, k=0.1, top=9999, name="cylindrical_confinement"): """As it says.""" if bottom == True: warnings.warn( DeprecationWarning("Use bottom=0 instead of bottom = True! ")) bottom = 0 if bottom is not None: force = openmm.CustomExternalForce( "kt * k * (" " step(dr) * (sqrt(dr*dr + t*t) - t)" " + step(-z + bottom) * (sqrt((z - bottom)^2 + t^2) - t) " " + step(z - top) * (sqrt((z - top)^2 + t^2) - t)" ") ;" "dr = sqrt(x^2 + y^2 + tt^2) - r + 10*t") else: force = openmm.CustomExternalForce( "kt * k * step(dr) * (sqrt(dr*dr + t*t) - t);" "dr = sqrt(x^2 + y^2 + tt^2) - r + 10*t") force.name = name for i in range(sim_object.N): force.addParticle(i, []) force.addGlobalParameter("k", k / simtk.unit.nanometer) force.addGlobalParameter("r", r * sim_object.conlen) force.addGlobalParameter("kt", sim_object.kT) force.addGlobalParameter("t", 0.1 / k * simtk.unit.nanometer) force.addGlobalParameter("tt", 0.01 * simtk.unit.nanometer) force.addGlobalParameter("top", top * sim_object.conlen) if bottom is not None: force.addGlobalParameter("bottom", bottom * sim_object.conlen) return force
def restrain_atoms(thermodynamic_state, sampler_state, topology, atoms_dsl, sigma=3.0*unit.angstroms): """Apply a soft harmonic restraint to the given atoms. This modifies the ``ThermodynamicState`` object. Parameters ---------- thermodynamic_state : openmmtools.states.ThermodynamicState The thermodynamic state with the system. This will be modified. sampler_state : openmmtools.states.SamplerState The sampler state with the positions. topology : mdtraj.Topology or simtk.openmm.Topology The topology of the system. atoms_dsl : str The MDTraj DSL string for selecting the atoms to restrain. sigma : simtk.unit.Quantity, optional Controls the strength of the restrain. The smaller, the tighter (units of distance, default is 3.0*angstrom). """ K = thermodynamic_state.kT / sigma**2 # Spring constant. system = thermodynamic_state.system # This is a copy. # Make sure the topology is an MDTraj topology. if isinstance(topology, mdtraj.Topology): mdtraj_topology = topology else: mdtraj_topology = mdtraj.Topology.from_openmm(topology) # Translate the system to the origin to avoid # MonteCarloBarostat rejections (see openmm#1854). protein_atoms = mdtraj_topology.select('protein') distance_unit = sampler_state.positions.unit centroid = np.mean(sampler_state.positions[protein_atoms,:] / distance_unit, 0) * distance_unit sampler_state.positions -= centroid # Create a CustomExternalForce to restrain all atoms. restraint_force = openmm.CustomExternalForce('(K/2)*((x-x0)^2 + (y-y0)^2 + (z-z0)^2)') restrained_atoms = mdtraj_topology.select(atoms_dsl).tolist() # Adding the spring constant as a global parameter allows us to turn it off if desired restraint_force.addGlobalParameter('K', K) restraint_force.addPerParticleParameter('x0') restraint_force.addPerParticleParameter('y0') restraint_force.addPerParticleParameter('z0') for index in restrained_atoms: parameters = sampler_state.positions[index,:].value_in_unit_system(unit.md_unit_system) restraint_force.addParticle(index, parameters) # Update thermodynamic state. system.addForce(restraint_force) thermodynamic_state.system = system
def _addPositionalHarmonicRestraints(self, sys): go = [] for (fcounter, conn, tables, offset) in self._localVars(): if not self._hasTable('posre_harm_term', tables): go.append(False) else: go.append(True) if go[fcounter] and (not self._hasTable('posre_harm_param', tables)): raise IOError( 'DMS file lacks posre_harm_param table even though posre_harm_term table is present.' ) return if not any(go): return if self._verbose: print("Using positional harmonic restraints.") force = mm.CustomExternalForce( "hkx*(x-x0)^2+hky*(y-y0)^2+hkz*(z-z0)^2") force.addPerParticleParameter("x0") force.addPerParticleParameter("y0") force.addPerParticleParameter("z0") force.addPerParticleParameter("hkx") force.addPerParticleParameter("hky") force.addPerParticleParameter("hkz") sys.addForce(force) q = """SELECT p0, x0, y0, z0, fcx, fcy, fcz FROM posre_harm_term INNER JOIN posre_harm_param ON posre_harm_term.param=posre_harm_param.id""" for (fcounter, conn, tables, offset) in self._localVars(): if not go[fcounter]: continue for p0, x0, y0, z0, fcx, fcy, fcz in conn.execute(q): p0 += offset x0d = (x0 * angstrom).value_in_unit(nanometer) y0d = (y0 * angstrom).value_in_unit(nanometer) z0d = (z0 * angstrom).value_in_unit(nanometer) hfcxd = (0.5 * fcx * kilocalorie_per_mole / angstrom**2).value_in_unit(kilojoule_per_mole / (nanometer**2)) hfcyd = (0.5 * fcy * kilocalorie_per_mole / angstrom**2).value_in_unit(kilojoule_per_mole / (nanometer**2)) hfczd = (0.5 * fcz * kilocalorie_per_mole / angstrom**2).value_in_unit(kilojoule_per_mole / (nanometer**2)) force.addParticle(p0, [x0d, y0d, z0d, hfcxd, hfcyd, hfczd])
def minimization(prmtop, inpcrd, PLATFORM, constraints, parameters, platformProperties, dummy=None): """ Function that runs a minimization of the system it uses the VerletIntegrator and applys to the heavy atoms of the protein and ligand. :param prmtop: OpenMM Topology object :param inpcrd: OpenMM Positions object :param PLATFORM: platform in which the minimization will run :type PLATFORM: str :param constraints: strength of the constrain (units: Kcal/mol) :type constraints: int :param parameters: Object with the parameters for the simulation :type parameters: :py:class:`/simulationrunner/SimulationParameters` -- SimulationParameters object :param platformProperties: Properties specific to the OpenMM platform :type platformProperties: dict :param dummy: Index of the dummy atom introduced as center of the box :type dummy: int :return: The minimized OpenMM simulation object """ system = prmtop.createSystem(nonbondedMethod=app.PME, nonbondedCutoff=parameters.nonBondedCutoff * unit.angstroms, constraints=app.HBonds) integrator = mm.VerletIntegrator(parameters.timeStep * unit.femtoseconds) if parameters.constraints is not None: # Add the specified constraints to the system addConstraints(system, prmtop.topology, parameters.constraints) if parameters.boxCenter or parameters.cylinderBases: # the last parameter is only used to print a message, by passing a # value different than 0 we avoid having too many prints addDummyAtomToSystem(system, prmtop.topology, inpcrd.positions, parameters.ligandName, dummy, 3) if constraints: # Add positional restraints to protein backbone force = mm.CustomExternalForce(str("k*periodicdistance(x, y, z, x0, y0, z0)^2")) force.addGlobalParameter(str("k"), constraints * unit.kilocalories_per_mole / unit.angstroms ** 2) force.addPerParticleParameter(str("x0")) force.addPerParticleParameter(str("y0")) force.addPerParticleParameter(str("z0")) atomNames = ('CA', 'C', 'N', 'O') for j, atom in enumerate(prmtop.topology.atoms()): if (atom.name in atomNames and atom.residue.name != "HOH") or (atom.residue.name == parameters.ligandName and atom.element.symbol != "H"): force.addParticle(j, inpcrd.positions[j].value_in_unit(unit.nanometers)) system.addForce(force) simulation = app.Simulation(prmtop.topology, system, integrator, PLATFORM, platformProperties=platformProperties) if inpcrd.boxVectors is not None: simulation.context.setPeriodicBoxVectors(*inpcrd.boxVectors) simulation.context.setPositions(inpcrd.positions) simulation.minimizeEnergy(maxIterations=parameters.minimizationIterations) return simulation
def __init__(self, variables, height, frequency, grid_expansion): self.bias_variables = [cv for cv in variables if cv.sigma is not None] self.height = height self.frequency = frequency self.grid_expansion = grid_expansion self._widths = [] self._bounds = [] self._expanded = [] self._extra_points = [] for cv in self.bias_variables: expanded = cv.periodic # and len(self.bias_variables) > 1 extra_points = min(grid_expansion, cv.grid_size) if expanded else 0 extra_range = extra_points * cv._range / (cv.grid_size - 1) self._widths += [cv.grid_size + 2 * extra_points] self._bounds += [ cv.min_value - extra_range, cv.max_value + extra_range ] self._expanded += [expanded] self._extra_points += [extra_points] self._bias = np.zeros(tuple(reversed(self._widths))) if len(variables) == 1: self._table = openmm.Continuous1DFunction( self._bias.flatten(), *self._bounds, # self.bias_variables[0].periodic, ) elif len(variables) == 2: self._table = openmm.Continuous2DFunction( *self._widths, self._bias.flatten(), *self._bounds, ) elif len(variables) == 3: self._table = openmm.Continuous3DFunction( *self._widths, self._bias.flatten(), *self._bounds, ) else: raise ValueError( 'UFED requires 1, 2, or 3 biased collective variables') parameter_list = ', '.join(f's_{cv.id}' for cv in self.bias_variables) self.force = openmm.CustomCVForce(f'bias({parameter_list})') for cv in self.bias_variables: expression = f'{cv.min_value}+{cv._range}*(x/Lx-floor(x/Lx))' parameter = openmm.CustomExternalForce(expression) parameter.addGlobalParameter('Lx', 0.0) parameter.addParticle(0, []) self.force.addCollectiveVariable(f's_{cv.id}', parameter) self.force.addTabulatedFunction('bias', self._table)
def setUp(self): system = mm.System() system.addParticle(1.0) for i in range(32): force = mm.CustomExternalForce(str(i)) force.addParticle(0, []) force.setForceGroup(i) system.addForce(force) platform = mm.Platform.getPlatformByName('Reference') context = mm.Context(system, mm.VerletIntegrator(0), platform) context.setPositions([(0, 0, 0)]) self.context = context
def wall_power(system, particles, direction, bound, k, cutoff, power=2): ''' Add a power wall for selected particles so that they cannot cross it. Note that periodic box condition is not considered, so you need to make sure particles will not move to other cells during the simulation. The energy equal to k when particle is located at the lower or higher bound, and equal to zero when particle is located between [lower bound + cutoff, higher bound - cutoff]. Parameters ---------- system : mm.System particles : list of int direction : ['x', 'y', 'z'] bound : list of float k : float cutoff : float power : int, optional Returns ------- force : mm.CustomExternalForce ''' if direction not in ['x', 'y', 'z']: raise Exception('direction can only be x, y or z') _min, _max = bound if unit.is_quantity(_min): _min = _min.value_in_unit(nm) if unit.is_quantity(_max): _max = _max.value_in_unit(nm) if unit.is_quantity(k): k = k.value_in_unit(kJ_mol) if unit.is_quantity(cutoff): cutoff = cutoff.value_in_unit(nm) _min_0 = _min + cutoff _max_0 = _max - cutoff force = mm.CustomExternalForce( f'{k}*step({_min_0}-{direction})*rmin^{power}+' f'{k}*step({direction}-{_max_0})*rmax^{power};' f'rmin=({_min_0}-{direction})/{cutoff};' f'rmax=({direction}-{_max_0})/{cutoff}') for i in particles: force.addParticle(i, []) system.addForce(force) return force
def wall_lj126(system, particles, direction, bound, epsilon, sigma): ''' Add a LJ-12-6 wall for selected particles so that they cannot cross it. Note that periodic box condition is not considered, so you need to make sure particles will not move to other cells during the simulation. The energy is infinite when particle is located at the lower or higher bound, and equal to epsilon when particle is located at lower bound + sigma or higher bound - sigma, and equal to zero when particle is located between [lower bound + sigma * 2^(1/6), higher bound - sigma * 2^(1/6)]. Parameters ---------- system : mm.System particles : list of int direction : str bound : list of float epsilon : float sigma : float Returns ------- force : mm.CustomExternalForce ''' if direction not in ['x', 'y', 'z']: raise Exception('direction can only be x, y or z') _min, _max = bound if unit.is_quantity(_min): _min = _min.value_in_unit(nm) if unit.is_quantity(_max): _max = _max.value_in_unit(nm) if unit.is_quantity(epsilon): epsilon = epsilon.value_in_unit(kJ_mol) if unit.is_quantity(sigma): sigma = sigma.value_in_unit(nm) _min_0 = _min + sigma * 2**(1 / 6) _max_0 = _max - sigma * 2**(1 / 6) force = mm.CustomExternalForce( f'4*{epsilon}*step({_min_0}-{direction})*(rmin^12-rmin^6+0.25)+' f'4*{epsilon}*step({direction}-{_max_0})*(rmax^12-rmax^6+0.25);' f'rmin={sigma}/({direction}-{_min});' f'rmax={sigma}/({_max}-{direction})') for i in particles: force.addParticle(i, []) system.addForce(force) return force
def spherical_well(sim_object, particles, r, center=[0, 0, 0], width=1, depth=1, name="spherical_well"): """ A spherical potential well, suited for example to simulate attraction to a lamina. Parameters ---------- particles : list of int or np.array indices of particles that are attracted r : float Radius of the nucleus center : vector, optional center position of the sphere. This parameter is useful when confining chromosomes to their territory. width : float, optional Width of attractive well, nm. depth : float, optional Depth of attractive potential in kT NOTE: switched sign from openmm-polymer, because it was confusing. Now this parameter is really the depth of the well, i.e. positive = attractive, negative = repulsive """ force = openmm.CustomExternalForce( "-step(1+d)*step(1-d)*SPHWELLdepth*cos(3.1415926536*d)/2 + 0.5;" "d = (sqrt((x-SPHWELLx)^2 + (y-SPHWELLy)^2 + (z-SPHWELLz)^2) - SPHWELLradius) / SPHWELLwidth" ) force.name = name force.addGlobalParameter("SPHWELLradius", r * sim_object.conlen) force.addGlobalParameter("SPHWELLwidth", width * sim_object.conlen) force.addGlobalParameter("SPHWELLdepth", depth * sim_object.kT) force.addGlobalParameter("SPHWELLx", center[0] * sim_object.conlen) force.addGlobalParameter("SPHWELLy", center[1] * sim_object.conlen) force.addGlobalParameter("SPHWELLz", center[2] * sim_object.conlen) # adding all the particles on which force acts for i in particles: # NOTE: the explicit type cast seems to be necessary if we have an np.array... force.addParticle(int(i), []) return force
def run_simulation(n_steps=10000): "Simulate a single particle in the double well" system = mm.System() system.addParticle(1)# added particle with a unit mass force = mm.CustomExternalForce('2*(x-1)^2*(x+1)^2 + y^2')# defines the potential force.addParticle(0, []) system.addForce(force) integrator = mm.LangevinIntegrator(500, 1, 0.02)% Langevin integrator with 500K temperature, gamma=1, step size = 0.02 context = mm.Context(system, integrator) context.setPositions([[0, 0, 0]]) context.setVelocitiesToTemperature(500) x = np.zeros((n_steps, 3)) for i in range(n_steps): x[i] = context.getState(getPositions=True).getPositions(asNumpy=True)._value integrator.step(1) return x
def add_spherical_container(system: mm.System, args: ListOfArgs): print(" Adding spherical container...") container_force = mm.CustomExternalForce( '{}*max(0, r-{})^2; r=sqrt((x-{})^2+(y-{})^2+(z-{})^2)'.format(args.SC_SCALE, args.SC_RADIUS, args.SC_CENTER_X, args.SC_CENTER_Y, args.SC_CENTER_Z, )) system.addForce(container_force) for i in range(system.getNumParticles()): container_force.addParticle(i, []) print(f" Spherical container added.") print(f" radius: {args.SC_RADIUS} nm") print(f" scale: {args.SC_SCALE} ") print(f" center: ({args.SC_CENTER_X}, {args.SC_CENTER_Y}, {args.SC_CENTER_Z})")