HookFunctions

class HookFunctions(pre_step_hooks=None, post_step_hooks=None, measurement_hooks=None)

Class to store and manage all hook functions for a dynamics calculation (MD or TS-FBMC).

Parameters:
  • pre_step_hooks (callable | list of callable | None) – A user-defined function or a list of functions which will be called just before the forces evaluation. The signature of the function requires the arguments step, time, configuration. The return status is ignored. Unhandled exceptions will terminate a Molecular Dynamics evaluation. If a list is given, the functions will be called in the given order.
    Default: None.

  • post_step_hooks (callable | list of callable | None) – A user-defined function or a list of functions which will be called just after the forces evaluation. The signature of the function requires the arguments step, time, configuration. Optional arguments include, forces, local_forces (for distributed MD), stress, trajectory (the MD trajectory), temperature, pressure, potential_energy, and/or kinetic_energy. The return status is ignored. Unhandled exceptions will terminate a Molecular Dynamics evaluation. If a list is given, the functions will be called in the given order.
    Default: None.

  • measurement_hooks (callable | list of callable | None) – A user-defined function or a list of functions which will be called at the end of each MD step after all constraints have been applied. The signature of the function requires the arguments step, time, configuration. Optional arguments include forces, local_forces (for distributed MD), stress, trajectory (the MD trajectory), temperature, pressure, potential_energy, and/or kinetic_energy. The return value should be a dictionary that maps string keys to values. The values may be numbers, numpy arrays, or PhysicalQuantities. These values are stored on the MDTrajectory and can be accessed using the measurement method. Unhandled exceptions will terminate a Molecular Dynamics evaluation. If a list is given, the functions will be called in the given order.
    Default: None.

addMeasurementHooks(hook_functions)

Add a measurement hook function or functions.

Parameters:

hook_functions (callable | list of callable) – A user-defined function or a list of functions which will be called at the end of each MD step after all constraints have been applied. The signature of the function requires the arguments step, time, configuration. Optional arguments include forces, local_forces (for distributed MD), stress, trajectory (the MD trajectory), temperature, pressure, potential_energy, and/or kinetic_energy. The return value should be a dictionary that maps string keys to values. The values may be numbers, numpy arrays, or PhysicalQuantities. These values are stored on the MDTrajectory and can be accessed using the measurement method. Unhandled exceptions will terminate a Molecular Dynamics evaluation. If a list is given, the functions will be called in the given order.

addPostStepHooks(hook_functions)

Add a post step hook function or functions.

Parameters:

hook_functions (callable | list of callable) – A user-defined function or a list of functions which will be called just after the forces evaluation. The signature of the function requires the arguments step, time, configuration. Optional arguments include, forces, local_forces (for distributed MD), stress, trajectory (the MD trajectory), temperature, pressure, potential_energy, and/or kinetic_energy. The return status is ignored. Unhandled exceptions will terminate a Molecular Dynamics evaluation. If a list is given, the functions will be called in the given order.

addPreStepHooks(hook_functions)

Add a pre-step hook function or functions.

Parameters:

hook_functions (callable | list of callable) – A user-defined function or a list of functions which will be called just before the forces evaluation. The signature of the function requires the arguments step, time, configuration. The return status is ignored. Unhandled exceptions will terminate a Molecular Dynamics evaluation. If a list is given, the functions will be called in the given order.

allHooks()
Returns:

All hook functions separated by hook types.

Return type:

dict

anyMeasurementHooksRequireStress()

Check if any of the measurement hooks requires stress.

Returns:

True, if any measurement hook requires stress.

Return type:

bool

callAllHookFunctions(hook_type, step, time, configuration, local_forces, stress, trajectory, md_quantities=None)

Run through all hook functions, gather their required arguments and call them in the given order.

Parameters:
  • hook_type (str) – The hook type.

  • step (int) – The current MD step number.

  • time (PhysicalQuantity of type time) – The current simulation time.

  • configuration (DistributedConfiguration | MoleculeConfiguration | BulkConfiguration | DeviceConfiguration | SurfaceConfiguration) – The current configuration.

  • local_forces (PhysicalQuantity of type energy/length) – The local forces vector. For serial simulation this will be the same as the global vector.

  • stress (PhysicalQuantity of type energy/length**3 | None) – The stress tensor or None if no stress calculation is carried out.

  • trajectory (MDTrajectory) – The trajectory calculated so far.

  • md_quantities (MDQuantities) – Optional, the MDQuantities object.
    Default: None.

Returns:

Measurement values.

Return type:

dict

hasMeasurementHooks()
Returns:

True, if there are measurement hooks in the store.

Return type:

bool

hasPostStepHooks()
Returns:

True, if there are post-step hooks in the store.

Return type:

bool

hasPreStepHooks()
Returns:

True, if there are pre-step hooks in the store.

Return type:

bool

measurementHooks()
Returns:

The measurement hooks.

