Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
aaad484
start of ip/ea-adc in refactored adcc
fedy9 Jan 20, 2026
856489a
Refactored guess setup and implemented ip/ea guesses making guess/__i…
fedy9 Jan 20, 2026
b5b108a
Merge branch 'adc-connect:master' into refactor_new_implementation
fedy9 Jan 20, 2026
11b32ea
IP/EA workflow running properly, ExcitedState implementation left to do
fedy9 Jan 21, 2026
34800a7
simplified adc0 pole strengths
fedy9 Jan 21, 2026
bc36c4d
cleanup
fedy9 Jan 21, 2026
1eade6e
extended ExcitedStates class with Child classes for IP/EA-ADC
fedy9 Jan 22, 2026
6ad844d
slight refactorization of guess setup for simplicity
fedy9 Jan 22, 2026
6a0fb82
corrected small mistakes and adapted some tests
fedy9 Jan 23, 2026
b16612f
refactored guess setup separating 'spin_change' and 'spin_block_symme…
fedy9 Feb 6, 2026
7a41274
Make Davidson subspace max_iter parameter available to user
fedy9 Feb 10, 2026
ac03f0c
added pole strengths for ip/ea-adc2x (which is adc2)
fedy9 Feb 24, 2026
1781cbe
prettied up
fedy9 Feb 24, 2026
3603f1c
refactored test setup to generate ip/ea reference data from adcc and …
fedy9 Feb 24, 2026
ecbb175
adapted workflow tests
fedy9 Feb 24, 2026
2a2da19
property and state_density tests for IP/EA-ADC(0-3) (adcman and adcc)
fedy9 Feb 24, 2026
8ecd776
guess tes setup
fedy9 Feb 24, 2026
31dc8a9
put spin_change back into guess functions and make guesses_doublet av…
fedy9 Feb 24, 2026
69dc17b
updated workflow test
fedy9 Feb 24, 2026
047d5f4
added matrix reference data for alpha ip/ea calcs and set alpha defau…
fedy9 Feb 25, 2026
7cb94c7
adapted spin_change behavior
fedy9 Feb 25, 2026
7a06f83
IP/EA-ADC AdcMatrix tests
fedy9 Feb 25, 2026
98a07bc
minimal ChargedExcitation test suite
fedy9 Feb 25, 2026
38f06d6
adapted property and state_dens tests to not perform ip/ea-adc1 tests
fedy9 Feb 25, 2026
3b5d9f4
adcman now produces alpha reference data also for restricted cases so…
fedy9 Feb 25, 2026
5cdf077
adapted tests, all running now
fedy9 Feb 25, 2026
1d0bed3
Merge branch 'refactor_new_implementation' that enables full IP/EA-AD…
fedy9 Feb 26, 2026
5d2ac4e
adapted new OneParticle Syntax
fedy9 Feb 26, 2026
61b7453
merge upstream (<S^2> calc. for PP)
fedy9 Mar 3, 2026
6ce8408
updated 1p property tests and name of pp test, all running for ip/ea …
fedy9 Mar 5, 2026
9dea173
added 2p densities/properties for IP/EA-ADC(0-2), TODO: tests for ip/…
fedy9 Mar 5, 2026
7e5c73d
merge upstream/master
fedy9 Mar 5, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
63 changes: 48 additions & 15 deletions adcc/AdcMatrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@

from .LazyMp import LazyMp
from .adc_pp import matrix as ppmatrix
from .adc_ip import matrix as ipmatrix
from .adc_ea import matrix as eamatrix
from .timings import Timer, timed_member_call
from .AdcMethod import AdcMethod
from .functions import ones_like
Expand Down Expand Up @@ -73,6 +75,8 @@ class AdcMatrixlike:

