> Calling State::update() in Model::evaluate() would not be > sufficient, at least for nonbonded lists, because you can also call > Restraint::evaluate() on individual restraints from the Python > interface. Sure, but I don't think there is any reason to guarantee that randomly calling evaluate on restraints gives you anything meaningful unless you are careful to update everything the restraint needs yourself. The Model is there to do this. We could put in a hook so that someone can request the Model update everything.
> How would a nonbonded list know that it needs to do an update? > I don't like the Statistics class proposed in ModelData.h. (The > idea of that class is to automatically keep min/max/change > statistics on all float variables.) Why: because 1. if you don't > want nonbonded lists, maintaining these statistics is inefficient, > and 2. because it's part of the ModelData class, it can't easily be > extended by other classes. Agreed.
> Two suggestions: > 1. Classes can register callbacks/actions with > ModelData::set_float, or this could trigger a State::set_float > method, to be notified whenever the model is changed. The main problem is that given "the float at index 10 is being set to 13.5", you have to lookup somewhat what is at index 10 and whether you care about it. Doing this every time anything is changed, for each of several State objects seems likely to be slow.
> The advantage of the former is that the callback can go away after > a nonbond update is triggered, saving the overhead of a function > call for subsequent set_float()s. How can it go away? You still have to keep track for the next update, no?
> 2. Classes to allow the get/set of the 'optimizable state' (right > now, this is just all optimizable floats) could have similar > methods, useful for optimizers such as CG and steepest descent > which change all attributes simultaneously.
I think in the normal course of things, if anything updates, lots of things update, so it probably more efficient to have State objects go search for changes they care about than notify them of every little change. However, this would require the non-bonded list to keep a copy of the original coordinates to determine how far things moved.
My suggestion: Keep State as it is, with the exception that ModelData has a dirty bit controlled by Model which Model uses to check if the States should be updated.
Add a FloatDataMonitor class which is called when floats change in the ModelData (we can add String and Int ones later).
We can have a FloatStatistic monitor which keeps statistics for a list of fields. The non-bonded list (a State) can use it to keep track of how far things move and delay update until needed.
Separating the two types (State and *DataMonitor) means we won't have too many things happening on each change in the ModelData and ones which want to do things as a batch don't have to slow down ModelData changes.