Source code for pyretis.inout.restart
# Copyright (c) 2026, PyRETIS Development Team.
# Distributed under the LGPLv2.1+ License. See LICENSE for more info.
"""This module defines how we write and read restart files.
Important methods defined here
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
read_restart_file (:py:func:`.read_restart_file`)
A method for reading restart information from a file.
write_restart_file (:py:func:`.write_restart_file`)
A method for writing the restart file.
write_ensemble_restart (:py:func:`.write_ensemble_restart`)
A method for writing restart files for path ensembles.
"""
import logging
import copy
import os
import pickle # nosec B403
from pyretis.inout.common import atomic_write
logger = logging.getLogger(__name__) # pylint: disable=invalid-name
logger.addHandler(logging.NullHandler())
__all__ = ['read_restart_file',
'write_restart_file',
'write_ensemble_restart',
'system_restart_info',
'load_system_restart']
[docs]def system_restart_info(system):
"""Collect restart info for a System (free-function form).
Equivalent to the soon-to-go ``System.restart_info()`` method on
the harness System. Returns the same dict shape; works on any
System with the bridge surface (``units``, ``temperature``,
``post_setup``, ``order``, ``box``, ``particles``).
Parameters
----------
system : object like :class:`.System`
The system whose state to serialise.
Returns
-------
dict
Restart-info dictionary.
"""
info = {}
for attr in ('units', 'temperature', 'post_setup', 'order'):
info[attr] = getattr(system, attr, None)
try:
info['box'] = system.box.restart_info()
except AttributeError:
pass
try:
info['particles'] = system.particles.restart_info()
except AttributeError:
pass
return info
[docs]def load_system_restart(system, info):
"""Restore System state from a restart-info dict.
Equivalent to the soon-to-go ``System.load_restart_info(info)``
method on the harness System.
Parameters
----------
system : object like :class:`.System`
The system to populate.
info : dict
The restart info, as produced by :func:`system_restart_info`.
"""
# Local imports to avoid pulling restart-only dependencies at
# module import time.
from pyretis.core.box import box_from_restart
from pyretis.core.particles import particles_from_restart
for attr in ('units', 'temperature', 'post_setup', 'order'):
if attr in info:
setattr(system, attr, info[attr])
system.box = box_from_restart(info)
system.particles = particles_from_restart(info)
[docs]def write_restart_file(filename, simulation):
"""Write restart info for a simulation.
Parameters
----------
filename : string
The file we are going to write to.
simulation : object like :py:class:`.Simulation`
A simulation object we will get information from.
"""
info = simulation.restart_info()
# Write atomically: the file is swapped into place with os.replace,
# so an abrupt interruption can never leave a half-written restart
# (it is always either the complete old or the complete new file).
atomic_write(
filename,
lambda outfile: pickle.dump(info, outfile),
binary=True,
)
[docs]def write_ensemble_restart(ensemble, settings_ens):
"""Write a restart file for a path ensemble.
Parameters
----------
ensemble : dict
it contains:
* `path_ensemble` : object like :py:class:`.PathEnsemble`
The path ensemble we are writing restart info for.
* ` system` : object like :py:class:`.System`
System is used here since we need access to the temperature
and to the particle list.
* `order_function` : object like :py:class:`.OrderParameter`
The class used for calculating the order parameter(s).
* `engine` : object like :py:class:`.EngineBase`
The engine to use for propagating a path.
settings_ens : dict
A dictionary with the ensemble settings.
"""
info = copy.deepcopy(settings_ens)
if ensemble.get('path_ensemble') is not None:
info['path_ensemble'] = ensemble['path_ensemble'].restart_info()
if ensemble.get('system') is not None:
info['system'] = ensemble['system'].restart_info()
if ensemble.get('engine') is not None:
info['engine'] = ensemble['engine'].restart_info()
if ensemble.get('rgen') is not None:
info['rgen'] = ensemble['rgen'].get_state()
if ensemble.get('order_function') is not None:
info['order_function'] = ensemble['order_function'].restart_info()
filename = os.path.join(
settings_ens['simulation']['exe_path'],
ensemble['path_ensemble'].ensemble_name_simple,
'ensemble.restart')
# Write atomically: the file is swapped into place with os.replace,
# so an abrupt interruption can never leave a half-written restart
# (it is always either the complete old or the complete new file).
atomic_write(
filename,
lambda outfile: pickle.dump(info, outfile),
binary=True,
)
[docs]def read_restart_file(filename):
"""Read restart info for a simulation.
Parameters
----------
filename : string
The file we are going to read from.
"""
with open(filename, 'rb') as infile:
info = pickle.load(infile) # nosec B301
return info