Skip to content

Commit

Permalink
new string cbs syntax (#2532)
Browse files Browse the repository at this point in the history
* new string cbs syntax

* review comments

* testing details

* another win conda attempt
  • Loading branch information
loriab committed Apr 8, 2022
1 parent fe6b26d commit 8a91285
Show file tree
Hide file tree
Showing 47 changed files with 5,701 additions and 193 deletions.
57 changes: 44 additions & 13 deletions doc/sphinxman/source/cbs.rst
Original file line number Diff line number Diff line change
Expand Up @@ -55,19 +55,35 @@ below more conveniently than the equivalent second or third items.

* ``energy('mp2/cc-pv[dt]z')``

* ``energy(cbs, corl_wfn='mp2', corl_basis='cc-pv[dt]z')``
* ``energy("cbs", corl_wfn='mp2', corl_basis='cc-pv[dt]z')``

* ``energy(cbs, cbs_metadata=[{"wfn": "hf", "basis": "cc-pvtz"}, {"wfn": "mp2", "basis": "cc-pv[dt]z"}])``
* ``energy("cbs", cbs_metadata=[{"wfn": "hf", "basis": "cc-pvtz"}, {"wfn": "mp2", "basis": "cc-pv[dt]z", "scheme": "corl_xtpl_helgaker_2"}])``

.. caution:: In |PSIfour| previous to Spring 2022 and v1.6, calling certain
cbs-related functions like the above looked like ::

energy(cbs, corl_wfn='mp2', corl_basis='cc-pv[dt]z')

energy(cbs, cbs_metadata=[{"wfn": "hf", "basis": "cc-pvtz"}, {"wfn": "mp2", "basis": "cc-pv[dt]z", "scheme": corl_xtpl_helgaker_2}])

The difference is that the main function
:py:func:`psi4.cbs` and extrapolation schemes like
:py:func:`psi4.driver.driver_cbs_helper.xtpl_highest_1` and
:py:func:`psi4.driver.driver_cbs_helper.scf_xtpl_helgaker_2` and composite
aliases like :py:func:`psi4.driver.aliases.sherrill_gold_standard`
and :py:func:`psi4.driver.aliases.allen_focal_point` in the old way
passed the Python function directly, whereas the new way uses the
string of the function name.

A CCSD(T) DT coupled-cluster correction atop a TQ MP2 extrapolation
geometry optimization can also be accessed through the first item below more
conveniently than the equivalent second and third items.

* ``optimize('mp2/cc-pv[tq]z + D:ccsd(t)/cc-pvdz')``

* ``optimize(cbs, corl_wfn='mp2', corl_basis='cc-pv[tq]z', delta_wfn='ccsd(t)', delta_basis='cc-pvdz')``
* ``optimize("cbs", corl_wfn='mp2', corl_basis='cc-pv[tq]z', delta_wfn='ccsd(t)', delta_basis='cc-pvdz')``

* ``optimize(cbs, cbs_metadata=[{"wfn": "hf", "basis": "cc-pvqz"}, {"wfn": "mp2", "basis": "cc-pv[tq]z"}, {"wfn": "ccsd(t)", "basis": "cc-pvdz"}])``
* ``optimize("cbs", cbs_metadata=[{"wfn": "hf", "basis": "cc-pvqz"}, {"wfn": "mp2", "basis": "cc-pv[tq]z"}, {"wfn": "ccsd(t)", "basis": "cc-pvdz"}])``

Many examples can be found at :srcsample:`cbs-xtpl-energy`,
:srcsample:`cbs-xtpl-gradient`, :srcsample:`cbs-xtpl-opt`,
Expand Down Expand Up @@ -164,34 +180,49 @@ of the cbs procedure. The stage energies of this section sum outright to the tot
Extrapolation Schemes
^^^^^^^^^^^^^^^^^^^^^

.. autofunction:: psi4.driver.driver_cbs.xtpl_highest_1
Basis set extrapolations are encoded into individual functions like the built-in ones below:

.. autofunction:: psi4.driver.driver_cbs.scf_xtpl_helgaker_2
.. autofunction:: psi4.driver.driver_cbs_helper.xtpl_highest_1

.. autofunction:: psi4.driver.driver_cbs.scf_xtpl_truhlar_2
.. autofunction:: psi4.driver.driver_cbs_helper.scf_xtpl_helgaker_2

.. autofunction:: psi4.driver.driver_cbs.scf_xtpl_karton_2
.. autofunction:: psi4.driver.driver_cbs_helper.scf_xtpl_truhlar_2

.. autofunction:: psi4.driver.driver_cbs.scf_xtpl_helgaker_3
.. autofunction:: psi4.driver.driver_cbs_helper.scf_xtpl_karton_2

.. autofunction:: psi4.driver.driver_cbs.corl_xtpl_helgaker_2
.. autofunction:: psi4.driver.driver_cbs_helper.scf_xtpl_helgaker_3

.. autofunction:: psi4.driver.driver_cbs_helper.corl_xtpl_helgaker_2

.. autofunction:: psi4.driver.driver_cbs._get_default_xtpl

Additional extrapolation schemes are easy to define by the
user. Follow models in :src:`psi4/driver/driver_cbs_helper.py`
and :srcsample:`pywrap-cbs1` and use the
:py:func:`psi4.driver.driver_cbs_helper.register_xtpl_function` to make
user-defined functions known to |PSIfour|.

.. autofunction:: psi4.driver.driver_cbs_helper.register_xtpl_function


Aliases
^^^^^^^

When a particular composite method or its functional form is going to be
reused often, it is convenient to define an alias to it. A convenient
place for such Python code to reside is in :source:`psi4/driver/aliases.py`
(source location) or ``psi4/lib/psi4/driver/aliases.py`` (installed
location). No recompilation is necessary after defining an alias. Some
existing examples are below.
Some existing examples are below.

.. autofunction:: psi4.driver.aliases.sherrill_gold_standard

.. autofunction:: psi4.driver.aliases.allen_focal_point

Additional composite aliases are easy to define by the
user. Follow models in :src:`psi4/driver/aliases.py`
and :srcsample:`cbs-xtpl-nbody` and use the
:py:func:`psi4.driver.driver_cbs_helper.register_composite_function`
to make user-defined functions known to |PSIfour|.

.. autofunction:: psi4.driver.driver_cbs_helper.register_composite_function


8 changes: 8 additions & 0 deletions doc/sphinxman/source/glossary_psivariables.rst
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,14 @@ PSI Variables by Alpha

Value 1 (0) when the Brueckner orbitals have (have not) converged.

.. psivar:: CBS NUMBER
NBODY NUMBER
FINDIF NUMBER

Number of tasks [] the named procedure performs. These are immediate
tasks, so if procedures are nested, the total number of tasks is
the product.

.. psivar:: CBS TOTAL ENERGY
CBS CORRELATION ENERGY
CBS REFERENCE ENERGY
Expand Down
7 changes: 4 additions & 3 deletions doc/sphinxman/source/psithoninput.rst
Original file line number Diff line number Diff line change
Expand Up @@ -481,16 +481,17 @@ do the extrapolation). For example,::

