Skip to content

Round partial charges to enforce correct integral charge on molecule #456

@j-wags

Description

@j-wags

Is your feature request related to a problem? Please describe.

  • Some partial charge assignment methods only report three or four decimal places of precision
  • Some System/Topology file formats only store three or four decimals of precision

Both of these issues can lead to rounding errors that become significant in larger molecules.

Describe the solution you'd like
ParmEd implemented this approach, which rounds existing charges to the desired precision, and then adds the sum of the rounding errors to the first particle to achieve the correct net charge on each residue. This may be tricky for OFFTK, since it has no concept of "Residues", thus a large biopolymer could require a substantial correction, which should not be dumped on a first atom (for example, if 1000 residues each contributed 0.001e of rounding error, then the first atom might end up getting +1 added to its charge).

It seems likely that we could apply the same solution, but just with a slightly more complex algorithm to spread out the final charge correction over several atoms. It's not clear to me that this is a question with an "automagic" solution -- pathological cases could lead us to introducing errors with this functionality (for example, accumulating a large error given a biopolymer, or adding a dipole to a symmetric system).

We'd want to figure out how this would interface with our current functionality. Basically, we should allow

  • Users disabling the rounding altogether
  • Users rounding to a custom precision
  • Users applying this rounding only to certain molecules

Further, we should figure out where this would live in our current API. Some possibilities include

  • kwarg to create_openmm_system: do_not_round_charges=[molecules] or custom_charge_rounding={molecule:precision}
  • Tag-level element in the ForceField itself -- likely in ElectrostaticsHandler (but this prevents us from handling different molecules individually). So, for example, <Electrostatics version="0.3" method="PME" scale12="0.0" scale13="0.0" scale14="0.833333" cutoff="9.0 * angstrom" rounding_precision="4"/>
  • In our eventual OFF System class, which would know which simulation format it is exporting to, and thus which precision to use.

I'm most in favor of the first and third options, since the second would require a change to the SMIRNOFF spec and disallow treating molecules differently. The first option is the only one that is immediately available.

Additional context
In the LibraryCharges PR that was already merged (#433), we added a check that the sum of a molecule's partial charges must be within 0.01 of the molecule's formal charge. This can be overridden by a kwarg (allow_nonintegral_charges=True).

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions