.. include:: autodoc_abbr_options_c.rst .. _`sec:proc_py`: Adding Methods to Driver ======================== This is concerned at present with normal methods added first to the procedures table in driver.py that associates method names with functions to run them located in proc.py . The function should start with a declaration, as below. ``methodname`` is never seen by users, so it's good to be specific; if there's lots of modules that can run mp2, call methodname modulenamemethodname, perhaps. The function must always take as arguments ``(name, **kwargs)``. :: # energy method def run_methodname(name, **kwargs): # gradient method def run_methodname_gradient(name, **kwargs): If the function needs to test the identity of ``name`` several times, it can be convenient to predefine the lowercase version of the variable. The case of all other py-side options (in kwargs) has already been handled by :py:func:`~driver.energy()`, etc. in driver.py and need not be repeated here. :: # include if convenient lowername = name.lower() # never include kwargs = kwargs_lower(kwargs) It's often necessary to The function often needs to set options for the c-side modules it calls. In order that the state of the options set by the user remains when control is returned to the user, an :py:class:`~optproc.OptionsState` object is set up. See :ref:`sec:handlingOptions_py` for details. *All* options set by the function need to be included here, and *only* options set by the function should be included. Most options should be associated with a particular module, but a few (see below) are given without module. :: # include if any options set optstash = OptionsState( # these and other basis options should have no associated module ['BASIS'], ['DF_BASIS_SCF'], ['DF_BASIS_MP2'], ['PUREAM'], ['FREEZE_CORE'], # all others should have an associated module ['SCF', 'SCF_TYPE'], ['SCF', 'GUESS'], ['DFMP2', 'MP2_OS_SCALE'], ) If options need to be set, set them anywhere here. Options should be set locally to a module, except for those without a module in :py:class:`~optproc.OptionsState`. :: # include if necessary as globals psi4.set_global_option('BASIS', guessbasis) psi4.set_global_option('DF_BASIS_SCF', guessbasisdf) # include if necessary as locals psi4.set_local_option('TRANSQT2', 'WFN', 'MP2') psi4.set_local_option('CCSORT', 'WFN', 'MP2') psi4.set_local_option('MP2', 'WFN', 'MP2') If the regular scf module is to be run, run it through :py:func:`~proc.scf_helper` so that cast-up can be used. Also, add the option to bypass it by pre-running scf, then running the module with this ``bypass_scf`` kwarg. Also, if the full two-electron integrals are necessary for the post-scf, compute them if only the df integrals were run previously. :: # include if scf module is to be run # Bypass routine scf if user did something special to get it to converge if not (('bypass_scf' in kwargs) and yes.match(str(kwargs['bypass_scf']))): scf_helper(name, **kwargs) # include if TEI are needed beyond scf # If the scf type is DF, then the AO integrals were never generated if psi4.get_option('SCF', 'SCF_TYPE') == 'DF': mints = psi4.MintsHelper() mints.integrals() Direct any post-scf modules to be run. :: # include if further post-scf modules are needed psi4.transqt2() psi4.ccsort() psi4.mp2() If an :py:class:`~optproc.OptionsState` object was set up, those options need to be returned to the original user state with the following. :: # include if optstash = OptionsState( was set up previously optstash.restore() No function should return anything. ``CURRENT ENERGY`` will be set by :py:func:`~driver.energy`, etc. :: # never include return returnvalue