Would you like ASE and python to control your calculation engine? There are several ways to do it:

Details of the calculator interface

A calculator object is connected to a ListOfAtoms like this:

 -------------  calculator                ----------
| ListOfAtoms |------------------------->|Calculator|
|             |                          |          |
|             |                    atoms |          |
|             |<- - - - - - - - - - - - -|          |
 -------------                (weak ref.) ----------

When a ListOfAtoms and a calculator are connected, the ListOfAtoms will have a reference to the calculator and the calculator will have a weak reference to the ListOfAtoms - this avoids circular references.

A Calculator should implement one or more of the following methods:

  • GetPotentialEnergy()
  • GetCartesianForces()
  • GetStress()

Example: When someone calls the GetPotentialEnergy() method of a ListOfAtoms, the ListOfAtoms will get the energy by calling the GetPotentialEnergy() method of its calculator. The same mechanism is used for forces and stresses.

When the state of a ListOfAtoms changes, its counter will be increased by one. A calculator should querry this counter in order to find out if a recalculation of the energy, forces and stresses will be required on a call to one of GetPotentialEnergy(), GetCartesianForces() or GetStress().

The calculator should ask the ListOfAtoms for what units it uses. It must deliver the energies, forces and stresses in the correct units.

The ListOfAtoms.SetCalculator(calculator) method will call the _SetListOfAtoms(mol) method of the calculator:

class ListOfAtoms(list):
    def SetCalculator(self, calculator):
        """Attach a calculator to the ListOfAtoms."""
        self.calculator = calculator
        calculator._SetListOfAtoms(self)

class Calculator:
    def _SetListOfAtoms(self, mol):
        """Make a weak reference to the ListOfAtoms."""
        self.mol = weakref.ref(mol)

Note

Calculation mode???

Note

From Jakobs email:

I see the point in calculating the dynamic part of the stress in the LOA. So a calculator has a GetStress() method, the LOA also has a GetStress() method, which calls the one in the calculator and then add the dynamic part. Or should the methods be called LOA.GetStress but calculator.GetStaticStress?

For the per-atom stress, only the calculator can do it, because only the calculator knows how the volume of the system was split up on each atom for the static part of the stress. But per-atom stress only makes sense in Asap, so perhaps it should not be part of the standard.