Example #1
0
    def setup_plumed(self, timestep, restart):
        r'''Send commands to PLUMED to make it computation-ready.

            **Arguments:**

            timestep
                The timestep (in au) of the integrator

            restart
                Set to a value different from 0 to let PLUMED know that this
                is a restarted run
        '''
        # Try to load the plumed Python wrapper, quit if not possible
        try:
            from plumed import Plumed
        except:
            log("Could not import the PLUMED python wrapper!")
            raise ImportError
        self.plumed = Plumed(kernel=self.kernel)
        # Conversion between PLUMED internal units and YAFF internal units
        # Note that PLUMED output will follow the PLUMED conventions
        # concerning units
        self.plumed.cmd("setMDEnergyUnits", 1.0 / kjmol)
        self.plumed.cmd("setMDLengthUnits", 1.0 / nanometer)
        self.plumed.cmd("setMDTimeUnits", 1.0 / picosecond)
        # Initialize the system in PLUMED
        self.plumed.cmd("setPlumedDat", self.fn)
        self.plumed.cmd("setNatoms", self.system.natom)
        self.plumed.cmd("setMDEngine", "YAFF")
        self.plumed.cmd("setLogFile", self.fn_log)
        self.plumed.cmd("setTimestep", timestep)
        self.plumed.cmd("setRestart", restart)
        self.plumed.cmd("init")
Example #2
0
    def __call__(self, iterative):
        r'''When this point is reached, a complete time integration step was
           finished and PLUMED should be notified about this.
        '''
        if not self.hooked:
            if log.do_high:
                log.hline()
                log("Reinitializing PLUMED")
                log.hline()
            if log.do_warning:
                log.warn("You are using PLUMED as a hook for your integrator. "
                         "If PLUMED adds time-dependent forces (for instance "
                         "when performing metadynamics) there is no energy "
                         "conservation. The conserved quantity reported by "
                         "YAFF is irrelevant in this case.")
            self.setup_plumed(timestep=iterative.timestep,
                              restart=iterative.counter > 0)
            self.hooked = True
        # PLUMED provides a setEnergy command, which should pass the
        # current potential energy. It seems that this is never used, so we
        # don't pass anything for the moment.
#        current_energy = sum([part.energy for part in iterative.ff.parts[:-1] if not isinstance(part, ForcePartPlumed)])
#        self.plumed.cmd("setEnergy", current_energy)
        self.plumedstep = iterative.counter
        self._internal_compute(None, None)
        self.plumed.cmd("update")
Example #3
0
File: ff.py Project: boegel/yaff
    def generate(cls, system, parameters, **kwargs):
        """Create a force field for the given system with the given parameters.

           **Arguments:**

           system
                An instance of the System class

           parameters
                Three types are accepted: (i) the filename of the parameter
                file, which is a text file that adheres to YAFF parameter
                format, (ii) a list of such filenames, or (iii) an instance of
                the Parameters class.

           See the constructor of the :class:`yaff.pes.generator.FFArgs` class
           for the available optional arguments.

           This method takes care of setting up the FF object, and configuring
           all the necessary FF parts. This is a lot easier than creating an FF
           with the default constructor. Parameters for atom types that are not
           present in the system, are simply ignored.
        """
        if system.ffatype_ids is None:
            raise ValueError(
                'The generators needs ffatype_ids in the system object.')
        with log.section('GEN'), timer.section('Generator'):
            from yaff.pes.generator import apply_generators, FFArgs
            from yaff.pes.parameters import Parameters
            if log.do_medium:
                log('Generating force field from %s' % str(parameters))
            if not isinstance(parameters, Parameters):
                parameters = Parameters.from_file(parameters)
            ff_args = FFArgs(**kwargs)
            apply_generators(system, parameters, ff_args)
            return ForceField(system, ff_args.parts, ff_args.nlist)
Example #4
0
    def __init__(self, system, part_pair):
        '''
           **Arguments:**

           system
                An instance of the ``System`` class.

           part_pair
                An instance of the ``PairPot`` class.

           This force part is only applicable to systems that are 3D periodic.
        '''
        if system.cell.nvec != 3:
            raise ValueError(
                'Tail corrections can only be applied to 3D periodic systems')
        if part_pair.name in ['pair_ei', 'pair_eidip']:
            raise ValueError('Tail corrections are divergent for %s' %
                             part_pair.name)
        super(ForcePartTailCorrection,
              self).__init__('tailcorr_%s' % (part_pair.name), system)
        self.ecorr, self.wcorr = part_pair.pair_pot.prepare_tailcorrections(
            system.natom)
        self.system = system
        if log.do_medium:
            with log.section('FPINIT'):
                log('Force part: %s' % self.name)
                log.hline()
Example #5
0
    def __init__(self, system, grids):
        '''
           **Arguments:**

           system
                An instance of the ``System`` class.

           grids
                A dictionary with (ffatype, grid) items. Each grid must be a
                three-dimensional array with energies.

           This force part is only applicable to systems that are 3D periodic.
        '''
        if system.cell.nvec != 3:
            raise ValueError(
                'The system must be 3d periodic for the grid term.')
        for grid in grids.values():
            if grid.ndim != 3:
                raise ValueError('The energy grids must be 3D numpy arrays.')
        ForcePart.__init__(self, 'grid', system)
        self.system = system
        self.grids = grids
        if log.do_medium:
            with log.section('FPINIT'):
                log('Force part: %s' % self.name)
                log.hline()
Example #6
0
    def set_external_conditions(self, T, fugacity):
        """
           **Arguments:**

           T
                Temperature

           fugacity
                Fugacity. If the species behaves more or less like an ideal gas,
                this is equal to the pressure. Otherwise, the fugacity can be
                obtained from the pressure using an equation of state from
                yaff.pes.eos
        """
        # External conditions
        assert T>0.0
        self.T = T
        self.beta = 1.0/boltzmann/self.T
        assert fugacity>=0.0
        self.fugacity = fugacity
        self.conditions_set = True
        if log.do_medium:
            with log.section(self.log_name):
                # log.pressure does not exist yet, what a pity...
                log("GCMC simulation with T = %s and fugacity = %12.6f bar"%(
                    log.temperature(self.T), self.fugacity/bar))
Example #7
0
    def __init__(self, system, parts, nlist=None):
        """
           **Arguments:**

           system
                An instance of the ``System`` class.

           parts
                A list of instances of sublcasses of ``ForcePart``. These are
                the different types of contributions to the force field, e.g.
                valence interactions, real-space electrostatics, and so on.

           **Optional arguments:**

           nlist
                A ``NeighborList`` instance. This is required if some items in the
                parts list use this nlist object.
        """
        ForcePart.__init__(self, 'all', system)
        self.system = system
        self.parts = []
        self.nlist = nlist
        self.needs_nlist_update = nlist is not None
        for part in parts:
            self.add_part(part)
        if log.do_medium:
            with log.section('FFINIT'):
                log('Force field with %i parts:&%s.' %
                    (len(self.parts), ', '.join(part.name
                                                for part in self.parts)))
                log('Neighborlist present: %s' % (self.nlist is not None))
Example #8
0
def get_trajectory_datasets(tgrp, *fields):
    '''Return a list of new/existing datasets corresponding to the given fields

       **Arguments:**

       tgrp
            The trajectory group

       fields
            A list of fields, i.e. pairs of name and row_shape.
    '''
    result = []
    for name, row_shape in fields:
        if name in tgrp:
            ds = tgrp[name]
            if ds.shape[1:] != row_shape:
                raise TypeError('The shape of the existing dataset is not compatible with the new data.')
            if log.do_medium:
                log('Found an existing dataset %s in group %s with %i rows.' % (name, tgrp.name, ds.shape[0]))
        else:
            if log.do_high:
                log('Creating new dataset %s with row shape %s' % (name, row_shape))
            # Create a new dataset
            shape = (0,) + row_shape
            maxshape = (None,) + row_shape
            ds = tgrp.create_dataset(name, shape, maxshape=maxshape, dtype=float)
        result.append(ds)
    return result
