-
Notifications
You must be signed in to change notification settings - Fork 28
IP/EA ADC(0-3) implementation without properties #206
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
base: master
Are you sure you want to change the base?
Changes from all commits
bdfd2f5
176d9c9
46b160b
bf9004d
be15aa1
65bbd06
db45a07
5828728
a0ac600
4646a87
62684e9
ce7de9d
76aa6a1
40c0d34
3725db9
2abd7b9
c08e25e
789a1a4
13e8582
b5ec713
5460d7a
1d3830d
5deaeda
5d7d861
90b9814
5f783a4
22a664e
92f3af0
165181a
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 | ||||||
|---|---|---|---|---|---|---|---|---|
|
|
@@ -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, Method, AdcType | ||||||||
| from .functions import ones_like | ||||||||
|
|
@@ -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}, | ||||||||
| "isr1s": {"ph_ph": 1, "ph_pphh": None, "pphh_ph": None, "pphh_pphh": None}, | ||||||||
| "isr2d": {"ph_ph": 2, "ph_pphh": 1, "pphh_ph": 1, "pphh_pphh": 0}, | ||||||||
| } | ||||||||
|
|
@@ -104,7 +108,9 @@ def _default_block_orders(cls, method: Method, | |||||||
| # - determine which spaces are available in the ADC(n) matrix | ||||||||
| # starting from the given minimal space | ||||||||
| min_space = { | ||||||||
| AdcType.PP: "ph" | ||||||||
| AdcType.PP: "ph", | ||||||||
| AdcType.IP: "h", | ||||||||
| AdcType.EA: "p", | ||||||||
| }.get(method.adc_type, None) | ||||||||
| if min_space is None: | ||||||||
| raise ValueError(f"Unknown adc type {method.adc_type.to_str()} for " | ||||||||
|
|
@@ -196,6 +202,10 @@ def _is_valid_space(cls, space: str, method: Method) -> bool: | |||||||
| # be equal or differ e.g. by +-1 (IP/EA) | ||||||||
| if method.adc_type is AdcType.PP: | ||||||||
| return n_particle == n_hole | ||||||||
| elif method.adc_type is AdcType.IP: | ||||||||
| return n_particle == n_hole - 1 | ||||||||
| elif method.adc_type is AdcType.EA: | ||||||||
| return n_particle == n_hole + 1 | ||||||||
| raise ValueError(f"Unknown adc type {method.adc_type.to_str()} for method " | ||||||||
| f"{method.name}. Can not validate space.") | ||||||||
|
|
||||||||
|
|
@@ -268,11 +278,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 = { | ||||||||
| AdcType.PP: ppmatrix.block, | ||||||||
| AdcType.IP: ipmatrix.block, | ||||||||
| AdcType.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, | ||||||||
| variant=variant) | ||||||||
| for block, order in self.block_orders.items() if order is not None | ||||||||
| 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 | ||||||||
| } | ||||||||
| self.blocks = {bl: blocks[bl].apply for bl in blocks} | ||||||||
| if diagonal_precomputed: | ||||||||
|
|
@@ -442,33 +460,57 @@ 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) | ||||||||
| # doubles part is antisymmetric wrt. (i,j,a,b) <-> (j,i,a,b) | ||||||||
| scratch = invec.antisymmetrise([(0, 1)]).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 | ||||||||
|
|
||||||||
| def symmetrise_generic_adc_triples(invec): | ||||||||
| # triples part is antisymmetric wrt. permutations of (i,j,k) | ||||||||
| # and wrt. permutations of (a,b,c) | ||||||||
| scratch = ( | ||||||||
| invec.antisymmetrise([(0, 1, 2)]).antisymmetrise([(3, 4, 5)]) | ||||||||
| ) | ||||||||
| # triples part is symmetric wrt. permutations of (i,j,k) and | ||||||||
| # permutations of (a,b,c) | ||||||||
| # NOTE: The doubles fix the (numerical) symmetry with a single | ||||||||
| # symmetrise call. This is not possible for triples, since the | ||||||||
| # following symmetrise call only covers 6 of the 18 | ||||||||
| # even permutations generated by the 2 antisymmetrise calls above: | ||||||||
| # ijkabc + ikjacb + jikbac + jkibca + kijcab + kjicba | ||||||||
| return scratch.symmetrise([(0, 1, 2), (3, 4, 5)]) | ||||||||
| ret["ppphhh"] = symmetrise_generic_adc_triples | ||||||||
| if self.method.adc_type is AdcType.PP: | ||||||||
|
Contributor
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. Please split the method into specific PP/IP/EA methods.
Suggested change
|
||||||||
| 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) | ||||||||
| # doubles part is antisymmetric wrt. (i,j,a,b) <-> (j,i,a,b) | ||||||||
| scratch = invec.antisymmetrise([(0, 1)]).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 | ||||||||
|
|
||||||||
| def symmetrise_generic_adc_triples(invec): | ||||||||
| # triples part is antisymmetric wrt. permutations of (i,j,k) | ||||||||
| # and wrt. permutations of (a,b,c) | ||||||||
| scratch = ( | ||||||||
| invec.antisymmetrise([(0, 1, 2)]).antisymmetrise( | ||||||||
| [(3, 4, 5)]) | ||||||||
| ) | ||||||||
| # triples part is symmetric wrt. permutations of (i,j,k) and | ||||||||
| # permutations of (a,b,c) | ||||||||
| # NOTE: The doubles fix the (numerical) symmetry with a single | ||||||||
| # symmetrise call. This is not possible for triples, since the | ||||||||
| # following symmetrise call only covers 6 of the 18 | ||||||||
| # even permutations generated by the 2 antisymmetrise calls | ||||||||
| # above: | ||||||||
| # ijkabc + ikjacb + jikbac + jkibca + kijcab + kjicba | ||||||||
| return scratch.symmetrise([(0, 1, 2), (3, 4, 5)]) | ||||||||
| ret["ppphhh"] = symmetrise_generic_adc_triples | ||||||||
| elif self.method.adc_type is AdcType.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 | ||||||||
|
|
||||||||
| def symmetrise_generic_adc_triples(invec): | ||||||||
| # TODO | ||||||||
| pass | ||||||||
|
Comment on lines
+501
to
+503
Contributor
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. Please remove the IP/EA triples functions, since they are not needed yet |
||||||||
| elif self.method.adc_type is AdcType.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 | ||||||||
|
|
||||||||
| def symmetrise_generic_adc_triples(invec): | ||||||||
| # TODO | ||||||||
| pass | ||||||||
| return ret | ||||||||
|
|
||||||||
| def dense_basis(self, axis_blocks=None, ordering="adcc"): | ||||||||
|
|
||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -70,6 +70,8 @@ def to_int(self) -> int: | |
|
|
||
| class AdcType(Enum): | ||
| PP = "pp" | ||
| IP = "ip" | ||
| EA = "ea" | ||
|
|
||
| def to_str(self) -> str: | ||
| return self.value | ||
|
|
@@ -253,7 +255,7 @@ def at_level(self: T, newlevel: Union[int, str]) -> T: | |
|
|
||
| def as_method(self, method_cls: type[T]) -> T: | ||
| """ | ||
| Return a equivalent Method with the method base name replaced | ||
| Return an equivalent Method with the method base name replaced | ||
| by the provided name. | ||
| """ | ||
| assert self._method_base_name is not None | ||
|
|
@@ -294,7 +296,23 @@ class AdcMethod(Method): | |
| ): LevelSpec( | ||
| max_level=3, | ||
| special_levels=(MethodLevel.TWO_X,) | ||
| ) | ||
| ), | ||
| LevelKey( | ||
| adc_type=AdcType.IP, | ||
| gs_type=GroundStateType.MP, | ||
| cvs=False | ||
| ): LevelSpec( | ||
| max_level=3, | ||
| special_levels=(MethodLevel.TWO_X,) | ||
| ), | ||
| LevelKey( | ||
| adc_type=AdcType.EA, | ||
| gs_type=GroundStateType.MP, | ||
| cvs=False | ||
| ): LevelSpec( | ||
| max_level=3, | ||
| special_levels=(MethodLevel.TWO_X,) | ||
| ), | ||
| } | ||
|
|
||
|
|
||
|
|
@@ -316,5 +334,21 @@ class IsrMethod(Method): | |
| ): LevelSpec( | ||
| max_level=2, | ||
| special_levels=(MethodLevel.ONE_S, MethodLevel.TWO_D) | ||
| ), | ||
| LevelKey( | ||
| adc_type=AdcType.IP, | ||
| gs_type=GroundStateType.MP, | ||
| cvs=False | ||
| ): LevelSpec( | ||
| max_level=2, | ||
| special_levels=None | ||
| ), | ||
| LevelKey( | ||
| adc_type=AdcType.EA, | ||
| gs_type=GroundStateType.MP, | ||
| cvs=False | ||
| ): LevelSpec( | ||
| max_level=2, | ||
| special_levels=None | ||
|
Comment on lines
+338
to
+352
Contributor
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. Strictly this should only be added as part of the second IP/EA property PR, right? However, in order to omit these changes you would need to temporarily set Also special levels is defined as |
||
| ) | ||
| } | ||
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.