Design of the OperatorBase Class
These are just some notes of things I thought about when I wrote the class. They should be formalized at a later point.
Architecture called for templating on particle type, i.e.,
OperatorBase<T...>
.Problem for Python exposure unless we expose each separately.
Would have
T...
values of:Electron
,ManyElectron
,Nucleus
,Nuclei
,Density<Electron>
,ChargeSet
, and pairs of these. That’s already 42 possible types (assuming we don’t ever need other densities, triples of particles, or more exotic particles like muons).Internally rely on
std::vector<std::variant>
?
Provide a class
OperatorImpl<T...>
for factoring out the common template pieces.OperatorImpl<T...>
derives formOperatorBase
. APIs should not rely onOperatorImpl<T...>
, rather they should rely onOperatorBase
or the class that derives fromOperatorImpl<T...>
.Can’t be in namespace
operator
(C++ keyword), so we opted forqm_operator
.Use visitor pattern to implement generic algorithms. Algorithms specific to an operator type should go through the derived class.
Visitor Pattern Notes
For background see here.
We assume that OperatorBase
defines an API like:
class OperatorBase {
public:
virtual void visit(OperatorVisitor& visitor) const = 0;
};
and each operator overloads it like:
template<typename T>
class Kinetic : public OperatorBase {
public:
void visit(OperatorVisitor& visitor) const override {
visitor.run(*this);
}
};
The visitor will then be called with the derived class. This requires the
visitor to define an overload for each operator it might get. The easiest
solution is to brute force enumerate the possible overloads in
OperatorVisitor
, implementing them all so that they error. Derived classes
can then override the ones they want to handle.