def run_cassandra_surf(chem_pot, temp): # Create box and species list box_list = [surface] species_list = [typed_surface,typed_ethane] # Since we have an occupied box we need to specify # the number of each species present in the intial config mols_in_boxes = [[2,0]] system = mc.System(box_list, species_list, mols_in_boxes=mols_in_boxes) moveset = mc.MoveSet("gcmc", species_list) custom_args = { "run_name": f"surfequil_{chem_pot:.0f}_{temp:.0f}", "chemical_potentials": ["none",chem_pot*u.Unit('kJ/mol')], "rcut_min": 0.3980 * 2.5* u.angstrom, #(or 3.0) "vdw_cutoff": min(box.lengths)/2.1* u.angstrom, "charge_style": "none", #"charge_cutoff": 14.0, "coord_freq": 100, "prop_freq": 10, } mc.run( system=system, moveset=moveset, run_type="equilibration", run_length= 3600549, # To reach ~1.33 hours temperature=temp*u.K, **custom_args ) # Set max translate and volume for production moveset.max_translate = [[0* u.angstrom,10.0* u.angstrom]] # angstroms # Update run_name and restart_name custom_args["run_name"] = f"surfprod_{chem_pot:.0f}_{temp:.0f}" custom_args["restart_name"] = f"surfequil_{chem_pot:.0f}_{temp:.0f}" mc.restart( system=system, moveset=moveset, run_type="production", run_length= 24097256, # To reach ~6.67 hours, total 8 hrs temperature=temp*u.K, **custom_args, )
def run_gemc(**custom_args): # Use mbuild to create molecules methane = mbuild.Compound(name="_CH4") # Create two empty mbuild.Box # (vapor = larger, liquid = smaller) liquid_box = mbuild.Box(lengths=[3.0, 3.0, 3.0]) vapor_box = mbuild.Box(lengths=[4.0, 4.0, 4.0]) # Load forcefields trappe = foyer.forcefields.load_TRAPPE_UA() # Use foyer to apply forcefields typed_methane = trappe.apply(methane) # Create box and species list box_list = [liquid_box, vapor_box] species_list = [typed_methane] mols_to_add = [[350], [100]] system = mc.System(box_list, species_list, mols_to_add=mols_to_add) moveset = mc.MoveSet("gemc", species_list) moveset.prob_volume = 0.010 moveset.prob_swap = 0.11 thermo_props = [ "energy_total", "energy_intervdw", "pressure", "volume", "nmols", "mass_density", ] default_args = { "run_name": "equil", "charge_style": "none", "rcut_min": 2.0 * u.angstrom, "vdw_cutoff": 14.0 * u.angstrom, "units": "sweeps", "steps_per_sweep": 450, "coord_freq": 50, "prop_freq": 10, "properties": thermo_props, } # Combine default/custom args and override default custom_args = {**default_args, **custom_args} mc.run( system=system, moveset=moveset, run_type="equilibration", run_length=250, temperature=151.0 * u.K, **custom_args, ) mc.restart( restart_from="equil", run_name="prod", run_type="production", total_run_length=750, )
def main(): # Create a water molecule with the spce geometry water = spce_water ff = foyer.Forcefield(get_ff("pore-spce-jc.xml")) water_typed = ff.apply(water) # Define conditions temperature = 298.0 * u.K # Define a range of (shifted) chemical potentials mus_adsorbate = np.arange(-58, -42, 2) * u.Unit("kJ/mol") # Define custom_args that are the same for all pure phase simulations custom_args = { "cutoff_style": "cut", "charge_style": "ewald", "rcut_min": 0.5 * u.angstrom, "vdw_cutoff": 9.0 * u.angstrom, "prop_freq": 10, "angle_style": ["fixed"], } for mu_adsorbate in mus_adsorbate: print(f"\nRun simulation: T = {temperature}, mu = {mu_adsorbate}\n") dirname = f"T_{temperature:0.1f}_mu_{mu_adsorbate:.1f}".replace( " ", "_" ).replace( "/", "-" ) if not os.path.isdir(dirname): os.mkdir(dirname) else: pass with temporary_cd(dirname): # Box size depends on chemical potential # Test simulations show mu' = -48 kJ/mol; p ~ 0.01 bar # Employ IG law to estimate remaining box sizes; target 40 waters mu_0 = -48 * u.kJ/u.mol p_0 = 0.01 * u.bar n_water_target = 40 p_ig = p_0 * np.exp((mu_adsorbate-mu_0)/(u.kb * temperature)) vol = n_water_target * u.kb * temperature / p_ig boxl = (vol**(1./3.)).to_value("nm") custom_args["charge_cutoff"] = 0.25 * boxl * u.nm species_list = [water_typed] box_list = [mbuild.Box([boxl, boxl, boxl])] system = mc.System( box_list, species_list, ) moveset = mc.MoveSet("gcmc", species_list) moveset.prob_regrow = 0.0 moveset.prob_translate = 0.3 moveset.prob_rotate = 0.3 moveset.prob_insert = 0.2 mc.run( system=system, moveset=moveset, run_type="equil", run_length=500000, temperature=temperature, run_name="equil", chemical_potentials=[mu_adsorbate], **custom_args, ) mc.restart( system=system, moveset=moveset, run_type="prod", run_length=1000000, temperature=temperature, run_name="prod", restart_name="equil", chemical_potentials=[mu_adsorbate], **custom_args, )
def main(): # Load TON from a CIF file, replicate the cell # Use mbuild to create a zeolite supercell from CIF cif_path = resource_filename( "mc_examples", "realistic_workflows/zeolite_adsorption/resources/structures/TON.cif") lattice = mbuild.lattice.load_cif(cif_path) compound_dict = { "Si": mbuild.Compound(name="Si"), "O": mbuild.Compound(name="O"), } zeolite = lattice.populate(compound_dict, 2, 2, 6) # Create a CG methane, load and apply ff methane = mbuild.Compound(name="_CH4") ff_path = resource_filename( "mc_examples", "realistic_workflows/zeolite_adsorption/resources/ffxml/adsorbates.xml", ) ff_ads = foyer.Forcefield(ff_path) methane_ff = ff_ads.apply(methane) # Define pure fluid temperatures and chemical potentials temperatures = [298 * u.K, 309 * u.K, 350 * u.K] mus_fluid = np.arange(-49, -30, 3) * u.Unit("kJ/mol") # Define the pressures at which we wish to study adsorption pressures = [ 0.01, 0.1, 0.25, 0.5, 0.75, 1.0, 2.0, 3.0, 5.0, ] * u.bar # Select the zeolite ff zeo_ff_names = ["june", "trappe"] # Define a few custom_args that will be # the same for all zeolite simulations custom_args = { "charge_style": "none", "vdw_cutoff": 14.0 * u.angstrom, "prop_freq": 10, "max_molecules": [1, 10000], } # Loop over different zeolite ff's for zeo_ff_name in zeo_ff_names: # Load and apply ff to the zeolite structure ff_path = resource_filename( "mc_examples", f"realistic_workflows/zeolite_adsorption/resources/ffxml/zeo_{zeo_ff_name}.xml", ) ff_zeo = foyer.Forcefield(ff_path) zeolite_ff = ff_zeo.apply(zeolite) # Create the box_list, species_list, System, and MoveSet. # These are not dependent upon (T,P) condition box_list = [zeolite] species_list = [zeolite_ff, methane_ff] mols_in_boxes = [[1, 0]] system = mc.System(box_list, species_list, mols_in_boxes=mols_in_boxes) moveset = mc.MoveSet("gcmc", species_list) # Loop over each temperature to compute an isotherm for temperature in temperatures: # Before we begin we must determine the # chemical potentials required to achieve # the desired pressures fluid_pressures = [] for mu_fluid in mus_fluid: dirname = f"fluid_T_{temperature:0.1f}_mu_{mu_fluid:.1f}".replace( " ", "_").replace("/", "-") thermo = ThermoProps(dirname + "/prod.out.prp") fluid_pressures.append(np.mean(thermo.prop("Pressure"))) fluid_pressures = u.unyt_array(fluid_pressures) # Fit a line to mu vs. P slope, intercept, r_value, p_value, stderr = linregress( np.log(fluid_pressures.to_value(u.bar)).flatten(), y=mus_fluid.to_value("kJ/mol").flatten(), ) # Determine chemical potentials mus = (slope * np.log(pressures.in_units(u.bar)) + intercept) * u.Unit("kJ/mol") # Loop over each pressure and run the MC simulation! for (pressure, mu) in zip(pressures, mus): print(f"\nRun simulation: T = {temperature}, P = {pressure}\n") dirname = f"zeo_ff_{zeo_ff_name}_T_{temperature:0.1f}_P_{pressure:0.2f}".replace( " ", "_").replace("/", "-") if not os.path.isdir(dirname): os.mkdir(dirname) else: pass with temporary_cd(dirname): mc.run( system=system, moveset=moveset, run_type="equil", run_length=50000, temperature=temperature, run_name="equil", chemical_potentials=["none", mu], **custom_args, ) mc.restart( restart_from="equil", run_name="prod", run_type="prod", total_run_length=200000, )
def run_gemc(job): "Run gemc" import mbuild import foyer import mosdef_cassandra as mc ff = foyer.Forcefield(job.fn("ff.xml")) # Load the compound and apply the ff compound = mbuild.load("C(F)(F)C(F)(F)F", smiles=True) compound_ff = ff.apply(compound) # Create box list and species list boxl = job.doc.liqbox_final_dim # saved in nm liq_box = mbuild.load(job.fn("liqbox.xyz")) liq_box.periodicity = [boxl, boxl, boxl] boxl = job.doc.vapboxl # nm vap_box = mbuild.Box(lengths=[boxl, boxl, boxl]) box_list = [liq_box, vap_box] species_list = [compound_ff] mols_in_boxes = [[job.sp.N_liq], [0]] mols_to_add = [[0], [job.sp.N_vap]] system = mc.System( box_list, species_list, mols_in_boxes=mols_in_boxes, mols_to_add=mols_to_add, ) # Create a new moves object moves = mc.Moves("gemc", species_list) # Edit the volume and swap move probability to be more reasonable orig_prob_volume = moves.prob_volume orig_prob_swap = moves.prob_swap new_prob_volume = 1.0 / (job.sp.N_liq + job.sp.N_vap) new_prob_swap = 4.0 / 0.05 / (job.sp.N_liq + job.sp.N_vap) moves.prob_volume = new_prob_volume moves.prob_swap = new_prob_swap moves.prob_translate = (moves.prob_translate + orig_prob_volume - new_prob_volume) moves.prob_translate = (moves.prob_translate + orig_prob_swap - new_prob_swap) # Define thermo output props thermo_props = [ "energy_total", "pressure", "volume", "nmols", "mass_density", "enthalpy", ] # Define custom args custom_args = { "run_name": "equil", "charge_style": "ewald", "rcut_min": 1.0, "charge_cutoff_box2": 25.0, "vdw_cutoff_box1": 12.0, "vdw_cutoff_box2": 25.0, "units": "sweeps", "steps_per_sweep": job.sp.N_liq + job.sp.N_vap, "coord_freq": 500, "prop_freq": 10, "properties": thermo_props, } # Move into the job dir and start doing things with job: # Run equilibration mc.run(system=system, moves=moves, run_type="equilibration", run_length=job.sp.nsteps_eq, temperature=job.sp.T, **custom_args) # Adjust custom args for production custom_args["run_name"] = "prod" custom_args["restart_name"] = "equil" # Run production mc.restart(system=system, moves=moves, run_type="production", run_length=job.sp.nsteps_prod, temperature=job.sp.T, **custom_args)
def main(): # Create a CG methane, load and apply ff methane = mbuild.Compound(name="_CH4") ff_path = resource_filename( "mc_examples", "realistic_workflows/zeolite_adsorption/resources/ffxml/adsorbates.xml", ) ff_ads = foyer.Forcefield(ff_path) methane_ff = ff_ads.apply(methane) # Define a few keyword args that will be the # same for all fluid phase simulations custom_args = { "charge_style": "none", "vdw_cutoff": 14.0 * u.angstrom, "prop_freq": 10, } # Define temperatures and chemical potential values # for the single phase GCMC simulations temperatures = [298 * u.K, 309 * u.K, 350 * u.K] mus = np.arange(-49, -30, 3) * u.Unit("kJ/mol") # Loop over temperatures and mus and run simulations for temperature in temperatures: for mu in mus: # For each simulation -- first estimate # the box volume to target ~40 molecules n_methane_target = 40 beta = 1.0 / (u.kb * temperature) mass = 16.04 * u.amu debroglie = np.sqrt(2 * np.pi * u.hbar**2 * beta / mass) vol = n_methane_target * debroglie**3 * np.exp( -beta.to("mol/kJ") * mu) boxl = (vol**(1.0 / 3.0)).to_value("nm") if boxl < 2.0 * custom_args["vdw_cutoff"].to_value("nm"): boxl = 2.0 * custom_args["vdw_cutoff"].to_value("nm") # Define the species list, box list, system, moveset # We start with an empty box species_list = [methane_ff] box_list = [mbuild.Box([boxl, boxl, boxl])] system = mc.System(box_list, species_list) moveset = mc.MoveSet("gcmc", species_list) # Create a new directory, temporary cd, and run # the equilibration and production simulations! print(f"\nRun simulation: T = {temperature}, mu = {mu}\n") dirname = f"fluid_T_{temperature:0.1f}_mu_{mu:.1f}".replace( " ", "_").replace("/", "-") if not os.path.isdir(dirname): os.mkdir(dirname) else: pass with temporary_cd(dirname): mc.run( system=system, moveset=moveset, run_type="equil", run_length=50000, temperature=temperature, run_name="equil", chemical_potentials=[mu], **custom_args, ) mc.restart( restart_from="equil", run_name="prod", run_type="prod", total_run_length=400000, )
def run_simulation(job): """Run GCMC simulations for the given statepoint""" import mbuild import foyer import unyt as u import numpy as np import mosdef_cassandra as mc from mosdef_slitpore.utils.cassandra_helpers import spce_water from mosdef_slitpore.utils.utils import get_ff temperature = job.sp.T * u.K mu = job.sp.mu * u.kJ / u.mol nsteps_eq = job.sp.nsteps.equil nsteps_prod = job.sp.nsteps.prod seed1 = job.sp.seed1 seed2 = job.sp.seed2 # Want box size to depend on chemical potential # Prelim simulation shows mu' = -48 kJ/mol; p ~ 0.01 bar # Employ IG law to estimate remaining box sizes; target 40 waters mu_0 = -48 * u.kJ / u.mol p_0 = 0.01 * u.bar n_water_target = 40 p_ig = p_0 * np.exp((mu - mu_0) / (u.kb * temperature)) vol = n_water_target * u.kb * temperature / p_ig boxl = (vol**(1. / 3.)).to_value("nm") # Define custom_args that are the same # for all pure phase simulations custom_args = { "cutoff_style": "cut", "charge_style": "ewald", "rcut_min": 0.5 * u.angstrom, "vdw_cutoff": 9.0 * u.angstrom, "charge_cutoff": 0.25 * boxl * u.nm, "prop_freq": 1000, "angle_style": ["fixed"], "seeds": [seed1, seed2], } # Create a water molecule with the spce geometry ff = foyer.Forcefield(get_ff("pore-spce.xml")) water_typed = ff.apply(spce_water) species_list = [water_typed] box_list = [mbuild.Box([boxl, boxl, boxl])] system = mc.System( box_list, species_list, ) moveset = mc.MoveSet("gcmc", species_list) moveset.prob_regrow = 0.0 moveset.prob_translate = 0.3 moveset.prob_rotate = 0.3 moveset.prob_insert = 0.2 with job: mc.run( system=system, moveset=moveset, run_type="equil", run_length=nsteps_eq, temperature=temperature, run_name="equil", chemical_potentials=[mu], **custom_args, ) mc.restart( system=system, moveset=moveset, run_type="prod", run_length=nsteps_prod, temperature=temperature, run_name="prod", restart_name="equil", chemical_potentials=[mu], **custom_args, )
def run_gemc(): # Use mbuild to create molecules methane = mbuild.Compound(name="_CH4") # Create two empty mbuild.Box # (vapor = larger, liquid = smaller) liquid_box = mbuild.Box(lengths=[3.0, 3.0, 3.0]) vapor_box = mbuild.Box(lengths=[4.0, 4.0, 4.0]) # Load forcefields trappe = foyer.forcefields.load_TRAPPE_UA() # Use foyer to apply forcefields typed_methane = trappe.apply(methane) # Create box and species list box_list = [liquid_box, vapor_box] species_list = [typed_methane] mols_to_add = [[350], [100]] system = mc.System(box_list, species_list, mols_to_add=mols_to_add) moves = mc.Moves("gemc", species_list) moves.prob_volume = 0.010 moves.prob_swap = 0.11 thermo_props = [ "energy_total", "energy_intervdw", "pressure", "volume", "nmols", "mass_density", ] custom_args = { "run_name": "equil", "charge_style": "none", "rcut_min": 2.0, "vdw_cutoff": 14.0, "units": "sweeps", "steps_per_sweep": 450, "coord_freq": 50, "prop_freq": 10, "properties": thermo_props, } mc.run( system=system, moves=moves, run_type="equilibration", run_length=250, temperature=151.0, **custom_args, ) # Set max translate and volume for production moves.max_translate = [[0.5], [14.0]] moves.max_volume = [700.0] # Update run_name and restart_name custom_args["run_name"] = "prod" custom_args["restart_name"] = "equil" mc.restart( system=system, moves=moves, run_type="production", run_length=750, temperature=151.0, **custom_args, )
def run_nvt(filled_pore, temperature, nsteps_eq, nsteps_prod, **custom_args): """Run an NVT MC simulation at the specified temperature Parameters ---------- filled_pore : porebuilder.GraphenePoreSolvent pore filled with water temperature: u.unyt_quantity (temperature) desired temperature nsteps_eq : int number of MC steps for NVT equilibration nsteps_prod : int number of MC steps for GCMC simulation custom_args : opt, additional keyword arguments provide additional custom keyword arguments to MoSDeF Cassandra and override the default values Returns ------- None: runs simulation """ # Load foyer ff ff = foyer.Forcefield(get_ff("pore-spce.xml")) # Extract just the pore and apply ff empty_pore = filled_pore.children[0] typed_pore = ff.apply(empty_pore) # Create a water molecule with the spce geometry and apply ff typed_water = ff.apply(spce_water) # Determine the number of waters in the pore nwater = len([child for child in filled_pore.children]) - 1 # Create box and species list box_list = [filled_pore] species_list = [typed_pore, typed_water] # Specify mols at start of the simulation mols_in_boxes = [[1, nwater]] # Create MC system system = mc.System(box_list, species_list, mols_in_boxes=mols_in_boxes) moves = mc.MoveSet("nvt", species_list) # Set move probabilities moves.prob_translate = 0.5 moves.prob_rotate = 0.5 moves.prob_regrow = 0.0 # Set thermodynamic properties thermo_props = [ "energy_total", "energy_intervdw", "energy_interq", ] default_args = { "run_name": "equil.nvt", "cutoff_style": "cut", "charge_style": "ewald", "rcut_min": 0.5 * u.angstrom, "vdw_cutoff": 9.0 * u.angstrom, "charge_cutoff": 9.0 * u.angstrom, "properties": thermo_props, "angle_style": ["harmonic", "fixed"], "coord_freq": 10000, "prop_freq": 1000, } custom_args = {**default_args, **custom_args} # Run NVT equilibration mc.run( system=system, moveset=moves, run_type="equilibration", run_length=nsteps_eq, temperature=temperature, **custom_args, ) # Run production custom_args["run_name"] = "prod.nvt" custom_args["restart_name"] = "equil.nvt" mc.restart( system=system, moveset=moves, run_type="production", run_length=nsteps_prod, temperature=temperature, **custom_args, )