# all equivalent

cbs('mp2', corl_basis='cc-pv[dt]z', corl_scheme=corl_xtpl_helgaker_2)
energy('mp2', corl_basis='cc-pv[dt]z', corl_scheme=corl_xtpl_helgaker_2)

energy('mp2/cc-pv[dt]z')

will compute a 2-point Helgaker extrapolation of the correlation energy
using the cc-pVDZ and cc-pVTZ basis sets (with method MP2) and add this
extrapolated correlation energy to the Hartree--Fock energy in the
largest basis (cc-pVTZ). :py:func:`~psi4.cbs` can
either be called directly, as in the first example, or the convenience
syntax of the equivalent second example can be used.
be configured behind-the-scenes with explicit arguments, as in the
first example, or the convenience syntax of the equivalent second
example can be used.

Another very useful and powerful feature of |PSIfour| is the ability
to compute results on entire databases of molecules at a time,
Expand Down
2 changes: 1 addition & 1 deletion psi4/driver/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,5 +64,5 @@
from psi4.driver.driver import *

# Single functions
from psi4.driver.driver_cbs import cbs
from psi4.driver.driver_cbs import cbs # remove in v1.8 when UpgradeHelper expires
from psi4.driver.p4util.python_helpers import set_options, set_module_options, pcm_helper, basis_helper
113 changes: 61 additions & 52 deletions psi4/driver/aliases.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import re
import warnings

import psi4
from psi4.driver import driver_cbs


