######################################################################
# BioSimSpace: Making biomolecular simulation a breeze!
#
# Copyright: 2017-2024
#
# Authors: Lester Hedges <lester.hedges@gmail.com>
#
# BioSimSpace is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BioSimSpace is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with BioSimSpace. If not, see <http://www.gnu.org/licenses/>.
#####################################################################
"""Functionality for initialising metadynamics simulation processes."""
__author__ = "Lester Hedges"
__email__ = "lester.hedges@gmail.com"
__all__ = ["run"]
from .._SireWrappers import System as _System
from .. import Process as _Process
from .. import Protocol as _Protocol
# Import common objects from BioSimSpace.MD._md
from ..MD._md import _file_extensions, _md_engines, _find_md_engines
[docs]
def run(
system,
protocol,
engine="auto",
gpu_support=False,
auto_start=True,
name="metamd",
work_dir=None,
seed=None,
property_map={},
**kwargs,
):
"""
Auto-configure and run a metadynamics process.
Parameters
----------
system : :class:`System <BioSimSpace._SireWrappers.System>`
The molecular system.
protocol : :class:`Protocol <BioSimSpace.Protocol.Metadynamics>`
The metadynamics protocol.
engine : str
The molecular dynamics engine to use. If "auto", then a matching
engine will automatically be chosen. Supported engines can be
found using 'BioSimSpace.Metadynamics.engines()'.
gpu_support : bool
Whether to choose an engine with GPU support.
auto_start : bool
Whether to start the process automatically.
name : str
The name of the process.
work_dir : str
The working directory for the process.
seed : int
A random number seed.
property_map : dict
A dictionary that maps system "properties" to their user defined
values. This allows the user to refer to properties with their
own naming scheme, e.g. { "charge" : "my-charge" }
kwargs : dict
A dictionary of optional keyword arguments neeeded by the engine.
Returns
-------
process : :class:`Process <BioSimSpace.Process>`
A process to run the molecular dynamics protocol.
"""
# Check that the system is valid.
if not isinstance(system, _System):
raise TypeError("'system' must be of type 'BioSimSpace._SireWrappers.System'")
# Check that the protocol is valid.
if not isinstance(protocol, _Protocol.Metadynamics):
raise TypeError(
"'protocol' must be of type 'BioSimSpace.Protocol.Metadynamics'"
)
# Validate optional arguments.
if not isinstance(engine, str):
raise TypeError("'engine' must be of type 'str'.")
md_engine = engine.upper().replace(" ", "")
if not isinstance(gpu_support, bool):
raise TypeError("'gpu_support' must be of type 'bool'")
if not isinstance(auto_start, bool):
raise TypeError("'auto_start' must be of type 'bool'")
if not isinstance(name, str):
raise TypeError("'name' must be of type 'str'")
if work_dir is not None:
if not isinstance(work_dir, str):
raise TypeError("'work_dir' must be of type 'str'")
if seed is not None:
if not type(seed) is int:
raise TypeError("'seed' must be of type 'int'")
if not isinstance(property_map, dict):
raise TypeError("'property_map' must be of type 'dict'")
# Find a molecular dynamics engine and executable.
engines, exes = _find_md_engines(system, protocol, md_engine, gpu_support)
# Create the process object, return the first supported engine that can
# instantiate a process.
for engine, exe in zip(engines, exes):
try:
# AMBER.
if engine == "AMBER":
process = _Process.Amber(
system,
protocol,
exe=exe,
name=name,
work_dir=work_dir,
seed=seed,
property_map=property_map,
**kwargs,
)
# GROMACS.
elif engine == "GROMACS":
process = _Process.Gromacs(
system,
protocol,
exe=exe,
name=name,
work_dir=work_dir,
seed=seed,
property_map=property_map,
**kwargs,
)
# OPENMM.
elif engine == "OPENMM":
if gpu_support:
platform = "CUDA"
else:
platform = "CPU"
# Don't pass the executable name through so that this works on Windows too.
process = _Process.OpenMM(
system,
protocol,
exe=None,
name=name,
work_dir=work_dir,
seed=seed,
property_map=property_map,
platform=platform,
**kwargs,
)
# Start the process.
if auto_start:
return process.start()
else:
return process
except:
pass
# If we got here, then we couldn't create a process.
if md_engine == "AUTO":
raise Exception(
f"Unable to create a process using any supported engine: {engines}"
)
else:
raise Exception(
f"Unable to create a process using the chosen engine: {md_engine}"
)