_special_block_orders = {
"adc2x": {"ph_ph": 2, "ph_pphh": 1, "pphh_ph": 1, "pphh_pphh": 1},
"ip-adc2x": {"h_h": 2, "h_phh": 1, "phh_h": 1, "phh_phh": 1},
"ea-adc2x": {"p_p": 2, "p_pph": 1, "pph_p": 1, "pph_pph": 1},
}

@classmethod
Expand All @@ -90,7 +94,9 @@ def _default_block_orders(cls, method: AdcMethod) -> dict[str, int]:
# - determine which spaces are available in the ADC(n) matrix
# starting from the given minimal space
min_space = {
"pp": "ph"
"pp": "ph",
"ip": "h",
"ea": "p"
}.get(method.adc_type, None)
if min_space is None:
raise ValueError(f"Unknown adc type {method.adc_type} for method "
Expand Down Expand Up @@ -178,6 +184,10 @@ def _is_valid_space(cls, space: str, method: AdcMethod) -> bool:
# be equal or differ e.g. by +-1 (IP/EA)
if method.adc_type == "pp":
return n_particle == n_hole
elif method.adc_type == "ip":
return n_particle == n_hole - 1
elif method.adc_type == "ea":
return n_particle == n_hole + 1
raise ValueError(f"Unknown adc type {method.adc_type} for method "
f"{method.name}. Can not validate space.")

Expand Down Expand Up @@ -252,11 +262,19 @@ def __init__(self, method, hf_or_mp, block_orders=None, intermediates=None,
variant = None
if self.is_core_valence_separated:
variant = "cvs"
# Directly import block dispatch functions?
BLOCK_DISPATCH = {
"pp": ppmatrix.block,
"ip": ipmatrix.block,
"ea": eamatrix.block}
block_dispatch_fun = BLOCK_DISPATCH[self.method.adc_type]
blocks = {
block: ppmatrix.block(self.ground_state, block.split("_"),
order=order, intermediates=self.intermediates,
block: block_dispatch_fun(self.ground_state, block.split("_"),
order=order,
intermediates=self.intermediates,
variant=variant)
for block, order in self.block_orders.items() if order is not None
for block, order in self.block_orders.items()
if order is not None
}
self.blocks = {bl: blocks[bl].apply for bl in blocks}
if diagonal_precomputed:
Expand Down Expand Up @@ -362,7 +380,8 @@ def block_apply(self, block, tensor):
with another AmplitudeVector or Tensor. Non-matching blocks
in the AmplitudeVector will be ignored.
"""
if not isinstance(tensor, libadcc.Tensor):
# TODO: Allow AmplitudeVector?
if not isinstance(tensor, (libadcc.Tensor, AmplitudeVector)):
raise TypeError("tensor should be an adcc.Tensor")

with self.timer.record(f"apply/{block}"):
Expand Down Expand Up @@ -426,16 +445,30 @@ def construct_symmetrisation_for_blocks(self):
Returns a dictionary block identifier -> function
"""
ret = {}
if self.is_core_valence_separated:
# CVS doubles part is antisymmetric wrt. (i,K,a,b) <-> (i,K,b,a)
ret["pphh"] = lambda v: v.antisymmetrise([(2, 3)])
else:
def symmetrise_generic_adc_doubles(invec):
# doubles part is antisymmetric wrt. (i,j,a,b) <-> (i,j,b,a)
scratch = invec.antisymmetrise([(2, 3)])
# doubles part is symmetric wrt. (i,j,a,b) <-> (j,i,b,a)
return scratch.symmetrise([(0, 1), (2, 3)])
ret["pphh"] = symmetrise_generic_adc_doubles
# TODO: IP/EA doubles
if self.method.adc_type == "pp":
if self.is_core_valence_separated:
# CVS doubles part is antisymmetric wrt. (i,K,a,b) <-> (i,K,b,a)
ret["pphh"] = lambda v: v.antisymmetrise([(2, 3)])
else:
def symmetrise_generic_adc_doubles(invec):
# doubles part is antisymmetric wrt. (i,j,a,b) <-> (i,j,b,a)
scratch = invec.antisymmetrise([(2, 3)])
# doubles part is symmetric wrt. (i,j,a,b) <-> (j,i,b,a)
return scratch.symmetrise([(0, 1), (2, 3)])
ret["pphh"] = symmetrise_generic_adc_doubles
elif self.method.adc_type == "ip":
if not self.is_core_valence_separated:
def symmetrise_generic_adc_doubles(invec):
# doubles part is antisymmetric wrt. (i,j,a) <-> (j,i,a)
return invec.antisymmetrise([(0, 1)])
ret["phh"] = symmetrise_generic_adc_doubles
elif self.method.adc_type == "ea":
if not self.is_core_valence_separated:
def symmetrise_generic_adc_doubles(invec):
# doubles part is antisymmetric wrt. (i,a,b) <-> (i,a,b)
return invec.antisymmetrise([(1, 2)])
ret["pph"] = symmetrise_generic_adc_doubles
return ret

def dense_basis(self, axis_blocks=None, ordering="adcc"):
Expand Down
33 changes: 24 additions & 9 deletions adcc/AdcMethod.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,13 @@

def get_valid_methods():
valid_prefixes = ["cvs"]
valid_adc_types = ["ip", "ea"]
valid_bases = ["adc0", "adc1", "adc2", "adc2x", "adc3"]

ret = valid_bases + [p + "-" + m for p in valid_prefixes
for m in valid_bases]
ret = (valid_bases
+ [p + "-" + m for p in valid_prefixes for m in valid_bases]
+ [t + "-" + m for t in valid_adc_types for m in valid_bases]
)
return ret


Expand All @@ -43,8 +46,13 @@ def __init__(self, method):
self.__base_method = split[-1]
split = split[:-1]
self.is_core_valence_separated = "cvs" in split
# NOTE: added this to make the testdata generation ready for IP/EA
self.adc_type = "pp"

if "ip" in split:
self.adc_type = "ip"
elif "ea" in split:
self.adc_type = "ea"
else:
self.adc_type = "pp"

try:
if self.__base_method == "adc2x":
Expand All @@ -59,17 +67,22 @@ def at_level(self, newlevel):
Return an equivalent method, where only the level is changed
(e.g. calling this on a CVS method returns a CVS method)
"""
name_str = "adc"
if self.adc_type != "pp":
name_str = self.adc_type + "-" + "adc"
if self.is_core_valence_separated:
return AdcMethod("cvs-adc" + str(newlevel))
return AdcMethod("cvs-" + name_str + str(newlevel))
else:
return AdcMethod("adc" + str(newlevel))
return AdcMethod(name_str + str(newlevel))

@property
def name(self):
name = self.__base_method
if self.adc_type != "pp":
name = self.adc_type + "-" + name
if self.is_core_valence_separated:
return "cvs-" + self.__base_method
else:
return self.__base_method
name = "cvs-" + name
return name

@property
def property_method(self):
Expand All @@ -89,6 +102,8 @@ def base_method(self):
The base (full) method, i.e. with all approximations such as
CVS stripped off.
"""
if self.adc_type != "pp":
return AdcMethod(self.adc_type + "-" + self.__base_method)
return AdcMethod(self.__base_method)

def __eq__(self, other):
Expand Down
4 changes: 3 additions & 1 deletion adcc/AmplitudeVector.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,9 @@ class AmplitudeVector(dict):
def __init__(self, **kwargs):
"""
Construct an AmplitudeVector. Typical use cases are
``AmplitudeVector(ph=tensor_singles, pphh=tensor_doubles)``.
``AmplitudeVector(ph=tensor_singles, pphh=tensor_doubles)``. For IP-ADC
``AmplitudeVector(h=tensor_singles, phh=tensor_doubles)``, and for
EA-ADC ``AmplitudeVector(p=tensor_singles, pph=tensor_doubles)``
"""
super().__init__(**kwargs)

Expand Down
Loading
Loading