Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
55 changes: 54 additions & 1 deletion adcc/AdcMatrix.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
from .functions import ones_like
from .Intermediates import Intermediates
from .AmplitudeVector import AmplitudeVector

# from .solver.explicit_symmetrisation import IndexSymmetrisation

class AdcExtraTerm:
def __init__(self, matrix, blocks):
Expand Down Expand Up @@ -650,3 +650,56 @@ def block_view(self, block):
"projected ADC matrices.")
# TODO The way to implement this is to ask the inner matrix to
# a block_view and then wrap that in an AdcMatrixProjected.


class AdcMatrixFolded(AdcMatrix):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would move it into a separate file within the solver directory, since it’s currently quite solver-specific (for example, the unfold_solution function clearly refers to solving the eigenvalue problem handled in the solver) and specific to ADC(2). I’d also rename it to Adc2MatrixFolded.

However, we should consider how to generalize it in the future. :)

def __init__(self, matrix):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you initialize the class, you should also set an omega
def __init__(self, matrix, omega):

"""
Initialise a ADC(2) matrix when using doubles-folding.

Parameters
----------
matrix : AdcMatrix
ADC(2) matrix
"""
super().__init__(matrix.method, matrix.ground_state,
Comment thread
TianLin-228 marked this conversation as resolved.
block_orders=matrix.block_orders,
intermediates=matrix.intermediates)
if matrix.method.name != "adc2":
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As an idea for a more general approach: matrix.method.level % 2 !=0, because in general the ADC(4) matrix can also be folded.

raise TypeError("The matrix should be ADC2 Matrix for doubles-folding.")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would call it:
"Doubles folding can currently only be applied to an ADC(2) matrix."


from .solver.explicit_symmetrisation import IndexSymmetrisation
self.isymm = IndexSymmetrisation(matrix)

def diagonal(self):
"""
Return the approximate diagonal of the ADC(2) matrix with doubles-folding.
"""
return AmplitudeVector(ph=super().diagonal().ph)

def u2_fold(self, other):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please rename it so that it is a bit more meaningful:
get_doubles_component(self, in_ampl)

"""
Return the doubles component of u in terms of its singles component.
"""
diag = super().diagonal().pphh
e = diag.ones_like()
u2 = self.block_apply("pphh_ph", other.ph) / (e * self.omega - diag)
Copy link
Copy Markdown
Contributor

@frieschneider frieschneider Oct 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

to get the correct symmetry: try to explicitly symmetrise it:

u2 = (
self.block_apply("pphh_ph", other.ph) / (e * self.omega - diag)
).antisymmetrise(0, 1).antisymmetrise(2, 3).symmetrise([(0, 1), (2, 3)])

return self.isymm.symmetrise(AmplitudeVector(pphh=u2))

def matvec(self, other):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here, you can rename other to in_ampl to keep it more in line with the AdcMatrix implementation.

"""
Compute the doubles-folded matrix-vector product of the singles vector with
an effective ADC matrix which depends on the eigenvalue(omega).
"""
u2 = self.u2_fold(other)
return AmplitudeVector(ph=self.block_apply("ph_ph", other.ph)
+ self.block_apply("ph_pphh", u2.pphh))

def unfold(self, other):
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unfold_solution(self, in_ampl)

"""
Recompute the doubles component and return the complete vector.
"""
other_symm = self.isymm.symmetrise(other)
u2 = self.u2_fold(other_symm)

return AmplitudeVector(ph=other_symm.ph, pphh=u2.pphh)
Loading