Improve MDLogger Design and Flexiblity
Improve MDLogger Design and Flexibility
Current State
The MDLogger currently handles basic MD quantities (time, energies, temperature) in a fixed format. Logging additional quantities requires modifying the MD classes themselves, as demonstrated by the recent need to log conserved energy in the Bussi thermostat implementation.
Previous Attempt (PR !3498 (closed))
Initially proposed adding an extra_fields attribute to Dynamics classes, allowing them to pass additional quantities to the logger. While this solved the immediate need for Bussi thermostat, discussions with @yuzie007 highlighted that this approach still tightly couples logging concerns with dynamics implementation.
Proposed Solution
After discussion, a better approach emerged:
-
Have the
MDLoggerrely entirely on a new attributefields, which contain names, callable and format of tracked quantities. A new methodadd_fieldscan be used to fully customize loggers.logger = MDLogger("md.log", mode="w") logger.add_fields("Econs[eV]", lambda: atoms.get_total_energy() - dyn.transferred_energy) -
As a result,
MDLoggerdoes not takedynoratomsdirectly as parameter anymore. A convenience method is addedadd_md_fieldsto add the standard MD quantities, this is directly called in the__init__ofMolecularDynamics. -
Move the header writing part outside of the
__init__, ideally somewhere related to the start of theDynamics, avoiding rewrite on restart. ConsequentlyMDLoggershould implement a methodwrite_header. -
At that point,
MDLoggercould be nicely deprecated and link to a new classLogger, ideally moved somewhere else, so that any kind of simulations could use it (optimizers, neb, etc...)
This leads to key improvements:
- Separate logging from dynamics implementation.
- Allow field addition to track any quantities.
- Let users customize logging without subclassing anything.
Please find an experimental (working) implementation of the above in this branch
Assuming correct link and depreciation notes breaking changes can be greatly limited. The only remaining would be for expert users who create MDLogger and attach it manually.
Example usage in the new framework:
# When using the `logfile` parameter, nothing changes
dyn = Bussi(
atoms,
...,
logfile="dyn.log"
)
# If attaching manually, the Logger has to be initialized to obtain the desired behavior
from ase.logger import Logger
dyn = Bussi(atoms, ...)
logger = Logger("dyn.log")
logger.add_md_fields(dyn)
dyn.attach(logger)
logger.add_fields("Econs[eV]", lambda: dyn.atoms.get_total_energy() - dyn.transferred_energy, "10.3f")
logger.write_header()
dyn.run(20)
Related Links
- !3498 (closed) Initial attempt to revamp MDLogger with relevant discussions.
- #1344 Optimizer logging initial consideration
- #1439 MD restart functionality discussion (relevant for header writing)