Expand Down Expand Up @@ -102,21 +103,25 @@ def sherrill_gold_standard(func, label, **kwargs):
>>> optimize('sherrill_gold_standard', corl_basis='cc-pV[DT]Z', delta_basis='3-21g')
"""
kwargs['scf_basis'] = kwargs.get('scf_basis', 'aug-cc-pVQZ')
kwargs['scf_scheme'] = kwargs.get('scf_scheme', driver_cbs.xtpl_highest_1)

kwargs['corl_wfn'] = kwargs.get('corl_wfn', 'mp2')
kwargs['corl_basis'] = kwargs.get('corl_basis', 'aug-cc-pV[TQ]Z')
kwargs['corl_scheme'] = kwargs.get('corl_scheme', driver_cbs.corl_xtpl_helgaker_2)

kwargs['delta_wfn'] = kwargs.get('delta_wfn', 'ccsd(t)')
kwargs['delta_wfn_lesser'] = kwargs.get('delta_wfn_lesser', 'mp2')
kwargs['delta_basis'] = kwargs.get('delta_basis', 'aug-cc-pVTZ')
kwargs['delta_scheme'] = kwargs.get('delta_scheme', driver_cbs.xtpl_highest_1)

if label == 'custom_function':
label = 'Sherrill Group Gold Standard'
return driver_cbs.cbs(func, label, **kwargs)
scf = {
'wfn': 'hf',
'basis': kwargs.pop('scf_basis', 'aug-cc-pVQZ'),
'scheme': kwargs.pop('scf_scheme', 'xtpl_highest_1')
}
corl = {
'wfn': kwargs.pop('corl_wfn', 'mp2'),
'basis': kwargs.pop('corl_basis', 'aug-cc-pV[TQ]Z'),
'scheme': kwargs.pop('corl_scheme', 'corl_xtpl_helgaker_2')
}
delta = {
'wfn': kwargs.pop('delta_wfn', 'ccsd(t)'),
'wfn_lesser': kwargs.pop('delta_wfn_lesser', 'mp2'),
'basis': kwargs.pop('delta_basis', 'aug-cc-pVTZ'),
'scheme': kwargs.pop('delta_scheme', 'xtpl_highest_1')
}

kwargs["cbs_metadata"] = [scf, corl, delta]
return driver_cbs.cbs(func, "", **kwargs)


def allen_focal_point(func, label, **kwargs):
Expand All @@ -134,45 +139,49 @@ def allen_focal_point(func, label, **kwargs):
>>> # [1] single-point energy by this composite method
>>> energy('allen_focal_point')
>>> # [2] finite-difference geometry optimization embarrasingly parallel
>>> optimize('allen_focal_point', mode='sow')
>>> # [2] single-point energy reducing the Hartree-Fock basis sets size
>>> energy('allen_focal_point', scf_basis='cc-pV[TQ5]Z')
"""

# SCF
kwargs['scf_basis'] = kwargs.get('scf_basis', 'cc-pV[Q56]Z')
kwargs['scf_scheme'] = kwargs.get('scf_scheme', driver_cbs.scf_xtpl_helgaker_3)

# delta MP2 - SCF
kwargs['corl_wfn'] = kwargs.get('corl_wfn', 'mp2')
kwargs['corl_basis'] = kwargs.get('corl_basis', 'cc-pV[56]Z')
kwargs['corl_scheme'] = kwargs.get('corl_scheme', driver_cbs.corl_xtpl_helgaker_2)

# delta CCSD - MP2
kwargs['delta_wfn'] = kwargs.get('delta_wfn', 'mrccsd')
kwargs['delta_wfn_lesser'] = kwargs.get('delta_wfn_lesser', 'mp2')
kwargs['delta_basis'] = kwargs.get('delta_basis', 'cc-pV[56]Z')
kwargs['delta_scheme'] = kwargs.get('delta_scheme', driver_cbs.corl_xtpl_helgaker_2)

# delta CCSD(T) - CCSD
kwargs['delta2_wfn'] = kwargs.get('delta2_wfn', 'mrccsd(t)')
kwargs['delta2_wfn_lesser'] = kwargs.get('delta2_wfn_lesser', 'mrccsd')
kwargs['delta2_basis'] = kwargs.get('delta2_basis', 'cc-pV[56]Z')
kwargs['delta2_scheme'] = kwargs.get('delta2_scheme', driver_cbs.corl_xtpl_helgaker_2)

# delta CCSDT - CCSD(T)
kwargs['delta3_wfn'] = kwargs.get('delta3_wfn', 'mrccsdt')
kwargs['delta3_wfn_lesser'] = kwargs.get('delta3_wfn_lesser', 'mrccsd(t)')
kwargs['delta3_basis'] = kwargs.get('delta3_basis', 'cc-pVTZ')
kwargs['delta3_scheme'] = kwargs.get('delta3_scheme', driver_cbs.xtpl_highest_1)

# delta CCSDT(Q) - CCSDT
kwargs['delta4_wfn'] = kwargs.get('delta4_wfn', 'mrccsdt(q)')
kwargs['delta4_wfn_lesser'] = kwargs.get('delta4_wfn_lesser', 'mrccsdt')
kwargs['delta4_basis'] = kwargs.get('delta4_basis', 'cc-pVDZ')
kwargs['delta4_scheme'] = kwargs.get('delta4_scheme', driver_cbs.xtpl_highest_1)

