I've time to blog while I am waiting for the Python wrappers to compile (they are pretty much all recompiling from scratch, so it will be a while!). Over the last few days I've been writing an 'Ensemble' class that allows me to describe the ensemble sampled by a move, or a group of moves. This became necessary as it was getting difficult to ensure that the right replica exchange test was being used for the different combinations of moves of the different replicas. Now, each move, and group of moves, returns the ensemble it samples, and now the replica exchange test can create the test based on what is the same and what is different between ensembles.
e.g. a rigid body MC move samples from the NVT ensemble. So, in the constructor of RigidBodyMC, there is the line;
RigidBodyMC::RigidBodyMC() : MonteCarlo()
{
MonteCarlo::setEnsemble( Ensemble::NVT( 25*celsius ) );
}
Similarly, when I finally get around to writing a volume move then it's constructor will look something like this;
VolumeMove::VolumeMove() : MonteCarlo()
{
MonteCarlo::setEnsemble( Ensemble::NPT( 25*celsius, 1*atmosphere ) );
}
So far so straightforward. Now the clever bit is that the Ensemble objects can be merged together. This is necessary as while a RigidBodyMC move samples the NVT ensemble, if it is used in combination with VolumeMove, then the combination of the two samples from the NPT ensemble. This is achieved via the "Ensemble::merge" function, that will combine together any of the ensembles to find the greatest common denominator (the superensemble that encapsulates both). This even catches weird things, such as trying to merge two NVT simulations that sample at different temperatures (thus forming an NV? ensemble - temperature or energy aren't constant, so the code realises that something is weird, and so exceptions will be thrown if this combination of moves is used to sample a replica).
On a different topic, I've been working through the metaprogramming book I got yesterday. It is very good, and I am learning a lot. I can see now that while I got the basics of SireUnits right (the metaprogramming to perform compile time dimensional analysis type checking for the units), I didn't do it a cleanly and safely as I could. Once I've finished the book (and have some spare time) I'll refactor SireUnits to update it with what I have learned. SireUnits is a little more complicated though than the book example, as all of the units and type checking are also exposed to Python (which has to do runtime checking). This works, as while Python does runtime checking, so can generate an infinite number of different units (compared to the finite number of compiled-in units generated by the compiler when it instantiates the templates), compatibility is maintained as the interface between Python and C++ are C++ function signatures, the template class units of which are of course fully instantiated.
Speaking of Python - it looks like the wrappers have finished compiling. Just a few small errors to fix, by the looks of it, and then it is time for bed.