The Matlab Version and its Shortcomings
The current stable WavePacket version is written in a relatively traditional, procedural way where the user sets some variables, lets the program run, and by manipulating internal variables in a suitable way, can tweak the program to calculate specific output required for the problem at hand. On the whole, this works fine, is stable etc.
However, over the years, the code has become rather rigid, which is related to the development history (the code is now approximately 7 years old) and also caused by the procedural coding style. As a consequence, there are a couple of things that are easy to write down on paper, but difficult to implement in the Matlab version. An example is the propagation of a density operator. Except for hardware constraints, propagating a density operator in Liouville space is essentially the same as propagating a wavepacket in the normal Hilbert space; however implementing it in the Matlab version would require smashing the grid setup that half of the code depends on. In a similar vein, it is not easy to propagate a system with a classical Hamiltonian, although the maths (grid-basis expansion and applying an operator to the state in phase space) are very similar.
Another problem was that the code was rather difficult to customize. As soon as you do some advanced scripting, say, doing optimal control theory, you need to know the guts of the program (internal data structures, dependencies between modules etc.).
Objective of the C++ Version
The goal of the C++ version is on one hand to update the code base and fix the dead ends of the previous incarnation. On the other hand, we want to avoid some problems of the Matlab version altogether. The goals of the rewrite are as follows:
- The code should be easy to use. It should be easy to set up and run a calculation by writing a simple program (run script). If written properly, you should be able to read a run script like a book (as opposed to setting some global variables). Nasty details should be encapsulated, so that a normal user never needs to deal with them.
- It should be easy to do complex things. If you want to do something that is not trivial, such as optimal control, or propagating a density operator in an open system and comparing to the wave function propagation in the closed system, this should be straight-forward to do. You should not need to know too much about internal data structures, and it should be possible to write your run script as a direct representation of the formulas that you want to implement.
- Extendable Code. Where possible and reasonable, Wavepacket should be written in such a way that it can be rather easily extended later if we find a use case that we have not considered initially (semiclassical methods anyone?).
- Tested Code. All components (operators, grids, propagators etc.) should have automatic tests attached so that you can reasonably expect them to be bug-free. I have come to loathe the case where your complex program outputs garbage because of some trivial bug deep inside the code.
- Lean, readable Code The code should have a high quality; no difficult execution pathways or hacks, good documentation and comments etc.
To accomodate this wishlist, it seems natural to require a couple of features from the code:
- Object-orientation. Every thing that you need in a program is an object, be it a grid, or an operator, or a wave function, or a propagator. These objects (or rather, their classes) have simple and sane public interfaces, and unless you try hard, you cannot and should not know what is inside, only how to use them.
- Wavepacket is a library. In contrast to the Matlab version, the C++ version only provides the various tools needed for the solution of the Schroedinger equation. Your task as user is to create the appropriate objects, and put them together in such a way that they solve your problem. This is done by writing a program that is linked against the library.
- Agile techniques. The basic idea of an agile development is to start writing a simple program (or here: toolset), and then handle more and more complex use-cases in the simplest possible way. This forces you to always keep the code extendable, and discourages complicated code.
- Test-driven development. A special agile technique, TDD requires you to write tests together with the code. It might not be immediately obvious, but to keep the tests reasonably simple to write, you are automatically forced to separate your code into clean modules (classes) that are easy to put together.