Skip to content

Commit cc80836

Browse files
Fix MCD (#15)
* fix mcd_bterm * pin zarr 2.0 * fix sos_mcd_bterm * update testdata with fixed magnetic tdms * add todo for transition_polarizability * fix ruff * fix ci
1 parent 7e0577c commit cc80836

File tree

8 files changed

+21
-66
lines changed

8 files changed

+21
-66
lines changed

ci_env.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ dependencies:
99
- pytest
1010
- pytest-cov
1111
- coveralls
12-
- zarr
12+
- zarr>=2,<3
1313
- ruff
1414
- isort

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ test = [
4242
"pytest-cov",
4343
"pytest-runner",
4444
"pyscf",
45-
"zarr",
45+
"zarr>=2,<3",
4646
]
4747

4848
[tool.setuptools]

respondo/mcd.py

Lines changed: 8 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -1,43 +1,12 @@
11
import numpy as np
2-
from adcc import AmplitudeVector
32
from adcc.adc_pp.modified_transition_moments import modified_transition_moments
43
from adcc.Excitation import Excitation
5-
from adcc.functions import einsum
64
from adcc.workflow import construct_adcmatrix
75

86
from .misc import select_property_method
97
from .solve_response import solve_response, transition_polarizability
108

119

12-
def compute_adc1_f1_mag(magdip, ground_state):
13-
mtm = magdip.ov + einsum("ijab,jb->ia", ground_state.t2("o1o1v1v1"), magdip.ov)
14-
return AmplitudeVector(ph=mtm)
15-
16-
17-
def compute_adc2_f1_mag(magdip, ground_state):
18-
t2 = ground_state.t2("o1o1v1v1")
19-
td2 = ground_state.td2("o1o1v1v1")
20-
p0 = ground_state.mp2_diffdm
21-
d = magdip
22-
return (
23-
d.ov
24-
+ 1.0 * einsum("ijab,jb->ia", t2, d.ov + 0.5 * einsum("jkbc,kc->jb", t2, d.ov))
25-
+ 0.5 * (einsum("ij,ja->ia", p0.oo, d.ov) - 1.0 * einsum("ib,ab->ia", d.ov, p0.vv))
26-
- 1.0 * einsum("ib,ab->ia", p0.ov, d.vv)
27-
- 1.0 * einsum("ij,ja->ia", d.oo, p0.ov)
28-
+ 1.0 * einsum("ijab,jb->ia", td2, d.ov)
29-
)
30-
31-
32-
def compute_adc2_f2_mag(magdip, ground_state):
33-
t2 = ground_state.t2("o1o1v1v1")
34-
term1 = -1.0 * einsum("ijac,bc->ijab", t2, magdip.vv)
35-
term2 = -1.0 * einsum("ik,kjab->ijab", magdip.oo, t2)
36-
term1 = term1.antisymmetrise(2, 3)
37-
term2 = term2.antisymmetrise(0, 1)
38-
return term1 - term2
39-
40-
4110
def mcd_bterm(state, property_method=None, **solver_args):
4211
if not isinstance(state, Excitation):
4312
raise TypeError()
@@ -49,30 +18,12 @@ def mcd_bterm(state, property_method=None, **solver_args):
4918

5019
dips_el = hf.operators.electric_dipole
5120
dips_mag = hf.operators.magnetic_dipole
52-
# Electric dipole right-hand-side
5321
rhss_el = modified_transition_moments(property_method, mp, dips_el)
22+
rhss_mag = modified_transition_moments(property_method, mp, dips_mag)
5423

55-
# Magnetic dipole right-hand-side
56-
# TODO: temporary hack, add to adcc...
57-
if property_method.name == "adc0":
58-
rhss_mag = modified_transition_moments(property_method, mp, dips_mag)
59-
rhss_mag = [-1.0 * rhs_mag for rhs_mag in rhss_mag]
60-
elif property_method.name == "adc1":
61-
rhss_mag = [-1.0 * compute_adc1_f1_mag(mag, mp) for mag in dips_mag]
62-
elif property_method.name == "adc2":
63-
rhss_mag = [
64-
-1.0
65-
* AmplitudeVector(
66-
ph=compute_adc2_f1_mag(mag, mp),
67-
pphh=compute_adc2_f2_mag(mag, mp),
68-
)
69-
for mag in dips_mag
70-
]
71-
else:
72-
raise NotImplementedError("")
73-
24+
# the minus sign is required due to the anti-hermiticity of the magnetic dipole operator
7425
response_mag = [
75-
solve_response(matrix, rhs_mag, omega=0.0, gamma=0.0, **solver_args) for rhs_mag in rhss_mag
26+
-1.0 * solve_response(matrix, rhs_mag, omega=0.0, gamma=0.0, **solver_args) for rhs_mag in rhss_mag
7627
]
7728

7829
v_f = state.excitation_vector
@@ -93,14 +44,16 @@ def projection(X, bl=None):
9344
for rhs_el in rhss_el
9445
]
9546

