├── .codecov.yml
├── .gitattributes
├── .github
└── workflows
│ └── CI.yml
├── .gitignore
├── .readthedocs.yaml
├── LICENSE
├── MANIFEST.in
├── Makefile
├── README.rst
├── devtools
├── conda-envs
│ ├── base.yaml
│ ├── dev.yaml
│ └── docs.yaml
├── scripts
│ ├── conda_env.py
│ └── dev_conda_env.py
└── travis-ci
│ └── before_install.sh
├── docs
├── Makefile
├── readme.md
└── source
│ ├── algorithms.rst
│ ├── api.rst
│ ├── conf.py
│ ├── convergence.rst
│ ├── coords.rst
│ ├── index.rst
│ ├── molecule.rst
│ ├── optimizations.rst
│ └── options.rst
├── media
├── optking.jpeg
└── s8.png
├── optking
├── IRCdata.py
├── IRCfollowing.py
├── __init__.py
├── _version.py
├── addIntcos.py
├── bend.py
├── cart.py
├── caseInsensitiveDict.py
├── compute_wrappers.py
├── convcheck.py
├── dimerfrag.py
├── displace.py
├── exceptions.py
├── frag.py
├── hessian.py
├── history.py
├── intcosMisc.py
├── linearAlgebra.py
├── linesearch.py
├── lj_functions.py
├── loggingconfig.py
├── misc.py
├── molsys.py
├── oofp.py
├── opt_helper.py
├── optimize.py
├── optparams.py
├── optwrapper.py
├── orient.py
├── printTools.py
├── simple.py
├── stepAlgorithms.py
├── stre.py
├── testB.py
├── tests
│ ├── __init__.py
│ ├── ch3chch2cl.in
│ ├── conftest.py
│ ├── dimer_benzene_jupyter_demo.ipynb
│ ├── json_betapinene.json
│ ├── json_h2o.json
│ ├── json_hooh_frozen.json
│ ├── json_lif_cp.json
│ ├── json_lif_nocp.json
│ ├── psi4_helper.py
│ ├── psi4inputs
│ │ ├── __init__.py
│ │ ├── psiAPIversions
│ │ │ ├── __init__.py
│ │ │ ├── dimer-h2o-c6h6.py
│ │ │ ├── dimer-h2o.py
│ │ │ ├── dimer-ne2.py
│ │ │ └── froz-dimer-h2o.py
│ │ └── psithon_versions
│ │ │ ├── b3lyp-g-phenylacetylene.in
│ │ │ ├── ccsd-g-ch2.in
│ │ │ ├── ccsd-g-h2o.in
│ │ │ ├── dcft-g-o2.in
│ │ │ ├── hf-e-h2o.in
│ │ │ ├── hf-g-SF4-breaksLinear.in
│ │ │ ├── hf-g-alleneLinear.in
│ │ │ ├── hf-g-alleneNonlinear.in
│ │ │ ├── hf-g-h2o-freq.in
│ │ │ ├── hf-g-h2o-frozenCart.in
│ │ │ ├── hf-g-h2o-large.in
│ │ │ ├── hf-g-h2o-test-maxiter.in
│ │ │ ├── hf-g-h2o-tight.in
│ │ │ ├── hf-g-h2o.in
│ │ │ ├── hf-g-hooh-fixed-3.in
│ │ │ ├── hf-g-hooh-frozen-3.in
│ │ │ ├── hf-g-hooh-frozenCart-2.in
│ │ │ ├── hf-g-hooh-frozenCartInCarts-3.in
│ │ │ ├── hf-g-ketene-bent.in
│ │ │ ├── mp2-g-h2o.in
│ │ │ ├── scsomp2-g-h2o.in
│ │ │ ├── scsomp3-g-h2o.in
│ │ │ ├── sosomp2-g-h2o.in
│ │ │ ├── sosomp3-g-h2o.in
│ │ │ ├── todo-psi4tests.txt
│ │ │ ├── ts-hf-g-hooh-2.in
│ │ │ ├── uccsd-g-ch2.in
│ │ │ ├── uccsdpt-g-ch2.in
│ │ │ └── uhf-g-ch2-dummy.in
│ ├── test_2_hessians.py
│ ├── test_atom.py
│ ├── test_atom_stepwise.py
│ ├── test_auxiliary_bonds.py
│ ├── test_ccsd_g_opt.py
│ ├── test_conjugate.py
│ ├── test_dcft_g_opt.py
│ ├── test_deriv_transforms.py
│ ├── test_dimers_Bmat.py
│ ├── test_dimers_benzene_pes.py
│ ├── test_dimers_h2o.py
│ ├── test_dimers_mt_tyr_Rscan.py
│ ├── test_dimers_mt_tyr_frozen_orientation.py
│ ├── test_dimers_ne2.py
│ ├── test_dimers_orient.py
│ ├── test_frozen_cart_and_backstep.py
│ ├── test_frozen_internals.py
│ ├── test_g_convergence.py
│ ├── test_hbond.py
│ ├── test_hf_g_keywords.py
│ ├── test_hf_g_opt.py
│ ├── test_hooh_ext_force.py
│ ├── test_irc_hooh.py
│ ├── test_jsoninput.py
│ ├── test_linesearch.py
│ ├── test_lj.py
│ ├── test_methimazole.py
│ ├── test_mp2_g_opt.py
│ ├── test_nearlinear_dft_opt.py
│ ├── test_oofp.py
│ ├── test_openshell.py
│ ├── test_opt2_allene.py
│ ├── test_opt5-ch2.py
│ ├── test_opthelper.py
│ ├── test_optimization_input.py
│ ├── test_ranged_internals.py
│ ├── test_scsmp2_opt.py
│ ├── test_sf4_quasilinear.py
│ ├── test_step_types.py
│ ├── test_trimers_h2o.py
│ ├── test_ts_opt.py
│ └── utils
│ │ ├── __init__.py
│ │ └── utils.py
├── tors.py
└── v3d.py
├── setup.cfg
├── setup.py
└── versioneer.py
/.codecov.yml:
--------------------------------------------------------------------------------
1 | coverage:
2 | status:
3 | patch: false
4 | project:
5 | default:
6 | threshold: 50%
7 | ignore:
8 | - "tests/.*"
9 | - "setup.py"
10 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | optking/_version.py export-subst
2 |
--------------------------------------------------------------------------------
/.github/workflows/CI.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on: [push, pull_request]
4 |
5 | jobs:
6 | build:
7 |
8 | # prevent actions from running on both the push to the PR and PR
9 | # only run actions on PRs originating from a fork
10 | if:
11 | github.event_name == 'push' || github.event.pull_request.head.repo.full_name !=
12 | github.repository
13 |
14 | runs-on: ubuntu-latest
15 | strategy:
16 | fail-fast: false
17 | matrix:
18 | cfg:
19 | - conda-env: base
20 | python-version: 3.8
21 | - conda-env: base
22 | python-version: 3.9
23 | - conda-env: base
24 | python-version: "3.10"
25 | - conda-env: base
26 | python-version: "3.12"
27 | env:
28 | PYVER: ${{ matrix.cfg.python-version }}
29 | CONDA_ENV: ${{ matrix.cfg.conda-env }}
30 |
31 | steps:
32 | - uses: actions/checkout@v2
33 |
34 | - name: Create Environment
35 | uses: conda-incubator/setup-miniconda@v2
36 | with:
37 | installer-url: https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh
38 | activate-environment: test
39 | environment-file: devtools/conda-envs/${{ matrix.cfg.conda-env }}.yaml
40 | python-version: ${{ matrix.cfg.python-version }}
41 | auto-activate-base: false
42 |
43 | - name: Setup Information
44 | shell: bash -l {0}
45 | run: |
46 | uname -a
47 | df -h
48 | ulimit -a
49 | echo $CONDA
50 | echo $(which conda)
51 | conda --version
52 |
53 | - name: Install
54 | shell: bash -l {0}
55 | run: |
56 | python -m pip install . --no-deps
57 | - name: Environment Information
58 | shell: bash -l {0}
59 | run: |
60 | conda list --show-channel-urls
61 | - name: PyTest
62 | shell: bash -l {0}
63 | run: |
64 | pytest -rws -v -m "not long" --cov=optking --color=yes --cov-report=xml optking/
65 | - name: CodeCov
66 | uses: codecov/codecov-action@v4
67 | with:
68 | token: ${{ secrets.CODECOV_TOKEN }}
69 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | env/
12 | build/
13 | develop-eggs/
14 | dist/
15 | downloads/
16 | eggs/
17 | .eggs/
18 | lib/
19 | lib64/
20 | parts/
21 | sdist/
22 | var/
23 | wheels/
24 | *.egg-info/
25 | .installed.cfg
26 | *.egg
27 |
28 | # PyInstaller
29 | # Usually these files are written by a python script from a template
30 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
31 | *.manifest
32 | *.spec
33 |
34 | # Installer logs
35 | pip-log.txt
36 | pip-delete-this-directory.txt
37 |
38 | # Unit test / coverage reports
39 | htmlcov/
40 | .tox/
41 | .coverage
42 | .coverage.*
43 | .cache
44 | nosetests.xml
45 | coverage.xml
46 | *.cover
47 | .hypothesis/
48 |
49 | # Translations
50 | *.mo
51 | *.pot
52 |
53 | # Django stuff:
54 | *.log
55 | local_settings.py
56 |
57 | # Flask stuff:
58 | instance/
59 | .webassets-cache
60 |
61 | # Scrapy stuff:
62 | .scrapy
63 |
64 | # Sphinx documentation
65 | docs/_build/
66 | docs/source/api/
67 |
68 | # PyBuilder
69 | target/
70 |
71 | # Jupyter Notebook
72 | .ipynb_checkpoints
73 |
74 | # pyenv
75 | .python-version
76 |
77 | # celery beat schedule file
78 | celerybeat-schedule
79 |
80 | # SageMath parsed files
81 | *.sage.py
82 |
83 | # dotenv
84 | .env
85 |
86 | # virtualenv
87 | .venv
88 | venv/
89 | ENV/
90 |
91 | # Spyder project settings
92 | .spyderproject
93 | .spyproject
94 |
95 | # Rope project settings
96 | .ropeproject
97 |
98 | # mkdocs documentation
99 | /site
100 |
101 | # mypy
102 | .mypy_cache/
103 |
104 | # Files resulting from compilation
105 | *.o
106 | *.a
107 | *.so
108 | *.d
109 | .idea
110 |
111 | # Compilation directories that people use
112 | obj*
113 | *objdir
114 | config
115 | build*
116 | debug
117 | debug_latest
118 | *.sh
119 | TEST
120 | */test.py
121 | */test.dat
122 |
123 | # Files resulting from running PSI4
124 | ijk.dat
125 | output.dat
126 | input.py.dat
127 | *.out
128 | *.32
129 | *.clean
130 | *timer.dat
131 | *.molden
132 | *.cube
133 | dfh.*
134 |
--------------------------------------------------------------------------------
/.readthedocs.yaml:
--------------------------------------------------------------------------------
1 | version: 2
2 |
3 | build:
4 | os: ubuntu-22.04
5 | tools:
6 | python: "mambaforge-latest"
7 |
8 | conda:
9 | environment: devtools/conda-envs/docs.yaml
10 |
11 | sphinx:
12 | configuration: docs/source/conf.py
13 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | BSD 3-Clause License
2 |
3 | Copyright (c) 2017-2022, Rollin A. King
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted provided that the following conditions are met:
8 |
9 | * Redistributions of source code must retain the above copyright notice, this
10 | list of conditions and the following disclaimer.
11 |
12 | * Redistributions in binary form must reproduce the above copyright notice,
13 | this list of conditions and the following disclaimer in the documentation
14 | and/or other materials provided with the distribution.
15 |
16 | * Neither the name of the copyright holder nor the names of its
17 | contributors may be used to endorse or promote products derived from
18 | this software without specific prior written permission.
19 |
20 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | recursive-include optking *.py *.json
2 |
3 | include setup.py
4 | include README.md
5 | include LICENSE
6 | include MANIFEST.in
7 |
8 | include versioneer.py
9 | include optking/_version.py
10 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | isort = isort optking
2 | black = black -l 120 optking
3 |
4 | .PHONY: format
5 | format:
6 | $(isort)
7 | $(black)
8 |
9 | .PHONY: lint
10 | lint:
11 | $(isort) --check-only
12 | $(black) --check
13 |
--------------------------------------------------------------------------------
/devtools/conda-envs/base.yaml:
--------------------------------------------------------------------------------
1 | name: test
2 | channels:
3 | - conda-forge
4 | - nodefaults
5 | dependencies:
6 | # Base
7 | - numpy
8 | - python
9 | - qcelemental
10 | - msgpack-python
11 |
12 | # Testing
13 | - pytest
14 | - pytest-cov
15 | - psi4 1.9.1
16 | - dftd3-python
17 | - codecov
18 |
--------------------------------------------------------------------------------
/devtools/conda-envs/dev.yaml:
--------------------------------------------------------------------------------
1 | name: test
2 | channels:
3 | - conda-forge
4 | - nodefaults
5 | dependencies:
6 | # Base
7 | - numpy
8 | - python
9 | - qcelemental
10 | - qcengine
11 | - msgpack-python
12 |
13 | # Testing
14 | - pytest
15 | - pytest-cov
16 | - psi4 1.9.1
17 | - dftd3-python
18 | - codecov
19 |
20 | # Dev
21 | - sphinx
22 | - sphinx-automodapi
23 | - sphinx_material
24 | - graphviz
25 | - black
26 | - isort
27 |
--------------------------------------------------------------------------------
/devtools/conda-envs/docs.yaml:
--------------------------------------------------------------------------------
1 | name: test
2 | channels:
3 | - conda-forge
4 |
5 | dependencies:
6 | - numpy
7 | - python
8 | - qcelemental
9 | - msgpack-python
10 | - sphinx=7.3.7
11 | - sphinx-automodapi=0.16
12 | - sphinx_rtd_theme=2.0.0
13 | - graphviz=9.0.0
14 |
--------------------------------------------------------------------------------
/devtools/scripts/conda_env.py:
--------------------------------------------------------------------------------
1 | import argparse
2 | import os
3 | import shutil
4 | import subprocess as sp
5 |
6 | # Args
7 | parser = argparse.ArgumentParser(
8 | description="Creates a conda environment from file for a given Python version."
9 | )
10 | parser.add_argument(
11 | "-n", "--name", type=str, nargs=1, help="The name of the created Python environment"
12 | )
13 | parser.add_argument(
14 | "-p",
15 | "--python",
16 | type=str,
17 | nargs=1,
18 | help="The version of the created Python environment",
19 | )
20 | parser.add_argument(
21 | "conda_file", nargs="*", help="The file for the created Python environment"
22 | )
23 |
24 | args = parser.parse_args()
25 |
26 | with open(args.conda_file[0], "r") as handle:
27 | script = handle.read()
28 |
29 | tmp_file = "tmp_env.yaml"
30 | script = script.replace("- python", "- python {}*".format(args.python[0]))
31 |
32 | with open(tmp_file, "w") as handle:
33 | handle.write(script)
34 |
35 | conda_path = shutil.which("conda")
36 |
37 | print("CONDA ENV NAME {}".format(args.name[0]))
38 | print("PYTHON VERSION {}".format(args.python[0]))
39 | print("CONDA FILE NAME {}".format(args.conda_file[0]))
40 | print("CONDA path {}".format(conda_path))
41 |
42 | sp.call(
43 | "{} env create -n {} -f {}".format(conda_path, args.name[0], tmp_file), shell=True
44 | )
45 | os.unlink(tmp_file)
46 |
--------------------------------------------------------------------------------
/devtools/scripts/dev_conda_env.py:
--------------------------------------------------------------------------------
1 | import argparse
2 | import os
3 | import shutil
4 | import subprocess as sp
5 |
6 | # Args
7 | parser = argparse.ArgumentParser(
8 | description="Creates a conda environment from file for a given Python version."
9 | )
10 |
11 | parser.add_argument(
12 | "-n", "--name", type=str, nargs=1, help="The name of the created Python environment"
13 | )
14 |
15 | args = parser.parse_args()
16 |
17 | with open('../conda-envs/dev.yaml', "r") as handle:
18 | script = handle.read()
19 |
20 | tmp_file = "tmp_env.yaml"
21 |
22 | with open(tmp_file, "w") as handle:
23 | handle.write(script)
24 |
25 | conda_path = shutil.which("conda")
26 |
27 | sp.call(
28 | "{} env create -n {} -f {}".format(conda_path, args.name[0], tmp_file), shell=True
29 | )
30 | os.unlink(tmp_file)
31 |
32 |
--------------------------------------------------------------------------------
/devtools/travis-ci/before_install.sh:
--------------------------------------------------------------------------------
1 | # Temporarily change directory to $HOME to install software
2 | pushd .
3 | cd "$HOME"
4 |
5 | # Install Miniconda
6 | if [ "$TRAVIS_OS_NAME" == "osx" ]; then
7 | # Make OSX md5 mimic md5sum from linux, alias does not work
8 | md5sum () {
9 | command md5 -r "$@"
10 | }
11 | MINICONDA=Miniconda3-latest-MacOSX-x86_64.sh
12 | else
13 | MINICONDA=Miniconda3-latest-Linux-x86_64.sh
14 | fi
15 | MINICONDA_HOME=$HOME/miniconda
16 |
17 | echo "-- Installing latest Miniconda"
18 | if [ -d "$MINICONDA_HOME/bin" ]; then
19 | echo "-- Miniconda latest version FOUND in cache"
20 |
21 | # Config settings are not saved in the cache
22 | export PIP_ARGS="-U"
23 | export PATH=$MINICONDA_HOME/bin:$PATH
24 |
25 | conda config --set always_yes yes --set changeps1 no
26 | else
27 | MINICONDA_MD5=$(wget -qO- https://repo.anaconda.com/miniconda/ | grep -A3 $MINICONDA | sed -n '4p' | sed -n 's/ *
\(.*\)<\/td> */\1/p')
28 | echo "-- Miniconda latest version NOT FOUND in cache"
29 | wget -q https://repo.continuum.io/miniconda/$MINICONDA
30 | if [[ $MINICONDA_MD5 != $(md5sum $MINICONDA | cut -d ' ' -f 1) ]]; then
31 | echo "Miniconda MD5 mismatch"
32 | exit 1
33 | fi
34 | # Travis creates the cached directories for us.
35 | # This is problematic when wanting to install Anaconda for the first time...
36 | rm -rf "$MINICONDA_HOME"
37 | bash $MINICONDA -b -p "$MINICONDA_HOME"
38 |
39 | # Configure miniconda
40 | export PIP_ARGS="-U"
41 | export PATH=$MINICONDA_HOME/bin:$PATH
42 |
43 | conda config --set always_yes yes --set changeps1 no
44 | conda update -q conda
45 |
46 | rm -f $MINICONDA
47 | fi
48 | echo "-- Done with latest Miniconda"
49 |
50 | # Restore original directory
51 | popd
52 |
--------------------------------------------------------------------------------
/docs/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | SPHINXPROJ = pyoptking
8 | SOURCEDIR = source
9 | BUILDDIR = build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile
16 |
17 | # Catch-all target: route all unknown targets to Sphinx using the new
18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19 | %: Makefile
20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
--------------------------------------------------------------------------------
/docs/readme.md:
--------------------------------------------------------------------------------
1 | Optking's documentation is built by `sphinx` and hosted on `readthedocs.org`
2 | To build the documentation install the following dependencies
3 |
4 | ```
5 | conda install sphinx graphviz sphinx-automodapi sphinx_rtd_theme -c conda-forge
6 | ```
7 |
8 | To build locally
9 |
10 | ```
11 | cd docs && make html
12 | ```
13 |
14 | For instructions on how to add documentation or a primer on `reStructuredText`, read the [Sphinx documentation](https://www.sphinx-doc.org/en/master/index.html)
15 |
--------------------------------------------------------------------------------
/docs/source/algorithms.rst:
--------------------------------------------------------------------------------
1 | Optimization Algorithms
2 | =======================
3 |
4 | Optking performs Newton-Raphson (NR) and Qausi-NR optimizations for small to medium-sized molecules.
5 |
6 | Algorithms include
7 | * Steepest descent
8 | * NR
9 | * Rational function optimization (RFO)
10 | * Restricted Step RFO
11 | * Partioned RFO
12 | * Intrinsic Reaction Coordinate (IRC) optimizations
13 |
14 | The type of optimization is controlled by the `step_type` and `opt_type` keywords. `step_type` chooses optimization algorithm (SD, NR, etc.)
15 | `opt_type` selects the kind of optimization (min, TS, or IRC) and unless overriden chooses the appropriate (or default) `step_type`.
16 |
17 | API Documentation
18 | -----------------
19 |
20 | For more information on the OptHelper classes see `optimizations`_. To simply run an optimization
21 | the OptHelper classes or the interfaces through QCEngine and Psi4 are recommended, especially the later.
22 |
23 | For more information on interacting directly with the algorithms see the API documentation below. In short,
24 | the OptimizationAlgorithm class provides a basic "interface" for running optimizations through the `take_step()`
25 | method. The OptimizationManager class extends this interface to encompass the addition of linesearching
26 | to any of the basic algorithms and IRCFollowing.
27 |
28 | .. automodapi:: optking.stepAlgorithms
29 | .. automodapi:: optking.linesearch
30 | .. automodapi:: optking.IRCfollowing
31 |
--------------------------------------------------------------------------------
/docs/source/api.rst:
--------------------------------------------------------------------------------
1 |
2 | High Level functions and Classes
3 | --------------------------------
4 |
5 | The following documentation pertains to the classes and functions that would
6 | most likely be useful for running optimizations directly through optkings python API and
7 | functions that would be helpful for driver level operations.
8 |
9 | .. automodapi:: optking.opt_helper
10 | .. automodapi:: optking.optimize
11 |
12 |
--------------------------------------------------------------------------------
/docs/source/convergence.rst:
--------------------------------------------------------------------------------
1 | ###########
2 | Convergence
3 | ###########
4 |
5 | .. |delta| unicode:: U+0394
6 |
7 | Optking utilizes a number of optimization presets which mirror and/or mimic the optmization behavior from a number
8 | of popular Quantum Chemistry packages. These may be selected with the *G_CONVERGENCE* keyword. Descriptions of each
9 | preset may be found below. See Notes [#fe] and [#ff] for clarification on what combinations of
10 | criteria are required or allowed.
11 |
12 | For greater control one or more ctriteria can be selectively activated through use of the *_G_CONVERGENCE* keywords.
13 | In order to modify a preset both *FLEXIBLE_G_CONVERGENCE* and one or more *_G_CONVERGENCE* keywords must be
14 | selected in addition to the preset. Specifying *_G_CONVERGENCE* without *FLEXIBLE_G_CONVERGENCE* will cause
15 | the preset to be discarded and optking will ONLY consider the *_G_CONVERGENCE* keyword for convergence.
16 |
17 | As an example the first set of options only changes the `rms_force` threshold. The second changes from `QCHEM` to `GAU_TIGHT` while
18 | loosening the `rms_force` threshold
19 |
20 | ::
21 |
22 | {"g_convergence": "gau_tight", "rms_force_g_convergence": 3e-5}
23 | {"g_convergence": "gau_tight", "flexible_g_convergence": True, "rms_force_g_convergence": 3e-5}
24 |
25 | .. _`table:optkingconv`:
26 |
27 | .. table:: Summary of convergence criteria for *g_convergence* defaults in optking (Same as in Psi4)
28 |
29 | +-----------------------------+----------------------------+----------------------------+----------------------------+----------------------------+----------------------------+
30 | | *g_convergence* | |delta| E | Max Force | RMS Force | Max Disp | RMS Disp |
31 | +=============================+============================+============================+============================+============================+============================+
32 | | NWCHEM_LOOSE [#fd]_ | | :math:`4.5 \times 10^{-3}` | :math:`3.0 \times 10^{-3}` | :math:`5.4 \times 10^{-3}` | :math:`3.6 \times 10^{-3}` |
33 | +-----------------------------+----------------------------+----------------------------+----------------------------+----------------------------+----------------------------+
34 | | GAU_LOOSE [#ff]_ | | :math:`2.5 \times 10^{-3}` | :math:`1.7 \times 10^{-3}` | :math:`1.0 \times 10^{-2}` | :math:`6.7 \times 10^{-3}` |
35 | +-----------------------------+----------------------------+----------------------------+----------------------------+----------------------------+----------------------------+
36 | | TURBOMOLE [#fd]_ | :math:`1.0 \times 10^{-6}` | :math:`1.0 \times 10^{-3}` | :math:`5.0 \times 10^{-4}` | :math:`1.0 \times 10^{-3}` | :math:`5.0 \times 10^{-4}` |
37 | +-----------------------------+----------------------------+----------------------------+----------------------------+----------------------------+----------------------------+
38 | | GAU [#fc]_ [#ff]_ | | :math:`4.5 \times 10^{-4}` | :math:`3.0 \times 10^{-4}` | :math:`1.8 \times 10^{-3}` | :math:`1.2 \times 10^{-3}` |
39 | +-----------------------------+----------------------------+----------------------------+----------------------------+----------------------------+----------------------------+
40 | | CFOUR [#fd]_ | | | :math:`1.0 \times 10^{-4}` | | |
41 | +-----------------------------+----------------------------+----------------------------+----------------------------+----------------------------+----------------------------+
42 | | QCHEM [#fa]_ [#fe]_ | :math:`1.0 \times 10^{-6}` | :math:`3.0 \times 10^{-4}` | | :math:`1.2 \times 10^{-3}` | |
43 | +-----------------------------+----------------------------+----------------------------+----------------------------+----------------------------+----------------------------+
44 | | MOLPRO [#fb]_ [#fe]_ | :math:`1.0 \times 10^{-6}` | :math:`3.0 \times 10^{-4}` | | :math:`3.0 \times 10^{-4}` | |
45 | +-----------------------------+----------------------------+----------------------------+----------------------------+----------------------------+----------------------------+
46 | | GAU_TIGHT [#fc]_ [#ff]_ | | :math:`1.5 \times 10^{-5}` | :math:`1.0 \times 10^{-5}` | :math:`6.0 \times 10^{-5}` | :math:`4.0 \times 10^{-5}` |
47 | +-----------------------------+----------------------------+----------------------------+----------------------------+----------------------------+----------------------------+
48 | | GAU_VERYTIGHT [#ff]_ | | :math:`2.0 \times 10^{-6}` | :math:`1.0 \times 10^{-6}` | :math:`6.0 \times 10^{-6}` | :math:`4.0 \times 10^{-6}` |
49 | +-----------------------------+----------------------------+----------------------------+----------------------------+----------------------------+----------------------------+
50 |
51 | .. rubric:: Footnotes
52 |
53 | .. [#fa] Default
54 | .. [#fb] Baker convergence criteria are the same.
55 | .. [#fc] Counterpart NWCHEM convergence criteria are the same.
56 | .. [#fd] Convergence achieved when all active criteria are fulfilled.
57 | .. [#fe] Convergence achieved when **Max Force** and one of **Max Energy** or **Max Disp** are fulfilled.
58 | .. [#ff] Normal convergence achieved when all four criteria (**Max Force**, **RMS Force**,
59 | **Max Disp**, and **RMS Disp**) are fulfilled. To help with flat
60 | potential surfaces, alternate convergence achieved when 100\ :math:`\times`\ *rms force* is less
61 | than **RMS Force** criterion.
62 |
63 | IRC Convergence
64 | ---------------
65 |
66 | The IRC algorithm uses slightly different convergence criteria since the step sizes are of a fixed distance.
67 | The optimization ends when the forces are opposite the forces of the previous step at a certain threshold < -0.7.
68 | Alternatively an increase in energy along the MEP with any negative overlap of the forces is sufficient.
69 |
70 | Individual points on the IRC are optimized in a constrained optimization (on a hypersphere of fixed radius) according
71 | to the convergence criteria of the table above.
72 |
--------------------------------------------------------------------------------
/docs/source/coords.rst:
--------------------------------------------------------------------------------
1 | General Recommendations
2 | =======================
3 |
4 | Redundant internal coordinates are the default coordinate set for optking. All possible simple stretches, bends,
5 | and dihedral angles are constructed. Automatic supplementation of cartesian coordinates is in development.
6 | If difficulty is encountered with linear coordinates, switching to `opt_coordinates = 'cartesian'` may be
7 | necessary. In some cases a full set of internal and cartesian coordinates has been found to work well this
8 | corresonds to `opt_coordinates = 'both'`
9 |
10 | It should be noted that optking does NOT accept zmatrix coordinates through any of it's supported interfaces.
11 | Communication of the initial geometry between optking and qcengine or psi4 is purely in cartesian coordinates.
12 | Simple internal coordinates can be created through the class constructors if desired; however,
13 | ghost atoms are not supported.
14 |
15 | Adding Constraints to the Optimization
16 | ======================================
17 |
18 | Three types of constraints are supported. The built in coordinates (stre, bend, cart, etc) can be frozen with a
19 | `frozen_` keyword. The coordinate will be held constant with the initial provided value throughout the
20 | optimization.
21 |
22 | For users of the old c++ optking, the `fixed_` options have been replaced with more general
23 | `ranged_` counterparts. This keyword adds forces to the optimization to keep the coordinate within a desired
24 | min and max value (these can be set arbitrarily close to each other to recover the `fixed_` behavior).
25 |
26 | Where applicable input should be specified in Angstroms and Degrees (even if the geomtry is provided in atomic units through QCEngine).
27 |
28 | Frozen Coordinates
29 | ~~~~~~~~~~~~~~~~~~
30 |
31 | Input for the `frozen_` keywords is expected as a list of the indices to constrain.
32 | Parentheses can be added by the user for clarity and are avoided.
33 | The string parsing is more robust and forgiving than in the c++ version and multiline strings and strange spacing
34 | is allowed.
35 |
36 | For hydrogen peroxide the following coordinates could be frozen:
37 |
38 | .. code-block:: python
39 |
40 | hooh = psi4.geometry(
41 | """
42 | H
43 | O 1 0.90
44 | O 2 1.40 1 100.0
45 | H 3 0.90 2 100.0 1 115.0
46 | """
47 | )
48 |
49 | params = {
50 | "frozen_distance": "1 2 3 4"
51 | }
52 |
53 | freezing bond angles::
54 |
55 | "frozen_bend": "1 2 3 2 3 4"
56 |
57 | freezing torsions::
58 |
59 | "frozen_dihedral": "1 2 3 4"
60 |
61 | The following strings are all acceptable to freeze the cartesian coordinates of the hydrogens:
62 |
63 | .. code-block:: python
64 |
65 | """ 1 Xyz 4 xYz """
66 | """ 2 xyz 3 xyz """
67 | """
68 | 1 x
69 | 1 y
70 | 1 Z
71 | 4 x
72 | 4 Y
73 | 4 z """
74 |
75 | Ranged Coordinates
76 | ~~~~~~~~~~~~~~~~~~
77 |
78 | The `ranged_` follows the basic format. `1 2 ... min max`. Multiple coordinates can be assigned
79 | ranges by specifying them sequentially in the string. Using the above example for `HOOH`:
80 |
81 | .. code-block:: python
82 |
83 | params = {
84 | "ranged_distance": "2 3 1.38 1.42"
85 | }
86 |
87 | or using parentheses for clarity:
88 |
89 | .. code-block:: python
90 |
91 | params = {
92 | "ranged_bend": "(1 2 3 99.0 110.0) (2 3 4 99.0 110.0)"
93 | }
94 |
95 |
96 | Adding Forces
97 | ~~~~~~~~~~~~~
98 |
99 | Custom forces may be added to specific coordinates by adding a potential function to the coordinate as a function of x.
100 |
101 | For instance a simple linear potential function can be added to push the OH bond lengths towards 0.95 angstroms::
102 |
103 | "ext_force_distance": "1 2 '-8.0*(x-0.950)' 3 4 '-8.0*(x-0.950)'"
104 |
105 | Currently supported functions are `"sin", "cos", "log", "ln", "log10", "exp", "pow", "abs"`
106 |
107 |
108 | Multifragment Optimizations
109 | ===========================
110 |
111 | For multifragment systems, dimer coordinates are recommended. These may be configured automatically
112 | (simply set `"frag_mode"="MULTI"`) or manually through the `interfrag_coords` keyword.
113 | The `interfrag_coords` keyword expects a dictionary and has a number of fields to allow full
114 | specification of these coordinates
115 |
116 | The DimerFrag creates internal coordinates between pairs of molecules. i.e. water trimer would
117 | consist internal coordinates for A, B, and C as well as dimer coordinates for AB, AC, and BC
118 |
119 | The important keys are
120 | * `"Natoms per frag"` is a list of ints
121 | * `X Frag` specifies the index of the Xth fragment in the molecular system.
122 | * `A Ref Atoms` list of the atoms to use as the three reference points. In the below example we choose the oxygen atom,
123 | third hydrogen atom, and the center of the two hydrogens.
124 | Lists of multiple indices denote the mid-point between the specified atoms.
125 |
126 | .. code-block:: python
127 |
128 | h2oA = psi4.geometry(
129 | """
130 | O
131 | H 1 1.0
132 | H 1 1.0 2 104.5
133 | """
134 | )
135 | Axyz = h2oA.geometry().np
136 |
137 | h2oB = psi4.geometry(
138 | """
139 | O
140 | H 1 1.0
141 | H 1 1.0 2 104.5
142 | """
143 | )
144 |
145 | water_dimer = {
146 | "Natoms per frag": [3, 3],
147 | "A Frag": 1, # Index of fragment in Molsys. 1 Based indexing
148 | "A Ref Atoms": [[1], [2, 3], [3]],
149 | "A Label": "Water-A", # optional
150 | "B Frag": 2,
151 | "B Ref Atoms": [[4], [5, 6], [6]],
152 | "B Label": "Water-B", # optional
153 | }
154 |
155 |
156 | .. automodapi:: optking.stre
157 | .. automodapi:: optking.bend
158 | .. automodapi:: optking.tors
159 |
--------------------------------------------------------------------------------
/docs/source/index.rst:
--------------------------------------------------------------------------------
1 | .. pyoptking documentation master file, created by
2 | sphinx-quickstart on Wed Jul 25 16:46:02 2018.
3 | You can adapt this file completely to your liking, but it should at least
4 | contain the root `toctree` directive.
5 |
6 | Welcome to pyoptking's documentation!
7 | =====================================
8 |
9 | .. image:: ../../media/optking.jpeg
10 | .. image:: ../../media/s8.png
11 |
12 | .. toctree::
13 | :maxdepth: 2
14 | :caption: Contents:
15 |
16 | optimizations
17 | convergence
18 | algorithms
19 | molecule
20 | coords
21 | options
22 |
23 |
24 | Indices and tables
25 | ==================
26 |
27 | * :ref:`genindex`
28 | * :ref:`modindex`
29 | * :ref:`search`
30 |
--------------------------------------------------------------------------------
/docs/source/molecule.rst:
--------------------------------------------------------------------------------
1 | The Molecular System
2 | ====================
3 |
4 | Opkting's molecular system, at its core, is a list of intramolecular fragments `frag.Frag` and
5 | intermolecular fragments `dimerfrag.DimerFrag`. The fragments in turn are lists of masses, atomic numbers and coordinates (cartesian or internal)
6 | along with a numpy array for the cartesian geometry.
7 | NIST values for masses, and atomic numbers can be easily retrieved through `qcelemental` e.g. `qcelemental.periodictable.to_Z('O')`
8 |
9 | A fragment for water:
10 |
11 | .. code-block:: python-console
12 |
13 | >>> import optking
14 | >>> zs = [1, 8, 1]
15 | >>> masses = [1.007825032230, 15.994914619570, 1.007825032230]
16 | >>> geometry = [[-0.028413670411, 0.928922556351, 0.000000000000],
17 | [-0.053670056908, -0.039737675589, 0.000000000000],
18 | [ 0.880196420813, -0.298256807934, 0.000000000000]]
19 | >>> fragment = optking.Frag(zs, geometry, masses)
20 |
21 | The optimization coordinates can be added manually.
22 |
23 | .. code-block:: python-console
24 |
25 | >>> intcos = [optking.Stre(1, 2), optking.Stre(2, 3), optking.Bend(1, 2, 3)]
26 | >>> fragment.intcos = intcos # intcos can also be added at instantiation
27 |
28 | More typically, the coordinate system is automatically generated once the full molecular system is built and then edited if nessecary.
29 |
30 | .. code-block:: python-console
31 |
32 | >>> molsys = optking.Molsys([fragment])
33 | >>> optking.make_internal_coords(molsys)
34 |
35 | To control the automatic generation of coordinates the following keywords can be modified. For more information see the keyword
36 | documentation.
37 |
38 | # TODO keyword documentation needs work (mostly copying pasting?)
39 |
40 | .. automodapi:: optking.molsys
41 | .. automodapi:: optking.frag
42 | .. automodapi:: optking.dimerfrag
43 |
--------------------------------------------------------------------------------
/docs/source/options.rst:
--------------------------------------------------------------------------------
1 | Keywords and Options
2 | ====================
3 |
4 | .. automodapi:: optking.optparams
5 |
--------------------------------------------------------------------------------
/media/optking.jpeg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/psi-rking/optking/2838f7d3fe3286e0aa5e3a16a1242d4dab16978b/media/optking.jpeg
--------------------------------------------------------------------------------
/media/s8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/psi-rking/optking/2838f7d3fe3286e0aa5e3a16a1242d4dab16978b/media/s8.png
--------------------------------------------------------------------------------
/optking/__init__.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import os
3 | import sys
4 | from logging.config import dictConfig
5 | from . import lj_functions, loggingconfig
6 |
7 | if "psi4" in sys.argv[0] or "psi4" in sys._getframe(1).f_globals.get("__name__") or "psi4" in sys.modules:
8 |
9 | opt_log = logging.getLogger("psi4.optking")
10 | log_name = "psi4."
11 | opt_log.propagate = True
12 | else:
13 | logger = logging.getLogger()
14 | dictConfig(loggingconfig.logging_configuration)
15 | logger = logging.getLogger(__name__)
16 | log_name = ""
17 |
18 | from . import optparams as op
19 | from ._version import get_versions
20 | from .opt_helper import EngineHelper, CustomHelper
21 | from .optimize import make_internal_coords, optimize
22 | from .optwrapper import optimize_psi4, optimize_qcengine
23 | from .stre import Stre
24 | from .bend import Bend
25 | from .tors import Tors
26 | from .frag import Frag
27 | from .molsys import Molsys
28 | from .history import History
29 |
30 | op.Params = op.OptParams({})
31 |
32 | __version__ = get_versions()["version"]
33 | del get_versions
34 | _optking_provenance_stamp = {
35 | "creator": "optking",
36 | "routine": None,
37 | "version": __version__,
38 | }
39 |
--------------------------------------------------------------------------------
/optking/cart.py:
--------------------------------------------------------------------------------
1 | import qcelemental as qcel
2 |
3 | from .exceptions import AlgError, OptError
4 | from .misc import string_math_fx
5 | from .simple import Simple
6 |
7 |
8 | class Cart(Simple):
9 | """Cartesian displacement coordinate on one atom
10 |
11 | Parameters
12 | ----------
13 | a : int
14 | atom number (zero indexing)
15 | constraint : string
16 | set coordinate as 'free', 'frozen', etc.
17 | """
18 |
19 | def __init__(
20 | self,
21 | a,
22 | xyz_in,
23 | constraint="free",
24 | range_min=None,
25 | range_max=None,
26 | ext_force=None,
27 | ):
28 |
29 | self.xyz = xyz_in # uses setter below
30 | atoms = (a,)
31 | Simple.__init__(self, atoms, constraint, range_min, range_max, ext_force)
32 |
33 | def __str__(self):
34 | if self.frozen:
35 | s = "*"
36 | elif self.ranged:
37 | s = "["
38 | else:
39 | s = " "
40 |
41 | if self.has_ext_force:
42 | s += ">"
43 |
44 | if self._xyz == 0:
45 | s += "X"
46 | elif self._xyz == 1:
47 | s += "Y"
48 | elif self._xyz == 2:
49 | s += "Z"
50 |
51 | s += "(%d)" % (self.A + 1)
52 | if self.ranged:
53 | s += "[{:.3f},{:.3f}]".format(self.range_min * self.q_show_factor, self.range_max * self.q_show_factor)
54 | return s
55 |
56 | def __eq__(self, other):
57 | if self.atoms != other.atoms:
58 | return False
59 | elif not isinstance(other, Cart):
60 | return False
61 | elif self.xyz != other.xyz:
62 | return False
63 | else:
64 | return True
65 |
66 | @property
67 | def xyz(self):
68 | return self._xyz
69 |
70 | @xyz.setter
71 | def xyz(self, setval):
72 | if setval in [0, "x", "X"]:
73 | self._xyz = 0
74 | elif setval in [1, "y", "Y"]:
75 | self._xyz = 1
76 | elif setval in [2, "z", "Z"]:
77 | self._xyz = 2
78 | else:
79 | raise OptError("Cartesian coordinate must be set to 0-2 or X-Z")
80 |
81 | def q(self, geom):
82 | return geom[self.A, self._xyz]
83 |
84 | @property
85 | def q_show_factor(self):
86 | return qcel.constants.bohr2angstroms
87 |
88 | def q_show(self, geom):
89 | return self.q_show_factor * self.q(geom)
90 |
91 | @property
92 | def f_show_factor(self):
93 | return qcel.constants.hartree2aJ / qcel.constants.bohr2angstroms
94 |
95 | def to_dict(self):
96 | d = {}
97 | d["type"] = Cart.__name__ # 'Cart'
98 | d["atoms"] = self.atoms # id to a tuple
99 | d["xyz"] = self.xyz
100 | d["constraint"] = self.constraint
101 | d["range_min"] = self.range_min
102 | d["range_max"] = self.range_max
103 | if self.has_ext_force:
104 | d["ext_force_str"] = self.ext_force.formula_string
105 | else:
106 | d["ext_force_str"] = None
107 | return d
108 |
109 | @classmethod
110 | def from_dict(cls, d):
111 | a = d["atoms"][0]
112 | constraint = d.get("constraint", "free")
113 | range_min = d.get("range_min", None)
114 | range_max = d.get("range_max", None)
115 | xyz = d.get("xyz", None)
116 | fstr = d.get("ext_force_str", None)
117 | if fstr is None:
118 | ext_force = None
119 | else:
120 | ext_force = string_math_fx(fstr)
121 | return cls(a, xyz, constraint, range_min, range_max, ext_force)
122 |
123 | # Compute and return in-place array of first derivative (row of B matrix)
124 | def DqDx(self, geom, dqdx, mini=False):
125 | dqdx[3 * self.A + self._xyz] = 1.0
126 | return
127 |
128 | # Do nothing, derivative B matrix is zero.
129 | def Dq2Dx2(self, geom, dq2dx2):
130 | pass
131 |
132 | def diagonal_hessian_guess(self, geom, Z, connectivity, guess_type="Simple"):
133 | """Generates diagonal empirical Hessians in a.u. such as
134 | Schlegel, Theor. Chim. Acta, 66, 333 (1984) and
135 | Fischer and Almlof, J. Phys. Chem., 96, 9770 (1992).
136 | """
137 | return 0.1
138 |
--------------------------------------------------------------------------------
/optking/caseInsensitiveDict.py:
--------------------------------------------------------------------------------
1 | import copy
2 | from collections.abc import Mapping
3 |
4 |
5 | class CaseInsensitiveDict(Mapping):
6 | def __init__(self, d):
7 | self._d = d
8 | self._s = dict((k.lower(), k) for k in d)
9 |
10 | def __contains__(self, k):
11 | return k.lower() in self._s
12 |
13 | def __len__(self):
14 | return len(self._s)
15 |
16 | def __iter__(self):
17 | return iter(self._s)
18 |
19 | def __getitem__(self, k):
20 | return self._d[self._s[k.lower()]]
21 |
22 | def __setitem__(self, k, val):
23 | self._s[k.lower()] = k
24 | self._d[k] = val
25 | return
26 |
27 | def actual_key_case(self, k):
28 | return self._s.get(k.lower())
29 |
30 | def copy(self):
31 | return copy.copy(self)
32 |
--------------------------------------------------------------------------------
/optking/exceptions.py:
--------------------------------------------------------------------------------
1 | import logging
2 |
3 | from . import log_name
4 |
5 | optimize_log = logging.getLogger(f"{log_name}{__name__}")
6 |
7 | # We don't catch this one internallyclass OptFail(Exception):
8 | class OptError(Exception):
9 | def __init__(self, mesg="None given", err_type="Not specified"):
10 | # optimize_log.critical("Error message: %s", mesg)
11 | # optimize_log.critical("OptError: Optimization has failed.")
12 | self.mesg = mesg
13 | self.err_type = err_type
14 | # Exception.__init__(self, mesg)
15 |
16 |
17 | class AlgError(Exception):
18 | # maybe generalize later def __init__(self, *args, **kwargs):
19 | def __init__(self, mesg="None given", new_linear_bends=[], new_linear_torsion=[], oofp_failures=[]):
20 | optimize_log.error(f"AlgError: Exception created. Mesg: {mesg}")
21 | if new_linear_bends:
22 | optimize_log.error("AlgError: Linear bends detected.\n%s", '\n'.join(map(str, new_linear_bends)))
23 | if new_linear_torsion:
24 | optimize_log.error("AlgError: Linear Torsions Detected\n%s", '\n'.join(map(str, new_linear_torsion)))
25 | if oofp_failures:
26 | optimize_log.error("AlgError: Linear Oofps Detected\n%s", '\n'.join(map(str, oofp_failures)))
27 | self.linear_bends = new_linear_bends
28 | self.linear_torsions = new_linear_torsion
29 | self.oofp_failures = oofp_failures
30 | self.mesg = mesg
31 |
--------------------------------------------------------------------------------
/optking/hessian.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import json
3 |
4 | import numpy as np
5 | import qcelemental as qcel
6 |
7 | from .bend import Bend
8 | from .printTools import print_mat_string
9 | from .stre import Stre
10 | from .tors import Tors
11 | from . import log_name
12 |
13 | logger = logging.getLogger(f"{log_name}{__name__}")
14 |
15 |
16 | def show(H: np.ndarray, oMolsys):
17 | """Print the Hessian in common spectroscopic units of [aJ/Ang^2], [aJ/deg^2] or [aJ/(Ang deg)]"""
18 |
19 | factors = np.zeros(oMolsys.num_intcos)
20 | cnt = -1
21 | for F in oMolsys._fragments:
22 | for I in F.intcos:
23 | cnt += 1
24 | factors[cnt] = I.q_show_factor
25 | for DI in oMolsys._dimer_intcos:
26 | for I in DI._pseudofrag._intcos:
27 | cnt += 1
28 | factors[cnt] = I.q_show_factor
29 |
30 | factors_inv = np.divide(1.0, factors)
31 | scaled_H = np.einsum("i,ij,j->ij", factors_inv, H, factors_inv)
32 | scaled_H *= qcel.constants.hartree2aJ
33 | logger.info("Hessian in [aJ/Ang^2], [aJ/deg^2], etc.\n" + print_mat_string(scaled_H))
34 |
35 |
36 | # def guess(intcos, geom, Z, connectivity=None, guessType="SIMPLE"):
37 | def guess(oMolsys, connectivity=None, guessType="SIMPLE"):
38 | """Generates diagonal empirical Hessian in a.u.
39 |
40 | Parameters
41 | ----------
42 | intcos : list of Stre, Bend, Tors
43 | geom : ndarray
44 | cartesian geometry
45 | connectivity : ndarray, optional
46 | connectivity matrix
47 | guessType: str, optional
48 | the default is SIMPLE. other options: FISCHER, LINDH_SIMPLE, SCHLEGEL
49 |
50 | Notes
51 | -----
52 | such as
53 | Schlegel, Theor. Chim. Acta, 66, 333 (1984) and
54 | Fischer and Almlof, J. Phys. Chem., 96, 9770 (1992).
55 | """
56 |
57 | diag = []
58 | for F in oMolsys._fragments:
59 | if F.num_intcos:
60 | geom = F.geom
61 | Z = F.Z
62 | connectivity = F.connectivity_from_distances()
63 | for intco in F._intcos:
64 | diag.append(intco.diagonal_hessian_guess(geom, Z, connectivity, guessType))
65 |
66 | # Since the reference points might not even be at atomic positions, let's not worry
67 | # about implementing various options for the diagonal Hessian guess.
68 | for DI in oMolsys._dimer_intcos:
69 | vals = DI.q()
70 | for i, intco in enumerate(DI._pseudo_frag._intcos):
71 | if isinstance(intco, Stre):
72 | h = 0.007
73 | if intco.inverse:
74 | h *= pow(1.0 / vals[i], 4)
75 | # i should be 0=stretch
76 | elif isinstance(intco, Bend):
77 | h = 0.003
78 | elif isinstance(intco, Tors):
79 | h = 0.001
80 | else:
81 | h = 0.111
82 | diag.append(h)
83 |
84 | H = np.diagflat(np.asarray(diag))
85 | return H
86 |
87 |
88 | def from_file(filename):
89 | """Read user provided hessian from disk"""
90 |
91 | with open(filename) as f:
92 | if ".json" == filename[:-5]:
93 | result = json.load(f)
94 | hess = result["return_result"]
95 | ncart = 3 * len(result["molecule"]["symbols"])
96 | else:
97 | # 2D split. Cast everything to floats and convert back to 2D list from map.
98 | lines = f.readlines()
99 | hess = [list(map(float, line.split())) for line in lines[1:]]
100 | ncart = int(lines[0].split()[1]) # assumes FCMFINAL / CFOUR format
101 | try:
102 | H = np.array(hess, dtype=float)
103 | H = H.reshape(ncart, ncart)
104 | except (IndexError, ValueError, TypeError) as error:
105 | logger.error("Hessian should be 3Nx3N cartesian force constant matrix or provided by MolSSI Schema")
106 | logger.error(error)
107 | raise ValueError("Could not load hessian from disk") from error
108 | else:
109 | return H
110 |
--------------------------------------------------------------------------------
/optking/intcosMisc.py:
--------------------------------------------------------------------------------
1 | import logging
2 | from math import sqrt
3 |
4 | import numpy as np
5 |
6 | from . import bend
7 | from . import tors
8 | from . import log_name
9 |
10 | # Some of these functions act on an arbitrary list of simple internals,
11 | # geometry etc. that may or may not be in a molecular system.
12 |
13 | logger = logging.getLogger(f"{log_name}{__name__}")
14 |
15 |
16 | def q_values(intcos, geom):
17 | # available for simple intco lists
18 | vals = [intco.q(geom) for intco in intcos]
19 | return np.asarray(vals)
20 |
21 |
22 | def Bmat(intcos, geom, masses=None):
23 | # Allocate memory for full system.
24 | # Returns mass-weighted Bmatrix if masses are supplied.
25 | # available for simple intco lists
26 | Nint = len(intcos)
27 | B = np.zeros((Nint, 3 * len(geom)))
28 |
29 | for i, intco in enumerate(intcos):
30 | intco.DqDx(geom, B[i])
31 |
32 | if type(masses) is np.ndarray:
33 | sqrtm = np.array([np.repeat(np.sqrt(masses), 3)] * Nint, float)
34 | B[:] = np.divide(B, sqrtm)
35 |
36 | return B
37 |
38 |
39 | def tors_contains_bend(b, t):
40 | return b.atoms in [
41 | t.atoms[0:3],
42 | t.atoms[3::-1],
43 | t.atoms[1:4],
44 | t.atoms[4:0:-1],
45 | ]
46 |
47 |
48 | def remove_old_now_linear_bend(atoms, intcos):
49 | """For given bend [A,B,C], remove any regular bends as well as any torsions
50 | which contain it
51 | """
52 | b = bend.Bend(atoms[0], atoms[1], atoms[2])
53 | logger.info("Removing Old Linear Bend")
54 | logger.info(str(b) + "\n")
55 | intcos[:] = [coord for coord in intcos if coord != b]
56 | intcos[:] = [coord for coord in intcos if not (isinstance(coord, tors.Tors) and tors_contains_bend(b, coord))]
57 |
--------------------------------------------------------------------------------
/optking/linearAlgebra.py:
--------------------------------------------------------------------------------
1 | import logging
2 | from math import sqrt
3 |
4 | import numpy as np
5 | from numpy.linalg import LinAlgError
6 |
7 | from .exceptions import OptError
8 | from . import log_name
9 |
10 | logger = logging.getLogger(f"{log_name}{__name__}")
11 | # Linear algebra routines. #
12 |
13 |
14 | def norm(V):
15 | return np.linalg.norm(V)
16 |
17 |
18 | def abs_max(V):
19 | return max(abs(elem) for elem in V)
20 |
21 |
22 | def abs_min(V):
23 | return min(abs(elem) for elem in V)
24 |
25 |
26 | def rms(V):
27 | return np.sqrt(np.mean(V**2))
28 |
29 |
30 | def sign_of_double(d):
31 | if d > 0:
32 | return 1
33 | elif d < 0:
34 | return -1
35 | else:
36 | return 0
37 |
38 |
39 | # Returns eigenvectors as rows?
40 | def symm_mat_eig(mat):
41 | try:
42 | evals, evects = np.linalg.eigh(mat)
43 | if abs(min(evects[:, 0])) > abs(max(evects[:, 0])):
44 | evects[:, 0] *= -1.0
45 | except:
46 | raise OptError("symm_mat_eig: could not compute eigenvectors")
47 | # could be ALG_FAIL ?
48 | evects = evects.T
49 | return evals, evects
50 |
51 |
52 | def lowest_eigenvector_symm_mat(mat):
53 | """Returns eigenvector with lowest eigenvalues; makes the largest
54 | magnitude element positive.
55 |
56 | Parameters
57 | ----------
58 | mat: np.ndarray
59 |
60 | Returns
61 | -------
62 | np.ndarray
63 | eigenvector for lowest eigenvalue
64 |
65 | """
66 |
67 | try:
68 | evals, evects = np.linalg.eigh(mat)
69 | if abs(min(evects[:, 0])) > abs(max(evects[:, 0])):
70 | evects[:, 0] *= -1.0
71 | except:
72 | raise OptError("symm_mat_eig: could not compute eigenvectors")
73 | return evects[:, 0]
74 |
75 |
76 | def asymm_mat_eig(mat):
77 | """Compute the eigenvalues and right eigenvectors of a square array.
78 | Wraps numpy.linalg.eig to sort eigenvalues, put eigenvectors in rows, and suppress complex.
79 |
80 | Parameters
81 | ----------
82 | mat : ndarray
83 | (n, n) Square matrix to diagonalize.
84 |
85 | Returns
86 | -------
87 | ndarray, ndarray
88 | (n, ), (n, n) sorted eigenvalues and normalized corresponding eigenvectors in rows.
89 |
90 | Raises
91 | ------
92 | OptError
93 | When eigenvalue computation does not converge.
94 |
95 | """
96 | try:
97 | evals, evects = np.linalg.eig(mat)
98 | except np.LinAlgError as e:
99 | raise OptError("asymm_mat_eig: could not compute eigenvectors") from e
100 |
101 | idx = np.argsort(evals)
102 | evals = evals[idx]
103 | evects = evects[:, idx]
104 |
105 | return evals.real, evects.real.T
106 |
107 |
108 | def symm_mat_inv(A, redundant=False, small_val_limit=1.0e-10):
109 | """
110 | Return the inverse of a real, symmetric matrix.
111 |
112 | Parameters
113 | ----------
114 | A : np.ndarray
115 | redundant : bool
116 | allow generalized inverse
117 | smallValLimit : float
118 | specifies how small of singular values to invert
119 |
120 | Returns
121 | -------
122 | np.ndarray
123 |
124 | """
125 |
126 | dim = A.shape[0]
127 | if dim == 0:
128 | return np.zeros((0, 0))
129 |
130 | try:
131 | if redundant:
132 |
133 | if logger.isEnabledFor(logging.DEBUG):
134 | try:
135 | evals, evects = np.linalg.eigh(A)
136 | except LinAlgError:
137 | raise OptError("symm_mat_inv: could not compute eigenvectors")
138 |
139 | absEvals = np.abs(evals)
140 | threshold = small_val_limit * np.max(absEvals)
141 | logger.debug("Singular | values | > %8.3e will be inverted." % threshold)
142 | val = np.min(absEvals[absEvals > threshold])
143 | logger.debug("Smallest inverted value is %8.3e." % val)
144 |
145 | return np.linalg.pinv(A, rcond=small_val_limit)
146 |
147 | else:
148 | return np.linalg.inv(A)
149 |
150 | except LinAlgError:
151 | raise OptError("symmMatrixInv: could not compute eigenvectors")
152 | # could be LinAlgError?
153 |
154 |
155 | def symm_mat_root(A, Inverse=None):
156 | """
157 | Compute A^(1/2) for a positive-definite matrix
158 |
159 | Parameters
160 | ----------
161 | A : np.ndarray
162 | Inverse : bool
163 | calculate A^(-1/2)
164 |
165 | Returns
166 | -------
167 | np.ndarray
168 |
169 | """
170 | try:
171 | evals, evects = np.linalg.eigh(A)
172 | # Eigenvectors of A are in columns of evects
173 | # Evals in ascending order
174 | except LinAlgError:
175 | raise OptError("symm_mat_root: could not compute eigenvectors")
176 |
177 | evals[np.abs(evals) < 10 * np.finfo(float).resolution] = 0.0
178 | evects[np.abs(evects) < 10 * np.finfo(float).resolution] = 0.0
179 |
180 | rootMatrix = np.zeros((len(evals), len(evals)))
181 | if Inverse:
182 | for i in range(0, len(evals)):
183 | evals[i] = 1 / evals[i]
184 |
185 | for i in range(0, len(evals)):
186 | rootMatrix[i][i] = sqrt(evals[i])
187 |
188 | A = np.dot(evects, np.dot(rootMatrix, evects.T))
189 |
190 | return A
191 |
--------------------------------------------------------------------------------
/optking/lj_functions.py:
--------------------------------------------------------------------------------
1 | """
2 | A simple set of functions to compute LJ energies and gradients.
3 | """
4 |
5 | from itertools import combinations
6 |
7 | import numpy as np
8 |
9 |
10 | def calc_energy_and_gradient(positions, sigma, epsilon, do_gradient=True):
11 | r"""
12 | Computes the energy and gradient of a expression in the form
13 | V_{ij} = 4 \epsilon [ (sigma / r) ^ 12 - (sigma / r)^6]
14 | """
15 |
16 | natom = positions.shape[0]
17 | # Holds the energy and the energy gradient
18 | E = 0.0
19 |
20 | gradient = np.zeros((natom, 3))
21 |
22 | sigma6 = sigma**6
23 | sigma12 = sigma6**2
24 |
25 | # Double loop over all particles
26 | for i, j in combinations(range(natom), 2):
27 | v_ij = positions[j] - positions[i]
28 | r = np.linalg.norm(v_ij)
29 | v_ij[:] = v_ij / r
30 | r6 = np.power(r, 6)
31 | r12 = np.power(r6, 2)
32 | E += sigma12 / r12 - sigma6 / r6
33 |
34 | if do_gradient:
35 | dVdr = -12 * sigma12 / (r12 * r) + 6 * sigma6 / (r6 * r)
36 | for xyz in range(3):
37 | gradient[i, xyz] -= dVdr * v_ij[xyz]
38 | gradient[j, xyz] += dVdr * v_ij[xyz]
39 |
40 | E *= 4.0 * epsilon
41 |
42 | if do_gradient:
43 | gradient = 4.0 * epsilon * gradient.reshape(3 * natom)
44 | return E, gradient
45 | else:
46 | return E
47 |
--------------------------------------------------------------------------------
/optking/loggingconfig.py:
--------------------------------------------------------------------------------
1 | import os
2 | import logging
3 |
4 | logging_configuration = {
5 | "version": 1,
6 | "disable_existing_loggers": False,
7 | "formatters": {
8 | "time_severity_message": {
9 | "format": "[{asctime}] - [{levelname}]: {message}",
10 | "style": "{",
11 | },
12 | "severity_name_message": {
13 | "format": "[{levelname}] [{name}]: {message}",
14 | "style": "{",
15 | },
16 | "severity_message": {"format": "[{levelname}]: {message}", "style": "{"},
17 | "message_format": {"format": "{message}", "style": "{"},
18 | },
19 | "handlers": {
20 | "terminal_debug": {
21 | "class": "logging.StreamHandler",
22 | "formatter": "severity_message",
23 | "level": "DEBUG",
24 | },
25 | "terminal_info": {
26 | "class": "logging.StreamHandler",
27 | "formatter": "severity_message",
28 | "level": "INFO",
29 | },
30 | "file_log_debug": {
31 | "class": "logging.FileHandler",
32 | "mode": "w",
33 | "formatter": "severity_message",
34 | "level": "DEBUG",
35 | "filename": os.path.join(os.getcwd(), "opt_log.out"),
36 | },
37 | "file_log_info": {
38 | "class": "logging.FileHandler",
39 | "mode": "w",
40 | "formatter": "severity_message",
41 | "level": "INFO",
42 | "filename": os.path.join(os.getcwd(), "opt_log.out"),
43 | },
44 | "file_king_info": {
45 | "class": "logging.FileHandler",
46 | "formatter": "message_format",
47 | "mode": "w",
48 | "level": "INFO",
49 | "filename": os.path.join(os.getcwd(), "opt_log.out"),
50 | },
51 | },
52 | "loggers": {"optking": {"level": "INFO", "handlers": ["file_log_info"]}},
53 | #"loggers": {"optking": {"level": "DEBUG", "handlers": ["file_log_debug"]}},
54 | # "root": {
55 | # # "level": "INFO",
56 | # # "handlers": ["file_log_info"],
57 | # "level": "WARNING",
58 | # "handlers": [logging.handlers.]
59 | # },
60 | }
61 |
--------------------------------------------------------------------------------
/optking/orient.py:
--------------------------------------------------------------------------------
1 | from math import acos, cos, sin, sqrt
2 |
3 | import numpy as np
4 |
5 | from optking import v3d
6 |
7 | from .exceptions import AlgError
8 |
9 | """ Tools for analytic rotation and orientation """
10 |
11 |
12 | def rotate_vector(rot_axis, phi, v):
13 | """rotate_vecs(): Rotate a set of vectors around an arbitrary axis
14 |
15 | Parameters
16 | ----------
17 | rot_axis : numpy array float[3]
18 | axis to rotate around - gets normalized here
19 | phi : float
20 | magnitude of rotation in radians
21 | v : numpy array of floats
22 | n points to rotate ; overwritten on exit
23 | vectors are rows.
24 |
25 | Returns
26 | -------
27 | None, but v is overwritten with new vectors
28 | """
29 | # normalize rotation axis
30 | norm = sqrt(rot_axis[0] ** 2 + rot_axis[1] ** 2 + rot_axis[2] ** 2)
31 | rot_axis /= norm
32 |
33 | wx = rot_axis[0]
34 | wy = rot_axis[1]
35 | wz = rot_axis[2]
36 | cos_phi = cos(phi)
37 | sin_phi = sin(phi)
38 | cp = 1.0 - cos_phi
39 |
40 | R = np.ndarray((3, 3), float)
41 | R[0, 0] = cos_phi + wx * wx * cp
42 | R[0, 1] = -wz * sin_phi + wx * wy * cp
43 | R[0, 2] = wy * sin_phi + wx * wz * cp
44 | R[1, 0] = wz * sin_phi + wx * wy * cp
45 | R[1, 1] = cos_phi + wy * wy * cp
46 | R[1, 2] = -wx * sin_phi + wy * wz * cp
47 | R[2, 0] = -wy * sin_phi + wx * wz * cp
48 | R[2, 1] = wx * sin_phi + wy * wz * cp
49 | R[2, 2] = cos_phi + wz * wz * cp
50 |
51 | v_new = np.dot(R, v.T) # vectors came in as rows!
52 | v[:] = v_new.T
53 | return
54 |
55 |
56 | def zmat_point(A, B, C, R_CD, theta_BCD, phi_ABCD):
57 | """zmat_point(): Given the xyz coordinates for three points and
58 | R, theta, and phi, as traditionally understood in a Z-matrix,
59 | returns the location of a 4th point.
60 |
61 | Parameters
62 | ----------
63 | A : numpy array float[3]
64 | Cartesian coordinates of atom A
65 | B : numpy array float[3]
66 | Cartesian coordinates of atom B
67 | C : numpy array float[3]
68 | Cartesian coordinates of atom C
69 | R_CD : float
70 | Distance between atoms C and d
71 | theta_BCD :
72 | Angle between atoms B, C and d
73 | phi_ABCD :
74 | Dihedral Angle between atoms A, B, C and d
75 |
76 | Returns
77 | ----------
78 | d : numpy array float[3]
79 | Cartesian coordinates of atom d
80 | """
81 |
82 | eAB = v3d.eAB(A, B) # vector A->B
83 | eBC = v3d.eAB(B, C) # vector B->C
84 | cosABC = -v3d.dot(eAB, eBC)
85 |
86 | sinABC = sqrt(1 - (cosABC * cosABC))
87 | if (sinABC - 1.0e-14) < 0.0:
88 | raise AlgError("Z-matrix (reference) points cannot be colinear.")
89 |
90 | eY = v3d.cross(eAB, eBC) / sinABC
91 | eX = v3d.cross(eY, eBC)
92 | D = C + R_CD * (-eBC * cos(theta_BCD) + eX * sin(theta_BCD) * cos(phi_ABCD) + eY * sin(theta_BCD) * sin(phi_ABCD))
93 | return D
94 |
95 |
96 | # axis = np.array( [0,0,1],float )
97 | # v = np.array( [2,0,0],float )
98 | # angle = acos(-1)
99 | # print('v:', v)
100 | # print('axis:',axis)
101 | # print('angle: %15.10f' % angle)
102 | # rotate_vector(axis, angle, v)
103 | # print('v:', v)
104 |
--------------------------------------------------------------------------------
/optking/printTools.py:
--------------------------------------------------------------------------------
1 | from __future__ import print_function
2 |
3 | import logging
4 | from itertools import chain
5 |
6 | import numpy as np
7 | import qcelemental as qcel
8 |
9 | # from sys import stdout
10 |
11 |
12 | def print_mat_string(M, Ncol=7, title=None):
13 | """Formats a Matrix for Logging or Printing
14 |
15 | Parameters
16 | ----------
17 | M : ndarray, list
18 |
19 | title : string, optional
20 | title to include
21 |
22 | Returns
23 | -------
24 | string
25 | numpy array as string
26 |
27 | """
28 | # if title != "\n":
29 | # title = title + "\n"
30 | # return np.array2string(M, max_line_width=100, precision=6, prefix=title, suffix="\n")
31 | s = "\t"
32 | if title != None:
33 | s += title + "\n\t"
34 | for row in range(M.shape[0]):
35 | tab = 0
36 | for col in range(M.shape[1]):
37 | tab += 1
38 | s += " %10.6f" % M[row, col]
39 | if tab == Ncol and col != (M.shape[1] - 1):
40 | s += "\n\t"
41 | tab = 0
42 | s += "\n\t"
43 | s = s[:-1]
44 | return s
45 |
46 |
47 | def print_array_string(M, Ncol=7, title=None, form=":10.6f"):
48 | """Formats Arrays for Logging or Printing
49 |
50 | Parameters
51 | ----------
52 | M : ndarray, list
53 |
54 | title="\n" : string
55 | optional title to include
56 |
57 | Returns
58 | -------
59 | string
60 | numpy array as string
61 | """
62 | # M = np.asarray(M)
63 | # if title != "\n":
64 | # title = title + "\n"
65 | # return np.array2string(M, max_line_width=100, precision=6, prefix=title, suffix="\n")
66 | s = "\t"
67 | if title != None:
68 | s += title + "\n\t\t"
69 | tab = 0
70 | formstring = "{" + form + "}"
71 | for i, entry in enumerate(M):
72 | tab += 1
73 | s += formstring.format(entry)
74 | if tab == Ncol and i != (len(M) - 1):
75 | s += "\n\t\t"
76 | tab = 0
77 | s += "\n"
78 | return s
79 |
80 |
81 | def print_geom_grad(geom, grad):
82 |
83 | Natom = geom.shape[0]
84 | geometry = [f"{'Geometry (au)':>22}"]
85 | geometry += ["{:15.10f}{:15.10f}{:15.10f}".format(geom[i, 0], geom[i, 1], geom[i, 2]) for i in range(Natom)]
86 |
87 | gradient = [f"{' ':39}Gradient (au)\n"]
88 | gradient += [
89 | "\t\t{:15.10f}{:15.10f}{:15.10f}\n".format(grad[3 * i + 0], grad[3 * i + 1], grad[3 * i + 2])
90 | for i in range(Natom)
91 | ]
92 |
93 | return "".join(list(chain(*zip(geometry, gradient))))
94 |
95 |
96 | def print_geom_string(symbols, geom, unit=None):
97 | if unit == "Angstrom" or unit == "Angstroms":
98 | geom_str = "\n\tCartesian Geometry (in Angstroms)\n"
99 | for i in range(geom.shape[0]):
100 | geom_str += "\t%5s%20.10f%20.10f%20.10f\n" % (
101 | symbols[i],
102 | qcel.constants.bohr2angstroms * geom[i, 0],
103 | qcel.constants.bohr2angstroms * geom[i, 1],
104 | qcel.constants.bohr2angstroms * geom[i, 2],
105 | )
106 | else:
107 | geom_str = "\n\tCartesian Geometry\n"
108 | for i in range(geom.shape[0]):
109 | geom_str += "\t%5s%20.10f%20.10f%20.10f\n" % (
110 | symbols[i],
111 | geom[i, 0],
112 | geom[i, 1],
113 | geom[i, 2],
114 | )
115 | return geom_str
116 |
117 |
118 | def welcome():
119 | welcome_string = """
120 | \t\t\t-----------------------------------------\n
121 | \t\t\t OPTKING 3.0: for geometry optimizations \n
122 | \t\t\t By R.A. King, Bethel University \n
123 | \t\t\t with contributions from \n
124 | \t\t\t A.V. Copan, J. Cayton, A. Heide \n
125 | \t\t\t-----------------------------------------\n
126 | """
127 | return welcome_string
128 |
--------------------------------------------------------------------------------
/optking/simple.py:
--------------------------------------------------------------------------------
1 | from abc import ABC, abstractmethod
2 |
3 | from .exceptions import AlgError, OptError
4 |
5 | supported_constraint_types = ("free", "frozen", "ranged")
6 |
7 |
8 | class Simple(ABC):
9 | def __init__(self, atoms, constraint, range_min, range_max, ext_force):
10 | # these lines use the property's and setters below
11 | self.atoms = atoms # atom indices for internal definition
12 | if constraint.lower() not in supported_constraint_types:
13 | raise OptError("status for simple intco unknown")
14 | self.constraint = constraint.lower()
15 | self._range_min = range_min
16 | self._range_max = range_max
17 | self._ext_force = ext_force
18 |
19 | @property
20 | def atoms(self):
21 | return self._atoms
22 |
23 | @atoms.setter
24 | def atoms(self, values):
25 | try:
26 | for v in values:
27 | if int(v) < 0:
28 | raise OptError("Atom identifier cannot be negative.")
29 | except TypeError:
30 | raise OptError("Atoms must be iterable list of whole numbers.")
31 | self._atoms = values
32 |
33 | @property
34 | def frozen(self):
35 | return self.constraint == "frozen"
36 |
37 | @property
38 | def ranged(self):
39 | return self.constraint == "ranged"
40 |
41 | def freeze(self):
42 | if self.constraint == "free":
43 | self.constraint = "frozen"
44 | # for now if 'ranged', don't change
45 | return
46 |
47 | def unfreeze(self):
48 | if self.constraint == "frozen":
49 | self.constraint = "free"
50 | # for now if 'ranged', don't change
51 |
52 | def set_range(self, range_min, range_max):
53 | self.constraint = "ranged"
54 | self._range_min = range_min
55 | self._range_max = range_max
56 |
57 | @property
58 | def range_min(self):
59 | return self._range_min
60 |
61 | @property
62 | def range_max(self):
63 | return self._range_max
64 |
65 | @property
66 | def has_ext_force(self):
67 | return bool(self._ext_force is not None)
68 |
69 | @property
70 | def ext_force(self):
71 | return self._ext_force
72 |
73 | # could add checking here later
74 | @ext_force.setter
75 | def ext_force(self, eqn):
76 | self._ext_force = eqn
77 |
78 | def ext_force_val(self, geom):
79 | val = self.q_show(geom) # angstroms or degrees
80 | return self._ext_force.evaluate(val)
81 |
82 | @property
83 | def A(self):
84 | try:
85 | return self.atoms[0]
86 | except:
87 | raise OptError("A() called but atoms[0] does not exist")
88 |
89 | @property
90 | def B(self):
91 | try:
92 | return self.atoms[1]
93 | except:
94 | raise OptError("B() called but atoms[1] does not exist")
95 |
96 | @property
97 | def C(self):
98 | try:
99 | return self.atoms[2]
100 | except:
101 | raise OptError("C() called but atoms[2] does not exist")
102 |
103 | @property
104 | def D(self):
105 | try:
106 | return self.atoms[3]
107 | except:
108 | raise OptError("d() called but atoms[3] does not exist")
109 |
110 | # ** constructor + 9 abstract methods are currently required
111 | # for full functionality **
112 | @abstractmethod # Given geometry, return value in Bohr or radians
113 | def q(self, geom):
114 | pass
115 |
116 | @abstractmethod # Given geometry, return Value in Angstroms or degrees.
117 | def q_show(self, geom):
118 | pass
119 |
120 | @abstractmethod # Return the scalar needed to convert value in au to Ang or Deg
121 | def q_show_factor(self):
122 | pass
123 |
124 | @abstractmethod # Return the scalar needed to convert force in au to aJ/(Ang or Deg)
125 | def f_show_factor(self):
126 | pass
127 |
128 | @abstractmethod # print type/classname plus contents to export
129 | def to_dict(self):
130 | pass
131 |
132 | @abstractmethod # construct from dictionary
133 | def from_dict(self, d):
134 | pass
135 |
136 | # Modify provided DqDx array with first derivative of value wrt cartesians
137 | # i.e., provide rows of B matrix.
138 | # Num. of rows is len(self._atoms), or Num. of atoms in coordinate definition
139 | # By default, col dimension of dqdx is assumed to be 3*(Num. of atoms in fragment,
140 | # or the number of atoms consistent with the values of self._atoms).
141 | # If mini==True, then col dimension of dqdx is only 3*len(self._atoms). For a stretch
142 | # then, e.g, DqDx is 2x6.
143 | @abstractmethod
144 | def DqDx(self, geom, dqdx, mini=False):
145 | raise AlgError("no DqDx for this coordinate")
146 |
147 | # Modify provided Dq2Dx2 array with second derivative of value wrt cartesians
148 | # i.e., provide derivative B matrix for coordinate.
149 | # dimension of dq2dx2 is 3*len(self._atoms)x3*len(self._atoms), or
150 | # cartesian by cartesian - of minimum size.
151 | @abstractmethod # Derivative of value wrt cartesians, i.e., B-matrix elements.
152 | def Dq2Dx2(self, geom, dq2dx2):
153 | raise AlgError("no Dq2Dx2 for this coordinate")
154 |
155 | @abstractmethod # Diagonal hessian guess
156 | def diagonal_hessian_guess(geom, Z, connectivity, guess_type):
157 | raise AlgError("no hessian guess for this coordinate")
158 |
--------------------------------------------------------------------------------
/optking/tests/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | Init file for tests, blank to avoid automatic imports.
3 | """
4 |
--------------------------------------------------------------------------------
/optking/tests/ch3chch2cl.in:
--------------------------------------------------------------------------------
1 | # Problem case from CDS
2 |
3 | memory 1024 mb
4 |
5 | molecule mol {
6 | 1 1
7 | C 0.00000000 0.00000000 0.00000000
8 | Cl 0.19771002 -0.99671665 -1.43703398
9 | C 1.06037767 1.11678073 0.00000000
10 | C 2.55772698 0.75685710 0.00000000
11 | H 3.15117939 1.67114056 0.00000000
12 | H 2.79090687 0.17233980 0.88998127
13 | H 2.79090687 0.17233980 -0.88998127
14 | H 0.75109254 2.16198057 0.00000000
15 | H -0.99541786 0.44412079 0.00000000
16 | H 0.12244541 -0.61728474 0.88998127
17 | }
18 |
19 | set scf_type df
20 | set basis 6-31+G(d)
21 | set reference rhf
22 | mol.update_geometry()
23 | mol.symmetrize(1e-3)
24 |
25 | e, wfn = optimize('scf', return_wfn=True)
26 | oeprop(wfn, "MULLIKEN_CHARGES")
27 | mol.print_out()
28 | print_variables()
29 |
30 |
--------------------------------------------------------------------------------
/optking/tests/conftest.py:
--------------------------------------------------------------------------------
1 | import pytest
2 |
3 |
4 | def pytest_configure(config):
5 | # Register marks to avoid warnings in installed testing
6 | # sync with setup.cfg
7 | config.addinivalue_line("markers", "long")
8 | config.addinivalue_line("markers", "dimers")
9 | config.addinivalue_line("markers", "multimers")
10 |
11 |
12 | @pytest.fixture(scope="function", autouse=True)
13 | def set_up():
14 | import optking
15 |
16 | optking.optparams.Params = optking.optparams.OptParams({})
17 |
18 |
19 | def pytest_addoption(parser):
20 | parser.addoption(
21 | "--check_iter",
22 | action="store",
23 | default=0,
24 | help="1 -- raise error if # of steps taken doesn't match expected. 0 (default) -- ignore mismatch but warn user in log",
25 | )
26 |
27 |
28 | @pytest.fixture
29 | def check_iter(request):
30 | return request.config.getoption("--check_iter")
31 |
--------------------------------------------------------------------------------
/optking/tests/dimer_benzene_jupyter_demo.ipynb:
--------------------------------------------------------------------------------
1 | {
2 | "cells": [
3 | {
4 | "cell_type": "code",
5 | "execution_count": null,
6 | "metadata": {},
7 | "outputs": [],
8 | "source": [
9 | "import psi4\n",
10 | "import optking\n",
11 | "import qcelemental as qcel\n",
12 | "au2kcal = qcel.constants.hartree2kcalmol\n",
13 | "import numpy as np\n",
14 | "\n",
15 | "dimerMol = psi4.geometry(\"\"\"\n",
16 | " C -1.2025450 -0.6942916 0.0\n",
17 | " C -1.2025450 0.6942916 0.0\n",
18 | " C 0.0000000 -1.3886100 0.0\n",
19 | " C -0.0000000 1.3886100 0.0\n",
20 | " C 1.2025450 -0.6942916 0.0\n",
21 | " C 1.2025450 0.6942916 0.0\n",
22 | " H -2.1397760 -1.2353675 0.0\n",
23 | " H -2.1397760 1.2353675 0.0\n",
24 | " H 0.0000000 -2.4708011 0.0\n",
25 | " H -0.0000000 2.4708011 0.0\n",
26 | " H 2.1397760 -1.2353675 0.0\n",
27 | " H 2.1397760 1.2353675 0.0\n",
28 | " --\n",
29 | " C -1.2025450 -0.6942916 10.0\n",
30 | " C -1.2025450 0.6942916 10.0\n",
31 | " C 0.0000000 -1.3886100 10.0\n",
32 | " C -0.0000000 1.3886100 10.0\n",
33 | " C 1.2025450 -0.6942916 10.0\n",
34 | " C 1.2025450 0.6942916 10.0\n",
35 | " H -2.1397760 -1.2353675 10.0\n",
36 | " H -2.1397760 1.2353675 10.0\n",
37 | " H 0.0000000 -2.4708011 10.0\n",
38 | " H -0.0000000 2.4708011 10.0\n",
39 | " H 2.1397760 -1.2353675 10.0\n",
40 | " H 2.1397760 1.2353675 10.0\n",
41 | "\"\"\")"
42 | ]
43 | },
44 | {
45 | "cell_type": "code",
46 | "execution_count": null,
47 | "metadata": {},
48 | "outputs": [],
49 | "source": [
50 | "Axyz = dimerMol.geometry().np[0:12,]\n",
51 | "Bxyz = dimerMol.geometry().np[12:,]\n",
52 | "\n",
53 | "# Define some reference atoms\n",
54 | "ArefAtoms = [ [0,1,2,3,4,5], # COM (between Carbon's)\n",
55 | " [2], # carbon on x-axis\n",
56 | " [1]] # another carbon\n",
57 | "BrefAtoms = [ [0,1,2,3,4,5], # COM (between Carbon's)\n",
58 | " [2], # carbon on x-axis\n",
59 | " [1]] # another carbon\n",
60 | "\n",
61 | "dimerCoord = optking.dimerfrag.DimerFrag(0, ArefAtoms, 1, BrefAtoms)\n",
62 | "\n",
63 | "# Here are the dimer coordinates defined, with their values in the\n",
64 | "# default of au or radians.:\n",
65 | "# name = value # description\n",
66 | "R = 6.0 # Distance A1 to B1 (in this case, between COM's)\n",
67 | "theta_A = np.pi/2 # Angle, A2-A1-B1\n",
68 | "theta_B = np.pi/2 # Angle, A1-B1-B2\n",
69 | "tau = 0.0 # Dihedral angle, A2-A1-B1-B2\n",
70 | "phi_A = np.pi/2 # Dihedral angle, A3-A2-A1-B1\n",
71 | "phi_B = -np.pi/2 # Dihedral angle, A1-B1-B2-B3\n",
72 | "# To see starting values:\n",
73 | "# dimerCoord.update_reference_geometry(Axyz, Bxyz)\n",
74 | "#q = dimerCoord.q_array()\n",
75 | "#print(q)\n",
76 | "\n",
77 | "# Choose a theory.\n",
78 | "psi4.core.clean_options()\n",
79 | "psi4_options = { 'basis':'sto-3g', 'd_convergence':'9' }\n",
80 | "psi4.set_options(psi4_options)\n",
81 | "\n",
82 | "# Vary tau, spinning one benzene ring above another parallel one at a distance of 6\n",
83 | "# Angstroms. Use degrees for fun.\n",
84 | "R = 3.0 \n",
85 | "theta_A = 90.0\n",
86 | "theta_B = 90.0\n",
87 | "phi_A = 90.0\n",
88 | "phi_B = -90.0\n",
89 | "\n",
90 | "E_tau = []\n",
91 | "geoms = []\n",
92 | "for tau in range(0,180,30):\n",
93 | " q_target = np.array([R, theta_A, theta_B, tau, phi_A, phi_B])\n",
94 | " Bxyz[:] = dimerCoord.orient_fragment(Axyz, Bxyz, q_target, unit_angle='deg', unit_length='Angstrom')\n",
95 | " xyz = psi4.core.Matrix.from_array( np.concatenate( (Axyz,Bxyz) ) )\n",
96 | " dimerMol.set_geometry( xyz )\n",
97 | " #dimerMol.update_geometry()\n",
98 | " E_tau.append( [tau, xyz.to_array(), psi4.energy('scf')] )\n",
99 | " \n",
100 | "E_tau = np.array(E_tau)\n",
101 | "Emin = min(E_tau[:,2])\n",
102 | "E_tau[:,2] = au2kcal*(E_tau[:,2] - Emin)\n",
103 | "\n",
104 | "import matplotlib.pyplot as plt\n",
105 | "x = E_tau[:,0]\n",
106 | "y = E_tau[:,2]\n",
107 | "fig = plt.figure()\n",
108 | "ax = fig.add_axes( [0.10,0.10,0.80,0.80] )\n",
109 | "ax.set_title('Benzene dimer')\n",
110 | "ax.set_xlabel('tau angle')\n",
111 | "ax.set_ylabel('Energy')\n",
112 | "ax.plot(x,y, 'g+-')\n",
113 | "plt.xlim(0,180)\n",
114 | "plt.show()\n",
115 | "\n",
116 | "# Lets see geometry at tau=60.0\n",
117 | "row = np.where(E_tau[:,0]==60.0)[0]\n",
118 | "dimerMol.set_geometry( psi4.core.Matrix.from_array(E_tau[row[0],1]) )\n",
119 | "qcelMol = qcel.models.Molecule(**dimerMol.to_schema(dtype=2))\n",
120 | "qcelMol.show()"
121 | ]
122 | },
123 | {
124 | "cell_type": "code",
125 | "execution_count": null,
126 | "metadata": {},
127 | "outputs": [],
128 | "source": []
129 | }
130 | ],
131 | "metadata": {
132 | "kernelspec": {
133 | "display_name": "Python 3",
134 | "language": "python",
135 | "name": "python3"
136 | },
137 | "language_info": {
138 | "codemirror_mode": {
139 | "name": "ipython",
140 | "version": 3
141 | },
142 | "file_extension": ".py",
143 | "mimetype": "text/x-python",
144 | "name": "python",
145 | "nbconvert_exporter": "python",
146 | "pygments_lexer": "ipython3",
147 | "version": "3.7.5"
148 | }
149 | },
150 | "nbformat": 4,
151 | "nbformat_minor": 4
152 | }
153 |
--------------------------------------------------------------------------------
/optking/tests/json_betapinene.json:
--------------------------------------------------------------------------------
1 | {
2 | "schema_name": "qcschema_optimization_input",
3 | "schema_version": 1,
4 | "keywords": {
5 | "program": "psi4"
6 | },
7 | "initial_molecule": {
8 | "geometry": [
9 | 1.570733,
10 | -1.623467,
11 | -4.880418,
12 | 1.466284,
13 | -1.616729,
14 | -2.827198,
15 | 1.421269,
16 | 1.255828,
17 | 1.082211,
18 | -2.33399,
19 | -1.577555,
20 | 0.265482,
21 | -1.51017,
22 | 1.162298,
23 | 0.637200,
24 | -1.05096,
25 | -2.899489,
26 | -1.986679,
27 | 1.636940,
28 | 1.135992,
29 | -1.865913,
30 | -2.36670,
31 | -2.872735,
32 | -3.569843,
33 | 3.080220,
34 | -2.687655,
35 | -2.143045,
36 | -2.71718,
37 | 2.165516,
38 | 1.966455,
39 | -0.72171,
40 | -4.878211,
41 | -1.539549,
42 | 3.208824,
43 | 2.139504,
44 | -2.736660,
45 | -1.02444,
46 | 2.355555,
47 | -2.000223,
48 | -0.97038,
49 | 4.403126,
50 | -1.943530,
51 | -2.24904,
52 | 1.760297,
53 | -3.535001,
54 | -4.00031,
55 | -2.707375,
56 | 1.706060,
57 | -4.53858,
58 | -4.656572,
59 | 1.421038,
60 | -4.92484,
61 | -1.743122,
62 | 3.250121,
63 | 2.296896,
64 | 3.838233,
65 | 2.138840,
66 | 4.343961,
67 | 3.973550,
68 | 2.062462,
69 | 1.718395,
70 | 4.033472,
71 | 4.098434,
72 | 1.515345,
73 | 5.410438,
74 | 1.083602,
75 | 2.654332,
76 | -0.848272,
77 | 2.686102,
78 | 4.696013,
79 | -0.785032,
80 | 2.483374,
81 | 2.014302,
82 | -2.718905,
83 | 2.157681,
84 | 2.204852,
85 | -0.565852,
86 | 4.668446
87 | ],
88 | "symbols": [
89 | "H",
90 | "C",
91 | "C",
92 | "C",
93 | "C",
94 | "C",
95 | "C",
96 | "H",
97 | "H",
98 | "H",
99 | "H",
100 | "H",
101 | "C",
102 | "H",
103 | "H",
104 | "C",
105 | "H",
106 | "H",
107 | "C",
108 | "H",
109 | "H",
110 | "H",
111 | "C",
112 | "H",
113 | "H",
114 | "H"
115 | ]
116 | },
117 | "input_specification": {
118 | "schema_name": "qcschema_input",
119 | "schema_version": 1,
120 | "driver": "gradient",
121 | "model": {
122 | "method": "HF",
123 | "basis": "sto-3g"
124 | },
125 | "keywords": {}
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/optking/tests/json_h2o.json:
--------------------------------------------------------------------------------
1 | {
2 | "schema_name": "qcschema_optimization_input",
3 | "schema_version": 1,
4 | "keywords": {
5 | "program": "psi4"
6 | },
7 | "initial_molecule": {
8 | "geometry": [
9 | 0.0,
10 | 0.0,
11 | 0.28100228,
12 | 0.0,
13 | 1.42674323,
14 | -0.8431958,
15 | 0.0,
16 | -1.42674323,
17 | -0.8431958
18 | ],
19 | "symbols": [
20 | "O",
21 | "H",
22 | "H"
23 | ],
24 | "masses": [
25 | 15.994915,
26 | 1.007825,
27 | 1.007825
28 | ]
29 | },
30 | "input_specification": {
31 | "schema_name": "qcschema_input",
32 | "schema_version": 1,
33 | "driver": "gradient",
34 | "model": {
35 | "method": "hf",
36 | "basis": "sto-3g"
37 | },
38 | "keywords": {
39 | "diis": false,
40 | "e_convergence": 10,
41 | "d_convergence": 10,
42 | "scf_type": "pk"
43 | }
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/optking/tests/json_hooh_frozen.json:
--------------------------------------------------------------------------------
1 | {
2 | "schema_name": "qcschema_optimization_input",
3 | "schema_version": 1,
4 | "keywords": {
5 | "program": "psi4",
6 | "frozen_bend": "1 2 3 2 3 4",
7 | "g_convergence": "gau_verytight"
8 | },
9 | "initial_molecule": {
10 | "geometry": [
11 | 1.635264,
12 | 1.392752,
13 | 0.846589,
14 | 0.194579,
15 | 1.308419,
16 | -0.053343,
17 | -0.194579,
18 | -1.308419,
19 | -0.053343,
20 | -1.635264,
21 | -1.392752,
22 | 0.846589
23 | ],
24 | "symbols": [
25 | "H",
26 | "O",
27 | "O",
28 | "H"
29 | ]
30 | },
31 | "input_specification": {
32 | "schema_name": "qcschema_input",
33 | "schema_version": 1,
34 | "driver": "gradient",
35 | "model": {
36 | "method": "HF",
37 | "basis": "cc-pvdz"
38 | },
39 | "keywords": {
40 | "diis": false,
41 | "scf_type": "pk"
42 | }
43 | }
44 | }
45 |
--------------------------------------------------------------------------------
/optking/tests/json_lif_cp.json:
--------------------------------------------------------------------------------
1 | {"initial_molecule": {"fragment_charges": [1, -1], "fragments": [[0], [1]], "geometry": [0.0, 0.0, 0.0, 0.0, 0.0, 3.0], "symbols": ["Li", "F"]},
2 | "input_specification": {"driver": "energy",
3 | "schema_name": "qcschema_manybodyspecification",
4 | "keywords": {"bsse_type": "cp", "supersystem_ie_only": true},
5 | "protocols": {"component_results": "all"},
6 | "specification": {"driver": "energy",
7 | "extras": {"psiapi": true},
8 | "keywords": {},
9 | "model": {"basis": "6-31g", "method": "hf"},
10 | "program": "psi4",
11 | "protocols": {"stdout": false}}},
12 | "keywords": {"g_convergence": "interfrag_tight", "program": "psi4"},
13 | "protocols": {"trajectory": "final"},
14 | "provenance": {"creator": "optking", "routine": "optimize_qcengine", "version": "0.2.1+14.gdc8fd03.dirty"},
15 | "schema_name": "qcschema_generalizedoptimizationinput",
16 | "schema_version": 1}
17 |
18 |
--------------------------------------------------------------------------------
/optking/tests/json_lif_nocp.json:
--------------------------------------------------------------------------------
1 | {"initial_molecule": {"fragment_charges": [1, -1], "fragments": [[0], [1]], "geometry": [0.0, 0.0, 0.0, 0.0, 0.0, 3.0], "symbols": ["Li", "F"]},
2 | "input_specification": {"driver": "energy",
3 | "keywords": {"bsse_type": "nocp", "supersystem_ie_only": true},
4 | "protocols": {"component_results": "all"},
5 | "schema_name": "qcschema_manybodyspecification",
6 | "specification": {"driver": "energy",
7 | "extras": {"psiapi": true},
8 | "keywords": {},
9 | "model": {"basis": "6-31g", "method": "hf"},
10 | "program": "psi4",
11 | "protocols": {"stdout": false}}},
12 | "keywords": {"g_convergence": "gau_verytight", "program": "psi4"},
13 | "protocols": {"trajectory": "final"},
14 | "provenance": {"creator": "optking", "routine": "optimize_qcengine", "version": "0.2.1+14.gdc8fd03.dirty"},
15 | "schema_name": "qcschema_generalizedoptimizationinput",
16 | "schema_version": 1}
17 |
18 |
--------------------------------------------------------------------------------
/optking/tests/psi4_helper.py:
--------------------------------------------------------------------------------
1 | """
2 | A simple OptKing wrapper for the Psi4 quantum chemistry program
3 | """
4 |
5 | import numpy
6 | import pytest
7 | from qcelemental.util import which_import
8 |
9 | # Try to pull in Psi4
10 | try:
11 | import psi4
12 |
13 | found_psi4 = True
14 | except ImportError:
15 | found_psi4 = False
16 |
17 | # Wrap Psi4 in ifden
18 | using_psi4 = pytest.mark.skipif(found_psi4, reason="Psi4 not found, skipping.")
19 | using_qcmanybody = pytest.mark.skipif(
20 | which_import("qcmanybody", return_bool=True) is False,
21 | reason="cound not find qcmanybody. please install the package to enable tests",
22 | )
23 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psiAPIversions/__init__.py:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psiAPIversions/dimer-h2o-c6h6.py:
--------------------------------------------------------------------------------
1 | import psi4
2 | import optking
3 |
4 | refenergy = -303.25404554
5 |
6 | dimer = psi4.geometry(
7 | """
8 | 0 1
9 | O -0.5026452583 -0.9681078610 -0.4772692868
10 | H -2.3292990446 -1.1611084524 -0.4772692868
11 | H -0.8887241813 0.8340933116 -0.4772692868
12 | --
13 | 0 1
14 | C 0.8853463281 -5.2235996493 0.5504918473
15 | C 1.8139169342 -2.1992967152 3.8040686146
16 | C 2.8624456357 -4.1143863257 0.5409035710
17 | C -0.6240195463 -4.8153482424 2.1904642137
18 | C -0.1646305764 -3.3031992532 3.8141619690
19 | C 3.3271056135 -2.6064153737 2.1669340785
20 | H 0.5244823836 -6.4459192939 -0.7478283184
21 | H 4.0823309159 -4.4449979205 -0.7680411190
22 | H -2.2074914566 -5.7109913627 2.2110247636
23 | H -1.3768100495 -2.9846751653 5.1327625515
24 | H 4.9209603634 -1.7288723155 2.1638694922
25 | H 2.1923374156 -0.9964630692 5.1155773223
26 | nocom
27 | units au
28 | """
29 | )
30 |
31 | psi4_options = {
32 | "basis": "sto-3g",
33 | "frag_mode": "MULTI",
34 | "frag_ref_atoms": [
35 | [[1], [2], [3]], # reference atoms are O, H, H for h2o,frag1
36 | [[1, 2, 3, 4, 5, 6], [2], [6]], # reference atoms are center of ring, C, C frag2
37 | ],
38 | }
39 | psi4.set_options(psi4_options)
40 |
41 | json_output = optking.optimize_psi4("mp2")
42 |
43 | print("Number of iterations: %5d" % len(json_output["energies"]))
44 | print("Start energy: %15.10f" % json_output["energies"][0])
45 | print("Final energy: %15.10f" % json_output["energies"][-1])
46 |
47 | assert psi4.compare_values(refenergy, json_output["energies"][-1], 6, "Reference energy")
48 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psiAPIversions/dimer-h2o.py:
--------------------------------------------------------------------------------
1 | #! water dimer
2 | import psi4
3 | import optking
4 |
5 | refenergy = -149.9414053335
6 |
7 | dimer = psi4.geometry(
8 | """
9 | 0 1
10 | H 0.53297836 -1.10088263 -2.17523351
11 | O 0.67046349 -1.17150926 -0.32413149
12 | H -0.87285505 -0.32827188 0.18313336
13 | --
14 | 0 1
15 | H -0.75224517 -2.04662631 -6.55895403
16 | O -0.20225739 -0.70744543 -5.42642983
17 | H 0.62391765 0.47566674 -6.56493124
18 | nocom
19 | units au
20 | """
21 | )
22 |
23 | psi4_options = {
24 | "basis": "sto-3g",
25 | "geom_maxiter": 30,
26 | "frag_mode": "MULTI",
27 | "frag_ref_atoms": [
28 | [[2], [1], [3]], # atoms for reference pts. on frag1
29 | [[2], [1], [3]], # atoms for reference pts. on frag 2
30 | ],
31 | }
32 |
33 | psi4.set_options(psi4_options)
34 | json_output = optking.optimize_psi4("hf")
35 |
36 | print("Number of iterations: %5d" % len(json_output["energies"]))
37 | print("Start energy: %15.10f" % json_output["energies"][0])
38 | print("Final energy: %15.10f" % json_output["energies"][-1])
39 |
40 | assert psi4.compare_values(refenergy, json_output["energies"][-1], 6, "Reference energy")
41 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psiAPIversions/dimer-ne2.py:
--------------------------------------------------------------------------------
1 | #! neon dimer; test interfragment coordinates for minimal system
2 | import psi4
3 | import optking
4 |
5 | refenergy = -253.209145
6 |
7 | dimer = psi4.geometry(
8 | """
9 | 0 1
10 | Ne 0.0 0.0 0.0
11 | --
12 | 0 1
13 | Ne 1.5 0.0 0.0
14 | nocom
15 | units au
16 | """
17 | )
18 |
19 | psi4_options = {
20 | "basis": "sto-3g",
21 | "geom_maxiter": 30,
22 | "frag_mode": "MULTI",
23 | "frag_ref_atoms": [[[1]], [[1]]], # atoms for reference pts. on frag1 # atoms for reference pts. on frag 2
24 | "g_convergence": "gau_tight",
25 | }
26 | psi4.set_options(psi4_options)
27 |
28 | json_output = optking.optimize_psi4("hf")
29 |
30 | print("\nNumber of iterations: %5d" % len(json_output["energies"]))
31 | print("Start energy: %15.10f" % json_output["energies"][0])
32 | print("Final energy: %15.10f" % json_output["energies"][-1])
33 |
34 | assert psi4.compare_values(refenergy, json_output["energies"][-1], 6, "Reference energy")
35 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psiAPIversions/froz-dimer-h2o.py:
--------------------------------------------------------------------------------
1 | #! water dimer
2 | import psi4
3 | import optking
4 |
5 | refenergy = -149.9414053335
6 |
7 | dimer = psi4.geometry(
8 | """
9 | 0 1
10 | H 0.53297836 -1.10088263 -2.17523351
11 | O 0.67046349 -1.17150926 -0.32413149
12 | H -0.87285505 -0.32827188 0.18313336
13 | --
14 | 0 1
15 | H -0.75224517 -2.04662631 -6.55895403
16 | O -0.20225739 -0.70744543 -5.42642983
17 | H 0.62391765 0.47566674 -6.56493124
18 | nocom
19 | units au
20 | """
21 | )
22 |
23 | psi4_options = {
24 | "basis": "sto-3g",
25 | "geom_maxiter": 40,
26 | "frag_mode": "MULTI",
27 | "frag_ref_atoms": [
28 | [[2], [1], [3]], # atoms for reference pts. on frag1
29 | [[2], [1], [3]], # atoms for reference pts. on frag 2
30 | ],
31 | "freeze_intrafrag": True,
32 | "intrafrag_step_limit": 0.2,
33 | "intrafrag_step_limit_max": 0.3,
34 | }
35 |
36 | psi4.set_options(psi4_options)
37 | json_output = optking.optimize_psi4("hf")
38 |
39 | print("Number of iterations: %5d" % len(json_output["energies"]))
40 | print("Start energy: %15.10f" % json_output["energies"][0])
41 | print("Final energy: %15.10f" % json_output["energies"][-1])
42 |
43 | assert psi4.compare_values(refenergy, json_output["energies"][-1], 6, "Reference energy")
44 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/b3lyp-g-phenylacetylene.in:
--------------------------------------------------------------------------------
1 | #! B3LYP cc-pVDZ geometry optimzation of phenylacetylene, starting from
2 | #! not quite linear structure
3 | import optking
4 | b3lyp_E = 308.413691796 # from tight run
5 |
6 | molecule {
7 | 0 1
8 | C 0.50424 2.62143 -1.86897
9 | C -0.79405 2.10443 -1.80601
10 | C -1.78491 2.59819 -2.66154
11 | C -1.47738 3.60745 -3.57782
12 | C -0.17996 4.12418 -3.64086
13 | C 0.81143 3.63137 -2.78697
14 | H 1.27012 2.23852 -1.20693
15 | H -2.24344 3.98980 -4.23978
16 | H 0.05756 4.90505 -4.35040
17 | H -1.03189 1.32372 -1.09717
18 | H -2.78881 2.19838 -2.61341
19 | C 2.14399 4.16411 -2.85667
20 | C 3.26501 4.60083 -2.90366
21 | H 4.24594 4.99166 -2.95361
22 | }
23 |
24 | set {
25 | guess sad
26 | basis cc-pVDZ
27 | }
28 |
29 | result = optking.optimize_psi4('B3LYP')
30 | thisenergy = result['energies'][-1]
31 | compare_values(b3lyp_E, thisenergy, 6, "B3LYP energy")
32 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/ccsd-g-ch2.in:
--------------------------------------------------------------------------------
1 | #! ROHF-CCSD/cc-pVDZ $^{3}B@@1$ CH2 geometry optimization via analytic gradients
2 | import optking
3 |
4 | molecule ch2 {
5 | 0 3
6 | C
7 | H 1 1.1
8 | H 1 1.1 2 109.0
9 | }
10 |
11 | set {
12 | reference rohf
13 | basis cc-pvdz
14 | max_disp_g_convergence 1e-6
15 | max_force_g_convergence 1.0e-6
16 | max_energy_g_convergence 7
17 | e_convergence 10
18 | r_convergence 10
19 | }
20 |
21 | result = optking.optimize_psi4('CCSD')
22 |
23 | this_scf = result['trajectory'][-1]['properties']['scf_total_energy']
24 | this_ccsd = result['trajectory'][-1]['properties']['ccsd_correlation_energy']
25 | this_total = result['trajectory'][-1]['properties']['return_energy']
26 |
27 | REF_scf = -38.921394733562281
28 | REF_cor = -0.120484098351036
29 | REF_tot = -39.041878831913316
30 |
31 | compare_values(REF_scf, this_scf, 6, "SCF energy")
32 | compare_values(REF_cor, this_ccsd, 6, "CCSD contribution")
33 | compare_values(REF_tot, this_total, 6, "Total energy")
34 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/ccsd-g-h2o.in:
--------------------------------------------------------------------------------
1 | #! RHF-CCSD 6-31G** all-electron optimization of the H2O molecule
2 | import optking
3 |
4 | molecule h2o {
5 | O
6 | H 1 0.97
7 | H 1 0.97 2 103.0
8 | }
9 |
10 | set {
11 | basis 6-31G**
12 | }
13 |
14 | result = optking.optimize_psi4('ccsd')
15 |
16 | this_scf = result['trajectory'][-1]['properties']['scf_total_energy']
17 | this_ccsd = result['trajectory'][-1]['properties']['ccsd_correlation_energy']
18 | this_total = result['trajectory'][-1]['properties']['return_energy']
19 |
20 | REF_scf = -76.0229427274435 #TEST
21 | REF_ccsd = -0.20823570806196 #TEST
22 | REF_total = -76.2311784355056 #TEST
23 |
24 | compare_values(REF_scf, this_scf, 5, "SCF energy") #TEST
25 | compare_values(REF_ccsd, this_ccsd, 5, "CCSD contribution") #TEST
26 | compare_values(REF_total, this_total, 5, "Total energy") #TEST
27 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/dcft-g-o2.in:
--------------------------------------------------------------------------------
1 | #! DC-06 calculation for the O2 molecule (triplet ground state). This performs
2 | #! geometry optimization using two-step and simultaneous solution of the
3 | #! response equations for the analytic gradient.
4 | import optking
5 |
6 | REF_uhf = -149.65205193206810
7 | REF_mp2 = -150.01099865665492
8 | REF_dctscf = -149.24779428002528
9 | REF_dct = -150.02279378629558
10 | 150.022793786307
11 |
12 | molecule O2 {
13 | 0 3
14 | O
15 | O 1 R
16 | R = 1.230
17 | }
18 |
19 | set {
20 | r_convergence 10
21 | algorithm twostep
22 | response_algorithm twostep
23 | basis dzp
24 | max_disp_g_convergence 1e-6
25 | rms_force_g_convergence 1e-6
26 | max_energy_g_convergence 1e-6
27 | reference uhf
28 | }
29 |
30 | set dct_functional dc-06
31 | result = optking.optimize_psi4('dct')
32 |
33 | this_uhf = result['trajectory'][-1]['properties']['scf_total_energy']
34 | this_mp2 = result['trajectory'][-1]['properties']['mp2_total_energy']
35 | this_dct = result['energies'][-1]
36 |
37 | compare_values(REF_uhf, this_uhf, 6, "UHF Energy");
38 | compare_values(REF_mp2, this_mp2, 6, "MP2 Energy");
39 | compare_values(REF_dct, this_dct, 6, "DC-06 Energy (two-step response)");
40 | #compare_values(REF_dctscf, variable("DCT SCF ENERGY"), 6, "DC-06 SCF Energy (two-step response)");
41 |
42 | set response_algorithm simultaneous
43 | O2.R = 1.232
44 |
45 | result = optking.optimize_psi4('dct')
46 |
47 | this_uhf = result['trajectory'][-1]['properties']['scf_total_energy']
48 | this_mp2 = result['trajectory'][-1]['properties']['mp2_total_energy']
49 | this_dct = result['energies'][-1]
50 |
51 | compare_values(REF_uhf, this_uhf, 6, "UHF Energy");
52 | compare_values(REF_mp2, this_mp2, 6, "MP2 Energy");
53 | compare_values(REF_dct, this_dct, 6, "DC-06 Energy (simultaneous response)");
54 | #compare_values(REF_dctscf, variable("DCT SCF ENERGY"), 6, "DC-06 SCF Energy (simultaneous response)");
55 |
56 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/hf-e-h2o.in:
--------------------------------------------------------------------------------
1 | #! SCF STO-3G geometry optimzation, with Z-matrix input, by finite-differences
2 | import optking
3 |
4 | REF_energy = -74.965901192
5 |
6 | molecule h2o {
7 | O
8 | H 1 1.0
9 | H 1 1.0 2 104.5
10 | }
11 |
12 | set {
13 | diis false
14 | basis sto-3g
15 | e_convergence 10
16 | d_convergence 10
17 | points 3
18 | scf_type pk
19 | }
20 |
21 | # This test requires a change to ~/psi4/psi4/driver/schema_wrapper.py
22 | # to detect "dertype" as a keyword and allow it to be an integer.
23 | result = optking.optimize_psi4('scf', dertype=0)
24 | this_energy = result['energies'][-1]
25 | print( result['trajectory'][-1]['stdout'] )
26 |
27 | compare_values(REF_energy, this_energy, 6, "Reference energy")
28 |
29 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/hf-g-SF4-breaksLinear.in:
--------------------------------------------------------------------------------
1 | #! 6-31G(d) optimization of SF4 starting from linear bond angle
2 | #! that is not linear in the optimized structure but is in a
3 | #! symmetry plane of the molecule.
4 | # Difficult case. It runs fine for ~7 steps but won't converge
5 | # until we get a symmetrization of our steps to keep C2v.
6 | import optking
7 | SCF_E = -795.1433964231258
8 |
9 | molecule {
10 | 0 1
11 | S 0.00000000 0.00000000 0.00000000
12 | F 0.03923814 -1.73955752 0.00000000
13 | F -1.73955752 -0.03923814 0.00000000
14 | F 1.73955752 0.03923814 0.00000000
15 | F -0.01961907 0.86977876 -1.50688420
16 | }
17 |
18 | set {
19 | scf_type pk
20 | basis 6-31G(d)
21 | reference rhf
22 | geom_maxiter 15
23 | }
24 |
25 | set optking intrafrag_step_limit_max 0.3
26 |
27 | result = optking.optimize_psi4('SCF')
28 | thisenergy = result['energies'][-1]
29 | print( result['trajectory'][-1]['stdout'] )
30 |
31 | compare_values(SCF_E, thisenergy, 5, "6-31G(D) SCF optimization of SF4")
32 |
33 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/hf-g-alleneLinear.in:
--------------------------------------------------------------------------------
1 | #! SCF DZ allene geometry optimization, with Cartesian input, first in c2v symmetry,
2 | #! then in Cs symmetry from a starting point with a non-linear central bond angle.
3 | import optking
4 |
5 | REF_energy = -115.8302823663
6 |
7 | # starting point is D2d/c2v
8 | molecule allene {
9 | H 0.0 -0.92 -1.8
10 | H 0.0 0.92 -1.8
11 | C 0.0 0.00 -1.3
12 | C 0.0 0.00 0.0
13 | C 0.0 0.00 1.3
14 | H 0.92 0.00 1.8
15 | H -0.92 0.00 1.8
16 | }
17 |
18 | set {
19 | basis DZ
20 | e_convergence 10
21 | d_convergence 10
22 | scf_type pk
23 | }
24 |
25 | result = optking.optimize_psi4('scf')
26 | thisenergy = result['energies'][-1]
27 | compare_values(REF_energy, thisenergy, 6, "Reference energy")
28 |
29 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/hf-g-alleneNonlinear.in:
--------------------------------------------------------------------------------
1 | #! SCF DZ allene geometry optimization in Cs symmetry from a non-linear starting point.
2 | import optking
3 |
4 | REF_energy = -115.8302823663
5 |
6 | # central C-C-C bond angle starts around 170 degrees to test the dynamic addition
7 | # of new linear bending coordinates, and the redefinition of dihedrals.
8 | molecule allene {
9 | H 0.0 -0.92 -1.8
10 | H 0.0 0.92 -1.8
11 | C 0.0 0.00 -1.3
12 | C 0.0 0.10 0.0
13 | C 0.0 0.00 1.3
14 | H 0.92 0.00 1.8
15 | H -0.92 0.00 1.8
16 | }
17 |
18 | set {
19 | basis DZ
20 | e_convergence 10
21 | d_convergence 10
22 | scf_type pk
23 | }
24 |
25 | result = optking.optimize_psi4('scf')
26 | thisenergy = result['energies'][-1]
27 |
28 | compare_values(REF_energy, thisenergy, 6, "Reference energy")
29 |
30 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/hf-g-h2o-freq.in:
--------------------------------------------------------------------------------
1 | #! Optimization followed by frequencies H2O HF/cc-pVDZ
2 | import optking
3 |
4 | molecule h2o {
5 | O
6 | H 1 0.96
7 | H 1 0.96 2 104.5
8 | }
9 |
10 | set basis cc-pVDZ
11 | result = optking.optimize_psi4('scf')
12 |
13 | nextStepSchema = result['final_molecule']
14 | nextStepMolecule = Molecule.from_schema( nextStepSchema )
15 | set_active_molecule( nextStepMolecule )
16 |
17 | scf_e, scf_wfn = frequencies('scf', return_wfn=True, dertype=1)
18 | fd_freqs = scf_wfn.frequencies()
19 |
20 | ref_freqs = psi4.Vector(3)
21 | ref_freqs.set(0, 0, 1776.15)
22 | ref_freqs.set(0, 1, 4113.69)
23 | ref_freqs.set(0, 2, 4212.12)
24 |
25 | #ref_freqs.set(0, 0, 1775.65) These were not correct for closer/tight to minimum.
26 | #ref_freqs.set(0, 1, 4113.38) The values above came from C++ optimizer with tight convergence.
27 | #ref_freqs.set(0, 2, 4212.18)
28 |
29 | compare_vectors(ref_freqs, fd_freqs, 1, "Reference vs computed frequencies to 0.1 cm^-1")
30 |
31 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/hf-g-h2o-frozenCart.in:
--------------------------------------------------------------------------------
1 | #! SCF/cc-pVDZ optimization example with frozen cartesian
2 | import optking
3 |
4 | molecule h2o {
5 | 0 1
6 | O 1.000000 1.000000 1.000000
7 | H 2.000000 1.000000 1.000000
8 | H 1.000000 2.000000 1.000000
9 | units angstrom
10 | no_com
11 | no_reorient
12 | }
13 |
14 | set {
15 | reference rhf
16 | basis cc-pVDZ
17 | e_convergence 11
18 | guess sad
19 | scf_type df
20 | }
21 |
22 | freeze_list = '''
23 | 1 xyz'''
24 |
25 | set optking {
26 | frozen_cartesian $freeze_list
27 | }
28 |
29 | result = optking.optimize_psi4('scf')
30 | opt_energy = result['energies'][-1]
31 |
32 | compare_values(opt_energy, -76.0270327834836, 6, "SCF Optimized energy")
33 |
34 | compare_values( h2o.x(0), 1.88972613289, 6, "X Frozen coordinate")
35 | compare_values( h2o.y(0), 1.88972613289, 6, "Y Frozen coordinate")
36 | compare_values( h2o.z(0), 1.88972613289, 6, "Z Frozen coordinate")
37 |
38 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/hf-g-h2o-large.in:
--------------------------------------------------------------------------------
1 | #! SCF cc-pVTZ geometry optimzation, with Z-matrix input
2 | import optking
3 |
4 | REF_energy = -76.057769702
5 |
6 | molecule h2o {
7 | O
8 | H 1 1.0
9 | H 1 1.0 2 104.5
10 | }
11 |
12 | set {
13 | basis cc-pvtz
14 | e_convergence 10
15 | d_convergence 10
16 | scf_type pk
17 | }
18 |
19 | result = optking.optimize_psi4('scf')
20 | thisenergy = result['energies'][-1]
21 |
22 | compare_values(REF_energy, thisenergy, 6, "Reference energy")
23 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/hf-g-h2o-test-maxiter.in:
--------------------------------------------------------------------------------
1 | #! Geometry optimization that fails to converge within geom_maxiter steps. The next-step geometry
2 | #! is placed in final_molecule, and its energy is tested.
3 | import optking
4 |
5 | molecule h2o {
6 | O
7 | H 1 1.0
8 | H 1 1.0 2 104.5
9 | }
10 |
11 | set {
12 | basis cc-pvdz
13 | e_convergence 10
14 | d_convergence 10
15 | scf_type pk
16 | g_convergence gau_verytight
17 | geom_maxiter 2
18 | }
19 |
20 | result = optking.optimize_psi4('scf')
21 | compare_integers(0, int(result['success']), 'optking() hit maxiter gracefully')
22 |
23 | nextStepSchema = result['final_molecule']
24 | nextStepMolecule = Molecule.from_schema( nextStepSchema )
25 | set_active_molecule( nextStepMolecule )
26 | nextStepEnergy = energy('scf')
27 |
28 | compare_values(-76.0270534, nextStepEnergy, 6, 'Energy of next-step/final molecule')
29 |
30 | # 1 -76.021418445931 -76.021418445931 0.05227592 0.04279207 0.10706998 0.08921782 ~
31 | # 2 -76.026924207554 -0.005505761623 0.00639940 0.00521067 0.03551610 0.02119399 ~
32 | # 3 -76.027052076499 -0.000127868945 0.00069761 0.00065158 0.00274272 0.00186582 ~
33 | # 4 -76.027053484650 -0.000001408151 0.00013145 0.00010801 0.00022518 0.00018425 ~
34 | # 5 -76.027053512590 -0.000000027940 0.00000849 0.00000726 0.00002709 0.00002046 ~
35 | # 6 -76.027053512764 -0.000000000174 0.00000069 0.00000057 0.00000161 0.00000138 ~
36 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/hf-g-h2o-tight.in:
--------------------------------------------------------------------------------
1 | #! SCF cc-pVDZ geometry optimzation, with Z-matrix input
2 | import optking
3 |
4 | # nucenergy = 9.3007
5 | REF_energy = -76.027053513
6 |
7 | molecule h2o {
8 | O
9 | H 1 1.0
10 | H 1 1.0 2 104.5
11 | }
12 |
13 | set {
14 | diis false
15 | basis cc-pvdz
16 | e_convergence 10
17 | d_convergence 10
18 | g_convergence gau_tight
19 | scf_type pk
20 | }
21 |
22 | result = optking.optimize_psi4('scf')
23 |
24 | #compare_values(nucenergy, h2o.nuclear_repulsion_energy(), 4, "Nuclear repulsion energy")
25 | compare_values(REF_energy, result['energies'][-1], 9, "Reference energy")
26 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/hf-g-h2o.in:
--------------------------------------------------------------------------------
1 | #! SCF STO-3G geometry optimzation, with Z-matrix input
2 | import optking
3 |
4 | #REF_nucenergy = 8.9064890670
5 | REF_energy = -74.965901192
6 |
7 | molecule h2o {
8 | O
9 | H 1 1.0
10 | H 1 1.0 2 104.5
11 | }
12 |
13 | set {
14 | diis false
15 | basis sto-3g
16 | e_convergence 10
17 | d_convergence 10
18 | scf_type pk
19 | }
20 |
21 | result = optking.optimize_psi4('scf')
22 | compare_values(REF_energy, result['energies'][-1], 6, "Reference energy")
23 |
24 | #computedNucenergy = result['trajectory'][-1]['properties']['nuclear_repulsion_energy']
25 | #compare_values(nucenergy, computedNucenergy, 3, "Nuclear repulsion energy")
26 |
27 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/hf-g-hooh-fixed-3.in:
--------------------------------------------------------------------------------
1 | #! Various constrained energy minimizations of HOOH with cc-pvdz RHF.
2 | #! For "fixed" coordinates, the final value is provided by the user.
3 | import optking
4 |
5 | # Minimized energy with OH bonds at 0.950 Angstroms. #TEST
6 | OH_950_stre = -150.78666731 #TEST
7 | # Minimized energy with OOH angles at 105.0 degrees. #TEST
8 | OOH_105_bend = -150.78617685 #TEST
9 | # Minimized energy with HOOH torsion at 120.0 degrees. #TEST
10 | HOOH_120_dihedral = -150.78664695 #TEST
11 |
12 | set {
13 | diis false
14 | basis cc-pvdz
15 | g_convergence gau_tight
16 | }
17 |
18 | # Constrained minimization with O-H bonds fixed to reach equilibrium at 0.950 Angstroms.
19 | molecule {
20 | H
21 | O 1 0.90
22 | O 2 1.40 1 100.0
23 | H 3 0.90 2 100.0 1 115.0
24 | }
25 |
26 | set optking {
27 | fixed_distance = ("
28 | 1 2 0.950
29 | 3 4 0.950
30 | ")
31 | }
32 | result = optking.optimize_psi4('scf')
33 | thisenergy = result['energies'][-1]
34 | compare_values(OH_950_stre , thisenergy, 6, "Int. Coord. RHF opt of HOOH with O-H fixed to 0.95, energy") #TEST
35 |
36 | # Constrained minimization with O-O-H angles fixed to reach eq. at 105.0 degrees.
37 | molecule {
38 | H
39 | O 1 0.90
40 | O 2 1.40 1 100.0
41 | H 3 0.90 2 100.0 1 115.0
42 | }
43 |
44 | set optking {
45 | fixed_distance = (" ")
46 | fixed_bend = ("
47 | 1 2 3 105.0
48 | 2 3 4 105.0
49 | ")
50 | }
51 | result = optking.optimize_psi4('scf')
52 | thisenergy = result['energies'][-1]
53 | compare_values(OOH_105_bend , thisenergy, 6, "Int. Coord. RHF opt of HOOH with O-O-H fixed to 105, energy") #TEST
54 |
55 | # Constrained minimization with H-O-O-H dihedral fixed to 120.0 degrees.
56 | molecule {
57 | H
58 | O 1 0.90
59 | O 2 1.40 1 100.0
60 | H 3 0.90 2 100.0 1 115.0
61 | }
62 |
63 | set optking {
64 | fixed_bend = (" ")
65 | fixed_dihedral = ("
66 | 1 2 3 4 120.0
67 | ")
68 | }
69 | result = optking.optimize_psi4('scf')
70 | thisenergy = result['energies'][-1]
71 | compare_values(HOOH_120_dihedral , thisenergy, 6, "Int. Coord. RHF opt of HOOH with H-O-O-H fixed to 120, energy") #TEST
72 |
73 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/hf-g-hooh-frozen-3.in:
--------------------------------------------------------------------------------
1 | #! Various constrained energy minimizations of HOOH with cc-pvdz RHF
2 | #! Internal-coordinate constraints in internal-coordinate optimizations.
3 | import optking
4 |
5 | OH_frozen_stre_rhf = -150.78104113
6 | OOH_frozen_bend_rhf = -150.78628057
7 | HOOH_frozen_dihedral_rhf = -150.78667424
8 |
9 | set {
10 | diis false
11 | basis cc-pvdz
12 | }
13 |
14 | # Constrained minimization with O-H bonds frozen.
15 | molecule {
16 | H
17 | O 1 0.90
18 | O 2 1.40 1 100.0
19 | H 3 0.90 2 100.0 1 115.0
20 | }
21 |
22 | set optking {
23 | frozen_distance = ("
24 | 1 2
25 | 3 4
26 | ")
27 | }
28 | result = optking.optimize_psi4('scf')
29 | thisenergy = result['energies'][-1]
30 | compare_values(OH_frozen_stre_rhf , thisenergy, 7, "Int. Coord. RHF opt of HOOH with O-H frozen, energy")
31 |
32 | # Constrained minimization with O-O-H angles frozen.
33 | molecule {
34 | H
35 | O 1 0.90
36 | O 2 1.40 1 100.0
37 | H 3 0.90 2 100.0 1 115.0
38 | }
39 |
40 | set optking {
41 | frozen_distance = "" # here, it's been previous used, so must be blanked
42 | frozen_bend = ("
43 | 1 2 3
44 | 2 3 4
45 | ")
46 | }
47 | result = optking.optimize_psi4('scf')
48 | thisenergy = result['energies'][-1]
49 | compare_values(OOH_frozen_bend_rhf , thisenergy, 7, "Int. Coord. RHF opt of HOOH with O-O-H frozen, energy")
50 |
51 | # Constrained minimization with H-O-O-H dihedral frozen.
52 | molecule {
53 | H
54 | O 1 0.90
55 | O 2 1.40 1 100.0
56 | H 3 0.90 2 100.0 1 115.0
57 | }
58 |
59 | set optking {
60 | frozen_distance = "" # here, it's been previous used, so must be blanked
61 | frozen_bend = ""
62 | frozen_dihedral = ("
63 | 1 2 3 4
64 | ")
65 | }
66 | result = optking.optimize_psi4('scf')
67 | thisenergy = result['energies'][-1]
68 | compare_values(HOOH_frozen_dihedral_rhf , thisenergy, 7, "Int. Coord. RHF opt of HOOH with H-O-O-H frozen, energy")
69 |
70 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/hf-g-hooh-frozenCart-2.in:
--------------------------------------------------------------------------------
1 | #! Various constrained energy minimizations of HOOH with cc-pvdz RHF.
2 | #! Cartesian-coordinate constrained optimizations of HOOH in internals.
3 | import optking
4 | HOOH_E_fixed_H_xyz = -150.7866490998188
5 | HOOH_E_fixed_O_xyz = -150.7866389583059
6 |
7 | set { basis cc-pvdz }
8 |
9 | # Freeze H xyz in HOOH.
10 | molecule {
11 | H 0.90 0.80 0.5
12 | O 0.00 0.70 0.0
13 | O 0.00 -0.70 0.0
14 | H -0.90 -0.80 0.5
15 | no_com
16 | no_reorient
17 | }
18 |
19 | freeze_list = """
20 | 1 xyz
21 | 4 xyz
22 | """
23 |
24 | set optking frozen_cartesian $freeze_list
25 | result = optking.optimize_psi4('scf')
26 | thisenergy = result['energies'][-1]
27 | compare_values(HOOH_E_fixed_H_xyz, thisenergy, 6, "Int. Coord. RHF opt of HOOH with H's xyz frozen, energy")
28 |
29 | # Freeze O xyz in HOOH.
30 | molecule {
31 | H 0.90 0.80 0.5
32 | O 0.00 0.70 0.0
33 | O 0.00 -0.70 0.0
34 | H -0.90 -0.80 0.5
35 | no_com
36 | no_reorient
37 | }
38 |
39 | freeze_list = """
40 | 2 xyz
41 | 3 xyz
42 | """
43 | set optking frozen_cartesian $freeze_list
44 | result = optking.optimize_psi4('scf')
45 | thisenergy = result['energies'][-1]
46 | compare_values(HOOH_E_fixed_O_xyz, thisenergy, 6, "Int. Coord. RHF opt of HOOH with O's xyz frozen, energy")
47 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/hf-g-hooh-frozenCartInCarts-3.in:
--------------------------------------------------------------------------------
1 | #! Various constrained energy minimizations of HOOH with cc-pvdz RHF.
2 | #! Cartesian-coordinate constrained optimizations of HOOH in Cartesians.
3 | import optking
4 |
5 | HOOH_E_fixed_H_xyz = -150.7866490998188
6 | HOOH_E_fixed_O_xyz = -150.7866389583059
7 | HOOH_E = -150.786674252464
8 |
9 | set {
10 | basis cc-pvdz
11 | opt_coordinates cartesian
12 | }
13 |
14 | # Freeze H xyz in HOOH.
15 | molecule {
16 | H 0.90 0.80 0.5
17 | O 0.00 0.70 0.0
18 | O 0.00 -0.70 0.0
19 | H -0.90 -0.80 0.5
20 | no_com
21 | no_reorient
22 | }
23 |
24 | freeze_list = """
25 | 1 xyz
26 | 4 xyz
27 | """
28 |
29 | set optking frozen_cartesian $freeze_list
30 | result = optking.optimize_psi4('scf')
31 | thisenergy = result['energies'][-1]
32 | compare_values(HOOH_E_fixed_H_xyz, thisenergy, 6, "Cart. Coord. RHF opt of HOOH with H's xyz frozen, energy")
33 |
34 | # Freeze O xyz in HOOH.
35 | molecule {
36 | H 0.90 0.80 0.5
37 | O 0.00 0.70 0.0
38 | O 0.00 -0.70 0.0
39 | H -0.90 -0.80 0.5
40 | no_com
41 | no_reorient
42 | }
43 |
44 | freeze_list = """
45 | 2 xyz
46 | 3 xyz
47 | """
48 |
49 | set optking frozen_cartesian $freeze_list
50 | result = optking.optimize_psi4('scf')
51 | thisenergy = result['energies'][-1]
52 | compare_values(HOOH_E_fixed_O_xyz, thisenergy, 6, "Cart. Coord. RHF opt of HOOH with O's xyz frozen, energy")
53 |
54 | # Full optimization
55 | molecule {
56 | H 0.90 0.80 0.5
57 | O 0.00 0.70 0.0
58 | O 0.00 -0.70 0.0
59 | H -0.90 -0.80 0.5
60 | no_com
61 | no_reorient
62 | }
63 |
64 | set g_convergence gau_tight
65 |
66 | freeze_list = ""
67 | set optking frozen_cartesian $freeze_list
68 | result = optking.optimize_psi4('scf')
69 | thisenergy = result['energies'][-1]
70 | compare_values(HOOH_E, thisenergy, 6, "Cart. Coord. RHF opt of HOOH, energy")
71 |
72 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/hf-g-ketene-bent.in:
--------------------------------------------------------------------------------
1 | #! SCF cc-pVDZ geometry optimzation of ketene, starting from bent structure
2 | import optking
3 | scf_E = -151.740757212
4 |
5 | molecule h2c2o {
6 | 0 1
7 | H
8 | C 1 1.1
9 | C 2 1.3 1 130.0
10 | H 2 1.1 3 110.0 1 180.0
11 | O 3 1.1 4 120.0 1 180.0
12 | }
13 |
14 | set basis cc-pVDZ
15 | set g_convergence gau_tight
16 |
17 | result = optking.optimize_psi4('scf')
18 | thisenergy = result['energies'][-1]
19 |
20 | compare_values(scf_E, thisenergy, 8, "Reference energy")
21 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/mp2-g-h2o.in:
--------------------------------------------------------------------------------
1 | #! All-electron MP2 6-31G** geometry optimization of water
2 | import optking
3 |
4 | REF_nucenergy = 9.1622581908184
5 | REF_mp2 = -76.2224486598878
6 |
7 | molecule h2o {
8 | O
9 | H 1 1.0
10 | H 1 1.0 2 106.0
11 | }
12 |
13 | set {
14 | basis 6-31G**
15 | reference rhf
16 | d_convergence 9
17 | e_convergence 9
18 | mp2_type conv
19 | }
20 |
21 | result = optking.optimize_psi4('mp2')
22 | this_mp2 = result['energies'][-1]
23 | this_nucenergy = result['trajectory'][-1]['properties']['nuclear_repulsion_energy']
24 |
25 | compare_values(REF_nucenergy, this_nucenergy, 3, "Nuclear repulsion energy")
26 | compare_values(REF_mp2, this_mp2, 6, "CONV MP2 energy")
27 |
28 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/scsomp2-g-h2o.in:
--------------------------------------------------------------------------------
1 | #! SCS-OMP2 cc-pVDZ geometry optimization for the H2O molecule.
2 | import optking
3 |
4 | REF_nuc = 9.11180990045111
5 | REF_scf = -76.02608509946806
6 | REF_scsomp2 = -76.22804532525168
7 |
8 | molecule h2o {
9 | 0 1
10 | o
11 | h 1 0.958
12 | h 1 0.958 2 104.4776
13 | }
14 |
15 | set {
16 | basis cc-pvdz
17 | }
18 |
19 | result = optking.optimize_psi4('scs-omp2')
20 |
21 | this_nucenergy = result['trajectory'][-1]['properties']['nuclear_repulsion_energy']
22 | this_scf = result['trajectory'][-1]['properties']['scf_total_energy']
23 | this_energy = result['energies'][-1]
24 |
25 | compare_values(REF_nuc, this_nucenergy, 5, "Nuclear Repulsion Energy (a.u.)");
26 | compare_values(REF_scf, this_scf, 6, "SCF Energy (a.u.)");
27 | compare_values(REF_scsomp2, this_energy, 6, "SCS-OMP2 Total Energy (a.u.)");
28 |
29 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/scsomp3-g-h2o.in:
--------------------------------------------------------------------------------
1 | #! SCS-OMP3 cc-pVDZ geometry optimization for the H2O molecule.
2 | import optking
3 |
4 | REF_nuc = 9.11871568396669
5 | REF_scf = -76.02615852683365
6 | REF_scsomp3 = -76.22962586987757
7 |
8 | molecule h2o {
9 | 0 1
10 | o
11 | h 1 0.958
12 | h 1 0.958 2 104.4776
13 | }
14 |
15 | set {
16 | basis cc-pvdz
17 | }
18 |
19 | result = optking.optimize_psi4('scs-omp3')
20 | this_nuc = result['trajectory'][-1]['properties']['nuclear_repulsion_energy']
21 | this_scf = result['trajectory'][-1]['properties']['scf_total_energy']
22 | this_energy = result['energies'][-1]
23 |
24 | compare_values(REF_nuc, this_nuc, 5, "Nuclear Repulsion Energy (a.u.)");
25 | compare_values(REF_scf, this_scf, 6, "SCF Energy (a.u.)");
26 | compare_values(REF_scsomp3, this_energy, 6, "SCS-OMP3 Total Energy (a.u.)");
27 |
28 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/sosomp2-g-h2o.in:
--------------------------------------------------------------------------------
1 | #! SOS-OMP2 cc-pVDZ geometry optimization for the H2O molecule.
2 | import optking
3 |
4 | REF_nuc = 9.12295422215394
5 | REF_scf = -76.02621188217395
6 | REF_sosomp2 = -76.21065070996092
7 |
8 | molecule h2o {
9 | 0 1
10 | o
11 | h 1 0.958
12 | h 1 0.958 2 104.4776
13 | }
14 |
15 | set {
16 | basis cc-pvdz
17 | }
18 |
19 | result = optking.optimize_psi4('sos-omp2')
20 | this_nuc = result['trajectory'][-1]['properties']['nuclear_repulsion_energy']
21 | this_scf = result['trajectory'][-1]['properties']['scf_total_energy']
22 | this_energy = result['energies'][-1]
23 |
24 |
25 | compare_values(REF_nuc, this_nuc, 4, "Nuclear Repulsion Energy (a.u.)");
26 | compare_values(REF_scf, this_scf, 6, "SCF Energy (a.u.)");
27 | compare_values(REF_sosomp2, this_energy, 6, "SOS-OMP2 Total Energy (a.u.)");
28 |
29 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/sosomp3-g-h2o.in:
--------------------------------------------------------------------------------
1 | #! SOS-OMP3 cc-pVDZ geometry optimization for the H2O molecule.
2 | import optking
3 |
4 | REF_nuc = 9.11294430202143
5 | REF_scf = -76.02611710513384
6 | REF_sosomp3 = -76.22772062866821
7 |
8 | molecule h2o {
9 | 0 1
10 | o
11 | h 1 0.958
12 | h 1 0.958 2 104.4776
13 | }
14 |
15 | set {
16 | basis cc-pvdz
17 | }
18 |
19 | result = optking.optimize_psi4('sos-omp3')
20 | this_nuc = result['trajectory'][-1]['properties']['nuclear_repulsion_energy']
21 | this_scf = result['trajectory'][-1]['properties']['scf_total_energy']
22 | this_energy = result['energies'][-1]
23 |
24 | compare_values(REF_nuc, this_nuc, 5, "Nuclear Repulsion Energy (a.u.)");
25 | compare_values(REF_scf, this_scf, 6, "SCF Energy (a.u.)");
26 | compare_values(REF_sosomp3, this_energy, 6, "SOS-OMP3 Total Energy (a.u.)");
27 |
28 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/todo-psi4tests.txt:
--------------------------------------------------------------------------------
1 | # Jan. 2019, Converting existing Psi4 test cases to here to see
2 | # how much functionality we can reproduce, and to test the
3 | # optimizer.
4 |
5 | * Input filename here * Previous directory name in psi4/tests
6 | _______________________________________________________________
7 | TODO:
8 | OK for 7-8 steps, but fails when step breaks c2v symmetry.
9 | May require fixing bond axes between steps.
10 | hf-g-SF4-breaksLinear opt14
11 |
12 | # TODO : other possible tests to examine.
13 | hf-h-h2o-fullHessEvery opt-full-hess-every
14 | ccsd-g-h2o-freqs cc3
15 | hf-g-h2o-freq tu4-h2o-freq
16 | irc-hf-g-hooh opt-irc-1
17 | irc-hf-g-hcn-2 opt-irc-2
18 | irc-hf-g-hooh-tight opt-irc-3
19 | mp2-g-ch4Dimer-fragsC1 opt-multi-dimer-c1
20 | mp2-g-ch4Dimer-fragsC2h opt-multi-dimer-c2h
21 | mp2-g-ch4Dimer-fragsFrozen opt-multi-frozen-dimer-c2h
22 | hf-g-h2o-freqIsotope1 freq-isotope1
23 | hf-g-h2o-freqIsotope2 freq-isotope2
24 | hf-g-several-gibbs gibbs
25 | hf-g-h2oTrimer-freq nbody-freq
26 |
27 | # TODO: get finite differences of energies working
28 | # Got one working using psi4_optimize( dertype=0)
29 | # converted into a keyword argument, and then processed
30 | # by a modified driver/schema_wrapper.py
31 | hf-e-alleneLinear opt2-fd
32 | ccsd-e-h2o cc2
33 | cisd-e-h2o cisd-opt-fd
34 |
35 | # Too computationally large of a test to keep?
36 | ts-mp2-gh-C5H8N2 opt10
37 |
38 | # Worry about later or forget?
39 | cbs-xtpl-func
40 | cbs-xtpl-opt
41 | cbs-xtpl-wrapper
42 | hf-g-benzene-pubchem
43 | pywrap-all
44 | pywrap-db2
45 | pywrap-opt-sowreap
46 | opt-lindep-change
47 | tu3-h2o-opt
48 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/ts-hf-g-hooh-2.in:
--------------------------------------------------------------------------------
1 | #! Transition-state optimizations of HOOH to both torsional transition states.
2 | import optking
3 | TORS_ENERGY = -150.7853070
4 | ZERO_TORS_ENERGY = -150.7739141
5 |
6 | # Optimization to 180 degree torsion from 120
7 | molecule hooh {
8 | 0 1
9 | H
10 | O 1 0.95
11 | O 2 1.40 1 105.0
12 | H 3 0.95 2 105.0 1 120.0
13 | noreorient
14 | }
15 | set {
16 | basis cc-pvdz
17 | opt_type ts
18 | docc = [ 5 , 4 ]
19 | intrafrag_step_limit 0.1
20 | # loose convergence criteria due to scf convergence problems as c2h structure is approached
21 | MAX_FORCE_G_CONVERGENCE 5.0e-4
22 | }
23 |
24 | result = optking.optimize_psi4('scf')
25 | thisenergy = result['energies'][-1]
26 | compare_values(TORS_ENERGY, thisenergy, 6, "cc-pVDZ RHF transition-state opt. of HOOH (dihedral=180), energy")
27 |
28 | # Optimization to 0 degree torsion from 100
29 | molecule hooh {
30 | H
31 | O 1 0.95
32 | O 2 1.40 1 105.0
33 | H 3 0.95 2 105.0 1 100.0
34 | }
35 |
36 | result = optking.optimize_psi4('scf')
37 | thisenergy = result['energies'][-1]
38 | compare_values(ZERO_TORS_ENERGY, thisenergy, 6, "cc-pVDZ RHF transition-state opt. of HOOH (dihedral=0), energy")
39 |
40 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/uccsd-g-ch2.in:
--------------------------------------------------------------------------------
1 | #! UHF-CCSD/cc-pVDZ $^{3}B@@1$ CH2 geometry optimization via analytic gradients
2 | import optking
3 |
4 | REF_scf = -38.92658702693478
5 | REF_ccsd = -0.11533612150975
6 | REF_total = -39.04192314844453
7 |
8 | molecule ch2 {
9 | 0 3
10 | C
11 | H 1 1.1
12 | H 1 1.1 2 109.0
13 | }
14 |
15 | set {
16 | reference uhf
17 | basis cc-pvdz
18 | max_disp_g_convergence 1e-6
19 | max_force_g_convergence 1.0e-6
20 | max_energy_g_convergence 7
21 | e_convergence 10
22 | d_convergence 10
23 | }
24 |
25 | result = optking.optimize_psi4('CCSD')
26 |
27 | this_scf = result['trajectory'][-1]['properties']['scf_total_energy']
28 | this_ccsd = result['trajectory'][-1]['properties']['ccsd_correlation_energy']
29 | this_total = result['trajectory'][-1]['properties']['return_energy']
30 |
31 | compare_values(REF_scf, this_scf, 6, "SCF energy")
32 | compare_values(REF_ccsd, this_ccsd, 6, "CCSD contribution")
33 | compare_values(REF_total, this_total, 6, "Total energy")
34 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/uccsdpt-g-ch2.in:
--------------------------------------------------------------------------------
1 | #! UHF-CCSD(T)/cc-pVDZ $^{3}B@@1$ CH2 geometry optimization via analytic gradients
2 | import optking
3 |
4 | molecule ch2 {
5 | 0 3
6 | C
7 | H 1 1.1
8 | H 1 1.1 2 109.0
9 | }
10 |
11 | set {
12 | reference uhf
13 | basis cc-pvdz
14 | max_disp_g_convergence 1e-6
15 | max_force_g_convergence 1.0e-6
16 | max_energy_g_convergence 7
17 | e_convergence 10
18 | r_convergence 10
19 | }
20 |
21 | result = optking.optimize_psi4('CCSD(T)')
22 |
23 | REF_scf = -38.92655208442658
24 | REF_ccsd_t = -0.11716018769631
25 | REF_total = -39.04371227103925
26 |
27 | this_scf = result['trajectory'][-1]['properties']['scf_total_energy']
28 | this_ccsd_t = result['trajectory'][-1]['properties']['ccsd_prt_pr_correlation_energy']
29 | this_total = result['trajectory'][-1]['properties']['ccsd_prt_pr_total_energy']
30 | this_return = result['trajectory'][-1]['properties']['return_energy']
31 |
32 | compare_values(REF_scf, this_scf, 6, "SCF energy")
33 | compare_values(REF_ccsd_t, this_ccsd_t, 6, "CCSD(T) contribution")
34 | compare_values(REF_total, this_total, 6, "Total CCSD(T) energy")
35 | compare_values(REF_total, this_return, 6, "Total CCSD(T) return energy")
36 |
37 |
--------------------------------------------------------------------------------
/optking/tests/psi4inputs/psithon_versions/uhf-g-ch2-dummy.in:
--------------------------------------------------------------------------------
1 | #! 6-31G** UHF CH2 3B1 optimization. Uses a Z-Matrix with dummy atoms, just for demo and testing purposes.
2 | import optking
3 |
4 | REF_energy = -38.925486977153
5 |
6 | molecule ch2 {
7 | 0 3
8 | c
9 | x 1 1.0
10 | h 1 b1 2 a1
11 | h 1 b1 2 a1 3 180.0
12 |
13 | b1 = 1.0
14 | a1 = 60.0
15 | }
16 |
17 | set {
18 | reference uhf
19 | basis 6-31G(d,p)
20 | docc [2, 0, 0, 1]
21 | socc [1, 0, 1, 0]
22 | scf_type pk
23 | }
24 |
25 | result = optking.optimize_psi4('scf')
26 | thisenergy = result['energies'][-1]
27 |
28 | compare_values(REF_energy, thisenergy, 6, "Reference energy")
29 |
--------------------------------------------------------------------------------
/optking/tests/test_2_hessians.py:
--------------------------------------------------------------------------------
1 | import logging
2 | import pytest
3 | import psi4
4 | import optking
5 | from .utils import utils
6 |
7 | final_energy = -150.786766850
8 | hess_every = [(-1, final_energy, 10), (0, final_energy, 10), (1, final_energy, 4), (3, final_energy, 5)]
9 | hess_guess = [
10 | ("fischer", final_energy, 9),
11 | ("lindH_simple", final_energy, 11),
12 | ("simple", final_energy, 12),
13 | ("lindh", final_energy, 16),
14 | ]
15 | hess_update = [("MS", final_energy, 10), ("powell", final_energy, 11), ("bofill", final_energy, 10)]
16 |
17 | logger = optking.logger
18 |
19 |
20 | @pytest.mark.parametrize("every, expected, num_steps", hess_every, ids=["None", "First Step", "Every", "Every 3"])
21 | def test_hess_every(check_iter, every, expected, num_steps):
22 |
23 | hooh = psi4.geometry(
24 | """
25 | H
26 | O 1 0.95
27 | O 2 1.39 1 102.0
28 | H 3 0.95 2 102.0 1 130.0
29 | """
30 | )
31 |
32 | psi4.core.clean_options()
33 | psi4_options = {
34 | "basis": "cc-pvdz",
35 | "scf_type": "pk",
36 | "g_convergence": "gau_verytight",
37 | "full_hess_every": every,
38 | "print": 4,
39 | }
40 |
41 | psi4.set_options(psi4_options)
42 | json_output = optking.optimize_psi4("hf") # Uses default program (psi4)
43 | E = json_output["energies"][-1]
44 |
45 | assert psi4.compare_values(expected, E, 8, "Final energy, every step Hessian") # TEST
46 |
47 | utils.compare_iterations(json_output, num_steps, check_iter)
48 |
49 |
50 | @pytest.mark.parametrize("guess, expected, num_steps", hess_guess)
51 | def test_hess_guess(check_iter, guess, expected, num_steps):
52 |
53 | hooh = psi4.geometry(
54 | """
55 | H
56 | O 1 0.95
57 | O 2 1.39 1 102.0
58 | H 3 0.95 2 102.0 1 130.0
59 | """
60 | )
61 |
62 | psi4.core.clean_options()
63 | psi4_options = {"basis": "cc-pvdz", "scf_type": "pk", "g_convergence": "gau_verytight", "intrafrag_hess": guess}
64 |
65 | psi4.set_options(psi4_options)
66 | json_output = optking.optimize_psi4("hf") # Uses default program (psi4)
67 | E = json_output["energies"][-1]
68 | print(f"Number of steps taken {len(json_output['trajectory'])}")
69 | assert psi4.compare_values(expected, E, 8, "Final energy, every step Hessian") # TEST
70 |
71 | utils.compare_iterations(json_output, num_steps, check_iter)
72 |
73 |
74 | @pytest.mark.parametrize("update, expected, num_steps", hess_update)
75 | def test_hess_update(check_iter, update, expected, num_steps):
76 |
77 | hooh = psi4.geometry(
78 | """
79 | H
80 | O 1 0.95
81 | O 2 1.39 1 102.0
82 | H 3 0.95 2 102.0 1 130.0
83 | """
84 | )
85 |
86 | psi4.core.clean_options()
87 | psi4_options = {"basis": "cc-pvdz", "scf_type": "pk", "g_convergence": "gau_verytight", "hess_update": update}
88 |
89 | psi4.set_options(psi4_options)
90 | json_output = optking.optimize_psi4("hf") # Uses default program (psi4)
91 | E = json_output["energies"][-1]
92 |
93 | assert psi4.compare_values(expected, E, 8, "Final energy, every step Hessian") # TEST
94 |
95 | utils.compare_iterations(json_output, num_steps, check_iter)
96 |
97 | def test_hess_read(check_iter):
98 | import os
99 | hooh = psi4.geometry(
100 | """
101 | H
102 | O 1 0.95
103 | O 2 1.39 1 102.0
104 | H 3 0.95 2 102.0 1 130.0
105 | """
106 | )
107 |
108 | psi4_options = {
109 | "basis": "cc-pvdz",
110 | "scf_type": "pk",
111 | "g_convergence": "gau_verytight",
112 | "hessian_write": True,
113 | }
114 |
115 | psi4.set_options(psi4_options)
116 | json_output = psi4.frequencies("hf") # Uses default program (psi4)
117 |
118 | psi4.core.clean_options()
119 | psi4_options = {
120 | "basis": "cc-pvdz",
121 | "scf_type": "pk",
122 | "g_convergence": "gau_verytight",
123 | "cart_hess_read": True,
124 | }
125 |
126 | psi4.set_options(psi4_options)
127 | json_output = optking.optimize_psi4("hf", **{"cart_hess_read": True, "hessian_file": f"stdout.default.{os.getpid()}.hess"})
128 | E = json_output["energies"][-1]
129 | assert psi4.compare_values(final_energy, E, 8, "Final energy, every step Hessian") # TEST
130 | utils.compare_iterations(json_output, 10, check_iter)
131 |
132 |
--------------------------------------------------------------------------------
/optking/tests/test_atom.py:
--------------------------------------------------------------------------------
1 | #! Test handling of atom. No optimization, computes energy.
2 | import psi4
3 | import optking
4 |
5 | RefEnergy = -127.8037761406364581
6 |
7 | def test_atom():
8 | mol = psi4.geometry( """ Ne 0.0 0.0 0.0 """ )
9 | psi4.core.clean_options()
10 | psi4.set_options({ "basis": "3-21G" })
11 |
12 | qc_output = optking.optimize_psi4("hf")
13 |
14 | E = qc_output['energies'][-1]
15 | success = qc_output['success']
16 | Etraj = qc_output["trajectory"][-1]['extras']['qcvars']['CURRENT ENERGY']
17 |
18 | assert not qc_output['success']
19 | assert qc_output["error"]["error_message"] == "There is only 1 atom. Nothing to optimize. Computing energy."
20 | assert psi4.compare_values(E, RefEnergy, 6, "Atom energy (energies)")
21 | assert psi4.compare_values(Etraj, RefEnergy, 6, "Atom energy (trajectory)")
22 |
23 |
--------------------------------------------------------------------------------
/optking/tests/test_atom_stepwise.py:
--------------------------------------------------------------------------------
1 | #! Test handling of atom for non optimize_psi4 case. No optimization, computes energy.
2 | import psi4
3 | import optking
4 | import numpy as np
5 |
6 | from optking.optparams import OptParams
7 | from optking.molsys import Molsys
8 | from optking.optimize import OptimizationManager
9 | from optking.optwrapper import make_computer
10 | from optking.history import History
11 | from optking.exceptions import OptError
12 |
13 | RefEnergy = -127.8037761406364581
14 |
15 | def test_atom_stepwise():
16 | neon = psi4.geometry(""" Ne """)
17 |
18 | psi4.core.clean_options()
19 |
20 | params = OptParams({})
21 | history = History(params)
22 | opt_mol, qcschema_mol = Molsys.from_psi4(neon)
23 |
24 | opt_input = {
25 | #"keywords": {}, for optimizer, optional
26 | "initial_molecule": qcschema_mol,
27 | "input_specification": {
28 | "model": {"basis": "3-21G", "method": 'hf'},
29 | "driver": "gradient",
30 | "keywords": {},
31 | },
32 | }
33 | computer = make_computer(opt_input, "psi4")
34 |
35 | opt_manager = OptimizationManager(opt_mol, history, params, computer)
36 |
37 | try:
38 | opt_manager.start_step(np.array(0))
39 | assert False
40 | except OptError as error:
41 | qc_output = opt_manager.opt_error_handler(error)
42 | E = qc_output['energies'][-1]
43 | Etraj = qc_output["trajectory"][-1]['extras']['qcvars']['CURRENT ENERGY']
44 |
45 | assert not qc_output['success']
46 | assert qc_output["error"]["error_message"] == "There is only 1 atom. Nothing to optimize. Computing energy."
47 | assert psi4.compare_values(RefEnergy, E, 6, "Atom energy (energies)")
48 | assert psi4.compare_values(RefEnergy, E, 6, "Atom energy (trajectory)")
49 |
50 |
--------------------------------------------------------------------------------
/optking/tests/test_auxiliary_bonds.py:
--------------------------------------------------------------------------------
1 | #! Test of adding auxiliary bonds. These are stre coordinates between
2 | #! two non-H atoms that are < 2.5(sum of covalent radii) but NOT already
3 | #! connected by 3 stretches as in A-x-y-B.
4 |
5 | # Here are number of iterations to convergence as of Jan 2022 for 3 molecules
6 | # in Baker database:
7 | # menthone ACHTAR10 histidine
8 | # 2 bonds added 1 bond added 1 bond added
9 | # RHF/6-31+G* 11 -> 10 RHF/6-31+G* 13 -> 11 RHF/6-31+G* 15 -> 16
10 | # B3LYP/6-31+G* 10 -> 9 B3LYP/6-31+G* 12 -> 11 B3LYP/6-31+G* 14 -> 14
11 | # TODO: explore FISCHER Hessian guess alongside auxiliary bonds performance
12 |
13 | import psi4
14 | import optking
15 | import pytest
16 | from .utils import utils
17 |
18 | menthone = psi4.geometry("""
19 | 0 1
20 | O 0.00000000 0.00000000 4.83502957
21 | C -5.06597212 -1.27592091 0.49885049
22 | C -3.60348796 -1.49111229 -2.01995066
23 | C -1.13779972 0.12182250 -2.02402508
24 | C 0.69335828 -0.53324847 0.24699141
25 | C -0.81879368 -0.76420189 2.79442766
26 | C -3.41755812 -2.06413311 2.77868746
27 | C 0.08327139 -0.18247958 -4.66184769
28 | C 3.16977849 1.11788425 0.33780916
29 | C 5.23967937 0.00000000 2.05851212
30 | C 2.74820737 3.91648659 1.03692914
31 | H -5.73534045 0.69223903 0.75660810
32 | H -6.80139535 -2.44289264 0.43045930
33 | H -3.15419510 -3.50140339 -2.39715388
34 | H -4.86109777 -0.90264082 -3.58603040
35 | H -1.71463208 2.12647811 -1.82542348
36 | H 1.33530286 -2.48925976 -0.10949068
37 | H -4.41049264 -1.64891601 4.56938165
38 | H -3.10227312 -4.12767303 2.77142958
39 | H -1.27515064 0.19340176 -6.20625544
40 | H 0.83979297 -2.10810531 -4.96157719
41 | H 1.65711962 1.15531285 -4.96195049
42 | H 4.01314574 1.10167735 -1.57473542
43 | H 4.69908810 0.02990650 4.07747056
44 | H 7.03475689 1.05859686 1.90111311
45 | H 5.66887645 -1.98486988 1.56898286
46 | H 4.52277834 5.01677786 0.95132487
47 | H 1.98900684 4.13531008 2.97264568
48 | H 1.40402606 4.85096335 -0.25821233
49 | units bohr
50 | """)
51 |
52 | ACHTAR10 = psi4.geometry("""
53 | 0 1
54 | O 0.00000000 0.00000000 3.93735249
55 | O 1.79875939 0.00000000 -0.09531034
56 | N -4.40589519 1.32037243 -3.31810156
57 | C -2.43021636 -0.18962157 -2.05696026
58 | C -0.22185404 1.49597798 -1.20775357
59 | C 1.69726730 -0.59259412 2.46067577
60 | C 3.97685548 -2.11479138 3.27934906
61 | H -3.68043380 2.27933244 -4.84082518
62 | H -5.10144333 2.68085421 -2.12147722
63 | H -3.24985392 -1.18842676 -0.41051393
64 | H -1.74547418 -1.68142667 -3.35347133
65 | H 0.55351430 2.51912058 -2.85842920
66 | H -0.88071695 2.99188292 0.10524925
67 | H 5.73529679 -1.04410557 2.94759034
68 | H 4.08562680 -3.90736002 2.21955987
69 | H 3.86856770 -2.56921447 5.31306580
70 | units bohr
71 | """)
72 |
73 | HF_expected_noaux = {'menthone': 11, 'ACHTAR10': 13}
74 | HF_expected_aux = {'menthone': 10, 'ACHTAR10': 11}
75 | HF_E = {'menthone': -464.0439981504222, 'ACHTAR10': -360.90442278650494}
76 |
77 | B3LYP_expected_noaux = {'menthone': 10, 'ACHTAR10': 12}
78 | B3LYP_expected_aux = {'menthone': 9, 'ACHTAR10': 11}
79 | B3LYP_E = {'menthone': -467.157103348465, 'ACHTAR10': -363.065807664032}
80 |
81 | @pytest.mark.long
82 | def test_auxiliary_bonds(check_iter):
83 | for molname in ['menthone', 'ACHTAR10']:
84 | psi4.core.set_active_molecule(eval(molname))
85 |
86 | psi4.core.clean_options()
87 | psi4.set_options({ "basis": "6-31+G*", })
88 |
89 | result = optking.optimize_psi4("HF")
90 | utils.compare_iterations(result, HF_expected_noaux[molname], check_iter)
91 | E = result["energies"][-1]
92 | assert psi4.compare_values(HF_E[molname], E, 5, "HF energy")
93 |
94 | psi4.core.set_active_molecule(eval(molname))
95 | psi4.core.clean_options()
96 |
97 | psi4.set_options({ "basis": "6-31+G*", })
98 | optking_options = {"add_auxiliary_bonds": True}
99 |
100 | result = optking.optimize_psi4("HF", **optking_options)
101 | utils.compare_iterations(result, HF_expected_aux[molname], check_iter)
102 | E = result["energies"][-1]
103 | assert psi4.compare_values(HF_E[molname], E, 5, "HF energy")
104 |
105 |
--------------------------------------------------------------------------------
/optking/tests/test_ccsd_g_opt.py:
--------------------------------------------------------------------------------
1 | import psi4
2 | import optking
3 | import pytest
4 | from .utils import utils
5 |
6 | #! RHF-CCSD 6-31G** all-electron opt of H2O, default convergence
7 | def test_ccsd_h2o(check_iter):
8 |
9 | h2o = psi4.geometry(
10 | """
11 | O
12 | H 1 0.97
13 | H 1 0.97 2 103.0
14 | """
15 | )
16 |
17 | psi4.core.clean_options()
18 | psi4_options = {"basis": "6-31G**", "scf_type": "pk"}
19 | psi4.set_options(psi4_options)
20 |
21 | result = optking.optimize_psi4("ccsd")
22 | print(result["trajectory"][-1].keys())
23 |
24 | this_scf = result["trajectory"][-1]["properties"]["scf_total_energy"] # TEST
25 | this_ccsd = result["trajectory"][-1]["properties"]["ccsd_correlation_energy"] # TEST
26 | this_total = result["trajectory"][-1]["properties"]["return_energy"] # TEST
27 | REF_scf = -76.0229406477 # TEST
28 | REF_ccsd = -0.2082378354 # TEST
29 | REF_total = -76.2311784830 # TEST
30 | assert psi4.compare_values(REF_scf, this_scf, 4, "SCF energy") # TEST
31 | assert psi4.compare_values(REF_ccsd, this_ccsd, 4, "CCSD contribution") # TEST
32 | assert psi4.compare_values(REF_total, this_total, 4, "Total energy") # TEST
33 |
34 | utils.compare_iterations(result, 3, check_iter)
35 |
36 |
37 | #! ROHF-CCSD/cc-pVDZ $^{3}B@@1$ CH2 geometry opt, analytic gradients, tight
38 | def test_ccsd_ch2(check_iter):
39 |
40 | ch2 = psi4.geometry(
41 | """
42 | 0 3
43 | C
44 | H 1 1.1
45 | H 1 1.1 2 109.0
46 | """
47 | )
48 |
49 | psi4.core.clean_options()
50 | psi4_options = {
51 | "reference": "rohf",
52 | "basis": "cc-pvdz",
53 | "max_disp_g_convergence": 1e-6,
54 | "max_force_g_convergence": 1.0e-6,
55 | "max_energy_g_convergence": 7,
56 | "e_convergence": 10,
57 | "r_convergence": 10,
58 | "scf_type": "pk",
59 | }
60 | psi4.set_options(psi4_options)
61 |
62 | result = optking.optimize_psi4("CCSD")
63 |
64 | this_scf = result["trajectory"][-1]["properties"]["scf_total_energy"] # TEST
65 | this_ccsd = result["trajectory"][-1]["properties"]["ccsd_correlation_energy"] # TEST
66 | this_total = result["trajectory"][-1]["properties"]["return_energy"] # TEST
67 | REF_scf = -38.9213947335 # TEST
68 | REF_cor = -0.1204840983 # TEST
69 | REF_tot = -39.0418788319 # TEST
70 | assert psi4.compare_values(REF_scf, this_scf, 6, "ROHF energy") # TEST
71 | assert psi4.compare_values(REF_cor, this_ccsd, 6, "ROHF CCSD contribution") # TEST
72 | assert psi4.compare_values(REF_tot, this_total, 6, "ROHF CCSD Total energy") # TEST
73 |
74 | utils.compare_iterations(result, 9, check_iter)
75 |
76 |
77 | #! UHF-CCSD/cc-pVDZ $^{3}B@@1$ CH2 geometry opt via analytic gradients, tight
78 | def test_uccsd_ch2(check_iter):
79 |
80 | ch2 = psi4.geometry(
81 | """
82 | 0 3
83 | C
84 | H 1 1.1
85 | H 1 1.1 2 109.0
86 | """
87 | )
88 |
89 | psi4.core.clean_options()
90 | psi4_options = {
91 | "reference": "uhf",
92 | "basis": "cc-pvdz",
93 | "max_disp_g_convergence": 1e-6,
94 | "max_force_g_convergence": 1.0e-6,
95 | "max_energy_g_convergence": 7,
96 | "e_convergence": 10,
97 | "r_convergence": 10,
98 | "scf_type": "pk",
99 | }
100 | psi4.set_options(psi4_options)
101 |
102 | result = optking.optimize_psi4("CCSD")
103 |
104 | this_scf = result["trajectory"][-1]["properties"]["scf_total_energy"] # TEST
105 | this_ccsd = result["trajectory"][-1]["properties"]["ccsd_correlation_energy"] # TEST
106 | this_total = result["trajectory"][-1]["properties"]["return_energy"] # TEST
107 | REF_scf = -38.9265869596 # TEST
108 | REF_ccsd = -0.1153361899 # TEST
109 | REF_total = -39.0419231495 # TEST
110 | assert psi4.compare_values(REF_scf, this_scf, 6, "UHF energy") # TEST
111 | assert psi4.compare_values(REF_ccsd, this_ccsd, 6, "UHF CCSD contribution") # TEST
112 | assert psi4.compare_values(REF_total, this_total, 6, "UCCSD Total energy") # TEST
113 |
114 | utils.compare_iterations(result, 9, check_iter)
115 |
116 |
117 | #! UHF-CCSD(T)/cc-pVDZ $^{3}B@@1$ CH2 geometry optimization via analytic gradients
118 | @pytest.mark.long
119 | def test_uccsdpt_ch2(check_iter):
120 |
121 | ch2 = psi4.geometry(
122 | """
123 | 0 3
124 | C
125 | H 1 1.1
126 | H 1 1.1 2 109.0
127 | """
128 | )
129 |
130 | psi4.core.clean_options()
131 | psi4_options = {
132 | "reference": "uhf",
133 | "basis": "cc-pvdz",
134 | "max_disp_g_convergence": 1e-6,
135 | "max_force_g_convergence": 1.0e-6,
136 | "max_energy_g_convergence": 7,
137 | "e_convergence": 10,
138 | "r_convergence": 10,
139 | "scf_type": "pk",
140 | }
141 | psi4.set_options(psi4_options)
142 |
143 | result = optking.optimize_psi4("CCSD(T)")
144 |
145 | this_ccsd_t = result["trajectory"][-1]["properties"]["ccsd_prt_pr_correlation_energy"] # TEST
146 | this_total = result["trajectory"][-1]["properties"]["ccsd_prt_pr_total_energy"] # TEST
147 | REF_scf = -38.9265520844 # TEST. Value is not currently included in trajectory output
148 | REF_ccsd_t = -0.1171601876 # TEST
149 | REF_total = -39.0437122710 # TEST
150 | assert psi4.compare_values(REF_ccsd_t, this_ccsd_t, 6, "CCSD(T) contribution") # TEST
151 | assert psi4.compare_values(REF_total, this_total, 6, "Total CCSD(T) energy") # TEST
152 |
153 | utils.compare_iterations(result, 9, check_iter)
154 |
155 |
--------------------------------------------------------------------------------
/optking/tests/test_conjugate.py:
--------------------------------------------------------------------------------
1 | #! Test conjugate gradient algorithms by optimizing propylamine
2 | #! For comparison steepest descent converges in 16 iterations.
3 | import pytest
4 |
5 | import psi4
6 | import optking
7 | from .utils import utils
8 |
9 | check_iter = True
10 |
11 | refE = -173.3000252
12 | cg_step_types = [("FLETCHER",14),("DESCENT", 24), ("POLAK", 44)]
13 |
14 | @pytest.mark.long
15 | @pytest.mark.parametrize("option, num_steps", cg_step_types, ids=["FLETCHER","DESCENT","POLAK"])
16 | def test_conjugate_gradient_type(option, num_steps, check_iter):
17 | propylamine = psi4.geometry(
18 | """
19 | N 1.8767 -0.1522 -0.0054
20 | C -0.5459 -0.5165 0.0053
21 | C 0.5800 0.5145 0.0053
22 | C -1.9108 0.1542 -0.0052
23 | H -0.4629 -1.1669 -0.8740
24 | H -0.4700 -1.1586 0.8912
25 | H 0.5127 1.1539 0.8920
26 | H 0.5047 1.1629 -0.8741
27 | H -2.0434 0.7874 0.8779
28 | H -2.0351 0.7769 -0.8969
29 | H -2.7039 -0.6001 -0.0045
30 | H 1.9441 -0.7570 -0.8233
31 | H 1.9519 -0.7676 0.8039
32 | """
33 | )
34 |
35 | psi4.core.clean_options()
36 | psi4_options = {"basis": "cc-pVDZ", "d_convergence": 10, "geom_maxiter": 70}
37 | psi4.set_options(psi4_options)
38 |
39 | optking_options = {
40 | "step_type" : "CONJUGATE",
41 | "conjugate_gradient_type" : option
42 | }
43 |
44 | json_output = optking.optimize_psi4("hf", **optking_options)
45 | thisenergy = json_output["energies"][-1]
46 |
47 | assert psi4.compare_values(refE, thisenergy, 5)
48 | utils.compare_iterations(json_output, num_steps, check_iter)
49 |
50 |
--------------------------------------------------------------------------------
/optking/tests/test_dcft_g_opt.py:
--------------------------------------------------------------------------------
1 | import psi4
2 | import optking
3 | from .utils import utils
4 |
5 | #! DC-06 calculation for the O2 molecule (triplet ground state). This performs
6 | #! geometry optimization using two-step and simultaneous solution of the
7 | #! response equations for the analytic gradient.
8 | def test_dcft_O2(check_iter):
9 | o2 = psi4.geometry(
10 | """
11 | 0 3
12 | O
13 | O 1 R
14 | R = 1.230
15 | """
16 | )
17 |
18 | psi4.core.clean_options()
19 | psi4_options = {
20 | "r_convergence": 10,
21 | "algorithm": "twostep",
22 | "response_algorithm": "twostep",
23 | "basis": "dzp",
24 | "max_disp_g_convergence": 1e-6,
25 | "rms_force_g_convergence": 1e-6,
26 | "max_energy_g_convergence": 1e-7,
27 | "reference": "uhf",
28 | "dct_functional": "dc-06",
29 | }
30 | psi4.set_options(psi4_options)
31 |
32 | result = optking.optimize_psi4("dct")
33 |
34 | this_uhf = result["trajectory"][-1]["properties"]["scf_total_energy"] # TEST
35 | this_mp2 = result["trajectory"][-1]["properties"]["mp2_total_energy"] # TEST
36 | this_dct = result["energies"][-1] # TEST
37 | REF_uhf = -149.6520519320 # TEST
38 | REF_mp2 = -150.0109986566 # TEST
39 | REF_dct = -150.0227937862 # TEST
40 | assert psi4.compare_values(REF_uhf, this_uhf, 6, "UHF Energy") # TEST
41 | assert psi4.compare_values(REF_mp2, this_mp2, 6, "MP2 Energy") # TEST
42 | assert psi4.compare_values(REF_dct, this_dct, 6, "DC-06 Energy (two-step response)") # TEST
43 |
44 | utils.compare_iterations(result, 4, check_iter)
45 | # Psi4 should test this; so optking shouldn't need to.
46 | # Now try alternative response
47 | # psi4.set_options( {'response_algorithm': 'simultaneous'} )
48 | # o2.R = 1.232
49 | #
50 | # result = optking.optimize_psi4('dct')
51 | #
52 | # this_uhf = result['trajectory'][-1]['properties']['scf_total_energy']
53 | # this_mp2 = result['trajectory'][-1]['properties']['mp2_total_energy']
54 | # this_dct = result['energies'][-1]
55 | # assert psi4.compare_values(REF_uhf, this_uhf, 6, "UHF Energy");
56 | # assert psi4.compare_values(REF_mp2, this_mp2, 6, "MP2 Energy");
57 | # assert psi4.compare_values(REF_dct, this_dct, 6, "DC-06 Energy (simultaneous response)");
58 |
--------------------------------------------------------------------------------
/optking/tests/test_dimers_Bmat.py:
--------------------------------------------------------------------------------
1 | import psi4
2 | import optking
3 | import numpy as np
4 | import pytest
5 |
6 | # Test interfragment coordinate B matrix numerically.
7 | @pytest.mark.dimers
8 | def test_dimers_bmat():
9 | h2oA = psi4.geometry(
10 | """
11 | O
12 | H 1 1.0
13 | H 1 1.0 2 104.5
14 | """
15 | )
16 | Axyz = h2oA.geometry().np
17 | h2oB = psi4.geometry(
18 | """
19 | O
20 | H 1 1.0
21 | H 1 1.0 2 104.5
22 | """
23 | )
24 | Bxyz = Axyz.copy() + 5.0 # Move B not right on top of A.
25 |
26 | dimer = {
27 | "Natoms per frag": [3, 3],
28 | "A Frag": 1,
29 | "A Ref Atoms": [[1], [2, 3], [3]],
30 | "B Frag": 2,
31 | "B Ref Atoms": [[4], [5, 6], [6]],
32 | }
33 | Itest = optking.dimerfrag.DimerFrag.fromUserDict(dimer)
34 |
35 | # Here is lower level method
36 | # Aref = [[0],[1,2],[2]]
37 | # Bref = [[0],[1,2],[2]]
38 | # Itest = optking.dimerfrag.DimerFrag(0,Aref,1,Bref)
39 |
40 | Itest.update_reference_geometry(Axyz, Bxyz)
41 | print(Itest)
42 |
43 | max_error = Itest.test_B(Axyz, Bxyz)
44 |
45 | print("Max. difference between analytic and numerical B matrix: {:8.3e}".format(max_error))
46 | assert max_error < 1.0e-9
47 |
--------------------------------------------------------------------------------
/optking/tests/test_dimers_h2o.py:
--------------------------------------------------------------------------------
1 | import psi4
2 | import optking
3 | import numpy as np
4 | import pytest
5 | from .utils import utils
6 |
7 | # Demonstrate and test positioning two water molecules by specifying
8 | # their interfragment reference points and coordinates.
9 | @pytest.mark.dimers
10 | def test_dimerfrag_orient_h2o_dimers():
11 | h2oA = psi4.geometry(
12 | """
13 | O
14 | H 1 1.0
15 | H 1 1.0 2 104.5
16 | """
17 | )
18 | Axyz = h2oA.geometry().np
19 |
20 | h2oB = psi4.geometry(
21 | """
22 | O
23 | H 1 1.0
24 | H 1 1.0 2 104.5
25 | """
26 | )
27 | Bxyz = Axyz.copy() + 5.0 # Move B not right on top of A.
28 |
29 | # Choose some reference atoms for each fragment.
30 | # These would be # the O atom, the point between the two H atoms,
31 | # and one of the hydrogen atoms for each fragment.
32 |
33 | dimer = {
34 | "Natoms per frag": [3, 3],
35 | "A Frag": 1,
36 | "A Ref Atoms": [[1], [2, 3], [3]],
37 | "A Label": "Water-A", # optional
38 | "B Frag": 2,
39 | "B Ref Atoms": [[4], [5, 6], [6]],
40 | "B Label": "Water-B", # optional
41 | }
42 |
43 | # The default weights are equal between involved atoms but
44 | # may be specified. Fragment labels are optional.
45 | Itest = optking.dimerfrag.DimerFrag.fromUserDict(dimer)
46 | Itest.update_reference_geometry(Axyz, Bxyz)
47 | # print(Itest)
48 |
49 | # Create arbitrary target for displacement with illustrative names.
50 | R_A1B1 = 3.4
51 | theta_A2A1B1 = 2.5
52 | theta_A1B1B2 = 2.7
53 | tau_A2A1B1B2 = -1.5
54 | phi_A3A2A1B1 = 0.3
55 | phi_A1B1B2B3 = 0.6
56 |
57 | q_target = np.array([R_A1B1, theta_A2A1B1, theta_A1B1B2, tau_A2A1B1B2, phi_A3A2A1B1, phi_A1B1B2B3])
58 | Bxyz_new = Itest.orient_fragment(Axyz, Bxyz, q_target)
59 |
60 | # Test how we did
61 | Itest.update_reference_geometry(Axyz, Bxyz_new)
62 | rms_error = np.sqrt(np.mean((q_target - Itest.q_array()) ** 2))
63 | print("RMS deviation from target interfragment coordinates: {:8.3e}".format(rms_error))
64 | assert rms_error < 1.0e-10
65 |
66 |
67 | MP2minEnergy = -152.5352095
68 |
69 |
70 | @pytest.mark.dimers
71 | @pytest.mark.parametrize("option, iter", [("gau_tight", 13), ("interfrag_tight", 11)])
72 | def test_dimers_h2o_auto(check_iter, option, iter): # auto reference pt. creation
73 | h2oD = psi4.geometry(
74 | """
75 | 0 1
76 | H 0.280638 -1.591779 -0.021801
77 | O 0.351675 -1.701049 0.952490
78 | H -0.464013 -1.272980 1.251761
79 | --
80 | 0 1
81 | H -0.397819 -1.918411 -2.373012
82 | O -0.105182 -1.256691 -1.722965
83 | H 0.334700 -0.589454 -2.277374
84 | nocom
85 | noreorient
86 | """
87 | )
88 |
89 | psi4.core.clean_options()
90 | psi4_options = {
91 | "basis": "aug-cc-pvdz",
92 | "geom_maxiter": 40,
93 | "frag_mode": "MULTI",
94 | "g_convergence": f"{option}",
95 | }
96 | psi4.set_options(psi4_options)
97 |
98 | newOptParams = {"interfrag_collinear_tol": 0.2} # increase to prevent too colinear reference points
99 | json_output = optking.optimize_psi4("mp2", **newOptParams)
100 |
101 | E = json_output["energies"][-1]
102 | assert psi4.compare_values(MP2minEnergy, E, 6, "MP2 Energy opt from afar, auto")
103 |
104 | utils.compare_iterations(json_output, iter, check_iter)
105 |
--------------------------------------------------------------------------------
/optking/tests/test_dimers_mt_tyr_frozen_orientation.py:
--------------------------------------------------------------------------------
1 | # Constrained optimization of tyrosine side group with methylthiophene.
2 | # The relative orientation of the two monomers is fixed. The monomers
3 | # themselves and the distance between them are optimized.
4 | import psi4
5 | import optking
6 |
7 | # import numpy as np
8 | import pytest
9 | # import qcelemental as qcel
10 | # import qcengine as qcng
11 | from qcengine.testing import has_program
12 |
13 | @pytest.mark.long
14 | @pytest.mark.dimers
15 | @pytest.mark.skipif(
16 | (has_program("dftd3") or has_program("s-dftd3")) is False,
17 | reason="Neither DFTD3 nor s-DFTD3 is findable"
18 | )
19 | def test_dimers_mt_tyr_frozen_orientation():
20 | # Starting at R ~ 5 Angstroms
21 | init_xyz = """
22 | C -1.258686 0.546935 0.436840
23 | H -0.683650 1.200389 1.102833
24 | C -0.699036 -0.349093 -0.396608
25 | C -2.693370 0.550414 0.355311
26 | H -3.336987 1.206824 0.952052
27 | C -3.159324 -0.343127 -0.536418
28 | H -4.199699 -0.558111 -0.805894
29 | S -1.883829 -1.212288 -1.301525
30 | C 0.786082 -0.656530 -0.606057
31 | H 1.387673 -0.016033 0.048976
32 | H 1.054892 -0.465272 -1.651226
33 | H 0.978834 -1.708370 -0.365860
34 | --
35 | C -6.955593 -0.119764 -1.395442
36 | C -6.977905 -0.135060 1.376787
37 | C -7.111625 1.067403 -0.697024
38 | C -6.810717 -1.314577 -0.707746
39 | C -6.821873 -1.322226 0.678369
40 | C -7.122781 1.059754 0.689090
41 | H -7.226173 2.012097 -1.240759
42 | H -6.687348 -2.253224 -1.259958
43 | H -6.707325 -2.266920 1.222105
44 | H -7.246150 1.998400 1.241304
45 | O -6.944245 -0.111984 -2.805375
46 | H -7.058224 0.807436 -3.049180
47 | C -6.990227 -0.143507 2.907714
48 | H -8.018305 -0.274985 3.264065
49 | H -6.592753 0.807024 3.281508
50 | H -6.368443 -0.968607 3.273516
51 | nocom
52 | unit angstrom
53 | """
54 | # Note that nocom is needed so psi4 does not move the fragment COM's.
55 |
56 | # Define the reference atoms for each fragment, as a linear combination
57 | # of the positions of one or more atoms of the fragment.
58 | # If no weights are given, then the atoms are equally weighted.
59 | MTdimer = {
60 | "Natoms per frag": [12, 16],
61 | "A Frag": 1,
62 | "A Ref Atoms": [[1, 3, 4, 6, 8], [8], [11]],
63 | "A Label": "methylthiophene",
64 | "B Frag": 2,
65 | "B Ref Atoms": [[13, 14, 15, 16, 17, 18], [13], [15]],
66 | "B Label": "tyrosine",
67 | "Frozen": ["theta_A", "theta_B", "tau", "phi_A", "phi_B"],
68 | }
69 | # Here are the dimer coordinates that are used with their definitions.
70 | # R : Distance A1 to B1
71 | # theta_A : Angle, A2-A1-B1
72 | # theta_B : Angle, A1-B1-B2
73 | # tau : Dihedral angle, A2-A1-B1-B2
74 | # phi_A : Dihedral angle, A3-A2-A1-B1
75 | # phi_B : Dihedral angle, A1-B1-B2-B3
76 |
77 | # mTmol = qcel.models.Molecule.from_data(init_xyz)
78 | # Build the psi4 molecule.
79 | MTmol = psi4.geometry(init_xyz)
80 |
81 | # To see the values of the interfragment coordinates, do this:
82 | # MTdimerCoord = optking.dimerfrag.DimerFrag.fromUserDict(MTdimer)
83 | # Axyz = MTmol.geometry().np[0:12,]
84 | # Bxyz = MTmol.geometry().np[12:,]
85 | # MTdimerCoord.update_reference_geometry(Axyz, Bxyz)
86 | # print( MTdimerCoord )
87 | # quit()
88 |
89 | # input_data = {"input_specification": {
90 | # "model": {
91 | # "method": "B3LYP-d3mbj",
92 | # "basis": "6-31G(d)"},
93 | # "keywords": {"d_convergence": 9}
94 | # },
95 | # "keywords": {
96 | # "frag_mode": "multi",
97 | # "interfrag_coords": str(MTdimer)},
98 | # "initial_molecule": mTmol
99 | # }
100 |
101 | # opt_input = qcel.models.OptimizationInput(**input_data)
102 | # result = qcng.compute_procedure(opt_input, "optking")
103 |
104 | # For the moment, 'interfrag_coords' is a non-standard keyword and so
105 | # must be passed like this.
106 | # Optimize fragments and R but not interfragment angular coordinates.
107 | # psi4.set_options({"d_convergence": 9, "basis": "6-31G(d)", "interfrag_coords": str(MTdimer)})
108 | # result = optking.optimize_psi4("b3lyp-d3mbj")
109 | psi4.set_options({"d_convergence": 9, "basis": "6-31G(d)"})
110 | result = optking.optimize_psi4("b3lyp-d3mbj", **{"interfrag_coords": str(MTdimer)})
111 |
112 | E = result["energies"][-1]
113 |
114 | REF_631Gd_Energy = -939.169521
115 | # REF_321G_Energy = -934.237170
116 | assert psi4.compare_values(REF_631Gd_Energy, E, 4, "B3LYP-D3MBJ energy") # TEST
117 |
--------------------------------------------------------------------------------
/optking/tests/test_dimers_ne2.py:
--------------------------------------------------------------------------------
1 | import psi4
2 | import optking
3 | import numpy as np
4 | import pytest
5 | from .utils import utils
6 |
7 | # Optimized neon dimer
8 | MP2minEnergy = -257.4109749
9 |
10 | #! (Ne)_2 with interfrag coordinates, specifying ref atoms, from long-range
11 | @pytest.mark.dimers
12 | def test_dimers_ne2_long(check_iter):
13 | # Test from long distance start.
14 | ne2 = psi4.geometry(
15 | """
16 | 0 1
17 | Ne 0.0 0.0 0.0
18 | --
19 | 0 1
20 | Ne 4.0 0.0 0.0
21 | nocom
22 | """
23 | )
24 |
25 | psi4_options = {
26 | "basis": "aug-cc-pvdz",
27 | "geom_maxiter": 30,
28 | "frag_mode": "MULTI",
29 | "frag_ref_atoms": [[[1]], [[2]]], # reference point atoms, numbering now total
30 | "g_convergence": "gau_verytight",
31 | }
32 | psi4.set_options(psi4_options)
33 | json_output = optking.optimize_psi4("mp2")
34 | E = json_output["energies"][-1]
35 | assert psi4.compare_values(MP2minEnergy, E, 6, "MP2 Energy opt from afar")
36 | utils.compare_iterations(json_output, 14, check_iter)
37 |
38 |
39 | #! (Ne)_2 with interfrag coordinates, specifying ref atoms, from short-range
40 | @pytest.mark.dimers
41 | def test_dimers_ne2_short(check_iter):
42 | # Test from short distance start.
43 | ne2 = psi4.geometry(
44 | """
45 | 0 1
46 | Ne 0.0 0.0 0.0
47 | --
48 | 0 1
49 | Ne 2.5 0.0 0.0
50 | nocom
51 | """
52 | )
53 |
54 | psi4_options = {
55 | "basis": "aug-cc-pvdz",
56 | "geom_maxiter": 30,
57 | "frag_mode": "MULTI",
58 | "frag_ref_atoms": [[[1]], [[2]]], # reference point atoms, numbering now total
59 | "g_convergence": "gau_verytight",
60 | }
61 | psi4.core.clean_options()
62 | psi4.set_options(psi4_options)
63 | json_output = optking.optimize_psi4("mp2")
64 | E = json_output["energies"][-1]
65 | assert psi4.compare_values(MP2minEnergy, E, 6, "MP2 Energy opt from close")
66 | utils.compare_iterations(json_output, 15, check_iter)
67 |
68 |
69 | #! (Ne)_2 with interfrag coordinates, auto-generated ref atoms
70 | @pytest.mark.dimers
71 | def test_dimers_ne2_auto(check_iter): # auto reference pt. creation
72 | ne2 = psi4.geometry(
73 | """
74 | 0 1
75 | Ne 0.0 0.0 0.0
76 | --
77 | 0 1
78 | Ne 3.0 0.0 0.0
79 | nocom
80 | """
81 | )
82 |
83 | psi4.core.clean_options()
84 | psi4_options = {"basis": "aug-cc-pvdz", "geom_maxiter": 30, "frag_mode": "MULTI", "g_convergence": "gau_verytight"}
85 | psi4.set_options(psi4_options)
86 | json_output = optking.optimize_psi4("mp2")
87 | E = json_output["energies"][-1]
88 | assert psi4.compare_values(MP2minEnergy, E, 6, "MP2 Energy opt from afar, auto")
89 | utils.compare_iterations(json_output, 13, check_iter)
90 |
91 |
92 | #! (Ne)_2 with interfrag coordinates, using 1/R distance
93 | @pytest.mark.dimers
94 | def test_dimers_ne2_inverseR(check_iter):
95 | ne2 = psi4.geometry(
96 | """
97 | 0 1
98 | Ne 0.0 0.0 0.0
99 | --
100 | 0 1
101 | Ne 3.0 0.0 0.0
102 | nocom
103 | """
104 | )
105 |
106 | psi4.core.clean_options()
107 | psi4_options = {
108 | "basis": "aug-cc-pvdz",
109 | "geom_maxiter": 20,
110 | "frag_mode": "MULTI",
111 | "g_convergence": "gau_verytight",
112 | "frag_ref_atoms": [[[1]], [[2]]], # atoms for reference points
113 | "interfrag_dist_inv": True,
114 | "test_B": True,
115 | }
116 | psi4.set_options(psi4_options)
117 | json_output = optking.optimize_psi4("mp2")
118 | E = json_output["energies"][-1]
119 | assert psi4.compare_values(MP2minEnergy, E, 6, "MP2 Energy opt from afar, auto")
120 | utils.compare_iterations(json_output, 10, check_iter)
121 |
122 |
123 | #! (Ne)_2 with interfrag coordinates, using full user dict input
124 | @pytest.mark.dimers
125 | def test_dimers_ne2_dict():
126 | ne2 = psi4.geometry(
127 | """
128 | 0 1
129 | Ne 0.0 0.0 0.0
130 | Ne 4.0 0.0 0.0
131 | nocom
132 | """
133 | )
134 | psi4.core.clean_options()
135 | psi4_options = {"basis": "aug-cc-pvdz", "geom_maxiter": 30, "frag_mode": "MULTI", "g_convergence": "gau_verytight"}
136 |
137 | dimer = {
138 | "Natoms per frag": [1, 1],
139 | "A Frag": 1,
140 | "A Ref Atoms": [[1]],
141 | "A Label": "Ne atom 1",
142 | "B Frag": 2,
143 | "B Ref Atoms": [[2]],
144 | "B Label": "Ne atom 2",
145 | }
146 |
147 | psi4.set_options(psi4_options)
148 | json_output = optking.optimize_psi4("mp2", interfrag_coords=str(dimer))
149 | E = json_output["energies"][-1]
150 | assert psi4.compare_values(MP2minEnergy, E, 6, "MP2 Energy opt from afar, auto")
151 |
--------------------------------------------------------------------------------
/optking/tests/test_dimers_orient.py:
--------------------------------------------------------------------------------
1 | import optking
2 | import pytest
3 |
4 | # Tests the dimer orientation code.
5 | # 1) Create random geometries for fragments with NA and NB atoms, respectively.
6 | # 2) Randomly choose 1-3 atoms on each fragment with which to define the
7 | # reference points on each fragment. Assign them random weights.
8 | # The linear combination prescribes each reference point.
9 | # 3) Choose an arbitrary displacement of the interfragment coordinates, rotate
10 | # the geometry of second fragment to match precisely the new values.
11 | # 4) If number of atoms in a fragment is <3, then tests code for all the
12 | # annoying situations in which some of the 6 interfragment coordinates drop out.
13 |
14 |
15 | @pytest.mark.dimers
16 | @pytest.mark.parametrize("NA,NB,seed", [(i, j, s) for i in range(1, 5) for j in range(1, 5) for s in range(1, 5)])
17 | def test_dimerfrag_orient(NA, NB, seed):
18 | rms_error = optking.dimerfrag.test_orient(NA, NB, randomSeed=seed)
19 | print("Error: {:10.5e}".format(rms_error))
20 | assert rms_error < 1.0e-10
21 |
--------------------------------------------------------------------------------
/optking/tests/test_frozen_cart_and_backstep.py:
--------------------------------------------------------------------------------
1 | import psi4
2 | import optking
3 | import pytest
4 | from .utils import utils
5 | import numpy as np
6 | from qcelemental import constants
7 | bohr2angstroms = constants.bohr2angstroms
8 |
9 | #! Various constrained energy minimizations of HOOH with cc-pvdz RHF.
10 | #! Cartesian-coordinate constrained optimizations of HOOH in Cartesians.
11 | #! 1. Cartesian optimization.
12 | #! 2. Cartesian optimization with frozen H's.
13 | #! 3. Cartesian optimization with frozen O's.
14 | HOOH_E = -150.7866742 # TEST
15 | HOOH_E_frozen_H_xyz = -150.7866491 # TEST
16 | HOOH_E_frozen_O_xyz = -150.7866390 # TEST
17 |
18 | f0 = """"""
19 | # Freeze H xyz in HOOH.
20 | f1 = """ 1 Xyz 4 xYz """
21 | # Freeze O xyz in HOOH.
22 | f2 = """ 2 xyz 3 xyz """
23 | # Freeze H xyz with individual input entries in HOOH.
24 | f3 = """
25 | 1 x
26 | 1 y
27 | 1 Z
28 | 4 x
29 | 4 Y
30 | 4 z """
31 |
32 | opt0 = {"frozen_cartesian": f0}
33 | opt1 = {"frozen_cartesian": f1}
34 | opt2 = {"frozen_cartesian": f2}
35 | opt3 = {"frozen_cartesian": f3}
36 | opt4 = {"frozen_cartesian": f1, "opt_coordinates": "redundant"}
37 |
38 | optking__freeze_params = [
39 | (opt0, HOOH_E, 15),
40 | (opt1, HOOH_E_frozen_H_xyz, 13),
41 | (opt2, HOOH_E_frozen_O_xyz, 13),
42 | (opt3, HOOH_E_frozen_H_xyz, 13),
43 | (opt4, HOOH_E_frozen_H_xyz, 13),
44 | ]
45 |
46 |
47 | @pytest.mark.parametrize(
48 | "options, expected, num_steps",
49 | # freeze_params,
50 | optking__freeze_params,
51 | ids=["Only backstep", "freeze H", "freeze O", "freeze individual x,y,z", "freeze then change coord"],
52 | )
53 | def test_hooh_freeze_xyz_Hs(check_iter, options, expected, num_steps):
54 |
55 | hooh = psi4.geometry(
56 | """
57 | H 0.90 0.80 0.5
58 | O 0.00 0.70 0.0
59 | O 0.00 -0.70 0.0
60 | H -0.90 -0.80 0.5
61 | """
62 | )
63 |
64 | psi4.core.clean_options()
65 | psi4_options = {
66 | "basis": "cc-pvdz",
67 | "optking__opt_coordinates": "cartesian",
68 | "optking__g_convergence": "gau_tight",
69 | "optking__geom_maxiter": 20,
70 | "optking__consecutive_backsteps": 1,
71 | }
72 | psi4.set_options(psi4_options)
73 | psi4.set_options(options)
74 |
75 | json_output = optking.optimize_psi4("hf")
76 |
77 | thisenergy = json_output["energies"][-1] # TEST
78 | assert psi4.compare_values(expected, thisenergy, 6) # TEST
79 |
80 | utils.compare_iterations(json_output, num_steps, check_iter)
81 |
82 |
83 | #! test if we can keep oxygen atom from moving off of the point (1,1,1)
84 | def test_frozen_cart_h2o(check_iter):
85 |
86 | h2o = psi4.geometry(
87 | """
88 | O 1.000000 1.000000 1.000000
89 | H 2.000000 1.000000 1.000000
90 | H 1.000000 2.000000 1.000000
91 | units angstrom
92 | no_com
93 | no_reorient
94 | """
95 | )
96 |
97 | psi4.core.clean_options()
98 | psi4_options = {"basis": "cc-pvdz", "reference": "rhf", "scf_type": "df", "max_energy_g_convergence": 7}
99 | psi4.set_options(psi4_options)
100 | psi4.set_options({"optking__frozen_cartesian": """1 xyz"""})
101 |
102 | json_output = optking.optimize_psi4("hf")
103 |
104 | optGeom = bohr2angstroms*np.asarray(json_output['final_molecule']['geometry']).reshape(-1,3)
105 |
106 | thisenergy = json_output["energies"][-1]
107 | assert psi4.compare_values(-76.0270327834836, thisenergy, 6, "RHF Energy")
108 | assert psi4.compare_values(optGeom[0,0], 1.0, 6, "X Frozen coordinate")
109 | assert psi4.compare_values(optGeom[0,1], 1.0, 6, "Y Frozen coordinate")
110 | assert psi4.compare_values(optGeom[0,2], 1.0, 6, "Z Frozen coordinate")
111 |
112 | utils.compare_iterations(json_output, 6, check_iter)
113 |
114 |
115 | #! test h2o dimer with frozen oxygen atoms
116 | def test_frozen_cart_h2o_dimer(check_iter):
117 | h2oDimer = psi4.geometry(
118 | """
119 | O -0.3289725 -1.4662712 0.0000000
120 | H -1.3007725 -1.5158712 0.0000000
121 | H 0.0634274 0.4333287 0.0000000
122 | O 0.3010274 1.3644287 0.0000000
123 | H 0.8404274 1.3494287 0.7893000
124 | H 0.8404274 1.3494287 -0.7893000
125 | units = angstrom
126 | no_com
127 | no_reorient
128 | """
129 | )
130 | inputGeom= np.asarray(h2oDimer.geometry())
131 |
132 | psi4.core.clean_options()
133 | psi4_options = {
134 | "basis": "cc-pVDZ",
135 | "optking__g_convergence": "gau_tight",
136 | "optking__frozen_cartesian": """ 1 xyz 4 xyz """,
137 | "optking__geom_maxiter": 40,
138 | }
139 | psi4.set_options(psi4_options)
140 |
141 | json_output = optking.optimize_psi4("mp2")
142 |
143 | optGeom = np.asarray(json_output['final_molecule']['geometry']).reshape(-1,3)
144 |
145 | thisenergy = json_output["energies"][-1] # TEST
146 | assert psi4.compare_values(-152.47381494, thisenergy, 8, "MP2 Energy")
147 |
148 | assert psi4.compare_values(inputGeom[0,0], optGeom[0,0], 6, "O1 X Frozen coordinate")
149 | assert psi4.compare_values(inputGeom[0,1], optGeom[0,1], 6, "O1 Y Frozen coordinate")
150 | assert psi4.compare_values(inputGeom[0,2], optGeom[0,2], 6, "O1 Z Frozen coordinate")
151 | assert psi4.compare_values(inputGeom[3,0], optGeom[3,0], 6, "O2 X Frozen coordinate")
152 | assert psi4.compare_values(inputGeom[3,1], optGeom[3,1], 6, "O2 Y Frozen coordinate")
153 | assert psi4.compare_values(inputGeom[3,2], optGeom[3,2], 6, "O2 Z Frozen coordinate")
154 | assert np.abs(inputGeom[1,0] - optGeom[1,0]) > 0.01 # Check a not-frozen coordinate.
155 |
156 | utils.compare_iterations(json_output, 25, True)
157 |
158 |
--------------------------------------------------------------------------------
/optking/tests/test_frozen_internals.py:
--------------------------------------------------------------------------------
1 | #! Various constrained energy minimizations of HOOH with cc-pvdz RHF
2 | #! Internal-coordinate constraints in internal-coordinate optimizations.
3 | import pytest
4 |
5 | import psi4
6 | import optking
7 | from .utils import utils
8 |
9 |
10 | OH_frozen_stre_rhf = -150.781130356 # TEST
11 | OOH_frozen_bend_rhf = -150.786372411 # TEST
12 | HOOH_frozen_dihedral_rhf = -150.786766848 # TEST
13 |
14 | f1 = {"frozen_distance": "1 2 3 4"}
15 | f2 = {"frozen_bend": "1 2 3 2 3 4"}
16 | f3 = {"frozen_dihedral": "1 2 3 4"}
17 |
18 | optking__frozen_coords = [
19 | (f1, OH_frozen_stre_rhf, 9),
20 | (f2, OOH_frozen_bend_rhf, 6),
21 | (f3, HOOH_frozen_dihedral_rhf, 6)
22 | ]
23 |
24 | @pytest.mark.parametrize(
25 | "option, expected, num_steps",
26 | optking__frozen_coords,
27 | ids=["frozen stretch", "frozen bend", "frozen dihedral"]
28 | )
29 | def test_frozen_coords(option, expected, num_steps, check_iter):
30 | # Constrained minimization with frozen bond, bend, and torsion
31 | hooh = psi4.geometry(
32 | """
33 | H
34 | O 1 0.90
35 | O 2 1.40 1 100.0
36 | H 3 0.90 2 100.0 1 115.0
37 | """
38 | )
39 |
40 | psi4.core.clean_options()
41 |
42 | psi4_options = {
43 | "diis": "false",
44 | "basis": "cc-PVDZ",
45 | "scf_type": "pk",
46 | "print": 4,
47 | "g_convergence": "gau_tight"
48 | }
49 | psi4.set_options(psi4_options)
50 | psi4.set_options(option)
51 |
52 | json_output = optking.optimize_psi4("hf")
53 | thisenergy = json_output["energies"][-1]
54 |
55 | assert psi4.compare_values(expected, thisenergy, 6) # TEST
56 | utils.compare_iterations(json_output, num_steps, check_iter)
57 |
58 |
59 | def test_butane_frozen(check_iter):
60 | _ = psi4.geometry("pubchem:butane")
61 |
62 | psi4.core.clean_options()
63 | psi4_options = {
64 | "basis": "6-31G",
65 | "g_convergence": "gau_tight",
66 | }
67 | psi4.set_options(psi4_options)
68 |
69 | tmp = {"freeze_all_dihedrals": True,}
70 | result = optking.optimize_psi4("scf", **tmp)
71 | E1 = result["energies"][-1] # TEST
72 |
73 | psi4.core.clean_options()
74 | psi4_options = {
75 | "basis": "6-31G",
76 | "g_convergence": "gau_tight",
77 | "frozen_dihedral": """
78 | 1 2 4 12
79 | 1 2 4 13
80 | 1 2 4 14
81 | 2 1 3 9
82 | 2 1 3 10
83 | 2 1 3 11
84 | 3 1 2 4
85 | 3 1 2 7
86 | 3 1 2 8
87 | 4 2 1 5
88 | 4 2 1 6
89 | 5 1 2 7
90 | 5 1 2 8
91 | 5 1 3 9
92 | 5 1 3 10
93 | 5 1 3 11
94 | 6 1 2 7
95 | 6 1 2 8
96 | 6 1 3 9
97 | 6 1 3 10
98 | 6 1 3 11
99 | 7 2 4 12
100 | 7 2 4 13
101 | 7 2 4 14
102 | 8 2 4 12
103 | 8 2 4 13
104 | 8 2 4 14
105 | """
106 | }
107 | psi4.set_options(psi4_options)
108 | result = optking.optimize_psi4("scf")
109 | E2 = result["energies"][-1]
110 |
111 | assert psi4.compare_values(E1, E2, 8, "RHF energy") # TEST
112 | utils.compare_iterations(result, 5, check_iter)
113 |
114 | def test_butane_skip_frozen(check_iter):
115 | _ = psi4.geometry("pubchem:butane")
116 |
117 | psi4.core.clean_options()
118 | psi4_options = {
119 | "basis": "6-31G",
120 | "g_convergence": "gau_tight",
121 | }
122 | tmp = {
123 | "freeze_all_dihedrals": True,
124 | "unfreeze_dihedrals": """
125 | 8 2 4 12
126 | 8 2 4 13
127 | 8 2 4 14
128 | 3 1 2 8
129 | 5 1 2 8
130 | 6 1 2 8"""}
131 |
132 | psi4.set_options(psi4_options)
133 |
134 | result = optking.optimize_psi4("scf", **tmp)
135 | E1 = result["energies"][-1] # TEST
136 |
137 | psi4.core.clean_options()
138 | psi4_options = {
139 | "basis": "6-31G",
140 | "g_convergence": "gau_tight",
141 | "frozen_dihedral": """
142 | 1 2 4 12
143 | 1 2 4 13
144 | 1 2 4 14
145 | 2 1 3 9
146 | 2 1 3 10
147 | 2 1 3 11
148 | 3 1 2 4
149 | 3 1 2 7
150 | 4 2 1 5
151 | 4 2 1 6
152 | 5 1 2 7
153 | 5 1 3 9
154 | 5 1 3 10
155 | 5 1 3 11
156 | 6 1 2 7
157 | 6 1 3 9
158 | 6 1 3 10
159 | 6 1 3 11
160 | 7 2 4 12
161 | 7 2 4 13
162 | 7 2 4 14
163 | """
164 | }
165 | psi4.set_options(psi4_options)
166 | result = optking.optimize_psi4("scf")
167 | E2 = result["energies"][-1]
168 |
169 | assert psi4.compare_values(E1, E2, 8, "RHF energy") # TEST
170 | utils.compare_iterations(result, 5, check_iter)
171 |
--------------------------------------------------------------------------------
/optking/tests/test_hbond.py:
--------------------------------------------------------------------------------
1 | import pytest
2 | import numpy as np
3 |
4 | import optking.stre
5 | import optking.bend
6 | import optking.tors
7 | import optking.intcosMisc
8 | import optking.addIntcos
9 | import optking.displace
10 | import optking.optparams as op
11 | import optking.caseInsensitiveDict
12 |
13 |
14 | # stretch displacement
15 | # bend displacement
16 | # whether h bond should be detected
17 | @pytest.mark.skip
18 | @pytest.mark.parametrize(
19 | "options, expected", [((0, 0), True), ((-0.375, 0), False), ((0, -np.pi / 8), False), ((0.8, 0), False)]
20 | )
21 | def test_hydrogen_bonds(options, expected):
22 |
23 | # Manually construct water dimer in single frag mode
24 | # Tests fail when run with entire suite due to op.Params missing
25 | op.Params = op.OptParams(optking.caseInsensitiveDict.CaseInsensitiveDict({}))
26 |
27 | # Geometry in Bohr
28 | geom = np.array(
29 | [
30 | [-1.2824641813, -2.3421356740, 0.0913301558],
31 | [-0.0314167971, -3.6520400907, 0.0340038272],
32 | [-1.9858966815, -2.4709212198, 1.7566192883],
33 | [1.3419482749, 2.4585411267, -0.1017720514],
34 | [0.4210461244, 0.8871180358, -0.1345980555],
35 | [0.6522116213, 3.3884042683, -1.4903045984],
36 | ]
37 | )
38 |
39 | Z = [8, 1, 1, 8, 1, 1]
40 | masses = [15.999, 1.008, 1.008, 15.999, 1.008, 1.008]
41 |
42 | s1 = optking.stre.Stre(0, 1)
43 | s2 = optking.stre.Stre(0, 2)
44 | s3 = optking.stre.Stre(0, 4)
45 | s4 = optking.stre.Stre(3, 4)
46 | s5 = optking.stre.Stre(3, 5)
47 |
48 | b1 = optking.bend.Bend(1, 0, 2)
49 | b2 = optking.bend.Bend(1, 0, 4)
50 | b3 = optking.bend.Bend(2, 0, 4)
51 | b4 = optking.bend.Bend(0, 4, 3)
52 | b5 = optking.bend.Bend(4, 3, 5)
53 |
54 | t1 = optking.bend.Bend(1, 0, 4, 3)
55 | t2 = optking.bend.Bend(2, 0, 4, 3)
56 | t3 = optking.bend.Bend(0, 4, 3, 5)
57 |
58 | intcos = [s1, s2, s3, s4, s5, b1, b2, b3, b4, b5, t1, t2, t3]
59 |
60 | o_frag = optking.frag.Frag(Z, geom, masses, intcos)
61 |
62 | dq = np.zeros(13)
63 | dq[2] = options[0]
64 | dq[8] = options[1]
65 |
66 | # Displace in Bohr and degrees. Do four smaller displacements
67 | optking.displace.displace_frag(o_frag, dq)
68 | o_frag.add_h_bonds()
69 |
70 | assert (optking.stre.HBond(0, 4) in o_frag.intcos) == expected
71 |
72 |
73 | # test_hydrogen_bonds( (-0.5,0), True)
74 |
--------------------------------------------------------------------------------
/optking/tests/test_hf_g_keywords.py:
--------------------------------------------------------------------------------
1 | import psi4
2 | import optking
3 | from .utils import utils
4 |
5 | # HF SCF CC-PVDZ geometry optimization of HOOH with Z-matrix input
6 | def test_B_dB_matrices(check_iter):
7 |
8 | hooh = psi4.geometry(
9 | """
10 | H
11 | O 1 0.9
12 | O 2 1.4 1 100.0
13 | H 3 0.9 2 100.0 1 114.0
14 | """
15 | )
16 |
17 | psi4.core.clean_options()
18 | psi4_options = {
19 | "basis": "cc-pvdz",
20 | "g_convergence": "gau_tight",
21 | "scf_type": "pk",
22 | "TEST_B": True,
23 | "TEST_DERIVATIVE_B": True,
24 | "G_CONVERGENCE": "gau_tight",
25 | }
26 | psi4.set_options(psi4_options)
27 |
28 | json_output = optking.optimize_psi4("hf") # Uses default program (psi4)
29 |
30 | E = json_output["energies"][-1] # TEST
31 | nucenergy = json_output["trajectory"][-1]["properties"]["nuclear_repulsion_energy"] # TEST
32 | refnucenergy = 38.06177 # TEST
33 | refenergy = -150.786766850 # TEST
34 | assert "test_b" in json_output["keywords"] # TEST
35 | assert "test_derivative_b" in json_output["keywords"] # TEST
36 | assert "g_convergence" in json_output["keywords"] # TEST
37 | assert psi4.compare_values(refnucenergy, nucenergy, 3, "Nuclear repulsion energy") # TEST
38 | assert psi4.compare_values(refenergy, E, 8, "Reference energy") # TEST
39 | utils.compare_iterations(json_output, 7, check_iter)
40 |
41 |
42 | def test_maxiter(check_iter):
43 |
44 | h2o = psi4.geometry(
45 | """
46 | O
47 | H 1 1.0
48 | H 1 1.0 2 104.5
49 | """
50 | )
51 |
52 | psi4.core.clean_options()
53 | psi4options = {
54 | # Throw a bunch of options at psi4
55 | "diis": 0,
56 | "basis": "STO-3G",
57 | "e_convergence": 1e-10,
58 | "d_convergence": 1e-10,
59 | "scf_type": "PK",
60 | "geom_maxiter": 2,
61 | }
62 | psi4.set_options(psi4options)
63 |
64 | json_output = optking.optimize_psi4("hf")
65 |
66 | assert "geom_maxiter" in json_output["keywords"] # TEST
67 | assert "Maximum number of steps exceeded" in json_output["error"]["error_message"] # TEST
68 | assert "OptError" in json_output["error"]["error_type"] # TEST
69 |
70 |
71 | # Test the energy of geometry output, when maxiter is reached.
72 | def test_maxiter_geom():
73 |
74 | h2o = psi4.geometry(
75 | """
76 | O
77 | H 1 1.0
78 | H 1 1.0 2 104.5
79 | """
80 | )
81 |
82 | psi4.core.clean_options()
83 | psi4options = {"basis": "cc-pvdz", "e_convergence": 10, "d_convergence": 10, "scf_type": "pk", "geom_maxiter": 2}
84 | psi4.set_options(psi4options)
85 |
86 | result = optking.optimize_psi4("hf")
87 | print(result)
88 |
89 | nextStepSchema = result["final_molecule"] # TEST
90 | nextStepMolecule = psi4.core.Molecule.from_schema(nextStepSchema) # TEST
91 | psi4.core.set_active_molecule(nextStepMolecule) # TEST
92 | psi4.set_options(psi4options)
93 | nextStepEnergy = psi4.driver.energy("scf/cc-pvdz") # TEST
94 | REF_energy = -76.0270381300 # TEST
95 | REF_energy = -76.0270521 # TEST changed. Energy different now that update occurs
96 | assert psi4.compare_values(REF_energy, nextStepEnergy, 5, "Energy of next-step molecule")
97 | # TEST
98 |
--------------------------------------------------------------------------------
/optking/tests/test_hf_g_opt.py:
--------------------------------------------------------------------------------
1 | #! SCF STO-3G geometry optimzation, with Z-matrix input
2 | import json
3 | import psi4
4 | import optking
5 | from .utils import utils
6 |
7 |
8 | def test_hf_g_h2o(check_iter):
9 | h2o = psi4.geometry(
10 | """
11 | O
12 | H 1 1.0
13 | H 1 1.0 2 104.5
14 | """
15 | )
16 |
17 | psi4.core.clean_options()
18 | psi4_options = {
19 | "diis": False,
20 | "basis": "sto-3g",
21 | "e_convergence": 10,
22 | "d_convergence": 10,
23 | "scf_type": "pk",
24 | }
25 | psi4.set_options(psi4_options)
26 |
27 | json_output = optking.optimize_psi4("hf")
28 |
29 | E = json_output["energies"][-1] # TEST
30 | nucenergy = json_output["trajectory"][-1]["properties"]["nuclear_repulsion_energy"] # TEST
31 | refnucenergy = 8.9064983474 # TEST
32 | refenergy = -74.9659011923 # TEST
33 | assert psi4.compare_values(refnucenergy, nucenergy, 3, "Nuclear repulsion energy") # TEST
34 | assert psi4.compare_values(refenergy, E, 6, "Reference energy") # TEST
35 | utils.compare_iterations(json_output, 4, check_iter)
36 |
37 |
38 | #! SCF cc-pVDZ geometry optimzation, Z-matrix input, tight convergence
39 | def test_hf_g_h2o_tight(check_iter):
40 | h2o = psi4.geometry(
41 | """
42 | O
43 | H 1 1.0
44 | H 1 1.0 2 104.5
45 | """
46 | )
47 |
48 | psi4.core.clean_options()
49 | psi4_options = {
50 | "diis": False,
51 | "basis": "cc-pvdz",
52 | "e_convergence": 10,
53 | "d_convergence": 10,
54 | "g_convergence": "gau_tight",
55 | "scf_type": "pk",
56 | }
57 | psi4.set_options(psi4_options)
58 |
59 | json_output = optking.optimize_psi4("hf")
60 |
61 | E = json_output["energies"][-1] # TEST
62 | REF_energy = -76.02705351276 # TEST
63 | assert psi4.compare_values(REF_energy, E, 8, "RHF energy") # TEST
64 | utils.compare_iterations(json_output, 6, check_iter)
65 |
66 |
67 | def test_hf_g_h2o_large(check_iter):
68 | h2o = psi4.geometry(
69 | """
70 | O
71 | H 1 1.0
72 | H 1 1.0 2 104.5
73 | """
74 | )
75 |
76 | psi4.core.clean_options()
77 | psi4_options = {
78 | "basis": "cc-pvtz",
79 | "e_convergence": 10,
80 | "d_convergence": 10,
81 | "g_convergence": "gau_tight",
82 | "scf_type": "pk",
83 | }
84 | psi4.set_options(psi4_options)
85 |
86 | json_output = optking.optimize_psi4("hf")
87 |
88 | E = json_output["energies"][-1] # TEST
89 | REF_energy = -76.05776970191 # TEST
90 | assert psi4.compare_values(REF_energy, E, 8, "RHF energy") # TEST
91 | utils.compare_iterations(json_output, 6, check_iter)
92 |
93 |
94 | #! SCF cc-pVDZ geometry optimzation of ketene, starting from bent structure
95 | def test_hf_g_ketene(check_iter):
96 |
97 | ketene = psi4.geometry(
98 | """
99 | 0 1
100 | H
101 | C 1 1.1
102 | C 2 1.3 1 130.0
103 | H 2 1.1 3 110.0 1 180.0
104 | O 3 1.1 4 120.0 1 180.0
105 | """
106 | )
107 |
108 | psi4.core.clean_options()
109 | psi4_options = {"basis": "cc-pvdz", "g_convergence": "gau_tight", "scf_type": "pk"}
110 | psi4.set_options(psi4_options)
111 |
112 | result = optking.optimize_psi4("scf")
113 | optking.logger.info(json.dumps(result, indent=2))
114 | E = result["energies"][-1] # TEST
115 | REF_energy = -151.7410313803 # TEST
116 | assert psi4.compare_values(REF_energy, E, 8, "RHF energy") # TEST
117 | utils.compare_iterations(result, 8, check_iter)
118 |
--------------------------------------------------------------------------------
/optking/tests/test_hooh_ext_force.py:
--------------------------------------------------------------------------------
1 | #! Various constrained energy minimizations of HOOH with cc-pvdz RHF.
2 | #! For "fixed" coordinates, the final value is provided by the user.
3 | import pytest
4 | import psi4
5 | import optking
6 | from .utils import utils
7 |
8 | # Minimized energy with OH bonds pushed toward 0.950 Angstroms.
9 | OH_950_stre = -150.786669
10 | # Minimized energy with OOH angles pushed toward 105.0 degrees.
11 | OOH_105_bend = -150.786177
12 | # Minimized energy with HOOH torsion pushed toward 120.0 degrees.
13 | HOOH_120_dihedral = -150.786647
14 | # Minimize energy with the x and y coordinates of atom 1 pushed
15 | # to 1.0 and 1.0. Just for fun.
16 | HOOH_minimum = -150.7866742
17 |
18 | f1 = ({"ext_force_distance": "1 2 '-8.0*(x-0.950)' 3 4 '-8.0*(x-0.950)'"}, OH_950_stre, 9)
19 | f2 = ({"ext_force_bend": "1 2 3 '-8.0*(x-105.0)' 2 3 4 '-8.0*(x-105.0)'"}, OOH_105_bend, 17)
20 | f3 = ({"ext_force_dihedral": "1 2 3 4 '-8.0*(x-120.0)'"}, HOOH_120_dihedral, 15)
21 | f4 = ({"ext_force_cartesian": "1 x '-2.0*(x-1.0)' 1 y '-2.0*(x-1.0)'"}, HOOH_minimum, 10)
22 | # Same as f1, but 'soften'/dampen force at long range.
23 | f5 = (
24 | {
25 | "ext_force_distance": "1 2 '-8.0 * (x-0.950) * exp(-20*abs(x-0.950) )' 3 4 '-8.0*(x-0.950) * exp(-20*abs(x-0.950))'"
26 | },
27 | OH_950_stre,
28 | 13
29 | )
30 |
31 |
32 | @pytest.mark.parametrize("option, expected, num_steps", [f1, f2, f3, f4, f5])
33 | def test_hooh_fixed_OH_stre(option, expected, num_steps, check_iter):
34 | hooh = psi4.geometry(
35 | """
36 | H
37 | O 1 0.90
38 | O 2 1.40 1 100.0
39 | H 3 0.90 2 100.0 1 115.0
40 | """
41 | )
42 |
43 | psi4.core.clean_options()
44 | psi4_options = {"diis": "false", "basis": "cc-pvdz", "g_convergence": "gau_tight"}
45 | psi4.set_options(psi4_options)
46 |
47 | json_output = optking.optimize_psi4("hf", **option)
48 |
49 | E = json_output["energies"][-1]
50 | assert psi4.compare_values(expected, E, 6, list(option.keys())[0])
51 | utils.compare_iterations(json_output, num_steps, check_iter)
52 |
--------------------------------------------------------------------------------
/optking/tests/test_irc_hooh.py:
--------------------------------------------------------------------------------
1 | # IRC for HOOH from cis confirmation.
2 | import psi4
3 | import optking
4 | import json
5 | from .utils import utils
6 |
7 | psi4.set_memory("2 GB")
8 |
9 |
10 | def test_hooh_irc(check_iter):
11 | energy_5th_IRC_pt = -150.812913276783 # TEST
12 | h2o2 = psi4.geometry(
13 | """
14 | H 0.0000000000 0.9803530335 -0.8498671785
15 | O 0.0000000000 0.6988545188 0.0536419016
16 | O 0.0000000000 -0.6988545188 0.0536419016
17 | H 0.0000000000 -0.9803530335 -0.8498671785
18 | """
19 | )
20 | # Necessary since IRC will break C2h.
21 | h2o2.reset_point_group("c2")
22 |
23 | psi4.core.clean_options()
24 |
25 | psi4_options = {
26 | "basis": "dzp",
27 | "scf_type": "pk",
28 | "g_convergence": "gau_verytight",
29 | "opt_type": "irc",
30 | "geom_maxiter": 60,
31 | "full_hess_every": 0,
32 | }
33 |
34 | psi4.set_options(psi4_options)
35 | json_output = optking.optimize_psi4("hf")
36 | print(json.dumps(json_output, indent=2))
37 | IRC = json_output["extras"]["irc_rxn_path"]
38 |
39 | print("%15s%15s%20s%15s" % ("Step Number", "Arc Distance", "Energy", "HOOH dihedral"))
40 | for step in IRC:
41 | print("%15d%15.5f%20.10f%15.5f" % (step["step_number"], step["arc_dist"], step["energy"], step["q"][5]))
42 |
43 | assert psi4.compare_values(energy_5th_IRC_pt, IRC[5]["energy"], 6, "Energy of 5th IRC point.") # TEST
44 | utils.compare_iterations(json_output, 45, check_iter)
45 |
--------------------------------------------------------------------------------
/optking/tests/test_jsoninput.py:
--------------------------------------------------------------------------------
1 | import os
2 | import json
3 |
4 | import pytest
5 | import optking
6 | import psi4
7 |
8 | from qcelemental.models import OptimizationInput
9 | from qcelemental.testing import compare_values
10 | from .utils import utils
11 | from .psi4_helper import using_qcmanybody
12 |
13 | # Varying number of repulsion energy decimals to check.
14 | @pytest.mark.parametrize(
15 | "inp,expected,num_steps",
16 | [
17 | pytest.param("json_h2o.json", (8.9064890670, -74.965901192, 3), 5),
18 | pytest.param("json_betapinene.json", (568.2219045869, -383.38105559, 1), 4),
19 | pytest.param("json_hooh_frozen.json", (37.969354880, -150.786372411, 2), 6),
20 | pytest.param("json_lif_cp.json", (8.95167, -106.8867587, 2, 3.016), 4, marks=using_qcmanybody),
21 | pytest.param("json_lif_nocp.json", (9.09281, -106.9208785, 2, 2.969), 5, marks=using_qcmanybody),
22 | ],
23 | )
24 | def test_input_through_json(inp, expected, num_steps, check_iter):
25 | with open(os.path.join(os.path.dirname(__file__), inp)) as input_data:
26 | input_copy = json.load(input_data)
27 | if "lif" in inp:
28 | from qcmanybody.models.generalized_optimization import GeneralizedOptimizationInput
29 | opt_schema = GeneralizedOptimizationInput(**input_copy)
30 | else:
31 | opt_schema = OptimizationInput(**input_copy)
32 |
33 | # Note it's important to have `input_specification.schema_name = "qcschema_manybodyspecification"`
34 | # in your json for a MBE optimization. Or you can explicitly construct a
35 | # GeneralizedOptimizationInput like above.
36 |
37 | # optking.run_json_file(os.path.join(os.path.dirname(__file__), inp))
38 | json_dict = optking.optimize_qcengine(input_copy)
39 |
40 | if "lif" in inp:
41 | assert inp, json_dict["trajectory"][-1]["schema_name"] == "qcschema_manybodyresult"
42 | else:
43 | assert inp, json_dict["trajectory"][-1]["schema_name"] == "qcschema_output"
44 |
45 | # For testing purposes. If this works, we have properly returned the output, and added the result
46 | # to the original file. In order to preserve the form of the test suite, we now resore the input
47 | # to its original state
48 | # with open(os.path.join(os.path.dirname(__file__), inp)) as input_data:
49 | # json_dict = json.load(input_data)
50 |
51 | # LAB: for the MBE optimizations, psi4.compare_values strangely segfaults python, so using compare_values from qcel
52 | assert compare_values(
53 | expected[0],
54 | json_dict["trajectory"][-1]["properties"]["nuclear_repulsion_energy"],
55 | atol=1.0 * 10**-expected[2],
56 | label="Nuclear repulsion energy",
57 | )
58 | assert compare_values(
59 | expected[1], json_dict["trajectory"][-1]["properties"]["return_energy"], atol=1.e-6, label="Reference energy"
60 | )
61 | utils.compare_iterations(json_dict, num_steps, check_iter)
62 |
63 | if len(expected) > 3:
64 | assert compare_values(expected[3], json_dict["final_molecule"]["geometry"][5] - json_dict["final_molecule"]["geometry"][2], atol=1.e-3, label="bond length")
65 |
66 | # with open(os.path.join(os.path.dirname(__file__), inp), 'r+') as input_data:
67 | # input_data.seek(0)
68 | # input_data.truncate()
69 | # json.dump(input_copy, input_data, indent=2)
70 |
--------------------------------------------------------------------------------
/optking/tests/test_linesearch.py:
--------------------------------------------------------------------------------
1 | #! Linesearch tests
2 | # memory 8gb
3 |
4 | refnucenergy = 41.670589 # Eh
5 | refenergy = -1053.880393 # Eh
6 |
7 | import optking
8 | import psi4
9 | from .utils import utils
10 |
11 |
12 | def test_linesearch(check_iter):
13 | Ar2 = psi4.geometry(
14 | """
15 | Ar
16 | Ar 1 5.0
17 | """
18 | )
19 |
20 | psi4.core.clean_options()
21 | psi4_options = {
22 | "basis": "cc-pvdz",
23 | "d_convergence": 10,
24 | "geom_maxiter": 60,
25 | "g_convergence": "gau_tight",
26 | "step_type": "SD",
27 | }
28 |
29 | psi4.set_options(psi4_options)
30 |
31 | # "linesearch" is not currrently recognized by psi4 read_options.
32 | json_output = optking.optimize_psi4("mp2", **{"linesearch": True})
33 | print(json_output)
34 | E = json_output["energies"][-1]
35 | nucenergy = json_output["trajectory"][-1]["properties"]["nuclear_repulsion_energy"]
36 | assert psi4.compare_values(nucenergy, nucenergy, 3, "Nuclear repulsion energy") # TEST
37 | assert psi4.compare_values(refenergy, E, 1, "Reference energy") # TEST
38 | utils.compare_iterations(json_output, 25, check_iter)
39 |
--------------------------------------------------------------------------------
/optking/tests/test_lj.py:
--------------------------------------------------------------------------------
1 | """
2 | Tests the LJ functions
3 | """
4 | import optking
5 | import pytest
6 | import numpy as np
7 |
8 | # Before 9-4-2020, these were in error because function expected
9 | # sigma first, then epsilon.
10 | @pytest.mark.parametrize(
11 | "R,ref",
12 | [
13 | (2.0, 1893.6914062),
14 | (3.0, 0.0000000), # V = 0 at r = sigma
15 | (3.0 * np.power(2, 1 / 6), -4.0), # Vmin=-epsilon at r = 2^(1/6)*sigma
16 | (4.0, -2.3408346),
17 | (6.0, -0.2460937500),
18 | ],
19 | )
20 | def test_lj_energy(R, ref):
21 | positions = np.array([[0, 0, -R / 2.0], [0, 0, R / 2.0]])
22 | energy = optking.lj_functions.calc_energy_and_gradient(positions, 3.0, 4.0, do_gradient=False)
23 |
24 | if not pytest.approx(ref) == energy:
25 | raise ValueError(
26 | "test_lj_energy for R=%.2f did not match reference (comp = %12.10f, ref = %12.10f)." % (R, energy, ref)
27 | )
28 |
--------------------------------------------------------------------------------
/optking/tests/test_methimazole.py:
--------------------------------------------------------------------------------
1 | import psi4
2 | import optking
3 | import pytest
4 | from .utils import utils
5 |
6 | REF_E = -662.48908779
7 |
8 |
9 | @pytest.mark.long
10 | def test_methimazole(check_iter):
11 | psi4.geometry(
12 | """
13 | 0 1
14 | S -1.887836596846 -0.729301509543 0.000151677997
15 | N 0.379763403154 0.904898490457 -0.000348322003
16 | N 0.782863403154 -1.302501509543 -0.000048322003
17 | C -0.271536596846 -0.357101509543 -0.000448322003
18 | C 1.743863403154 0.684098490457 0.000051677997
19 | C -0.201136596846 2.231498490457 0.000151677997
20 | C 1.979363403154 -0.633601509543 0.000151677997
21 | H 2.450363403154 1.498298490457 0.000251677997
22 | H 0.132963403154 2.764798490457 0.894951677997
23 | H -1.292036596846 2.183998490457 -0.001348322003
24 | H 0.135363403154 2.766598490457 -0.892748322003
25 | H 0.687263403154 -2.310401509543 0.000151677997
26 | H 2.917763403154 -1.162001509543 0.000551677997
27 | """
28 | )
29 | psi4_options = {"basis": "pcseg-0"}
30 | psi4.set_options(psi4_options)
31 | result = optking.optimize_psi4("wb97x-d")
32 | E = result["energies"][-1]
33 | assert psi4.compare_values(E, REF_E, 5, "WB97X-D Min Energy")
34 | utils.compare_iterations(result, 6, check_iter)
35 |
--------------------------------------------------------------------------------
/optking/tests/test_mp2_g_opt.py:
--------------------------------------------------------------------------------
1 | import psi4
2 | import optking
3 | from .utils import utils
4 |
5 |
6 | def test_mp2_h2o(check_iter):
7 |
8 | h2o = psi4.geometry(
9 | """
10 | O
11 | H 1 1.0
12 | H 1 1.0 2 106.0
13 | """
14 | )
15 |
16 | psi4.core.clean_options()
17 | psi4_options = {
18 | "basis": "6-31G**",
19 | "reference": "rhf",
20 | "d_convergence": 9,
21 | "e_convergence": 9,
22 | "mp2_type": "conv",
23 | "max_energy_g_convergence": 7,
24 | }
25 | psi4.set_options(psi4_options)
26 |
27 | result = optking.optimize_psi4("mp2")
28 |
29 | this_nucenergy = result["trajectory"][-1]["properties"]["nuclear_repulsion_energy"] # TEST
30 | this_mp2 = result["energies"][-1] # TEST
31 | REF_nucenergy = 9.1622581908184 # TEST
32 | REF_mp2 = -76.2224486598878 # TEST
33 | assert psi4.compare_values(REF_nucenergy, this_nucenergy, 3, "Nuclear repulsion energy") # TEST
34 | assert psi4.compare_values(REF_mp2, this_mp2, 6, "CONV MP2 energy") # TEST
35 | utils.compare_iterations(result, 5, check_iter)
36 |
--------------------------------------------------------------------------------
/optking/tests/test_nearlinear_dft_opt.py:
--------------------------------------------------------------------------------
1 | import psi4
2 | import optking
3 | from .utils import utils
4 |
5 | #! B3LYP cc-pVDZ geometry optimzation of phenylacetylene, starting from
6 | #! not quite linear structure
7 | def test_b3lyp_phenylacetylene(check_iter):
8 |
9 | phenylacetylene = psi4.geometry(
10 | """
11 | 0 1
12 | C 0.50424 2.62143 -1.86897
13 | C -0.79405 2.10443 -1.80601
14 | C -1.78491 2.59819 -2.66154
15 | C -1.47738 3.60745 -3.57782
16 | C -0.17996 4.12418 -3.64086
17 | C 0.81143 3.63137 -2.78697
18 | H 1.27012 2.23852 -1.20693
19 | H -2.24344 3.98980 -4.23978
20 | H 0.05756 4.90505 -4.35040
21 | H -1.03189 1.32372 -1.09717
22 | H -2.78881 2.19838 -2.61341
23 | C 2.14399 4.16411 -2.85667
24 | C 3.26501 4.60083 -2.90366
25 | H 4.24594 4.99166 -2.95361
26 | """
27 | )
28 |
29 | psi4.core.clean_options()
30 | psi4_options = {
31 | "guess": "sad",
32 | "basis": "cc-pVDZ",
33 | }
34 | psi4.set_options(psi4_options)
35 |
36 | result = optking.optimize_psi4("B3LYP")
37 |
38 | REF_b3lyp_E = -308.413691796 # TEST
39 | E = result["energies"][-1] # TEST
40 | assert psi4.compare_values(REF_b3lyp_E, E, 5, "B3LYP energy") # TEST
41 | utils.compare_iterations(result, 5, check_iter)
42 |
--------------------------------------------------------------------------------
/optking/tests/test_oofp.py:
--------------------------------------------------------------------------------
1 | #! Test out-of-plane angles. Added when only one central atom.
2 | # Usually not needed, but problem in a situation like this, very nearly
3 | # planar formaldehyde. Three bends become redundant as one approaches planarity.
4 | # So eigenvalues of (B*B^t) contain a very small eval. If you include this in
5 | # your matrix inversion it blows up, and if you don't, then you can't tightly
6 | # converge. Adding out-of-planes solves problem.
7 |
8 | b3lyp_opt_energy = -114.41550257
9 | # Range limit both H-C-O(-H) out-of-plane angles to >30 degrees
10 | b3lyp_ranged_oop_30_energy = -114.4032481
11 | # Add harmonic force to push out-of-plane angles to +30 and -30 degrees,
12 | # because extra force is additional, final values are not exactly 30/-30
13 | # and final is a bit lower.
14 | b3lyp_ext_force_oop_30_energy = -114.4032891
15 |
16 | import psi4
17 | import optking
18 | from .utils import utils
19 |
20 |
21 | def test_oofp_formaldehyde(check_iter):
22 | form = psi4.geometry(
23 | """
24 | O 0.6 -0.00007 0.0
25 | C -0.6 -0.00007 0.0
26 | H -1.2 0.24 -0.9
27 | H -1.2 -0.24 0.9
28 | symmetry c1
29 | """
30 | )
31 | psi4.core.clean_options()
32 | psi4_options = {
33 | "basis": "def2-SVP",
34 | "g_convergence": "gau_tight",
35 | "test_B": True,
36 | }
37 | psi4.set_options(psi4_options)
38 |
39 | result = optking.optimize_psi4("b3lyp")
40 | E = result["energies"][-1] # TEST
41 |
42 | assert psi4.compare_values(b3lyp_opt_energy, E, 8, "B3LYP energy")
43 | utils.compare_iterations(result, 6, check_iter)
44 |
45 |
46 | def test_ranged_oofp(check_iter):
47 | form = psi4.geometry(
48 | """
49 | O 0.08 0.60 -0.0
50 | C -0.04 -0.60 -0.0
51 | H -0.4 -1.14 -0.92
52 | H -0.4 -1.14 0.92
53 | """
54 | )
55 | psi4.core.clean_options()
56 | psi4_options = {"basis": "def2-SVP", "ensure_bt_convergence": True}
57 | psi4.set_options(psi4_options)
58 |
59 | xtra = {"ranged_oofp": "(3 2 1 4 -40.0 -30.0) (4 2 1 3 30.0 40.0)"}
60 | result = optking.optimize_psi4("b3lyp", **xtra)
61 | E = result["energies"][-1]
62 |
63 | assert psi4.compare_values(b3lyp_ranged_oop_30_energy, E, 5, "B3LYP energy")
64 | utils.compare_iterations(result, 3, check_iter)
65 |
66 |
67 | def test_ext_force_oofp(check_iter):
68 | form = psi4.geometry(
69 | """
70 | O 0.08 0.60 -0.0
71 | C -0.04 -0.60 -0.0
72 | H -0.4 -1.14 -0.92
73 | H -0.4 -1.14 0.92
74 | """
75 | )
76 | psi4.core.clean_options()
77 | psi4_options = {"basis": "def2-SVP", "ensure_bt_convergence": True}
78 | psi4.set_options(psi4_options)
79 |
80 | xtra = {"ext_force_oofp": "3 2 1 4 '-0.5*(x+30)' 4 2 1 3 '-0.5*(x-30.0)'"}
81 | result = optking.optimize_psi4("b3lyp", **xtra)
82 | E = result["energies"][-1]
83 |
84 | assert psi4.compare_values(b3lyp_ext_force_oop_30_energy, E, 5, "B3LYP energy")
85 | utils.compare_iterations(result, 8, check_iter)
86 |
--------------------------------------------------------------------------------
/optking/tests/test_openshell.py:
--------------------------------------------------------------------------------
1 | import psi4
2 | import optking
3 |
4 | from .utils import utils
5 |
6 |
7 | def test_charged_anion(check_iter):
8 | no2 = psi4.geometry(
9 | """
10 | -1 1
11 | N -0.0001995858 -0.8633595176 0.0000000000
12 | O -0.7026831726 0.4173795866 0.0000000000
13 | O 0.7028810651 0.4175165407 0.0000000000
14 | """
15 | )
16 |
17 | psi4.core.clean_options()
18 | psi4_options = {
19 | "basis": "cc-pvdz",
20 | }
21 | psi4.set_options(psi4_options)
22 |
23 | json_output = optking.optimize_psi4("hf")
24 |
25 | E = json_output["energies"][-1]
26 | refenergy = -203.894394347422
27 | assert psi4.compare_values(refenergy, E, 6, "RHF singlet NO2- energy")
28 | utils.compare_iterations(json_output, 3, check_iter)
29 |
30 |
31 | def test_neutral_triplet(check_iter):
32 | o2 = psi4.geometry(
33 | """
34 | 0 3
35 | O
36 | O 1 1.2
37 | """
38 | )
39 |
40 | psi4.core.clean_options()
41 | psi4_options = {
42 | "basis": "cc-pvdz",
43 | "reference": "uhf",
44 | }
45 | psi4.set_options(psi4_options)
46 |
47 | result = optking.optimize_psi4("hf")
48 |
49 | E = result["energies"][-1]
50 | REF_uhf = -149.6318688
51 | assert psi4.compare_values(REF_uhf, E, 6, "UHF triplet O2 Energy") # TEST
52 | utils.compare_iterations(result, 3, check_iter)
53 |
--------------------------------------------------------------------------------
/optking/tests/test_opt2_allene.py:
--------------------------------------------------------------------------------
1 | #! SCF DZ allene geometry optimization, with Cartesian input, first in c2v symmetry,
2 | #! then in Cs symmetry from a starting point with a non-linear central bond angle.
3 |
4 | import psi4
5 | import optking
6 | from .utils import utils
7 |
8 | # import importlib
9 |
10 |
11 | def test_opt2_allene(check_iter):
12 | refnucenergy = 59.2532646680161 # TEST
13 | refenergy = -115.8302823663 # TEST
14 |
15 | # starting point is D2d/c2v
16 | allene = psi4.geometry(
17 | """
18 | H 0.0 -0.92 -1.8
19 | H 0.0 0.92 -1.8
20 | C 0.0 0.00 -1.3
21 | C 0.0 0.00 0.0
22 | C 0.0 0.00 1.3
23 | H 0.92 0.00 1.8
24 | H -0.92 0.00 1.8
25 | """
26 | )
27 |
28 | psi4.core.clean_options()
29 |
30 | psi4_options = {
31 | "basis": "DZ",
32 | "e_convergence": 10,
33 | "d_convergence": 10,
34 | "scf_type": "pk",
35 | }
36 | psi4.set_options(psi4_options)
37 |
38 | json_output = optking.optimize_psi4("hf")
39 | E = json_output["energies"][-1]
40 | nucenergy = json_output["trajectory"][-1]["properties"]["nuclear_repulsion_energy"]
41 | assert psi4.compare_values(refnucenergy, nucenergy, 2, "Nuclear repulsion energy") # TEST
42 | assert psi4.compare_values(refenergy, E, 6, "Reference energy") # TEST
43 |
44 | # central C-C-C bond angle starts around 170 degrees to test the dynamic addition
45 | # of new linear bending coordinates, and the redefinition of dihedrals.
46 | allene = psi4.geometry(
47 | """
48 | H 0.0 -0.92 -1.8
49 | H 0.0 0.92 -1.8
50 | C 0.0 0.00 -1.3
51 | C 0.0 0.10 0.0
52 | C 0.0 0.00 1.3
53 | H 0.92 0.00 1.8
54 | H -0.92 0.00 1.8
55 | """
56 | )
57 |
58 | psi4.set_options(psi4_options)
59 | json_output = optking.optimize_psi4("hf")
60 | E = json_output["energies"][-1]
61 | nucenergy = json_output["trajectory"][-1]["properties"]["nuclear_repulsion_energy"]
62 | assert psi4.compare_values(refnucenergy, nucenergy, 2, "Nuclear repulsion energy") # TEST
63 | assert psi4.compare_values(refenergy, E, 6, "Reference energy") # TEST
64 | utils.compare_iterations(json_output, 7, check_iter)
65 |
--------------------------------------------------------------------------------
/optking/tests/test_opt5-ch2.py:
--------------------------------------------------------------------------------
1 | #! 6-31G** UHF CH2 3B1 optimization. Uses a Z-Matrix with dummy atoms, just for demo and testing purposes.
2 |
3 | import psi4
4 | import optking
5 |
6 | from .utils import utils
7 |
8 | nucrefenergy = 6.197322440574482 # TEST
9 | refenergy = -38.925486977153 # TEST
10 |
11 |
12 | def test_ch2_with_dummy_atoms(check_iter):
13 | ch2 = psi4.geometry(
14 | """
15 | 0 3
16 | c
17 | x 1 1.0
18 | h 1 b1 2 a1
19 | h 1 b1 2 a1 3 180.0
20 |
21 | b1 = 1.0
22 | a1 = 60.0
23 | """
24 | )
25 |
26 | psi4.core.clean_options()
27 |
28 | psi4_options = {
29 | "reference": "uhf",
30 | "basis": "6-31G(d,p)",
31 | "docc": [2, 0, 0, 1],
32 | "socc": [1, 0, 1, 0],
33 | "scf_type": "pk",
34 | }
35 |
36 | psi4.set_options(psi4_options)
37 |
38 | json_output = optking.optimize_psi4("hf")
39 | thisenergy = json_output["energies"][-1]
40 | nucenergy = json_output["trajectory"][-1]["properties"]["nuclear_repulsion_energy"]
41 |
42 | assert psi4.compare_values(nucrefenergy, nucenergy, 3, "Nuclear repulsion energy") # TEST
43 | assert psi4.compare_values(refenergy, thisenergy, 6, "Reference energy") # TEST
44 |
45 | utils.compare_iterations(json_output, 4, check_iter)
46 |
--------------------------------------------------------------------------------
/optking/tests/test_optimization_input.py:
--------------------------------------------------------------------------------
1 | import pprint
2 | import json
3 | from qcelemental.models.procedures import OptimizationInput
4 | from qcelemental.util.serialization import json_dumps
5 |
6 | from optking.optwrapper import optimize_qcengine, optimize_psi4, initialize_options, make_computer
7 | from optking.molsys import Molsys
8 | from optking.optimize import prepare_opt_output
9 |
10 | from optking.compute_wrappers import QCEngineComputer
11 |
12 |
13 | pp = pprint.PrettyPrinter(indent=2)
14 |
15 |
16 | def test_optimization_input():
17 |
18 | opt_input_dict = {
19 | "schema_name": "qcschema_optimization_input",
20 | "schema_version": 1,
21 | "keywords": {"program": "psi4"},
22 | "initial_molecule": {
23 | "geometry": [0.90, 0.80, 0.5, 0.00, 0.70, 0.0, 0.00, -0.70, 0.0, -0.90, -0.80, 0.5],
24 | "symbols": ["H", "O", "O", "H"],
25 | },
26 | "input_specification": {
27 | "schema_name": "qcschema_input",
28 | "schema_version": 1,
29 | "driver": "gradient",
30 | "model": {"method": "HF", "basis": "sto-3g"},
31 | "keywords": {"soscf": True},
32 | },
33 | }
34 |
35 | # Create Pydantic Model Fills all fields (including non-required)
36 | opt_in = OptimizationInput(**opt_input_dict)
37 |
38 | # Convert back to plain python dictionary
39 | full_model = json.loads(json_dumps(opt_in))
40 |
41 | oMolsys = Molsys.from_schema(full_model["initial_molecule"]) # Create Optking's molecular system
42 | initialize_options(full_model["keywords"])
43 | computer = make_computer(full_model, "qc")
44 | # Takes the o_json object and creates QCSchema formatted python dict. Has numpy elements
45 | opt_output = prepare_opt_output(oMolsys, computer)
46 |
47 | assert "success" in opt_output
48 |
49 | psi_computer = make_computer(full_model, "psi4")
50 | opt_output = prepare_opt_output(oMolsys, computer)
51 |
--------------------------------------------------------------------------------
/optking/tests/test_ranged_internals.py:
--------------------------------------------------------------------------------
1 | #! Test of 'ranged' coordinates. Intcos that cannot move
2 | # out of a prescribed range.
3 | import pytest
4 | import psi4
5 | import optking
6 | from .utils import utils
7 |
8 | conv_RHF_OO_at_135 = -150.7853238 # minimum is 1.39
9 | init_OO_distance = [("1.28", 9), ("1.30", 7), ("1.325", 8), ("1.35", 9), ("1.38", 8)]
10 |
11 | @pytest.mark.parametrize("option, num_steps", init_OO_distance)
12 | def test_ranged_stretch(option, num_steps, check_iter):
13 | geom_input_string = (
14 | """
15 | H
16 | O 1 0.90
17 | O 2 """
18 | + option
19 | + """ 1 100.0
20 | H 3 0.90 2 100.0 1 115.0 """
21 | )
22 | hooh = psi4.geometry(geom_input_string)
23 |
24 | psi4.core.clean_options()
25 | psi4options = {"basis": "cc-PVDZ", "print": 4, "g_convergence": "gau_tight", "geom_maxiter": 20}
26 | psi4.set_options(psi4options)
27 |
28 | xtra = {"ranged_distance": "2 3 1.30 1.35"}
29 | json_output = optking.optimize_psi4("hf", **xtra)
30 |
31 | thisenergy = json_output["energies"][-1]
32 | assert psi4.compare_values(conv_RHF_OO_at_135, thisenergy, 6)
33 | utils.compare_iterations(json_output, num_steps, check_iter)
34 |
35 | conv_RHF_HOO_at_105 = -150.7861769 # minimum is 102 degrees
36 | init_HOO_bend = [("100", 8), ("105", 6), ("108", 7), ("110", 8), ("115", 9)]
37 |
38 | @pytest.mark.parametrize("option, num_steps", init_HOO_bend)
39 | def test_ranged_bend(option, num_steps, check_iter):
40 | geom_input_string = (
41 | """
42 | H
43 | O 1 0.90
44 | O 2 1.35 1 """
45 | + option
46 | + """
47 | H 3 0.90 2 """
48 | + option
49 | + """ 1 115.0 """
50 | )
51 | hooh = psi4.geometry(geom_input_string)
52 |
53 | psi4.core.clean_options()
54 | psi4options = {"basis": "cc-PVDZ", "g_convergence": "gau_tight", "geom_maxiter": 20}
55 | psi4.set_options(psi4options)
56 |
57 | xtra = {"ranged_bend": "(1 2 3 105.0 110.0) (2 3 4 105.0 110.0)"}
58 | json_output = optking.optimize_psi4("hf", **xtra)
59 |
60 | thisenergy = json_output["energies"][-1]
61 | assert psi4.compare_values(conv_RHF_HOO_at_105, thisenergy, 6)
62 | utils.compare_iterations(json_output, num_steps, check_iter)
63 |
64 | conv_RHF_HOOH_at_110 = -150.7866419 # minimum is 115 degrees
65 | init_HOOH_tors = ["95", "100", "105", "110", "115"]
66 |
67 | @pytest.mark.parametrize("option", init_HOOH_tors)
68 | def test_ranged_tors(option):
69 | geom_input_string = (
70 | """
71 | H
72 | O 1 0.90
73 | O 2 1.35 1 100.0
74 | H 3 0.90 2 100.0 1 """
75 | + option
76 | )
77 | hooh = psi4.geometry(geom_input_string)
78 |
79 | psi4.core.clean_options()
80 | psi4options = {"basis": "cc-PVDZ", "g_convergence": "gau_tight", "geom_maxiter": 20}
81 | psi4.set_options(psi4options)
82 |
83 | xtra = {"ranged_dihedral": "(1 2 3 4 100.0 110.0)"}
84 | json_output = optking.optimize_psi4("hf", **xtra)
85 |
86 | thisenergy = json_output["energies"][-1]
87 | assert psi4.compare_values(conv_RHF_HOOH_at_110, thisenergy, 6)
88 |
89 |
90 | conv_RHF_HOOH = -150.7866742 # this is the global minimum (GM)
91 | cart_limits = [
92 | "1 x 0.77 0.80", # Make H x be within 0.77 - 0.80; converge to GM
93 | "2 y 0.50 0.60", # Make O y be within 0.50 - 0.60; converge to GM
94 | "(1 x 0.77 0.80) (2 y 0.50 0.60)",
95 | ] # parentheses optional
96 |
97 |
98 | @pytest.mark.parametrize("option", cart_limits)
99 | def test_ranged_cart(option):
100 | hooh = psi4.geometry(
101 | """
102 | H 0.7551824472 0.7401035426 0.5633005896
103 | O 0.0870189589 0.6693673665 -0.0354930582
104 | O -0.0870189589 -0.6693673665 -0.0354930582
105 | H -0.7551824472 -0.7401035426 0.5633005896"""
106 | )
107 |
108 | psi4.core.clean_options()
109 | psi4options = {"basis": "cc-PVDZ", "g_convergence": "gau_tight", "geom_maxiter": 20}
110 | psi4.set_options(psi4options)
111 |
112 | xtra = {"ranged_cartesian": option}
113 | json_output = optking.optimize_psi4("hf", **xtra)
114 |
115 | thisenergy = json_output["energies"][-1]
116 | assert psi4.compare_values(conv_RHF_HOOH, thisenergy, 6)
117 |
--------------------------------------------------------------------------------
/optking/tests/test_scsmp2_opt.py:
--------------------------------------------------------------------------------
1 | import psi4
2 | import optking
3 | import json
4 | from .utils import utils
5 |
6 | #! SCS-OMP2 cc-pVDZ geometry optimization for the H2O molecule.
7 | def test_scsmp2_opt(check_iter):
8 |
9 | h2o = psi4.geometry(
10 | """
11 | 0 1
12 | o
13 | h 1 0.958
14 | h 1 0.958 2 104.4776
15 | """
16 | )
17 |
18 | psi4.core.clean_options()
19 | psi4_options = {"basis": "cc-pvdz", "max_energy_g_convergence": 7}
20 | psi4.set_options(psi4_options)
21 |
22 | result = optking.optimize_psi4("scs-omp2")
23 |
24 | this_nuc = result["trajectory"][-1]["properties"]["nuclear_repulsion_energy"] # TEST
25 | this_scf = result["trajectory"][-1]["extras"]["qcvars"]["SCF TOTAL ENERGY"] # TEST
26 | this_energy = result["energies"][-1] # TEST
27 | REF_nuc = 9.1123208123
28 | REF_scf = -76.0260868661
29 | REF_scsomp2 = -76.2280452486
30 | assert psi4.compare_values(REF_nuc, this_nuc, 3, "Nuclear Repulsion Energy (a.u.)")
31 | # TEST
32 | assert psi4.compare_values(REF_scf, this_scf, 6, "SCF Energy (a.u.)")
33 | # TEST
34 | assert psi4.compare_values(REF_scsomp2, this_energy, 6, "SCS-OMP2 Total Energy (a.u.)")
35 | # TEST
36 |
37 | utils.compare_iterations(result, 4, check_iter)
38 |
39 |
40 | #! SCS-OMP3 cc-pVDZ geometry optimization for the H2O molecule.
41 | def test_scsmp3_opt(check_iter):
42 |
43 | h2o = psi4.geometry(
44 | """
45 | 0 1
46 | o
47 | h 1 0.958
48 | h 1 0.958 2 104.4776
49 | """
50 | )
51 |
52 | psi4.core.clean_options()
53 | psi4_options = {"basis": "cc-pvdz", "max_energy_g_convergence": 7}
54 | psi4.set_options(psi4_options)
55 |
56 | result = optking.optimize_psi4("scs-omp3")
57 | print(json.dumps(result, indent=2))
58 |
59 | this_nuc = result["trajectory"][-1]["properties"]["nuclear_repulsion_energy"] # TEST
60 | this_scf = result["trajectory"][-1]["extras"]["qcvars"]["SCF TOTAL ENERGY"] # TEST
61 | this_energy = result["energies"][-1] # TEST
62 | REF_nuc = 9.1193753755 # TEST
63 | REF_scf = -76.0261614278 # TEST
64 | REF_scsomp3 = -76.2296260036 # TEST
65 | assert psi4.compare_values(REF_nuc, this_nuc, 3, "Nuclear Repulsion Energy (a.u.)")
66 | # TEST
67 | assert psi4.compare_values(REF_scf, this_scf, 6, "SCF Energy (a.u.)")
68 | # TEST
69 | assert psi4.compare_values(REF_scsomp3, this_energy, 6, "SCS-OMP3 Total Energy (a.u.)")
70 | # TEST
71 |
72 | utils.compare_iterations(result, 4, check_iter)
73 |
74 |
75 | #! SOS-OMP2 cc-pVDZ geometry optimization for the H2O molecule.
76 | def test_sosmp2_opt(check_iter):
77 |
78 | h2o = psi4.geometry(
79 | """
80 | 0 1
81 | o
82 | h 1 0.958
83 | h 1 0.958 2 104.4776
84 | """
85 | )
86 |
87 | psi4.core.clean_options()
88 | psi4_options = {"basis": "cc-pvdz", "max_energy_g_convergence": 7}
89 | psi4.set_options(psi4_options)
90 |
91 | result = optking.optimize_psi4("sos-omp2")
92 | print(json.dumps(result, indent=2))
93 |
94 | this_nuc = result["trajectory"][-1]["properties"]["nuclear_repulsion_energy"] # TEST
95 | this_scf = result["trajectory"][-1]["extras"]["qcvars"]["SCF TOTAL ENERGY"] # TEST
96 | this_energy = result["energies"][-1] # TEST
97 | REF_nuc = 9.1236764248 # TEST
98 | REF_scf = -76.0262152850 # TEST
99 | REF_sosomp2 = -76.2106507336 # TEST
100 | assert psi4.compare_values(REF_nuc, this_nuc, 3, "Nuclear Repulsion Energy (a.u.)")
101 | # TEST
102 | assert psi4.compare_values(REF_scf, this_scf, 6, "SCF Energy (a.u.)")
103 | # TEST
104 | assert psi4.compare_values(REF_sosomp2, this_energy, 6, "SOS-OMP2 Total Energy (a.u.)")
105 | # TEST
106 |
107 | utils.compare_iterations(result, 4, check_iter)
108 |
109 |
110 | #! SOS-OMP3 cc-pVDZ geometry optimization for the H2O molecule.
111 | def test_sosmp3_opt(check_iter):
112 |
113 | h2o = psi4.geometry(
114 | """
115 | 0 1
116 | o
117 | h 1 0.958
118 | h 1 0.958 2 104.4776
119 | """
120 | )
121 |
122 | psi4.core.clean_options()
123 | psi4_options = {"basis": "cc-pvdz", "max_energy_g_convergence": 7}
124 | psi4.set_options(psi4_options)
125 |
126 | result = optking.optimize_psi4("sos-omp3")
127 | print(json.dumps(result, indent=2))
128 |
129 | this_nuc = result["trajectory"][-1]["properties"]["nuclear_repulsion_energy"] # TEST
130 | this_scf = result["trajectory"][-1]["extras"]["qcvars"]["SCF TOTAL ENERGY"] # TEST
131 | this_energy = result["energies"][-1] # TEST
132 | REF_nuc = 9.1134855397 # TEST
133 | REF_scf = -76.0261191302 # TEST
134 | REF_sosomp3 = -76.2277207554 # TEST
135 | assert psi4.compare_values(REF_nuc, this_nuc, 3, "Nuclear Repulsion Energy (a.u.)")
136 | # TEST
137 | assert psi4.compare_values(REF_scf, this_scf, 6, "SCF Energy (a.u.)")
138 | # TEST
139 | assert psi4.compare_values(REF_sosomp3, this_energy, 6, "SOS-OMP3 Total Energy (a.u.)")
140 | # TEST
141 |
142 | utils.compare_iterations(result, 4, check_iter)
143 |
--------------------------------------------------------------------------------
/optking/tests/test_sf4_quasilinear.py:
--------------------------------------------------------------------------------
1 | # SF4 problem case
2 | # Has linear bend, breaks symmetry
3 | # Converges fine if Cartesian
4 | # needs debugging
5 |
6 | import psi4
7 | import optking
8 | import pytest
9 |
10 | from .utils import utils
11 |
12 |
13 | def test_sf4_quasilinear_cart(check_iter):
14 | sf4 = psi4.geometry(
15 | """
16 | S 0.00000000 -0.00000000 -0.30618267
17 | F -1.50688420 -0.00000000 0.56381732
18 | F 0.00000000 -1.74000000 -0.30618267
19 | F -0.00000000 1.74000000 -0.30618267
20 | F 1.50688420 0.00000000 0.56381732
21 | """
22 | )
23 |
24 | psi4.core.clean_options()
25 | psi4_options = {
26 | "basis": "6-31G(d)",
27 | "scf_type": "pk",
28 | "opt_coordinates": "cartesian",
29 | }
30 | psi4.set_options(psi4_options)
31 |
32 | json_output = optking.optimize_psi4("hf")
33 |
34 | E = json_output["energies"][-1]
35 | REF_energy = -795.1433965
36 | assert psi4.compare_values(REF_energy, E, 6, "Reference energy")
37 |
38 | utils.compare_iterations(json_output, 9, check_iter)
39 |
40 |
41 | # This needs debugged. RAK (Jan. 2020) thinks that when/if we get
42 | # full symmetrization of our step (C2v) point group here, then the
43 | # problem that appears in step 7-8 will go away.
44 | # A secondary problem is that it is possible that our definition of
45 | # linear bends forces symmetry breaking, but for now this has been
46 | # tweaked for at least this case by choosing different bend axes
47 | # inside optking. (see the arbitrary ref. axes in Helgaker/Bakken).
48 | @pytest.mark.skip
49 | def test_sf4_quasilinear():
50 | sf4 = psi4.geometry(
51 | """
52 | S 0.00000000 -0.00000000 -0.30618267
53 | F -1.50688420 -0.00000000 0.56381732
54 | F 0.00000000 -1.74000000 -0.30618267
55 | F -0.00000000 1.74000000 -0.30618267
56 | F 1.50688420 0.00000000 0.56381732
57 | """
58 | )
59 |
60 | psi4.core.clean_options()
61 | psi4_options = {
62 | "basis": "6-31G(d)",
63 | "scf_type": "pk",
64 | "g_convergence": "gau_tight",
65 | }
66 | psi4.set_options(psi4_options)
67 |
68 | json_output = optking.optimize_psi4("hf")
69 |
70 | E = json_output["energies"][-1]
71 | REF_energy = -795.1433965
72 | assert psi4.compare_values(REF_energy, E, 5, "Reference energy")
73 |
--------------------------------------------------------------------------------
/optking/tests/test_step_types.py:
--------------------------------------------------------------------------------
1 | import psi4
2 | import optking
3 | import pytest
4 |
5 | from .utils import utils
6 |
7 | finalEnergy = -76.05776970 # TEST
8 |
9 | #! SCF CC-PVTZ geometry optimzation, with Z-matrix input
10 | @pytest.mark.parametrize(
11 | "option, expected, num_steps", [("RFO", finalEnergy, 5), ("NR", finalEnergy, 5), ("SD", finalEnergy, 10)]
12 | )
13 | def test_h2o_rfo(option, expected, num_steps, check_iter):
14 |
15 | h2o = psi4.geometry(
16 | """
17 | O
18 | H 1 1.0
19 | H 1 1.0 2 104.5
20 | """
21 | )
22 |
23 | psi4.core.clean_options()
24 | psi4_options = {
25 | "basis": "cc-pvtz",
26 | "e_convergence": "10",
27 | "d_convergence": "10",
28 | "scf_type": "pk",
29 | "max_energy_g_convergence": 7,
30 | "step_type": option,
31 | }
32 | psi4.set_options(psi4_options)
33 |
34 | json_output = optking.optimize_psi4("hf")
35 |
36 | E = json_output["energies"][-1] # TEST
37 | assert psi4.compare_values(finalEnergy, E, 6, f"{option} Step Final Energy") # TEST
38 | utils.compare_iterations(json_output, num_steps, check_iter)
39 |
--------------------------------------------------------------------------------
/optking/tests/test_ts_opt.py:
--------------------------------------------------------------------------------
1 | import psi4
2 | import optking
3 | import pytest
4 |
5 | from .utils import utils
6 |
7 | #! Optimization to 180 degree torsion from 120
8 | @pytest.mark.parametrize("option, expected_steps", [("P_RFO", 14), ("RS_I_RFO", 10)])
9 | def test_hooh_TS(check_iter, option, expected_steps):
10 |
11 | hooh = psi4.geometry(
12 | """
13 | 0 1
14 | H
15 | O 1 0.95
16 | O 2 1.40 1 105.0
17 | H 3 0.95 2 105.0 1 120.0
18 | """
19 | )
20 |
21 | psi4.core.clean_options()
22 | psi4options = {
23 | "basis": "cc-pvdz",
24 | "geom_maxiter": 30,
25 | "opt_type": "TS",
26 | "scf_type": "pk",
27 | "docc": [5, 4],
28 | "intrafrag_step_limit": 0.1,
29 | "max_energy_g_convergence": 7,
30 | }
31 | psi4.set_options(psi4options)
32 |
33 | json_output = optking.optimize_psi4("hf", {"step_type": option})
34 |
35 | E = json_output["energies"][-1] # TEST
36 | # print( '{:15.10f}'.format(E) )
37 | C2H_TS_ENERGY = -150.7854114803 # TEST
38 | assert psi4.compare_values(C2H_TS_ENERGY, E, 6, "RHF Energy after optimization to C2H TS") # TEST
39 | utils.compare_iterations(json_output, expected_steps, check_iter)
40 |
41 |
42 | #! Optimization to 0 degree torsion from 100
43 | @pytest.mark.parametrize("option, expected_steps", [("P_RFO", 21), ("RS_I_RFO", 10)])
44 | def test_hooh_TS_zero(check_iter, option, expected_steps):
45 |
46 | hooh = psi4.geometry(
47 | """
48 | 0 1
49 | H
50 | O 1 0.95
51 | O 2 1.40 1 105.0
52 | H 3 0.95 2 105.0 1 100.0
53 | """
54 | )
55 |
56 | psi4.core.clean_options()
57 | psi4options = {
58 | "basis": "cc-pvdz",
59 | "geom_maxiter": 40,
60 | "opt_type": "TS",
61 | "scf_type": "pk",
62 | "docc": [5, 4],
63 | "intrafrag_step_limit": 0.1,
64 | "max_energy_g_convergence": 7,
65 | }
66 | psi4.set_options(psi4options)
67 |
68 | json_output = optking.optimize_psi4("hf", {"step_type": option})
69 |
70 | E = json_output["energies"][-1] # TEST
71 | C2V_TS_ENERGY = -150.774009217562 # TEST
72 | assert psi4.compare_values(C2V_TS_ENERGY, E, 6, "RHF Energy after optimization to C2H TS") # TEST
73 | utils.compare_iterations(json_output, expected_steps, check_iter)
74 |
75 |
76 | def test_hooh_min(check_iter):
77 | hooh = psi4.geometry(
78 | """
79 | H
80 | O 1 0.95
81 | O 2 1.40 1 105.0
82 | H 3 0.95 2 105.0 1 100.0
83 | """
84 | )
85 |
86 | psi4.core.clean_options()
87 | psi4options = {
88 | "basis": "cc-pvdz",
89 | "geom_maxiter": 20,
90 | "opt_type": "min",
91 | "scf_type": "pk",
92 | "docc": [5, 4],
93 | "max_energy_g_convergence": 7,
94 | }
95 | psi4.set_options(psi4options)
96 |
97 | json_output = optking.optimize_psi4("hf")
98 |
99 | E = json_output["energies"][-1] # TEST
100 | # print( '{:15.10f}'.format(E) )
101 | MIN_ENERGY = -150.7867668 # TEST
102 | assert psi4.compare_values(MIN_ENERGY, E, 6, "RHF Energy") # TEST
103 | utils.compare_iterations(json_output, 7, check_iter)
104 |
--------------------------------------------------------------------------------
/optking/tests/utils/__init__.py:
--------------------------------------------------------------------------------
1 | from . import utils
2 |
--------------------------------------------------------------------------------
/optking/tests/utils/utils.py:
--------------------------------------------------------------------------------
1 | import optking
2 |
3 |
4 | def compare_iterations(json_output, expected_steps, assert_iter):
5 |
6 | logger = optking.logger
7 | steps_taken = len(json_output["trajectory"])
8 | if steps_taken != expected_steps:
9 | logger.warning(f"TEST - Number of steps taken {steps_taken}, Previous required steps {expected_steps}")
10 | else:
11 | logger.info(f"TEST - Number of steps taken matches expected {steps_taken}")
12 |
13 | if int(assert_iter):
14 | assert steps_taken == expected_steps
15 |
--------------------------------------------------------------------------------
/setup.cfg:
--------------------------------------------------------------------------------
1 | # Helper file to handle all configs
2 |
3 | [coverage:run]
4 | # .coveragerc to control coverage.py and pytest-cov
5 | # Omit the test directory from test coverage
6 | omit =
7 | */tests/*
8 | optking/_version.py
9 |
10 |
11 | [tool:isort]
12 | line_length=120
13 | include_trailing_comma=True
14 | force_grid_wrap=0
15 | use_parentheses=True
16 | multi_line_output=3
17 |
18 | [yapf]
19 | # YAPF, in .style.yapf files this shows up as "[style]" header
20 | BASED_ON_sTYLE = PEP8
21 | COLUMN_LIMIT = 119
22 | INDENT_WIDTH = 4
23 | USE_TABS = False
24 |
25 | [flake8]
26 | # Flake8, PyFlakes, etc
27 | max-line-length = 119
28 |
29 | [versioneer]
30 | # Automatic version numbering scheme
31 | VCS = git
32 | style = pep440
33 | versionfile_source = optking/_version.py
34 | versionfile_build = optking/_version.py
35 | tag_prefix = ''
36 |
37 | [tool:pytest]
38 | markers =
39 | dimers
40 | long
41 |
--------------------------------------------------------------------------------
/setup.py:
--------------------------------------------------------------------------------
1 | import setuptools
2 | import versioneer
3 |
4 | short_description = "OptKing is a python geometry optimization module originally written for PSI by R. A. King."
5 |
6 | try:
7 | with open("README.md", "r") as handle:
8 | long_description = handle.read()
9 | except:
10 | long_description = short_description
11 |
12 | if __name__ == "__main__":
13 | setuptools.setup(
14 | name="OptKing",
15 | description="A geometry optimizer for quantum chemistry.",
16 | author="Rollin King",
17 | author_email="rking@bethel.edu",
18 | url="https://github.com/psi-rking/optking",
19 | license="BSD-3C",
20 | version=versioneer.get_version(),
21 | cmdclass=versioneer.get_cmdclass(),
22 | packages=setuptools.find_packages(),
23 | include_package_data=True,
24 | install_requires=[
25 | "numpy>=1.20",
26 | "qcelemental>=0.20.0",
27 | "qcengine>=0.20.0",
28 | "msgpack>=1.0",
29 | ],
30 | extras_require={
31 | "docs": [
32 | "sphinx", # autodoc was broken in 1.3.1
33 | "sphinxcontrib-napoleon",
34 | "sphinx-automodapi"
35 | "sphinx_rtd_theme",
36 | "numpydoc",
37 | ],
38 | "tests": ["pytest", "pytest-cov", "pytest-pep8",],
39 | },
40 | tests_require=["pytest", "pytest-cov", "pytest-pep8",],
41 | classifiers=[
42 | "Development Status :: 4 - Beta",
43 | "Intended Audience :: Science/Research",
44 | "Programming Language :: Python :: 3",
45 | ],
46 | zip_safe=False,
47 | long_description=long_description,
48 | long_description_content_type="text/markdown",
49 | )
50 |
--------------------------------------------------------------------------------
|