#
# @BEGIN LICENSE
#
# Psi4: an open-source quantum chemistry software package
#
# Copyright (c) 2007-2016 The Psi4 Developers.
#
# The copyrights for code used from other parties are included in
# the corresponding files.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
# @END LICENSE
#
"""Module with functions that encode the sequence of PSI module
calls for each of the *name* values of the energy(), optimize(),
response(), and frequency() function. *name* can be assumed lowercase by here.
"""
from __future__ import print_function
from __future__ import absolute_import
import shutil
import os
import subprocess
import re
# Relative hack for now
import sys, inspect
path_dir = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"../")))
sys.path.append(path_dir)
import p4util
from p4util.exceptions import *
from molutil import *
from .functional import *
from .roa import *
from . import proc_util
# never import driver, wrappers, or aliases into this file
# ATTN NEW ADDITIONS!
# consult http://psicode.org/psi4manual/master/proc_py.html
[docs]def select_mp2(name, **kwargs):
"""Function selecting the algorithm for a MP2 energy call
and directing to specified or best-performance default modules.
"""
reference = psi4.get_option('SCF', 'REFERENCE')
mtd_type = psi4.get_global_option('MP2_TYPE')
module = psi4.get_global_option('QC_MODULE')
# Considering only [df]occ/dfmp2/detci/fnocc
# MP2_TYPE exists largely for py-side reasoning, so must manage it
# here rather than passing to c-side unprepared for validation
func = None
if reference == 'RHF':
if mtd_type == 'CONV':
if module == 'DETCI':
func = run_detci
elif module == 'FNOCC':
func = run_fnocc
elif module in ['', 'OCC']:
func = run_occ
elif mtd_type == 'DF':
if module == 'OCC':
func = run_dfocc
elif module in ['', 'DFMP2']:
func = run_dfmp2
elif mtd_type == 'CD':
if module in ['', 'OCC']:
func = run_dfocc
elif reference == 'UHF':
if mtd_type == 'CONV':
if module in ['', 'OCC']:
func = run_occ
elif mtd_type == 'DF':
if module == 'OCC':
func = run_dfocc
elif module in ['', 'DFMP2']:
func = run_dfmp2
elif mtd_type == 'CD':
if module in ['', 'OCC']:
func = run_dfocc
elif reference == 'ROHF':
if mtd_type == 'CONV':
if module == 'DETCI':
func = run_detci
elif module in ['', 'OCC']:
func = run_occ
elif mtd_type == 'DF':
if module == 'OCC':
func = run_dfocc
elif module in ['', 'DFMP2']:
func = run_dfmp2
elif mtd_type == 'CD':
if module in ['', 'OCC']:
func = run_dfocc
elif reference in ['RKS', 'UKS']:
if mtd_type == 'DF':
if module in ['', 'DFMP2']:
func = run_dfmp2
if func is None:
raise ManagedMethodError(['select_mp2', name, 'MP2_TYPE', mtd_type, reference, module])
if kwargs.pop('probe', False):
return
else:
return func(name, **kwargs)
[docs]def select_mp2_gradient(name, **kwargs):
"""Function selecting the algorithm for a MP2 gradient call
and directing to specified or best-performance default modules.
"""
reference = psi4.get_option('SCF', 'REFERENCE')
mtd_type = psi4.get_global_option('MP2_TYPE')
module = psi4.get_global_option('QC_MODULE')
# Considering only [df]occ/dfmp2
func = None
if reference == 'RHF':
if mtd_type == 'CONV':
if module in ['', 'OCC']:
func = run_occ_gradient
elif mtd_type == 'DF':
if module == 'OCC':
func = run_dfocc_gradient
elif module in ['', 'DFMP2']:
func = run_dfmp2_gradient
elif reference == 'UHF':
if mtd_type == 'CONV':
if module in ['', 'OCC']:
func = run_occ_gradient
elif mtd_type == 'DF':
if module in ['', 'OCC']:
func = run_dfocc_gradient
if func is None:
raise ManagedMethodError(['select_mp2_gradient', name, 'MP2_TYPE', mtd_type, reference, module])
if kwargs.pop('probe', False):
return
else:
return func(name, **kwargs)
[docs]def select_mp2_property(name, **kwargs):
"""Function selecting the algorithm for a MP2 property call
and directing to specified or best-performance default modules.
"""
reference = psi4.get_option('SCF', 'REFERENCE')
mtd_type = psi4.get_global_option('MP2_TYPE')
module = psi4.get_global_option('QC_MODULE')
# Considering only dfmp2 for now
func = None
if reference == 'RHF':
if mtd_type == 'DF':
#if module == 'OCC':
# func = run_dfocc_property
if module in ['', 'DFMP2']:
func = run_dfmp2_property
#elif reference == 'UHF':
# if mtd_type == 'DF':
# if module in ['', 'OCC']:
# func = run_dfocc_property
if func is None:
raise ManagedMethodError(['select_mp2_property', name, 'MP2_TYPE', mtd_type, reference, module])
if kwargs.pop('probe', False):
return
else:
return func(name, **kwargs)
[docs]def select_omp2(name, **kwargs):
"""Function selecting the algorithm for an OMP2 energy call
and directing to specified or best-performance default modules.
"""
reference = psi4.get_option('SCF', 'REFERENCE')
mtd_type = psi4.get_global_option('MP2_TYPE')
module = psi4.get_global_option('QC_MODULE')
# Considering only [df]occ
func = None
if reference in ['RHF', 'UHF', 'ROHF', 'RKS', 'UKS']:
if mtd_type == 'CONV':
if module in ['', 'OCC']:
func = run_occ
elif mtd_type == 'DF':
if module in ['', 'OCC']:
func = run_dfocc
elif mtd_type == 'CD':
if module in ['', 'OCC']:
func = run_dfocc
if func is None:
raise ManagedMethodError(['select_omp2', name, 'MP2_TYPE', mtd_type, reference, module])
if kwargs.pop('probe', False):
return
else:
return func(name, **kwargs)
[docs]def select_omp2_gradient(name, **kwargs):
"""Function selecting the algorithm for an OMP2 gradient call
and directing to specified or best-performance default modules.
"""
reference = psi4.get_option('SCF', 'REFERENCE')
mtd_type = psi4.get_global_option('MP2_TYPE')
module = psi4.get_global_option('QC_MODULE')
# Considering only [df]occ
func = None
if reference in ['RHF', 'UHF', 'ROHF', 'RKS', 'UKS']:
if mtd_type == 'CONV':
if module in ['', 'OCC']:
func = run_occ_gradient
elif mtd_type == 'DF':
if module in ['', 'OCC']:
func = run_dfocc_gradient
if func is None:
raise ManagedMethodError(['select_omp2_gradient', name, 'MP2_TYPE', mtd_type, reference, module])
if kwargs.pop('probe', False):
return
else:
return func(name, **kwargs)
[docs]def select_omp2_property(name, **kwargs):
"""Function selecting the algorithm for an OMP2 property call
and directing to specified or best-performance default modules.
"""
reference = psi4.get_option('SCF', 'REFERENCE')
mtd_type = psi4.get_global_option('MP2_TYPE')
module = psi4.get_global_option('QC_MODULE')
# Considering only [df]occ
func = None
if reference in ['RHF', 'UHF', 'ROHF', 'RKS', 'UKS']:
if mtd_type == 'DF':
if module in ['', 'OCC']:
func = run_dfocc_property
if func is None:
raise ManagedMethodError(['select_omp2_property', name, 'MP2_TYPE', mtd_type, reference, module])
if kwargs.pop('probe', False):
return
else:
return func(name, **kwargs)
[docs]def select_mp3(name, **kwargs):
"""Function selecting the algorithm for a MP3 energy call
and directing to specified or best-performance default modules.
"""
reference = psi4.get_option('SCF', 'REFERENCE')
mtd_type = psi4.get_global_option('MP_TYPE')
module = psi4.get_global_option('QC_MODULE')
# Considering only [df]occ/fnocc/detci
func = None
if reference == 'RHF':
if mtd_type == 'CONV':
if module == 'DETCI':
func = run_detci
elif module == 'FNOCC':
func = run_fnocc
elif module in ['', 'OCC']:
func = run_occ
elif mtd_type == 'DF':
if module in ['', 'OCC']:
func = run_dfocc
elif mtd_type == 'CD':
if module in ['', 'OCC']:
func = run_dfocc
elif reference == 'UHF':
if mtd_type == 'CONV':
if module in ['', 'OCC']:
func = run_occ
elif mtd_type == 'DF':
if module in ['', 'OCC']:
func = run_dfocc
elif mtd_type == 'CD':
if module in ['', 'OCC']:
func = run_dfocc
elif reference == 'ROHF':
if mtd_type == 'CONV':
if module == 'DETCI': # no default for this case
func = run_detci
elif module in ['']:
psi4.print_out("""\nThis method is available inefficiently as a """
"""byproduct of a CISD computation.\n Add "set """
"""qc_module detci" to input to access this route.\n""")
if func is None:
raise ManagedMethodError(['select_mp3', name, 'MP_TYPE', mtd_type, reference, module])
if kwargs.pop('probe', False):
return
else:
return func(name, **kwargs)
[docs]def select_mp3_gradient(name, **kwargs):
"""Function selecting the algorithm for a MP3 gradient call
and directing to specified or best-performance default modules.
"""
reference = psi4.get_option('SCF', 'REFERENCE')
mtd_type = psi4.get_global_option('MP_TYPE')
module = psi4.get_global_option('QC_MODULE')
# Considering only [df]occ
func = None
if reference == 'RHF':
if mtd_type == 'CONV':
if module in ['', 'OCC']:
func = run_occ_gradient
elif mtd_type == 'DF':
if module in ['', 'OCC']:
func = run_dfocc_gradient
elif reference == 'UHF':
if mtd_type == 'CONV':
if module in ['', 'OCC']:
func = run_occ_gradient
elif mtd_type == 'DF':
if module in ['', 'OCC']:
func = run_dfocc_gradient
if func is None:
raise ManagedMethodError(['select_mp3_gradient', name, 'MP_TYPE', mtd_type, reference, module])
if kwargs.pop('probe', False):
return
else:
return func(name, **kwargs)
[docs]def select_omp3(name, **kwargs):
"""Function selecting the algorithm for an OMP3 energy call
and directing to specified or best-performance default modules.
"""
reference = psi4.get_option('SCF', 'REFERENCE')
mtd_type = psi4.get_global_option('MP_TYPE')
module = psi4.get_global_option('QC_MODULE')
# Considering only [df]occ
func = None
if reference in ['RHF', 'UHF', 'ROHF', 'RKS', 'UKS']:
if mtd_type == 'CONV':
if module in ['', 'OCC']:
func = run_occ
elif mtd_type == 'DF':
if module in ['', 'OCC']:
func = run_dfocc
elif mtd_type == 'CD':
if module in ['', 'OCC']:
func = run_dfocc
if func is None:
raise ManagedMethodError(['select_omp3', name, 'MP_TYPE', mtd_type, reference, module])
if kwargs.pop('probe', False):
return
else:
return func(name, **kwargs)
[docs]def select_omp3_gradient(name, **kwargs):
"""Function selecting the algorithm for an OMP3 gradient call
and directing to specified or best-performance default modules.
"""
reference = psi4.get_option('SCF', 'REFERENCE')
mtd_type = psi4.get_global_option('MP_TYPE')
module = psi4.get_global_option('QC_MODULE')
# Considering only [df]occ
func = None
if reference in ['RHF', 'UHF', 'ROHF', 'RKS', 'UKS']:
if mtd_type == 'CONV':
if module in ['', 'OCC']:
func = run_occ_gradient
elif mtd_type == 'DF':
if module in ['', 'OCC']:
func = run_dfocc_gradient
if func is None:
raise ManagedMethodError(['select_omp3_gradient', name, 'MP_TYPE', mtd_type, reference, module])
if kwargs.pop('probe', False):
return
else:
return func(name, **kwargs)
[docs]def select_mp2p5(name, **kwargs):
"""Function selecting the algorithm for a MP2.5 energy call
and directing to specified or best-performance default modules.
"""
reference = psi4.get_option('SCF', 'REFERENCE')
mtd_type = psi4.get_global_option('MP_TYPE')
module = psi4.get_global_option('QC_MODULE')
# Considering only [df]occ
func = None
if reference in ['RHF', 'UHF']:
if mtd_type == 'CONV':
if module in ['', 'OCC']:
func = run_occ
elif mtd_type == 'DF':
if module in ['', 'OCC']:
func = run_dfocc
elif mtd_type == 'CD':
if module in ['', 'OCC']:
func = run_dfocc
if func is None:
raise ManagedMethodError(['select_mp2p5', name, 'MP_TYPE', mtd_type, reference, module])
if kwargs.pop('probe', False):
return
else:
return func(name, **kwargs)
[docs]def select_mp2p5_gradient(name, **kwargs):
"""Function selecting the algorithm for a MP2.5 gradient call
and directing to specified or best-performance default modules.
"""
reference = psi4.get_option('SCF', 'REFERENCE')
mtd_type = psi4.get_global_option('MP_TYPE')
module = psi4.get_global_option('QC_MODULE')
# Considering only [df]occ
func = None
if reference in ['RHF', 'UHF']:
if mtd_type == 'CONV':
if module in ['', 'OCC']:
func = run_occ_gradient
elif mtd_type == 'DF':
if module in ['', 'OCC']:
func = run_dfocc_gradient
if func is None:
raise ManagedMethodError(['select_mp2p5_gradient', name, 'MP_TYPE', mtd_type, reference, module])
if kwargs.pop('probe', False):
return
else:
return func(name, **kwargs)
[docs]def select_omp2p5(name, **kwargs):
"""Function selecting the algorithm for an OMP2.5 energy call
and directing to specified or best-performance default modules.
"""
reference = psi4.get_option('SCF', 'REFERENCE')
mtd_type = psi4.get_global_option('MP_TYPE')
module = psi4.get_global_option('QC_MODULE')
# Considering only [df]occ
func = None
if reference in ['RHF', 'UHF', 'ROHF', 'RKS', 'UKS']:
if mtd_type == 'CONV':
if module in ['', 'OCC']:
func = run_occ
elif mtd_type == 'DF':
if module in ['', 'OCC']:
func = run_dfocc
elif mtd_type == 'CD':
if module in ['', 'OCC']:
func = run_dfocc
if func is None:
raise ManagedMethodError(['select_omp2p5', name, 'MP_TYPE', mtd_type, reference, module])
if kwargs.pop('probe', False):
return
else:
return func(name, **kwargs)
[docs]def select_omp2p5_gradient(name, **kwargs):
"""Function selecting the algorithm for an OMP2.5 gradient call
and directing to specified or best-performance default modules.
"""
reference = psi4.get_option('SCF', 'REFERENCE')
mtd_type = psi4.get_global_option('MP_TYPE')
module = psi4.get_global_option('QC_MODULE')
# Considering only [df]occ
func = None
if reference in ['RHF', 'UHF', 'ROHF', 'RKS', 'UKS']:
if mtd_type == 'CONV':
if module in ['', 'OCC']:
func = run_occ_gradient
elif mtd_type == 'DF':
if module in ['', 'OCC']:
func = run_dfocc_gradient
if func is None:
raise ManagedMethodError(['select_omp2p5_gradient', name, 'MP_TYPE', mtd_type, reference, module])
if kwargs.pop('probe', False):
return
else:
return func(name, **kwargs)
[docs]def select_lccd(name, **kwargs):
"""Function selecting the algorithm for a LCCD energy call
and directing to specified or best-performance default modules.
"""
reference = psi4.get_option('SCF', 'REFERENCE')
mtd_type = psi4.get_global_option('CC_TYPE')
module = psi4.get_global_option('QC_MODULE')
# Considering only [df]occ/fnocc
func = None
if reference == 'RHF':
if mtd_type == 'CONV':
if module == 'OCC':
func = run_occ
elif module in ['', 'FNOCC']:
func = run_cepa
elif mtd_type == 'DF':
if module in ['', 'OCC']:
func = run_dfocc
elif mtd_type == 'CD':
if module in ['', 'OCC']:
func = run_dfocc
elif reference == 'UHF':
if mtd_type == 'CONV':
if module in ['', 'OCC']:
func = run_occ
elif mtd_type == 'DF':
if module in ['', 'OCC']:
func = run_dfocc
elif mtd_type == 'CD':
if module in ['', 'OCC']:
func = run_dfocc
if func is None:
raise ManagedMethodError(['select_lccd', name, 'CC_TYPE', mtd_type, reference, module])
if kwargs.pop('probe', False):
return
else:
return func(name, **kwargs)
[docs]def select_lccd_gradient(name, **kwargs):
"""Function selecting the algorithm for a LCCD gradient call
and directing to specified or best-performance default modules.
"""
reference = psi4.get_option('SCF', 'REFERENCE')
mtd_type = psi4.get_global_option('CC_TYPE')
module = psi4.get_global_option('QC_MODULE')
# Considering only [df]occ
func = None
if reference in ['RHF', 'UHF']:
if mtd_type == 'CONV':
if module in ['', 'OCC']:
func = run_occ_gradient
elif mtd_type == 'DF':
if module in ['', 'OCC']:
func = run_dfocc_gradient
if func is None:
raise ManagedMethodError(['select_lccd_gradient', name, 'CC_TYPE', mtd_type, reference, module])
if kwargs.pop('probe', False):
return
else:
return func(name, **kwargs)
[docs]def select_olccd(name, **kwargs):
"""Function selecting the algorithm for an OLCCD energy call
and directing to specified or best-performance default modules.
"""
reference = psi4.get_option('SCF', 'REFERENCE')
mtd_type = psi4.get_global_option('CC_TYPE')
module = psi4.get_global_option('QC_MODULE')
# Considering only [df]occ
func = None
if reference in ['RHF', 'UHF', 'ROHF', 'RKS', 'UKS']:
if mtd_type == 'CONV':
if module in ['', 'OCC']:
func = run_occ
elif mtd_type == 'DF':
if module in ['', 'OCC']:
func = run_dfocc
elif mtd_type == 'CD':
if module in ['', 'OCC']:
func = run_dfocc
if func is None:
raise ManagedMethodError(['select_olccd', name, 'CC_TYPE', mtd_type, reference, module])
if kwargs.pop('probe', False):
return
else:
return func(name, **kwargs)
[docs]def select_olccd_gradient(name, **kwargs):
"""Function selecting the algorithm for an OLCCD gradient call
and directing to specified or best-performance default modules.
"""
reference = psi4.get_option('SCF', 'REFERENCE')
mtd_type = psi4.get_global_option('CC_TYPE')
module = psi4.get_global_option('QC_MODULE')
# Considering only [df]occ
func = None
if reference in ['RHF', 'UHF', 'ROHF', 'RKS', 'UKS']:
if mtd_type == 'CONV':
if module in ['', 'OCC']:
func = run_occ_gradient
elif mtd_type == 'DF':
if module in ['', 'OCC']:
func = run_dfocc_gradient
if func is None:
raise ManagedMethodError(['select_olccd_gradient', name, 'CC_TYPE', mtd_type, reference, module])
if kwargs.pop('probe', False):
return
else:
return func(name, **kwargs)
[docs]def select_fnoccsd(name, **kwargs):
"""Function selecting the algorithm for a FNO-CCSD energy call
and directing to specified or best-performance default modules.
"""
reference = psi4.get_option('SCF', 'REFERENCE')
mtd_type = psi4.get_global_option('CC_TYPE')
module = psi4.get_global_option('QC_MODULE')
# Considering only fnocc
func = None
if reference == 'RHF':
if mtd_type == 'CONV':
if module in ['', 'FNOCC']:
func = run_fnocc
elif mtd_type == 'DF':
if module in ['', 'FNOCC']:
func = run_fnodfcc
elif mtd_type == 'CD':
if module in ['', 'FNOCC']:
func = run_fnodfcc
if func is None:
raise ManagedMethodError(['select_fnoccsd', name, 'CC_TYPE', mtd_type, reference, module])
if kwargs.pop('probe', False):
return
else:
return func(name, **kwargs)
[docs]def select_ccsd(name, **kwargs):
"""Function selecting the algorithm for a CCSD energy call
and directing to specified or best-performance default modules.
"""
reference = psi4.get_option('SCF', 'REFERENCE')
mtd_type = psi4.get_global_option('CC_TYPE')
module = psi4.get_global_option('QC_MODULE')
# Considering only [df]occ/ccenergy/detci/fnocc
func = None
if reference == 'RHF':
if mtd_type == 'CONV':
if module == 'DETCI':
func = run_detci
elif module == 'FNOCC':
func = run_fnocc
elif module in ['', 'CCENERGY']:
func = run_ccenergy
elif mtd_type == 'DF':
if module == 'OCC':
func = run_dfocc
elif module in ['', 'FNOCC']:
func = run_fnodfcc
elif mtd_type == 'CD':
if module == 'OCC':
func = run_dfocc
elif module in ['', 'FNOCC']:
func = run_fnodfcc
elif reference == 'UHF':
if mtd_type == 'CONV':
if module in ['', 'CCENERGY']:
func = run_ccenergy
elif reference == 'ROHF':
if mtd_type == 'CONV':
if module == 'DETCI':
func = run_detci
elif module in ['', 'CCENERGY']:
func = run_ccenergy
if func is None:
raise ManagedMethodError(['select_ccsd', name, 'CC_TYPE', mtd_type, reference, module])
if kwargs.pop('probe', False):
return
else:
return func(name, **kwargs)
[docs]def select_ccsd_gradient(name, **kwargs):
"""Function selecting the algorithm for a CCSD gradient call
and directing to specified or best-performance default modules.
"""
reference = psi4.get_option('SCF', 'REFERENCE')
mtd_type = psi4.get_global_option('CC_TYPE')
module = psi4.get_global_option('QC_MODULE')
# Considering only [df]occ/ccenergy
func = None
if reference == 'RHF':
if mtd_type == 'CONV':
if module in ['', 'CCENERGY']:
func = run_ccenergy_gradient
elif mtd_type == 'DF':
if module in ['', 'OCC']:
func = run_dfocc_gradient
elif reference == 'UHF':
if mtd_type == 'CONV':
if module in ['', 'CCENERGY']:
func = run_ccenergy_gradient
elif reference == 'ROHF':
if mtd_type == 'CONV':
if module in ['', 'CCENERGY']:
func = run_ccenergy_gradient
if func is None:
raise ManagedMethodError(['select_ccsd_gradient', name, 'CC_TYPE', mtd_type, reference, module])
if kwargs.pop('probe', False):
return
else:
return func(name, **kwargs)
[docs]def select_fnoccsd_t_(name, **kwargs):
"""Function selecting the algorithm for a FNO-CCSD(T) energy call
and directing to specified or best-performance default modules.
"""
reference = psi4.get_option('SCF', 'REFERENCE')
mtd_type = psi4.get_global_option('CC_TYPE')
module = psi4.get_global_option('QC_MODULE')
# Considering only fnocc
func = None
if reference == 'RHF':
if mtd_type == 'CONV':
if module in ['', 'FNOCC']:
func = run_fnocc
elif mtd_type == 'DF':
if module in ['', 'FNOCC']:
func = run_fnodfcc
elif mtd_type == 'CD':
if module in ['', 'FNOCC']:
func = run_fnodfcc
if func is None:
raise ManagedMethodError(['select_fnoccsd_t_', name, 'CC_TYPE', mtd_type, reference, module])
if kwargs.pop('probe', False):
return
else:
return func(name, **kwargs)
[docs]def select_ccsd_t_(name, **kwargs):
"""Function selecting the algorithm for a CCSD(T) energy call
and directing to specified or best-performance default modules.
"""
reference = psi4.get_option('SCF', 'REFERENCE')
mtd_type = psi4.get_global_option('CC_TYPE')
module = psi4.get_global_option('QC_MODULE')
# Considering only [df]occ/ccenergy/fnocc
func = None
if reference == 'RHF':
if mtd_type == 'CONV':
if module == 'FNOCC':
func = run_fnocc
elif module in ['', 'CCENERGY']:
func = run_ccenergy
elif mtd_type == 'DF':
if module == 'OCC':
func = run_dfocc
elif module in ['', 'FNOCC']:
func = run_fnodfcc
elif mtd_type == 'CD':
if module == 'OCC':
func = run_dfocc
elif module in ['', 'FNOCC']:
func = run_fnodfcc
elif reference in ['UHF', 'ROHF']:
if mtd_type == 'CONV':
if module in ['', 'CCENERGY']:
func = run_ccenergy
if func is None:
raise ManagedMethodError(['select_ccsd_t_', name, 'CC_TYPE', mtd_type, reference, module])
if kwargs.pop('probe', False):
return
else:
return func(name, **kwargs)
[docs]def select_ccsd_t__gradient(name, **kwargs):
"""Function selecting the algorithm for a CCSD(T) gradient call
and directing to specified or best-performance default modules.
"""
reference = psi4.get_option('SCF', 'REFERENCE')
mtd_type = psi4.get_global_option('CC_TYPE')
module = psi4.get_global_option('QC_MODULE')
# Considering only ccenergy
func = None
if reference == 'UHF':
if mtd_type == 'CONV':
if module in ['', 'CCENERGY']:
func = run_ccenergy_gradient
if func is None:
raise ManagedMethodError(['select_ccsd_t__gradient', name, 'CC_TYPE', mtd_type, reference, module])
if kwargs.pop('probe', False):
return
else:
return func(name, **kwargs)
[docs]def select_ccsd_at_(name, **kwargs):
"""Function selecting the algorithm for a CCSD(AT) energy call
and directing to specified or best-performance default modules.
"""
reference = psi4.get_option('SCF', 'REFERENCE')
mtd_type = psi4.get_global_option('CC_TYPE')
module = psi4.get_global_option('QC_MODULE')
# Considering only [df]occ/ccenergy
func = None
if reference == 'RHF':
if mtd_type == 'CONV':
if module in ['', 'CCENERGY']:
func = run_ccenergy
elif mtd_type == 'DF':
if module in ['', 'OCC']:
func = run_dfocc
elif mtd_type == 'CD':
if module in ['', 'OCC']:
func = run_dfocc
if func is None:
raise ManagedMethodError(['select_ccsd_at_', name, 'CC_TYPE', mtd_type, reference, module])
if kwargs.pop('probe', False):
return
else:
return func(name, **kwargs)
[docs]def select_cisd(name, **kwargs):
"""Function selecting the algorithm for a CISD energy call
and directing to specified or best-performance default modules.
"""
reference = psi4.get_option('SCF', 'REFERENCE')
mtd_type = psi4.get_global_option('CI_TYPE')
module = psi4.get_global_option('QC_MODULE')
# Considering only detci/fnocc
func = None
if reference == 'RHF':
if mtd_type == 'CONV':
if module == 'DETCI':
func = run_detci
elif module in ['', 'FNOCC']:
func = run_cepa
elif reference == 'ROHF':
if mtd_type == 'CONV':
if module in ['', 'DETCI']:
func = run_detci
if func is None:
raise ManagedMethodError(['select_cisd', name, 'CI_TYPE', mtd_type, reference, module])
if kwargs.pop('probe', False):
return
else:
return func(name, **kwargs)
[docs]def select_mp4(name, **kwargs):
"""Function selecting the algorithm for a MP4 energy call
and directing to specified or best-performance default modules.
"""
reference = psi4.get_option('SCF', 'REFERENCE')
mtd_type = psi4.get_global_option('MP_TYPE')
module = psi4.get_global_option('QC_MODULE')
# Considering only detci/fnocc
func = None
if reference == 'RHF':
if mtd_type == 'CONV':
if module == 'DETCI':
func = run_detci
elif module in ['', 'FNOCC']:
func = run_fnocc
elif reference == 'ROHF':
if mtd_type == 'CONV':
if module == 'DETCI': # no default for this case
func = run_detci
elif module in ['']:
psi4.print_out("""\nThis method is available inefficiently as a """
"""byproduct of a CISDT computation.\n Add "set """
"""qc_module detci" to input to access this route.\n""")
if func is None:
raise ManagedMethodError(['select_mp4', name, 'MP_TYPE', mtd_type, reference, module])
if kwargs.pop('probe', False):
return
else:
return func(name, **kwargs)
[docs]def scf_helper(name, **kwargs):
"""Function serving as helper to SCF, choosing whether to cast
up or just run SCF with a standard guess. This preserves
previous SCF options set by other procedures (e.g., SAPT
output file types for SCF).
"""
optstash = p4util.OptionsState(
['PUREAM'],
['BASIS'],
['QMEFP'],
['DF_BASIS_SCF'],
['SCF', 'GUESS'],
['SCF', 'DF_INTS_IO'],
['SCF', 'SCF_TYPE'] # Hack: scope gets changed internally with the Andy trick
)
optstash2 = p4util.OptionsState(
['BASIS'],
['DF_BASIS_SCF'],
['SCF', 'SCF_TYPE'],
['SCF', 'DF_INTS_IO'])
# Grab a few kwargs
use_c1 = kwargs.get('use_c1', False)
scf_molecule = kwargs.get('molecule', psi4.get_active_molecule())
if 'ref_wfn' in kwargs:
raise ValidationError("It is not possible to pass scf_helper a reference wavefunction")
# Second-order SCF requires non-symmetric density matrix support
if psi4.get_option('SCF', 'SOSCF'):
proc_util.check_non_symmetric_jk_density("Second-order SCF")
# sort out cast_up settings. no need to stash these since only read, never reset
cast = False
if psi4.has_option_changed('SCF', 'BASIS_GUESS'):
cast = psi4.get_option('SCF', 'BASIS_GUESS')
if yes.match(str(cast)):
cast = True
elif no.match(str(cast)):
cast = False
if psi4.get_option('SCF', 'SCF_TYPE') == 'DF':
castdf = True
else:
castdf = False
if psi4.has_option_changed('SCF', 'DF_BASIS_GUESS'):
castdf = psi4.get_option('SCF', 'DF_BASIS_GUESS')
if yes.match(str(castdf)):
castdf = True
elif no.match(str(castdf)):
castdf = False
# sort out broken_symmetry settings.
if 'brokensymmetry' in kwargs:
multp = scf_molecule.multiplicity()
if multp != 1:
raise ValidationError('Broken symmetry is only for singlets.')
if psi4.get_option('SCF', 'REFERENCE') not in ['UHF', 'UKS']:
raise ValidationError("""You must specify 'set reference uhf' to use broken symmetry.""")
do_broken = True
else:
do_broken = False
precallback = None
if 'precallback' in kwargs:
precallback = kwargs.pop('precallback')
postcallback = None
if 'postcallback' in kwargs:
postcallback = kwargs.pop('postcallback')
# Hack to ensure cartesian or pure are used throughout
# Note that can't query PUREAM option directly, as it only
# reflects user changes to value, so load basis and
# read effective PUREAM setting off of it
#psi4.set_global_option('BASIS', psi4.get_global_option('BASIS'))
#psi4.set_global_option('PUREAM', psi4.MintsHelper().basisset().has_puream())
# broken set-up
if do_broken:
scf_molecule.set_multiplicity(3)
psi4.print_out('\n')
p4util.banner(' Computing high-spin triplet guess ')
psi4.print_out('\n')
# cast set-up
if (cast):
if yes.match(str(cast)):
guessbasis = '3-21G'
else:
guessbasis = cast
#if (castdf):
# if yes.match(str(castdf)):
# guessbasisdf = p4util.corresponding_jkfit(guessbasis)
# else:
# guessbasisdf = castdf
# Switch to the guess namespace
namespace = psi4.IO.get_default_namespace()
guesspace = namespace + '.guess'
if namespace == '':
guesspace = 'guess'
psi4.IO.set_default_namespace(guesspace)
# Setup initial SCF
psi4.set_global_option('BASIS', guessbasis)
if (castdf):
psi4.set_local_option('SCF', 'SCF_TYPE', 'DF')
psi4.set_local_option('SCF', 'DF_INTS_IO', 'none')
#psi4.set_global_option('DF_BASIS_SCF', guessbasisdf)
if not yes.match(str(castdf)):
psi4.set_global_option('DF_BASIS_SCF', castdf)
# Print some info about the guess
psi4.print_out('\n')
p4util.banner('Guess SCF, %s Basis' % (guessbasis))
psi4.print_out('\n')
# If we force c1 copy the active molecule
if use_c1:
scf_molecule.update_geometry()
if scf_molecule.schoenflies_symbol() != 'c1':
psi4.print_out(""" A requested method does not make use of molecular symmetry: """
"""further calculations in C1 point group.\n""")
scf_molecule = scf_molecule.clone()
scf_molecule.reset_point_group('c1')
scf_molecule.fix_orientation(True)
scf_molecule.fix_com(True)
scf_molecule.update_geometry()
# the FIRST scf call
if cast or do_broken:
# Cast or broken are special cases
new_wfn = psi4.new_wavefunction(scf_molecule, psi4.get_global_option('BASIS'))
psi4.scf(new_wfn, precallback, postcallback)
# broken clean-up
if do_broken:
scf_molecule.set_multiplicity(1)
psi4.set_local_option('SCF', 'GUESS', 'READ')
psi4.print_out('\n')
p4util.banner(' Computing broken symmetry solution from high-spin triplet guess ')
psi4.print_out('\n')
# cast clean-up
if (cast):
# Move files to proper namespace
psi4.IO.change_file_namespace(180, guesspace, namespace)
psi4.IO.set_default_namespace(namespace)
# Set to read and project, and reset bases to final ones
optstash2.restore()
psi4.set_local_option('SCF', 'GUESS', 'READ')
# Print the banner for the standard operation
psi4.print_out('\n')
p4util.banner(name.upper())
psi4.print_out('\n')
# If GUESS is auto guess what it should be
elif psi4.get_option('SCF', 'GUESS') == "AUTO":
if (psi4.get_option('SCF', 'REFERENCE') in ['RHF', 'RKS']) and \
((scf_molecule.natom() > 1) or psi4.get_option('SCF', 'SAD_FRAC_OCC')):
psi4.set_local_option('SCF', 'GUESS', 'SAD')
elif psi4.get_option('SCF', 'REFERENCE') in ['ROHF', 'ROKS', 'UHF', 'UKS']:
psi4.set_local_option('SCF', 'GUESS', 'GWH')
else:
psi4.set_local_option('SCF', 'GUESS', 'CORE')
# EFP preparation
efp = psi4.get_active_efp()
if efp.nfragments() > 0:
psi4.set_legacy_molecule(scf_molecule)
psi4.set_global_option('QMEFP', True) # apt to go haywire if set locally to efp
psi4.efp_set_options()
efp.set_qm_atoms()
efp.print_out()
# the SECOND scf call
ref_wfn = psi4.new_wavefunction(scf_molecule, psi4.get_global_option('BASIS'))
scf_wfn = psi4.scf(ref_wfn, precallback, postcallback)
e_scf = psi4.get_variable('CURRENT ENERGY')
# We always would like to print a little dipole information
if kwargs.get('scf_do_dipole', True):
oeprop = psi4.OEProp(scf_wfn)
oeprop.set_title("SCF")
oeprop.add("DIPOLE")
oeprop.compute()
psi4.set_variable("CURRENT DIPOLE X", psi4.get_variable("SCF DIPOLE X"))
psi4.set_variable("CURRENT DIPOLE Y", psi4.get_variable("SCF DIPOLE Y"))
psi4.set_variable("CURRENT DIPOLE Z", psi4.get_variable("SCF DIPOLE Z"))
optstash.restore()
return scf_wfn
[docs]def run_dcft(name, **kwargs):
"""Function encoding sequence of PSI module calls for
a density cumulant functional theory calculation.
"""
if (psi4.get_global_option('FREEZE_CORE') == 'TRUE'):
raise ValidationError('Frozen core is not available for DCFT.')
# Bypass the scf call if a reference wavefunction is given
ref_wfn = kwargs.get('ref_wfn', None)
if ref_wfn is None:
ref_wfn = scf_helper(name, **kwargs)
# Ensure IWL files have been written
proc_util.check_iwl_file_from_scf_type(psi4.get_option('SCF', 'SCF_TYPE'), ref_wfn)
dcft_wfn = psi4.dcft(ref_wfn)
return dcft_wfn
[docs]def run_dcft_gradient(name, **kwargs):
"""Function encoding sequence of PSI module calls for
DCFT gradient calculation.
"""
optstash = p4util.OptionsState(
['GLOBALS', 'DERTYPE'])
psi4.set_global_option('DERTYPE', 'FIRST')
dcft_wfn = run_dcft(name, **kwargs)
derivobj = psi4.Deriv(dcft_wfn)
derivobj.set_tpdm_presorted(True)
grad = derivobj.compute()
dcft_wfn.set_gradient(grad)
optstash.restore()
return dcft_wfn
[docs]def run_dfocc(name, **kwargs):
"""Function encoding sequence of PSI module calls for
a density-fitted or Cholesky-decomposed
(non-)orbital-optimized MPN or CC computation.
"""
optstash = p4util.OptionsState(
['SCF', 'SCF_TYPE'],
['SCF', 'DF_INTS_IO'],
['DFOCC', 'WFN_TYPE'],
['DFOCC', 'ORB_OPT'],
['DFOCC', 'DO_SCS'],
['DFOCC', 'DO_SOS'],
['DFOCC', 'READ_SCF_3INDEX'],
['DFOCC', 'CHOLESKY'],
['DFOCC', 'CC_LAMBDA'])
def set_cholesky_from(mtd_type):
type_val = psi4.get_global_option(mtd_type)
if type_val == 'DF':
psi4.set_local_option('DFOCC', 'CHOLESKY', 'FALSE')
# Alter default algorithm
if not psi4.has_option_changed('SCF', 'SCF_TYPE'):
psi4.set_global_option('SCF_TYPE', 'DF')
psi4.print_out(""" SCF Algorithm Type (re)set to DF.\n""")
elif type_val == 'CD':
psi4.set_local_option('DFOCC', 'CHOLESKY', 'TRUE')
# Alter default algorithm
if not psi4.has_option_changed('SCF', 'SCF_TYPE'):
psi4.set_global_option('SCF_TYPE', 'CD')
psi4.print_out(""" SCF Algorithm Type (re)set to CD.\n""")
if psi4.get_option('SCF', 'SCF_TYPE') != 'CD':
psi4.set_local_option('DFOCC', 'READ_SCF_3INDEX', 'FALSE')
else:
raise ValidationError("""Invalid type '%s' for DFOCC""" % type_val)
if name in ['mp2', 'omp2']:
psi4.set_local_option('DFOCC', 'WFN_TYPE', 'DF-OMP2')
set_cholesky_from('MP2_TYPE')
elif name in ['mp2.5', 'omp2.5']:
psi4.set_local_option('DFOCC', 'WFN_TYPE', 'DF-OMP2.5')
set_cholesky_from('MP_TYPE')
elif name in ['mp3', 'omp3']:
psi4.set_local_option('DFOCC', 'WFN_TYPE', 'DF-OMP3')
set_cholesky_from('MP_TYPE')
elif name in ['lccd', 'olccd']:
psi4.set_local_option('DFOCC', 'WFN_TYPE', 'DF-OLCCD')
set_cholesky_from('CC_TYPE')
elif name == 'ccd':
psi4.set_local_option('DFOCC', 'WFN_TYPE', 'DF-CCD')
set_cholesky_from('CC_TYPE')
elif name == 'ccsd':
psi4.set_local_option('DFOCC', 'WFN_TYPE', 'DF-CCSD')
set_cholesky_from('CC_TYPE')
elif name == 'ccsd(t)':
psi4.set_local_option('DFOCC', 'WFN_TYPE', 'DF-CCSD(T)')
set_cholesky_from('CC_TYPE')
elif name == 'ccsd(at)':
psi4.set_local_option('DFOCC', 'CC_LAMBDA', 'TRUE')
psi4.set_local_option('DFOCC', 'WFN_TYPE', 'DF-CCSD(AT)')
set_cholesky_from('CC_TYPE')
elif name == 'dfocc':
pass
else:
raise ValidationError('Unidentified method %s' % (name))
# conventional vs. optimized orbitals
if name in ['mp2', 'mp2.5', 'mp3', 'lccd',
'ccd', 'ccsd', 'ccsd(t)', 'ccsd(at)']:
psi4.set_local_option('DFOCC', 'ORB_OPT', 'FALSE')
elif name in ['omp2', 'omp2.5', 'omp3', 'olccd']:
psi4.set_local_option('DFOCC', 'ORB_OPT', 'TRUE')
psi4.set_local_option('DFOCC', 'DO_SCS', 'FALSE')
psi4.set_local_option('DFOCC', 'DO_SOS', 'FALSE')
psi4.set_local_option('SCF', 'DF_INTS_IO', 'SAVE')
# Bypass the scf call if a reference wavefunction is given
ref_wfn = kwargs.get('ref_wfn', None)
if ref_wfn is None:
ref_wfn = scf_helper(name, use_c1=True, **kwargs) # C1 certified
else:
if ref_wfn.molecule().schoenflies_symbol() != 'c1':
raise ValidationError(""" DFOCC does not make use of molecular symmetry: """
"""reference wavefunction must be C1.\n""")
if psi4.get_option('SCF', 'REFERENCE') == 'ROHF':
ref_wfn.semicanonicalize()
dfocc_wfn = psi4.dfocc(ref_wfn)
optstash.restore()
return dfocc_wfn
[docs]def run_dfocc_gradient(name, **kwargs):
"""Function encoding sequence of PSI module calls for
a density-fitted (non-)orbital-optimized MPN or CC computation.
"""
optstash = p4util.OptionsState(
['SCF', 'SCF_TYPE'],
['SCF', 'DF_INTS_IO'],
['REFERENCE'],
['DFOCC', 'WFN_TYPE'],
['DFOCC', 'ORB_OPT'],
['DFOCC', 'CC_LAMBDA'],
['GLOBALS', 'DERTYPE'])
# Alter default algorithm
if not psi4.has_option_changed('SCF', 'SCF_TYPE'):
psi4.set_global_option('SCF_TYPE', 'DF')
psi4.print_out(""" SCF Algorithm Type (re)set to DF.\n""")
if psi4.get_option('SCF', 'SCF_TYPE') != 'DF':
raise ValidationError('DFOCC gradients need DF-HF reference, for now.')
if name in ['mp2', 'omp2']:
psi4.set_local_option('DFOCC', 'WFN_TYPE', 'DF-OMP2')
elif name in ['mp2.5', 'omp2.5']:
psi4.set_local_option('DFOCC', 'WFN_TYPE', 'DF-OMP2.5')
elif name in ['mp3', 'omp3']:
psi4.set_local_option('DFOCC', 'WFN_TYPE', 'DF-OMP3')
elif name in ['lccd', 'olccd']:
psi4.set_local_option('DFOCC', 'WFN_TYPE', 'DF-OLCCD')
elif name in ['ccd']:
psi4.set_local_option('DFOCC', 'WFN_TYPE', 'DF-CCD')
psi4.set_local_option('DFOCC', 'CC_LAMBDA', 'TRUE')
elif name in ['ccsd']:
psi4.set_local_option('DFOCC', 'WFN_TYPE', 'DF-CCSD')
psi4.set_local_option('DFOCC', 'CC_LAMBDA', 'TRUE')
else:
raise ValidationError('Unidentified method %s' % (name))
if name in ['mp2', 'mp2.5', 'mp3', 'lccd', 'ccd', 'ccsd']:
psi4.set_local_option('DFOCC', 'ORB_OPT', 'FALSE')
elif name in ['omp2', 'omp2.5', 'omp3', 'olccd']:
psi4.set_local_option('DFOCC', 'ORB_OPT', 'TRUE')
psi4.set_global_option('DERTYPE', 'FIRST')
psi4.set_local_option('DFOCC', 'DO_SCS', 'FALSE')
psi4.set_local_option('DFOCC', 'DO_SOS', 'FALSE')
psi4.set_local_option('SCF', 'DF_INTS_IO', 'SAVE')
# Bypass the scf call if a reference wavefunction is given
ref_wfn = kwargs.get('ref_wfn', None)
if ref_wfn is None:
ref_wfn = scf_helper(name, use_c1=True, **kwargs) # C1 certified
else:
if ref_wfn.molecule().schoenflies_symbol() != 'c1':
raise ValidationError(""" DFOCC does not make use of molecular symmetry: """
"""reference wavefunction must be C1.\n""")
if psi4.get_option('SCF', 'REFERENCE') == 'ROHF':
ref_wfn.semicanonicalize()
dfocc_wfn = psi4.dfocc(ref_wfn)
optstash.restore()
return dfocc_wfn
[docs]def run_dfocc_property(name, **kwargs):
"""Function encoding sequence of PSI module calls for
a density-fitted (non-)orbital-optimized MPN or CC computation.
"""
optstash = p4util.OptionsState(
['SCF', 'SCF_TYPE'],
['SCF', 'DF_INTS_IO'],
['DFOCC', 'WFN_TYPE'],
['DFOCC', 'ORB_OPT'],
['DFOCC', 'OEPROP'])
if name in ['mp2', 'omp2']:
psi4.set_local_option('DFOCC', 'WFN_TYPE', 'DF-OMP2')
else:
raise ValidationError('Unidentified method ' % (name))
# Alter default algorithm
if not psi4.has_option_changed('SCF', 'SCF_TYPE'):
psi4.set_global_option('SCF_TYPE', 'DF')
psi4.print_out(""" SCF Algorithm Type (re)set to DF.\n""")
if psi4.get_option('SCF', 'SCF_TYPE') != 'DF':
raise ValidationError('DFOCC gradients need DF-HF reference, for now.')
if name in ['mp2']:
psi4.set_local_option('DFOCC', 'ORB_OPT', 'FALSE')
elif name in ['omp2']:
psi4.set_local_option('DFOCC', 'ORB_OPT', 'TRUE')
psi4.set_local_option('DFOCC', 'OEPROP', 'TRUE')
psi4.set_local_option('DFOCC', 'DO_SCS', 'FALSE')
psi4.set_local_option('DFOCC', 'DO_SOS', 'FALSE')
psi4.set_local_option('SCF', 'DF_INTS_IO', 'SAVE')
# Bypass the scf call if a reference wavefunction is given
ref_wfn = kwargs.get('ref_wfn', None)
if ref_wfn is None:
ref_wfn = scf_helper(name, use_c1=True, **kwargs) # C1 certified
else:
if ref_wfn.molecule().schoenflies_symbol() != 'c1':
raise ValidationError(""" DFOCC does not make use of molecular symmetry: """
"""reference wavefunction must be C1.\n""")
if psi4.get_option('SCF', 'REFERENCE') == 'ROHF':
ref_wfn.semicanonicalize()
dfocc_wfn = psi4.dfocc(ref_wfn)
optstash.restore()
return dfocc_wfn
[docs]def run_qchf(name, **kwargs):
"""Function encoding sequence of PSI module calls for
an density-fitted orbital-optimized MP2 computation
"""
optstash = p4util.OptionsState(
['SCF', 'DF_INTS_IO'],
['DF_BASIS_SCF'],
['DIE_IF_NOT_CONVERGED'],
['MAXITER'],
['DFOCC', 'ORB_OPT'],
['DFOCC', 'WFN_TYPE'],
['DFOCC', 'QCHF'],
['DFOCC', 'E_CONVERGENCE'])
psi4.set_local_option('DFOCC', 'ORB_OPT', 'TRUE')
psi4.set_local_option('DFOCC', 'WFN_TYPE', 'QCHF')
psi4.set_local_option('DFOCC', 'QCHF', 'TRUE')
psi4.set_local_option('DFOCC', 'E_CONVERGENCE', 8)
psi4.set_local_option('SCF', 'DF_INTS_IO', 'SAVE')
psi4.set_local_option('SCF', 'DIE_IF_NOT_CONVERGED', 'FALSE')
psi4.set_local_option('SCF', 'MAXITER', 1)
# Bypass the scf call if a reference wavefunction is given
ref_wfn = kwargs.get('ref_wfn', None)
if ref_wfn is None:
ref_wfn = scf_helper(name, use_c1=True, **kwargs) # C1 certified
else:
if ref_wfn.molecule().schoenflies_symbol() != 'c1':
raise ValidationError(""" QCHF does not make use of molecular symmetry: """
"""reference wavefunction must be C1.\n""")
if psi4.get_option('SCF', 'REFERENCE') == 'ROHF':
ref_wfn.semicanonicalize()
dfocc_wfn = psi4.dfocc(ref_wfn)
return dfocc_wfn
[docs]def run_occ(name, **kwargs):
"""Function encoding sequence of PSI module calls for
a conventional integral (O)MPN computation
"""
optstash = p4util.OptionsState(
['OCC', 'SCS_TYPE'],
['OCC', 'DO_SCS'],
['OCC', 'SOS_TYPE'],
['OCC', 'DO_SOS'],
['OCC', 'ORB_OPT'],
['OCC', 'WFN_TYPE'])
if name == 'mp2':
psi4.set_local_option('OCC', 'WFN_TYPE', 'OMP2')
psi4.set_local_option('OCC', 'ORB_OPT', 'FALSE')
psi4.set_local_option('OCC', 'DO_SCS', 'FALSE')
psi4.set_local_option('OCC', 'DO_SOS', 'FALSE')
elif name == 'omp2':
psi4.set_local_option('OCC', 'WFN_TYPE', 'OMP2')
psi4.set_local_option('OCC', 'ORB_OPT', 'TRUE')
psi4.set_local_option('OCC', 'DO_SCS', 'FALSE')
psi4.set_local_option('OCC', 'DO_SOS', 'FALSE')
elif name == 'scs-omp2':
psi4.set_local_option('OCC', 'WFN_TYPE', 'OMP2')
psi4.set_local_option('OCC', 'ORB_OPT', 'TRUE')
psi4.set_local_option('OCC', 'DO_SCS', 'TRUE')
psi4.set_local_option('OCC', 'SCS_TYPE', 'SCS')
elif name == 'scs(n)-omp2':
psi4.set_local_option('OCC', 'WFN_TYPE', 'OMP2')
psi4.set_local_option('OCC', 'ORB_OPT', 'TRUE')
psi4.set_local_option('OCC', 'DO_SCS', 'TRUE')
psi4.set_local_option('OCC', 'SCS_TYPE', 'SCSN')
elif name == 'scs-omp2-vdw':
psi4.set_local_option('OCC', 'WFN_TYPE', 'OMP2')
psi4.set_local_option('OCC', 'ORB_OPT', 'TRUE')
psi4.set_local_option('OCC', 'DO_SCS', 'TRUE')
psi4.set_local_option('OCC', 'SCS_TYPE', 'SCSVDW')
elif name == 'sos-omp2':
psi4.set_local_option('OCC', 'WFN_TYPE', 'OMP2')
psi4.set_local_option('OCC', 'ORB_OPT', 'TRUE')
psi4.set_local_option('OCC', 'DO_SOS', 'TRUE')
psi4.set_local_option('OCC', 'SOS_TYPE', 'SOS')
elif name == 'sos-pi-omp2':
psi4.set_local_option('OCC', 'WFN_TYPE', 'OMP2')
psi4.set_local_option('OCC', 'ORB_OPT', 'TRUE')
psi4.set_local_option('OCC', 'DO_SOS', 'TRUE')
psi4.set_local_option('OCC', 'SOS_TYPE', 'SOSPI')
elif name == 'mp2.5':
psi4.set_local_option('OCC', 'WFN_TYPE', 'OMP2.5')
psi4.set_local_option('OCC', 'ORB_OPT', 'FALSE')
psi4.set_local_option('OCC', 'DO_SCS', 'FALSE')
psi4.set_local_option('OCC', 'DO_SOS', 'FALSE')
elif name == 'omp2.5':
psi4.set_local_option('OCC', 'WFN_TYPE', 'OMP2.5')
psi4.set_local_option('OCC', 'ORB_OPT', 'TRUE')
psi4.set_local_option('OCC', 'DO_SCS', 'FALSE')
psi4.set_local_option('OCC', 'DO_SOS', 'FALSE')
elif name == 'mp3':
psi4.set_local_option('OCC', 'WFN_TYPE', 'OMP3')
psi4.set_local_option('OCC', 'ORB_OPT', 'FALSE')
psi4.set_local_option('OCC', 'DO_SCS', 'FALSE')
psi4.set_local_option('OCC', 'DO_SOS', 'FALSE')
elif name == 'omp3':
psi4.set_local_option('OCC', 'WFN_TYPE', 'OMP3')
psi4.set_local_option('OCC', 'ORB_OPT', 'TRUE')
psi4.set_local_option('OCC', 'DO_SCS', 'FALSE')
psi4.set_local_option('OCC', 'DO_SOS', 'FALSE')
elif name == 'scs-omp3':
psi4.set_local_option('OCC', 'WFN_TYPE', 'OMP3')
psi4.set_local_option('OCC', 'ORB_OPT', 'TRUE')
psi4.set_local_option('OCC', 'DO_SCS', 'TRUE')
psi4.set_local_option('OCC', 'SCS_TYPE', 'SCS')
elif name == 'scs(n)-omp3':
psi4.set_local_option('OCC', 'WFN_TYPE', 'OMP3')
psi4.set_local_option('OCC', 'ORB_OPT', 'TRUE')
psi4.set_local_option('OCC', 'DO_SCS', 'TRUE')
psi4.set_local_option('OCC', 'SCS_TYPE', 'SCSN')
elif name == 'scs-omp3-vdw':
psi4.set_local_option('OCC', 'WFN_TYPE', 'OMP3')
psi4.set_local_option('OCC', 'ORB_OPT', 'TRUE')
psi4.set_local_option('OCC', 'DO_SCS', 'TRUE')
psi4.set_local_option('OCC', 'SCS_TYPE', 'SCSVDW')
elif name == 'sos-omp3':
psi4.set_local_option('OCC', 'WFN_TYPE', 'OMP3')
psi4.set_local_option('OCC', 'ORB_OPT', 'TRUE')
psi4.set_local_option('OCC', 'DO_SOS', 'TRUE')
psi4.set_local_option('OCC', 'SOS_TYPE', 'SOS')
elif name == 'sos-pi-omp3':
psi4.set_local_option('OCC', 'WFN_TYPE', 'OMP3')
psi4.set_local_option('OCC', 'ORB_OPT', 'TRUE')
psi4.set_local_option('OCC', 'DO_SOS', 'TRUE')
psi4.set_local_option('OCC', 'SOS_TYPE', 'SOSPI')
elif name == 'lccd':
psi4.set_local_option('OCC', 'WFN_TYPE', 'OCEPA')
psi4.set_local_option('OCC', 'ORB_OPT', 'FALSE')
psi4.set_local_option('OCC', 'DO_SCS', 'FALSE')
psi4.set_local_option('OCC', 'DO_SOS', 'FALSE')
elif name == 'olccd':
psi4.set_local_option('OCC', 'WFN_TYPE', 'OCEPA')
psi4.set_local_option('OCC', 'ORB_OPT', 'TRUE')
psi4.set_local_option('OCC', 'DO_SCS', 'FALSE')
psi4.set_local_option('OCC', 'DO_SOS', 'FALSE')
else:
raise ValidationError("""Invalid method %s""" % name)
# Bypass the scf call if a reference wavefunction is given
ref_wfn = kwargs.get('ref_wfn', None)
if ref_wfn is None:
ref_wfn = scf_helper(name, **kwargs) # C1 certified
# Ensure IWL files have been written
proc_util.check_iwl_file_from_scf_type(psi4.get_option('SCF', 'SCF_TYPE'), ref_wfn)
if psi4.get_option('SCF', 'REFERENCE') == 'ROHF':
ref_wfn.semicanonicalize()
occ_wfn = psi4.occ(ref_wfn)
optstash.restore()
return occ_wfn
[docs]def run_occ_gradient(name, **kwargs):
"""Function encoding sequence of PSI module calls for
a conventional integral (O)MPN computation
"""
optstash = p4util.OptionsState(
['OCC', 'ORB_OPT'],
['OCC', 'WFN_TYPE'],
['OCC', 'DO_SCS'],
['OCC', 'DO_SOS'],
['GLOBALS', 'DERTYPE'])
if name == 'mp2':
psi4.set_local_option('OCC', 'WFN_TYPE', 'OMP2')
psi4.set_local_option('OCC', 'ORB_OPT', 'FALSE')
elif name in ['omp2', 'conv-omp2']:
psi4.set_local_option('OCC', 'WFN_TYPE', 'OMP2')
psi4.set_local_option('OCC', 'ORB_OPT', 'TRUE')
elif name == 'mp2.5':
psi4.set_local_option('OCC', 'WFN_TYPE', 'OMP2.5')
psi4.set_local_option('OCC', 'ORB_OPT', 'FALSE')
elif name == 'omp2.5':
psi4.set_local_option('OCC', 'WFN_TYPE', 'OMP2.5')
psi4.set_local_option('OCC', 'ORB_OPT', 'TRUE')
elif name == 'mp3':
psi4.set_local_option('OCC', 'WFN_TYPE', 'OMP3')
psi4.set_local_option('OCC', 'ORB_OPT', 'FALSE')
elif name == 'omp3':
psi4.set_local_option('OCC', 'WFN_TYPE', 'OMP3')
psi4.set_local_option('OCC', 'ORB_OPT', 'TRUE')
elif name == 'lccd':
psi4.set_local_option('OCC', 'WFN_TYPE', 'OCEPA')
psi4.set_local_option('OCC', 'ORB_OPT', 'FALSE')
elif name == 'olccd':
psi4.set_local_option('OCC', 'WFN_TYPE', 'OCEPA')
psi4.set_local_option('OCC', 'ORB_OPT', 'TRUE')
else:
raise ValidationError("""Invalid method %s""" % name)
psi4.set_global_option('DERTYPE', 'FIRST')
# locking out SCS through explicit keyword setting
# * so that current energy must match call
# * since grads not avail for scs
psi4.set_local_option('OCC', 'DO_SCS', 'FALSE')
psi4.set_local_option('OCC', 'DO_SOS', 'FALSE')
# Bypass the scf call if a reference wavefunction is given
ref_wfn = kwargs.get('ref_wfn', None)
if ref_wfn is None:
ref_wfn = scf_helper(name, **kwargs) # C1 certified
# Ensure IWL files have been written
proc_util.check_iwl_file_from_scf_type(psi4.get_option('SCF', 'SCF_TYPE'), ref_wfn)
if psi4.get_option('SCF', 'REFERENCE') == 'ROHF':
ref_wfn.semicanonicalize()
occ_wfn = psi4.occ(ref_wfn)
derivobj = psi4.Deriv(occ_wfn)
grad = derivobj.compute()
occ_wfn.set_gradient(grad)
optstash.restore()
return occ_wfn
[docs]def run_scf(name, **kwargs):
"""Function encoding sequence of PSI module calls for
a self-consistent-field theory (HF & DFT) calculation.
"""
optstash = proc_util.scf_set_reference_local(name)
scf_wfn = scf_helper(name, **kwargs)
optstash.restore()
return scf_wfn
[docs]def run_scf_gradient(name, **kwargs):
"""Function encoding sequence of PSI module calls for
a SCF gradient calculation.
"""
optstash = proc_util.scf_set_reference_local(name)
# Bypass the scf call if a reference wavefunction is given
ref_wfn = kwargs.get('ref_wfn', None)
if ref_wfn is None:
ref_wfn = run_scf(name, **kwargs)
if psi4.get_option('SCF', 'REFERENCE') in ['ROHF', 'CUHF']:
ref_wfn.semicanonicalize()
grad = psi4.scfgrad(ref_wfn)
ref_wfn.set_gradient(grad)
optstash.restore()
return ref_wfn
[docs]def run_libfock(name, **kwargs):
"""Function encoding sequence of PSI module calls for
a calculation through libfock, namely RCPHF,
RCIS, RTDHF, RTDA, and RTDDFT.
"""
if name == 'cphf':
psi4.set_global_option('MODULE', 'RCPHF')
if name == 'cis':
psi4.set_global_option('MODULE', 'RCIS')
if name == 'tdhf':
psi4.set_global_option('MODULE', 'RTDHF')
if name == 'cpks':
psi4.set_global_option('MODULE', 'RCPKS')
if name == 'tda':
psi4.set_global_option('MODULE', 'RTDA')
if name == 'tddft':
psi4.set_global_option('MODULE', 'RTDDFT')
# Bypass the scf call if a reference wavefunction is given
ref_wfn = kwargs.get('ref_wfn', None)
if ref_wfn is None:
ref_wfn = scf_helper(name, **kwargs)
libfock_wfn = psi4.libfock(ref_wfn)
libfock_wfn.compute_energy()
return libfock_wfn
[docs]def run_mcscf(name, **kwargs):
"""Function encoding sequence of PSI module calls for
a multiconfigurational self-consistent-field calculation.
"""
# Make sure the molecule the user provided is the active one
mcscf_molecule = kwargs.get('molecule', psi4.get_active_molecule())
mcscf_molecule.update_geometry()
if 'ref_wfn' in kwargs:
raise ValidationError("It is not possible to pass run_mcscf a reference wavefunction")
new_wfn = psi4.new_wavefunction(mcscf_molecule, psi4.get_global_option('BASIS'))
return psi4.mcscf(new_wfn)
[docs]def run_dfmp2_gradient(name, **kwargs):
"""Function encoding sequence of PSI module calls for
a DFMP2 gradient calculation.
"""
optstash = p4util.OptionsState(
['DF_BASIS_SCF'],
['DF_BASIS_MP2'],
['SCF_TYPE']) # yes, this really must be global, not local to SCF
# Alter default algorithm
if not psi4.has_option_changed('SCF', 'SCF_TYPE'):
psi4.set_global_option('SCF_TYPE', 'DF')
psi4.print_out(""" SCF Algorithm Type (re)set to DF.\n""")
if psi4.get_option('SCF', 'SCF_TYPE') != 'DF':
raise ValidationError('DF-MP2 gradients need DF-SCF reference.')
# Bypass the scf call if a reference wavefunction is given
ref_wfn = kwargs.get('ref_wfn', None)
if ref_wfn is None:
ref_wfn = scf_helper(name, **kwargs) # C1 certified
psi4.print_out('\n')
p4util.banner('DFMP2')
psi4.print_out('\n')
dfmp2_wfn = psi4.dfmp2(ref_wfn)
grad = dfmp2_wfn.compute_gradient()
dfmp2_wfn.set_gradient(grad)
optstash.restore()
return dfmp2_wfn
[docs]def run_ccenergy(name, **kwargs):
"""Function encoding sequence of PSI module calls for
a CCSD, CC2, and CC3 calculation.
"""
optstash = p4util.OptionsState(
['TRANSQT2', 'WFN'],
['CCSORT', 'WFN'],
['CCENERGY', 'WFN'])
if name == 'ccsd':
psi4.set_local_option('TRANSQT2', 'WFN', 'CCSD')
psi4.set_local_option('CCSORT', 'WFN', 'CCSD')
psi4.set_local_option('CCTRANSORT', 'WFN', 'CCSD')
psi4.set_local_option('CCENERGY', 'WFN', 'CCSD')
elif name == 'ccsd(t)':
psi4.set_local_option('TRANSQT2', 'WFN', 'CCSD_T')
psi4.set_local_option('CCSORT', 'WFN', 'CCSD_T')
psi4.set_local_option('CCTRANSORT', 'WFN', 'CCSD_T')
psi4.set_local_option('CCENERGY', 'WFN', 'CCSD_T')
elif name == 'ccsd(at)':
psi4.set_local_option('TRANSQT2', 'WFN', 'CCSD_AT')
psi4.set_local_option('CCSORT', 'WFN', 'CCSD_AT')
psi4.set_local_option('CCTRANSORT', 'WFN', 'CCSD_AT')
psi4.set_local_option('CCENERGY', 'WFN', 'CCSD_AT')
psi4.set_local_option('CCHBAR', 'WFN', 'CCSD_AT')
psi4.set_local_option('CCLAMBDA', 'WFN', 'CCSD_AT')
elif name == 'cc2':
psi4.set_local_option('TRANSQT2', 'WFN', 'CC2')
psi4.set_local_option('CCSORT', 'WFN', 'CC2')
psi4.set_local_option('CCTRANSORT', 'WFN', 'CC2')
psi4.set_local_option('CCENERGY', 'WFN', 'CC2')
elif name == 'cc3':
psi4.set_local_option('TRANSQT2', 'WFN', 'CC3')
psi4.set_local_option('CCSORT', 'WFN', 'CC3')
psi4.set_local_option('CCTRANSORT', 'WFN', 'CC3')
psi4.set_local_option('CCENERGY', 'WFN', 'CC3')
elif name == 'eom-cc2':
psi4.set_local_option('TRANSQT2', 'WFN', 'EOM_CC2')
psi4.set_local_option('CCSORT', 'WFN', 'EOM_CC2')
psi4.set_local_option('CCTRANSORT', 'WFN', 'EOM_CC2')
psi4.set_local_option('CCENERGY', 'WFN', 'EOM_CC2')
elif name == 'eom-ccsd':
psi4.set_local_option('TRANSQT2', 'WFN', 'EOM_CCSD')
psi4.set_local_option('CCSORT', 'WFN', 'EOM_CCSD')
psi4.set_local_option('CCTRANSORT', 'WFN', 'EOM_CCSD')
psi4.set_local_option('CCENERGY', 'WFN', 'EOM_CCSD')
# Call a plain energy('ccenergy') and have full control over options, incl. wfn
elif name == 'ccenergy':
pass
# Bypass routine scf if user did something special to get it to converge
ref_wfn = kwargs.get('ref_wfn', None)
if ref_wfn is None:
ref_wfn = scf_helper(name, **kwargs) # C1 certified
# Ensure IWL files have been written
proc_util.check_iwl_file_from_scf_type(psi4.get_option('SCF', 'SCF_TYPE'), ref_wfn)
# Obtain semicanonical orbitals
if (psi4.get_option('SCF', 'REFERENCE') == 'ROHF') and \
((name in ['ccsd(t)', 'ccsd(at)', 'cc2', 'cc3', 'eom-cc2', 'eom-cc3']) or
psi4.get_option('CCTRANSORT', 'SEMICANONICAL')):
ref_wfn.semicanonicalize()
if psi4.get_global_option('RUN_CCTRANSORT'):
psi4.cctransort(ref_wfn)
else:
psi4.transqt2(ref_wfn)
psi4.ccsort()
ccwfn = psi4.ccenergy(ref_wfn)
if name == 'ccsd(at)':
psi4.cchbar(ref_wfn)
psi4.cclambda(ref_wfn)
optstash.restore()
return ccwfn
[docs]def run_ccenergy_gradient(name, **kwargs):
"""Function encoding sequence of PSI module calls for
a CCSD and CCSD(T) gradient calculation.
"""
optstash = p4util.OptionsState(
['GLOBALS', 'DERTYPE'],
['CCLAMBDA', 'WFN'],
['CCDENSITY', 'WFN'])
psi4.set_global_option('DERTYPE', 'FIRST')
if psi4.get_global_option('FREEZE_CORE') == 'TRUE':
raise ValidationError('Frozen core is not available for the CC gradients.')
ccwfn = run_ccenergy(name, **kwargs)
if name == 'ccsd':
psi4.set_local_option('CCLAMBDA', 'WFN', 'CCSD')
psi4.set_local_option('CCDENSITY', 'WFN', 'CCSD')
elif name == 'ccsd(t)':
psi4.set_local_option('CCLAMBDA', 'WFN', 'CCSD_T')
psi4.set_local_option('CCDENSITY', 'WFN', 'CCSD_T')
user_ref = psi4.get_option('CCENERGY', 'REFERENCE')
if user_ref != 'UHF':
raise ValidationError('Reference %s for CCSD(T) gradients is not available.' % user_ref)
psi4.cchbar(ccwfn)
psi4.cclambda(ccwfn)
psi4.ccdensity(ccwfn)
derivobj = psi4.Deriv(ccwfn)
grad = derivobj.compute()
del derivobj
ccwfn.set_gradient(grad)
optstash.restore()
return ccwfn
[docs]def run_bccd(name, **kwargs):
"""Function encoding sequence of PSI module calls for
a Brueckner CCD calculation.
"""
optstash = p4util.OptionsState(
['TRANSQT2', 'DELETE_TEI'],
['TRANSQT2', 'WFN'],
['CCSORT', 'WFN'],
['CCENERGY', 'WFN'])
if name == 'bccd':
psi4.set_local_option('TRANSQT2', 'WFN', 'BCCD')
psi4.set_local_option('CCSORT', 'WFN', 'BCCD')
psi4.set_local_option('CCTRANSORT', 'WFN', 'BCCD')
psi4.set_local_option('CCENERGY', 'WFN', 'BCCD')
elif name == 'bccd(t)':
psi4.set_local_option('TRANSQT2', 'WFN', 'BCCD_T')
psi4.set_local_option('CCSORT', 'WFN', 'BCCD_T')
psi4.set_local_option('CCENERGY', 'WFN', 'BCCD_T')
psi4.set_local_option('CCTRANSORT', 'WFN', 'BCCD_T')
psi4.set_local_option('CCTRIPLES', 'WFN', 'BCCD_T')
else:
raise ValidationError("proc.py:run_bccd name %s not recognized" % name)
# Bypass routine scf if user did something special to get it to converge
ref_wfn = kwargs.get('ref_wfn', None)
if ref_wfn is None:
ref_wfn = scf_helper(name, **kwargs) # C1 certified
# Needed for (T).
if (psi4.get_option('SCF', 'REFERENCE') == 'ROHF'):
ref_wfn.semicanonicalize()
# Ensure IWL files have been written
proc_util.check_iwl_file_from_scf_type(psi4.get_option('SCF', 'SCF_TYPE'), ref_wfn)
psi4.set_local_option('TRANSQT2', 'DELETE_TEI', 'false')
psi4.set_local_option('CCTRANSORT', 'DELETE_TEI', 'false')
bcc_iter_cnt = 0
while True:
if (psi4.get_global_option("RUN_CCTRANSORT")):
psi4.cctransort(ref_wfn)
else:
psi4.transqt2(ref_wfn)
psi4.ccsort()
ref_wfn = psi4.ccenergy(ref_wfn)
psi4.print_out('Brueckner convergence check: %s\n' % bool(psi4.get_variable('BRUECKNER CONVERGED')))
if (psi4.get_variable('BRUECKNER CONVERGED') == True):
break
if bcc_iter_cnt >= psi4.get_option('CCENERGY', 'BCCD_MAXITER'):
psi4.print_out("\n\nWarning! BCCD did not converge within the maximum number of iterations.")
psi4.print_out("You can increase the number of BCCD iterations by changing BCCD_MAXITER.\n\n")
break
bcc_iter_cnt += 1
if name == 'bccd(t)':
psi4.cctriples(ref_wfn)
optstash.restore()
return ref_wfn
[docs]def run_dft_property(name, **kwargs):
"""Function encoding sequence of PSI module calls for
DFT calculations. This is a simple alias to :py:func:`~proc.run_scf`
since DFT properties all handled through oeprop.
"""
optstash = proc_util.dft_set_reference_local(name)
properties = kwargs.pop('properties')
proc_util.oeprop_validator(properties)
scf_wfn = run_scf(name, scf_do_dipole=False, *kwargs)
# Run OEProp
oe = psi4.OEProp(scf_wfn)
oe.set_title(name.upper())
for prop in properties:
oe.add(prop.upper())
oe.compute()
optstash.restore()
return scf_wfn
[docs]def run_scf_property(name, **kwargs):
"""Function encoding sequence of PSI module calls for
SCF calculations. This is a simple alias to :py:func:`~proc.run_scf`
since SCF properties all handled through oeprop.
"""
optstash = proc_util.scf_set_reference_local(name)
properties = kwargs.pop('properties')
proc_util.oeprop_validator(properties)
scf_wfn = run_scf(name, scf_do_dipole=False, **kwargs)
# Run OEProp
oe = psi4.OEProp(scf_wfn)
oe.set_title(name.upper())
for prop in properties:
oe.add(prop.upper())
oe.compute()
optstash.restore()
return scf_wfn
[docs]def run_cc_property(name, **kwargs):
"""Function encoding sequence of PSI module calls for
all CC property calculations.
"""
optstash = p4util.OptionsState(
['WFN'],
['DERTYPE'],
['ONEPDM'],
['PROPERTY'],
['CCLAMBDA', 'R_CONVERGENCE'],
['CCEOM', 'R_CONVERGENCE'],
['CCEOM', 'E_CONVERGENCE'])
oneel_properties = ['dipole', 'quadrupole']
twoel_properties = []
response_properties = ['polarizability', 'rotation', 'roa', 'roa_tensor']
excited_properties = ['oscillator_strength', 'rotational_strength']
one = []
two = []
response = []
excited = []
invalid = []
if 'properties' in kwargs:
properties = kwargs['properties']
for prop in properties:
if prop in oneel_properties:
one.append(prop)
elif prop in twoel_properties:
two.append(prop)
elif prop in response_properties:
response.append(prop)
elif prop in excited_properties:
excited.append(prop)
else:
invalid.append(prop)
else:
raise ValidationError("""The "properties" keyword is required with the property() function.""")
n_one = len(one)
n_two = len(two)
n_response = len(response)
n_excited = len(excited)
n_invalid = len(invalid)
if n_invalid > 0:
print("""The following properties are not currently supported: %s""" % invalid)
if n_excited > 0 and (name not in ['eom-ccsd', 'eom-cc2']):
raise ValidationError("""Excited state CC properties require EOM-CC2 or EOM-CCSD.""")
if (name in ['eom-ccsd', 'eom-cc2']) and n_response > 0:
raise ValidationError("""Cannot (yet) compute response properties for excited states.""")
if 'roa' in response:
# Perform distributed roa job
run_roa(name, **kwargs)
return # Don't do anything further
if (n_one > 0 or n_two > 0) and (n_response > 0):
print("""Computing both density- and response-based properties.""")
if name in ['ccsd', 'cc2', 'eom-ccsd', 'eom-cc2']:
this_name = name.upper().replace('-', '_')
psi4.set_global_option('WFN', this_name)
ccwfn = run_ccenergy(name, **kwargs)
psi4.set_global_option('WFN', this_name)
else:
raise ValidationError("""CC property name %s not recognized""" % name.upper())
# Need cchbar for everything
psi4.cchbar(ccwfn)
# Need ccdensity at this point only for density-based props
if n_one > 0 or n_two > 0:
if name == 'eom-ccsd':
psi4.set_global_option('WFN', 'EOM_CCSD')
psi4.set_global_option('DERTYPE', 'NONE')
psi4.set_global_option('ONEPDM', 'TRUE')
psi4.cceom(ccwfn)
elif name == 'eom-cc2':
psi4.set_global_option('WFN', 'EOM_CC2')
psi4.set_global_option('DERTYPE', 'NONE')
psi4.set_global_option('ONEPDM', 'TRUE')
psi4.cceom(ccwfn)
psi4.set_global_option('DERTYPE', 'NONE')
psi4.set_global_option('ONEPDM', 'TRUE')
psi4.cclambda(ccwfn)
psi4.ccdensity(ccwfn)
# Need ccresponse only for response-type props
if n_response > 0:
psi4.set_global_option('DERTYPE', 'RESPONSE')
psi4.cclambda(ccwfn)
for prop in response:
psi4.set_global_option('PROPERTY', prop)
psi4.ccresponse(ccwfn)
# Excited-state transition properties
if n_excited > 0:
if name == 'eom-ccsd':
psi4.set_global_option('WFN', 'EOM_CCSD')
elif name == 'eom-cc2':
psi4.set_global_option('WFN', 'EOM_CC2')
else:
raise ValidationError("""Unknown excited-state CC wave function.""")
psi4.set_global_option('DERTYPE', 'NONE')
psi4.set_global_option('ONEPDM', 'TRUE')
# Tight convergence unnecessary for transition properties
psi4.set_local_option('CCLAMBDA','R_CONVERGENCE',1e-4)
psi4.set_local_option('CCEOM','R_CONVERGENCE',1e-4)
psi4.set_local_option('CCEOM','E_CONVERGENCE',1e-5)
psi4.cceom(ccwfn)
psi4.cclambda(ccwfn)
psi4.ccdensity(ccwfn)
psi4.set_global_option('WFN', 'SCF')
psi4.revoke_global_option_changed('WFN')
psi4.set_global_option('DERTYPE', 'NONE')
psi4.revoke_global_option_changed('DERTYPE')
optstash.restore()
return ccwfn
[docs]def run_dfmp2_property(name, **kwargs):
"""Function encoding sequence of PSI module calls for
a DFMP2 property calculation.
"""
optstash = p4util.OptionsState(
['DF_BASIS_SCF'],
['DF_BASIS_MP2'],
['ONEPDM'],
['OPDM_RELAX'],
['SCF_TYPE'])
psi4.set_global_option('ONEPDM', 'TRUE')
psi4.set_global_option('OPDM_RELAX', 'TRUE')
# Alter default algorithm
if not psi4.has_option_changed('SCF', 'SCF_TYPE'):
psi4.set_global_option('SCF_TYPE', 'DF') # local set insufficient b/c SCF option read in DFMP2
psi4.print_out(""" SCF Algorithm Type (re)set to DF.\n""")
if not psi4.get_option('SCF', 'SCF_TYPE') == 'DF':
raise ValidationError('DF-MP2 properties need DF-SCF reference.')
properties = kwargs.pop('properties')
proc_util.oeprop_validator(properties)
# Bypass the scf call if a reference wavefunction is given
ref_wfn = kwargs.get('ref_wfn', None)
if ref_wfn is None:
ref_wfn = scf_helper(name, scf_do_dipole=False, use_c1=True, **kwargs) # C1 certified
psi4.print_out('\n')
p4util.banner('DFMP2')
psi4.print_out('\n')
dfmp2_wfn = psi4.dfmp2(ref_wfn)
grad = dfmp2_wfn.compute_gradient()
if name == 'scs-mp2':
psi4.set_variable('CURRENT ENERGY', psi4.get_variable('SCS-MP2 TOTAL ENERGY'))
psi4.set_variable('CURRENT CORRELATION ENERGY', psi4.get_variable('SCS-MP2 CORRELATION ENERGY'))
elif name == 'mp2':
psi4.set_variable('CURRENT ENERGY', psi4.get_variable('MP2 TOTAL ENERGY'))
psi4.set_variable('CURRENT CORRELATION ENERGY', psi4.get_variable('MP2 CORRELATION ENERGY'))
# Run OEProp
oe = psi4.OEProp(dfmp2_wfn)
oe.set_title(name.upper())
for prop in properties:
oe.add(prop.upper())
oe.compute()
optstash.restore()
return dfmp2_wfn
[docs]def run_detci_property(name, **kwargs):
"""Function encoding sequence of PSI module calls for
a configuration interaction calculation, namely FCI,
CIn, MPn, and ZAPTn, computing properties.
"""
optstash = p4util.OptionsState(
['OPDM'],
['TDM'])
# Find valid properties
valid_transition = ['TRANSITION_DIPOLE', 'TRANSITION_QUADRUPOLE']
ci_prop = []
ci_trans = []
properties = kwargs.pop('properties')
for prop in properties:
if prop.upper() in valid_transition:
ci_trans.append(prop)
else:
ci_prop.append(prop)
proc_util.oeprop_validator(ci_prop)
psi4.set_global_option('OPDM', 'TRUE')
if len(ci_trans):
psi4.set_global_option('TDM', 'TRUE')
# Compute
if name in ['mcscf', 'rasscf', 'casscf']:
ciwfn = run_detcas(name, **kwargs)
else:
ciwfn = run_detci(name, **kwargs)
# All property names are just CI
if 'CI' in name.upper():
name = 'CI'
states = psi4.get_global_option('avg_states')
nroots = psi4.get_global_option('num_roots')
if len(states) != nroots:
states = range(1, nroots + 1)
# Run OEProp
oe = psi4.OEProp(ciwfn)
oe.set_title(name.upper())
for prop in ci_prop:
oe.add(prop.upper())
# Compute "the" CI density
oe.compute()
# If we have more than one root, compute all data
if nroots > 1:
psi4.print_out("\n ===> %s properties for all CI roots <=== \n\n" % name.upper())
for root in states:
oe.set_title("%s ROOT %d" % (name.upper(), root))
root = root - 1
if ciwfn.same_a_b_dens():
oe.set_Da_mo(ciwfn.get_opdm(root, root, "A", True))
else:
oe.set_Da_mo(ciwfn.get_opdm(root, root, "A", True))
oe.set_Db_mo(ciwfn.get_opdm(root, root, "B", True))
oe.compute()
# Transition density matrices
if (nroots > 1) and len(ci_trans):
oe.clear()
for tprop in ci_trans:
oe.add(tprop.upper())
psi4.print_out("\n ===> %s properties for all CI transition density matrices <=== \n\n" % name.upper())
for root in states[1:]:
oe.set_title("%s ROOT %d -> ROOT %d" % (name.upper(), 1, root))
root = root - 1
if ciwfn.same_a_b_dens():
oe.set_Da_mo(ciwfn.get_opdm(0, root, "A", True))
else:
oe.set_Da_mo(ciwfn.get_opdm(0, root, "A", True))
oe.set_Db_mo(ciwfn.get_opdm(0, root, "B", True))
oe.compute()
optstash.restore()
return ciwfn
[docs]def run_eom_cc(name, **kwargs):
"""Function encoding sequence of PSI module calls for
an EOM-CC calculation, namely EOM-CC2, EOM-CCSD, and EOM-CC3.
"""
optstash = p4util.OptionsState(
['TRANSQT2', 'WFN'],
['CCSORT', 'WFN'],
['CCENERGY', 'WFN'],
['CCHBAR', 'WFN'],
['CCEOM', 'WFN'])
if name == 'eom-ccsd':
psi4.set_local_option('TRANSQT2', 'WFN', 'EOM_CCSD')
psi4.set_local_option('CCSORT', 'WFN', 'EOM_CCSD')
psi4.set_local_option('CCENERGY', 'WFN', 'EOM_CCSD')
psi4.set_local_option('CCHBAR', 'WFN', 'EOM_CCSD')
psi4.set_local_option('CCEOM', 'WFN', 'EOM_CCSD')
ref_wfn = run_ccenergy('ccsd', **kwargs)
elif name == 'eom-cc2':
user_ref = psi4.get_option('CCENERGY', 'REFERENCE')
if (user_ref != 'RHF') and (user_ref != 'UHF'):
raise ValidationError('Reference %s for EOM-CC2 is not available.' % user_ref)
psi4.set_local_option('TRANSQT2', 'WFN', 'EOM_CC2')
psi4.set_local_option('CCSORT', 'WFN', 'EOM_CC2')
psi4.set_local_option('CCENERGY', 'WFN', 'EOM_CC2')
psi4.set_local_option('CCHBAR', 'WFN', 'EOM_CC2')
psi4.set_local_option('CCEOM', 'WFN', 'EOM_CC2')
ref_wfn = run_ccenergy('cc2', **kwargs)
elif name == 'eom-cc3':
psi4.set_local_option('TRANSQT2', 'WFN', 'EOM_CC3')
psi4.set_local_option('CCSORT', 'WFN', 'EOM_CC3')
psi4.set_local_option('CCENERGY', 'WFN', 'EOM_CC3')
psi4.set_local_option('CCHBAR', 'WFN', 'EOM_CC3')
psi4.set_local_option('CCEOM', 'WFN', 'EOM_CC3')
ref_wfn = run_ccenergy('cc3', **kwargs)
psi4.cchbar(ref_wfn)
psi4.cceom(ref_wfn)
optstash.restore()
return ref_wfn
# TODO ask if all these cc modules not actually changing wfn
[docs]def run_eom_cc_gradient(name, **kwargs):
"""Function encoding sequence of PSI module calls for
an EOM-CCSD gradient calculation.
"""
optstash = p4util.OptionsState(
['CCDENSITY', 'XI'],
['CCDENSITY', 'ZETA'],
['CCLAMBDA', 'ZETA'],
['DERTYPE'],
['CCDENSITY', 'WFN'],
['CCLAMBDA', 'WFN'])
psi4.set_global_option('DERTYPE', 'FIRST')
if name == 'eom-ccsd':
psi4.set_local_option('CCLAMBDA', 'WFN', 'EOM_CCSD')
psi4.set_local_option('CCDENSITY', 'WFN', 'EOM_CCSD')
ref_wfn = run_eom_cc(name, **kwargs)
else:
psi4.print_out('DGAS: proc.py:1599 hitting an undefined sequence')
psi4.clean()
raise ValueError('Hit a wall in proc.py:1599')
psi4.set_local_option('CCLAMBDA', 'ZETA', 'FALSE')
psi4.set_local_option('CCDENSITY', 'ZETA', 'FALSE')
psi4.set_local_option('CCDENSITY', 'XI', 'TRUE')
psi4.cclambda(ref_wfn)
psi4.ccdensity(ref_wfn)
psi4.set_local_option('CCLAMBDA', 'ZETA', 'TRUE')
psi4.set_local_option('CCDENSITY', 'ZETA', 'TRUE')
psi4.set_local_option('CCDENSITY', 'XI', 'FALSE')
psi4.cclambda(ref_wfn)
psi4.ccdensity(ref_wfn)
derivobj = psi4.Deriv(ref_wfn)
grad = derivobj.compute()
ref_wfn.set_gradient(grad)
optstash.restore()
return ref_wfn
[docs]def run_adc(name, **kwargs):
"""Function encoding sequence of PSI module calls for
an algebraic diagrammatic construction calculation.
.. caution:: Get rid of active molecule lines- should be handled in energy.
"""
if psi4.get_option('ADC', 'REFERENCE') != 'RHF':
raise ValidationError('ADC requires reference RHF')
# Bypass the scf call if a reference wavefunction is given
ref_wfn = kwargs.get('ref_wfn', None)
if ref_wfn is None:
ref_wfn = scf_helper(name, **kwargs)
# Ensure IWL files have been written
proc_util.check_iwl_file_from_scf_type(psi4.get_option('SCF', 'SCF_TYPE'), ref_wfn)
return psi4.adc(ref_wfn)
[docs]def run_dft(name, **kwargs):
"""Function encoding sequence of PSI module calls for
a density-functional-theory calculation.
"""
optstash = p4util.OptionsState(
['SCF', 'DFT_FUNCTIONAL'],
['SCF', 'REFERENCE'],
['SCF', 'SCF_TYPE'],
['DF_BASIS_MP2'],
['DFMP2', 'MP2_OS_SCALE'],
['DFMP2', 'MP2_SS_SCALE'])
# Alter default algorithm
if not psi4.has_option_changed('SCF', 'SCF_TYPE'):
psi4.set_local_option('SCF', 'SCF_TYPE', 'DF')
psi4.set_local_option('SCF', 'DFT_FUNCTIONAL', name)
user_ref = psi4.get_option('SCF', 'REFERENCE')
if (user_ref == 'RHF'):
psi4.set_local_option('SCF', 'REFERENCE', 'RKS')
elif (user_ref == 'UHF'):
psi4.set_local_option('SCF', 'REFERENCE', 'UKS')
elif (user_ref == 'ROHF'):
raise ValidationError('ROHF reference for DFT is not available.')
elif (user_ref == 'CUHF'):
raise ValidationError('CUHF reference for DFT is not available.')
scf_wfn = run_scf(name, **kwargs)
returnvalue = psi4.get_variable('CURRENT ENERGY')
for ssuper in superfunctional_list():
if ssuper.name().lower() == name:
dfun = ssuper
if dfun.is_c_hybrid():
if dfun.is_c_scs_hybrid():
psi4.set_local_option('DFMP2', 'MP2_OS_SCALE', dfun.c_os_alpha())
psi4.set_local_option('DFMP2', 'MP2_SS_SCALE', dfun.c_ss_alpha())
dfmp2_wfn = psi4.dfmp2(scf_wfn)
dfmp2_wfn.compute_energy()
vdh = dfun.c_alpha() * psi4.get_variable('SCS-MP2 CORRELATION ENERGY')
else:
dfmp2_wfn = psi4.dfmp2(scf_wfn)
dfmp2_wfn.compute_energy()
vdh = dfun.c_alpha() * psi4.get_variable('MP2 CORRELATION ENERGY')
# TODO: delete these variables, since they don't mean what they look to mean?
# 'MP2 TOTAL ENERGY',
# 'MP2 CORRELATION ENERGY',
# 'MP2 SAME-SPIN CORRELATION ENERGY']
psi4.set_variable('DOUBLE-HYBRID CORRECTION ENERGY', vdh)
returnvalue += vdh
psi4.set_variable('DFT TOTAL ENERGY', returnvalue)
psi4.set_variable('CURRENT ENERGY', returnvalue)
psi4.print_out('\n\n')
psi4.print_out(' %s Energy Summary\n' % (name.upper()))
psi4.print_out(' -------------------------\n')
psi4.print_out(' DFT Reference Energy = %22.16lf\n' % (returnvalue - vdh))
psi4.print_out(' Scaled MP2 Correlation = %22.16lf\n' % (vdh))
psi4.print_out(' @Final double-hybrid DFT total energy = %22.16lf\n\n' % (returnvalue))
optstash.restore()
return scf_wfn
[docs]def run_dft_gradient(name, **kwargs):
"""Function encoding sequence of PSI module calls for
a density-functional-theory gradient calculation.
"""
optstash = p4util.OptionsState(
['SCF', 'DFT_FUNCTIONAL'],
['SCF', 'REFERENCE'],
['SCF', 'SCF_TYPE'])
# Alter default algorithm
if not psi4.has_option_changed('SCF', 'SCF_TYPE'):
psi4.set_local_option('SCF', 'SCF_TYPE', 'DF')
psi4.set_local_option('SCF', 'DFT_FUNCTIONAL', name.upper())
user_ref = psi4.get_option('SCF', 'REFERENCE')
if (user_ref == 'RHF'):
psi4.set_local_option('SCF', 'REFERENCE', 'RKS')
elif (user_ref == 'UHF'):
psi4.set_local_option('SCF', 'REFERENCE', 'UKS')
elif (user_ref == 'ROHF'):
raise ValidationError('ROHF reference for DFT is not available.')
elif (user_ref == 'CUHF'):
raise ValidationError('CUHF reference for DFT is not available.')
wfn = run_scf_gradient(name, **kwargs)
optstash.restore()
return wfn
[docs]def run_detci(name, **kwargs):
"""Function encoding sequence of PSI module calls for
a configuration interaction calculation, namely FCI,
CIn, MPn, and ZAPTn.
"""
optstash = p4util.OptionsState(
['DETCI', 'WFN'],
['DETCI', 'MAX_NUM_VECS'],
['DETCI', 'MPN_ORDER_SAVE'],
['DETCI', 'MPN'],
['DETCI', 'FCI'],
['DETCI', 'EX_LEVEL'])
if psi4.get_option('DETCI', 'REFERENCE') not in ['RHF', 'ROHF']:
raise ValidationError('Reference %s for DETCI is not available.' %
psi4.get_option('DETCI', 'REFERENCE'))
if name == 'zapt':
psi4.set_local_option('DETCI', 'WFN', 'ZAPTN')
level = kwargs['level']
maxnvect = int((level + 1) / 2) + (level + 1) % 2
psi4.set_local_option('DETCI', 'MAX_NUM_VECS', maxnvect)
if (level + 1) % 2:
psi4.set_local_option('DETCI', 'MPN_ORDER_SAVE', 2)
else:
psi4.set_local_option('DETCI', 'MPN_ORDER_SAVE', 1)
elif name in ['mp', 'mp2', 'mp3', 'mp4']:
psi4.set_local_option('DETCI', 'WFN', 'DETCI')
psi4.set_local_option('DETCI', 'MPN', 'TRUE')
if name == 'mp2':
level = 2
elif name == 'mp3':
level = 3
elif name == 'mp4':
level = 4
else:
level = kwargs['level']
maxnvect = int((level + 1) / 2) + (level + 1) % 2
psi4.set_local_option('DETCI', 'MAX_NUM_VECS', maxnvect)
if (level + 1) % 2:
psi4.set_local_option('DETCI', 'MPN_ORDER_SAVE', 2)
else:
psi4.set_local_option('DETCI', 'MPN_ORDER_SAVE', 1)
elif name == 'ccsd':
# untested
psi4.set_local_option('DETCI', 'WFN', 'DETCI')
psi4.set_local_option('DETCI', 'CC', 'TRUE')
psi4.set_local_option('DETCI', 'CC_EX_LEVEL', 2)
elif name == 'fci':
psi4.set_local_option('DETCI', 'WFN', 'DETCI')
psi4.set_local_option('DETCI', 'FCI', 'TRUE')
elif name == 'cisd':
psi4.set_local_option('DETCI', 'WFN', 'DETCI')
psi4.set_local_option('DETCI', 'EX_LEVEL', 2)
elif name == 'cisdt':
psi4.set_local_option('DETCI', 'WFN', 'DETCI')
psi4.set_local_option('DETCI', 'EX_LEVEL', 3)
elif name == 'cisdtq':
psi4.set_local_option('DETCI', 'WFN', 'DETCI')
psi4.set_local_option('DETCI', 'EX_LEVEL', 4)
elif name == 'ci':
psi4.set_local_option('DETCI', 'WFN', 'DETCI')
level = kwargs['level']
psi4.set_local_option('DETCI', 'EX_LEVEL', level)
elif name == 'detci':
pass
# Bypass the scf call if a reference wavefunction is given
ref_wfn = kwargs.get('ref_wfn', None)
if ref_wfn is None:
ref_wfn = scf_helper(name, **kwargs) # C1 certified
# Ensure IWL files have been written
proc_util.check_iwl_file_from_scf_type(psi4.get_option('SCF', 'SCF_TYPE'), ref_wfn)
ci_wfn = psi4.detci(ref_wfn)
optstash.restore()
return ci_wfn
[docs]def run_dfmp2(name, **kwargs):
"""Function encoding sequence of PSI module calls for
a density-fitted MP2 calculation.
"""
optstash = p4util.OptionsState(
['DF_BASIS_MP2'],
['SCF', 'SCF_TYPE'])
# Alter default algorithm
if not psi4.has_option_changed('SCF', 'SCF_TYPE'):
psi4.set_local_option('SCF', 'SCF_TYPE', 'DF')
psi4.print_out(""" SCF Algorithm Type (re)set to DF.\n""")
# Bypass the scf call if a reference wavefunction is given
ref_wfn = kwargs.get('ref_wfn', None)
if ref_wfn is None:
ref_wfn = scf_helper(name, **kwargs) # C1 certified
psi4.print_out('\n')
p4util.banner('DFMP2')
psi4.print_out('\n')
if psi4.get_global_option('REFERENCE') == "ROHF":
ref_wfn.semicanonicalize()
dfmp2_wfn = psi4.dfmp2(ref_wfn)
dfmp2_wfn.compute_energy()
if name == 'scs-mp2':
psi4.set_variable('CURRENT ENERGY', psi4.get_variable('SCS-MP2 TOTAL ENERGY'))
psi4.set_variable('CURRENT CORRELATION ENERGY', psi4.get_variable('SCS-MP2 CORRELATION ENERGY'))
elif name == 'mp2':
psi4.set_variable('CURRENT ENERGY', psi4.get_variable('MP2 TOTAL ENERGY'))
psi4.set_variable('CURRENT CORRELATION ENERGY', psi4.get_variable('MP2 CORRELATION ENERGY'))
optstash.restore()
return dfmp2_wfn
[docs]def run_dmrgscf(name, **kwargs):
"""Function encoding sequence of PSI module calls for
an DMRG calculation.
"""
optstash = p4util.OptionsState(
['SCF', 'SCF_TYPE'],
['DMRG', 'DMRG_CASPT2_CALC'])
# Bypass the scf call if a reference wavefunction is given
ref_wfn = kwargs.get('ref_wfn', None)
if ref_wfn is None:
ref_wfn = scf_helper(name, **kwargs)
# Ensure IWL files have been written
proc_util.check_iwl_file_from_scf_type(psi4.get_option('SCF', 'SCF_TYPE'), ref_wfn)
if 'CASPT2' in name.upper():
psi4.set_local_option("DMRG", "DMRG_CASPT2_CALC", True)
dmrg_wfn = psi4.dmrg(ref_wfn)
optstash.restore()
return dmrg_wfn
[docs]def run_dmrgci(name, **kwargs):
"""Function encoding sequence of PSI module calls for
an DMRG calculation.
"""
optstash = p4util.OptionsState(
['SCF', 'SCF_TYPE'],
['DMRG', 'DMRG_SCF_MAX_ITER'])
# Bypass the scf call if a reference wavefunction is given
ref_wfn = kwargs.get('ref_wfn', None)
if ref_wfn is None:
ref_wfn = scf_helper(name, **kwargs)
# Ensure IWL files have been written
proc_util.check_iwl_file_from_scf_type(psi4.get_option('SCF', 'SCF_TYPE'), ref_wfn)
psi4.set_local_option('DMRG', 'DMRG_SCF_MAX_ITER', 1)
dmrg_wfn = psi4.dmrg(ref_wfn)
optstash.restore()
return dmrg_wfn
[docs]def run_psimrcc(name, **kwargs):
"""Function encoding sequence of PSI module calls for a PSIMRCC computation
using a reference from the MCSCF module
"""
mcscf_wfn = run_mcscf(name, **kwargs)
psimrcc_e = psi4.psimrcc(mcscf_wfn)
return mcscf_wfn
[docs]def run_psimrcc_scf(name, **kwargs):
"""Function encoding sequence of PSI module calls for a PSIMRCC computation
using a reference from the SCF module
"""
# Bypass the scf call if a reference wavefunction is given
ref_wfn = kwargs.get('ref_wfn', None)
if ref_wfn is None:
ref_wfn = scf_helper(name, **kwargs)
psimrcc_e = psi4.psimrcc(ref_wfn)
return ref_wfn
[docs]def run_sapt(name, **kwargs):
"""Function encoding sequence of PSI module calls for
a SAPT calculation of any level.
"""
optstash = p4util.OptionsState(
['SCF', 'SCF_TYPE'])
# Alter default algorithm
if not psi4.has_option_changed('SCF', 'SCF_TYPE'):
psi4.set_local_option('SCF', 'SCF_TYPE', 'DF')
# Get the molecule of interest
ref_wfn = kwargs.get('ref_wfn', None)
if ref_wfn is None:
sapt_dimer = kwargs.pop('molecule', psi4.get_active_molecule())
else:
psi4.print_out('Warning! SAPT argument "ref_wfn" is only able to use molecule information.')
sapt_dimer = ref_wfn.molecule()
sapt_dimer.update_geometry() # make sure since mol from wfn, kwarg, or P::e
# Shifting to C1 so we need to copy the active molecule
if sapt_dimer.schoenflies_symbol() != 'c1':
psi4.print_out(' SAPT does not make use of molecular symmetry, further calculations in C1 point group.\n')
sapt_dimer = sapt_dimer.clone()
sapt_dimer.reset_point_group('c1')
sapt_dimer.fix_orientation(True)
sapt_dimer.fix_com(True)
sapt_dimer.update_geometry()
if psi4.get_option('SCF', 'REFERENCE') != 'RHF':
raise ValidationError('SAPT requires requires \"reference rhf\".')
nfrag = sapt_dimer.nfragments()
if nfrag != 2:
raise ValidationError('SAPT requires active molecule to have 2 fragments, not %s.' % (nfrag))
do_delta_mp2 = True if name.endswith('dmp2') else False
sapt_basis = 'dimer'
if 'sapt_basis' in kwargs:
sapt_basis = kwargs.pop('sapt_basis')
sapt_basis = sapt_basis.lower()
if sapt_basis == 'dimer':
monomerA = sapt_dimer.extract_subsets(1, 2)
monomerA.set_name('monomerA')
monomerB = sapt_dimer.extract_subsets(2, 1)
monomerB.set_name('monomerB')
elif sapt_basis == 'monomer':
monomerA = sapt_dimer.extract_subsets(1)
monomerA.set_name('monomerA')
monomerB = sapt_dimer.extract_subsets(2)
monomerB.set_name('monomerB')
ri = psi4.get_option('SCF', 'SCF_TYPE')
df_ints_io = psi4.get_option('SCF', 'DF_INTS_IO')
# inquire if above at all applies to dfmp2
psi4.IO.set_default_namespace('dimer')
psi4.print_out('\n')
p4util.banner('Dimer HF')
psi4.print_out('\n')
if sapt_basis == 'dimer':
psi4.set_global_option('DF_INTS_IO', 'SAVE')
dimer_wfn = scf_helper('RHF', molecule=sapt_dimer, **kwargs)
if do_delta_mp2:
select_mp2(name, ref_wfn=dimer_wfn, **kwargs)
mp2_corl_interaction_e = psi4.get_variable('MP2 CORRELATION ENERGY')
if sapt_basis == 'dimer':
psi4.set_global_option('DF_INTS_IO', 'LOAD')
if sapt_basis == 'dimer':
psi4.IO.change_file_namespace(97, 'dimer', 'monomerA')
psi4.IO.set_default_namespace('monomerA')
psi4.print_out('\n')
p4util.banner('Monomer A HF')
psi4.print_out('\n')
monomerA_wfn = scf_helper('RHF', molecule=monomerA, **kwargs)
if do_delta_mp2:
select_mp2(name, ref_wfn=monomerA_wfn, **kwargs)
mp2_corl_interaction_e -= psi4.get_variable('MP2 CORRELATION ENERGY')
if sapt_basis == 'dimer':
psi4.IO.change_file_namespace(97, 'monomerA', 'monomerB')
psi4.IO.set_default_namespace('monomerB')
psi4.print_out('\n')
p4util.banner('Monomer B HF')
psi4.print_out('\n')
monomerB_wfn = scf_helper('RHF', molecule=monomerB, **kwargs)
if do_delta_mp2:
select_mp2(name, ref_wfn=monomerB_wfn, **kwargs)
mp2_corl_interaction_e -= psi4.get_variable('MP2 CORRELATION ENERGY')
psi4.set_variable('SAPT MP2 CORRELATION ENERGY', mp2_corl_interaction_e)
psi4.set_global_option('DF_INTS_IO', df_ints_io)
psi4.IO.change_file_namespace(p4const.PSIF_SAPT_MONOMERA, 'monomerA', 'dimer')
psi4.IO.change_file_namespace(p4const.PSIF_SAPT_MONOMERB, 'monomerB', 'dimer')
psi4.IO.set_default_namespace('dimer')
psi4.set_local_option('SAPT', 'E_CONVERGENCE', 10e-10)
psi4.set_local_option('SAPT', 'D_CONVERGENCE', 10e-10)
if name in ['sapt0', 'ssapt0']:
psi4.set_local_option('SAPT', 'SAPT_LEVEL', 'SAPT0')
elif name == 'sapt2':
psi4.set_local_option('SAPT', 'SAPT_LEVEL', 'SAPT2')
elif name in ['sapt2+', 'sapt2+dmp2']:
psi4.set_local_option('SAPT', 'SAPT_LEVEL', 'SAPT2+')
psi4.set_local_option('SAPT', 'DO_CCD_DISP', False)
elif name in ['sapt2+(3)', 'sapt2+(3)dmp2']:
psi4.set_local_option('SAPT', 'SAPT_LEVEL', 'SAPT2+3')
psi4.set_local_option('SAPT', 'DO_THIRD_ORDER', False)
psi4.set_local_option('SAPT', 'DO_CCD_DISP', False)
elif name in ['sapt2+3', 'sapt2+3dmp2']:
psi4.set_local_option('SAPT', 'SAPT_LEVEL', 'SAPT2+3')
psi4.set_local_option('SAPT', 'DO_THIRD_ORDER', True)
psi4.set_local_option('SAPT', 'DO_CCD_DISP', False)
elif name in ['sapt2+(ccd)', 'sapt2+(ccd)dmp2']:
psi4.set_local_option('SAPT', 'SAPT_LEVEL', 'SAPT2+')
psi4.set_local_option('SAPT', 'DO_CCD_DISP', True)
elif name in ['sapt2+(3)(ccd)', 'sapt2+(3)(ccd)dmp2']:
psi4.set_local_option('SAPT', 'SAPT_LEVEL', 'SAPT2+3')
psi4.set_local_option('SAPT', 'DO_THIRD_ORDER', False)
psi4.set_local_option('SAPT', 'DO_CCD_DISP', True)
elif name in ['sapt2+3(ccd)', 'sapt2+3(ccd)dmp2']:
psi4.set_local_option('SAPT', 'SAPT_LEVEL', 'SAPT2+3')
psi4.set_local_option('SAPT', 'DO_THIRD_ORDER', True)
psi4.set_local_option('SAPT', 'DO_CCD_DISP', True)
psi4.print_out('\n')
p4util.banner(name.upper())
psi4.print_out('\n')
e_sapt = psi4.sapt(dimer_wfn, monomerA_wfn, monomerB_wfn)
from qcdb.psivardefs import sapt_psivars
p4util.expand_psivars(sapt_psivars())
optstash.restore()
for term in ['ELST', 'EXCH', 'IND', 'DISP', 'TOTAL']:
psi4.set_variable(' '.join(['SAPT', term, 'ENERGY']),
psi4.get_variable(' '.join([name.upper(), term, 'ENERGY'])))
psi4.set_variable('CURRENT ENERGY', psi4.get_variable('SAPT TOTAL ENERGY'))
return dimer_wfn
[docs]def run_sapt_ct(name, **kwargs):
"""Function encoding sequence of PSI module calls for
a charge-transfer SAPT calcuation of any level.
"""
optstash = p4util.OptionsState(
['SCF', 'SCF_TYPE'])
if 'ref_wfn' in kwargs:
psi4.print_out('\nWarning! Argument ref_wfn is not valid for sapt computations\n')
# Alter default algorithm
if not psi4.has_option_changed('SCF', 'SCF_TYPE'):
psi4.set_local_option('SCF', 'SCF_TYPE', 'DF')
# Get the molecule of interest
ref_wfn = kwargs.get('ref_wfn', None)
if ref_wfn is None:
sapt_dimer = kwargs.pop('molecule', psi4.get_active_molecule())
else:
psi4.print_out('Warning! SAPT argument "ref_wfn" is only able to use molecule information.')
sapt_dimer = ref_wfn.molecule()
sapt_dimer.update_geometry() # make sure since mol from wfn, kwarg, or P::e
# Shifting to C1 so we need to copy the active molecule
if sapt_dimer.schoenflies_symbol() != 'c1':
psi4.print_out(' SAPT does not make use of molecular symmetry, further calculations in C1 point group.\n')
sapt_dimer = sapt_dimer.clone()
sapt_dimer.reset_point_group('c1')
sapt_dimer.fix_orientation(True)
sapt_dimer.fix_com(True)
sapt_dimer.update_geometry()
if psi4.get_option('SCF', 'REFERENCE') != 'RHF':
raise ValidationError('SAPT requires requires \"reference rhf\".')
nfrag = sapt_dimer.nfragments()
if nfrag != 2:
raise ValidationError('SAPT requires active molecule to have 2 fragments, not %s.' % (nfrag))
monomerA = sapt_dimer.extract_subsets(1, 2)
monomerA.set_name('monomerA')
monomerB = sapt_dimer.extract_subsets(2, 1)
monomerB.set_name('monomerB')
sapt_dimer.update_geometry()
monomerAm = sapt_dimer.extract_subsets(1)
monomerAm.set_name('monomerAm')
monomerBm = sapt_dimer.extract_subsets(2)
monomerBm.set_name('monomerBm')
ri = psi4.get_option('SCF', 'SCF_TYPE')
df_ints_io = psi4.get_option('SCF', 'DF_INTS_IO')
# inquire if above at all applies to dfmp2
psi4.IO.set_default_namespace('dimer')
psi4.print_out('\n')
p4util.banner('Dimer HF')
psi4.print_out('\n')
psi4.set_global_option('DF_INTS_IO', 'SAVE')
dimer_wfn = scf_helper('RHF', molecule=sapt_dimer, **kwargs)
psi4.set_global_option('DF_INTS_IO', 'LOAD')
if (ri == 'DF'):
psi4.IO.change_file_namespace(97, 'dimer', 'monomerA')
psi4.IO.set_default_namespace('monomerA')
psi4.print_out('\n')
p4util.banner('Monomer A HF (Dimer Basis)')
psi4.print_out('\n')
monomerA_wfn = scf_helper('RHF', molecule=monomerA, **kwargs)
if (ri == 'DF'):
psi4.IO.change_file_namespace(97, 'monomerA', 'monomerB')
psi4.IO.set_default_namespace('monomerB')
psi4.print_out('\n')
p4util.banner('Monomer B HF (Dimer Basis)')
psi4.print_out('\n')
monomerB_wfn = scf_helper('RHF', molecule=monomerB, **kwargs)
psi4.set_global_option('DF_INTS_IO', df_ints_io)
psi4.IO.set_default_namespace('monomerAm')
psi4.print_out('\n')
p4util.banner('Monomer A HF (Monomer Basis)')
psi4.print_out('\n')
monomerAm_wfn = scf_helper('RHF', molecule=monomerAm, **kwargs)
psi4.IO.set_default_namespace('monomerBm')
psi4.print_out('\n')
p4util.banner('Monomer B HF (Monomer Basis)')
psi4.print_out('\n')
monomerBm_wfn = scf_helper('RHF', molecule=monomerBm, **kwargs)
psi4.IO.set_default_namespace('dimer')
psi4.set_local_option('SAPT', 'E_CONVERGENCE', 10e-10)
psi4.set_local_option('SAPT', 'D_CONVERGENCE', 10e-10)
if name == 'sapt0-ct':
psi4.set_local_option('SAPT', 'SAPT_LEVEL', 'SAPT0')
elif name == 'sapt2-ct':
psi4.set_local_option('SAPT', 'SAPT_LEVEL', 'SAPT2')
elif name == 'sapt2+-ct':
psi4.set_local_option('SAPT', 'SAPT_LEVEL', 'SAPT2+')
elif name == 'sapt2+(3)-ct':
psi4.set_local_option('SAPT', 'SAPT_LEVEL', 'SAPT2+3')
psi4.set_local_option('SAPT', 'DO_THIRD_ORDER', False)
elif name == 'sapt2+3-ct':
psi4.set_local_option('SAPT', 'SAPT_LEVEL', 'SAPT2+3')
psi4.set_local_option('SAPT', 'DO_THIRD_ORDER', True)
elif name == 'sapt2+(ccd)-ct':
psi4.set_local_option('SAPT', 'SAPT_LEVEL', 'SAPT2+')
psi4.set_local_option('SAPT', 'DO_CCD_DISP', True)
elif name == 'sapt2+(3)(ccd)-ct':
psi4.set_local_option('SAPT', 'SAPT_LEVEL', 'SAPT2+3')
psi4.set_local_option('SAPT', 'DO_THIRD_ORDER', False)
psi4.set_local_option('SAPT', 'DO_CCD_DISP', True)
elif name == 'sapt2+3(ccd)-ct':
psi4.set_local_option('SAPT', 'SAPT_LEVEL', 'SAPT2+3')
psi4.set_local_option('SAPT', 'DO_THIRD_ORDER', True)
psi4.set_local_option('SAPT', 'DO_CCD_DISP', True)
psi4.print_out('\n')
p4util.banner('SAPT Charge Transfer')
psi4.print_out('\n')
psi4.print_out('\n')
p4util.banner('Dimer Basis SAPT')
psi4.print_out('\n')
psi4.IO.change_file_namespace(p4const.PSIF_SAPT_MONOMERA, 'monomerA', 'dimer')
psi4.IO.change_file_namespace(p4const.PSIF_SAPT_MONOMERB, 'monomerB', 'dimer')
e_sapt = psi4.sapt(dimer_wfn, monomerA_wfn, monomerB_wfn)
CTd = psi4.get_variable('SAPT CT ENERGY')
psi4.print_out('\n')
p4util.banner('Monomer Basis SAPT')
psi4.print_out('\n')
psi4.IO.change_file_namespace(p4const.PSIF_SAPT_MONOMERA, 'monomerAm', 'dimer')
psi4.IO.change_file_namespace(p4const.PSIF_SAPT_MONOMERB, 'monomerBm', 'dimer')
e_sapt = psi4.sapt(dimer_wfn, monomerAm_wfn, monomerBm_wfn)
CTm = psi4.get_variable('SAPT CT ENERGY')
CT = CTd - CTm
units = (1000.0, p4const.psi_hartree2kcalmol, p4const.psi_hartree2kJmol)
psi4.print_out('\n\n')
psi4.print_out(' SAPT Charge Transfer Analysis\n')
psi4.print_out(' ------------------------------------------------------------------------------------------------\n')
psi4.print_out(' SAPT Induction (Dimer Basis) %12.4lf [mEh] %12.4lf [kcal/mol] %12.4lf [kJ/mol]\n' %
tuple(CTd * u for u in units))
psi4.print_out(' SAPT Induction (Monomer Basis)%12.4lf [mEh] %12.4lf [kcal/mol] %12.4lf [kJ/mol]\n' %
tuple(CTm * u for u in units))
psi4.print_out(' SAPT Charge Transfer %12.4lf [mEh] %12.4lf [kcal/mol] %12.4lf [kJ/mol]\n\n' %
tuple(CT * u for u in units))
psi4.set_variable('SAPT CT ENERGY', CT)
optstash.restore()
return dimer_wfn
[docs]def run_fisapt(name, **kwargs):
"""Function encoding sequence of PSI module calls for
an F/ISAPT0 computation
"""
optstash = p4util.OptionsState(
['SCF', 'SCF_TYPE'])
# Alter default algorithm
if not psi4.has_option_changed('SCF', 'SCF_TYPE'):
psi4.set_local_option('SCF', 'SCF_TYPE', 'DF')
# Get the molecule of interest
ref_wfn = kwargs.get('ref_wfn', None)
if ref_wfn is None:
sapt_dimer = kwargs.pop('molecule', psi4.get_active_molecule())
else:
psi4.print_out('Warning! FISAPT argument "ref_wfn" is only able to use molecule information.')
sapt_dimer = ref_wfn.molecule()
sapt_dimer.update_geometry() # make sure since mol from wfn, kwarg, or P::e
# Shifting to C1 so we need to copy the active molecule
if sapt_dimer.schoenflies_symbol() != 'c1':
psi4.print_out(' FISAPT does not make use of molecular symmetry, further calculations in C1 point group.\n')
sapt_dimer = sapt_dimer.clone()
sapt_dimer.reset_point_group('c1')
sapt_dimer.fix_orientation(True)
sapt_dimer.fix_com(True)
sapt_dimer.update_geometry()
if psi4.get_option('SCF', 'REFERENCE') != 'RHF':
raise ValidationError('FISAPT requires requires \"reference rhf\".')
if ref_wfn is None:
ref_wfn = scf_helper('RHF', molecule=sapt_dimer, **kwargs)
fisapt_wfn = psi4.fisapt(ref_wfn)
optstash.restore()
return fisapt_wfn
[docs]def run_mrcc(name, **kwargs):
"""Function that prepares environment and input files
for a calculation calling Kallay's MRCC code.
"""
# Check to see if we really need to run the SCF code.
ref_wfn = kwargs.get('ref_wfn', None)
if ref_wfn is None:
ref_wfn = scf_helper(name, **kwargs)
vscf = psi4.get_variable('SCF TOTAL ENERGY')
# The parse_arbitrary_order method provides us the following information
# We require that level be provided. level is a dictionary
# of settings to be passed to psi4.mrcc
if not('level' in kwargs):
raise ValidationError('level parameter was not provided.')
level = kwargs['level']
# Fullname is the string we need to search for in iface
fullname = level['fullname']
# User can provide 'keep' to the method.
# When provided, do not delete the MRCC scratch directory.
keep = False
if 'keep' in kwargs:
keep = kwargs['keep']
# Save current directory location
current_directory = os.getcwd()
# Find environment by merging PSIPATH and PATH environment variables
lenv = {
'PATH': ':'.join([os.path.abspath(x) for x in os.environ.get('PSIPATH', '').split(':') if x != '']) + \
':' + os.environ.get('PATH'),
'LD_LIBRARY_PATH': os.environ.get('LD_LIBRARY_PATH')
}
# Filter out None values as subprocess will fault on them
lenv = {k: v for k, v in lenv.items() if v is not None}
# Need to move to the scratch directory, perferrably into a separate directory in that location
psi_io = psi4.IOManager.shared_object()
os.chdir(psi_io.get_default_path())
# Make new directory specifically for mrcc
mrcc_tmpdir = 'mrcc_' + str(os.getpid())
if 'path' in kwargs:
mrcc_tmpdir = kwargs['path']
# Check to see if directory already exists, if not, create.
if os.path.exists(mrcc_tmpdir) is False:
os.mkdir(mrcc_tmpdir)
# Move into the new directory
os.chdir(mrcc_tmpdir)
# Generate integrals and input file (dumps files to the current directory)
psi4.mrcc_generate_input(ref_wfn, level)
# Load the fort.56 file
# and dump a copy into the outfile
psi4.print_out('\n===== Begin fort.56 input for MRCC ======\n')
psi4.print_out(open('fort.56', 'r').read())
psi4.print_out('===== End fort.56 input for MRCC ======\n')
# Close psi4 output file and reopen with filehandle
psi4.close_outfile()
pathfill = '' if os.path.isabs(psi4.outfile_name()) else current_directory + os.path.sep
p4out = open(pathfill + psi4.outfile_name(), 'a')
# Modify the environment:
# PGI Fortan prints warning to screen if STOP is used
os.environ['NO_STOP_MESSAGE'] = '1'
# Obtain user's OMP_NUM_THREADS so that we don't blow it away.
omp_num_threads_found = 'OMP_NUM_THREADS' in os.environ
if omp_num_threads_found == True:
omp_num_threads_user = os.environ['OMP_NUM_THREADS']
# If the user provided MRCC_OMP_NUM_THREADS set the environ to it
if psi4.has_option_changed('MRCC', 'MRCC_OMP_NUM_THREADS') == True:
os.environ['OMP_NUM_THREADS'] = str(psi4.get_option('MRCC', 'MRCC_OMP_NUM_THREADS'))
# Call dmrcc, directing all screen output to the output file
external_exe = 'dmrcc'
try:
retcode = subprocess.Popen([external_exe], bufsize=0, stdout=subprocess.PIPE, env=lenv)
except OSError as e:
sys.stderr.write('Program %s not found in path or execution failed: %s\n' % (cfour_executable, e.strerror))
p4out.write('Program %s not found in path or execution failed: %s\n' % (external_exe, e.strerror))
message = ("Program %s not found in path or execution failed: %s\n" % (external_exe, e.strerror))
raise ValidationError(message)
c4out = ''
while True:
data = retcode.stdout.readline()
if not data:
break
if psi4.outfile_name() == 'stdout':
sys.stdout.write(data)
else:
p4out.write(data)
p4out.flush()
c4out += data
# try:
# if psi4.outfile_name() == 'stdout':
# retcode = subprocess.call('dmrcc', shell=True, env=lenv)
# else:
# retcode = subprocess.call('dmrcc >> ' + current_directory + '/' + psi4.outfile_name(), shell=True, env=lenv)
#
# if retcode < 0:
# print('MRCC was terminated by signal %d' % -retcode, file=sys.stderr)
# exit(1)
# elif retcode > 0:
# print('MRCC errored %d' % retcode, file=sys.stderr)
# exit(1)
#
# except OSError as e:
# print('Execution failed: %s' % e, file=sys.stderr)
# exit(1)
# Restore the OMP_NUM_THREADS that the user set.
if omp_num_threads_found == True:
if psi4.has_option_changed('MRCC', 'MRCC_OMP_NUM_THREADS') == True:
os.environ['OMP_NUM_THREADS'] = omp_num_threads_user
# Scan iface file and grab the file energy.
ene = 0.0
for line in open('iface'):
fields = line.split()
m = fields[1]
try:
ene = float(fields[5])
if m == "MP(2)":
m = "MP2"
psi4.set_variable(m + ' TOTAL ENERGY', ene)
psi4.set_variable(m + ' CORRELATION ENERGY', ene - vscf)
except ValueError:
continue
# The last 'ene' in iface is the one the user requested.
psi4.set_variable('CURRENT ENERGY', ene)
psi4.set_variable('CURRENT CORRELATION ENERGY', ene - vscf)
# Load the iface file
iface = open('iface', 'r')
iface_contents = iface.read()
# Delete mrcc tempdir
os.chdir('..')
try:
# Delete unless we're told not to
if (keep is False and not('path' in kwargs)):
shutil.rmtree(mrcc_tmpdir)
except OSError as e:
print('Unable to remove MRCC temporary directory %s' % e, file=sys.stderr)
exit(1)
# Return to submission directory and reopen output file
os.chdir(current_directory)
p4out.close()
psi4.reopen_outfile()
# If we're told to keep the files or the user provided a path, do nothing.
if (keep != False or ('path' in kwargs)):
psi4.print_out('\nMRCC scratch files have been kept.\n')
psi4.print_out('They can be found in ' + mrcc_tmpdir)
# Dump iface contents to output
psi4.print_out('\n')
p4util.banner('Full results from MRCC')
psi4.print_out('\n')
psi4.print_out(iface_contents)
return ref_wfn
[docs]def run_fnodfcc(name, **kwargs):
"""Function encoding sequence of PSI module calls for
a DF-CCSD(T) computation.
>>> set cc_type df
>>> energy('fno-ccsd(t)')
"""
kwargs = p4util.kwargs_lower(kwargs)
# stash user options
optstash = p4util.OptionsState(
['FNOCC', 'COMPUTE_TRIPLES'],
['FNOCC', 'DFCC'],
['FNOCC', 'NAT_ORBS'],
['FNOCC', 'RUN_CEPA'],
['FNOCC', 'DF_BASIS_CC'],
['SCF', 'DF_BASIS_SCF'],
['SCF', 'DF_INTS_IO'],
['SCF', 'SCF_TYPE'])
psi4.set_local_option('FNOCC', 'DFCC', True)
psi4.set_local_option('FNOCC', 'RUN_CEPA', False)
# throw an exception for open-shells
if psi4.get_option('SCF', 'REFERENCE') != 'RHF':
raise ValidationError("""Error: %s requires 'reference rhf'.""" % name)
def set_cholesky_from(mtd_type):
type_val = psi4.get_global_option(mtd_type)
if type_val == 'CD':
psi4.set_local_option('FNOCC', 'DF_BASIS_CC', 'CHOLESKY')
# Alter default algorithm
if not psi4.has_option_changed('SCF', 'SCF_TYPE'):
psi4.set_global_option('SCF_TYPE', 'CD')
psi4.print_out(""" SCF Algorithm Type (re)set to CD.\n""")
elif type_val == 'DF':
if psi4.get_option('FNOCC', 'DF_BASIS_CC') == 'CHOLESKY':
psi4.set_local_option('FNOCC', 'DF_BASIS_CC', '')
# Alter default algorithm
if not psi4.has_option_changed('SCF', 'SCF_TYPE'):
psi4.set_global_option('SCF_TYPE', 'DF')
psi4.print_out(""" SCF Algorithm Type (re)set to DF.\n""")
else:
raise ValidationError("""Invalid type '%s' for DFCC""" % type_val)
# triples?
if name == 'ccsd':
psi4.set_local_option('FNOCC', 'COMPUTE_TRIPLES', False)
set_cholesky_from('CC_TYPE')
elif name == 'ccsd(t)':
psi4.set_local_option('FNOCC', 'COMPUTE_TRIPLES', True)
set_cholesky_from('CC_TYPE')
elif name == 'fno-ccsd':
psi4.set_local_option('FNOCC', 'COMPUTE_TRIPLES', False)
psi4.set_local_option('FNOCC', 'NAT_ORBS', True)
set_cholesky_from('CC_TYPE')
elif name == 'fno-ccsd(t)':
psi4.set_local_option('FNOCC', 'COMPUTE_TRIPLES', True)
psi4.set_local_option('FNOCC', 'NAT_ORBS', True)
set_cholesky_from('CC_TYPE')
if psi4.get_option('SCF', 'SCF_TYPE') not in ['CD', 'DF']:
raise ValidationError("""Invalid scf_type for DFCC.""")
# save DF or CD ints generated by SCF for use in CC
psi4.set_local_option('SCF', 'DF_INTS_IO', 'SAVE')
ref_wfn = kwargs.get('ref_wfn', None)
if ref_wfn is None:
ref_wfn = scf_helper(name, use_c1=True, **kwargs) # C1 certified
else:
if ref_wfn.molecule().schoenflies_symbol() != 'c1':
raise ValidationError(""" FNOCC does not make use of molecular symmetry: """
"""reference wavefunction must be C1.\n""")
fnocc_wfn = psi4.fnocc(ref_wfn)
optstash.restore()
return fnocc_wfn
[docs]def run_fnocc(name, **kwargs):
"""Function encoding sequence of PSI module calls for
a QCISD(T), CCSD(T), MP2.5, MP3, and MP4 computation.
>>> energy('fno-ccsd(t)')
"""
kwargs = p4util.kwargs_lower(kwargs)
level = kwargs.get('level', 0)
# stash user options:
optstash = p4util.OptionsState(
['TRANSQT2', 'WFN'],
['FNOCC', 'RUN_MP2'],
['FNOCC', 'RUN_MP3'],
['FNOCC', 'RUN_MP4'],
['FNOCC', 'RUN_CCSD'],
['FNOCC', 'COMPUTE_TRIPLES'],
['FNOCC', 'COMPUTE_MP4_TRIPLES'],
['FNOCC', 'DFCC'],
['FNOCC', 'RUN_CEPA'],
['FNOCC', 'USE_DF_INTS'],
['FNOCC', 'NAT_ORBS'])
psi4.set_local_option('FNOCC', 'DFCC', False)
psi4.set_local_option('FNOCC', 'RUN_CEPA', False)
psi4.set_local_option('FNOCC', 'USE_DF_INTS', False)
# which method?
if name == 'ccsd':
psi4.set_local_option('FNOCC', 'COMPUTE_TRIPLES', False)
psi4.set_local_option('FNOCC', 'RUN_CCSD', True)
elif name == 'ccsd(t)':
psi4.set_local_option('FNOCC', 'COMPUTE_TRIPLES', True)
psi4.set_local_option('FNOCC', 'RUN_CCSD', True)
elif name == 'fno-ccsd':
psi4.set_local_option('FNOCC', 'COMPUTE_TRIPLES', False)
psi4.set_local_option('FNOCC', 'RUN_CCSD', True)
psi4.set_local_option('FNOCC', 'NAT_ORBS', True)
elif name == 'fno-ccsd(t)':
psi4.set_local_option('FNOCC', 'COMPUTE_TRIPLES', True)
psi4.set_local_option('FNOCC', 'RUN_CCSD', True)
psi4.set_local_option('FNOCC', 'NAT_ORBS', True)
elif name == 'qcisd':
psi4.set_local_option('FNOCC', 'COMPUTE_TRIPLES', False)
psi4.set_local_option('FNOCC', 'RUN_CCSD', False)
elif name == 'qcisd(t)':
psi4.set_local_option('FNOCC', 'COMPUTE_TRIPLES', True)
psi4.set_local_option('FNOCC', 'RUN_CCSD', False)
elif name == 'fno-qcisd':
psi4.set_local_option('FNOCC', 'COMPUTE_TRIPLES', False)
psi4.set_local_option('FNOCC', 'RUN_CCSD', False)
psi4.set_local_option('FNOCC', 'NAT_ORBS', True)
elif name == 'fno-qcisd(t)':
psi4.set_local_option('FNOCC', 'COMPUTE_TRIPLES', True)
psi4.set_local_option('FNOCC', 'NAT_ORBS', True)
psi4.set_local_option('FNOCC', 'RUN_CCSD', False)
elif name == 'mp2':
psi4.set_local_option('FNOCC', 'RUN_MP2', True)
elif name == 'fno-mp3':
psi4.set_local_option('FNOCC', 'RUN_MP3', True)
psi4.set_local_option('FNOCC', 'NAT_ORBS', True)
elif name == 'fno-mp4':
psi4.set_local_option('FNOCC', 'RUN_MP4', True)
psi4.set_local_option('FNOCC', 'COMPUTE_MP4_TRIPLES', True)
psi4.set_local_option('FNOCC', 'COMPUTE_TRIPLES', True)
psi4.set_local_option('FNOCC', 'NAT_ORBS', True)
elif name == 'mp4(sdq)':
psi4.set_local_option('FNOCC', 'RUN_MP4', True)
psi4.set_local_option('FNOCC', 'COMPUTE_MP4_TRIPLES', False)
psi4.set_local_option('FNOCC', 'COMPUTE_TRIPLES', False)
elif name == 'fno-mp4(sdq)':
psi4.set_local_option('FNOCC', 'RUN_MP4', True)
psi4.set_local_option('FNOCC', 'COMPUTE_MP4_TRIPLES', False)
psi4.set_local_option('FNOCC', 'COMPUTE_TRIPLES', False)
psi4.set_local_option('FNOCC', 'NAT_ORBS', True)
elif name == 'mp3':
psi4.set_local_option('FNOCC', 'RUN_MP3', True)
elif name == 'mp4':
psi4.set_local_option('FNOCC', 'RUN_MP4', True)
psi4.set_local_option('FNOCC', 'COMPUTE_MP4_TRIPLES', True)
psi4.set_local_option('FNOCC', 'COMPUTE_TRIPLES', True)
# throw an exception for open-shells
if psi4.get_option('SCF', 'REFERENCE') != 'RHF':
raise ValidationError("""Error: %s requires 'reference rhf'.""" % name)
# Bypass the scf call if a reference wavefunction is given
ref_wfn = kwargs.get('ref_wfn', None)
if ref_wfn is None:
ref_wfn = scf_helper(name, **kwargs) # C1 certified
if psi4.get_option('FNOCC', 'USE_DF_INTS') == False:
# Ensure IWL files have been written
proc_util.check_iwl_file_from_scf_type(psi4.get_option('SCF', 'SCF_TYPE'), ref_wfn)
fnocc_wfn = psi4.fnocc(ref_wfn)
# set current correlation energy and total energy. only need to treat mpn here.
if name == 'mp3':
emp3 = psi4.get_variable("MP3 TOTAL ENERGY")
cemp3 = psi4.get_variable("MP3 CORRELATION ENERGY")
psi4.set_variable("CURRENT ENERGY", emp3)
psi4.set_variable("CURRENT CORRELATION ENERGY", cemp3)
elif name == 'fno-mp3':
emp3 = psi4.get_variable("MP3 TOTAL ENERGY")
cemp3 = psi4.get_variable("MP3 CORRELATION ENERGY")
psi4.set_variable("CURRENT ENERGY", emp3)
psi4.set_variable("CURRENT CORRELATION ENERGY", cemp3)
elif name == 'mp4(sdq)':
emp4sdq = psi4.get_variable("MP4(SDQ) TOTAL ENERGY")
cemp4sdq = psi4.get_variable("MP4(SDQ) CORRELATION ENERGY")
psi4.set_variable("CURRENT ENERGY", emp4sdq)
psi4.set_variable("CURRENT CORRELATION ENERGY", cemp4sdq)
elif name == 'fno-mp4(sdq)':
emp4sdq = psi4.get_variable("MP4(SDQ) TOTAL ENERGY")
cemp4sdq = psi4.get_variable("MP4(SDQ) CORRELATION ENERGY")
psi4.set_variable("CURRENT ENERGY", emp4sdq)
psi4.set_variable("CURRENT CORRELATION ENERGY", cemp4sdq)
elif name == 'fno-mp4':
emp4 = psi4.get_variable("MP4 TOTAL ENERGY")
cemp4 = psi4.get_variable("MP4 CORRELATION ENERGY")
psi4.set_variable("CURRENT ENERGY", emp4)
psi4.set_variable("CURRENT CORRELATION ENERGY", cemp4)
elif name == 'mp4':
emp4 = psi4.get_variable("MP4 TOTAL ENERGY")
cemp4 = psi4.get_variable("MP4 CORRELATION ENERGY")
psi4.set_variable("CURRENT ENERGY", emp4)
psi4.set_variable("CURRENT CORRELATION ENERGY", cemp4)
optstash.restore()
return fnocc_wfn
[docs]def run_cepa(name, **kwargs):
"""Function encoding sequence of PSI module calls for
a cepa-like calculation.
>>> energy('cepa(1)')
"""
kwargs = p4util.kwargs_lower(kwargs)
# save user options
optstash = p4util.OptionsState(
['TRANSQT2', 'WFN'],
['FNOCC', 'NAT_ORBS'],
['FNOCC', 'RUN_CEPA'],
['FNOCC', 'USE_DF_INTS'],
['FNOCC', 'CEPA_NO_SINGLES'])
psi4.set_local_option('FNOCC', 'RUN_CEPA', True)
psi4.set_local_option('FNOCC', 'USE_DF_INTS', False)
# what type of cepa?
if name in ['lccd', 'fno-lccd']:
cepa_level = 'cepa(0)'
psi4.set_local_option('FNOCC', 'CEPA_NO_SINGLES', True)
elif name in ['cepa(0)', 'fno-cepa(0)', 'lccsd', 'fno-lccsd']:
cepa_level = 'cepa(0)'
psi4.set_local_option('FNOCC', 'CEPA_NO_SINGLES', False)
elif name in ['cepa(1)', 'fno-cepa(1)']:
cepa_level = 'cepa(1)'
elif name in ['cepa(3)', 'fno-cepa(3)']:
cepa_level = 'cepa(3)'
elif name in ['acpf', 'fno-acpf']:
cepa_level = 'acpf'
elif name in ['aqcc', 'fno-aqcc']:
cepa_level = 'aqcc'
elif name in ['cisd', 'fno-cisd']:
cepa_level = 'cisd'
else:
raise ValidationError("""Error: %s not implemented\n""" % name)
psi4.set_local_option('FNOCC', 'CEPA_LEVEL', cepa_level.upper())
if name in ['fno-lccd', 'fno-lccsd', 'fno-cepa(0)', 'fno-cepa(1)', 'fno-cepa(3)',
'fno-acpf', 'fno-aqcc', 'fno-cisd']:
psi4.set_local_option('FNOCC', 'NAT_ORBS', True)
# throw an exception for open-shells
if psi4.get_option('SCF', 'REFERENCE') != 'RHF':
raise ValidationError("""Error: %s requires 'reference rhf'.""" % name)
ref_wfn = kwargs.get('ref_wfn', None)
if ref_wfn is None:
ref_wfn = scf_helper(name, **kwargs) # C1 certified
if psi4.get_option('FNOCC', 'USE_DF_INTS') == False:
# Ensure IWL files have been written
proc_util.check_iwl_file_from_scf_type(psi4.get_option('SCF', 'SCF_TYPE'), ref_wfn)
fnocc_wfn = psi4.fnocc(ref_wfn)
# one-electron properties
if psi4.get_option('FNOCC', 'DIPMOM'):
if cepa_level in ['cepa(1)', 'cepa(3)']:
psi4.print_out("""\n Error: one-electron properties not implemented for %s\n\n""" % name)
elif psi4.get_option('FNOCC', 'NAT_ORBS'):
psi4.print_out("""\n Error: one-electron properties not implemented for %s\n\n""" % name)
else:
p4util.oeprop(fnocc_wfn, 'DIPOLE', 'QUADRUPOLE', 'MULLIKEN_CHARGES', 'NO_OCCUPATIONS', title=cepa_level.upper())
optstash.restore()
return fnocc_wfn
[docs]def run_detcas(name, **kwargs):
"""Function encoding sequence of PSI module calls for
determinant-based multireference wavefuncations,
namely CASSCF and RASSCF.
"""
optstash = p4util.OptionsState(
['DETCI', 'WFN'],
['SCF', 'SCF_TYPE']
)
user_ref = psi4.get_option('DETCI', 'REFERENCE')
if user_ref not in ['RHF', 'ROHF']:
raise ValidationError('Reference %s for DETCI is not available.' % user_ref)
if name == 'rasscf':
psi4.set_local_option('DETCI', 'WFN', 'RASSCF')
elif name == 'casscf':
psi4.set_local_option('DETCI', 'WFN', 'CASSCF')
else:
raise ValidationError("Run DETCAS: Name %s not understood" % name)
ref_wfn = kwargs.get('ref_wfn', None)
if ref_wfn is None:
ref_wfn = scf_helper(name, **kwargs) # C1 certified
molecule = ref_wfn.molecule()
# The DF case
if psi4.get_option('DETCI', 'MCSCF_TYPE') == 'DF':
# Do NOT set global options in general, this is a bit of a hack
if not psi4.has_option_changed('SCF', 'SCF_TYPE'):
psi4.set_global_option('SCF_TYPE', 'DF')
# The non-DF case
else:
if not psi4.has_option_changed('SCF', 'SCF_TYPE'):
psi4.set_global_option('SCF_TYPE', 'PK')
# Ensure IWL files have been written
proc_util.check_iwl_file_from_scf_type(psi4.get_option('SCF', 'SCF_TYPE'), ref_wfn)
# Second-order SCF requires non-symmetric density matrix support
if psi4.get_option('DETCI', 'MCSCF_SO'):
proc_util.check_non_symmetric_jk_density("Second-order MCSCF")
ciwfn = psi4.detci(ref_wfn)
# We always would like to print a little dipole information
oeprop = psi4.OEProp(ciwfn)
oeprop.set_title(name.upper())
oeprop.add("DIPOLE")
oeprop.compute()
psi4.set_variable("CURRENT DIPOLE X", psi4.get_variable(name.upper() + " DIPOLE X"))
psi4.set_variable("CURRENT DIPOLE Y", psi4.get_variable(name.upper() + " DIPOLE Y"))
psi4.set_variable("CURRENT DIPOLE Z", psi4.get_variable(name.upper() + " DIPOLE Z"))
optstash.restore()
return ciwfn
[docs]def run_efp(name, **kwargs):
"""Function encoding sequence of module calls for a pure EFP
computation (ignore any QM atoms).
"""
# initialize library
efp = psi4.get_active_efp()
if efp.nfragments() == 0:
raise ValidationError("""Method 'efp' not available without EFP fragments in molecule""")
# set options
psi4.set_global_option('QMEFP', False) # apt to go haywire if set locally to efp
psi4.efp_set_options()
efp.print_out()
returnvalue = efp.compute()
return returnvalue