Exemplo n.º 1
0
 def _interpolation_grid_force(self):
     self._widths = []
     self._bounds = []
     self._extra_points = []
     for v in self.bias_variables:
         extra_points = min(self.grid_expansion, v.grid_size) if v.periodic else 0
         extra_range = extra_points*v._range/(v.grid_size - 1)
         self._widths.append(v.grid_size + 2*extra_points)
         self._bounds += [v.min_value - extra_range, v.max_value + extra_range]
         self._extra_points.append(extra_points)
     self._bias = np.zeros(np.prod(self._widths))
     num_bias_variables = len(self.bias_variables)
     if num_bias_variables == 1:
         self._table = openmm.Continuous1DFunction(self._bias, *self._bounds)
     elif num_bias_variables == 2:
         self._table = openmm.Continuous2DFunction(*self._widths, self._bias, *self._bounds)
     else:
         self._table = openmm.Continuous3DFunction(*self._widths, self._bias, *self._bounds)
     expression = f'bias({",".join(v.id for v in self.bias_variables)})'
     for i, v in enumerate(self.bias_variables):
         expression += f';{v.id}={v._get_energy_function(i+1)}'
     force = openmm.CustomCVForce(expression)
     for i in range(num_bias_variables):
         x = openmm.CustomExternalForce('x')
         x.addParticle(0, [])
         force.addCollectiveVariable(f'x{i+1}', x)
     force.addTabulatedFunction('bias', self._table)
     force.addGlobalParameter('Lx', 0)
     return force
Exemplo n.º 2
0
def add_external_field(system: mm.System, args: ListOfArgs):
    """Add external forcefield for image-driven modelling purposes."""
    print('      Adding external forcefield.')
    size = os.stat(args.EF_PATH).st_size
    print(f"   Reading {args.EF_PATH} file ({sizeof_fmt(size)})...")
    img = np.load(args.EF_PATH)
    print(f"   Array of shape {img.shape} loaded.")
    print(f"   Number of values: {img.size}")
    print(f"   Min: {np.min(img)}")
    print(f"   Max: {np.max(img)}")
    if args.EF_NORMALIZE:
        print('   [INFO] Field will be normalized to [0, -1]')
        img = standardize_image(img)
    print(f'   [INFO] IMG min = {np.min(img)}, max = {np.max(img)}')
    print(f'   [INFO] Adding funnel like border to image')
    mask_p = (img < -0.1)
    mask_n = np.logical_not(mask_p)
    img = add_funnel(img, mask_n)
    print("  Creating a force based on density...")
    voxel_size = np.array((args.EF_VOXEL_SIZE_X, args.EF_VOXEL_SIZE_Y, args.EF_VOXEL_SIZE_Z))
    real_size = img.shape * voxel_size
    density_fun_args = dict(
        xsize=img.shape[2],
        ysize=img.shape[1],
        zsize=img.shape[0],
        values=img.flatten().astype(np.float64),
        xmin=0 * simtk.unit.angstrom - 0.5 * voxel_size[0],
        ymin=0 * simtk.unit.angstrom - 0.5 * voxel_size[1],
        zmin=0 * simtk.unit.angstrom - 0.5 * voxel_size[2],
        xmax=(img.shape[0] - 1) * voxel_size[0] + 0.5 * voxel_size[0],
        ymax=(img.shape[1] - 1) * voxel_size[1] + 0.5 * voxel_size[1],
        zmax=(img.shape[2] - 1) * voxel_size[2] + 0.5 * voxel_size[2])

    print(f'   [INFO] Voxel size: ({args.EF_VOXEL_SIZE_X}, {args.EF_VOXEL_SIZE_Y}, {args.EF_VOXEL_SIZE_Z})')
    print(f'   [INFO] Real size (Shape * voxel size): ({real_size[0]}, {real_size[1]}, {real_size[2]})')
    print(
        f"   [INFO] begin coords: ({density_fun_args['xmin']}, {density_fun_args['ymin']}, {density_fun_args['zmin']})")
    print(
        f"   [INFO] end coords:   ({density_fun_args['xmax']}, {density_fun_args['ymax']}, {density_fun_args['zmax']})")
    center_x = (density_fun_args['xmax'] - density_fun_args['xmin']) / 2 + density_fun_args['xmin']
    center_y = (density_fun_args['ymax'] - density_fun_args['ymin']) / 2 + density_fun_args['ymin']
    center_z = (density_fun_args['zmax'] - density_fun_args['zmin']) / 2 + density_fun_args['zmin']
    print(f"   [INFO] Image central point: ({center_x}, {center_y}, {center_z}) ")
    field_function = mm.Continuous3DFunction(**density_fun_args)
    field_force = mm.CustomCompoundBondForce(1, 'ksi*fi(x1,y1,z1)')
    field_force.addTabulatedFunction('fi', field_function)
    field_force.addGlobalParameter('ksi', args.EF_SCALING_FACTOR)
    print("  Adding force to the system...")
    for i in range(system.getNumParticles()):
        field_force.addBond([i], [])
    system.addForce(field_force)