if label == 'custom_function':
label = 'Allen Focal Point'
if not psi4.addons("mrcc"):
raise ImportError("Install MRCC (executable 'dmrcc') to use the allen_focal_point function.")

scf = { # HF
'wfn': 'hf',
'basis': kwargs.pop('scf_basis', 'cc-pV[Q56]Z'),
'scheme': kwargs.pop('scf_scheme', 'scf_xtpl_helgaker_3'),
}
corl = { # MP2 - HF
'wfn': kwargs.pop('corl_wfn', 'mp2'),
'basis': kwargs.pop('corl_basis', 'cc-pV[56]Z'),
'scheme': kwargs.pop('corl_scheme', 'corl_xtpl_helgaker_2'),
}
delta = { # CCSD - MP2
'wfn': kwargs.pop('delta_wfn', 'mrccsd'),
'wfn_lesser': kwargs.pop('delta_wfn_lesser', 'mp2'),
'basis': kwargs.pop('delta_basis', 'cc-pV[56]Z'),
'scheme': kwargs.pop('delta_scheme', 'corl_xtpl_helgaker_2'),
}
delta2 = { # CCSD(T) - CCSD
'wfn': kwargs.pop('delta2_wfn', 'mrccsd(t)'),
'wfn_lesser': kwargs.pop('delta2_wfn_lesser', 'mrccsd'),
'basis': kwargs.pop('delta2_basis', 'cc-pV[56]Z'),
'scheme': kwargs.pop('delta2_scheme', 'corl_xtpl_helgaker_2'),
}
delta3 = { # CCSDT - CCSD(T)
'wfn': kwargs.pop('delta3_wfn', 'mrccsdt'),
'wfn_lesser': kwargs.pop('delta3_wfn_lesser', 'mrccsd(t)'),
'basis': kwargs.pop('delta3_basis', 'cc-pVTZ'),
'scheme': kwargs.pop('delta3_scheme', 'xtpl_highest_1'),
}
delta4 = { # CCSDT(Q) - CCSDT
'wfn': kwargs.pop('delta4_wfn', 'mrccsdt(q)'),
'wfn_lesser': kwargs.pop('delta4_wfn_lesser', 'mrccsdt'),
'basis': kwargs.pop('delta4_basis', 'cc-pVDZ'),
'scheme': kwargs.pop('delta4_scheme', 'xtpl_highest_1'),
}

kwargs["cbs_metadata"] = [scf, corl, delta, delta2, delta3, delta4]
return driver_cbs.cbs(func, label, **kwargs)

6 changes: 5 additions & 1 deletion psi4/driver/driver.py
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,7 @@ def energy(name, **kwargs):
core.print_out("\nScratch directory: %s\n" % core.IOManager.shared_object().get_default_path())

# Bounce to CP if bsse kwarg
name = driver_util.upgrade_interventions(name)
if kwargs.get('bsse_type', None) is not None:
return driver_nbody.nbody_gufunc(energy, name, ptype='energy', **kwargs)

Expand Down Expand Up @@ -653,6 +654,7 @@ def gradient(name, **kwargs):
core.print_out("\nScratch directory: %s\n" % core.IOManager.shared_object().get_default_path())

# Figure out what kind of gradient this is
name = driver_util.upgrade_interventions(name)
if hasattr(name, '__call__'):
if name.__name__ in ['cbs', 'complete_basis_set']:
gradient_type = 'cbs_wrapper'
Expand Down Expand Up @@ -908,7 +910,7 @@ def properties(*args, **kwargs):
kwargs['molecule'] = molecule

# Allow specification of methods to arbitrary order
lowername = args[0].lower()
lowername = driver_util.upgrade_interventions(args[0])
lowername, level = driver_util.parse_arbitrary_order(lowername)
if level:
kwargs['level'] = level
Expand Down Expand Up @@ -1293,6 +1295,7 @@ def optimize(name, **kwargs):
elif engine != 'optking':
raise ValidationError(f"Optimizer {engine} is not supported.")

name = driver_util.upgrade_interventions(name)
if hasattr(name, '__call__'):
lowername = name
custom_gradient = True
Expand Down Expand Up @@ -1500,6 +1503,7 @@ def hessian(name, **kwargs):
kwargs = p4util.kwargs_lower(kwargs)

# Figure out what kind of gradient this is
name = driver_util.upgrade_interventions(name)
if hasattr(name, '__call__'):
if name.__name__ in ['cbs', 'complete_basis_set']:
gradient_type = 'cbs_wrapper'
Expand Down
Loading

0 comments on commit 8a91285

Please sign in to comment.