Task #3418: Infrastructure improvements for modular simulator
Use builders to prepare modules
The current setup of modular simulator is more complicated as necessary, as it mixes constructing the elements, satisfying their mutual connections (registering clients to signallers and functionality providers), and their arrangement (which defines the exact integration algorithm being used).
The approach would become significantly easier to understand, maintain and extend if the responsibility of preparing the elements would be delegated to builder object. This would encapsulate the implementation details of construction and inter-connection of elements, helping to more clearly expose the arrangement of modules.
Modular simulator: Separate trajectory element and signaller
The trajectory element implemented both the ISimulatorElement and
the ISignaller interface. It was both signalling its clients that a
trajectory writing step was about to occur during task list creation,
and actually performing trajectory writing during the simulation.
In general, the tasks of signallers and elements, their call site in
the code, and their build and ownership procedures are all significantly
different. The dual nature of the trajectory element makes this
differentiation less clear, and requires some workarounds. Additionally,
separating the trajectory element in separate element and a signaller
requires no changes on client side, since all clients of the trajectory
element with integrated signaller already implemented two interfaces,
ITrajectorySignallerClient and ITrajectoryWriterClient.
The current change hence splits the current trajectory element into
a pure element and a pure signaller. This will make subsequent changes,
especially the introduction of a builder approach much easier. It also
removes support for combined elements and signallers: It renames the setup
method of the ISignaller interface from `signallerSetup` to `setup`, as
this differentiation was only used for classes implementing both element
and signaller interfaces. It also simplifies the handling of signallers
in ModularSimulator, as having a separate ownership and call list is not
Separate ModularSimulator and ModularSimulatorAlgorithm
This introduces the ModularSimulatorAlgorithm, which takes over some
responsibilities from ModularSimulator. The ModularSimulatorAlgorithm
owns the elements, and allows ModularSimulator to run a simulation
following the prescribed algorithm. This change is only refactoring -
no functionality is added or removed, but separating the algorithm and
its builder from the simulator allows to develop the two independently.
The ModularSimulatorAlgorithm is built by ModularSimulatorAlgorithmBuilder.
In a first approach, ModularSimulatorAlgorithmBuilder creates an appropriate
algorithm based on the input passed from the runner level (md or md-vv, thermo-
and / or barostat, constraining, FEP, etc).
Eventually, the builder will not need to know about all possible algorithms,
but offer an interface for its user to creat algorithms. Currently, the only
planned user of the ModularSimulatorAlgorithm is the ModularSimulator itself.
In view of this, two "hacks" were used to reduce unnecessary line changes
to simplify review: The builder mirrors all protected members of ISimulator,
and some of its member function implementations were left in modularsimulator.cpp.
Note that both of these "hacks" will disappear in subsequent changes.