def add_barostat(system, args): if args.pressure <= 0.0: logger.info("This is a constant volume (NVT) run") else: logger.info( "This is a constant pressure (NPT) run at %.2f bar pressure" % args.pressure) logger.info( "Adding Monte Carlo barostat with volume adjustment interval %i" % args.nbarostat) logger.info("Anisotropic box scaling is %s" % ("ON" if args.anisotropic else "OFF")) #if args.tension > 0: if (args.tension is not None) and args.restoring_scale == 0.: logger.info( '...detected tension, but no extra nonlinear restoring force, using openMM Membrane Barostat...' ) logger.info( '...openMM MembraneBarostat only accepts z-axis, be warned!') logger.info('...setting tension {} bar*nm'.format(args.tension)) XYmode = mm.MonteCarloMembraneBarostat.XYIsotropic Zmode = mm.MonteCarloMembraneBarostat.ZFree barostat = mm.MonteCarloMembraneBarostat( args.pressure * u.bar, args.tension, args.temperature * u.kelvin, XYmode, args.zmode, args.nbarostat) elif args.tension is not None and args.restoring_scale != 0.: raise ValueError( 'Restoring scale not zero, should use simDCD0_Tension.py script instead' ) ''' logger.info("Tension={} > 0, using Membrane Barostat with z-mode {}".format(args.tension, args.zmode)) if args.anisotropic: logger.info("XY-axes will change length independently") XYmode = mm.MonteCarloMembraneBarostat.XYAnisotropic else: XYmode = mm.MonteCarloMembraneBarostat.XYIsotropic #barostat = mm.MonteCarloMembraneBarostat(args.pressure*u.bar,args.tension*u.bar*u.nanometer,args.temperature*u.kelvin,XYmode,args.zmode,args.nbarostat) barostat = mm.MonteCarloMembraneBarostat(args.pressure*u.bar,args.tension,args.temperature*u.kelvin,XYmode,args.zmode,args.nbarostat) ''' elif args.anisotropic: logger.info("Only the Z-axis will be adjusted") barostat = mm.MonteCarloAnisotropicBarostat( mm.vec3.Vec3(args.pressure * u.bar, args.pressure * u.bar, args.pressure * u.bar), args.temperature * u.kelvin, False, False, True, args.nbarostat) else: barostat = mm.MonteCarloBarostat(args.pressure * u.bar, args.temperature * u.kelvin, args.nbarostat) system.addForce(barostat) '''
def apply_mc_barostat(system, pcoupl, P, T, nsteps=100): if pcoupl == 'iso': print('Isotropic barostat') system.addForce(mm.MonteCarloBarostat(P * bar, T * kelvin, nsteps)) elif pcoupl == 'semi-iso': print('Anisotropic barostat with coupled XY') system.addForce(mm.MonteCarloMembraneBarostat(P * bar, 0 * bar * nm, T * kelvin, mm.MonteCarloMembraneBarostat.XYIsotropic, mm.MonteCarloMembraneBarostat.ZFree, nsteps)) elif pcoupl == 'xyz': print('Anisotropic barostat') system.addForce( mm.MonteCarloAnisotropicBarostat([P * bar] * 3, T * kelvin, True, True, True, nsteps)) elif pcoupl == 'xy': print('Anisotropic barostat only for X and Y') system.addForce( mm.MonteCarloAnisotropicBarostat([P * bar] * 3, T * kelvin, True, True, False, nsteps)) elif pcoupl == 'z': print('Anisotropic barostat only for Z') system.addForce( mm.MonteCarloAnisotropicBarostat([P * bar] * 3, T * kelvin, False, False, True, nsteps)) else: raise Exception('Available pressure coupling types: iso, semi-iso, xyz, xy, z')
def add_barostat(system,args): if args.pressure <= 0.0: logger.info("This is a constant volume (NVT) run") else: logger.info("This is a constant pressure (NPT) run at %.2f bar pressure" % args.pressure) logger.info("Adding Monte Carlo barostat with volume adjustment interval %i" % args.nbarostat) logger.info("Anisotropic box scaling is %s" % ("ON" if args.anisotropic else "OFF")) if args.anisotropic: logger.info("Only the Z-axis will be adjusted") barostat = mm.MonteCarloAnisotropicBarostat(Vec3(args.pressure*u.bar, args.pressure*u.bar, args.pressure*u.bar), args.temperature*u.kelvin, False, False, True, args.nbarostat) else: barostat = mm.MonteCarloBarostat(args.pressure * u.bar, args.temperature * u.kelvin, args.nbarostat) system.addForce(barostat) '''
def configure_amber_explicit( pdb_file: str, top_file: str, dt_ps: float, temperature_kelvin: float, heat_bath_friction_coef: float, platform: simtk.openmm.Platform, platform_properties: dict, explicit_barostat: str, ) -> Tuple[simtk.openmm.app.Simulation, parmed.Structure]: # Configure system top = parmed.load_file(top_file, xyz=pdb_file) system = top.createSystem( nonbondedMethod=app.PME, nonbondedCutoff=1.0 * u.nanometer, constraints=app.HBonds, ) # Congfigure integrator integrator = omm.LangevinIntegrator( temperature_kelvin * u.kelvin, heat_bath_friction_coef / u.picosecond, dt_ps * u.picosecond, ) if explicit_barostat == "MonteCarloBarostat": system.addForce( omm.MonteCarloBarostat(1 * u.bar, temperature_kelvin * u.kelvin) ) elif explicit_barostat == "MonteCarloAnisotropicBarostat": system.addForce( omm.MonteCarloAnisotropicBarostat( (1, 1, 1) * u.bar, temperature_kelvin * u.kelvin, False, False, True ) ) else: raise ValueError(f"Invalid explicit_barostat option: {explicit_barostat}") sim = app.Simulation( top.topology, system, integrator, platform, platform_properties ) # Return simulation and handle to coordinates return sim, top
const = opt.force_constant * u.kilocalories_per_mole/u.angstroms**2 const = const.value_in_unit_system(u.md_unit_system) force = mm.CustomExternalForce('k*periodicdistance(x, y, z, x0, y0, z0)^2') force.addGlobalParameter('k', const) force.addPerParticleParameter('x0') force.addPerParticleParameter('y0') force.addPerParticleParameter('z0') for i, atom_crd in enumerate(pdb.positions): if sel[i]: force.addParticle(i, atom_crd.value_in_unit(u.nanometers)) system.addForce(force) if opt.ntp: if opt.aniso: print('Using anisotropic barostat'); sys.stdout.flush() baro = mm.MonteCarloAnisotropicBarostat(1*u.bar, opt.temp*u.kelvin) else: print('Using isotropic barostat'); sys.stdout.flush() baro = mm.MonteCarloBarostat(1*u.bar, opt.temp*u.kelvin) system.addForce(baro) if opt.gamma_ln == 0.0 and not opt.nve: print('Adding Anderson thermostat at %sK, 0.1 psec^-1' % opt.temp); sys.stdout.flush() thermo = mm.AndersenThermostat(opt.temp*u.kelvin, 0.1/u.picosecond) system.addForce(thermo) # Create the simulation if opt.gamma_ln > 0.0: if opt.nrespa > 1: integrator = MTSVVVRIntegrator(opt.temp*u.kelvin, opt.gamma_ln/u.picosecond, opt.timestep*u.femtoseconds,
def openmm_simulate_charmm_npt_z(top_file, pdb_file, check_point=None, GPU_index=0, output_traj="output.dcd", output_log="output.log", output_cm=None, report_time=10 * u.picoseconds, sim_time=10 * u.nanoseconds): """ Start and run an OpenMM NVT simulation with Langevin integrator at 2 fs time step and 300 K. The cutoff distance for nonbonded interactions were set at 1.2 nm and LJ switch distance at 1.0 nm, which commonly used with Charmm force field. Long-range nonbonded interactions were handled with PME. Parameters ---------- top_file : topology file (.top, .prmtop, ...) This is the topology file discribe all the interactions within the MD system. pdb_file : coordinates file (.gro, .pdb, ...) This is the molecule configuration file contains all the atom position and PBC (periodic boundary condition) box in the system. check_point : None or check point file to load GPU_index : Int or Str The device # of GPU to use for running the simulation. Use Strings, '0,1' for example, to use more than 1 GPU output_traj : the trajectory file (.dcd) This is the file stores all the coordinates information of the MD simulation results. output_log : the log file (.log) This file stores the MD simulation status, such as steps, time, potential energy, temperature, speed, etc. output_cm : the h5 file contains contact map information report_time : 10 ps The program writes its information to the output every 10 ps by default sim_time : 10 ns The timespan of the simulation trajectory """ top = pmd.load_file(top_file, xyz=pdb_file) system = top.createSystem(nonbondedMethod=app.PME, nonbondedCutoff=1.2 * u.nanometer, switchDistance=1.0 * u.nanometer, constraints=app.HBonds) dt = 0.002 * u.picoseconds integrator = omm.LangevinIntegrator(300 * u.kelvin, 1 / u.picosecond, dt) system.addForce( omm.MonteCarloAnisotropicBarostat((1, 1, 1) * u.bar, 300 * u.kelvin, False, False, True)) try: platform = omm.Platform_getPlatformByName("CUDA") properties = {'DeviceIndex': str(GPU_index), 'CudaPrecision': 'mixed'} except Exception: platform = omm.Platform_getPlatformByName("OpenCL") properties = {'DeviceIndex': str(GPU_index)} simulation = app.Simulation(top.topology, system, integrator, platform, properties) simulation.context.setPositions(top.positions) simulation.minimizeEnergy() report_freq = int(report_time / dt) simulation.context.setVelocitiesToTemperature(10 * u.kelvin, random.randint(1, 10000)) simulation.reporters.append(app.DCDReporter(output_traj, report_freq)) if output_cm: simulation.reporters.append(ContactMapReporter(output_cm, report_freq)) simulation.reporters.append( app.StateDataReporter(output_log, report_freq, step=True, time=True, speed=True, potentialEnergy=True, temperature=True, totalEnergy=True)) simulation.reporters.append( app.CheckpointReporter('checkpnt.chk', report_freq)) if check_point: simulation.loadCheckpoint(check_point) nsteps = int(sim_time / dt) simulation.step(nsteps)
def doSimDynamics(top, systemRef, integratorRef, platform, prop, temperature, scalexy=False, inBulk=False, state=None, pos=None, vels=None, nSteps=10000000): #Input a topology object, reference system, integrator, platform, platform properties, #and optionally state file, positions, or velocities #If state is specified including positions and velocities and pos and vels are not None, the #positions and velocities from the provided state will be overwritten #Does NPT, stopping periodically to run NVE to compute dynamics #Only the NPT simulation will be saved, not the NVE #Copy the reference system and integrator objects system = copy.deepcopy(systemRef) integrator = copy.deepcopy(integratorRef) #For NPT, add the barostat as a force #If not in bulk, use anisotropic barostat if not inBulk: system.addForce( mm.MonteCarloAnisotropicBarostat( (1.0, 1.0, 1.0) * u.bar, temperature, #Temperature should be SAME as for thermostat scalexy, #Set with flag for flexibility scalexy, True, #Only scale in z-direction 250 #Time-steps between MC moves )) #If in bulk, have to use isotropic barostat to avoid any weird effects with box changing dimensions else: system.addForce(mm.MonteCarloBarostat(1.0 * u.bar, temperature, 250)) #Create new simulation object for NPT simulation sim = app.Simulation(top.topology, system, integrator, platform, prop, state) #Also create copies and simulation object for the NVE we will be running systemNVE = copy.deepcopy(systemRef) integratorNVE = mm.VerletIntegrator(2.0 * u.femtoseconds) integratorNVE.setConstraintTolerance(1.0E-08) simNVE = app.Simulation(top.topology, systemNVE, integratorNVE, platform, prop) #Set the particle positions in the NPT simulation if pos is not None: sim.context.setPositions(pos) #Apply constraints before starting the simulation sim.context.applyConstraints(1.0E-08) #Check starting energy decomposition if want #decompEnergy(sim.system, sim.context.getState(getPositions=True)) #Initialize velocities if not specified if vels is not None: sim.context.setVelocities(vels) else: try: testvel = sim.context.getState(getVelocities=True).getVelocities() print( "Velocities included in state, starting with 1st particle: %s" % str(testvel[0])) #If all the velocities are zero, then set them to the temperature if not np.any(testvel.value_in_unit(u.nanometer / u.picosecond)): print( "Had velocities, but they were all zero, so setting based on temperature." ) sim.context.setVelocitiesToTemperature(temperature) except: print("Could not find velocities, setting with temperature") sim.context.setVelocitiesToTemperature(temperature) #Set up the reporter to output energies, volume, etc. sim.reporters.append( app.StateDataReporter( 'prod_out.txt', #Where to write - can be stdout or file name (default .csv, I prefer .txt) 500, #Number of steps between writes step=True, #Write step number time=True, #Write simulation time potentialEnergy=True, #Write potential energy kineticEnergy=True, #Write kinetic energy totalEnergy=True, #Write total energy temperature=True, #Write temperature volume=True, #Write volume density=False, #Write density speed=True, #Estimate of simulation speed separator= ' ' #Default is comma, but can change if want (I like spaces) )) #Set up reporter for printing coordinates (trajectory) sim.reporters.append( NetCDFReporter( 'prod.nc', #File name to write trajectory to 500, #Number of steps between writes crds=True, #Write coordinates vels=True, #Write velocities frcs=False #Write forces )) #Identify solute indices and water oxygen indices soluteInds = [] owInds = [] hw1Inds = [] hw2Inds = [] for res in top.residues: if res.name not in ['OTM', 'CTM', 'STM', 'NTM', 'SOL']: for atom in res.atoms: soluteInds.append(atom.idx) elif res.name == 'SOL': for atom in res.atoms: if atom.name == 'OW': owInds.append(atom.idx) elif atom.name == 'HW1': hw1Inds.append(atom.idx) elif atom.name == 'HW2': hw2Inds.append(atom.idx) print("Solute indices:") print(soluteInds) #print("Water oxygen indices:") #print(owInds) #print("Water hydrogen (1st) indices:") #print(hw1Inds) #print("Water hydrogen (2nd) indices:") #print(hw2Inds) #Define cutoffs for solute solvation shells solShell1Cut = 0.55 #nanometers from all solute atoms (including hydrogens) solShell2Cut = 0.85 #Create array to store the dynamic information of interest every 0.2 ps (100 steps) for 50 ps calcSteps = 100 calcTotSteps = 25000 numWats = np.zeros( (int(calcTotSteps / calcSteps) + 1, 2) ) #Number waters that started in shell that are in shell at later time dipCorrs = np.zeros((int(calcTotSteps / calcSteps) + 1, 2)) #Dipole correlation in both solute shells #Start running dynamics print("\nRunning NPT simulation with interspersed NVE to find dynamics...") sim.context.setTime(0.0) stepChunk = 5000 #Run NVE for 50 ps to find dynamics every 10 ps countSteps = 0 while countSteps < nSteps: countSteps += stepChunk sim.step(stepChunk) #Record the simulation state so can kick off the NVE simulation thisState = sim.context.getState(getPositions=True, getVelocities=True) #Get solute and water oxygen coordinates after wrapping around the solute coords = thisState.getPositions(asNumpy=True) boxDims = np.diagonal(thisState.getPeriodicBoxVectors(asNumpy=True)) wrapCOM = np.average(coords[soluteInds], axis=0) coords = wl.reimage(coords, wrapCOM, boxDims) - wrapCOM solCoords = coords[soluteInds] owCoords = coords[owInds] hw1Coords = coords[hw1Inds] hw2Coords = coords[hw2Inds] #Figure out which waters are in the solute solvation shells shell1BoolMat = wl.nearneighbors(solCoords, owCoords, boxDims, 0.0, solShell1Cut) shell1Bool = np.array(np.sum(shell1BoolMat, axis=0), dtype=bool) shell2BoolMat = wl.nearneighbors(solCoords, owCoords, boxDims, solShell1Cut, solShell2Cut) shell2Bool = np.array(np.sum(shell2BoolMat, axis=0), dtype=bool) #Count number of waters in each shell (will need for averaging) thisCount1 = int(np.sum(shell1Bool)) thisCount2 = int(np.sum(shell2Bool)) #print("Found %i waters in shell1"%thisCount1) #print("Found %i waters in shell2"%thisCount2) #Loop over waters in shells and compute dipole vectors as references refDipoles1 = np.zeros((thisCount1, 3)) refDipoles2 = np.zeros((thisCount2, 3)) for k, pos in enumerate(owCoords[shell1Bool]): thisOHvecs = wl.reimage( [hw1Coords[shell1Bool][k], hw2Coords[shell1Bool][k]], pos, boxDims) - pos thisDip = -0.5 * (thisOHvecs[0] + thisOHvecs[1]) refDipoles1[k] = thisDip / np.linalg.norm(thisDip) for k, pos in enumerate(owCoords[shell2Bool]): thisOHvecs = wl.reimage( [hw1Coords[shell2Bool][k], hw2Coords[shell2Bool][k]], pos, boxDims) - pos thisDip = -0.5 * (thisOHvecs[0] + thisOHvecs[1]) refDipoles2[k] = thisDip / np.linalg.norm(thisDip) #Set up the NVE simulation simNVE.context.setState(thisState) simNVE.context.setTime(0.0) #Loop over taking steps to computed dynamics countStepsNVE = 0 while countStepsNVE <= calcTotSteps: calcState = simNVE.context.getState(getPositions=True) #Get solute and water oxygen coordinates after wrapping around the solute coords = calcState.getPositions(asNumpy=True) wrapCOM = np.average(coords[soluteInds], axis=0) coords = wl.reimage(coords, wrapCOM, boxDims) - wrapCOM solCoords = coords[soluteInds] owCoords = coords[owInds] hw1Coords = coords[hw1Inds] hw2Coords = coords[hw2Inds] #Count waters that started in each shell that are now in the shell at this time #No absorbing boundaries thisbool1Mat = wl.nearneighbors(solCoords, owCoords, boxDims, 0.0, solShell1Cut) thisbool1 = np.array(np.sum(thisbool1Mat, axis=0), dtype=bool) thisbool2Mat = wl.nearneighbors(solCoords, owCoords, boxDims, solShell1Cut, solShell2Cut) thisbool2 = np.array(np.sum(thisbool2Mat, axis=0), dtype=bool) numWats[int(countStepsNVE / calcSteps), 0] += int(np.sum(thisbool1 * shell1Bool)) numWats[int(countStepsNVE / calcSteps), 1] += int(np.sum(thisbool2 * shell2Bool)) #Loop over waters in shells and compute dipole vectors for this configuration #Adding to sum that we will normalize to find average at each time point for k, pos in enumerate(owCoords[shell1Bool]): thisOHvecs = wl.reimage( [hw1Coords[shell1Bool][k], hw2Coords[shell1Bool][k]], pos, boxDims) - pos thisDip = -0.5 * (thisOHvecs[0] + thisOHvecs[1]) thisDip /= np.linalg.norm(thisDip) dipCorrs[int(countStepsNVE / calcSteps), 0] += (np.dot(thisDip, refDipoles1[k]) / float(thisCount1)) for k, pos in enumerate(owCoords[shell2Bool]): thisOHvecs = wl.reimage( [hw1Coords[shell2Bool][k], hw2Coords[shell2Bool][k]], pos, boxDims) - pos thisDip = -0.5 * (thisOHvecs[0] + thisOHvecs[1]) thisDip /= np.linalg.norm(thisDip) dipCorrs[int(countStepsNVE / calcSteps), 1] += (np.dot(thisDip, refDipoles2[k]) / float(thisCount2)) simNVE.step(calcSteps) countStepsNVE += calcSteps #Finish normalizing dipole correlations (really cosine of angle between dipole vector at different times) numWats /= float(int(nSteps / stepChunk)) dipCorrs /= float(int(nSteps / stepChunk)) print("Normalizing factor for finding averages: %f" % float(int(nSteps / stepChunk))) #And save the final state of the NPT simulation in case we want to extend it sim.saveState('nptDynamicsState.xml') #And return the dipole correlations and times at which they were computed timeVals = 0.002 * np.arange(0.0, calcTotSteps + 0.0001, calcSteps) return numWats, dipCorrs, timeVals
def gen_simulation(gro_file, psf_file, prm_file, T, P, pcoupl='iso'): print('Building system...') gro = app.GromacsGroFile(gro_file) psf = OplsPsfFile(psf_file, periodicBoxVectors=gro.getPeriodicBoxVectors()) prm = app.CharmmParameterSet(prm_file) system = psf.createSystem(prm, nonbondedMethod=app.PME, ewaldErrorTolerance=1E-5, nonbondedCutoff=1.2 * nm, constraints=app.HBonds, rigidWater=True, verbose=True) if not psf.is_drude: print('\tLangevin thermostat: 1.0/ps') integrator = mm.LangevinIntegrator(T * kelvin, 1.0 / ps, 0.001 * ps) else: print('\tDual Langevin thermostat: 10/ps, 50/ps') integrator = mm.DrudeLangevinIntegrator(T * kelvin, 10 / ps, 1 * kelvin, 50 / ps, 0.001 * ps) integrator.setMaxDrudeDistance(0.02 * nm) if pcoupl == 'iso': print('\tIsotropic barostat') system.addForce(mm.MonteCarloBarostat(P * bar, T * kelvin, 25)) elif pcoupl == 'xyz': print('\tAnisotropic barostat') system.addForce( mm.MonteCarloAnisotropicBarostat([P * bar] * 3, T * kelvin, True, True, True, 25)) elif pcoupl == 'xy': print('\tAnisotropic Barostat only for X and Y') system.addForce( mm.MonteCarloAnisotropicBarostat([P * bar] * 3, T * kelvin, True, True, False, 25)) else: print('\tNo barostat') print('Initializing simulation...') platform = mm.Platform.getPlatformByName('CUDA') properties = {'CudaPrecision': 'mixed'} sim = app.Simulation(psf.topology, system, integrator, platform, properties) sim.context.setPositions(gro.positions) sim.context.setVelocitiesToTemperature(T * kelvin) sim.reporters.append(GroReporter('dump.gro', 10000)) sim.reporters.append(app.DCDReporter('dump.dcd', 1000)) sim.reporters.append( app.StateDataReporter(sys.stdout, 500, step=True, temperature=True, potentialEnergy=True, kineticEnergy=True, volume=True, density=True, elapsedTime=True, speed=True, separator='\t')) state = sim.context.getState(getEnergy=True) print('Energy: ' + str(state.getPotentialEnergy())) return sim
system = psf.createSystem(params, nonbondedMethod=ff.PME, nonbondedCutoff=1.20, switchDistance=1.00, ewaldErrorTolerance=0.0001, constraints=ff.HBonds) if ftype == 'c36': system = psf.createSystem(params, nonbondedMethod=ff.PME, nonbondedCutoff=1.20, switchDistance=1.00, ewaldErrorTolerance=0.0001, constraints=ff.HBonds) system.addForce( mm.MonteCarloAnisotropicBarostat((1, 1, 1) * bar, temp * kelvin, True, True, True)) #if P.FLAG_POSRES_HEAVY : if restraint == 'Yes': harmonic_force_str = '%f*( (x-x0)*(x-x0) + (y-y0)*(y-y0) + (z-z0)*(z-z0) )' % restraint_force restr_force = mm.CustomExternalForce(harmonic_force_str) restr_force.addPerParticleParameter('x0') restr_force.addPerParticleParameter('y0') restr_force.addPerParticleParameter('z0') atoms = crd.topology.atoms() restr_list = list() for x in atoms: if x.element != None: if x.residue.name not in ("HOH", "SOL", "WAT", "SWM4", "SWM6",
def createOMMSimulation(system_specs, system, top, prefix="", chkfile='chkpnt.chk', verbose=False): # --- integration options --- # TODO: NPT sim_options, run_options = parsevalidate.parseSimulation(system_specs) print(sim_options) reduced_timestep = sim_options['dt'] dt = reduced_timestep * tau if sim_options['T'] is not None: reduced_temp = sim_options['T'] #1 temperature = reduced_temp * epsilon / kB / N_av reduced_Tdamp = sim_options['t_damp'] friction = 1 / (reduced_Tdamp) / tau pressure = sim_options['P'] if pressure is not None: useNPT = True useNVT = False else: useNPT = False useNVT = True """ reduced_pressure = 1 reduced_Pdamp = 0.1 #time units pressure = reduced_pressure * epsilon/(sigma**3) / N_av barostatInterval = int(reduced_Pdamp/reduced_timestep) """ #=========================== ## Prepare the Simulation ## #=========================== print("\n=== Preparing Simulation ===") if useNPT: pressure = pressure * epsilon / N_av / sigma / sigma / sigma #convert from unitless to OMM units barostatInterval = sim_options[ 'barostat_freq'] #in units of time steps. 25 is OpenMM default if sim_options['tension'] is not None and sim_options[ 'tension_alphascale'] == 0.: print( '...detected tension, but no extra nonlinear restoring force, using openMM Membrane Barostat...' ) print('...overriding tension_freq {} with barostat_freq {}'.format( sim_options['tension_freq'], barostatInterval)) if sim_options['tension_axis'] != 2: raise ValueError( '...openMM MembraneBarostat only accepts z-axis, but input script requested axis {}' ) tension = sim_options['tension'] * epsilon / sigma / sigma print('... applying tension of {}kT/sig^2'.format( sim_options['tension'])) print('... in OpenMM natural units: {}'.format(tension)) tension = (tension / N_av).value_in_unit( unit.bar * unit.nanometer) #to convert to bar*nm units print('... in bar*nm: {}'.format(tension)) #see https://github.com/openmm/openmm/issues/2438, can't include explicit units for tension... XYmode = openmm.MonteCarloMembraneBarostat.XYIsotropic Zmode = openmm.MonteCarloMembraneBarostat.ZFree my_barostat = openmm.MonteCarloMembraneBarostat( pressure, tension, temperature, XYmode, Zmode, barostatInterval) elif sim_options['barostat_axis'] in [ 'isotropic', 'iso', 'all', 'xyz' ]: my_barostat = openmm.MonteCarloBarostat(pressure, temperature, barostatInterval) elif sim_options['barostat_axis'] in [0, 'x', 'X']: my_barostat = openmm.MonteCarloAnisotropicBarostat( openmm.vec3.Vec3(pressure, pressure, pressure), temperature, True, False, False, barostatInterval) elif sim_options['barostat_axis'] in [1, 'y', 'Y']: my_barostat = openmm.MonteCarloAnisotropicBarostat( openmm.vec3.Vec3(pressure, pressure, pressure), temperature, False, True, False, barostatInterval) elif sim_options['barostat_axis'] in [2, 'z', 'Z']: my_barostat = openmm.MonteCarloAnisotropicBarostat( openmm.vec3.Vec3(pressure, pressure, pressure), temperature, False, False, True, barostatInterval) system.addForce(my_barostat) print("Added MC Barostat with P {} (eps/sig^3), T {}, freq {}".format( 6.02214179e23 * pressure.value_in_unit(unit.kilojoules / unit.nanometer**3), temperature, barostatInterval)) print("In OMM units, is P={}'bar'".format( pressure.value_in_unit(unit.bar))) if sim_options['T'] is None: print("This is a constant energy, constant volume (NVE) run.") integrator = openmm.VerletIntegrator(dt) else: if sim_options['thermostat'] == 'langevin': print("This is a thermostatted run with langevin thermostat") integrator = openmm.LangevinIntegrator(temperature, friction, dt) else: raise OMMError( "Specified temperature but unsupported thermostat {}".format( sim_options['thermostat'])) if system.getNumConstraints() > 0: print("Applying bond constraints before starting") integrator.setConstraintTolerance(CONSTRAINT_TOLERANCE) # TODO: simulation platform #platform = openmm.Platform.getPlatformByName('CUDA') #platformProperties = {'Precision': 'mixed'} #platform = openmm.Platform.getPlatformByName('CPU') #platform = openmm.Platform.getPlatformByName('Reference') #simulation = app.Simulation(top,system, integrator, platform) #simulation = app.Simulation(top,system, integrator, platform,platformProperties) if sim_options['platform'] is None: print("Automatically choosing platform") simulation = app.Simulation(top, system, integrator) else: platformName = sim_options['platform'] device = sim_options['device'] print("Manually setting platform: {} and device: {}".format( platformName, device)) platform = openmm.Platform.getPlatformByName(platformName) if platformName.lower() in ['CUDA', 'cuda']: platform.setPropertyDefaultValue("CudaDeviceIndex", str(device)) elif platformName.lower() in ['OpenCL', 'opencl']: platform.setPropertyDefaultValue("OpenCLDeviceIndex", str(device)) else: platform = openmm.Platform.getPlatformByName('CPU') simulation = app.Simulation(top, system, integrator, platform) chkfile = prefix + chkfile chkpt_freq = 10000 simulation.reporters.append( app.checkpointreporter.CheckpointReporter(chkfile, chkpt_freq)) # --- done --- #simOptions = {'dt':dt, 'temp':temperature, 'fric':friction} sim_options['temp_dimensionful'] = temperature print("") print("Parsed simulation options: {}".format(sim_options)) print("Parsed runtime options: {}".format(run_options)) return simulation, sim_options, run_options