What is means for a particle to be inactive is not well defined at
this point. My proposal would be that we define them to be permanently
dead-- particles are made inactive by removing them from the Model.
When restraints encounter inactive particles, they should either:
- if they act on bulk sets of particles, just remove the inactive
particle from their list and go on. This would apply to the nonbonded
list and list-based restraints
- if they act on a constant number of particles, the
InactiveParticleException should propagate. The thing holding the
restraint can use the exception to destroy the restraint (maybe) or,
probably better, just to kill the optimization.
The iterators provided by the model would skip inactive particles (and
reference counting would ensure that the memory is reclaimed when
everything is cleaned up), thereby allowing the optimizers to work
when there are inactive particles.
Using this, you could, for example, maintain a dynamic set of
particles by adding all new particles to the nonbonded list and know
that all inactive particles will get cleaned up properly.
In order to make sure the reference counting works, Particles would
get a new attribute type which is a pointer to another particle. Bonds
and hierarchies would use this new attribute type.
Note that swig reference counting is pretty much useless, so there is
no trivial way to ensure that all references held in python keep the
respective bit of memory alive. Namely, if you get a particle back
from the model or a restraint, this python object will not keep the
corresponding C++ object alive. There are solutions to this problem,
but I don't want to implement them now as they are a bit complicated.
For now, the best solution might be to have the python wrapper print
warnings when the dangerous functions are used.