Example #9
0
 def polynomial_roots(self):
     """
         Find the real roots of the polynomial form of the Peng-Robinson
         equation of state
     """
     a = -(1 - self.B)
     b = self.A - 2 * self.B - 3 * self.B**2
     c = -(self.A * self.B - self.B**2 - self.B**3)
     Q = (a**2 - 3 * b) / 9
     R = (2 * a**3 - 9 * a * b + 27 * c) / 54
     M = R**2 - Q**3
     if M > 0:
         S = np.cbrt(-R + np.sqrt(M))
         T = np.cbrt(-R - np.sqrt(M))
         Z = S + T - a / 3
     else:
         theta = np.arccos(R / np.sqrt(Q**3))
         x1 = -2.0 * np.sqrt(Q) * np.cos(theta / 3) - a / 3
         x2 = -2.0 * np.sqrt(Q) * np.cos((theta + 2 * np.pi) / 3) - a / 3
         x3 = -2.0 * np.sqrt(Q) * np.cos((theta - 2 * np.pi) / 3) - a / 3
         solutions = np.array([x1, x2, x3])
         solutions = solutions[solutions > 0.0]
         if self.phase == 'vapour':
             Z = np.amax(solutions)
         elif self.phase == 'liquid':
             Z = np.amin(solutions)
         else:
             raise NotImplementedError
         if log.do_high:
             log("Found 3 solutions for Z (%f,%f,%f), meaning that two "
                 "phases coexist. Returning Z=%f, corresponding to the "
                 "%s phase" % (x1, x2, x3, Z, self.phase))
     return Z
Example #10
0
    def generate(cls, system, parameters, **kwargs):
        """Create a force field for the given system with the given parameters.

           **Arguments:**

           system
                An instance of the System class

           parameters
                Three types are accepted: (i) the filename of the parameter
                file, which is a text file that adheres to YAFF parameter
                format, (ii) a list of such filenames, or (iii) an instance of
                the Parameters class.

           See the constructor of the :class:`yaff.pes.generator.FFArgs` class
           for the available optional arguments.

           This method takes care of setting up the FF object, and configuring
           all the necessary FF parts. This is a lot easier than creating an FF
           with the default constructor. Parameters for atom types that are not
           present in the system, are simply ignored.
        """
        if system.ffatype_ids is None:
            raise ValueError('The generators needs ffatype_ids in the system object.')
        with log.section('GEN'), timer.section('Generator'):
            from yaff.pes.generator import apply_generators, FFArgs
            from yaff.pes.parameters import Parameters
            if log.do_medium:
                log('Generating force field from %s' % str(parameters))
            if not isinstance(parameters, Parameters):
                parameters = Parameters.from_file(parameters)
            ff_args = FFArgs(**kwargs)
            apply_generators(system, parameters, ff_args)
            return ForceField(system, ff_args.parts, ff_args.nlist)
Example #11
0
    def __init__(self, system, parts, nlist=None):
        """
           **Arguments:**

           system
                An instance of the ``System`` class.

           parts
                A list of instances of sublcasses of ``ForcePart``. These are
                the different types of contributions to the force field, e.g.
                valence interactions, real-space electrostatics, and so on.

           **Optional arguments:**

           nlist
                A ``NeighborList`` instance. This is required if some items in the
                parts list use this nlist object.
        """
        ForcePart.__init__(self, 'all', system)
        self.system = system
        self.parts = []
        self.nlist = nlist
        self.needs_nlist_update = nlist is not None
        for part in parts:
            self.add_part(part)
        if log.do_medium:
            with log.section('FFINIT'):
                log('Force field with %i parts:&%s.' % (
                    len(self.parts), ', '.join(part.name for part in self.parts)
                ))
                log('Neighborlist present: %s' % (self.nlist is not None))
Example #12
0
    def __init__(self, system, grids):
        '''
           **Arguments:**

           system
                An instance of the ``System`` class.

           grids
                A dictionary with (ffatype, grid) items. Each grid must be a
                three-dimensional array with energies.

           This force part is only applicable to systems that are 3D periodic.
        '''
        if system.cell.nvec != 3:
            raise ValueError('The system must be 3d periodic for the grid term.')
        for grid in grids.itervalues():
            if grid.ndim != 3:
                raise ValueError('The energy grids must be 3D numpy arrays.')
        ForcePart.__init__(self, 'grid', system)
        self.system = system
        self.grids = grids
        if log.do_medium:
            with log.section('FPINIT'):
                log('Force part: %s' % self.name)
                log.hline()
Example #13
0
 def await_header(self):
     data = self.s.recv(HDRLEN * L_CHAR)
     if self.verbose:
         print('RECV', (data,))
     with log.section('DRIVER'):
         log("RECV %s %s" % (data, datetime.now()))
     return data
Example #14
0
    def load_hdf5(self, fn, T=None):
        """
           Read information from HDF5 file

           **Arguments:**

           fn
                A HDF5 filename containing a hills group. If this concerns a well-
                tempered MTD run, the simulation temperature should be provided
                Otherwise, it will be read from the HDF5 file.
        """
        with h5.File(fn,'r') as f:
            q0s = f['hills/q0'][:]
            Ks = f['hills/K'][:]
            sigmas = f['hills/sigma'][:]
            tempering = f['hills'].attrs['tempering']
            if tempering!=0.0:
                if T is None:
                    if not 'trajectory/temp' in f:
                        raise ValueError("For a well-tempered MTD run, the temperature "
                            "should be specified or readable from the trajectory/temp "
                            "group in the HDF5 file")
                    T = np.mean(f['trajectory/temp'][:])
                if log.do_medium:
                    log("Well-tempered MTD run: T = %s deltaT = %s"%(log.temperature(T), log.temperature(tempering)))
            if 'hills/periodicities' in f:
                periodicities = f['hills/periodicities'][:]
            else:
                periodicities = None
            self.set_hills(q0s, Ks, sigmas, tempering=tempering, T=T, periodicities=periodicities)
Example #15
0
 def update_gmax(self):
     '''This routine must be called after the attribute self.gmax is modified.'''
     self.gmax = np.ceil(self.gcut / self.system.cell.gspacings -
                         0.5).astype(int)
     if log.do_debug:
         with log.section('EWALD'):
             log('gmax a,b,c   = %i,%i,%i' % tuple(self.gmax))
