@@ -36,14 +36,23 @@ class ChargeTransferModification(BaseModification):
3636 post_dependencies : List [str ] = []
3737
3838 @staticmethod
39- def get_is_donor_acceptor (topology : _Topology ) -> tuple [list [int ], list [int ]]:
39+ def get_is_donor_acceptor (
40+ topology : _Topology , alchemical_atoms : List [int ], symmetric : bool = False
41+ ) -> tuple [list [int ], list [int ]]:
4042 """
4143 Generate per-atom flags for donors and acceptors.
4244
4345 Parameters
4446 ----------
4547 topology : openff.toolkit.topology.Topology
4648
49+ alchemical_atoms : list of int
50+ List of indices of alchemical atoms.
51+
52+ symmetric : bool, optional
53+ If True, CT will be applied symmetrically between alchemical and MM atoms.
54+ Otherwise, only from MM to alchemical atoms. Default is False.
55+
4756 Returns
4857 -------
4958 is_donor : list[int]
@@ -57,13 +66,13 @@ def get_is_donor_acceptor(topology: _Topology) -> tuple[list[int], list[int]]:
5766
5867 for idx , atom in enumerate (topology .atoms ):
5968 # Donor: hydrogen bonded to N/O/S
60- if atom .atomic_number == 1 :
69+ if atom .atomic_number == 1 and ( symmetric or idx in alchemical_atoms ) :
6170 for bonded_atom in atom .bonded_atoms :
6271 if bonded_atom .atomic_number in [7 , 8 , 16 ]:
6372 is_donor [idx ] = 1
6473 break
6574 # Acceptor: heavy atoms
66- elif atom .atomic_number == 8 :
75+ elif atom .atomic_number == 8 and ( symmetric or idx not in alchemical_atoms ) :
6776 num_H = sum (b .atomic_number == 1 for b in atom .bonded_atoms )
6877 is_acceptor [idx ] = 1
6978 elif atom .atomic_number == 7 :
@@ -138,7 +147,9 @@ def apply(
138147 energy_function = f"-{ lambda_value } *donor_acceptor*epsilon*exp(-sigma*r);"
139148 energy_function += "sigma = 0.5*(sigma1+sigma2);"
140149 energy_function += "epsilon = sqrt(epsilon1*epsilon2);"
141- energy_function += "donor_acceptor = isDonor1*isAcceptor2;"
150+ energy_function += (
151+ "donor_acceptor = isDonor1*isAcceptor2 + isDonor2*isAcceptor1;"
152+ )
142153
143154 logger .debug (f"Charge transfer function: { energy_function } " )
144155
@@ -165,7 +176,7 @@ def apply(
165176
166177 # Get donor/acceptor flags
167178 is_donor , is_acceptor = ChargeTransferModification .get_is_donor_acceptor (
168- topology_off
179+ topology_off , alchemical_atoms
169180 )
170181
171182 for index in range (system .getNumParticles ()):
0 commit comments