Return type:

list of HookFunctionCall

metatext()
Returns:

The metatext of the object or None if no metatext is present.

Return type:

str | None

nlinfo()

Create NLInfo.

Returns:

The nlinfo.

Return type:

dict

postStepHooks()
Returns:

The post-step hooks.

Return type:

list of HookFunctionCall

preStepHooks()
Returns:

The pre-step hooks.

Return type:

list of HookFunctionCall

removeMeasurementHook(index)

Remove a measurement hook function.

Parameters:

index (int) – The index of the hook function to remove.

Returns:

The removed hook function.

Return type:

HookFunctionCall | None

removePostStepHook(index)

Remove a post-step hook function.

Parameters:

index (int) – The index of the hook function to remove.

Returns:

The removed hook function.

Return type:

HookFunctionCall | None

removePreStepHook(index)

Remove a pre-step hook function.

Parameters:

index (int) – The index of the hook function to remove.

Returns:

The removed hook function.

Return type:

HookFunctionCall | None

setHookFunctions(pre_step_hooks=None, post_step_hooks=None, measurement_hooks=None)

Set hook functions.

Note! This replaces any currently set hook functions.

Parameters:
  • pre_step_hooks (callable | list of callable | None) – A user-defined function or a list of functions which will be called just before the forces evaluation. The signature of the function requires the arguments step, time, configuration. The return status is ignored. Unhandled exceptions will terminate a Molecular Dynamics evaluation. If a list is given, the functions will be called in the given order.
    Default: None.

  • post_step_hooks (callable | list of callable | None) – A user-defined function or a list of functions which will be called just after the forces evaluation. The signature of the function requires the arguments step, time, configuration. Optional arguments include, forces, local_forces (for distributed MD), stress, trajectory (the MD trajectory), temperature, pressure, potential_energy, and/or kinetic_energy. The return status is ignored. Unhandled exceptions will terminate a Molecular Dynamics evaluation. If a list is given, the functions will be called in the given order.
    Default: None.

  • measurement_hooks (callable | list of callable | None) – A user-defined function or a list of functions which will be called at the end of each MD step after all constraints have been applied. The signature of the function requires the arguments step, time, configuration. Optional arguments include forces, local_forces (for distributed MD), stress, trajectory (the MD trajectory), temperature, pressure, potential_energy, and/or kinetic_energy. The return value should be a dictionary that maps string keys to values. The values may be numbers, numpy arrays, or PhysicalQuantities. These values are stored on the MDTrajectory and can be accessed using the measurement method. Unhandled exceptions will terminate a Molecular Dynamics evaluation. If a list is given, the functions will be called in the given order.
    Default: None.

setMetatext(metatext)

Set a given metatext string on the object.

Parameters:

metatext (str | None) – The metatext string that should be set. A value of “None” can be given to remove the current metatext.

uniqueString()

Return a unique string representing the state of the object.

Usage Examples

Set up a HookFunctions object with a StrainConfigurationHook as a pre-step hook, a custom hook function as a post-step hook and a measurement hook to measure the uniaxial stress and strain in all three Cartesian directions:

# -*- coding: utf-8 -*-
from .hook_functions_configuration import silver

# %% HookFunctions

# Pre-step hook functions
strain_configuration_hook = StrainConfigurationHook(
    strain_direction='xx', strain_rate=5.0 * 1 / ps, call_interval=10, strain_interval=1
)


# Post-step hook functions
def custom_hook(step, time, configuration, forces):
    call_interval = 10
    if step % call_interval != 0:
        return

    print(forces)


# Measurement hooks
md_measurement = MDMeasurement(
    measurements=[
        'strain_xx',
        'strain_yy',
        'strain_zz',
        'stress_xx',
        'stress_yy',
        'stress_zz',
    ],
    call_interval=10
)


pre_step_hooks = [
    strain_configuration_hook,
]
post_step_hooks = [
    custom_hook,
]
measurement_hooks = [
    md_measurement,
]
hook_functions = HookFunctions(
    pre_step_hooks=pre_step_hooks,
    post_step_hooks=post_step_hooks,
    measurement_hooks=measurement_hooks,
)

nlsave('HookFunctions_results.hdf5', hook_functions)


# %% MolecularDynamics

method = NVEVelocityVerlet(
    initial_velocity=MaxwellBoltzmannDistribution(
        temperature=300.0 * Kelvin,
        remove_center_of_mass_momentum=False,
        random_seed=None,
        enforce_temperature=True,
    ),
    time_step=1.0 * fs,
)

md_trajectory = MolecularDynamics(
    configuration=silver,
    constraints=[],
    trajectory_filename='HookFunctions_results.hdf5',
    steps=5000,
    log_interval=100,
    method=method,
    hook_functions=hook_functions,
)
last_image = md_trajectory.lastImage()


# %% TimeStampedForceBiasMonteCarlo