Example #16
0
    def to_file(self, fn):
        """Write the system to a file

           **Arguments:**

           fn
                The file to write to.

           Supported formats are:

           chk
                Internal human-readable checkpoint format. This format includes
                all the information of a system object. All data are stored in
                atomic units.

           h5
                Internal binary checkpoint format. This format includes
                all the information of a system object. All data are stored in
                atomic units.

           xyz
                A simple file with atomic positions and elements. Coordinates
                are written in Angstroms.
        """
        if fn.endswith('.chk'):
            from molmod.io import dump_chk
            dump_chk(
                fn, {
                    'numbers': self.numbers,
                    'pos': self.pos,
                    'ffatypes': self.ffatypes,
                    'ffatype_ids': self.ffatype_ids,
                    'scopes': self.scopes,
                    'scope_ids': self.scope_ids,
                    'bonds': self.bonds,
                    'rvecs': self.cell.rvecs,
                    'charges': self.charges,
                    'radii': self.radii,
                    'valence_charges': self.valence_charges,
                    'dipoles': self.dipoles,
                    'radii2': self.radii2,
                    'masses': self.masses,
                })
        elif fn.endswith('.h5'):
            with h5.File(fn, 'w') as f:
                self.to_hdf5(f)
        elif fn.endswith('.xyz'):
            from molmod.io import XYZWriter
            from molmod.periodic import periodic
            xyz_writer = XYZWriter(fn,
                                   [periodic[n].symbol for n in self.numbers])
            xyz_writer.dump(str(self), self.pos)
        else:
            raise NotImplementedError(
                'The extension of %s does not correspond to any known format.'
                % fn)
        if log.do_high:
            with log.section('SYS'):
                log('Wrote system to %s.' % fn)
Example #17
0
 def send_header(self, header):
     assert len(header) <= 12
     header = header.ljust(12, ' ')
     if self.verbose:
         print('SEND', (header,))
     with log.section('DRIVER'):
         log("SEND %s %s" % (header, datetime.now()))
     self.s.send(header)
Example #18
0
def g09log_to_hdf5(f, fn_log):
    """Convert Gaussian09 BOMD log file to Yaff HDF5 format.

       **Arguments:**

       f
            An open and writable HDF5 file.

       fn_log
            The name of the Gaussian log file.
    """
    with log.section('G09H5'):
        if log.do_medium:
            log('Loading Gaussian 09 file \'%s\' into \'trajectory\' of HDF5 file \'%s\'' % (
                fn_log, f.filename
            ))

        # First make sure the HDF5 file has a system description that is consistent
        # with the XYZ file.
        if 'system' not in f:
            raise ValueError('The HDF5 file must contain a system group.')
        if 'numbers' not in f['system']:
            raise ValueError('The HDF5 file must have a system group with atomic numbers.')
        natom = f['system/numbers'].shape[0]

        # Take care of the trajectory group
        tgrp = get_trajectory_group(f)

        # Take care of the pos and vel datasets
        dss = get_trajectory_datasets(tgrp,
            ('pos', (natom, 3)),
            ('vel', (natom, 3)),
            ('frc', (natom, 3)),
            ('time', (1,)),
            ('step', (1,)),
            ('epot', (1,)),
            ('ekin', (1,)),
            ('etot', (1,)),
        )
        ds_pos, ds_vel, ds_frc, ds_time, ds_step, ds_epot, ds_ekin, ds_etot = dss

        # Load frame by frame
        row = get_last_trajectory_row(dss)
        for numbers, pos, vel, frc, time, step, epot, ekin, etot in _iter_frames_g09(fn_log):
            if (numbers != f['system/numbers']).any():
                log.warn('The element numbers of the HDF5 and LOG file do not match.')
            write_to_dataset(ds_pos, pos, row)
            write_to_dataset(ds_vel, vel, row)
            write_to_dataset(ds_frc, frc, row)
            write_to_dataset(ds_time, time, row)
            write_to_dataset(ds_step, step, row)
            write_to_dataset(ds_epot, epot, row)
            write_to_dataset(ds_ekin, ekin, row)
            write_to_dataset(ds_etot, etot, row)
            row += 1

        # Check number of rows
        check_trajectory_rows(tgrp, dss, row)
Example #19
0
    def to_file(self, fn):
        """Write the system to a file

           **Arguments:**

           fn
                The file to write to.

           Supported formats are:

           chk
                Internal human-readable checkpoint format. This format includes
                all the information of a system object. All data are stored in
                atomic units.

           h5
                Internal binary checkpoint format. This format includes
                all the information of a system object. All data are stored in
                atomic units.

           xyz
                A simple file with atomic positions and elements. Coordinates
                are written in Angstroms.
        """
        if fn.endswith('.chk'):
            from molmod.io import dump_chk
            dump_chk(fn, {
                'numbers': self.numbers,
                'pos': self.pos,
                'ffatypes': self.ffatypes,
                'ffatype_ids': self.ffatype_ids,
                'scopes': self.scopes,
                'scope_ids': self.scope_ids,
                'bonds': self.bonds,
                'rvecs': self.cell.rvecs,
                'charges': self.charges,
                'radii': self.radii,
                'valence_charges': self.valence_charges,
                'dipoles': self.dipoles,
                'radii2': self.radii2,
                'masses': self.masses,
            })
        elif fn.endswith('.h5'):
            with h5.File(fn, 'w') as f:
                self.to_hdf5(f)
        elif fn.endswith('.xyz'):
            from molmod.io import XYZWriter
            from molmod.periodic import periodic
            xyz_writer = XYZWriter(fn, [periodic[n].symbol for n in self.numbers])
            xyz_writer.dump(str(self), self.pos)
        else:
            raise NotImplementedError('The extension of %s does not correspond to any known format.' % fn)
        if log.do_high:
            with log.section('SYS'):
                log('Wrote system to %s.' % fn)
Example #20
0
    def update(self):
        '''Rebuild or recompute the neighbor lists

           Based on the changes of the atomic positions or due to calls to
           ``update_rcut`` and ``update_rmax``, the neighbor lists will be
           rebuilt from scratch.

           The heavy computational work is done in low-level C routines. The
           neighbor lists array is reallocated if needed. The memory allocation
           is done in Python for convenience.
        '''
        with log.section('NLIST'), timer.section('Nlists'):
            assert self.rcut > 0

            if self._need_rebuild():
                # *rebuild* the entire neighborlist
                if self.system.cell.volume != 0:
                    if self.system.natom / self.system.cell.volume > 10:
                        raise ValueError('Atom density too high')
                # 1) make an initial status object for the neighbor list algorithm
                status = nlist_status_init(self.rmax)
                # The atom index of the first atom in pair is always at least
                # nlow. The following status initialization avoids searching
                # for excluded atom pairs in the neighbourlist build
                status[3] = self.nlow
                # 2) a loop of consecutive update/allocate calls
                last_start = 0
                while True:
                    done = nlist_build(self.system.pos, self.rcut + self.skin,
                                       self.rmax, self.system.cell, status,
                                       self.neighs[last_start:], self.nlow,
                                       self.nhigh)
                    if done:
                        break
                    last_start = len(self.neighs)
                    new_neighs = np.empty((len(self.neighs) * 3) // 2,
                                          dtype=neigh_dtype)
                    new_neighs[:last_start] = self.neighs
                    self.neighs = new_neighs
                    del new_neighs
                # 3) get the number of neighbors in the list.
                self.nneigh = nlist_status_finish(status)
                if log.do_debug:
                    log('Rebuilt, size = %i' % self.nneigh)
                # 4) store the current state to check in future calls if we
                #    need to do a rebuild or a recompute.
                self._checkpoint()
                self.rebuild_next = False
            else:
                # just *recompute* the deltas and the distance in the
                # neighborlist
                nlist_recompute(self.system.pos, self._pos_old,
                                self.system.cell, self.neighs[:self.nneigh])
                if log.do_debug:
                    log('Recomputed')
Example #21
0
 def __call__(self, iterative):
     if log.do_medium:
         if self.time0 is None:
             self.time0 = time.time()
             if log.do_medium:
                 log.hline()
                 log('counter  Walltime')
                 log.hline()
         log('%7i %10.1f' % (
             iterative.counter,
             time.time() - self.time0,
         ))
