Skip to content

Combining SMIRNOFF interchanges with isomorphic molecules with different charges uses only the charges from the latter molecule #1075

@Yoshanuikabundi

Description

@Yoshanuikabundi

Description

I was looking to see if @IAlibay's desired workflow in #1059 could be accomplished by creating two separate interchanges and then combining them to get a single interchange with different charges for isomorphic molecules, and it does not. I think this is surprising - in my head, an interchange associates each atom in the topology with its own parameters, and the fact that parameters are deduplicated is like an optimization. I've already unambiguously identified which atoms should have which charges, and so to lose that information for that optimization is surprising.

Reproduction

Modified version of Irfan's code:

from openff.toolkit import Molecule, Topology, ForceField
from openff.interchange.components._packmol import solvate_topology_nonwater
from openff.interchange import Interchange
from openff.units import unit
import numpy as np

solvent = Molecule.from_smiles('c1ccccc1')
solvent.assign_partial_charges(partial_charge_method='gasteiger')

ligand = Molecule.from_smiles('c1ccccc1')
ligand.generate_conformers()
ligand.assign_partial_charges(partial_charge_method='am1bcc')

print("molecules are isomorphic: ", ligand.is_isomorphic_with(solvent))

off_top = Topology.from_molecules(ligand)
solvated_off_top = solvate_topology_nonwater(topology=off_top, solvent=solvent)
solvent_off_top = Topology.from_molecules([solvated_off_top.molecule(i) for i in range(off_top.n_molecules, solvated_off_top.n_molecules)])

ff = ForceField('openff-2.2.0.offxml', 'opc.offxml')
ligand_interchange = Interchange.from_smirnoff(topology=off_top, force_field=ff, charge_from_molecules=[ligand])
inter_lig_charges = [c.m_as(unit.elementary_charge) for c in ligand_interchange.collections["Electrostatics"].charges.values()] * unit.elementary_charge

solvent_interchange = Interchange.from_smirnoff(topology=off_top, force_field=ff, charge_from_molecules=[solvent])
inter_sol_charges = [c.m_as(unit.elementary_charge) for c in solvent_interchange.collections["Electrostatics"].charges.values()] * unit.elementary_charge

inter = ligand_interchange.combine(solvent_interchange)
inter_charges = [c.m_as(unit.elementary_charge) for c in inter.collections["Electrostatics"].charges.values()] * unit.elementary_charge

print("ligand charges in ligand interchange: ", inter_lig_charges)
print("charges in solvent interchange: ", inter_sol_charges)
print("charges in combined interchange: ", inter_charges)

assert not np.isclose(inter_charges, np.append(inter_lig_charges, inter_sol_charges)).all()

Output

molecules are isomorphic:  True
ligand charges in ligand interchange:  [-0.1301600026587645 -0.1300999956826369 -0.1300999956826369 -0.1300999956826369 -0.1300999956826369 -0.1300999956826369 0.13010999684532484 0.13010999684532484 0.13010999684532484 0.13010999684532484 0.13010999684532484 0.13010999684532484] elementary_charge
charges in solvent interchange:  [-0.06175815314054489 -0.06175815314054489 -0.06175815314054489 -0.06175815314054489 -0.06175815314054489 -0.06175815314054489 0.06175815314054489 0.06175815314054489 0.06175815314054489 0.06175815314054489 0.06175815314054489 0.06175815314054489] elementary_charge
charges in combined interchange:  [-0.06175815314054489 -0.06175815314054489 -0.06175815314054489 -0.06175815314054489 -0.06175815314054489 -0.06175815314054489 0.06175815314054489 0.06175815314054489 0.06175815314054489 0.06175815314054489 0.06175815314054489 0.06175815314054489 -0.06175815314054489 -0.06175815314054489 -0.06175815314054489 -0.06175815314054489 -0.06175815314054489 -0.06175815314054489 0.06175815314054489 0.06175815314054489 0.06175815314054489 0.06175815314054489 0.06175815314054489 0.06175815314054489] elementary_charge

Software versions

Interchange v0.4.0beta2

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions