Source code for metafalcon.cvs.cv

# -*- coding: utf-8 -*-

"""Contains a general collective variable class that is inherited by individual CVs."""

from __future__ import print_function
import os
import numpy as np
import json

from .. import wall
from .. import constants as c

[docs]class cv(): """Collective variable class. Parameters ---------- idx : int index of the cv, used for filename-numbering symbols : list of str atomic symbols of the molecule kwargs : See below Keyword Arguments ----------------- name : str name of the collective variable type : str type of the collective variable width : float width of the added Gaussians active : bool whether CV is used for metadynamics thresh : bool whether to use threshold to switch off / on the addition of Gaussians thresh_type : str type of threshold to be used (upper | lower) thresh_value : float value of the CV to switch off / on the addition of Gaussians periodic : bool whether to use periodic boundaries for the CV periodic_type : str type of periodic boundaries for the CV (mirror | continue) periodic_start : float start value of the periodic range periodic_end : float end value of the periodic range Attributes ---------- idx symbols kwargs tmp name type width active thresh thresh_type thresh_value update use_wall s ds_dr step shift ticks periodic periodic_type periodic_start periodic_end au2unit """ def __init__(self, idx, symbols, **kwargs): """Construct collective variable object.""" self.idx = idx self.symbols = symbols self.tmp = "tmp.npy" self.kwargs = kwargs self.name = self.get_kwargs("name") self.type = self.get_kwargs("type") self.width = self.get_kwargs("width") self.active = not self.get_kwargs("wall only", default=False) self.thresh = self.get_kwargs("thresh", default=False) self.nproc = self.get_kwargs("nproc", default=1) if self.thresh: # self.thresh_type = self.get_kwargs("thresh_type") self.thresh_type = self.thresh["type"] # self.thresh_value = self.get_kwargs("thresh_value") if self.thresh_type.startswith("noon_"): self.thresh_value = self.thresh["value"] elif self.thresh_type.startswith("energy_"): self.thresh_value = self.thresh["value"]*c.from_energyunit(self.thresh["unit"]) else: # default is energies self.thresh_value = self.thresh["value"]*c.from_energyunit(self.thresh["unit"]) print("THRESHOLD: ", self.thresh_value) # print("threshold parameters:\n", self.thresh_type, self.thresh_value) self.update = True self.use_wall = False self.s = 0.0 self.ds_dr = np.zeros((len(self.symbols), 3)) self.step = 0 # for periodicity self.shift = [0.] self.ticks = None self.periodic = self.get_kwargs("periodic", default=False) if self.periodic: self.periodic_type = self.get_kwargs("periodic_type") self.periodic_start = self.get_kwargs("periodic_start") self.periodic_end = self.get_kwargs("periodic_end") with open("meta-config.json") as f: self.tstep = json.load(f)["molecular dynamics"]["tstep"] # for unit conversion self.au2unit = 1.0 with open("meta-config.json") as f: mdconf = json.load(f)["molecular dynamics"] self.iface = mdconf["interface"]["type"] self.restart = False if "restart" in mdconf.keys() and mdconf["restart"]: self.restart = True
[docs] def initialize(self): if "wall" in self.kwargs.keys(): self.set_wall(self.kwargs["wall"])
[docs] def get_kwargs(self, key, default=None): try: return self.kwargs[key] except KeyError: if default is not None: return default else: print("Error: mandatory keyword %s missing in the input file!" % key)
[docs] def reset_width(self): self.width = self.get_kwargs("width", default=1.0)/self.au2unit
[docs] def set_step(self, step): self.step = step
[docs] def set_update(self, value): if self.thresh: if ((self.thresh_type.endswith("upper") and value > self.thresh_value) or (self.thresh_type.endswith("lower") and value < self.thresh_value)): self.update = False else: self.update = True
[docs] def delete_tmpfile(self): if os.path.exists(self.tmp): os.remove(self.tmp)
[docs] def set_plot(self, plot): self.x = np.linspace(plot["min"], plot["max"], plot["npoints"]) self.ticks = plot["ticks"]
[docs] def set_wall_s(self): if ("dynamic_scaling" in self.wall_kwargs and self.wall_kwargs["dynamic_scaling"] and self.step > 1): previous = np.loadtxt(self.wall_kwargs["file"])[-2:] diff = previous[1]-previous[0] print("diff: ", diff) print("old s: ", self.wall_kwargs["s"]) if diff > self.wall_kwargs["threshold"]: self.wall_kwargs["s"] += self.wall_kwargs["step_up"] else: self.wall_kwargs["s"] -= self.wall_kwargs["step_down"] if self.wall_kwargs["s"] < 0: self.wall_kwargs["s"] = 0 print("new s: ", self.wall_kwargs["s"])
[docs] def set_wall(self, wall_kwargs): self.use_wall = True with open("wall_%d.dat" % self.idx, "w") as f: f.write("# wall values:\n") self.wall_kwargs = wall_kwargs["prm"] self.wall_kwargs["offset"] = self.wall_kwargs["offset"]/self.au2unit walls = {"polynomial_upper": wall.polynomial_upper, "polynomial_lower": wall.polynomial_lower, "log_upper": wall.log_upper, "log_lower": wall.log_lower} dwalls = {"polynomial_upper": wall.dpolynomial_upper, "polynomial_lower": wall.dpolynomial_lower, "log_upper": wall.dlog_upper, "log_lower": wall.dlog_lower} self.wallfunc = walls[wall_kwargs["type"]] self.dwallfunc = dwalls[wall_kwargs["type"]]
[docs] def convert_units(self, s): return s*self.au2unit
[docs] def get_s(self): """ Get current value of the collective variable. Returns ------- s : float current value of the CV """ return self.s
[docs] def get_ds_dr(self): """ Get current gradient of the collective variable. Returns ------- s : np.2darray current gradient of the CV (shape: (N, 3)) """ return self.ds_dr