Example #22
0
 def _need_rebuild(self):
     '''Internal method that determines if a rebuild is needed.'''
     if self.skin <= 0 or self._pos_old is None or self.rebuild_next:
         return True
     else:
         # Compute an upper bound for the maximum relative displacement.
         disp = np.sqrt(((self.system.pos - self._pos_old)**2).sum(axis=1).max())
         disp *= 2*(self.rmax.max()+1)
         if log.do_debug:
             log('Maximum relative displacement %s      Skin %s' % (log.length(disp), log.length(self.skin)))
         # Compare with skin parameter
         return disp >= self.skin
Example #23
0
 def __call__(self, iterative):
     if log.do_medium:
         if self.time0 is None:
             self.time0 = time.time()
             if log.do_medium:
                 log.hline()
                 log('counter  Walltime')
                 log.hline()
         log('%7i %10.1f' % (
             iterative.counter,
             time.time() - self.time0,
         ))
Example #24
0
 def _need_rebuild(self):
     '''Internal method that determines if a rebuild is needed.'''
     if self.skin <= 0 or self._pos_old is None or self.rebuild_next:
         return True
     else:
         # Compute an upper bound for the maximum relative displacement.
         disp = np.sqrt(((self.system.pos - self._pos_old)**2).sum(axis=1).max())
         disp *= 2*(self.rmax.max()+1)
         if log.do_debug:
             log('Maximum relative displacement %s      Skin %s' % (log.length(disp), log.length(self.skin)))
         # Compare with skin parameter
         return disp >= self.skin
Example #25
0
    def apply(self, par_table, cpar_table, scale_table, mixing_rules, system, ff_args):
        # Prepare the atomic parameters
        amps = np.zeros(system.nffatype, float)
        bs = np.zeros(system.nffatype, float)
        for i in xrange(system.nffatype):
            key = (system.ffatypes[i],)
            par_list = par_table.get(key, [])
            if len(par_list) == 0:
                if log.do_warning:
                    log.warn('No EXPREP parameters found for ffatype %s.' % system.ffatypes[i])
            else:
                amps[i], bs[i] = par_list[0]

        # Prepare the cross parameters
        amp_cross = np.zeros((system.nffatype, system.nffatype), float)
        b_cross = np.zeros((system.nffatype, system.nffatype), float)
        for i0 in xrange(system.nffatype):
            for i1 in xrange(i0+1):
                cpar_list = cpar_table.get((system.ffatypes[i0], system.ffatypes[i1]), [])
                if len(cpar_list) == 0:
                    if log.do_high:
                        log('No EXPREP cross parameters found for ffatypes %s,%s. Mixing rule will be used' % (system.ffatypes[i0], system.ffatypes[i1]))
                else:
                    amp_cross[i0,i1], b_cross[i0,i1] = cpar_list[0]
                    if i0 != i1:
                        amp_cross[i1,i0], b_cross[i1,i0] = cpar_list[0]

        # Prepare the global parameters
        scalings = Scalings(system, scale_table[1], scale_table[2], scale_table[3])
        amp_mix, amp_mix_coeff = mixing_rules['A']
        if amp_mix == 0:
            amp_mix_coeff = 0.0
        elif amp_mix == 1:
            amp_mix_coeff = amp_mix_coeff[0]
        b_mix, b_mix_coeff = mixing_rules['B']
        if b_mix == 0:
            b_mix_coeff = 0.0
        elif b_mix == 1:
            b_mix_coeff = b_mix_coeff[0]

        # Get the part. It should not exist yet.
        part_pair = ff_args.get_part_pair(PairPotExpRep)
        if part_pair is not None:
            raise RuntimeError('Internal inconsistency: the EXPREP part should not be present yet.')

        pair_pot = PairPotExpRep(
            system.ffatype_ids, amp_cross, b_cross, ff_args.rcut, ff_args.tr,
            amps, amp_mix, amp_mix_coeff, bs, b_mix, b_mix_coeff,
        )
        nlist = ff_args.get_nlist(system)
        part_pair = ForcePartPair(system, nlist, scalings, pair_pot)
        ff_args.parts.append(part_pair)
Example #26
0
 def __call__(self, mc):
     if log.do_medium:
         if self.time0 is None:
             self.time0 = time.time()
             if log.do_medium:
                 log.hline()
                 log('     counter %s   Walltime' % (mc.log_header()))
                 log.hline()
         log('%12i %s %10.1f' % (
             mc.counter,
             mc.log(),
             time.time() - self.time0,
         ))
Example #27
0
File: opt.py Project: tovrstra/yaff
    def update(self, dx, dg):
        tmp = dg - np.dot(self.hessian, dx)

        denom = np.dot(tmp, dx)
        if abs(denom) > 1e-5 * np.linalg.norm(dx) * np.linalg.norm(tmp):
            if log.do_debug:
                log("Updating SR1 Hessian.       denom=%10.3e" % denom)
            self.hessian += np.outer(tmp, tmp) / denom
            return True
        else:
            if log.do_high:
                log("Skipping SR1 update because denom=%10.3e is not big enough." % denom)
            return False
Example #28
0
File: opt.py Project: boegel/yaff
    def update(self, dx, dg):
        tmp = dg - np.dot(self.hessian, dx)

        denom = np.dot(tmp, dx)
        if abs(denom) > 1e-5*np.linalg.norm(dx)*np.linalg.norm(tmp):
            if log.do_debug:
                log('Updating SR1 Hessian.       denom=%10.3e' % denom)
            self.hessian += np.outer(tmp, tmp)/denom
            return True
        else:
            if log.do_high:
                log('Skipping SR1 update because denom=%10.3e is not big enough.' % denom)
            return False
Example #29
0
    def _verify_hooks(self):
        with log.section('ENSEM'):
            thermo = None
            index_thermo = 0
            baro = None
            index_baro = 0

            # Look for the presence of a thermostat and/or barostat
            if hasattr(self.hooks, '__len__'):
                for index, hook in enumerate(self.hooks):
                    if hook.method == 'thermostat':
                        thermo = hook
                        index_thermo = index
                    elif hook.method == 'barostat':
                        baro = hook
                        index_baro = index
            elif self.hooks is not None:
                if self.hooks.method == 'thermostat':
                    thermo = self.hooks
                elif self.hooks.method == 'barostat':
                    baro = self.hooks

            # If both are present, delete them and generate TBCombination element
            if thermo is not None and baro is not None:
                from yaff.sampling.npt import TBCombination
                if log.do_warning:
                    log.warn(
                        'Both thermostat and barostat are present separately and will be merged'
                    )
                del self.hooks[max(index_thermo, index_thermo)]
                del self.hooks[min(index_thermo, index_baro)]
                self.hooks.append(TBCombination(thermo, baro))

            if hasattr(self.hooks, '__len__'):
                for hook in self.hooks:
                    if hook.name == 'TBCombination':
                        thermo = hook.thermostat
                        baro = hook.barostat
            elif self.hooks is not None:
                if self.hooks.name == 'TBCombination':
                    thermo = self.hooks.thermostat
                    baro = self.hooks.barostat

            if log.do_warning:
                if thermo is not None:
                    log('Temperature coupling achieved through ' +
                        str(thermo.name) + ' thermostat')
                if baro is not None:
                    log('Pressure coupling achieved through ' +
                        str(baro.name) + ' barostat')
