cclib 1.8.1__tar.gz → 2.0a1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cclib-1.8.1/cclib.egg-info → cclib-2.0a1}/PKG-INFO +2 -2
- {cclib-1.8.1 → cclib-2.0a1}/README.md +1 -1
- {cclib-1.8.1 → cclib-2.0a1}/cclib/__init__.py +19 -7
- cclib-2.0a1/cclib/_version.py +1 -0
- cclib-2.0a1/cclib/attribute_parsers/__init__.py +26 -0
- cclib-2.0a1/cclib/attribute_parsers/aooverlaps.py +57 -0
- cclib-2.0a1/cclib/attribute_parsers/atombasis.py +176 -0
- cclib-2.0a1/cclib/attribute_parsers/atomcharges.py +270 -0
- cclib-2.0a1/cclib/attribute_parsers/atomcoords.py +94 -0
- cclib-2.0a1/cclib/attribute_parsers/atommasses.py +66 -0
- cclib-2.0a1/cclib/attribute_parsers/atomnos.py +91 -0
- cclib-2.0a1/cclib/attribute_parsers/base_parser.py +20 -0
- cclib-2.0a1/cclib/attribute_parsers/charge.py +70 -0
- cclib-2.0a1/cclib/attribute_parsers/coreelectrons.py +77 -0
- {cclib-1.8.1/cclib/parser → cclib-2.0a1/cclib/attribute_parsers}/data.py +45 -91
- cclib-2.0a1/cclib/attribute_parsers/gbasis.py +299 -0
- cclib-2.0a1/cclib/attribute_parsers/mocoeffs.py +73 -0
- cclib-2.0a1/cclib/attribute_parsers/moenergies.py +65 -0
- cclib-2.0a1/cclib/attribute_parsers/mosyms.py +206 -0
- cclib-2.0a1/cclib/attribute_parsers/mult.py +67 -0
- cclib-2.0a1/cclib/attribute_parsers/natom.py +57 -0
- cclib-2.0a1/cclib/attribute_parsers/nbasis.py +78 -0
- cclib-2.0a1/cclib/attribute_parsers/nmo.py +53 -0
- cclib-2.0a1/cclib/attribute_parsers/scfenergies.py +56 -0
- cclib-2.0a1/cclib/attribute_parsers/scftargets.py +72 -0
- cclib-2.0a1/cclib/attribute_parsers/scfvalues.py +70 -0
- cclib-2.0a1/cclib/attributes/__init__.py +6 -0
- cclib-2.0a1/cclib/attributes/attribute.py +811 -0
- cclib-2.0a1/cclib/collection/__init__.py +8 -0
- cclib-2.0a1/cclib/collection/collection.py +41 -0
- cclib-2.0a1/cclib/combinator/__init__.py +5 -0
- cclib-2.0a1/cclib/combinator/combinator.py +41 -0
- cclib-2.0a1/cclib/driver/__init__.py +8 -0
- cclib-2.0a1/cclib/driver/ccdriver.py +526 -0
- cclib-2.0a1/cclib/file_handler/__init__.py +8 -0
- cclib-1.8.1/cclib/parser/logfilewrapper.py → cclib-2.0a1/cclib/file_handler/file_handler.py +121 -4
- cclib-2.0a1/cclib/file_handler/utils.py +270 -0
- cclib-2.0a1/cclib/io/__init__.py +25 -0
- cclib-2.0a1/cclib/io/ccio.py +339 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/io/cjsonwriter.py +3 -3
- {cclib-1.8.1 → cclib-2.0a1}/cclib/io/moldenwriter.py +3 -6
- {cclib-1.8.1 → cclib-2.0a1}/cclib/method/bader.py +1 -4
- {cclib-1.8.1 → cclib-2.0a1}/cclib/method/ddec.py +5 -12
- {cclib-1.8.1 → cclib-2.0a1}/cclib/method/hirshfeld.py +1 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/method/volume.py +2 -1
- cclib-2.0a1/cclib/parser/__init__.py +18 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/parser/daltonparser.py +0 -1
- {cclib-1.8.1 → cclib-2.0a1}/cclib/parser/fchkparser.py +0 -1
- {cclib-1.8.1 → cclib-2.0a1}/cclib/parser/gamessdatparser.py +0 -1
- {cclib-1.8.1 → cclib-2.0a1}/cclib/parser/gamessparser.py +0 -1
- {cclib-1.8.1 → cclib-2.0a1}/cclib/parser/gamessukparser.py +0 -1
- {cclib-1.8.1 → cclib-2.0a1}/cclib/parser/gaussianparser.py +9 -6
- {cclib-1.8.1 → cclib-2.0a1}/cclib/parser/jaguarparser.py +0 -1
- {cclib-1.8.1 → cclib-2.0a1}/cclib/parser/molcasparser.py +9 -9
- {cclib-1.8.1 → cclib-2.0a1}/cclib/parser/molproparser.py +0 -1
- {cclib-1.8.1 → cclib-2.0a1}/cclib/parser/nboparser.py +0 -1
- {cclib-1.8.1 → cclib-2.0a1}/cclib/parser/nwchemparser.py +3 -4
- {cclib-1.8.1 → cclib-2.0a1}/cclib/parser/orcaparser.py +37 -18
- {cclib-1.8.1 → cclib-2.0a1}/cclib/parser/psi4parser.py +3 -8
- {cclib-1.8.1 → cclib-2.0a1}/cclib/parser/qchemparser.py +9 -13
- cclib-2.0a1/cclib/parser/utils.py +270 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/scripts/ccget.py +0 -1
- cclib-2.0a1/cclib/tree/__init__.py +5 -0
- cclib-2.0a1/cclib/tree/tree.py +87 -0
- {cclib-1.8.1 → cclib-2.0a1/cclib.egg-info}/PKG-INFO +2 -2
- {cclib-1.8.1 → cclib-2.0a1}/cclib.egg-info/SOURCES.txt +36 -2
- cclib-1.8.1/cclib/_version.py +0 -1
- cclib-1.8.1/cclib/io/__init__.py +0 -21
- cclib-1.8.1/cclib/io/ccio.py +0 -444
- cclib-1.8.1/cclib/parser/__init__.py +0 -37
- {cclib-1.8.1 → cclib-2.0a1}/ANNOUNCE +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/LICENSE +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/MANIFEST.in +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/THANKS +0 -0
- {cclib-1.8.1/cclib/parser → cclib-2.0a1/cclib/attribute_parsers}/utils.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/bridge/__init__.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/bridge/cclib2ase.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/bridge/cclib2biopython.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/bridge/cclib2horton.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/bridge/cclib2openbabel.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/bridge/cclib2psi4.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/bridge/cclib2pyquante.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/bridge/cclib2pyscf.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/io/cjsonreader.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/io/cmlwriter.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/io/filereader.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/io/filewriter.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/io/wfxwriter.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/io/xyzreader.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/io/xyzwriter.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/method/__init__.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/method/bickelhaupt.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/method/calculationmethod.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/method/cda.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/method/cm5.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/method/cspa.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/method/density.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/method/electrons.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/method/fragments.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/method/lpa.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/method/mbo.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/method/moments.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/method/mpa.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/method/nuclear.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/method/opa.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/method/orbitals.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/method/population.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/method/stockholder.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/parser/adfparser.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/parser/logfileparser.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/parser/mopacparser.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/parser/psi3parser.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/parser/turbomoleparser.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/parser/xtbparser.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/progress/__init__.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/progress/textprogress.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/py.typed +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/scripts/__init__.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/scripts/ccframe.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/scripts/ccwrite.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib/scripts/cda.py +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib.egg-info/dependency_links.txt +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib.egg-info/entry_points.txt +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib.egg-info/not-zip-safe +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib.egg-info/requires.txt +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/cclib.egg-info/top_level.txt +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/pyproject.toml +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/setup.cfg +0 -0
- {cclib-1.8.1 → cclib-2.0a1}/tools/versioningit_override.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: cclib
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0a1
|
|
4
4
|
Summary: parsers and algorithms for computational chemistry
|
|
5
5
|
Author-email: cclib development team <cclib@googlegroups.com>
|
|
6
6
|
Maintainer-email: cclib development team <cclib@googlegroups.com>
|
|
@@ -79,7 +79,7 @@ Requires-Dist: cclib[bridges]; extra == "all"
|
|
|
79
79
|
[](https://doi.org/10.5281/zenodo.8280878)
|
|
80
80
|
[](https://pypi.python.org/pypi/cclib)
|
|
81
81
|
[](https://github.com/cclib/cclib/releases)
|
|
82
|
-
[](https://github.com/cclib/cclib/actions/workflows/
|
|
82
|
+
[](https://github.com/cclib/cclib/actions/workflows/ci.yml)
|
|
83
83
|
[](https://github.com/cclib/cclib/blob/master/LICENSE)
|
|
84
84
|
|
|
85
85
|
<img src="./logo.png" alt="cclib logo" width="100" />
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[](https://doi.org/10.5281/zenodo.8280878)
|
|
4
4
|
[](https://pypi.python.org/pypi/cclib)
|
|
5
5
|
[](https://github.com/cclib/cclib/releases)
|
|
6
|
-
[](https://github.com/cclib/cclib/actions/workflows/
|
|
6
|
+
[](https://github.com/cclib/cclib/actions/workflows/ci.yml)
|
|
7
7
|
[](https://github.com/cclib/cclib/blob/master/LICENSE)
|
|
8
8
|
|
|
9
9
|
<img src="./logo.png" alt="cclib logo" width="100" />
|
|
@@ -20,17 +20,29 @@ as well as example methods that take parsed data as input.
|
|
|
20
20
|
from cclib._version import __version__
|
|
21
21
|
|
|
22
22
|
# isort: off
|
|
23
|
-
from cclib import parser, progress, method, bridge
|
|
23
|
+
# from cclib import parser, progress, method, bridge
|
|
24
|
+
from cclib import (
|
|
25
|
+
io,
|
|
26
|
+
file_handler,
|
|
27
|
+
collection,
|
|
28
|
+
combinator,
|
|
29
|
+
driver,
|
|
30
|
+
attributes,
|
|
31
|
+
attribute_parsers,
|
|
32
|
+
tree,
|
|
33
|
+
)
|
|
24
34
|
# isort: on
|
|
25
35
|
|
|
26
36
|
# The test module can be imported if it was installed with cclib.
|
|
27
|
-
try:
|
|
28
|
-
|
|
29
|
-
except ImportError:
|
|
30
|
-
|
|
37
|
+
# todo try:
|
|
38
|
+
# todo from cclib import test
|
|
39
|
+
# todo except ImportError:
|
|
40
|
+
# todo pass
|
|
31
41
|
|
|
32
42
|
# The objects below constitute our public API. These names will not change
|
|
33
43
|
# over time. Names in the sub-modules will typically also be backwards
|
|
34
44
|
# compatible, but may sometimes change when code is moved around.
|
|
35
|
-
ccopen = io.ccopen
|
|
36
|
-
ccwrite = io.ccwrite
|
|
45
|
+
# ccopen = io.ccopen
|
|
46
|
+
# ccwrite = io.ccwrite
|
|
47
|
+
|
|
48
|
+
ccDriver = driver.ccDriver
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.0a1"
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Copyright (c) 2024, the cclib development team
|
|
2
|
+
#
|
|
3
|
+
# This file is part of cclib (http://cclib.github.io) and is distributed under
|
|
4
|
+
# the terms of the BSD 3-Clause License.
|
|
5
|
+
from cclib.attribute_parsers import utils
|
|
6
|
+
from cclib.attribute_parsers.aooverlaps import aooverlaps
|
|
7
|
+
from cclib.attribute_parsers.atombasis import atombasis
|
|
8
|
+
from cclib.attribute_parsers.atomcharges import atomcharges
|
|
9
|
+
from cclib.attribute_parsers.atomcoords import atomcoords
|
|
10
|
+
from cclib.attribute_parsers.atommasses import atommasses
|
|
11
|
+
from cclib.attribute_parsers.atomnos import atomnos
|
|
12
|
+
from cclib.attribute_parsers.base_parser import base_parser
|
|
13
|
+
from cclib.attribute_parsers.charge import charge
|
|
14
|
+
from cclib.attribute_parsers.coreelectrons import coreelectrons
|
|
15
|
+
from cclib.attribute_parsers.data import ccData
|
|
16
|
+
from cclib.attribute_parsers.gbasis import gbasis
|
|
17
|
+
from cclib.attribute_parsers.mocoeffs import mocoeffs
|
|
18
|
+
from cclib.attribute_parsers.moenergies import moenergies
|
|
19
|
+
from cclib.attribute_parsers.mosyms import mosyms
|
|
20
|
+
from cclib.attribute_parsers.mult import mult
|
|
21
|
+
from cclib.attribute_parsers.natom import natom
|
|
22
|
+
from cclib.attribute_parsers.nbasis import nbasis
|
|
23
|
+
from cclib.attribute_parsers.nmo import nmo
|
|
24
|
+
from cclib.attribute_parsers.scfenergies import scfenergies
|
|
25
|
+
from cclib.attribute_parsers.scftargets import scftargets
|
|
26
|
+
from cclib.attribute_parsers.scfvalues import scfvalues
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Copyright (c) 2024, the cclib development team
|
|
2
|
+
#
|
|
3
|
+
# This file is part of cclib (http://cclib.github.io) and is distributed under
|
|
4
|
+
# the terms of the BSD 3-Clause License.
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
from cclib.attribute_parsers import utils
|
|
8
|
+
from cclib.attribute_parsers.base_parser import base_parser
|
|
9
|
+
|
|
10
|
+
import numpy as np
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class aooverlaps(base_parser):
|
|
14
|
+
"""
|
|
15
|
+
Docstring? Units?
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
known_codes = ["gaussian"]
|
|
19
|
+
|
|
20
|
+
@staticmethod
|
|
21
|
+
def gaussian(file_handler, ccdata) -> Optional[dict]:
|
|
22
|
+
# Molecular orbital overlap matrix.
|
|
23
|
+
# Has to deal with lines such as:
|
|
24
|
+
# *** Overlap ***
|
|
25
|
+
# ****** Overlap ******
|
|
26
|
+
# Note that Gaussian sometimes drops basis functions,
|
|
27
|
+
# causing the overlap matrix as parsed below to not be
|
|
28
|
+
line = file_handler.last_line
|
|
29
|
+
if line[1:4] == "***" and (line[5:12] == "Overlap" or line[8:15] == "Overlap"):
|
|
30
|
+
# Ensure that this is the main calc and not a fragment
|
|
31
|
+
# if ccdata.counterpoise != 0:
|
|
32
|
+
# return
|
|
33
|
+
constructed_aooverlaps = np.zeros((ccdata.nbasis, ccdata.nbasis), "d")
|
|
34
|
+
# Overlap integrals for basis fn#1 are in aooverlaps[0]
|
|
35
|
+
base = 0
|
|
36
|
+
colmNames = file_handler.virtual_next()
|
|
37
|
+
while base < ccdata.nbasis:
|
|
38
|
+
for i in range(ccdata.nbasis - base): # Fewer lines this time
|
|
39
|
+
line = file_handler.virtual_next()
|
|
40
|
+
parts = line.split()
|
|
41
|
+
for j in range(len(parts) - 1): # Some lines are longer than others
|
|
42
|
+
k = float(parts[j + 1].replace("D", "E"))
|
|
43
|
+
constructed_aooverlaps[base + j, i + base] = k
|
|
44
|
+
constructed_aooverlaps[i + base, base + j] = k
|
|
45
|
+
base += 5
|
|
46
|
+
colmNames = file_handler.virtual_next()
|
|
47
|
+
return {aooverlaps.__name__: constructed_aooverlaps}
|
|
48
|
+
|
|
49
|
+
@staticmethod
|
|
50
|
+
def parse(file_handler, program: str, ccdata) -> Optional[dict]:
|
|
51
|
+
constructed_data = None
|
|
52
|
+
if program in aooverlaps.known_codes:
|
|
53
|
+
file_handler.virtual_set()
|
|
54
|
+
program_parser = getattr(aooverlaps, program)
|
|
55
|
+
constructed_data = program_parser(file_handler, ccdata)
|
|
56
|
+
file_handler.virtual_reset()
|
|
57
|
+
return constructed_data
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Copyright (c) 2024, the cclib development team
|
|
2
|
+
#
|
|
3
|
+
# This file is part of cclib (http://cclib.github.io) and is distributed under
|
|
4
|
+
# the terms of the BSD 3-Clause License.
|
|
5
|
+
import re
|
|
6
|
+
from typing import Optional
|
|
7
|
+
|
|
8
|
+
from cclib.attribute_parsers import utils
|
|
9
|
+
from cclib.attribute_parsers.base_parser import base_parser
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class atombasis(base_parser):
|
|
15
|
+
"""
|
|
16
|
+
Docstring? Units?
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
known_codes = ["gaussian", "psi4", "qchem"]
|
|
20
|
+
|
|
21
|
+
@staticmethod
|
|
22
|
+
def gaussian(file_handler, ccdata) -> Optional[dict]:
|
|
23
|
+
# ccdata is "const" here and we don't need to modify it yet. The driver will set the attr
|
|
24
|
+
dependency_list = ["nmo", "nbasis"]
|
|
25
|
+
line = file_handler.last_line
|
|
26
|
+
constructed_data = None
|
|
27
|
+
if (
|
|
28
|
+
line[5:35] == "Molecular Orbital Coefficients"
|
|
29
|
+
or line[5:41] == "Alpha Molecular Orbital Coefficients"
|
|
30
|
+
or line[5:40] == "Beta Molecular Orbital Coefficients"
|
|
31
|
+
):
|
|
32
|
+
constructed_atombasis = []
|
|
33
|
+
if not base_parser.check_dependencies(dependency_list, ccdata, "atombasis"):
|
|
34
|
+
return None
|
|
35
|
+
beta = False
|
|
36
|
+
if line[5:40] == "Beta Molecular Orbital Coefficients":
|
|
37
|
+
beta = True
|
|
38
|
+
base = 0
|
|
39
|
+
curr_atombasis = []
|
|
40
|
+
for base in range(0, ccdata.nmo, 5):
|
|
41
|
+
colNames = file_handler.virtual_next()
|
|
42
|
+
symmetries = file_handler.virtual_next()
|
|
43
|
+
eigenvalues = file_handler.virtual_next()
|
|
44
|
+
for i in range(ccdata.nbasis):
|
|
45
|
+
line = file_handler.virtual_next()
|
|
46
|
+
if i == 0:
|
|
47
|
+
# Find location of the start of the basis function name
|
|
48
|
+
start_of_basis_fn_name = line.find(line.split()[3]) - 1
|
|
49
|
+
if base == 0 and not beta: # Just do this the first time 'round
|
|
50
|
+
parts = line[:start_of_basis_fn_name].split()
|
|
51
|
+
if len(parts) > 1: # New atom
|
|
52
|
+
if i > 0:
|
|
53
|
+
constructed_atombasis.append(curr_atombasis)
|
|
54
|
+
curr_atombasis = []
|
|
55
|
+
curr_atombasis.append(i)
|
|
56
|
+
if base == 0 and not beta: # Just do this the first time 'round
|
|
57
|
+
constructed_atombasis.append(curr_atombasis)
|
|
58
|
+
constructed_data = {atombasis.__name__: constructed_atombasis}
|
|
59
|
+
return constructed_data
|
|
60
|
+
|
|
61
|
+
# Natural orbital coefficients (nocoeffs) and occupation numbers (nooccnos),
|
|
62
|
+
# which are respectively define the eigenvectors and eigenvalues of the
|
|
63
|
+
# diagonalized one-electron density matrix. These orbitals are formed after
|
|
64
|
+
# configuration interaction (CI) calculations, but not only. Similarly to mocoeffs,
|
|
65
|
+
# we can parse and check aonames and atombasis here.
|
|
66
|
+
#
|
|
67
|
+
# Natural Orbital Coefficients:
|
|
68
|
+
# 1 2 3 4 5
|
|
69
|
+
# Eigenvalues -- 2.01580 2.00363 2.00000 2.00000 1.00000
|
|
70
|
+
# 1 1 O 1S 0.00000 -0.15731 -0.28062 0.97330 0.00000
|
|
71
|
+
# 2 2S 0.00000 0.75440 0.57746 0.07245 0.00000
|
|
72
|
+
# ...
|
|
73
|
+
#
|
|
74
|
+
def natural_orbital_single_spin_parsing(fh):
|
|
75
|
+
coeffs = np.zeros((ccdata.nmo, ccdata.nbasis), "d")
|
|
76
|
+
this_atombasis = []
|
|
77
|
+
for base in range(0, ccdata.nmo, 5):
|
|
78
|
+
colmNames = fh.virtual_next()
|
|
79
|
+
eigenvalues = fh.virtual_next()
|
|
80
|
+
for i in range(ccdata.nbasis):
|
|
81
|
+
line = fh.virtual_next()
|
|
82
|
+
# Just do this the first time 'round.
|
|
83
|
+
if base == 0:
|
|
84
|
+
parts = line[:12].split()
|
|
85
|
+
# New atom.
|
|
86
|
+
if len(parts) > 1:
|
|
87
|
+
if i > 0:
|
|
88
|
+
this_atombasis.append(basisonatom)
|
|
89
|
+
basisonatom = []
|
|
90
|
+
orbital = line[11:20].strip()
|
|
91
|
+
basisonatom.append(i)
|
|
92
|
+
part = line[21:].replace("D", "E").rstrip()
|
|
93
|
+
temp = []
|
|
94
|
+
for j in range(0, len(part), 10):
|
|
95
|
+
temp.append(float(part[j : j + 10]))
|
|
96
|
+
# Do the last update of atombasis.
|
|
97
|
+
if base == 0:
|
|
98
|
+
this_atombasis.append(basisonatom)
|
|
99
|
+
return this_atombasis
|
|
100
|
+
|
|
101
|
+
if line[5:33] == "Natural Orbital Coefficients":
|
|
102
|
+
parsed_atombasis = natural_orbital_single_spin_parsing(file_handler)
|
|
103
|
+
return {atombasis.__name__: parsed_atombasis}
|
|
104
|
+
|
|
105
|
+
if line[5:39] == "Alpha Natural Orbital Coefficients":
|
|
106
|
+
parsed_atombasis = natural_orbital_single_spin_parsing(file_handler)
|
|
107
|
+
print(atombasis.__name__)
|
|
108
|
+
return {atombasis.__name__: parsed_atombasis}
|
|
109
|
+
if line[5:38] == "Beta Natural Orbital Coefficients":
|
|
110
|
+
parsed_atombasis = natural_orbital_single_spin_parsing(file_handler)
|
|
111
|
+
return {atombasis.__name__: parsed_atombasis}
|
|
112
|
+
|
|
113
|
+
return None
|
|
114
|
+
|
|
115
|
+
@staticmethod
|
|
116
|
+
def psi4(file_handler, ccdata) -> Optional[dict]:
|
|
117
|
+
dependency_list = ["nmo", "nbasis"]
|
|
118
|
+
if getattr(ccdata, "atombasis") == None:
|
|
119
|
+
line = file_handler.last_line
|
|
120
|
+
if line.strip() == "-Contraction Scheme:":
|
|
121
|
+
file_handler.skip_lines(["headers", "d"], virtual=True)
|
|
122
|
+
line = file_handler.virtual_next()
|
|
123
|
+
constructed_atombasis = []
|
|
124
|
+
atombasis_pos = 0
|
|
125
|
+
while line.strip():
|
|
126
|
+
ao_count = 0
|
|
127
|
+
shells = line.split("//")[1].split()
|
|
128
|
+
for s in shells:
|
|
129
|
+
count, basistype = s
|
|
130
|
+
multiplier = 3 * (basistype == "p") or 1
|
|
131
|
+
ao_count += multiplier * int(count)
|
|
132
|
+
if len(constructed_atombasis) > 0:
|
|
133
|
+
atombasis_pos = constructed_atombasis[-1][-1] + 1
|
|
134
|
+
constructed_atombasis.append(
|
|
135
|
+
list(range(atombasis_pos, atombasis_pos + ao_count))
|
|
136
|
+
)
|
|
137
|
+
line = file_handler.virtual_next()
|
|
138
|
+
constructed_data = {atombasis.__name__: constructed_atombasis}
|
|
139
|
+
return constructed_data
|
|
140
|
+
return None
|
|
141
|
+
|
|
142
|
+
@staticmethod
|
|
143
|
+
def qchem(file_handler, ccdata) -> Optional[dict]:
|
|
144
|
+
# This block comes from `print_orbitals = true/{int}`. Less
|
|
145
|
+
# precision than `scf_final_print >= 2` for `mocoeffs`, but
|
|
146
|
+
# important for `aonames` and `atombasis`.
|
|
147
|
+
alpha_mo_coefficient_headers = []
|
|
148
|
+
qchem_re_atomindex = re.compile(r"(\d+)_")
|
|
149
|
+
|
|
150
|
+
dependency_list = ["aonames", "atomnos", "nbasis", "natom"]
|
|
151
|
+
line = file_handler.last_line
|
|
152
|
+
if any(header in line for header in alpha_mo_coefficient_headers):
|
|
153
|
+
if base_parser.check_dependencies(dependency_list, ccdata, "atombasis"):
|
|
154
|
+
constructed_atombasis = []
|
|
155
|
+
for n in range(ccdata.natom):
|
|
156
|
+
constructed_atombasis.append([])
|
|
157
|
+
# Go back through `aonames` to create `atombasis`.
|
|
158
|
+
assert len(ccdata.aonames) == ccdata.nbasis
|
|
159
|
+
for aoindex, aoname in enumerate(ccdata.aonames):
|
|
160
|
+
atomindex = int(qchem_re_atomindex.search(aoname).groups()[0]) - 1
|
|
161
|
+
constructed_atombasis.atombasis[atomindex].append(aoindex)
|
|
162
|
+
assert len(self.atombasis) == len(self.atomnos)
|
|
163
|
+
if not hasattr(ccdata, "atombasis"):
|
|
164
|
+
constructed_data = {atombasis.__name__: constructed_atombasis}
|
|
165
|
+
return constructed_data
|
|
166
|
+
return None
|
|
167
|
+
|
|
168
|
+
@staticmethod
|
|
169
|
+
def parse(file_handler, program: str, ccdata) -> Optional[dict]:
|
|
170
|
+
constructed_data = None
|
|
171
|
+
if program in atombasis.known_codes:
|
|
172
|
+
file_handler.virtual_set()
|
|
173
|
+
program_parser = getattr(atombasis, program)
|
|
174
|
+
constructed_data = program_parser(file_handler, ccdata)
|
|
175
|
+
file_handler.virtual_reset()
|
|
176
|
+
return constructed_data
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
# Copyright (c) 2024, the cclib development team
|
|
2
|
+
#
|
|
3
|
+
# This file is part of cclib (http://cclib.github.io) and is distributed under
|
|
4
|
+
# the terms of the BSD 3-Clause License.
|
|
5
|
+
from typing import Optional
|
|
6
|
+
|
|
7
|
+
from cclib.attribute_parsers import utils
|
|
8
|
+
from cclib.attribute_parsers.base_parser import base_parser
|
|
9
|
+
|
|
10
|
+
import numpy as np
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def orca_parse_charge_section(file_handler, chargestype):
|
|
14
|
+
"""Parse a charge section
|
|
15
|
+
|
|
16
|
+
Parameters
|
|
17
|
+
----------
|
|
18
|
+
file_handler :
|
|
19
|
+
generates lines
|
|
20
|
+
chargestype : str
|
|
21
|
+
what type of charge we're dealing with, must be one of
|
|
22
|
+
'mulliken', 'lowdin', 'chelpg' or 'hirshfeld'
|
|
23
|
+
"""
|
|
24
|
+
atomcharges = dict()
|
|
25
|
+
atomspins = dict()
|
|
26
|
+
line = file_handler.last_line
|
|
27
|
+
has_spins = "AND SPIN POPULATIONS" in line
|
|
28
|
+
|
|
29
|
+
file_handler.skip_lines(["dashes"], virtual=True)
|
|
30
|
+
|
|
31
|
+
# depending on chargestype, decide when to stop parsing lines
|
|
32
|
+
# start, stop - indices for slicing lines and grabbing values
|
|
33
|
+
# should_stop: when to stop parsing
|
|
34
|
+
if chargestype == "mulliken":
|
|
35
|
+
should_stop = lambda x: x.startswith("Sum of atomic charges")
|
|
36
|
+
start, stop = 8, 20
|
|
37
|
+
elif chargestype == "lowdin":
|
|
38
|
+
should_stop = lambda x: not bool(x.strip())
|
|
39
|
+
start, stop = 8, 20
|
|
40
|
+
elif chargestype == "chelpg":
|
|
41
|
+
should_stop = lambda x: x.startswith("---")
|
|
42
|
+
start, stop = 11, 26
|
|
43
|
+
elif chargestype == "hirshfeld":
|
|
44
|
+
should_stop = lambda x: not bool(x.strip())
|
|
45
|
+
start, stop = 9, 18
|
|
46
|
+
file_handler.skip_lines(
|
|
47
|
+
["d", "b", "Total integrated alpha density", "Total integrated beta density", "header"],
|
|
48
|
+
virtual=True,
|
|
49
|
+
)
|
|
50
|
+
else:
|
|
51
|
+
raise RuntimeError(f"unknown chargestype: {chargestype}")
|
|
52
|
+
|
|
53
|
+
charges = []
|
|
54
|
+
spins = []
|
|
55
|
+
|
|
56
|
+
line = file_handler.virtual_next()
|
|
57
|
+
while not should_stop(line):
|
|
58
|
+
# Don't add point charges or embedding potentials.
|
|
59
|
+
if "Q :" not in line:
|
|
60
|
+
charges.append(float(line[start:stop]))
|
|
61
|
+
if has_spins:
|
|
62
|
+
spins.append(float(line[stop:]))
|
|
63
|
+
line = file_handler.virtual_next()
|
|
64
|
+
|
|
65
|
+
atomcharges[chargestype] = charges
|
|
66
|
+
if has_spins:
|
|
67
|
+
atomspins[chargestype] = spins
|
|
68
|
+
return atomcharges, atomspins
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def qchem_parse_charge_section(file_handler, chargetype):
|
|
72
|
+
"""Parse the population analysis charge block."""
|
|
73
|
+
atomcharges = dict()
|
|
74
|
+
atomspins = dict()
|
|
75
|
+
charges = []
|
|
76
|
+
spins = []
|
|
77
|
+
line = file_handler.last_line
|
|
78
|
+
file_handler.skip_lines(["blank"], virtual=True)
|
|
79
|
+
line = file_handler.virtual_next()
|
|
80
|
+
has_spins = False
|
|
81
|
+
if "Spin" in line:
|
|
82
|
+
has_spins = True
|
|
83
|
+
file_handler.skip_lines(["dashes"], virtual=True)
|
|
84
|
+
line = file_handler.virtual_next()
|
|
85
|
+
|
|
86
|
+
while list(set(line.strip())) != ["-"]:
|
|
87
|
+
elements = line.split()
|
|
88
|
+
charge = utils.float(elements[2])
|
|
89
|
+
charges.append(charge)
|
|
90
|
+
if has_spins:
|
|
91
|
+
spin = utils.float(elements[3])
|
|
92
|
+
spins.append(spin)
|
|
93
|
+
line = file_handler.virtual_next()
|
|
94
|
+
|
|
95
|
+
atomcharges[chargetype] = charges
|
|
96
|
+
if has_spins:
|
|
97
|
+
atomspins[chargestype] = spins
|
|
98
|
+
return atomcharges, atomspins
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
class atomcharges(base_parser):
|
|
102
|
+
"""
|
|
103
|
+
Docstring? Units?
|
|
104
|
+
"""
|
|
105
|
+
|
|
106
|
+
known_codes = ["ORCA", "NBO", "qchem"]
|
|
107
|
+
|
|
108
|
+
@staticmethod
|
|
109
|
+
def ORCA(file_handler, ccdata) -> Optional[dict]:
|
|
110
|
+
# ccdata is "const" here and we don't need to modify it yet. The driver will set the attr
|
|
111
|
+
line = file_handler.last_line
|
|
112
|
+
constructed_charge_data = None
|
|
113
|
+
constructed_spin_data = None
|
|
114
|
+
|
|
115
|
+
# ORCA will print atomic charges along with the spin populations,
|
|
116
|
+
# so care must be taken about choosing the proper column.
|
|
117
|
+
# Population analyses are performed usually only at the end
|
|
118
|
+
# of a geometry optimization or other run, so we want to
|
|
119
|
+
# leave just the final atom charges.
|
|
120
|
+
# Here is an example for Mulliken charges:
|
|
121
|
+
# --------------------------------------------
|
|
122
|
+
# MULLIKEN ATOMIC CHARGES AND SPIN POPULATIONS
|
|
123
|
+
# --------------------------------------------
|
|
124
|
+
# 0 H : 0.126447 0.002622
|
|
125
|
+
# 1 C : -0.613018 -0.029484
|
|
126
|
+
# 2 H : 0.189146 0.015452
|
|
127
|
+
# 3 H : 0.320041 0.037434
|
|
128
|
+
# ...
|
|
129
|
+
# Sum of atomic charges : -0.0000000
|
|
130
|
+
# Sum of atomic spin populations: 1.0000000
|
|
131
|
+
if line[:23] == "MULLIKEN ATOMIC CHARGES":
|
|
132
|
+
constructed_charge_data, constructed_spin_data = orca_parse_charge_section(
|
|
133
|
+
file_handler, "mulliken"
|
|
134
|
+
)
|
|
135
|
+
# Things are the same for Lowdin populations, except that the sums
|
|
136
|
+
# are not printed (there is a blank line at the end).
|
|
137
|
+
if line[:22] == "LOEWDIN ATOMIC CHARGES":
|
|
138
|
+
constructed_charge_data, constructed_spin_data = orca_parse_charge_section(
|
|
139
|
+
file_handler, "lowdin"
|
|
140
|
+
)
|
|
141
|
+
# ------------------
|
|
142
|
+
# HIRSHFELD ANALYSIS
|
|
143
|
+
# ------------------
|
|
144
|
+
#
|
|
145
|
+
# Total integrated alpha density = 142.999988722
|
|
146
|
+
# Total integrated beta density = 142.999988722
|
|
147
|
+
#
|
|
148
|
+
# ATOM CHARGE SPIN
|
|
149
|
+
# 0 H 0.157924 0.000000
|
|
150
|
+
# 1 O -0.209542 0.000000
|
|
151
|
+
# 2 C 0.030659 0.000000
|
|
152
|
+
# ...
|
|
153
|
+
# TOTAL -0.999977 0.000000
|
|
154
|
+
if line[:18] == "HIRSHFELD ANALYSIS":
|
|
155
|
+
constructed_charge_data, constructed_spin_data = orca_parse_charge_section(
|
|
156
|
+
file_handler, "hirshfeld"
|
|
157
|
+
)
|
|
158
|
+
# CHELPG Charges
|
|
159
|
+
# --------------------------------
|
|
160
|
+
# 0 C : 0.363939
|
|
161
|
+
# 1 H : 0.025695
|
|
162
|
+
# ...
|
|
163
|
+
# --------------------------------
|
|
164
|
+
# Total charge: -0.000000
|
|
165
|
+
# --------------------------------
|
|
166
|
+
if line.startswith("CHELPG Charges"):
|
|
167
|
+
constructed_charge_data, constructed_spin_data = orca_parse_charge_section(
|
|
168
|
+
file_handler, "chelpg"
|
|
169
|
+
)
|
|
170
|
+
# TODO handle atomspins
|
|
171
|
+
constructed_data = dict()
|
|
172
|
+
if constructed_charge_data:
|
|
173
|
+
if ccdata.atomcharges:
|
|
174
|
+
constructed_data["atomcharges"] = {**ccdata.atomcharges, **constructed_charge_data}
|
|
175
|
+
else:
|
|
176
|
+
constructed_data["atomcharges"] = {**constructed_charge_data}
|
|
177
|
+
if constructed_spin_data:
|
|
178
|
+
if ccdata.atomspins:
|
|
179
|
+
constructed_data["atomspins"] = {**ccdata.atomspins, **constructed_spin_data}
|
|
180
|
+
else:
|
|
181
|
+
constructed_data["atomspins"] = {**constructed_spin_data}
|
|
182
|
+
if constructed_data:
|
|
183
|
+
return constructed_data
|
|
184
|
+
return None
|
|
185
|
+
|
|
186
|
+
@staticmethod
|
|
187
|
+
def NBO(file_handler, ccdata) -> Optional[dict]:
|
|
188
|
+
atomcharges = dict()
|
|
189
|
+
# ccdata is "const" here and we don't need to modify it yet. The driver will set the attr
|
|
190
|
+
charges = None
|
|
191
|
+
line = file_handler.last_line
|
|
192
|
+
if " Atom No Charge" in line:
|
|
193
|
+
parsed_charges = []
|
|
194
|
+
line = file_handler.virtual_next()
|
|
195
|
+
line = file_handler.virtual_next()
|
|
196
|
+
while "==============" not in line:
|
|
197
|
+
population_analysis = line.split()
|
|
198
|
+
atom = population_analysis[0]
|
|
199
|
+
no = int(population_analysis[1])
|
|
200
|
+
natural_charge = float(population_analysis[2])
|
|
201
|
+
core = float(population_analysis[3])
|
|
202
|
+
valence = float(population_analysis[4])
|
|
203
|
+
rydberg = float(population_analysis[5])
|
|
204
|
+
total = float(population_analysis[6])
|
|
205
|
+
parsed_charges.append(natural_charge)
|
|
206
|
+
line = file_handler.virtual_next()
|
|
207
|
+
atomcharges["nbo"] = parsed_charges
|
|
208
|
+
constructed_data = dict()
|
|
209
|
+
if atomcharges != dict():
|
|
210
|
+
if ccdata.atomcharges:
|
|
211
|
+
constructed_data["atomcharges"] = {**ccdata.atomcharges, **atomcharges}
|
|
212
|
+
else:
|
|
213
|
+
constructed_data["atomcharges"] = {**atomcharges}
|
|
214
|
+
return constructed_data
|
|
215
|
+
return None
|
|
216
|
+
|
|
217
|
+
@staticmethod
|
|
218
|
+
def qchem(file_handler, ccdata) -> Optional[dict]:
|
|
219
|
+
line = file_handler.last_line
|
|
220
|
+
constructed_charge_data = None
|
|
221
|
+
constructed_spin_data = None
|
|
222
|
+
constructed_data = dict()
|
|
223
|
+
if "Ground-State Mulliken Net Atomic Charges" in line:
|
|
224
|
+
constructed_charge_data, constructed_spin_data = qchem_parse_charge_section(
|
|
225
|
+
inputfile, "mulliken"
|
|
226
|
+
)
|
|
227
|
+
if "Hirshfeld Atomic Charges" in line:
|
|
228
|
+
constructed_charge_data, constructed_spin_data = qchem_parse_charge_section(
|
|
229
|
+
inputfile, "hirshfeld"
|
|
230
|
+
)
|
|
231
|
+
if "Charge Model 5" in line:
|
|
232
|
+
constructed_charge_data, constructed_spin_data = qchem_parse_charge_section(
|
|
233
|
+
inputfile, "cm5"
|
|
234
|
+
)
|
|
235
|
+
if "Ground-State ChElPG Net Atomic Charges" in line:
|
|
236
|
+
constructed_charge_data, constructed_spin_data = qchem_parse_charge_section(
|
|
237
|
+
inputfile, "chelpg"
|
|
238
|
+
)
|
|
239
|
+
if "Merz-Kollman ESP Net Atomic Charges" in line:
|
|
240
|
+
constructed_charge_data, constructed_spin_data = qchem_parse_charge_section(
|
|
241
|
+
inputfile, "esp"
|
|
242
|
+
)
|
|
243
|
+
if "Merz-Kollman RESP Net Atomic Charges" in line:
|
|
244
|
+
constructed_charge_data, constructed_spin_data = qchem_parse_charge_section(
|
|
245
|
+
inputfile, "resp"
|
|
246
|
+
)
|
|
247
|
+
constructed_data = dict()
|
|
248
|
+
if constructed_charge_data:
|
|
249
|
+
if ccdata.atomcharges:
|
|
250
|
+
constructed_data["atomcharges"] = {**ccdata.atomcharges, **constructed_charge_data}
|
|
251
|
+
else:
|
|
252
|
+
constructed_data["atomcharges"] = {**constructed_charge_data}
|
|
253
|
+
if constructed_spin_data:
|
|
254
|
+
if ccdata.atomspins:
|
|
255
|
+
constructed_data["atomspins"] = {**ccdata.atomspins, **constructed_spin_data}
|
|
256
|
+
else:
|
|
257
|
+
constructed_data["atomspins"] = {**constructed_spin_data}
|
|
258
|
+
if constructed_data:
|
|
259
|
+
return constructed_data
|
|
260
|
+
return None
|
|
261
|
+
|
|
262
|
+
@staticmethod
|
|
263
|
+
def parse(file_handler, program: str, ccdata) -> Optional[dict]:
|
|
264
|
+
constructed_data = None
|
|
265
|
+
if program in atomcharges.known_codes:
|
|
266
|
+
file_handler.virtual_set()
|
|
267
|
+
program_parser = getattr(atomcharges, program)
|
|
268
|
+
constructed_data = program_parser(file_handler, ccdata)
|
|
269
|
+
file_handler.virtual_reset()
|
|
270
|
+
return constructed_data
|