Exemplo n.º 3
0
 def __init__(self, variables, height, frequency, grid_expansion):
     self.bias_variables = [cv for cv in variables if cv.sigma is not None]
     self.height = height
     self.frequency = frequency
     self.grid_expansion = grid_expansion
     self._widths = []
     self._bounds = []
     self._expanded = []
     self._extra_points = []
     for cv in self.bias_variables:
         expanded = cv.periodic  # and len(self.bias_variables) > 1
         extra_points = min(grid_expansion, cv.grid_size) if expanded else 0
         extra_range = extra_points * cv._range / (cv.grid_size - 1)
         self._widths += [cv.grid_size + 2 * extra_points]
         self._bounds += [
             cv.min_value - extra_range, cv.max_value + extra_range
         ]
         self._expanded += [expanded]
         self._extra_points += [extra_points]
     self._bias = np.zeros(tuple(reversed(self._widths)))
     if len(variables) == 1:
         self._table = openmm.Continuous1DFunction(
             self._bias.flatten(),
             *self._bounds,
             # self.bias_variables[0].periodic,
         )
     elif len(variables) == 2:
         self._table = openmm.Continuous2DFunction(
             *self._widths,
             self._bias.flatten(),
             *self._bounds,
         )
     elif len(variables) == 3:
         self._table = openmm.Continuous3DFunction(
             *self._widths,
             self._bias.flatten(),
             *self._bounds,
         )
     else:
         raise ValueError(
             'UFED requires 1, 2, or 3 biased collective variables')
     parameter_list = ', '.join(f's_{cv.id}' for cv in self.bias_variables)
     self.force = openmm.CustomCVForce(f'bias({parameter_list})')
     for cv in self.bias_variables:
         expression = f'{cv.min_value}+{cv._range}*(x/Lx-floor(x/Lx))'
         parameter = openmm.CustomExternalForce(expression)
         parameter.addGlobalParameter('Lx', 0.0)
         parameter.addParticle(0, [])
         self.force.addCollectiveVariable(f's_{cv.id}', parameter)
     self.force.addTabulatedFunction('bias', self._table)
Exemplo n.º 4
0
    def __init__(self,
                 system,
                 variables,
                 temperature,
                 biasFactor,
                 height,
                 frequency,
                 saveFrequency=None,
                 biasDir=None):
        """Create a Metadynamics object.

        Parameters
        ----------
        system: System
            the System to simulate.  A CustomCVForce implementing the bias is created and
            added to the System.
        variables: list of BiasVariables
            the collective variables to sample
        temperature: temperature
            the temperature at which the simulation is being run.  This is used in computing
            the free energy.
        biasFactor: float
            used in scaling the height of the Gaussians added to the bias.  The collective
            variables are sampled as if the effective temperature of the simulation were
            temperature*biasFactor.
        height: energy
            the initial height of the Gaussians to add
        frequency: int
            the interval in time steps at which Gaussians should be added to the bias potential
        saveFrequency: int (optional)
            the interval in time steps at which to write out the current biases to disk.  At
            the same time it writes biases, it also checks for updated biases written by other
            processes and loads them in.  This must be a multiple of frequency.
        biasDir: str (optional)
            the directory to which biases should be written, and from which biases written by
            other processes should be loaded
        """
        if not unit.is_quantity(temperature):
            temperature = temperature * unit.kelvin
        if not unit.is_quantity(height):
            height = height * unit.kilojoules_per_mole
        if biasFactor < 1.0:
            raise ValueError('biasFactor must be >= 1')
        if (saveFrequency is None
                and biasDir is not None) or (saveFrequency is not None
                                             and biasDir is None):
            raise ValueError('Must specify both saveFrequency and biasDir')
        if saveFrequency is not None and (saveFrequency < frequency
                                          or saveFrequency % frequency != 0):
            raise ValueError('saveFrequency must be a multiple of frequency')
        self.variables = variables
        self.temperature = temperature
        self.biasFactor = biasFactor
        self.height = height
        self.frequency = frequency
        self.biasDir = biasDir
        self.saveFrequency = saveFrequency
        self._id = np.random.randint(0x7FFFFFFF)
        self._saveIndex = 0
        self._selfBias = np.zeros(tuple(v.gridWidth for v in variables))
        self._totalBias = np.zeros(tuple(v.gridWidth for v in variables))
        self._loadedBiases = {}
        self._deltaT = temperature * (biasFactor - 1)
        varNames = ['cv%d' % i for i in range(len(variables))]
        self._force = mm.CustomCVForce('table(%s)' % ', '.join(varNames))
        for name, var in zip(varNames, variables):
            self._force.addCollectiveVariable(name, var.force)
        widths = [v.gridWidth for v in variables]
        mins = [v.minValue for v in variables]
        maxs = [v.maxValue for v in variables]
        if len(variables) == 1:
            self._table = mm.Continuous1DFunction(self._totalBias.flatten(),
                                                  mins[0], maxs[0])
        elif len(variables) == 2:
            self._table = mm.Continuous2DFunction(widths[0], widths[1],
                                                  self._totalBias.flatten(),
                                                  mins[0], maxs[0], mins[1],
                                                  maxs[1])
        elif len(variables) == 3:
            self._table = mm.Continuous3DFunction(widths[0], widths[1],
                                                  widths[2],
                                                  self._totalBias.flatten(),
                                                  mins[0], maxs[0], mins[1],
                                                  maxs[1], mins[2], maxs[2])
        else:
            raise ValueError(
                'Metadynamics requires 1, 2, or 3 collective variables')
        self._force.addTabulatedFunction('table', self._table)
        self._force.setForceGroup(31)
        system.addForce(self._force)
        self._syncWithDisk()