Example #30
0
File: opt.py Project: boegel/yaff
    def make_step(self):
        # get relevant hessian information
        evals, evecs = self.hessian.get_spectrum()
        if log.do_high:
            log(' lowest eigen value: %7.1e' % evals.min())
            log('highest eigen value: %7.1e' % evals.max())
        # convert gradient to eigen basis
        grad_eigen = np.dot(evecs.T, self.g_old)

        while True:
            # Find the step with the given radius. If the hessian is positive
            # definite and the unconstrained step is smaller than the trust
            # radius, this step is returned
            delta_eigen = solve_trust_radius(grad_eigen, evals, self.trust_radius)
            radius = np.linalg.norm(delta_eigen)

            # convert the step to user basis
            delta_x = np.dot(evecs, delta_eigen)

            # compute the function and gradient at the new position
            x = self.x_old + delta_x
            f, g = self.fun(x, True)

            # compute the change in function value
            delta_f = f - self.f_old
            # compute the change in norm of the gradient
            delta_norm_g = np.linalg.norm(g) - np.linalg.norm(self.g_old)
            # must_shrink is a parameter to control the trust radius
            must_shrink = False

            if delta_f > 0:
                # The function must decrease, if not the trust radius is too big.
                if log.do_high:
                    log('Function increases.')
                must_shrink = True

            if (self.trust_radius < self.small_radius and delta_norm_g > 0):
                # When the trust radius becomes small, the numerical noise on
                # the energy may be too large to detect an increase energy.
                # In that case the norm of the gradient is used instead.
                if log.do_high:
                    log('Gradient norm increases.')
                must_shrink = True

            if must_shrink:
                self.trust_radius *= 0.5
                while self.trust_radius >= radius:
                    self.trust_radius *= 0.5
                if self.trust_radius < self.too_small_radius:
                    raise RuntimeError('The trust radius becomes too small. Is the potential energy surface smooth?')
            else:
                # If we get here, we are done with the trust radius loop.
                if log.do_high:
                    log.hline()
                # It is fine to increase the trust radius a little after a
                # successful step.
                if self.trust_radius < self.initial_trust_radius:
                    self.trust_radius *= 2.0
                # Return the results of the successful step
                return x, f, g
Example #31
0
File: opt.py Project: tovrstra/yaff
    def make_step(self):
        # get relevant hessian information
        evals, evecs = self.hessian.get_spectrum()
        if log.do_high:
            log(" lowest eigen value: %7.1e" % evals.min())
            log("highest eigen value: %7.1e" % evals.max())
        # convert gradient to eigen basis
        grad_eigen = np.dot(evecs.T, self.g_old)

        while True:
            # Find the step with the given radius. If the hessian is positive
            # definite and the unconstrained step is smaller than the trust
            # radius, this step is returned
            delta_eigen = solve_trust_radius(grad_eigen, evals, self.trust_radius)
            radius = np.linalg.norm(delta_eigen)

            # convert the step to user basis
            delta_x = np.dot(evecs, delta_eigen)

            # compute the function and gradient at the new position
            x = self.x_old + delta_x
            f, g = self.fun(x, True)

            # compute the change in function value
            delta_f = f - self.f_old
            # compute the change in norm of the gradient
            delta_norm_g = np.linalg.norm(g) - np.linalg.norm(self.g_old)
            # must_shrink is a parameter to control the trust radius
            must_shrink = False

            if delta_f > 0:
                # The function must decrease, if not the trust radius is too big.
                if log.do_high:
                    log("Function increases.")
                must_shrink = True

            if self.trust_radius < self.small_radius and delta_norm_g > 0:
                # When the trust radius becomes small, the numerical noise on
                # the energy may be too large to detect an increase energy.
                # In that case the norm of the gradient is used instead.
                if log.do_high:
                    log("Gradient norm increases.")
                must_shrink = True

            if must_shrink:
                self.trust_radius *= 0.5
                while self.trust_radius >= radius:
                    self.trust_radius *= 0.5
                if self.trust_radius < self.too_small_radius:
                    raise RuntimeError("The trust radius becomes too small. Is the potential energy surface smooth?")
            else:
                # If we get here, we are done with the trust radius loop.
                if log.do_high:
                    log.hline()
                # It is fine to increase the trust radius a little after a
                # successful step.
                if self.trust_radius < self.initial_trust_radius:
                    self.trust_radius *= 2.0
                # Return the results of the successful step
                return x, f, g
Example #32
0
 def __init__(self, comsystem, scaling=None):
     ForcePart.__init__(self, 'valence_com', comsystem)
     #ForcePartValence.__init__(self, system)
     self.comlist = comsystem.comlist
     self.gpos = np.zeros((comsystem.gpos_dim, 3), float)
     self.dlist = DeltaList(self.comlist)
     self.iclist = InternalCoordinateList(self.dlist)
     self.vlist = ValenceList(self.iclist)
     self.scaling = scaling
     if log.do_medium:
         with log.section('FPINIT'):
             log('Force part: %s' % self.name)
             log.hline()
     self.term = None  # volume term
Example #33
0
    def update(self):
        '''Rebuild or recompute the neighbor lists

           Based on the changes of the atomic positions or due to calls to
           ``update_rcut`` and ``update_rmax``, the neighbor lists will be
           rebuilt from scratch.

           The heavy computational work is done in low-level C routines. The
           neighbor lists array is reallocated if needed. The memory allocation
           is done in Python for convenience.
        '''
        with log.section('NLIST'), timer.section('Nlists'):
            assert self.rcut > 0

            if self._need_rebuild():
                # *rebuild* the entire neighborlist
                if self.system.cell.volume != 0:
                    if self.system.natom/self.system.cell.volume > 10:
                        raise ValueError('Atom density too high')
                # 1) make an initial status object for the neighbor list algorithm
                status = nlist_status_init(self.rmax)
                # 2) a loop of consecutive update/allocate calls
                last_start = 0
                while True:
                    done = nlist_build(
                        self.system.pos, self.rcut + self.skin, self.rmax,
                        self.system.cell, status, self.neighs[last_start:]
                    )
                    if done:
                        break
                    last_start = len(self.neighs)
                    new_neighs = np.empty((len(self.neighs)*3)/2, dtype=neigh_dtype)
                    new_neighs[:last_start] = self.neighs
                    self.neighs = new_neighs
                    del new_neighs
                # 3) get the number of neighbors in the list.
                self.nneigh = nlist_status_finish(status)
                if log.do_debug:
                    log('Rebuilt, size = %i' % self.nneigh)
                # 4) store the current state to check in future calls if we
                #    need to do a rebuild or a recompute.
                self._checkpoint()
                self.rebuild_next = False
            else:
                # just *recompute* the deltas and the distance in the
                # neighborlist
                nlist_recompute(self.system.pos, self._pos_old, self.system.cell, self.neighs[:self.nneigh])
                if log.do_debug:
                    log('Recomputed')
Example #34
0
    def __init__(self, system):
        '''
           **Arguments:**

           system
                An instance of the ``System`` class.
        '''
        ForcePart.__init__(self, 'valence', system)
        self.dlist = DeltaList(system)
        self.iclist = InternalCoordinateList(self.dlist)
        self.vlist = ValenceList(self.iclist)
        if log.do_medium:
            with log.section('FPINIT'):
                log('Force part: %s' % self.name)
                log.hline()
Example #35
0
File: ff.py Project: boegel/yaff
    def __init__(self, system):
        '''
           **Arguments:**

           system
                An instance of the ``System`` class.
        '''
        ForcePart.__init__(self, 'valence', system)
        self.dlist = DeltaList(system)
        self.iclist = InternalCoordinateList(self.dlist)
        self.vlist = ValenceList(self.iclist)
        if log.do_medium:
            with log.section('FPINIT'):
                log('Force part: %s' % self.name)
                log.hline()