96-
term1 = -transition_polarizability(property_method, mp, response_mag, dips_el, v_f)
97-
term2 = -transition_polarizability(property_method, mp, v_f, dips_mag, response_el)
47+
term1 = transition_polarizability(property_method, mp, v_f, dips_el, response_mag)
48+
term2 = transition_polarizability(property_method, mp, v_f, dips_mag, response_el)
9849

9950
# Levi-Civita tensor
10051
epsilon = np.zeros((3, 3, 3))
10152
epsilon[0, 1, 2] = epsilon[1, 2, 0] = epsilon[2, 0, 1] = 1
10253
epsilon[2, 1, 0] = epsilon[0, 2, 1] = epsilon[1, 0, 2] = -1
10354

10455
tdip_f = state.transition_dipole_moment
105-
B = np.einsum("abc,a,bc->", epsilon, tdip_f, term1 + term2)
56+
# the minus sign accounts for the negative charge, since it is not included in the operators
57+
# TODO as soon as PR #190 in adcc is merged: remove minus
58+
B = -1.0 * np.einsum("abc,a,bc->", epsilon, tdip_f, term1 + np.transpose(term2))
10659
return B

respondo/solve_response.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ def solve_response(
8989
)
9090

9191

92+
# TODO: fix transition_polarizability and transition_polarizability_complex
93+
# by swapping from_vecs and to_vecs (for ADC it is defined the other way around)
9294
# from_vecs * B(ops) * to_vecs
9395
def transition_polarizability(method, ground_state, from_vecs, ops, to_vecs):
9496
if not isinstance(from_vecs, list):

respondo/sos.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -112,19 +112,19 @@ def sos_mcd_bterm(state, final_state=0):
112112
for A in range(3):
113113
for B in range(3):
114114
term1[A, B] -= (
115-
state.transition_magnetic_dipole_moment[k][A]
116-
* s2s_tdm[k, final_state, B]
115+
state.transition_magnetic_dipole_moment[k][B]
116+
* s2s_tdm[final_state, k, A]
117117
/ (state.excitation_energy_uncorrected[k])
118118
)
119119
if k != final_state:
120120
term2[A, B] += (
121-
state.transition_dipole_moment[k][B]
122-
* s2s_tdm_mag[k, final_state, A]
121+
state.transition_dipole_moment[k][A]
122+
* s2s_tdm_mag[final_state, k, B]
123123
/ (state.excitation_energy_uncorrected[k] - e_f)
124124
)
125125

126126
epsilon = np.zeros((3, 3, 3))
127127
epsilon[0, 1, 2] = epsilon[1, 2, 0] = epsilon[2, 0, 1] = 1
128128
epsilon[2, 1, 0] = epsilon[0, 2, 1] = epsilon[1, 0, 2] = -1
129-
B = np.einsum("abc,a,bc->", epsilon, tdip_f, term1 + term2)
129+
B = -1.0 * np.einsum("abc,a,bc->", epsilon, tdip_f, term1 + term2)
130130
return B

respondo/testdata/0_download_testdata.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
# taken from adcc repository, written by @mfherbst
44

5-
SOURCE="https://wwwagdreuw.iwr.uni-heidelberg.de/respondo_test_data/0.1.0"
5+
SOURCE="https://wwwagdreuw.iwr.uni-heidelberg.de/respondo_test_data/0.2.0"
66
DATAFILES=(
7-
data_0.0.1.tar.gz
7+
data_0.2.0.tar.gz
88
)
99
#
1010
# -----

respondo/testdata/SHA256SUMS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
63522c1f857212c5622de5b18f89e9c8c1d9676f5b5621b24f9508fc48d5d6ef data_0.0.1.tar.gz
1+
ed7bf0506c2c9d299529a56a5b4a6c76b9985b2bd2954b8be13abc33375342ed data_0.2.0.tar.gz

respondo/testdata/dump_full_diagonalization.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ def main():
4747
z.create_group("excitation")
4848
exci = z["excitation"]
4949
propkeys = state.excitation_property_keys
50-
propkeys.extend(state.excitation_energy_corrections.keys())
50+
propkeys.extend([k.name for k in state._excitation_energy_corrections])
5151
for key in propkeys:
5252
try:
5353
d = getattr(state, key)

0 commit comments

Comments
 (0)