def createSystem(self, nonbondedMethod=ff.NoCutoff, nonbondedCutoff=1.0*u.nanometer, constraints=None, rigidWater=True, implicitSolvent=None, implicitSolventKappa=None, implicitSolventSaltConc=0.0*u.moles/u.liter, temperature=298.15*u.kelvin, soluteDielectric=1.0, solventDielectric=78.5, removeCMMotion=True, hydrogenMass=None, ewaldErrorTolerance=0.0005, flexibleConstraints=True, verbose=False): """ Construct an OpenMM System representing the topology described by the prmtop file. Parameters: - nonbondedMethod (object=NoCutoff) The method to use for nonbonded interactions. Allowed values are NoCutoff, CutoffNonPeriodic, CutoffPeriodic, Ewald, or PME. - nonbondedCutoff (distance=1*nanometer) The cutoff distance to use for nonbonded interactions. - constraints (object=None) Specifies which bonds or angles should be implemented with constraints. Allowed values are None, HBonds, AllBonds, or HAngles. - rigidWater (boolean=True) If true, water molecules will be fully rigid regardless of the value passed for the constraints argument - implicitSolvent (object=None) If not None, the implicit solvent model to use. Allowed values are HCT, OBC1, OBC2, or GBn - implicitSolventKappa (float=None): Debye screening parameter to model salt concentrations in GB solvent. - implicitSolventSaltConc (float=0.0*u.moles/u.liter): Salt concentration for GB simulations. Converted to Debye length `kappa' - temperature (float=298.15*u.kelvin): Temperature used in the salt concentration-to-kappa conversion for GB salt concentration term - soluteDielectric (float=1.0) The solute dielectric constant to use in the implicit solvent model. - solventDielectric (float=78.5) The solvent dielectric constant to use in the implicit solvent model. - removeCMMotion (boolean=True) If true, a CMMotionRemover will be added to the System. - hydrogenMass (mass=None) The mass to use for hydrogen atoms bound to heavy atoms. Any mass added to a hydrogen is subtracted from the heavy atom to keep their total mass the same. - ewaldErrorTolerance (float=0.0005) The error tolerance to use if the nonbonded method is Ewald or PME. - flexibleConstraints (bool=True) Are our constraints flexible or not? - verbose (bool=False) Optionally prints out a running progress report """ # Rebuild the topology file if necessary, and flush the atom property # data to the atom list if self._topology_changed(): self.remake_parm() else: self.atom_list.refresh_data() LJ_radius, LJ_depth = self.openmm_LJ() # Get our LJ parameters LJ_14_radius, LJ_14_depth = self.openmm_14_LJ() # Set the cutoff distance in nanometers cutoff = None if nonbondedMethod is not ff.NoCutoff: cutoff = nonbondedCutoff # Remove units from cutoff if u.is_quantity(cutoff): cutoff = cutoff.value_in_unit(u.nanometers) if nonbondedMethod not in (ff.NoCutoff, ff.CutoffNonPeriodic, ff.CutoffPeriodic, ff.Ewald, ff.PME): raise ValueError('Illegal value for nonbonded method') if self.ptr('ifbox') == 0 and nonbondedMethod in (ff.CutoffPeriodic, ff.Ewald, ff.PME): raise ValueError('Illegal nonbonded method for a ' 'non-periodic system') if implicitSolvent not in (HCT, OBC1, OBC2, GBn, GBn2, None): raise ValueError('Illegal implicit solvent model choice.') if not constraints in (None, ff.HAngles, ff.HBonds, ff.AllBonds): raise ValueError('Illegal constraints choice') # Define conversion factors length_conv = u.angstrom.conversion_factor_to(u.nanometer) _ambfrc = u.kilocalorie_per_mole/(u.angstrom*u.angstrom) _openmmfrc = u.kilojoule_per_mole/(u.nanometer*u.nanometer) bond_frc_conv = _ambfrc.conversion_factor_to(_openmmfrc) _ambfrc = u.kilocalorie_per_mole/(u.radians*u.radians) _openmmfrc = u.kilojoule_per_mole/(u.radians*u.radians) angle_frc_conv = _ambfrc.conversion_factor_to(_openmmfrc) dihe_frc_conv = u.kilocalorie_per_mole.conversion_factor_to( u.kilojoule_per_mole) ene_conv = dihe_frc_conv # Create the system system = mm.System() if verbose: print('Adding particles...') for mass in self.parm_data['MASS']: system.addParticle(mass) # Set up the constraints if verbose and (constraints is not None and not rigidWater): print('Adding constraints...') if constraints in (ff.HBonds, ff.AllBonds, ff.HAngles): for bond in self.bonds_inc_h: system.addConstraint(bond.atom1.starting_index, bond.atom2.starting_index, bond.bond_type.req*length_conv) if constraints in (ff.AllBonds, ff.HAngles): for bond in self.bonds_without_h: system.addConstraint(bond.atom1.starting_index, bond.atom2.starting_index, bond.bond_type.req*length_conv) if rigidWater and constraints is None: for bond in self.bonds_inc_h: if (bond.atom1.residue.resname in WATNAMES and bond.atom2.residue.resname in WATNAMES): system.addConstraint(bond.atom1.starting_index, bond.atom2.starting_index, bond.bond_type.req*length_conv) # Add Bond forces if verbose: print('Adding bonds...') force = mm.HarmonicBondForce() force.setForceGroup(self.BOND_FORCE_GROUP) if flexibleConstraints or (constraints not in (ff.HBonds, ff.AllBonds, ff.HAngles)): for bond in self.bonds_inc_h: force.addBond(bond.atom1.starting_index, bond.atom2.starting_index, bond.bond_type.req*length_conv, 2*bond.bond_type.k*bond_frc_conv) if flexibleConstraints or (constraints not in (ff.AllBonds,ff.HAngles)): for bond in self.bonds_without_h: force.addBond(bond.atom1.starting_index, bond.atom2.starting_index, bond.bond_type.req*length_conv, 2*bond.bond_type.k*bond_frc_conv) system.addForce(force) # Add Angle forces if verbose: print('Adding angles...') force = mm.HarmonicAngleForce() force.setForceGroup(self.ANGLE_FORCE_GROUP) if constraints is ff.HAngles: num_constrained_bonds = system.getNumConstraints() atom_constraints = [[]] * system.getNumParticles() for i in range(num_constrained_bonds): c = system.getConstraintParameters(i) dist = c[2].value_in_unit(u.nanometer) atom_constraints[c[0]].append((c[1], dist)) atom_constraints[c[1]].append((c[0], dist)) for angle in self.angles_inc_h: if constraints is ff.HAngles: a1 = angle.atom1.element a2 = angle.atom2.element a3 = angle.atom3.element nh = int(a1==1) + int(a2==1) + int(a3==1) constrained = (nh >= 2 or (nh == 1 and a2 == 8)) else: constrained = False # no constraints if constrained: l1 = l2 = None for bond in angle.atom2.bonds: if bond.atom1 is angle.atom1 or bond.atom2 is angle.atom1: l1 = bond.bond_type.req * length_conv elif bond.atom1 is angle.atom3 or bond.atom2 is angle.atom3: l2 = bond.bond_type.req * length_conv # Compute the distance between the atoms and add a constraint length = sqrt(l1*l1 + l2*l2 - 2*l1*l2* cos(angle.angle_type.theteq)) system.addConstraint(bond.atom1.starting_index, bond.atom2.starting_index, length) if flexibleConstraints or not constrained: force.addAngle(angle.atom1.starting_index, angle.atom2.starting_index, angle.atom3.starting_index, angle.angle_type.theteq, 2*angle.angle_type.k*angle_frc_conv) for angle in self.angles_without_h: force.addAngle(angle.atom1.starting_index, angle.atom2.starting_index, angle.atom3.starting_index, angle.angle_type.theteq, 2*angle.angle_type.k*angle_frc_conv) system.addForce(force) # Add dihedral forces if verbose: print('Adding torsions...') force = mm.PeriodicTorsionForce() force.setForceGroup(self.DIHEDRAL_FORCE_GROUP) for tor in self.dihedrals_inc_h + self.dihedrals_without_h: force.addTorsion(tor.atom1.starting_index, tor.atom2.starting_index, tor.atom3.starting_index, tor.atom4.starting_index, int(tor.dihed_type.per), tor.dihed_type.phase, tor.dihed_type.phi_k*dihe_frc_conv) system.addForce(force) # Add nonbonded terms now if verbose: print('Adding nonbonded interactions...') force = mm.NonbondedForce() force.setForceGroup(self.NONBONDED_FORCE_GROUP) if self.ptr('ifbox') == 0: # non-periodic if nonbondedMethod is ff.NoCutoff: force.setNonbondedMethod(mm.NonbondedForce.NoCutoff) elif nonbondedMethod is ff.CutoffNonPeriodic: if cutoff is None: raise ValueError('No cutoff value specified') force.setNonbondedMethod(mm.NonbondedForce.CutoffNonPeriodic) force.setCutoffDistance(cutoff) else: raise ValueError('Illegal nonbonded method for non-periodic ' 'system') else: # periodic # Set up box vectors (from inpcrd if available, or fall back to # prmtop definitions system.setDefaultPeriodicBoxVectors(*self.box_vectors) # Set cutoff if cutoff is None: # Compute cutoff automatically box = self.box_lengths min_box_width = min((box[0]/u.nanometers, box[1]/u.nanometers, box[2]/u.nanometers)) CLEARANCE_FACTOR = 0.97 cutoff = u.Quantity((min_box_width*CLEARANCE_FACTOR)/2.0, u.nanometers) if nonbondedMethod is not ff.NoCutoff: force.setCutoffDistance(cutoff) # Set nonbonded method. if nonbondedMethod is ff.NoCutoff: force.setNonbondedMethod(mm.NonbondedForce.NoCutoff) elif nonbondedMethod is ff.CutoffNonPeriodic: force.setNonbondedMethod(mm.NonbondedForce.CutoffNonPeriodic) elif nonbondedMethod is ff.CutoffPeriodic: force.setNonbondedMethod(mm.NonbondedForce.CutoffPeriodic) elif nonbondedMethod is ff.Ewald: force.setNonbondedMethod(mm.NonbondedForce.Ewald) elif nonbondedMethod is ff.PME: force.setNonbondedMethod(mm.NonbondedForce.PME) else: raise ValueError('Cutoff method is not understood') if ewaldErrorTolerance is not None: force.setEwaldErrorTolerance(ewaldErrorTolerance) # Add per-particle nonbonded parameters (LJ params) sigma_scale = 2**(-1/6) * 2 for i, atm in enumerate(self.atom_list): force.addParticle(atm.charge, sigma_scale*LJ_radius[atm.nb_idx-1]*length_conv, LJ_depth[atm.nb_idx-1]*ene_conv) # Add 1-4 interactions excluded_atom_pairs = set() # save these pairs so we don't zero them out sigma_scale = 2**(-1/6) for tor in self.dihedrals_inc_h + self.dihedrals_without_h: if min(tor.signs) < 0: continue # multi-terms and impropers charge_prod = (tor.atom1.charge * tor.atom4.charge / tor.dihed_type.scee) epsilon = (sqrt(LJ_14_depth[tor.atom1.nb_idx-1] * ene_conv * LJ_14_depth[tor.atom4.nb_idx-1] * ene_conv) / tor.dihed_type.scnb) sigma = (LJ_14_radius[tor.atom1.nb_idx-1] + LJ_14_radius[tor.atom4.nb_idx-1])*length_conv*sigma_scale force.addException(tor.atom1.starting_index, tor.atom4.starting_index, charge_prod, sigma, epsilon) excluded_atom_pairs.add( min( (tor.atom1.starting_index, tor.atom4.starting_index), (tor.atom4.starting_index, tor.atom1.starting_index) ) ) # Add excluded atoms for atom in self.atom_list: # Exclude all bonds and angles for atom2 in atom.bond_partners: if atom2.starting_index > atom.starting_index: force.addException(atom.starting_index, atom2.starting_index, 0.0, 0.1, 0.0) for atom2 in atom.angle_partners: if atom2.starting_index > atom.starting_index: force.addException(atom.starting_index, atom2.starting_index, 0.0, 0.1, 0.0) for atom2 in atom.exclusion_partners: if atom2.starting_index > atom.starting_index: force.addException(atom.starting_index, atom2.starting_index, 0.0, 0.1, 0.0) for atom2 in atom.dihedral_partners: if atom2.starting_index <= atom.starting_index: continue if ((atom.starting_index, atom2.starting_index) in excluded_atom_pairs): continue force.addException(atom.starting_index, atom2.starting_index, 0.0, 0.1, 0.0) system.addForce(force) # Add virtual sites for water # First tag the residues that have an extra point in them for res in self.residue_list: res.has_ep = False ep = [atom for atom in self.atom_list if atom.atname in EPNAMES] for atom in ep: atom.residue.has_ep = True if len(ep) > 0: numRes = ep[-1].residue.idx + 1 waterO = [[] for i in range(numRes)] waterH = [[] for i in range(numRes)] waterEP = [[] for i in range(numRes)] for atom in self.atom_list: if atom.residue.has_ep: if atom.element == 8: waterO[res].append(atom) elif atom.element == 1: waterH[res].append(atom) elif atom.element == 0: waterEP[res].append(atom) # Record bond lengths for faster access distOH = [None] * numRes distHH = [None] * numRes distOE = [None] * numRes for bond in self.bonds_inc_h + self.bonds_without_h: a1 = bond.atom1 a2 = bond.atom2 if a1.residue.has_ep: res = a1.residue.idx if a1.element == 1 or a2.element == 1: if a1.element == 1 and a2.element == 1: distHH[res] = bond.bond_type.req * u.angstroms if a1.element == 8 or a2.element == 8: distOH[res] = bond.bond_type.req * u.angstroms elif ((a1.element == 8 or a2.element == 8) and (a1.element == 0 or a2.element == 0)): distOE[res] = bond.bond_type.req * u.angstroms # Loop over residues and add the virtual points out_of_plane_angle = 54.735 * u.degrees cosOOP = u.cos(out_of_plane_angle) sinOOP = u.sin(out_of_plane_angle) for residue in self.residue_list: if not residue.has_ep: continue res = residue.idx if len(waterO[res]) == 1 and len(waterH[res]) == 2: if len(waterEP[res]) == 1: # 4-point water weightH = distOE[res] / sqrt(distOH[res] * distOH[res] - 0.25 * distHH[res] * distHH[res]) system.setVirtualSite( waterEP[res][0], mm.ThreeParticleAverageSite(waterO[res][0], waterH[res][0], waterH[res][1], 1-weightH, weightH/2, weightH/2) ) elif len(waterEP[res]) == 2: # 5-point water weightH = (cosOOP * distOE[res] / sqrt(distOH[res] * distOH[res] - 0.25 * distHH[res] * distHH[res]) ) angleHOH = 2 * asin(0.5 * distHH[res] / distOH[res]) lenCross = distOH[res] * distOH[res] * sin(angleHOH) weightCross = sinOOP * distOE[res] / lenCross site1 = mm.OutOfPlaneSite(waterO[res][0], waterH[res][0], waterH[res][1], weightH/2, weightH/2, weightCross) site2 = mm.OutOfPlaneSite(waterO[res][0], waterH[res][0], waterH[res][1], weightH/2, weightH/2, -weightCross) system.setVirtualSite(waterEP[res][0], site1) system.setVirtualSite(waterEP[res][1], site2) # Add GB model if we're doing one if implicitSolvent is not None: if verbose: print('Adding GB parameters...') gb_parms = self._get_gb_params(implicitSolvent) # If implicitSolventKappa is None, compute it from salt # concentration if implicitSolventKappa is None: if u.is_quantity(implicitSolventSaltConc): sc = implicitSolventSaltConc.value_in_unit(u.moles/u.liter) implicitSolventSaltConc = sc if u.is_quantity(temperature): temperature = temperature.value_in_unit(u.kelvin) # The constant is 1 / sqrt( epsilon_0 * kB / (2 * NA * q^2 * # 1000) ) where NA is avogadro's number, epsilon_0 is the # permittivity of free space, q is the elementary charge (this # number matches sander/pmemd's kappa conversion factor) implicitSolventKappa = 50.33355 * sqrt(implicitSolventSaltConc / solventDielectric / temperature) # Multiply by 0.73 to account for ion exclusions, and multiply # by 10 to convert to 1/nm from 1/angstroms implicitSolventKappa *= 7.3 elif implicitSolvent is None: implicitSolventKappa = 0.0 if u.is_quantity(implicitSolventKappa): implicitSolventKappa = implicitSolventKappa.value_in_unit( (1.0/u.nanometer).unit) if implicitSolvent is HCT: gb = GBSAHCTForce(solventDielectric, soluteDielectric, None, cutoff, kappa=implicitSolventKappa) elif implicitSolvent is OBC1: gb = GBSAOBC1Force(solventDielectric, soluteDielectric, None, cutoff, kappa=implicitSolventKappa) elif implicitSolvent is OBC2: gb = GBSAOBC2Force(solventDielectric, soluteDielectric, None, cutoff, kappa=implicitSolventKappa) elif implicitSolvent is GBn: gb = GBSAGBnForce(solventDielectric, soluteDielectric, None, cutoff, kappa=implicitSolventKappa) elif implicitSolvent is GBn2: gb = GBSAGBn2Force(solventDielectric, soluteDielectric, None, cutoff, kappa=implicitSolventKappa) for i, atom in enumerate(self.atom_list): gb.addParticle([atom.charge] + list(gb_parms[i])) # Set cutoff method if nonbondedMethod is ff.NoCutoff: gb.setNonbondedMethod(mm.NonbondedForce.NoCutoff) elif nonbondedMethod is ff.CutoffNonPeriodic: gb.setNonbondedMethod(mm.NonbondedForce.CutoffNonPeriodic) gb.setCutoffDistance(cutoff) elif nonbondedMethod is ff.CutoffPeriodic: gb.setNonbondedMethod(mm.NonbondedForce.CutoffPeriodic) gb.setCutoffDistance(cutoff) else: raise ValueError('Illegal nonbonded method for use with GBSA') gb.setForceGroup(self.GB_FORCE_GROUP) system.addForce(gb) force.setReactionFieldDielectric(1.0) # applies to NonbondedForce # See if we repartition the hydrogen masses if hydrogenMass is not None: for bond in self.bonds_inc_h: atom1, atom2 = bond.atom1, bond.atom2 if atom1.element == 1: atom1, atom2 = atom2, atom1 # now atom2 is hydrogen for sure if atom1.element != 1: transfer_mass = hydrogenMass - atom2.mass new_mass1 = (system.getParticleMass(atom1.index) - transfer_mass) system.setParticleMass(atom2.index, hydrogenMass) system.setParticleMass(atom1.index, new_mass1) # See if we want to remove COM motion if removeCMMotion: system.addForce(mm.CMMotionRemover()) # Cache our system for easy access self._system = system return system
def createSystem(self, nonbondedMethod=ff.NoCutoff, nonbondedCutoff=1.0 * nanometer, ewaldErrorTolerance=0.0005, removeCMMotion=True, hydrogenMass=None, OPLS=False, implicitSolvent=None, AGBNPVersion=1): """Construct an OpenMM System representing the topology described by this DMS file Parameters ---------- nonbondedMethod : object=NoCutoff The method to use for nonbonded interactions. Allowed values are NoCutoff, CutoffNonPeriodic, CutoffPeriodic, Ewald, PME, or LJPME. nonbondedCutoff : distance=1*nanometer The cutoff distance to use for nonbonded interactions ewaldErrorTolerance : float=0.0005 The error tolerance to use if nonbondedMethod is Ewald, PME, or LJPME. removeCMMotion : boolean=True If true, a CMMotionRemover will be added to the System hydrogenMass : mass=None The mass to use for hydrogen atoms bound to heavy atoms. Any mass added to a hydrogen is subtracted from the heavy atom to keep their total mass the same. OPLS : boolean=False If True, forces OPLS combining rules implicitSolvent: string=None If not None, creates implicit solvent force of the given name Allowed values are: HCT and 'AGBNP' (the corresponding tables must be present in the DMS file) AGBNPVersion: int=1 AGBNP implicit solvent version """ self._checkForUnsupportedTerms() sys = mm.System() # Build the box dimensions boxSize = self.topology.getUnitCellDimensions() if boxSize is not None: sys.setDefaultPeriodicBoxVectors( (boxSize[0], 0, 0), (0, boxSize[1], 0), (0, 0, boxSize[2])) elif nonbondedMethod in (ff.CutoffPeriodic, ff.Ewald, ff.PME, ff.LJPME): raise ValueError( 'Illegal nonbonded method for a non-periodic system') # Create all of the particles for (fcounter, conn, tables, offset) in self._localVars(): for mass in conn.execute('SELECT mass FROM particle ORDER BY id'): sys.addParticle(mass[0] * dalton) # Add all of the forces self._addBondsToSystem(sys) self._addAnglesToSystem(sys) self._addConstraintsToSystem(sys) self._addPeriodicTorsionsToSystem(sys, OPLS) self._addImproperHarmonicTorsionsToSystem(sys) self._addCMAPToSystem(sys) self._addVirtualSitesToSystem(sys) self._addPositionalHarmonicRestraints(sys) nb, cnb = self._addNonbondedForceToSystem(sys, OPLS) # Finish configuring the NonbondedForce. methodMap = { ff.NoCutoff: mm.NonbondedForce.NoCutoff, ff.CutoffNonPeriodic: mm.NonbondedForce.CutoffNonPeriodic, ff.CutoffPeriodic: mm.NonbondedForce.CutoffPeriodic, ff.Ewald: mm.NonbondedForce.Ewald, ff.PME: mm.NonbondedForce.PME, ff.LJPME: mm.NonbondedForce.LJPME } nb.setNonbondedMethod(methodMap[nonbondedMethod]) nb.setCutoffDistance(nonbondedCutoff) nb.setEwaldErrorTolerance(ewaldErrorTolerance) if cnb is not None: nb.setUseDispersionCorrection(False) if nonbondedMethod in (ff.CutoffPeriodic, ff.Ewald, ff.PME, ff.LJPME): cnb.setNonbondedMethod(methodMap[ff.CutoffPeriodic]) cnb.setCutoffDistance(nonbondedCutoff) elif nonbondedMethod == ff.CutoffNonPeriodic: cnb.setNonbondedMethod(methodMap[ff.CutoffNonPeriodic]) cnb.setCutoffDistance(nonbondedCutoff) else: cnb.setNonbondedMethod(methodMap[ff.NoCutoff]) cnb.setUseSwitchingFunction(False) cnb.setUseLongRangeCorrection(False) #add implicit solvent model. if implicitSolvent is not None: if not (implicitSolvent in (HCT, 'AGBNP', 'GVolSA', 'AGBNP3')): raise ValueError('Illegal implicit solvent method') if self._verbose: print('Adding implicit solvent ...') #with implicit solvent turn off native reaction field #However note that this does not affect the shifted Coulomb potential of the Nonbonded force #(it affects the only the energy, not the forces and equation of motion) nb.setReactionFieldDielectric(1.0) if implicitSolvent is HCT: gb_parms = self._get_gb_params() if gb_parms: if self._verbose: print('Adding HCT GB force ...') gb = GBSAHCTForce(SA='ACE') for i in range(len(gb_parms)): gb.addParticle(list(gb_parms[i])) gb.finalize() sys.addForce(gb) else: raise IOError("No HCT parameters found in DMS file") if implicitSolvent is 'AGBNP3': #load AGBNP3 plugin if available try: from AGBNP3plugin import AGBNP3Force except ImportError: raise NotImplementedError( 'AGBNP3 is not supported in this version') #sets up AGBNP3 gb_parms = self._get_agbnp2_params() if gb_parms: if self._verbose: print('Adding AGBNP3 force ...') gb = AGBNP3Force() # add particles for i in range(len(gb_parms)): p = gb_parms[i] gb.addParticle(p[0], p[1], p[2], p[3], p[4], p[5], p[6]) # connection table (from bonds) self._add_agbnp2_ct(gb) sys.addForce(gb) else: raise IOError("No AGBNP parameters found in DMS file") if implicitSolvent is 'GVolSA': #implemented as AGBNP version 0 implicitSolvent = 'AGBNP' AGBNPVersion = 0 if self._verbose: print('Using GVolSA') if implicitSolvent is 'AGBNP': #load AGBNP plugin if available try: from AGBNPplugin import AGBNPForce except ImportError: raise NotImplementedError( 'AGBNP is not supported in this version') #sets up AGBNP gb_parms = self._get_agbnp2_params() if gb_parms: gb = AGBNPForce() gb.setNonbondedMethod(methodMap[nonbondedMethod]) gb.setCutoffDistance(nonbondedCutoff) gb.setVersion(AGBNPVersion) if self._verbose: print('Using AGBNP force version %d ...' % AGBNPVersion) # add particles for i in range(len(gb_parms)): [ radiusN, chargeN, gammaN, alphaN, hbtype, hbwN, ishydrogenN ] = gb_parms[i] h_flag = ishydrogenN > 0 gb.addParticle(radiusN, gammaN, alphaN, chargeN, h_flag) sys.addForce(gb) self.gb_parms = gb_parms self.agbnp = gb else: raise IOError("No AGBNP parameters found in DMS file") # Adjust masses. if hydrogenMass is not None: for atom1, atom2 in self.topology.bonds(): if atom1.element == hydrogen: (atom1, atom2) = (atom2, atom1) if atom2.element == hydrogen and atom1.element not in ( hydrogen, None): transferMass = hydrogenMass - sys.getParticleMass( atom2.index) sys.setParticleMass(atom2.index, hydrogenMass) sys.setParticleMass( atom1.index, sys.getParticleMass(atom1.index) - transferMass) # Add a CMMotionRemover. if removeCMMotion: sys.addForce(mm.CMMotionRemover()) return sys
def createSystem(self, nonbondedMethod=ff.NoCutoff, nonbondedCutoff=1.0*nanometer, ewaldErrorTolerance=0.0005, removeCMMotion=True, hydrogenMass=None, OPLS=False, implicitSolvent=None): """Construct an OpenMM System representing the topology described by this dms file Parameters: - nonbondedMethod (object=NoCutoff) The method to use for nonbonded interactions. Allowed values are NoCutoff, CutoffNonPeriodic, CutoffPeriodic, Ewald, or PME. - nonbondedCutoff (distance=1*nanometer) The cutoff distance to use for nonbonded interactions - ewaldErrorTolerance (float=0.0005) The error tolerance to use if nonbondedMethod is Ewald or PME. - removeCMMotion (boolean=True) If true, a CMMotionRemover will be added to the System - hydrogenMass (mass=None) The mass to use for hydrogen atoms bound to heavy atoms. Any mass added to a hydrogen is subtracted from the heavy atom to keep their total mass the same. - OPLS (boolean=False) If True, force field parameters are interpreted as OPLS parameters; OPLS variants of torsional and non-bonded forces are constructed. - implicitSolvent (object=None) if not None, the implicit solvent model to use, the only allowed value is HCT """ self._checkForUnsupportedTerms() sys = mm.System() # Buld the box dimensions sys = mm.System() boxSize = self.topology.getUnitCellDimensions() if boxSize is not None: sys.setDefaultPeriodicBoxVectors((boxSize[0], 0, 0), (0, boxSize[1], 0), (0, 0, boxSize[2])) elif nonbondedMethod in (ff.CutoffPeriodic, ff.Ewald, ff.PME): raise ValueError('Illegal nonbonded method for a non-periodic system') # Create all of the particles for mass in self._conn.execute('SELECT mass FROM particle ORDER BY id'): sys.addParticle(mass[0]*dalton) # Add all of the forces self._addBondsToSystem(sys) self._addAnglesToSystem(sys) self._addConstraintsToSystem(sys) self._addPeriodicTorsionsToSystem(sys, OPLS) self._addImproperHarmonicTorsionsToSystem(sys) self._addCMAPToSystem(sys) self._addVirtualSitesToSystem(sys) nb, cnb = self._addNonbondedForceToSystem(sys, OPLS) # Finish configuring the NonbondedForce. methodMap = {ff.NoCutoff:mm.NonbondedForce.NoCutoff, ff.CutoffNonPeriodic:mm.NonbondedForce.CutoffNonPeriodic, ff.CutoffPeriodic:mm.NonbondedForce.CutoffPeriodic, ff.Ewald:mm.NonbondedForce.Ewald, ff.PME:mm.NonbondedForce.PME} nb.setNonbondedMethod(methodMap[nonbondedMethod]) nb.setCutoffDistance(nonbondedCutoff) nb.setEwaldErrorTolerance(ewaldErrorTolerance) if cnb is not None: cnb.setNonbondedMethod(methodMap[nonbondedMethod]) cnb.setCutoffDistance(nonbondedCutoff) #add implicit solvent model. Right now, only HCT model is considered. if implicitSolvent is not None: print('Adding implicit solvent ...') if implicitSolvent is HCT: gb_parms = self._get_gb_params() if gb_parms: print('Adding HCT GB force ...') gb = GBSAHCTForce(SA='ACE') for i in range(len(gb_parms)): gb.addParticle(list(gb_parms[i])) sys.addForce(gb) if implicitSolvent is 'AGBNP': #load AGBNP3 plugin if available try: from AGBNP3plugin import AGBNP3Force AGBNP3enabled = True except ImportError: AGBNP3enabled = False #sets up AGBNP3 if AGBNP3enabled: gb_parms = self._get_agbnp2_params() if gb_parms: print('Adding AGBNP3 force ...') gb = AGBNP3Force() # add particles for i in range(len(gb_parms)): p = gb_parms[i] gb.addParticle(p[0],p[1],p[2],p[3],p[4],p[5],p[6]) # connection table (from bonds) self._add_agbnp2_ct(gb) sys.addForce(gb) else: print('Warning: AGBNP is not supported in this version') if implicitSolvent is 'GVolSA': #load Gaussvol plugin if available try: from GVolplugin import GVolForce GVolEnabled = True except ImportError: GVolEnabled = False #sets up GVol if GVolEnabled: gb_parms = self._get_agbnp2_params() if gb_parms: print('Adding GVol force ...') gb = GVolForce() gb.setNonbondedMethod(methodMap[nonbondedMethod]) gb.setCutoffDistance(nonbondedCutoff) # add particles for i in range(len(gb_parms)): [radiusN,chargeN,gammaN,alphaN,hbtype,hbwN,ishydrogenN] = gb_parms[i] h_flag = ishydrogenN > 0 Roffset = 0.05; radiusN += Roffset; gb.addParticle(radiusN, gammaN, h_flag) #print "Adding", radiusN, gammaN, h_flag print ("Adding GVolforce ...") sys.addForce(gb) print ("Done") else: print('Warning: GVol is not supported in this version') # Adjust masses. if hydrogenMass is not None: for atom1, atom2 in self.topology.bonds(): if atom1.element == hydrogen: (atom1, atom2) = (atom2, atom1) if atom2.element == hydrogen and atom1.element not in (hydrogen, None): transferMass = hydrogenMass-sys.getParticleMass(atom2.index) sys.setParticleMass(atom2.index, hydrogenMass) sys.setParticleMass(atom1.index, sys.getParticleMass(atom1.index)-transferMass) # Add a CMMotionRemover. if removeCMMotion: sys.addForce(mm.CMMotionRemover()) return sys
def createSystem(self, nonbondedMethod=ff.NoCutoff, nonbondedCutoff=1.0*nanometer, ewaldErrorTolerance=0.0005, removeCMMotion=True, hydrogenMass=None, OPLS=False, implicitSolvent=None): """Construct an OpenMM System representing the topology described by this dms file Parameters: - nonbondedMethod (object=NoCutoff) The method to use for nonbonded interactions. Allowed values are NoCutoff, CutoffNonPeriodic, CutoffPeriodic, Ewald, or PME. - nonbondedCutoff (distance=1*nanometer) The cutoff distance to use for nonbonded interactions - ewaldErrorTolerance (float=0.0005) The error tolerance to use if nonbondedMethod is Ewald or PME. - removeCMMotion (boolean=True) If true, a CMMotionRemover will be added to the System - hydrogenMass (mass=None) The mass to use for hydrogen atoms bound to heavy atoms. Any mass added to a hydrogen is subtracted from the heavy atom to keep their total mass the same. - OPLS (boolean=False) If True, force field parameters are interpreted as OPLS parameters; OPLS variants of torsional and non-bonded forces are constructed. - implicitSolvent (object=None) if not None, the implicit solvent model to use, the only allowed value is HCT """ self._checkForUnsupportedTerms() sys = mm.System() # Buld the box dimensions sys = mm.System() boxSize = self.topology.getUnitCellDimensions() if boxSize is not None: sys.setDefaultPeriodicBoxVectors((boxSize[0], 0, 0), (0, boxSize[1], 0), (0, 0, boxSize[2])) elif nonbondedMethod in (ff.CutoffPeriodic, ff.Ewald, ff.PME): raise ValueError('Illegal nonbonded method for a non-periodic system') # Create all of the particles for mass in self._conn.execute('SELECT mass FROM particle ORDER BY id'): sys.addParticle(mass[0]*dalton) # Add all of the forces self._addBondsToSystem(sys) self._addAnglesToSystem(sys) self._addConstraintsToSystem(sys) self._addPeriodicTorsionsToSystem(sys, OPLS) self._addImproperHarmonicTorsionsToSystem(sys) self._addCMAPToSystem(sys) self._addVirtualSitesToSystem(sys) nb, cnb = self._addNonbondedForceToSystem(sys, OPLS) # Finish configuring the NonbondedForce. methodMap = {ff.NoCutoff:mm.NonbondedForce.NoCutoff, ff.CutoffNonPeriodic:mm.NonbondedForce.CutoffNonPeriodic, ff.CutoffPeriodic:mm.NonbondedForce.CutoffPeriodic, ff.Ewald:mm.NonbondedForce.Ewald, ff.PME:mm.NonbondedForce.PME} nb.setNonbondedMethod(methodMap[nonbondedMethod]) nb.setCutoffDistance(nonbondedCutoff) nb.setEwaldErrorTolerance(ewaldErrorTolerance) if cnb is not None: cnb.setNonbondedMethod(methodMap[nonbondedMethod]) cnb.setCutoffDistance(nonbondedCutoff) #add implicit solvent model. Right now, only HCT model is considered. if implicitSolvent is not None: print('Adding implicit solvent ...') if implicitSolvent is HCT: gb_parms = self._get_gb_params() if gb_parms: print('Adding HCT GB force ...') gb = GBSAHCTForce(SA='ACE') for i in range(len(gb_parms)): gb.addParticle(list(gb_parms[i])) sys.addForce(gb) if implicitSolvent is 'AGBNP': #load AGBNP3 plugin if available try: from AGBNP3plugin import AGBNP3Force AGBNP3enabled = True except ImportError: AGBNP3enabled = False #sets up AGBNP3 if AGBNP3enabled: gb_parms = self._get_agbnp2_params() if gb_parms: print('Adding AGBNP3 force ...') gb = AGBNP3Force() # add particles for i in range(len(gb_parms)): p = gb_parms[i] gb.addParticle(p[0],p[1],p[2],p[3],p[4],p[5],p[6]) # connection table (from bonds) self._add_agbnp2_ct(gb) sys.addForce(gb) else: print('Warning: AGBNP is not supported in this version') if implicitSolvent is 'GVolSA': #load Gaussvol plugin if available try: from GVolplugin import GVolForce GVolEnabled = True except ImportError: GVolEnabled = False #sets up GVol if GVolEnabled: gb_parms = self._get_agbnp2_params() if gb_parms: print('Adding GVol force ...') gb = GVolForce() gb.setNonbondedMethod(methodMap[nonbondedMethod]) gb.setCutoffDistance(nonbondedCutoff) # add particles for i in range(len(gb_parms)): [radiusN,chargeN,gammaN,alphaN,hbtype,hbwN,ishydrogenN] = gb_parms[i] h_flag = ishydrogenN > 0 Roffset = 0.05; radiusN += Roffset; gb.addParticle(radiusN, gammaN, h_flag) #print "Adding", radiusN, gammaN, h_flag print "Adding GVolforce ..." sys.addForce(gb) print "Done" else: print('Warning: GVol is not supported in this version') # Adjust masses. if hydrogenMass is not None: for atom1, atom2 in self.topology.bonds(): if atom1.element == hydrogen: (atom1, atom2) = (atom2, atom1) if atom2.element == hydrogen and atom1.element not in (hydrogen, None): transferMass = hydrogenMass-sys.getParticleMass(atom2.index) sys.setParticleMass(atom2.index, hydrogenMass) sys.setParticleMass(atom1.index, sys.getParticleMass(atom1.index)-transferMass) # Add a CMMotionRemover. if removeCMMotion: sys.addForce(mm.CMMotionRemover()) return sys