Example #36
0
    def add_term(self, term):
        '''Add a new term to the covalent force field.

           **Arguments:**

           term
                An instance of the class :class:`yaff.pes.ff.vlist.ValenceTerm`.

           In principle, one should add all energy terms before calling the
           ``compute`` method, but with the current implementation of Yaff,
           energy terms can be added at any time. (This may change in future.)
        '''
        if log.do_high:
            with log.section('VTERM'):
                log('%7i&%s %s' % (self.vlist.nv, term.get_log(), ' '.join(ic.get_log() for ic in term.ics)))
        self.vlist.add_term(term)
Example #37
0
    def __init__(self,
                 system,
                 alpha,
                 gcut=0.35,
                 dielectric=1.0,
                 exclude_frame=False,
                 n_frame=0):
        '''
           **Arguments:**

           system
                The system to which this interaction applies.

           alpha
                The alpha parameter in the Ewald summation method.

           **Optional arguments:**

           gcut
                The cutoff in reciprocal space.

           dielectric
                The scalar relative permittivity of the system.

           exclude_frame
                A boolean to exclude framework-framework interactions
                (exclude_frame=True) for efficiency sake in MC simulations.

           n_frame
                Number of framework atoms. This parameter is used to exclude
                framework-framework neighbors when exclude_frame=True.
        '''
        ForcePart.__init__(self, 'ewald_reci', system)
        if not system.cell.nvec == 3:
            raise TypeError('The system must have a 3D periodic cell.')
        if system.charges is None:
            raise ValueError('The system does not have charges.')
        self.system = system
        self.alpha = alpha
        self.gcut = gcut
        self.dielectric = dielectric
        self.update_gmax()
        self.work = np.empty(system.natom * 2)
        if exclude_frame == True and n_frame < 0:
            raise ValueError(
                'The number of framework atoms to exclude must be positive.')
        elif exclude_frame == False:
            n_frame = 0
        self.n_frame = n_frame
        if log.do_medium:
            with log.section('FPINIT'):
                log('Force part: %s' % self.name)
                log.hline()
                log('  alpha:                 %s' % log.invlength(self.alpha))
                log('  gcut:                  %s' % log.invlength(self.gcut))
                log('  relative permittivity: %5.3f' % self.dielectric)
                log.hline()
Example #38
0
    def _verify_hooks(self):
        with log.section('ENSEM'):
            thermo = None
            index_thermo = 0
            baro = None
            index_baro = 0

            # Look for the presence of a thermostat and/or barostat
            if hasattr(self.hooks, '__len__'):
                for index, hook in enumerate(self.hooks):
                    if hook.method == 'thermostat':
                        thermo = hook
                        index_thermo = index
                    elif hook.method == 'barostat':
                        baro = hook
                        index_baro = index
            elif self.hooks is not None:
                if self.hooks.method == 'thermostat':
                    thermo = self.hooks
                elif self.hooks.method == 'barostat':
                    baro = self.hooks

            # If both are present, delete them and generate TBCombination element
            if thermo is not None and baro is not None:
                from yaff.sampling.npt import TBCombination
                if log.do_warning:
                    log.warn('Both thermostat and barostat are present separately and will be merged')
                del self.hooks[max(index_thermo, index_thermo)]
                del self.hooks[min(index_thermo, index_baro)]
                self.hooks.append(TBCombination(thermo, baro))

            if hasattr(self.hooks, '__len__'):
                for hook in self.hooks:
                    if hook.name == 'TBCombination':
                        thermo = hook.thermostat
                        baro = hook.barostat
            elif self.hooks is not None:
                if self.hooks.name == 'TBCombination':
                    thermo = self.hooks.thermostat
                    baro = self.hooks.barostat

            if log.do_warning:
                if thermo is not None:
                    log('Temperature coupling achieved through ' + str(thermo.name) + ' thermostat')
                if baro is not None:
                    log('Pressure coupling achieved through ' + str(baro.name) + ' barostat')
Example #39
0
def get_trajectory_group(f):
    '''Create or return an existing trajectory group

       **Arguments:**

       f
            An open HDF5 File or Group object.
    '''
    if 'trajectory' not in f:
        if log.do_high:
            log('Creating new trajectory datagroup in %s.' % f.filename)
        tgrp = f.create_group('trajectory')
    else:
        tgrp = f['trajectory']
        if log.do_high:
            log('Using existing trajectory datagroup in %s.' % f.filename)
    return tgrp
Example #40
0
    def add_term(self, term):
        '''Add a new term to the covalent force field.

           **Arguments:**

           term
                An instance of the class :class:`yaff.pes.ff.vlist.ValenceTerm`.

           In principle, one should add all energy terms before calling the
           ``compute`` method, but with the current implementation of Yaff,
           energy terms can be added at any time. (This may change in future.)
        '''
        if log.do_high:
            with log.section('VTERM'):
                log('%7i&%s %s' % (self.vlist.nv, term.get_log(), ' '.join(
                    ic.get_log() for ic in term.ics)))
        self.vlist.add_term(term)
Example #41
0
 def set_hills(self, q0s, Ks, sigmas, tempering=0.0, T=None, periodicities=None):
     # Safety checks
     assert q0s.shape[1]==self.ncv
     assert sigmas.shape[0]==self.ncv
     assert q0s.shape[0]==Ks.shape[0]
     if tempering != 0.0 and T is None:
         raise ValueError("For a well-tempered MTD run, the temperature "
             "has to be specified")
     self.q0s = q0s
     self.sigmas = sigmas
     self.Ks = Ks
     self.tempering = tempering
     self.T = T
     self.periodicities = periodicities
     if log.do_medium:
         with log.section("SUMHILL"):
             log("Found %d collective variables and %d Gaussian hills"%(self.ncv,self.q0s.shape[0]))
Example #42
0
    def add_term(self, term, use_comlist=False):
        '''Add a new term to the bias potential.

           **Arguments:**

           term
                An instance of the class :class:`yaff.pes.ff.vlist.ValenceTerm`
                or an instance of the class
                :class:`yaff.pes.ff.vias.BiasPotential`

           **Optional arguments:**

           use_comlist
                Boolean indicating whether the comlist should be used for
                adding this ValenceTerm
        '''
        if isinstance(term, ValenceTerm):
            if use_comlist:
                raise NotImplementedError('Cannot use COMList')
                if self.valence_com is None:
                    raise TypeError(
                        "No COMList was provided when setting up the ForcePartBias"
                    )
                self.term_lookup.append((2, self.valence_com.vlist.nv))
                # Keep track of the index this term gets in the ValenceList
                self.valence_com.vlist.add_term(term)
            else:
                self.term_lookup.append((1, self.valence.vlist.nv))
                # Add to the ValenceList
                self.valence.vlist.add_term(term)
            if log.do_high:
                with log.section('BIAS'):
                    log('%7i&%s %s' % (len(self.terms), term.get_log(),
                                       ' '.join(ic.get_log()
                                                for ic in term.ics)))
        elif isinstance(term, BiasPotential):
            self.term_lookup.append((0, len(self.terms)))
            if log.do_high:
                with log.section('BIAS'):
                    log('%7i&%s %s' % (len(self.terms), term.get_log(),
                                       ' '.join(cv.get_log()
                                                for cv in term.cvs)))
        else:
            raise NotImplementedError
        self.terms.append(term)
Example #43
0
File: opt.py Project: tovrstra/yaff
 def propagate(self):
     # Update the Hessian
     assert not self.g is self.g_old
     assert not self.x is self.x_old
     hessian_safe = self.hessian.update(self.x - self.x_old, self.g - self.g_old)
     if not hessian_safe:
         # Reset the Hessian completely
         if log.do_high:
             log("Resetting hessian due to failed update.")
         self.hessian = SR1HessianModel(len(self.x))
         self.trust_radius = self.initial_trust_radius
     # Move new to old
     self.x_old = self.x
     self.f_old = self.f
     self.g_old = self.g
     # Compute a step
     self.x, self.f, self.g = self.make_step()
     return BaseOptimizer.propagate(self)
