Source code for pyretis.simulation.mc_simulation

# -*- coding: utf-8 -*-
# Copyright (c) 2023, PyRETIS Development Team.
# Distributed under the LGPLv2.1+ License. See LICENSE for more info.
"""Definition of simulation objects for Monte Carlo simulations.

This module defines some classes and functions for performing
Monte Carlo simulations.

Important classes defined here
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

UmbrellaWindowSimulation (:py:class:`.UmbrellaWindowSimulation`)
    Defines a simulation for performing umbrella window simulations.
    Several umbrella window simulations can be joined to perform a
    umbrella simulation.
"""
import numpy as np
from pyretis.core.montecarlo import max_displace_step
from pyretis.simulation.simulation import Simulation
from pyretis.core.random_gen import create_random_generator

__all__ = ['UmbrellaWindowSimulation']


def mc_task(rgen, system, maxdx):
    """Perform a Monte Carlo displacement move.

    Here, a displacement step will be carried out and
    the trial move will be accepted/rejected and the
    positions and potential energy will be updated as needed.

    Parameters
    ----------
    rgen : object like :py:class`.RandomGenerator`
        This object is used for generating random numbers.
    system : object like :py:class:`.System`
        The system we act on.
    maxdx : float
        Maximum displacement step for the Monte Carlo move.

    """
    accepted_r, _, trial_r, v_trial, status = max_displace_step(rgen, system,
                                                                maxdx)
    if status:
        system.particles.pos = accepted_r
        system.particles.vpot = v_trial
    return accepted_r, v_trial, trial_r, status


[docs]class UmbrellaWindowSimulation(Simulation): """This class defines an Umbrella simulation. The Umbrella simulation is a special case of the simulation class with settings to simplify the execution of the umbrella simulation. Attributes ---------- ensemble : dict It contains the simulations info * system : object like :py:class:`.System` The system to act on. * rgen : object like :py:class:`.RandomGenerator` Object to use for random number generation. umbrella : list, [float, float] The umbrella window to consider. overlap : float The position we have to cross before the simulation ends. maxdx : float Defines the maximum movement allowed in the Monte Carlo steps : int, optional The number of simulation steps to perform. startcycle : int, optional The cycle we start the simulation on, can be useful if restarting. """ simulation_type = 'umbrella-window'
[docs] def __init__(self, ensemble, settings, controls=None): """Initialise the umbrella simulation simulation. Parameters ---------- ensemble : dict It contains the simulations info * system : object like :py:class:`.System` The system to act on. * rgen : object like :py:class:`.RandomGenerator` Object to use for random number generation. settings : dict Contains all the simulation settings. controls: dict of parameters to control the simulations. Optional It can contain: * mincycle : int, optional The *MINIMUM* number of cycles to perform. Note that in base `Simulation` class this is the *MAXIMUM* number of cycles to perform. The meaning is redefined in this class by overriding `self.simulation_finished`. * startcycle : int, optional The current simulation cycle, i.e. where we start. """ super().__init__(settings, controls) self.umbrella = settings['simulation']['umbrella'] self.overlap = settings['simulation']['overlap'] self.maxdx = settings['simulation']['maxdx'] self.rgen = ensemble.get( 'rgen', create_random_generator(settings['simulation'])) self.system = ensemble['system'] task_monte_carlo = {'func': mc_task, 'args': [self.rgen, self.system, self.maxdx], 'result': 'displace_step'} self.add_task(task_monte_carlo) self.first_step = False if 'restart' in settings: self.load_restart_info(settings['restart'])
[docs] def is_finished(self): """Check if the simulation is done. In the umbrella simulation, the simulation is finished when we cycle is larger than maxcycle and all particles have crossed self.overlap. Returns ------- out : boolean True if the simulation is finished, False otherwise. """ return (self.cycle['step'] > self.cycle['endcycle'] and np.all(self.system.particles.pos > self.overlap))
[docs] def __str__(self): """Return some info about the simulation as a string.""" msg = ['Umbrella window simulation'] msg += [f'Umbrella: {self.umbrella}, Overlap: {self.overlap}.'] msg += [f"Minimum number of cycles: {self.cycle['endcycle']}"] return '\n'.join(msg)
[docs] def restart_info(self): """Return information which can be used to restart the simulation. Returns ------- info : dict, Contains all the updated simulation settings and counters. """ info = super().restart_info() info['simulation'].update(self.rgen.get_state()) info['umbrella'] = self.umbrella info['overlap'] = self.overlap info['type'] = self.simulation_type return info
[docs] def load_restart_info(self, info): """Load the restart information.""" super().load_restart_info(info) self.umbrella = info.get('umbrella', self.umbrella) self.overlap = info.get('overlap', self.overlap) self.rgen = create_random_generator(info['simulation'])