symvb 2.0.0__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.
- symvb-2.0.0/LICENSE +21 -0
- symvb-2.0.0/PKG-INFO +152 -0
- symvb-2.0.0/README.md +122 -0
- symvb-2.0.0/setup.cfg +4 -0
- symvb-2.0.0/setup.py +44 -0
- symvb-2.0.0/symvb/__init__.py +18 -0
- symvb-2.0.0/symvb/_o2_benchmark.py +163 -0
- symvb-2.0.0/symvb/_o2_blocked.py +301 -0
- symvb-2.0.0/symvb/_o2_symmetric.py +124 -0
- symvb-2.0.0/symvb/data.py +24 -0
- symvb-2.0.0/symvb/fixed_psi.py +272 -0
- symvb-2.0.0/symvb/functions.py +231 -0
- symvb-2.0.0/symvb/huckel.py +322 -0
- symvb-2.0.0/symvb/mo_projection.py +252 -0
- symvb-2.0.0/symvb/molecule.py +736 -0
- symvb-2.0.0/symvb/numerical.py +267 -0
- symvb-2.0.0/symvb/operators.py +667 -0
- symvb-2.0.0/symvb/orbital_permutations.py +49 -0
- symvb-2.0.0/symvb/slaterdet.py +142 -0
- symvb-2.0.0/symvb/spin.py +233 -0
- symvb-2.0.0/symvb/symmetry.py +467 -0
- symvb-2.0.0/symvb/system.py +354 -0
- symvb-2.0.0/symvb/test_det_conventions.py +292 -0
- symvb-2.0.0/symvb/test_fixed_psi.py +170 -0
- symvb-2.0.0/symvb/test_functions.py +95 -0
- symvb-2.0.0/symvb/test_molecule.py +467 -0
- symvb-2.0.0/symvb/test_non_default_flags.py +124 -0
- symvb-2.0.0/symvb/test_numerical.py +72 -0
- symvb-2.0.0/symvb/test_o2_agreement.py +548 -0
- symvb-2.0.0/symvb/test_o2_symmetric.py +193 -0
- symvb-2.0.0/symvb/test_operators.py +227 -0
- symvb-2.0.0/symvb/test_slaterdet.py +93 -0
- symvb-2.0.0/symvb/test_symmetry_exact.py +234 -0
- symvb-2.0.0/symvb/test_system.py +297 -0
- symvb-2.0.0/symvb.egg-info/PKG-INFO +152 -0
- symvb-2.0.0/symvb.egg-info/SOURCES.txt +38 -0
- symvb-2.0.0/symvb.egg-info/dependency_links.txt +1 -0
- symvb-2.0.0/symvb.egg-info/requires.txt +3 -0
- symvb-2.0.0/symvb.egg-info/top_level.txt +1 -0
- symvb-2.0.0/symvb.egg-info/zip-safe +1 -0
symvb-2.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Marat R. Talipov, Punhasa Senanayake, and contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
symvb-2.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: symvb
|
|
3
|
+
Version: 2.0.0
|
|
4
|
+
Summary: Symbolic calculations for semi-quantitative Valence Bond Theory
|
|
5
|
+
Home-page: https://github.com/ComputationalChemistry-NMSU/symvb
|
|
6
|
+
Author: Marat Talipov
|
|
7
|
+
Author-email: talipovm@nmsu.edu
|
|
8
|
+
License: MIT
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
13
|
+
Requires-Python: >=3.8
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
License-File: LICENSE
|
|
16
|
+
Requires-Dist: sympy>=1.13
|
|
17
|
+
Requires-Dist: numpy>=1.24
|
|
18
|
+
Requires-Dist: scipy>=1.10
|
|
19
|
+
Dynamic: author
|
|
20
|
+
Dynamic: author-email
|
|
21
|
+
Dynamic: classifier
|
|
22
|
+
Dynamic: description
|
|
23
|
+
Dynamic: description-content-type
|
|
24
|
+
Dynamic: home-page
|
|
25
|
+
Dynamic: license
|
|
26
|
+
Dynamic: license-file
|
|
27
|
+
Dynamic: requires-dist
|
|
28
|
+
Dynamic: requires-python
|
|
29
|
+
Dynamic: summary
|
|
30
|
+
|
|
31
|
+
# symvb
|
|
32
|
+
|
|
33
|
+
Symbolic valence-bond theory in Python. `symvb` builds Slater
|
|
34
|
+
determinants over user-supplied orbital sets, computes one- and
|
|
35
|
+
two-electron matrix elements via Löwdin's cofactor expansion, and
|
|
36
|
+
returns the resulting Hamiltonian and overlap as `sympy` matrices —
|
|
37
|
+
everything stays symbolic in the bond, overlap, and Coulomb
|
|
38
|
+
parameters until you choose to substitute.
|
|
39
|
+
|
|
40
|
+
The package targets pedagogical and small-system research use:
|
|
41
|
+
H₂, allyl, benzene, (H₂)ₙ⁺ chains, cyclic polyenes, and similar
|
|
42
|
+
model systems where closed-form analysis is preferable to
|
|
43
|
+
purely numerical FCI.
|
|
44
|
+
|
|
45
|
+
## Install
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install git+https://github.com/ComputationalChemistry-NMSU/symvb.git
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
Or clone and run without installing:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
git clone https://github.com/ComputationalChemistry-NMSU/symvb.git
|
|
55
|
+
cd symvb
|
|
56
|
+
PYTHONPATH=. python3 examples/h2_hubbard_bond.py
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Python ≥ 3.8 (tested on 3.8 and 3.11). The symbolic core needs only
|
|
60
|
+
`sympy`; the numeric helpers (`ground_state(subs=...)`, the scan
|
|
61
|
+
patterns) and most examples also use `numpy` and `scipy`. For the
|
|
62
|
+
teaching notebooks add `jupyter` and `matplotlib`.
|
|
63
|
+
|
|
64
|
+
## Quick start
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
from symvb import Molecule, FixedPsi, System
|
|
68
|
+
|
|
69
|
+
m = Molecule(zero_ii=True, interacting_orbs=['ab'],
|
|
70
|
+
subst={'h': ('H_ab',), 's': ('S_ab',)},
|
|
71
|
+
subst_2e={'U': ('1111',)}, max_2e_centers=1)
|
|
72
|
+
cov = FixedPsi('aB'); cov.add_str_det('bA', coef=1) # Heitler-London singlet
|
|
73
|
+
ion = FixedPsi('aA'); ion.add_str_det('bB', coef=1) # symmetric ionic
|
|
74
|
+
|
|
75
|
+
bond = System.from_structures(m, [cov, ion])
|
|
76
|
+
E, c = bond.ground_state() # symbolic ground-state energy + vector
|
|
77
|
+
w_cov, w_ion = bond.weights() # Chirgwin-Coulson weights
|
|
78
|
+
|
|
79
|
+
benzene = System.ring(6) # topology fills in every edge + on-site U
|
|
80
|
+
H, S = benzene.hamiltonian() # 400x400 sympy matrices, 2e block folded in (~1 min build)
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
The underlying symbolic matrices stay fully accessible
|
|
84
|
+
(`m.build_matrix(P, op='H')`, `m.o2_matrix(P)`). See
|
|
85
|
+
[docs/recipes.md](docs/recipes.md) for common tasks and
|
|
86
|
+
[docs/api.md](docs/api.md) for the full surface.
|
|
87
|
+
|
|
88
|
+
## Documentation
|
|
89
|
+
|
|
90
|
+
- [docs/api.md](docs/api.md) — API reference: modules, signatures, conventions.
|
|
91
|
+
- [docs/recipes.md](docs/recipes.md) — task-oriented cookbook; every snippet is
|
|
92
|
+
verified by `docs/_recipes_check.py`.
|
|
93
|
+
- [docs/operators_tutorial.md](docs/operators_tutorial.md) — the second-quantized
|
|
94
|
+
operator algebra, in depth.
|
|
95
|
+
|
|
96
|
+
[docs/README.md](docs/README.md) is the index.
|
|
97
|
+
|
|
98
|
+
## Teaching notebooks
|
|
99
|
+
|
|
100
|
+
`notebooks/` derives valence-bond theory from the ground up with `symvb`; every
|
|
101
|
+
result is *derived*, not quoted. The four main notebooks are companions to the
|
|
102
|
+
manuscript's four model systems:
|
|
103
|
+
|
|
104
|
+
1. **H₂, the two-center two-electron bond** — covalent/ionic weights versus
|
|
105
|
+
correlation, the singlet–triplet gap, and charge-shift bonding.
|
|
106
|
+
2. **The allyl anion (3c4e)** — a long-bond Rumer structure as a biradical
|
|
107
|
+
signature.
|
|
108
|
+
3. **The (H₂)₂⁺ disphenoid (4c3e)** — the Robin–Day Class II/III crossover.
|
|
109
|
+
4. **Benzene** — a covalent-only model inverts the sign of the energy response.
|
|
110
|
+
|
|
111
|
+
`notebooks/additional/` keeps further topics (the U=J operator identity, the
|
|
112
|
+
Hubbard→Heisenberg mapping, symmetry projection). See
|
|
113
|
+
[notebooks/README.md](notebooks/README.md), and open in Jupyter with:
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
PYTHONPATH=. jupyter notebook notebooks/
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Examples
|
|
120
|
+
|
|
121
|
+
`examples/` collects 80 stand-alone scripts, most of them cited from
|
|
122
|
+
the manuscript's source-data records. Worked examples cover H₂, H₂⁺,
|
|
123
|
+
allyl (anion / cation / triplet), benzene, (H₂)ₙ⁺ chains for
|
|
124
|
+
$n = 2, 3, 4$, cyclobutadiene dianion, cyclopentadienyl anion, F₂,
|
|
125
|
+
and benzene + O₃ aromaticity loss. Run any script from the repo root
|
|
126
|
+
with `PYTHONPATH=.`:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
PYTHONPATH=. python3 examples/benzene_heisenberg_mapping.py
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
A few scripts cache large symbolic matrices under `/tmp` on first run
|
|
133
|
+
(subsequent runs are fast), and the plotting scripts write their PNGs
|
|
134
|
+
into `figures/`.
|
|
135
|
+
|
|
136
|
+
## Tests
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
PYTHONPATH=. python3 -m pytest symvb -q # 201 tests
|
|
140
|
+
PYTHONPATH=. python3 docs/_recipes_check.py # every documented recipe, executed
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## License
|
|
144
|
+
|
|
145
|
+
MIT.
|
|
146
|
+
|
|
147
|
+
## Funding
|
|
148
|
+
|
|
149
|
+
Research reported in this repository was supported by an
|
|
150
|
+
Institutional Development Award (IDeA) from the National Institute
|
|
151
|
+
of General Medical Sciences of the National Institutes of Health
|
|
152
|
+
under grant number P20GM103451.
|
symvb-2.0.0/README.md
ADDED
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# symvb
|
|
2
|
+
|
|
3
|
+
Symbolic valence-bond theory in Python. `symvb` builds Slater
|
|
4
|
+
determinants over user-supplied orbital sets, computes one- and
|
|
5
|
+
two-electron matrix elements via Löwdin's cofactor expansion, and
|
|
6
|
+
returns the resulting Hamiltonian and overlap as `sympy` matrices —
|
|
7
|
+
everything stays symbolic in the bond, overlap, and Coulomb
|
|
8
|
+
parameters until you choose to substitute.
|
|
9
|
+
|
|
10
|
+
The package targets pedagogical and small-system research use:
|
|
11
|
+
H₂, allyl, benzene, (H₂)ₙ⁺ chains, cyclic polyenes, and similar
|
|
12
|
+
model systems where closed-form analysis is preferable to
|
|
13
|
+
purely numerical FCI.
|
|
14
|
+
|
|
15
|
+
## Install
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install git+https://github.com/ComputationalChemistry-NMSU/symvb.git
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Or clone and run without installing:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
git clone https://github.com/ComputationalChemistry-NMSU/symvb.git
|
|
25
|
+
cd symvb
|
|
26
|
+
PYTHONPATH=. python3 examples/h2_hubbard_bond.py
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
Python ≥ 3.8 (tested on 3.8 and 3.11). The symbolic core needs only
|
|
30
|
+
`sympy`; the numeric helpers (`ground_state(subs=...)`, the scan
|
|
31
|
+
patterns) and most examples also use `numpy` and `scipy`. For the
|
|
32
|
+
teaching notebooks add `jupyter` and `matplotlib`.
|
|
33
|
+
|
|
34
|
+
## Quick start
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
from symvb import Molecule, FixedPsi, System
|
|
38
|
+
|
|
39
|
+
m = Molecule(zero_ii=True, interacting_orbs=['ab'],
|
|
40
|
+
subst={'h': ('H_ab',), 's': ('S_ab',)},
|
|
41
|
+
subst_2e={'U': ('1111',)}, max_2e_centers=1)
|
|
42
|
+
cov = FixedPsi('aB'); cov.add_str_det('bA', coef=1) # Heitler-London singlet
|
|
43
|
+
ion = FixedPsi('aA'); ion.add_str_det('bB', coef=1) # symmetric ionic
|
|
44
|
+
|
|
45
|
+
bond = System.from_structures(m, [cov, ion])
|
|
46
|
+
E, c = bond.ground_state() # symbolic ground-state energy + vector
|
|
47
|
+
w_cov, w_ion = bond.weights() # Chirgwin-Coulson weights
|
|
48
|
+
|
|
49
|
+
benzene = System.ring(6) # topology fills in every edge + on-site U
|
|
50
|
+
H, S = benzene.hamiltonian() # 400x400 sympy matrices, 2e block folded in (~1 min build)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
The underlying symbolic matrices stay fully accessible
|
|
54
|
+
(`m.build_matrix(P, op='H')`, `m.o2_matrix(P)`). See
|
|
55
|
+
[docs/recipes.md](docs/recipes.md) for common tasks and
|
|
56
|
+
[docs/api.md](docs/api.md) for the full surface.
|
|
57
|
+
|
|
58
|
+
## Documentation
|
|
59
|
+
|
|
60
|
+
- [docs/api.md](docs/api.md) — API reference: modules, signatures, conventions.
|
|
61
|
+
- [docs/recipes.md](docs/recipes.md) — task-oriented cookbook; every snippet is
|
|
62
|
+
verified by `docs/_recipes_check.py`.
|
|
63
|
+
- [docs/operators_tutorial.md](docs/operators_tutorial.md) — the second-quantized
|
|
64
|
+
operator algebra, in depth.
|
|
65
|
+
|
|
66
|
+
[docs/README.md](docs/README.md) is the index.
|
|
67
|
+
|
|
68
|
+
## Teaching notebooks
|
|
69
|
+
|
|
70
|
+
`notebooks/` derives valence-bond theory from the ground up with `symvb`; every
|
|
71
|
+
result is *derived*, not quoted. The four main notebooks are companions to the
|
|
72
|
+
manuscript's four model systems:
|
|
73
|
+
|
|
74
|
+
1. **H₂, the two-center two-electron bond** — covalent/ionic weights versus
|
|
75
|
+
correlation, the singlet–triplet gap, and charge-shift bonding.
|
|
76
|
+
2. **The allyl anion (3c4e)** — a long-bond Rumer structure as a biradical
|
|
77
|
+
signature.
|
|
78
|
+
3. **The (H₂)₂⁺ disphenoid (4c3e)** — the Robin–Day Class II/III crossover.
|
|
79
|
+
4. **Benzene** — a covalent-only model inverts the sign of the energy response.
|
|
80
|
+
|
|
81
|
+
`notebooks/additional/` keeps further topics (the U=J operator identity, the
|
|
82
|
+
Hubbard→Heisenberg mapping, symmetry projection). See
|
|
83
|
+
[notebooks/README.md](notebooks/README.md), and open in Jupyter with:
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
PYTHONPATH=. jupyter notebook notebooks/
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Examples
|
|
90
|
+
|
|
91
|
+
`examples/` collects 80 stand-alone scripts, most of them cited from
|
|
92
|
+
the manuscript's source-data records. Worked examples cover H₂, H₂⁺,
|
|
93
|
+
allyl (anion / cation / triplet), benzene, (H₂)ₙ⁺ chains for
|
|
94
|
+
$n = 2, 3, 4$, cyclobutadiene dianion, cyclopentadienyl anion, F₂,
|
|
95
|
+
and benzene + O₃ aromaticity loss. Run any script from the repo root
|
|
96
|
+
with `PYTHONPATH=.`:
|
|
97
|
+
|
|
98
|
+
```bash
|
|
99
|
+
PYTHONPATH=. python3 examples/benzene_heisenberg_mapping.py
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
A few scripts cache large symbolic matrices under `/tmp` on first run
|
|
103
|
+
(subsequent runs are fast), and the plotting scripts write their PNGs
|
|
104
|
+
into `figures/`.
|
|
105
|
+
|
|
106
|
+
## Tests
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
PYTHONPATH=. python3 -m pytest symvb -q # 201 tests
|
|
110
|
+
PYTHONPATH=. python3 docs/_recipes_check.py # every documented recipe, executed
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## License
|
|
114
|
+
|
|
115
|
+
MIT.
|
|
116
|
+
|
|
117
|
+
## Funding
|
|
118
|
+
|
|
119
|
+
Research reported in this repository was supported by an
|
|
120
|
+
Institutional Development Award (IDeA) from the National Institute
|
|
121
|
+
of General Medical Sciences of the National Institutes of Health
|
|
122
|
+
under grant number P20GM103451.
|
symvb-2.0.0/setup.cfg
ADDED
symvb-2.0.0/setup.py
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
from setuptools import setup
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def get_long_description():
|
|
6
|
+
topdir = os.path.abspath(os.path.join(__file__, '..'))
|
|
7
|
+
with open(os.path.join(topdir, 'README.md'), 'r') as f:
|
|
8
|
+
return f.read()
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def get_version():
|
|
12
|
+
topdir = os.path.abspath(os.path.join(__file__, '..'))
|
|
13
|
+
with open(os.path.join(topdir, 'symvb', '__init__.py'), 'r') as f:
|
|
14
|
+
for line in f.readlines():
|
|
15
|
+
if line.startswith('__version__'):
|
|
16
|
+
delim = '"' if '"' in line else "'"
|
|
17
|
+
return line.split(delim)[1]
|
|
18
|
+
raise ValueError("Version string not found")
|
|
19
|
+
|
|
20
|
+
VERSION = get_version()
|
|
21
|
+
|
|
22
|
+
setup(name='symvb',
|
|
23
|
+
version=VERSION,
|
|
24
|
+
description='Symbolic calculations for semi-quantitative Valence Bond Theory',
|
|
25
|
+
long_description=get_long_description(),
|
|
26
|
+
long_description_content_type='text/markdown',
|
|
27
|
+
url='https://github.com/ComputationalChemistry-NMSU/symvb',
|
|
28
|
+
author='Marat Talipov',
|
|
29
|
+
author_email='talipovm@nmsu.edu',
|
|
30
|
+
license='MIT',
|
|
31
|
+
license_files=['LICENSE'],
|
|
32
|
+
classifiers=[
|
|
33
|
+
'Programming Language :: Python :: 3',
|
|
34
|
+
'License :: OSI Approved :: MIT License',
|
|
35
|
+
'Intended Audience :: Science/Research',
|
|
36
|
+
'Topic :: Scientific/Engineering :: Chemistry',
|
|
37
|
+
],
|
|
38
|
+
packages=['symvb'],
|
|
39
|
+
zip_safe=True,
|
|
40
|
+
python_requires='>=3.8',
|
|
41
|
+
# numpy/scipy are imported at module level by molecule, functions,
|
|
42
|
+
# numerical, symmetry, spin, operators, and mo_projection
|
|
43
|
+
install_requires=['sympy>=1.13', 'numpy>=1.24', 'scipy>=1.10'],
|
|
44
|
+
)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from symvb.slaterdet import SlaterDet
|
|
2
|
+
from symvb.fixed_psi import FixedPsi
|
|
3
|
+
from symvb.molecule import Molecule
|
|
4
|
+
from symvb import symmetry
|
|
5
|
+
from symvb import spin
|
|
6
|
+
from symvb import huckel
|
|
7
|
+
from symvb import mo_projection
|
|
8
|
+
from symvb import operators
|
|
9
|
+
from symvb import system
|
|
10
|
+
from symvb.system import (System, hamiltonian, ground_state,
|
|
11
|
+
chirgwin_coulson, structure_vector)
|
|
12
|
+
from symvb.mo_projection import verify_eigenpair, EigenpairResidualError
|
|
13
|
+
|
|
14
|
+
import logging
|
|
15
|
+
|
|
16
|
+
logging.basicConfig(format='%(levelname)-8s: %(message)s')
|
|
17
|
+
|
|
18
|
+
__version__ = "2.0.0"
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Benchmark the two o2_det implementations on a fixed system battery.
|
|
3
|
+
|
|
4
|
+
Runs each (system, method) combination N_TRIALS times, reports the median
|
|
5
|
+
of wall-time and peak memory, plus the total SymPy-op count of the
|
|
6
|
+
resulting matrix as a proxy for output expression complexity.
|
|
7
|
+
|
|
8
|
+
Usage:
|
|
9
|
+
cd vbt-3-repo
|
|
10
|
+
PYTHONPATH=. python3 -m symvb._o2_benchmark
|
|
11
|
+
"""
|
|
12
|
+
from __future__ import annotations
|
|
13
|
+
|
|
14
|
+
import gc
|
|
15
|
+
import time
|
|
16
|
+
import tracemalloc
|
|
17
|
+
|
|
18
|
+
import sympy as sp
|
|
19
|
+
|
|
20
|
+
from symvb import Molecule
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
# --- Cases ---------------------------------------------------------------
|
|
24
|
+
|
|
25
|
+
_PPP_2E = {'U': ('1111',), 'J': ('1212',), 'K': ('1122',),
|
|
26
|
+
'M': ('1112', '1121', '1222')}
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _h2(cutoff):
|
|
30
|
+
return dict(
|
|
31
|
+
label='H2',
|
|
32
|
+
Na=1, Nb=1, Norbs=2,
|
|
33
|
+
kwargs=dict(subst_2e=_PPP_2E,
|
|
34
|
+
interacting_orbs=['ab'],
|
|
35
|
+
max_2e_centers=cutoff),
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def _allyl(cutoff):
|
|
40
|
+
return dict(
|
|
41
|
+
label='allyl-3c4e',
|
|
42
|
+
Na=2, Nb=2, Norbs=3,
|
|
43
|
+
kwargs=dict(subst_2e=_PPP_2E,
|
|
44
|
+
interacting_orbs=['ab', 'bc'],
|
|
45
|
+
max_2e_centers=cutoff),
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def _benzene_ppp():
|
|
50
|
+
return dict(
|
|
51
|
+
label='benzene-PPP',
|
|
52
|
+
Na=3, Nb=3, Norbs=6,
|
|
53
|
+
kwargs=dict(
|
|
54
|
+
zero_ii=True,
|
|
55
|
+
interacting_orbs=['ab', 'bc', 'cd', 'de', 'ef', 'af'],
|
|
56
|
+
subst={'h': ('H_ab', 'H_bc', 'H_cd', 'H_de', 'H_ef', 'H_af'),
|
|
57
|
+
's': ('S_ab', 'S_bc', 'S_cd', 'S_de', 'S_ef', 'S_af')},
|
|
58
|
+
subst_2e=_PPP_2E,
|
|
59
|
+
max_2e_centers=2,
|
|
60
|
+
),
|
|
61
|
+
)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
CASES = [
|
|
65
|
+
(_h2(cutoff=1), 5),
|
|
66
|
+
(_h2(cutoff=2), 5),
|
|
67
|
+
(_allyl(cutoff=1), 5),
|
|
68
|
+
(_allyl(cutoff=2), 5),
|
|
69
|
+
(_allyl(cutoff=3), 3),
|
|
70
|
+
(_allyl(cutoff=4), 3),
|
|
71
|
+
(_benzene_ppp(), 1), # 1 trial; if blocked is fast we can rerun with more
|
|
72
|
+
]
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
# --- Bench runner --------------------------------------------------------
|
|
76
|
+
|
|
77
|
+
def _build_matrix_o2(method, case):
|
|
78
|
+
m = Molecule(o2_method=method, **case['kwargs'])
|
|
79
|
+
m.generate_basis(case['Na'], case['Nb'], case['Norbs'])
|
|
80
|
+
return m.o2_matrix(m.basis)
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
def _count_ops(matrix):
|
|
84
|
+
return sum(int(matrix[i, j].count_ops())
|
|
85
|
+
for i in range(matrix.rows) for j in range(matrix.cols))
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def _trial(method, case):
|
|
89
|
+
gc.collect()
|
|
90
|
+
tracemalloc.start()
|
|
91
|
+
t0 = time.perf_counter()
|
|
92
|
+
H2 = _build_matrix_o2(method, case)
|
|
93
|
+
wall = time.perf_counter() - t0
|
|
94
|
+
_, peak = tracemalloc.get_traced_memory()
|
|
95
|
+
tracemalloc.stop()
|
|
96
|
+
ops = _count_ops(H2)
|
|
97
|
+
n = H2.rows
|
|
98
|
+
return dict(wall=wall, peak_mb=peak / (1024 * 1024), ops=ops, dim=n)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _median(xs):
|
|
102
|
+
xs = sorted(xs)
|
|
103
|
+
n = len(xs)
|
|
104
|
+
if n == 0:
|
|
105
|
+
return float('nan')
|
|
106
|
+
if n % 2 == 1:
|
|
107
|
+
return xs[n // 2]
|
|
108
|
+
return 0.5 * (xs[n // 2 - 1] + xs[n // 2])
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def benchmark():
|
|
112
|
+
print('=' * 78)
|
|
113
|
+
print('Two-electron matrix benchmark: direct vs blocked')
|
|
114
|
+
print('=' * 78)
|
|
115
|
+
print()
|
|
116
|
+
header = ('| %-15s | %-7s | %-7s | dim | wall (s) | peak (MB) '
|
|
117
|
+
'| ops | speedup |')
|
|
118
|
+
sep = ('|-----------------|---------|---------|-------'
|
|
119
|
+
'|------------|------------|----------|---------|')
|
|
120
|
+
print(header % ('system', 'cutoff', 'method'))
|
|
121
|
+
print(sep)
|
|
122
|
+
for case, n_trials in CASES:
|
|
123
|
+
cutoff = case['kwargs'].get('max_2e_centers', 4)
|
|
124
|
+
results = {}
|
|
125
|
+
for method in ('direct', 'blocked'):
|
|
126
|
+
print(' ... %s cutoff=%d %s (n=%d)'
|
|
127
|
+
% (case['label'], cutoff, method, n_trials), flush=True)
|
|
128
|
+
trials = []
|
|
129
|
+
for ti in range(n_trials):
|
|
130
|
+
t = _trial(method, case)
|
|
131
|
+
trials.append(t)
|
|
132
|
+
print(' trial %d: wall=%.3fs peak=%.1fMB'
|
|
133
|
+
% (ti, t['wall'], t['peak_mb']), flush=True)
|
|
134
|
+
results[method] = dict(
|
|
135
|
+
wall=_median([t['wall'] for t in trials]),
|
|
136
|
+
peak_mb=_median([t['peak_mb'] for t in trials]),
|
|
137
|
+
ops=trials[0]['ops'],
|
|
138
|
+
dim=trials[0]['dim'],
|
|
139
|
+
)
|
|
140
|
+
# Print rows; speedup column shown on the blocked row only.
|
|
141
|
+
for method in ('direct', 'blocked'):
|
|
142
|
+
r = results[method]
|
|
143
|
+
speedup = ''
|
|
144
|
+
if method == 'blocked' and results['direct']['wall'] > 0:
|
|
145
|
+
speedup = '%.2fx' % (results['direct']['wall'] / r['wall'])
|
|
146
|
+
print('| %-15s | %-7d | %-7s | %-5d | %-10.3f | %-10.2f '
|
|
147
|
+
'| %-8d | %-7s |'
|
|
148
|
+
% (case['label'], cutoff, method, r['dim'],
|
|
149
|
+
r['wall'], r['peak_mb'], r['ops'], speedup))
|
|
150
|
+
# Sanity: ops should agree (modulo chemist-symmetry symbol naming).
|
|
151
|
+
ops_diff = results['direct']['ops'] - results['blocked']['ops']
|
|
152
|
+
if ops_diff != 0:
|
|
153
|
+
print('| ^ ops differ by %+d (chemist-symbol naming, not '
|
|
154
|
+
'a correctness issue)' % ops_diff)
|
|
155
|
+
print()
|
|
156
|
+
print('Notes:')
|
|
157
|
+
print(' - wall and peak_mb are medians across N_TRIALS runs.')
|
|
158
|
+
print(' - ops = sum of sympy.count_ops() over all matrix entries.')
|
|
159
|
+
print(' - speedup > 1 means blocked is faster.')
|
|
160
|
+
|
|
161
|
+
|
|
162
|
+
if __name__ == '__main__':
|
|
163
|
+
benchmark()
|