Example #44
0
File: opt.py Project: boegel/yaff
 def propagate(self):
     # Update the Hessian
     assert not self.g is self.g_old
     assert not self.x is self.x_old
     hessian_safe = self.hessian.update(self.x - self.x_old, self.g - self.g_old)
     if not hessian_safe:
         # Reset the Hessian completely
         if log.do_high:
             log('Resetting hessian due to failed update.')
         self.hessian = SR1HessianModel(len(self.x))
         self.trust_radius = self.initial_trust_radius
     # Move new to old
     self.x_old = self.x
     self.f_old = self.f
     self.g_old = self.g
     # Compute a step
     self.x, self.f, self.g = self.make_step()
     return BaseOptimizer.propagate(self)
Example #45
0
 def __call__(self, iterative):
     if log.do_medium:
         if self.time0 is None:
             self.time0 = time.time()
             if log.do_medium:
                 log.hline()
                 log('Cons.Err. =&the root of the ratio of the variance on the conserved quantity and the variance on the kinetic energy.')
                 log('d-rmsd    =&the root-mean-square displacement of the atoms.')
                 log('g-rmsd    =&the root-mean-square gradient of the energy.')
                 log('counter  Cons.Err.       Temp     d-RMSD     g-RMSD   Walltime')
                 log.hline()
         log('%7i %10.5f %s %s %s %10.1f' % (
             iterative.counter,
             iterative.cons_err,
             log.temperature(iterative.temp),
             log.length(iterative.rmsd_delta),
             log.force(iterative.rmsd_gpos),
             time.time() - self.time0,
         ))
Example #46
0
 def __call__(self):
     """Perform a trial move and calculate the associated energy difference,
     decide whether it is accepted or not, and update the state of the
     MC simulation accordingly
     """
     with timer.section("MC %s move" % self.log_name):
         e = self.compute()
         p = self.probability(e)
         if np.random.rand()>p:
             accepted = False
             self.reject()
         else:
             accepted = True
             self.mc.energy += e
             self.accept()
     if log.do_debug:
         log("MC %s: N = %d energy difference = %s acceptance probability = %6.2f %% accepted = %s"
             % (self.__class__.__name__, self.mc.N, log.energy(e), p*100.0, accepted))
     return accepted
Example #47
0
File: opt.py Project: molmod/yaff
 def __call__(self, iterative):
     if log.do_medium:
         if self.time0 is None:
             self.time0 = time.time()
             if log.do_medium:
                 log.hline()
                 log('Conv.val. =&the highest ratio of a convergence criterion over its threshold.')
                 log('N         =&the number of convergence criteria that is not met.')
                 log('Worst     =&the name of the convergence criterion that is worst.')
                 log('counter  Conv.val.  N           Worst     Energy   Walltime')
                 log.hline()
         log('%7i % 10.3e %2i %15s %s %10.1f' % (
             iterative.counter,
             iterative.dof.conv_val,
             iterative.dof.conv_count,
             iterative.dof.conv_worst,
             log.energy(iterative.epot),
             time.time() - self.time0,
         ))
Example #48
0
    def from_hdf5(cls, f):
        '''Create a system from an HDF5 file/group containing a system group

           **Arguments:**

           f
                An open h5.File object with a system group. The system group
                must at least contain a numbers and pos dataset.
        '''
        sgrp = f['system']
        kwargs = {
            'numbers': sgrp['numbers'][:],
            'pos': sgrp['pos'][:],
        }
        for key in 'scopes', 'scope_ids', 'ffatypes', 'ffatype_ids', 'bonds', 'rvecs', 'charges', 'masses':
            if key in sgrp:
                kwargs[key] = sgrp[key][:]
        if log.do_high:
            log('Read system parameters from %s.' % f.filename)
        return cls(**kwargs)
Example #49
0
File: ff.py Project: molmod/yaff
    def __init__(self, system, comlist=None):
        '''
           Parameters
           ----------

           system
                An instance of the ``System`` class.
           comlist
                An optional layer to derive centers of mass from the atomic positions.
                These centers of mass are used as input for the first layer, the relative
                vectors.
        '''
        ForcePart.__init__(self, 'valence', system)
        self.comlist = comlist
        self.dlist = DeltaList(system if comlist is None else comlist)
        self.iclist = InternalCoordinateList(self.dlist)
        self.vlist = ValenceList(self.iclist)
        if log.do_medium:
            with log.section('FPINIT'):
                log('Force part: %s' % self.name)
                log.hline()
Example #50
0
File: ff.py Project: molmod/yaff
    def __init__(self, system, alpha, gcut=0.35, dielectric=1.0, exclude_frame=False, n_frame=0):
        '''
           **Arguments:**

           system
                The system to which this interaction applies.

           alpha
                The alpha parameter in the Ewald summation method.

           **Optional arguments:**

           gcut
                The cutoff in reciprocal space.

           dielectric
                The scalar relative permittivity of the system.

           exclude_frame
                A boolean to exclude framework-framework interactions
                (exclude_frame=True) for efficiency sake in MC simulations.

           n_frame
                Number of framework atoms. This parameter is used to exclude
                framework-framework neighbors when exclude_frame=True.
        '''
        ForcePart.__init__(self, 'ewald_reci', system)
        if not system.cell.nvec == 3:
            raise TypeError('The system must have a 3D periodic cell.')
        if system.charges is None:
            raise ValueError('The system does not have charges.')
        self.system = system
        self.alpha = alpha
        self.gcut = gcut
        self.dielectric = dielectric
        self.update_gmax()
        self.work = np.empty(system.natom*2)
        if exclude_frame == True and n_frame < 0:
            raise ValueError('The number of framework atoms to exclude must be positive.')
        elif exclude_frame == False:
            n_frame = 0
        self.n_frame = n_frame
        if log.do_medium:
            with log.section('FPINIT'):
                log('Force part: %s' % self.name)
                log.hline()
                log('  alpha:                 %s' % log.invlength(self.alpha))
                log('  gcut:                  %s' % log.invlength(self.gcut))
                log('  relative permittivity: %5.3f' % self.dielectric)
                log.hline()
Example #51
0
 def _init_log(self):
     if log.do_medium:
         log('Unit cell')
         log.hline()
         log('Number of periodic dimensions: %i' % self.cell.nvec)
         lengths, angles = self.cell.parameters
         names = 'abc'
         for i in xrange(len(lengths)):
             log('Cell parameter %5s: %10s' % (names[i], log.length(lengths[i])))
         names = 'alpha', 'beta', 'gamma'
         for i in xrange(len(angles)):
             log('Cell parameter %5s: %10s' % (names[i], log.angle(angles[i])))
         log.hline()
         log.blank()
Example #52
0
 def _init_derived_scopes(self):
     if self.scope_ids is None:
         if len(self.scopes) != self.natom:
             raise TypeError('When the scope_ids are derived automatically, the length of the scopes list must match the number of atoms.')
         lookup = {}
         scopes = []
         self.scope_ids = np.zeros(self.natom, int)
         for i in xrange(self.natom):
             scope = self.scopes[i]
             scope_id = lookup.get(scope)
             if scope_id is None:
                 scope_id = len(scopes)
                 scopes.append(scope)
                 lookup[scope] = scope_id
             self.scope_ids[i] = scope_id
         self.scopes = scopes
     for scope in self.scopes:
         check_name(scope)
     # check the range of the ids
     if self.scope_ids.min() != 0 or self.scope_ids.max() != len(self.scopes)-1:
         raise ValueError('The ffatype_ids have incorrect bounds.')
     if log.do_medium:
         log('The following scopes are present in the system:')
         log.hline()
         log('                 Scope   ID   Number of atoms')
         log.hline()
         for scope_id, scope in enumerate(self.scopes):
             log('%22s  %3i       %3i' % (scope, scope_id, (self.scope_ids==scope_id).sum()))
         log.hline()
         log.blank()