monte_carlo_method = ForceBiasMonteCarlo(
    temperature=300.0 * Kelvin,
    max_atom_displacement=0.1 * Angstrom,
    heating_rate=0.0 * Kelvin,
    random_seed=None,
    max_random_attempts=500,
)

tfmc_trajectory = TimeStampedForceBiasMonteCarlo(
    configuration=last_image,
    constraints=[],
    trajectory_filename='HookFunctions_results.hdf5',
    steps=5000,
    log_interval=100,
    method=monte_carlo_method,
    hook_functions=hook_functions,
)
last_image_1 = tfmc_trajectory.lastImage()

hook_functions_configuration.py hook_functions.py

For sake of clarity, the configuration and calculator are defined in a separate file. In the example, both a MolecularDynamics and a TimeStampedForceBiasMonteCarlo are instantiated to illustrate how the HookFunctions is passed to them respectively.

General

The HookFunctions class can be used to organize sets of pre-, post- and measurement hook functions, that can then be passed to a MolecularDynamics or TimeStampedForceBiasMonteCarlo function to be used in a dynamics simulation.

The pre-step hook is invoked immediately before each forces calculation during the MD loop, whereas the post-step hook is invoked immediately after the forces calculation. The measurement hook is invoked at the end of each MD step (see also the reference manual notes MolecularDynamics).

Each category of hook functions can consist of a list of functions. For instance, the pre-step hook can consist of a StrainConfigurationHook and two CustomHooks. The functions within each category are then called in the order they are given in the list.

A HookFunctions object can be saved to disk, and so can be created once and used/reused in different dynamics simulations.

The HookFunctions object is also supported in NanoLab, in the form of a Workflow Builder Block with the icon qatkicon-hookfunctions-block. It can be found under the Optimization and Dynamics category. The block requires an input configuration and provides a HookFunctions object.

Available hook functions

The following classes are available for use in scripting, though not all of them may be available in NanoLab:

Custom hook functions

In principle, any callable object can be used as a custom hook function. Python generator objects are not allowed as hook functions. Examples of valid hook functions are:

Function

def customHookFunction(step, time, configuration):
    call_interval = 10
    if step % call_interval != 0:
        return

    ...

hook_functions = HookFunctions(pre_step_hooks=[customHookFunction])

For functions, the call interval can be included as part of the function body, if the hook should not be called at each step.

Callable class

class CustomHookCallable:
    def __call__(self, step, time, configuration):
        ...

    def callInterval(self):
        return 10

hook_functions = HookFunctions(pre_step_hooks=[CustomHookCallable])

For callable classes, the call interval can be provided by defining a callInterval method on the class that returns an integer, if the hook should not be called at each step.

Class method

class CustomHookClass:
    def hookMethod(self, step, time, configuration):
        ...

    def callInterval(self):
        return 10

hook_functions = HookFunctions(pre_step_hooks=[CustomHookClass.hookMethod])

For class methods, there can also be a callInterval method on the class that returns the call interval as an integer.

Warning

It is not recommended to use class methods as these cannot be reconstructed when a saved HookFunctions object is read from disk. They can, however, be safely used if the custom hook class and HookFunctions are defined within the same script. If possible, opt to re-write the custom hook class with a __call__ method instead.

Note! Any modification to the configuration, forces, or stress, must be made in-place, e.g:

def customHookFunction(step, time, configuration, forces):
    # Add a small constant forces to the forces vector of the first atom.
    forces[0] += [0.1, 0.1, 0.1] * eV / Ang

Because the pre-step hook is invoked immediately before each forces calculation during the MD loop, any modification to the forces or stress, e.g. adding an external force, should be made in a post-step hook, which is invoked after the forces calculation. If a modification is done in a pre-step hook, it would be overwritten by the calculated forces, and have no effect.

In contrast, any modification to the configuration, e.g. straining the cell, should be made in a pre-step-hook, so that the following forces calculation will be carried out on the modified configuration.

Input arguments

A custom hook function must take at least the following arguments:

  • step

  • time

  • configuration

It may optionally take the following arguments:

  • forces

  • local_forces (for MPI-distributed MD simulations)

  • stress

  • trajectory

If it is to be used as a measurement hook, it may also optionally take the following arguments:

  • temperature

  • pressure

  • potential_energy

  • kinetic_energy

  • md_quantities

md_quantities contains all of the other measurement types, and additionally has the methods reservoirTemperature, reservoirPressure and timeStep.

Any arguments not listed above (excluding self, cls for callable classes and class methods) will raise an exception when the HookFunctions object is instantiated.

Return value

In general, a hook function does not return a value. For pre- and post-step hooks any return value is simply neglected.

For measurement hooks, a dict can be returned, for which each entry in the dictionary is then stored as a separate measurement on the MDTrajectory, and would be automatically available as a plot when visualized in the MovieTool. In this way, custom measurement quantities can be introduced in a dynamics simulation.

Notes