-
Notifications
You must be signed in to change notification settings - Fork 21
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IP/EA-ADC up to 3rd order #168
base: master
Are you sure you want to change the base?
Changes from all commits
a894098
0228ea4
228e34b
e67996a
c0c3fc4
bbd1aa4
007e95c
6e4fec9
5682cc4
54b722c
5d1eb88
e741a77
2c2b2ac
47402bb
8282d04
7f76e3e
34e84a5
2de6a19
f388516
15d726f
9cfce9a
d8ee7cf
d898c48
c976f79
8ec6aa3
f753dde
bcc05e6
3181cbb
15e443a
e6a922b
8f5b3c0
269f58e
8e73f1d
6d03562
d36f561
4029b99
79f14b7
b52b2f9
ff1085f
3f4f504
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,6 +26,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 | ||
|
@@ -73,14 +75,25 @@ class AdcMatrixlike: | |
|
||
|
||
class AdcMatrix(AdcMatrixlike): | ||
# Default perturbation-theory orders for the matrix blocks (== standard ADC-PP). | ||
# Default perturbation-theory orders for the matrix blocks | ||
# (== standard ADC-PP). | ||
default_block_orders = { | ||
# ph_ph=0, ph_pphh=None, pphh_ph=None, pphh_pphh=None), | ||
"adc0": dict(ph_ph=0, ph_pphh=None, pphh_ph=None, pphh_pphh=None), # noqa: E501 | ||
"adc1": dict(ph_ph=1, ph_pphh=None, pphh_ph=None, pphh_pphh=None), # noqa: E501 | ||
"adc2": dict(ph_ph=2, ph_pphh=1, pphh_ph=1, pphh_pphh=0), # noqa: E501 | ||
"adc2x": dict(ph_ph=2, ph_pphh=1, pphh_ph=1, pphh_pphh=1), # noqa: E501 | ||
"adc3": dict(ph_ph=3, ph_pphh=2, pphh_ph=2, pphh_pphh=1), # noqa: E501 | ||
"adc0": dict(ph_ph=0, ph_pphh=None, pphh_ph=None, pphh_pphh=None), # noqa: E501 | ||
"adc1": dict(ph_ph=1, ph_pphh=None, pphh_ph=None, pphh_pphh=None), # noqa: E501 | ||
"adc2": dict(ph_ph=2, ph_pphh=1, pphh_ph=1, pphh_pphh=0), # noqa: E501 | ||
"adc2x": dict(ph_ph=2, ph_pphh=1, pphh_ph=1, pphh_pphh=1), # noqa: E501 | ||
"adc3": dict(ph_ph=3, ph_pphh=2, pphh_ph=2, pphh_pphh=1), # noqa: E501 | ||
"ip_adc0": dict(h_h=0, h_phh=None, phh_h=None, phh_phh=None), | ||
"ip_adc1": dict(h_h=1, h_phh=None, phh_h=None, phh_phh=None), | ||
"ip_adc2": dict(h_h=2, h_phh=1, phh_h=1, phh_phh=0), | ||
"ip_adc2x": dict(h_h=2, h_phh=1, phh_h=1, phh_phh=1), | ||
"ip_adc3": dict(h_h=3, h_phh=2, phh_h=2, phh_phh=1), | ||
"ea_adc0": dict(p_p=0, p_pph=None, pph_p=None, pph_pph=None), | ||
"ea_adc1": dict(p_p=1, p_pph=None, pph_p=None, pph_pph=None), | ||
"ea_adc2": dict(p_p=2, p_pph=1, pph_p=1, pph_pph=0), | ||
"ea_adc2x": dict(p_p=2, p_pph=1, pph_p=1, pph_pph=1), | ||
"ea_adc3": dict(p_p=3, p_pph=2, pph_p=2, pph_pph=1), | ||
} | ||
|
||
def __init__(self, method, hf_or_mp, block_orders=None, intermediates=None, | ||
|
@@ -96,7 +109,8 @@ def __init__(self, method, hf_or_mp, block_orders=None, intermediates=None, | |
HF reference or MP ground state | ||
block_orders : optional | ||
The order of perturbation theory to employ for each matrix block. | ||
If not set, defaults according to the selected ADC method are chosen. | ||
If not set, defaults according to the selected ADC method are | ||
chosen. | ||
intermediates : adcc.Intermediates or NoneType | ||
Allows to pass intermediates to re-use to this class. | ||
diagonal_precomputed: adcc.AmplitudeVector | ||
|
@@ -123,6 +137,12 @@ def __init__(self, method, hf_or_mp, block_orders=None, intermediates=None, | |
|
||
self.timer = Timer() | ||
self.method = method | ||
if "ip" in method.name: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think this should be handled within the |
||
self.type = "ip" | ||
elif "ea" in method.name: | ||
self.type = "ea" | ||
else: | ||
self.type = "pp" | ||
self.ground_state = hf_or_mp | ||
self.reference_state = hf_or_mp.reference_state | ||
self.mospaces = hf_or_mp.reference_state.mospaces | ||
|
@@ -143,27 +163,35 @@ def __init__(self, method, hf_or_mp, block_orders=None, intermediates=None, | |
block_orders = tmp_orders | ||
|
||
# Sanity checks on block_orders | ||
valid_blocks = {"pp": ("ph_ph", "ph_pphh", "pphh_ph", "pphh_pphh"), | ||
"ip": ("h_h", "h_phh", "phh_h", "phh_phh"), | ||
"ea": ("p_p", "p_pph", "pph_p", "pph_pph")} | ||
for block in block_orders.keys(): | ||
if block not in ("ph_ph", "ph_pphh", "pphh_ph", "pphh_pphh"): | ||
if block not in valid_blocks[self.type]: | ||
raise ValueError(f"Invalid block order key: {block}") | ||
if block_orders["ph_pphh"] != block_orders["pphh_ph"]: | ||
raise ValueError("ph_pphh and pphh_ph should always have " | ||
"the same order") | ||
if block_orders["ph_pphh"] is not None \ | ||
and block_orders["pphh_pphh"] is None: | ||
raise ValueError("pphh_pphh cannot be None if ph_pphh isn't.") | ||
if (block_orders[valid_blocks[self.type][1]] | ||
!= block_orders[valid_blocks[self.type][2]]): | ||
raise ValueError(f"{valid_blocks[self.type][1]} and " | ||
f"{valid_blocks[self.type][2]} should always " | ||
"have the same order") | ||
if block_orders[valid_blocks[self.type][1]] is not None \ | ||
and block_orders[valid_blocks[self.type][3]] is None: | ||
raise ValueError(f"{valid_blocks[self.type][3]} cannot be None if " | ||
f"{valid_blocks[self.type][1]} isn't.") | ||
self.block_orders = block_orders | ||
|
||
# Build the blocks and diagonals | ||
with self.timer.record("build"): | ||
variant = None | ||
if self.is_core_valence_separated: | ||
variant = "cvs" | ||
matrix = {"pp": ppmatrix, "ip": ipmatrix, "ea": eamatrix} | ||
blocks = { | ||
block: ppmatrix.block(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 | ||
block: matrix[self.type].block( | ||
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 | ||
} | ||
# TODO Rename to self.block in 0.16.0 | ||
self.blocks_ph = {bl: blocks[bl].apply for bl in blocks} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,10 +24,13 @@ | |
|
||
def get_valid_methods(): | ||
valid_prefixes = ["cvs"] | ||
valid_bases = ["adc0", "adc1", "adc2", "adc2x", "adc3"] | ||
valid_bases = ["adc0", "adc1", "adc2", "adc2x", "adc3", | ||
"ip_adc0", "ip_adc1", "ip_adc2", "ip_adc2x", "ip_adc3", | ||
"ea_adc0", "ea_adc1", "ea_adc2", "ea_adc2x", "ea_adc3"] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Intuitively I would expect |
||
|
||
# CVS-IP calculations not yet implemented | ||
ret = valid_bases + [p + "-" + m for p in valid_prefixes | ||
for m in valid_bases] | ||
for m in valid_bases[:5]] | ||
return ret | ||
|
||
|
||
|
@@ -37,15 +40,15 @@ class AdcMethod: | |
def __init__(self, method): | ||
if method not in self.available_methods: | ||
raise ValueError("Invalid method " + str(method) + ". Only " | ||
+ ",".join(self.available_methods) + " are known.") | ||
+ ",".join(self.available_methods) | ||
+ " are known.") | ||
|
||
split = method.split("-") | ||
self.__base_method = split[-1] | ||
split = split[:-1] | ||
self.__base_method = split.pop() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think |
||
self.is_core_valence_separated = "cvs" in split | ||
|
||
try: | ||
if self.__base_method == "adc2x": | ||
if self.__base_method in ["adc2x", "ip_adc2x", "ea_adc2x"]: | ||
self.level = 2 | ||
else: | ||
self.level = int(self.__base_method[-1]) | ||
|
@@ -57,10 +60,13 @@ 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) | ||
""" | ||
if self.is_core_valence_separated: | ||
return AdcMethod("cvs-adc" + str(newlevel)) | ||
else: | ||
return AdcMethod("adc" + str(newlevel)) | ||
try: | ||
int(self.name[-1]) | ||
except ValueError: | ||
raise NotImplementedError("This method is not implemented for ADC " | ||
"methods that do not end with a number " | ||
"like 'adc2x'.") | ||
return AdcMethod(self.name[:-1] + str(newlevel)) | ||
|
||
@property | ||
def name(self): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See my comment in
AdcMethod.py
. I think we should consistently useip-adcn
andea-adcn
internally.