Example #53
0
    def apply(self, par_table, cpar_table, scale_table, system, ff_args):
        # Prepare the atomic parameters
        c6s = np.zeros(system.nffatype, float)
        bs = np.zeros(system.nffatype, float)
        vols = np.zeros(system.nffatype, float)
        for i in xrange(system.nffatype):
            key = (system.ffatypes[i],)
            par_list = par_table.get(key, [])
            if len(par_list) == 0:
                if log.do_warning:
                    log.warn('No DAMPDISP parameters found for atom %i with fftype %s.' % (i, system.get_ffatype(i)))
            else:
                c6s[i], bs[i], vols[i] = par_list[0]

        # Prepare the cross parameters
        c6_cross = np.zeros((system.nffatype, system.nffatype), float)
        b_cross = np.zeros((system.nffatype, system.nffatype), float)
        for i0 in xrange(system.nffatype):
            for i1 in xrange(i0+1):
                cpar_list = cpar_table.get((system.ffatypes[i0], system.ffatypes[i1]), [])
                if len(cpar_list) == 0:
                    if log.do_high:
                        log('No DAMPDISP cross parameters found for ffatypes %s,%s. Mixing rule will be used' % (system.ffatypes[i0], system.ffatypes[i1]))
                else:
                    c6_cross[i0,i1], b_cross[i0,i1] = cpar_list[0]
                    if i0 != i1:
                        c6_cross[i1,i0], b_cross[i1,i0] = cpar_list[0]

        # Prepare the global parameters
        scalings = Scalings(system, scale_table[1], scale_table[2], scale_table[3])

        # Get the part. It should not exist yet.
        part_pair = ff_args.get_part_pair(PairPotDampDisp)
        if part_pair is not None:
            raise RuntimeError('Internal inconsistency: the DAMPDISP part should not be present yet.')

        pair_pot = PairPotDampDisp(system.ffatype_ids, c6_cross, b_cross, ff_args.rcut, ff_args.tr, c6s, bs, vols)
        nlist = ff_args.get_nlist(system)
        part_pair = ForcePartPair(system, nlist, scalings, pair_pot)
        ff_args.parts.append(part_pair)
Example #54
0
    def __init__(self, system, alpha, gcut=0.35):
        '''
           **Arguments:**

           system
                The system to which this interaction applies.

           alpha
                The alpha parameter in the Ewald summation method.

           gcut
                The cutoff in reciprocal space.
        '''
        ForcePart.__init__(self, 'ewald_reci', system)
        if not system.cell.nvec == 3:
            raise TypeError('The system must have a 3D periodic cell.')
        if system.charges is None:
            raise ValueError('The system does not have charges.')
        if system.dipoles is None:
            raise ValueError('The system does not have dipoles.')
        self.system = system
        self.alpha = alpha
        self.gcut = gcut
        self.update_gmax()
        self.work = np.empty(system.natom*2)
        if log.do_medium:
            with log.section('FPINIT'):
                log('Force part: %s' % self.name)
                log.hline()
                log('  alpha:             %s' % log.invlength(self.alpha))
                log('  gcut:              %s' % log.invlength(self.gcut))
                log.hline()
Example #55
0
    def __init__(self, system, alpha, scalings):
        '''
           **Arguments:**

           system
                The system to which this interaction applies.

           alpha
                The alpha parameter in the Ewald summation method.

           scalings
                A ``Scalings`` object. This object contains all the information
                about the energy scaling of pairwise contributions that are
                involved in covalent interactions. See
                :class:`yaff.pes.scalings.Scalings` for more details.
        '''
        ForcePart.__init__(self, 'ewald_cor', system)
        if not system.cell.nvec == 3:
            raise TypeError('The system must have a 3D periodic cell')
        if system.charges is None:
            raise ValueError('The system does not have charges.')
        self.system = system
        self.alpha = alpha
        self.scalings = scalings
        if log.do_medium:
            with log.section('FPINIT'):
                log('Force part: %s' % self.name)
                log.hline()
                log('  alpha:             %s' % log.invlength(self.alpha))
                log('  scalings:          %5.3f %5.3f %5.3f' % (scalings.scale1, scalings.scale2, scalings.scale3))
                log.hline()
Example #56
0
    def __init__(self, system, alpha, dielectric=1.0):
        '''
           **Arguments:**

           system
                The system to which this interaction applies.

           alpha
                The alpha parameter in the Ewald summation method.

           **Optional arguments:**

           dielectric
                The scalar relative permittivity of the system.
        '''
        ForcePart.__init__(self, 'ewald_neut', system)
        if not system.cell.nvec == 3:
            raise TypeError('The system must have a 3D periodic cell')
        if system.charges is None:
            raise ValueError('The system does not have charges.')
        self.system = system
        self.alpha = alpha
        self.dielectric = dielectric
        if log.do_medium:
            with log.section('FPINIT'):
                log('Force part: %s' % self.name)
                log.hline()
                log('  alpha:                   %s' % log.invlength(self.alpha))
                log('  relative permittivity:   %5.3f' % self.dielectric)
                log.hline()
Example #57
0
    def __init__(self, system, nlist, scalings, pair_pot):
        '''
           **Arguments:**

           system
                The system to which this pairwise interaction applies.

           nlist
                A ``NeighborList`` object. This has to be the same as the one
                passed to the ForceField object that contains this part.

           scalings
                A ``Scalings`` object. This object contains all the information
                about the energy scaling of pairwise contributions that are
                involved in covalent interactions. See
                :class:`yaff.pes.scalings.Scalings` for more details.

           pair_pot
                An instance of the ``PairPot`` built-in class from
                :mod:`yaff.pes.ext`.
        '''
        ForcePart.__init__(self, 'pair_%s' % pair_pot.name, system)
        self.nlist = nlist
        self.scalings = scalings
        self.pair_pot = pair_pot
        self.nlist.request_rcut(pair_pot.rcut)
        if log.do_medium:
            with log.section('FPINIT'):
                log('Force part: %s' % self.name)
                log.hline()
                log('  scalings:          %5.3f %5.3f %5.3f' % (scalings.scale1, scalings.scale2, scalings.scale3))
                log('  real space cutoff: %s' % log.length(pair_pot.rcut))
                tr = pair_pot.get_truncation()
                if tr is None:
                    log('  truncation:     none')
                else:
                    log('  truncation:     %s' % tr.get_log())
                self.pair_pot.log()
                log.hline()
Example #58
0
    def __init__(self, system, pext):
        '''
           **Arguments:**

           system
                An instance of the ``System`` class.

           pext
                The external pressure. (Positive will shrink the system.) In
                case of 2D-PBC, this is the surface tension. In case of 1D, this
                is the linear strain.

           This force part is only applicable to systems that are periodic.
        '''
        if system.cell.nvec == 0:
            raise ValueError('The system must be periodic in order to apply a pressure')
        ForcePart.__init__(self, 'press', system)
        self.system = system
        self.pext = pext
        if log.do_medium:
            with log.section('FPINIT'):
                log('Force part: %s' % self.name)
                log.hline()