def energy_minimize(dirname='em', mdp=config.templates['em.mdp'], struct='solvate/ionized.pdb', top='top/system.top', output='em.pdb', deffnm="em", mdrunner=None, **kwargs): """Energy minimize the system. This sets up the system (creates run input files) and also runs ``mdrun_d``. Thus it can take a while. Additional itp files should be in the same directory as the top file. Many of the keyword arguments below already have sensible values. :Keywords: *dirname* set up under directory dirname [em] *struct* input structure (gro, pdb, ...) [solvate/ionized.pdb] *output* output structure (will be put under dirname) [em.pdb] *deffnm* default name for mdrun-related files [em] *top* topology file [top/system.top] *mdp* mdp file (or use the template) [templates/em.mdp] *includes* additional directories to search for itp files *mdrunner* :class:`gromacs.run.MDrunner` class; by defauly we just try :func:`gromacs.mdrun_d` and :func:`gromacs.mdrun` but a MDrunner class gives the user the ability to run mpi jobs etc. [None] *kwargs* remaining key/value pairs that should be changed in the template mdp file, eg ``nstxtcout=250, nstfout=250``. .. note:: If :func:`~gromacs.mdrun_d` is not found, the function falls back to :func:`~gromacs.mdrun` instead. """ structure = realpath(struct) topology = realpath(top) mdp_template = config.get_template(mdp) deffnm = deffnm.strip() # write the processed topology to the default output kwargs.setdefault('pp', 'processed.top') # filter some kwargs that might come through when feeding output # from previous stages such as solvate(); necessary because *all* # **kwargs must be *either* substitutions in the mdp file *or* valid # command line parameters for ``grompp``. kwargs.pop('ndx', None) # mainselection is not used but only passed through; right now we # set it to the default that is being used in all argument lists # but that is not pretty. TODO. mainselection = kwargs.pop('mainselection', '"Protein"') # only interesting when passed from solvate() qtot = kwargs.pop('qtot', 0) mdp = deffnm+'.mdp' tpr = deffnm+'.tpr' logger.info("[%(dirname)s] Energy minimization of struct=%(struct)r, top=%(top)r, mdp=%(mdp)r ..." % vars()) add_mdp_includes(topology, kwargs) if qtot != 0: # At the moment this is purely user-reported and really only here because # it might get fed into the function when using the keyword-expansion pipeline # usage paradigm. wmsg = "Total charge was reported as qtot = %(qtot)g <> 0; probably a problem." % vars() logger.warn(wmsg) warnings.warn(wmsg, category=BadParameterWarning) with in_dir(dirname): unprocessed = gromacs.cbook.edit_mdp(mdp_template, new_mdp=mdp, **kwargs) check_mdpargs(unprocessed) gromacs.grompp(f=mdp, o=tpr, c=structure, p=topology, **unprocessed) mdrun_args = dict(v=True, stepout=10, deffnm=deffnm, c=output) if mdrunner is None: try: gromacs.mdrun_d(**mdrun_args) except (AttributeError, OSError): # fall back to mdrun if no double precision binary wmsg = "No 'mdrun_d' binary found so trying 'mdrun' instead.\n"\ "(Note that energy minimization runs better with mdrun_d.)" logger.warn(wmsg) warnings.warn(wmsg, category=AutoCorrectionWarning) gromacs.mdrun(**mdrun_args) else: # user wants full control and provides simulation.MDrunner **class** # NO CHECKING --- in principle user can supply any callback they like mdrun = mdrunner(**mdrun_args) mdrun.run() # em.gro --> gives 'Bad box in file em.gro' warning --- why?? # --> use em.pdb instead. if not os.path.exists(output): errmsg = "Energy minimized system NOT produced." logger.error(errmsg) raise GromacsError(errmsg) final_struct = realpath(output) logger.info("[%(dirname)s] energy minimized structure %(final_struct)r" % vars()) return {'struct': final_struct, 'top': topology, 'mainselection': mainselection, }
def _setup_MD(dirname, deffnm='md', mdp=config.templates['md_OPLSAA.mdp'], struct=None, top='top/system.top', ndx=None, mainselection='"Protein"', qscript=config.qscript_template, qname=None, startdir=None, mdrun_opts="", budget=None, walltime=1/3., dt=0.002, runtime=1e3, multi=1, **mdp_kwargs): """Generic function to set up a ``mdrun`` MD simulation. See the user functions for usage. @param qname: name of the queing system, may be None. @param multi: setup multiple concurrent simulations. These are based upon deffnm being set, and a set of mdp / tpr are created named [deffnm]0.tpr. [deffnm]1.tpr, ... """ if struct is None: raise ValueError('struct must be set to a input structure') structure = realpath(struct) topology = realpath(top) try: index = realpath(ndx) except AttributeError: # (that's what realpath(None) throws...) index = None # None is handled fine below qname = mdp_kwargs.pop('sgename', qname) # compatibility for old scripts qscript = mdp_kwargs.pop('sge', qscript) # compatibility for old scripts qscript_template = config.get_template(qscript) mdp_template = config.get_template(mdp) nsteps = int(float(runtime)/float(dt)) mainindex = deffnm + '.ndx' final_structure = deffnm + '.pdb' # guess... really depends on templates,could also be DEFFNM.pdb # write the processed topology to the default output mdp_parameters = {'nsteps':nsteps, 'dt':dt} mdp_parameters.update(mdp_kwargs) add_mdp_includes(topology, mdp_parameters) # the basic result dictionary # depending on options, various bits might be added to this. result = {'struct': realpath(os.path.join(dirname, final_structure)), # guess 'top': topology, 'ndx': index, # possibly mainindex 'mainselection': mainselection, 'deffnm': deffnm, # return deffnm (tpr = deffnm.tpr!) } with in_dir(dirname): if not (mdp_parameters.get('Tcoupl','').lower() == 'no' or mainselection is None): logger.info("[%(dirname)s] Automatic adjustment of T-coupling groups" % vars()) # make index file in almost all cases; with mainselection == None the user # takes FULL control and also has to provide the template or index groups = make_main_index(structure, selection=mainselection, oldndx=index, ndx=mainindex) natoms = dict([(g['name'], float(g['natoms'])) for g in groups]) tc_group_names = ('__main__', '__environment__') # defined in make_main_index() try: x = natoms['__main__']/natoms['__environment__'] except KeyError: x = 0 # force using SYSTEM in code below wmsg = "Missing __main__ and/or __environment__ index group.\n" \ "This probably means that you have an atypical system. You can " \ "set mainselection=None and provide your own mdp and index files " \ "in order to set up temperature coupling.\n" \ "If no T-coupling is required then set Tcoupl='no'.\n" \ "For now we will just couple everything to 'System'." logger.warn(wmsg) warnings.warn(wmsg, category=AutoCorrectionWarning) if x < 0.1: # couple everything together tau_t = firstof(mdp_parameters.pop('tau_t', 0.1)) ref_t = firstof(mdp_parameters.pop('ref_t', 300)) # combine all in one T-coupling group mdp_parameters['tc-grps'] = 'System' mdp_parameters['tau_t'] = tau_t # this overrides the commandline! mdp_parameters['ref_t'] = ref_t # this overrides the commandline! mdp_parameters['gen-temp'] = mdp_parameters.pop('gen_temp', ref_t) wmsg = "Size of __main__ is only %.1f%% of __environment__ so " \ "we use 'System' for T-coupling and ref_t = %g K and " \ "tau_t = %g 1/ps (can be changed in mdp_parameters).\n" \ % (x * 100, ref_t, tau_t) logger.warn(wmsg) warnings.warn(wmsg, category=AutoCorrectionWarning) else: # couple protein and bath separately n_tc_groups = len(tc_group_names) tau_t = asiterable(mdp_parameters.pop('tau_t', 0.1)) ref_t = asiterable(mdp_parameters.pop('ref_t', 300)) if len(tau_t) != n_tc_groups: tau_t = n_tc_groups * [tau_t[0]] wmsg = "%d coupling constants should have been supplied for tau_t. "\ "Using %f 1/ps for all of them." % (n_tc_groups, tau_t[0]) logger.warn(wmsg) warnings.warn(wmsg, category=AutoCorrectionWarning) if len(ref_t) != n_tc_groups: ref_t = n_tc_groups * [ref_t[0]] wmsg = "%d temperatures should have been supplied for ref_t. "\ "Using %g K for all of them." % (n_tc_groups, ref_t[0]) logger.warn(wmsg) warnings.warn(wmsg, category=AutoCorrectionWarning) mdp_parameters['tc-grps'] = tc_group_names mdp_parameters['tau_t'] = tau_t mdp_parameters['ref_t'] = ref_t mdp_parameters['gen-temp'] = mdp_parameters.pop('gen_temp', ref_t[0]) index = realpath(mainindex) if mdp_parameters.get('Tcoupl','').lower() == 'no': logger.info("Tcoupl == no: disabling all temperature coupling mdp options") mdp_parameters['tc-grps'] = "" mdp_parameters['tau_t'] = "" mdp_parameters['ref_t'] = "" mdp_parameters['gen-temp'] = "" if mdp_parameters.get('Pcoupl','').lower() == 'no': logger.info("Pcoupl == no: disabling all pressure coupling mdp options") mdp_parameters['tau_p'] = "" mdp_parameters['ref_p'] = "" mdp_parameters['compressibility'] = "" # do multiple concurrent simulations - ensemble sampling if multi > 1: for i in range(multi): new_mdp = deffnm + str(i) + ".mdp" mdout = deffnm + "out" + str(i) + ".mdp" pp = "processed" + str(i) + ".top" tpr = deffnm + str(i) + ".tpr" # doing ensemble sampling, so give differnt seeds for each one # if we are using 32 bit gromacs, make seeds are are 32 bit even on # 64 bit machine mdp_parameters["andersen_seed"] = random.randint(0,2**31) mdp_parameters["gen_seed"] = random.randint(0,2**31) mdp_parameters["ld_seed"] = random.randint(0,2**31) unprocessed = gromacs.cbook.edit_mdp(mdp_template, new_mdp=new_mdp, **mdp_parameters) check_mdpargs(unprocessed) gromacs.grompp(f=new_mdp, p=topology, c=structure, n=index, o=tpr, po=mdout, pp=pp, **unprocessed) # only add multi to result if we really are doing multiple runs result["multi"] = multi else: new_mdp = deffnm + '.mdp' tpr = deffnm + '.tpr' unprocessed = gromacs.cbook.edit_mdp(mdp_template, new_mdp=new_mdp, **mdp_parameters) check_mdpargs(unprocessed) gromacs.grompp(f=new_mdp, p=topology, c=structure, n=index, o=tpr, po="mdout.mdp", pp="processed.top", **unprocessed) # generate scripts for queing system if requested if qname is not None: runscripts = gromacs.qsub.generate_submit_scripts( qscript_template, deffnm=deffnm, jobname=qname, budget=budget, startdir=startdir, mdrun_opts=mdrun_opts, walltime=walltime) result["qscript"] =runscripts logger.info("[%(dirname)s] All files set up for a run time of %(runtime)g ps " "(dt=%(dt)g, nsteps=%(nsteps)g)" % vars()) result.update(mdp_kwargs) # return extra mdp args so that one can use them for prod run result.pop('define', None) # but make sure that -DPOSRES does not stay... return result
def _setup_MD( dirname, deffnm="md", mdp=config.templates["md_OPLSAA.mdp"], struct=None, top="top/system.top", ndx=None, mainselection='"Protein"', qscript=config.qscript_template, qname=None, startdir=None, mdrun_opts="", budget=None, walltime=1 / 3.0, dt=0.002, runtime=1e3, **mdp_kwargs ): """Generic function to set up a ``mdrun`` MD simulation. See the user functions for usage. """ if struct is None: raise ValueError("struct must be set to a input structure") structure = realpath(struct) topology = realpath(top) try: index = realpath(ndx) except AttributeError: # (that's what realpath(None) throws...) index = None # None is handled fine below qname = mdp_kwargs.pop("sgename", qname) # compatibility for old scripts qscript = mdp_kwargs.pop("sge", qscript) # compatibility for old scripts qscript_template = config.get_template(qscript) mdp_template = config.get_template(mdp) nsteps = int(float(runtime) / float(dt)) mdp = deffnm + ".mdp" tpr = deffnm + ".tpr" mainindex = deffnm + ".ndx" final_structure = deffnm + ".gro" # guess... really depends on templates,could also be DEFFNM.pdb # write the processed topology to the default output mdp_parameters = {"nsteps": nsteps, "dt": dt, "pp": "processed.top"} mdp_parameters.update(mdp_kwargs) add_mdp_includes(topology, mdp_parameters) logger.info("[%(dirname)s] input mdp = %(mdp_template)r", vars()) with in_dir(dirname): if not (mdp_parameters.get("Tcoupl", "").lower() == "no" or mainselection is None): logger.info("[%(dirname)s] Automatic adjustment of T-coupling groups" % vars()) # make index file in almost all cases; with mainselection == None the user # takes FULL control and also has to provide the template or index groups = make_main_index(structure, selection=mainselection, oldndx=index, ndx=mainindex) natoms = dict([(g["name"], float(g["natoms"])) for g in groups]) tc_group_names = ("__main__", "__environment__") # defined in make_main_index() try: x = natoms["__main__"] / natoms["__environment__"] except KeyError: x = 0 # force using SYSTEM in code below wmsg = ( "Missing __main__ and/or __environment__ index group.\n" "This probably means that you have an atypical system. You can " "set mainselection=None and provide your own mdp and index files " "in order to set up temperature coupling.\n" "If no T-coupling is required then set Tcoupl='no'.\n" "For now we will just couple everything to 'System'." ) logger.warn(wmsg) warnings.warn(wmsg, category=AutoCorrectionWarning) if x < 0.1: # couple everything together tau_t = firstof(mdp_parameters.pop("tau_t", 0.1)) ref_t = firstof(mdp_parameters.pop("ref_t", 300)) # combine all in one T-coupling group mdp_parameters["tc-grps"] = "System" mdp_parameters["tau_t"] = tau_t # this overrides the commandline! mdp_parameters["ref_t"] = ref_t # this overrides the commandline! mdp_parameters["gen-temp"] = mdp_parameters.pop("gen_temp", ref_t) wmsg = ( "Size of __main__ is only %.1f%% of __environment__ so " "we use 'System' for T-coupling and ref_t = %g K and " "tau_t = %g 1/ps (can be changed in mdp_parameters).\n" % (x * 100, ref_t, tau_t) ) logger.warn(wmsg) warnings.warn(wmsg, category=AutoCorrectionWarning) else: # couple protein and bath separately n_tc_groups = len(tc_group_names) tau_t = asiterable(mdp_parameters.pop("tau_t", 0.1)) ref_t = asiterable(mdp_parameters.pop("ref_t", 300)) if len(tau_t) != n_tc_groups: tau_t = n_tc_groups * [tau_t[0]] wmsg = ( "%d coupling constants should have been supplied for tau_t. " "Using %f 1/ps for all of them." % (n_tc_groups, tau_t[0]) ) logger.warn(wmsg) warnings.warn(wmsg, category=AutoCorrectionWarning) if len(ref_t) != n_tc_groups: ref_t = n_tc_groups * [ref_t[0]] wmsg = "%d temperatures should have been supplied for ref_t. " "Using %g K for all of them." % ( n_tc_groups, ref_t[0], ) logger.warn(wmsg) warnings.warn(wmsg, category=AutoCorrectionWarning) mdp_parameters["tc-grps"] = tc_group_names mdp_parameters["tau_t"] = tau_t mdp_parameters["ref_t"] = ref_t mdp_parameters["gen-temp"] = mdp_parameters.pop("gen_temp", ref_t[0]) index = realpath(mainindex) if mdp_parameters.get("Tcoupl", "").lower() == "no": logger.info("Tcoupl == no: disabling all temperature coupling mdp options") mdp_parameters["tc-grps"] = "" mdp_parameters["tau_t"] = "" mdp_parameters["ref_t"] = "" mdp_parameters["gen-temp"] = "" if mdp_parameters.get("Pcoupl", "").lower() == "no": logger.info("Pcoupl == no: disabling all pressure coupling mdp options") mdp_parameters["tau_p"] = "" mdp_parameters["ref_p"] = "" mdp_parameters["compressibility"] = "" unprocessed = gromacs.cbook.edit_mdp(mdp_template, new_mdp=mdp, **mdp_parameters) check_mdpargs(unprocessed) gromacs.grompp(f=mdp, p=topology, c=structure, n=index, o=tpr, **unprocessed) runscripts = gromacs.qsub.generate_submit_scripts( qscript_template, deffnm=deffnm, jobname=qname, budget=budget, startdir=startdir, mdrun_opts=mdrun_opts, walltime=walltime, ) logger.info("[%(dirname)s] output mdp = %(mdp)r", vars()) logger.info("[%(dirname)s] output ndx = %(ndx)r", vars()) logger.info("[%(dirname)s] output tpr = %(tpr)r", vars()) logger.info("[%(dirname)s] output runscripts = %(runscripts)r", vars()) logger.info( "[%(dirname)s] All files set up for a run time of %(runtime)g ps " "(dt=%(dt)g, nsteps=%(nsteps)g)" % vars() ) kwargs = { "struct": realpath(os.path.join(dirname, final_structure)), # guess "top": topology, "ndx": index, # possibly mainindex "qscript": runscripts, "mainselection": mainselection, "deffnm": deffnm, # return deffnm (tpr = deffnm.tpr!) } kwargs.update(mdp_kwargs) # return extra mdp args so that one can use them for prod run return kwargs