Exemple #1
0
 def _internal_compute(self, gpos, vtens):
     with timer.section("LAMMPS overhead"):
         self.update_rvecs(self.system.cell.rvecs)
         self.update_pos(self.system.pos.copy())
     with timer.section("LAMMPS"):
         self.lammps.command("run 0 post no")
     with timer.section("LAMMPS overhead"):
         energy = self.lammps.extract_variable("eng",None,0)
         if gpos is not None:
             f = self.lammps.gather_atoms("f",1,3)
             gpos[:] = np.ctypeslib.as_array(f).reshape((-1,3))
             gpos[:] = -np.einsum('ij,kj', gpos, self.rot.transpose())
         if vtens is not None:
             w = self.lammps.extract_compute("virial",0,1)
             vtens_lammps = np.ctypeslib.as_array(w,shape=(6,))
             # Lammps gives the virial per volume in pascal, so we have to
             # multiply with some prefactors
             vtens_lammps[:] *= -pascal*self.system.cell.volume
             # The [6x1] vector has to be cast to a symmetric [3x3] tensor
             # Lammps orders the values as [xx,yy,zz,xy,xz,yz]
             vtens[np.triu_indices(3)] = vtens_lammps[[0,3,4,1,5,2]]
             vtens[np.tril_indices(3)] = vtens_lammps[[0,3,1,4,5,2]]
             # Finally we have to compute the effect of the rotation on the
             # the virial tensor to get the values in Yaff coordinates
             vtens[:] = np.dot(self.rot.transpose(),np.dot(vtens[:],self.rot))
     return energy
Exemple #2
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)
Exemple #3
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)
Exemple #4
0
 def _internal_compute(self, gpos, vtens):
     with timer.section('Valence'):
         self.comlist.forward()
         self.dlist.forward()
         self.iclist.forward()
         energy = 0
         energy += self.vlist.forward()
         if self.term is not None:
             energy += self.term.compute()
         if not ((gpos is None) and (vtens is None)):
             #print('AA gpos before bias: ', gpos[:3])
             self.vlist.back()
             self.iclist.back()
             self.comlist.gpos[:] = 0.0
             self.dlist.back(self.comlist.gpos, vtens)
             if self.term is not None and vtens is not None:
                 my_vtens = np.zeros((3, 3))
                 self.term.compute(np.zeros((3, 3)), my_vtens)
                 vtens += my_vtens
             energy = self._scale(self.comlist.gpos, vtens, energy)
             #print('COM bias energy: ', energy / molmod.units.kjmol)
             self.comlist.back(gpos)
             #print('ValenceCOM gpos after bias: ', gpos[:3])
         else:
             energy = self._scale(None, None, energy)
         #print('compos 0: ', self.comlist.pos[0, :])
         #print('vtab: ', self.vlist.vtab)
         #print('ValenceCOM energy: ', energy)
         return energy
Exemple #5
0
 def _internal_compute(self, gpos, vtens):
     with timer.section('PLUMED'):
         self.plumed.cmd("setStep", self.plumedstep)
         self.plumed.cmd("setPositions", self.system.pos)
         self.plumed.cmd("setMasses", self.system.masses)
         if self.system.charges is not None:
             self.plumed.cmd("setCharges", self.system.charges)
         if self.system.cell.nvec > 0:
             rvecs = self.system.cell.rvecs.copy()
             self.plumed.cmd("setBox", rvecs)
         # PLUMED always needs arrays to write forces and virial to, so
         # provide dummy arrays if Yaff does not provide them
         # Note that gpos and forces differ by a minus sign, which has to be
         # corrected for when interacting with PLUMED
         if gpos is None:
             my_gpos = np.zeros(self.system.pos.shape)
         else:
             gpos[:] *= -1.0
             my_gpos = gpos
         self.plumed.cmd("setForces", my_gpos)
         if vtens is None:
             my_vtens = np.zeros((3, 3))
         else:
             my_vtens = vtens
         self.plumed.cmd("setVirial", my_vtens)
         # Do the actual calculation, without an update; this should
         # only be done at the end of a time step
         self.plumed.cmd("prepareCalc")
         self.plumed.cmd("performCalcNoUpdate")
         if gpos is not None:
             gpos[:] *= -1.0
         # Retrieve biasing energy
         energy = np.zeros((1, ))
         self.plumed.cmd("getBias", energy)
         return energy[0]
Exemple #6
0
 def _internal_compute(self, gpos, vtens):
     with timer.section('Ewald neut.'):
         #TODO: interaction of dipoles with background? I think this is zero, need proof...
         fac = self.system.charges.sum()**2*np.pi/(2.0*self.system.cell.volume*self.alpha**2)/self.dielectric
         if self.system.radii is not None:
             fac -= self.system.charges.sum()*np.pi/(2.0*self.system.cell.volume)*np.sum( self.system.charges*self.system.radii**2 )/self.dielectric
         if vtens is not None:
             vtens.ravel()[::4] -= fac
         return fac
Exemple #7
0
 def call_hooks(self):
     with timer.section('%s hooks' % self.log_name):
         state_updated = False
         for hook in self.hooks:
             if hook.expects_call(self.counter):
                 if not state_updated:
                     for item in self.state_list:
                         item.update(self)
                     state_updated = True
                 hook(self)
Exemple #8
0
 def _internal_compute(self, gpos, vtens):
     with timer.section('Valence'):
         self.dlist.forward()
         self.iclist.forward()
         energy = self.vlist.forward()
         if not ((gpos is None) and (vtens is None)):
             self.vlist.back()
             self.iclist.back()
             self.dlist.back(gpos, vtens)
         return energy
Exemple #9
0
 def _internal_compute(self, gpos, vtens):
     with timer.section('Valence'):
         self.dlist.forward()
         self.iclist.forward()
         energy = self.vlist.forward()
         if not ((gpos is None) and (vtens is None)):
             self.vlist.back()
             self.iclist.back()
             self.dlist.back(gpos, vtens)
         return energy
Exemple #10
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')
Exemple #11
0
 def run(self):
     # Run indefinitely (until i-PI sends exit message)
     while True:
         with timer.section("WAITHEADER"):
             # log("WAITHEADER %s" % datetime.now())
             header = self.s.await_header()
             # log("GOTHEADER %s" % datetime.now())
         if header == Message("status"):
             if not self.isinit:
                 self.s.send_header(Message("needinit"))
             elif self.hasdata:
                 self.s.send_header(Message("havedata"))
             else:
                 self.s.send_header(Message("ready"))
         elif header == Message("init"):
             # ibead = np.fromstring(self.s.await_data(L_INT), np.int32)[0]
             # len_init = np.fromstring(self.s.await_data(L_INT), np.int32)[0]
             # init = self.s.await_data(len_init * L_CHAR)
             if log.do_high:
                 with log.section(self.log_name):
                     # log( "YAFF driver initialized for pid %s (bead %d - %s)" % (os.getpid(), ibead, init) )
                     log("INIT %s" % datetime.now())
             self.isinit = True
         elif header == Message("posdata"):
             with timer.section("RECVPOS"), log.section(self.log_name):
                 self.receive_pos()
                 log("RECV %-12s %s" % ("POS", datetime.now()))
             with timer.section("COMPUTE"):
                 self.compute()
         elif header == Message("getforce"):
             with timer.section("SENDFORCE"), log.section(self.log_name):
                 self.send_forces()
                 log("SEND %-12s %s" % ("FORCE", datetime.now()))
         elif header == Message("exit"):
             if log.do_high:
                 with log.section(self.log_name):
                     # log('i-PI finished, stopping Yaff driver')
                     log("EXIT %s" % datetime.now())
             break
         else:
             raise NotImplementedError("Received unknown message %s" %
                                       header)
Exemple #12
0
 def run(self, nstep=None):
     with log.section(self.log_name), timer.section(self.log_name):
         if nstep is None:
             while True:
                 if self.propagate():
                     break
         else:
             for i in xrange(nstep):
                 if self.propagate():
                     break
         self.finalize()
Exemple #13
0
 def run(self, nstep=None):
     with log.section(self.log_name), timer.section(self.log_name):
         if nstep is None:
             while True:
                 if self.propagate():
                     break
         else:
             for i in range(nstep):
                 if self.propagate():
                     break
         self.finalize()
Exemple #14
0
 def call_hooks(self):
     # Initialize hooks
     with timer.section('%s hooks' % self.log_name):
         state_updated = False
         for hook in self.hooks:
             if hook.expects_call(self.counter):
                 if not state_updated:
                     for item in self.state_list:
                         item.update(self)
                     state_updated = True
                 hook(self)
Exemple #15
0
 def _internal_compute(self, gpos, vtens):
     with timer.section('Grid'):
         if gpos is not None:
             raise NotImplementedError('Cartesian gradients are not supported yet in ForcePartGrid')
         if vtens is not None:
             raise NotImplementedError('Cell deformation are not supported by ForcePartGrid')
         cell = self.system.cell
         result = 0
         for i in xrange(self.system.natom):
             grid = self.grids[self.system.get_ffatype(i)]
             result += compute_grid3d(self.system.pos[i], cell, grid)
         return result
Exemple #16
0
    def __init__(self, ff, state=None, hooks=None, counter0=0):
        """
           **Arguments:**

           ff
                The ForceField instance used in the iterative algorithm

           **Optional arguments:**

           state
                A list with state items. State items are simple objects
                that take or derive a property from the current state of the
                iterative algorithm.

           hooks
                A function (or a list of functions) that is called after every
                iterative.

           counter0
                The counter value associated with the initial state.
        """
        self.ff = ff
        if state is None:
            self.state_list = [
                state_item.copy() for state_item in self.default_state
            ]
        else:
            #self.state_list = state
            self.state_list = [
                state_item.copy() for state_item in self.default_state
            ]
            self.state_list += state
        self.state = dict((item.key, item) for item in self.state_list)
        if hooks is None:
            self.hooks = []
        elif hasattr(hooks, '__len__'):
            self.hooks = hooks
        else:
            self.hooks = [hooks]
        self._add_default_hooks()
        self.counter0 = counter0
        self.counter = counter0
        with log.section(self.log_name), timer.section(self.log_name):
            self.initialize()

        # Initialize restart hook if present
        from yaff.sampling.io import RestartWriter
        for hook in self.hooks:
            if isinstance(hook, RestartWriter):
                hook.init_state(self)
Exemple #17
0
 def call_hooks(self):
     with timer.section('%s hooks' % self.log_name):
         state_updated = False
         from yaff.sampling.io import RestartWriter
         for hook in self.hooks:
             if hook.expects_call(self.counter) and not (isinstance(hook, RestartWriter) and self.counter==self.counter0):
                 if not state_updated:
                     for item in self.state_list:
                         item.update(self)
                     state_updated = True
                 if isinstance(hook, RestartWriter):
                     for item in hook.state_list:
                         item.update(self)
                 hook(self)
Exemple #18
0
 def call_hooks(self):
     with timer.section('%s hooks' % self.log_name):
         state_updated = False
         from yaff.sampling.io import RestartWriter
         for hook in self.hooks:
             if hook.expects_call(self.counter) and not (isinstance(hook, RestartWriter) and self.counter==self.counter0):
                 if not state_updated:
                     for item in self.state_list:
                         item.update(self)
                     state_updated = True
                 if isinstance(hook, RestartWriter):
                     for item in hook.state_list:
                         item.update(self)
                 hook(self)
Exemple #19
0
 def _internal_compute(self, gpos, vtens):
     with timer.section('Ewald neut.'):
         #TODO: interaction of dipoles with background? I think this is zero, need proof...
         fac = self.system.charges.sum()**2 * np.pi / (
             2.0 * self.system.cell.volume *
             self.alpha**2) / self.dielectric
         if self.system.radii is not None:
             fac -= self.system.charges.sum() * np.pi / (
                 2.0 * self.system.cell.volume) * np.sum(
                     self.system.charges *
                     self.system.radii**2) / self.dielectric
         if vtens is not None:
             vtens.ravel()[::4] -= fac
         return fac
Exemple #20
0
 def _internal_compute(self, gpos, vtens):
     with timer.section("LAMMPS overhead"):
         self.update_rvecs(self.system.cell.rvecs)
         self.update_pos(self.system.pos.copy())
     with timer.section("LAMMPS"):
         self.lammps.command("run 0 post no")
     with timer.section("LAMMPS overhead"):
         energy = self.lammps.extract_variable("eng", None, 0)
         if gpos is not None:
             f = self.lammps.gather_atoms("f", 1, 3)
             buffer = np.core.multiarray.int_asbuffer(
                 ctypes.addressof(f), 8 * 3 * self.system.natom)
             gpos[:] = np.frombuffer(buffer, float).reshape((-1, 3))
             #                for iatom in xrange(self.system.natom):
             #                    for j in xrange(3):
             #                        gpos[iatom,j] = f[3*iatom+j]
             gpos[:] = -np.einsum('ij,kj', gpos, self.rot.transpose())
         if vtens is not None:
             w = self.lammps.extract_compute("virial", 0, 1)
             buffer = np.core.multiarray.int_asbuffer(
                 ctypes.addressof(w.contents), 8 * 6)
             vtens_lammps = np.frombuffer(buffer, float)
             #                vtens_lammps = np.zeros(6)
             #                for i in xrange(6):
             #                    vtens_lammps[i] = w[i]
             # Lammps gives the virial per volume in pascal, so we have to
             # multiply with some prefactors
             vtens_lammps[:] *= -pascal * self.system.cell.volume
             # The [6x1] vector has to be cast to a symmetric [3x3] tensor
             # Lammps orders the values as [xx,yy,zz,xy,xz,yz]
             vtens[np.triu_indices(3)] = vtens_lammps[[0, 3, 4, 1, 5, 2]]
             vtens[np.tril_indices(3)] = vtens_lammps[[0, 3, 1, 4, 5, 2]]
             # Finally we have to compute the effect of the rotation on the
             # the virial tensor to get the values in Yaff coordinates
             vtens[:] = np.dot(self.rot.transpose(),
                               np.dot(vtens[:], self.rot))
     return energy
Exemple #21
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')
Exemple #22
0
 def _internal_compute(self, gpos, vtens):
     with timer.section('Grid'):
         if gpos is not None:
             raise NotImplementedError(
                 'Cartesian gradients are not supported yet in ForcePartGrid'
             )
         if vtens is not None:
             raise NotImplementedError(
                 'Cell deformation are not supported by ForcePartGrid')
         cell = self.system.cell
         result = 0
         for i in range(self.system.natom):
             grid = self.grids[self.system.get_ffatype(i)]
             result += compute_grid3d(self.system.pos[i], cell, grid)
         return result
Exemple #23
0
 def call_verlet_hooks(self, kind):
     # In this call, the state items are not updated. The pre and post calls
     # of the verlet hooks can rely on the specific implementation of the
     # VerletIntegrator and need not to rely on the generic state item
     # interface.
     with timer.section('%s special hooks' % self.log_name):
         for hook in self.hooks:
             if isinstance(hook, VerletHook) and hook.expects_call(self.counter):
                 if kind == 'init':
                     hook.init(self)
                 elif kind == 'pre':
                     hook.pre(self)
                 elif kind == 'post':
                     hook.post(self)
                 else:
                     raise NotImplementedError
Exemple #24
0
    def __init__(self, ff, state=None, hooks=None, counter0=0):
        """
           **Arguments:**

           ff
                The ForceField instance used in the iterative algorithm

           **Optional arguments:**

           state
                A list with state items. State items are simple objects
                that take or derive a property from the current state of the
                iterative algorithm.

           hooks
                A function (or a list of functions) that is called after every
                iterative.

           counter0
                The counter value associated with the initial state.
        """
        self.ff = ff
        if state is None:
            self.state_list = [state_item.copy() for state_item in self.default_state]
        else:
            #self.state_list = state
            self.state_list = [state_item.copy() for state_item in self.default_state]
            self.state_list += state
        self.state = dict((item.key, item) for item in self.state_list)
        if hooks is None:
            self.hooks = []
        elif hasattr(hooks, '__len__'):
            self.hooks = hooks
        else:
            self.hooks = [hooks]
        self._add_default_hooks()
        self.counter0 = counter0
        self.counter = counter0
        with log.section(self.log_name), timer.section(self.log_name):
            self.initialize()

        # Initialize restart hook if present
        from yaff.sampling.io import RestartWriter
        for hook in self.hooks:
            if isinstance(hook, RestartWriter):
                hook.init_state(self)
Exemple #25
0
 def call_verlet_hooks(self, kind):
     from yaff.sampling.npt import BerendsenBarostat, TBCombination
     # In this call, the state items are not updated. The pre and post calls
     # of the verlet hooks can rely on the specific implementation of the
     # VerletIntegrator and need not to rely on the generic state item
     # interface.
     with timer.section('%s special hooks' % self.log_name):
         for hook in self.hooks:
             if isinstance(hook, VerletHook) and hook.expects_call(
                     self.counter):
                 if kind == 'init':
                     hook.init(self)
                 elif kind == 'pre':
                     hook.pre(self)
                 elif kind == 'post':
                     hook.post(self)
                 else:
                     raise NotImplementedError
Exemple #26
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
Exemple #27
0
 def _internal_compute(self, gpos, vtens):
     with timer.section('Valence'):
         cell = self.system.cell
         if (vtens is not None):
             rvecs = cell.rvecs
             if cell.nvec == 1:
                 vtens += self.pext/cell.volume*np.outer(rvecs[0], rvecs[0])
             elif cell.nvec == 2:
                 vtens += self.pext/cell.volume*(
                       np.dot(rvecs[0], rvecs[0])*np.outer(rvecs[1], rvecs[1])
                     + np.dot(rvecs[0], rvecs[0])*np.outer(rvecs[1], rvecs[1])
                     - np.dot(rvecs[1], rvecs[0])*np.outer(rvecs[0], rvecs[1])
                     - np.dot(rvecs[0], rvecs[1])*np.outer(rvecs[1], rvecs[0])
                 )
             elif cell.nvec == 3:
                 gvecs = cell.gvecs
                 vtens += self.pext*cell.volume*np.identity(3)
             else:
                 raise NotImplementedError
         return cell.volume*self.pext
Exemple #28
0
 def _internal_compute(self, gpos, vtens):
     with timer.section('Bias'):
         energy = 0.0
         # ValenceTerms
         energy += self.valence._internal_compute(gpos, vtens)
         #if self.valence_com is not None:
         #    energy += self.valence_com._internal_compute(gpos, vtens)
         # BiasPotentials
         if gpos is None:
             my_gpos = None
         else:
             my_gpos = np.zeros((self.system.natom, 3))
         if vtens is None:
             my_vtens = None
         else:
             my_vtens = np.zeros((3, 3))
         for term in self.terms:
             if isinstance(term, ValenceTerm): continue
             energy += term.compute(gpos=my_gpos, vtens=my_vtens)
             if gpos is not None: gpos[:] += my_gpos
             if vtens is not None: vtens[:] += my_vtens
         return energy
Exemple #29
0
 def _internal_compute(self, gpos, vtens):
     with timer.section('Valence'):
         cell = self.system.cell
         if (vtens is not None):
             rvecs = cell.rvecs
             if cell.nvec == 1:
                 vtens += self.pext / cell.volume * np.outer(
                     rvecs[0], rvecs[0])
             elif cell.nvec == 2:
                 vtens += self.pext / cell.volume * (
                     np.dot(rvecs[0], rvecs[0]) * np.outer(
                         rvecs[1], rvecs[1]) + np.dot(rvecs[0], rvecs[0]) *
                     np.outer(rvecs[1], rvecs[1]) -
                     np.dot(rvecs[1], rvecs[0]) * np.outer(
                         rvecs[0], rvecs[1]) - np.dot(rvecs[0], rvecs[1]) *
                     np.outer(rvecs[1], rvecs[0]))
             elif cell.nvec == 3:
                 gvecs = cell.gvecs
                 vtens += self.pext * cell.volume * np.identity(3)
             else:
                 raise NotImplementedError
         return cell.volume * self.pext
Exemple #30
0
def estimate_hessian(dof, eps=1e-4):
    """Estimate the Hessian using the symmetric finite difference approximation.

       **Arguments:**

       dof
            A DOF object

       **Optional arguments:**

       eps
            The magnitude of the displacements
    """
    with log.section('HESS'), timer.section('Hessian'):
        # Loop over all displacements
        if log.do_medium:
            log('The following displacements are computed:')
            log('DOF     Dir Energy')
            log.hline()
        x1 = dof.x0.copy()
        rows = np.zeros((len(x1), len(x1)), float)
        for i in xrange(len(x1)):
            x1[i] = dof.x0[i] + eps
            epot, gradient_p = dof.fun(x1, do_gradient=True)
            if log.do_medium:
                log('% 7i pos %s' % (i, log.energy(epot)))
            x1[i] = dof.x0[i] - eps
            epot, gradient_m = dof.fun(x1, do_gradient=True)
            if log.do_medium:
                log('% 7i neg %s' % (i, log.energy(epot)))
            rows[i] = (gradient_p - gradient_m) / (2 * eps)
            x1[i] = dof.x0[i]
        dof.reset()
        if log.do_medium:
            log.hline()

        # Enforce symmetry and return
        return 0.5 * (rows + rows.T)
Exemple #31
0
def estimate_hessian(dof, eps=1e-4):
    """Estimate the Hessian using the symmetric finite difference approximation.

       **Arguments:**

       dof
            A DOF object

       **Optional arguments:**

       eps
            The magnitude of the displacements
    """
    with log.section('HESS'), timer.section('Hessian'):
        # Loop over all displacements
        if log.do_medium:
            log('The following displacements are computed:')
            log('DOF     Dir Energy')
            log.hline()
        x1 = dof.x0.copy()
        rows = np.zeros((len(x1), len(x1)), float)
        for i in xrange(len(x1)):
            x1[i] = dof.x0[i] + eps
            epot, gradient_p = dof.fun(x1, do_gradient=True)
            if log.do_medium:
                log('% 7i pos %s' % (i, log.energy(epot)))
            x1[i] = dof.x0[i] - eps
            epot, gradient_m = dof.fun(x1, do_gradient=True)
            if log.do_medium:
                log('% 7i neg %s' % (i, log.energy(epot)))
            rows[i] = (gradient_p-gradient_m)/(2*eps)
            x1[i] = dof.x0[i]
        dof.reset()
        if log.do_medium:
            log.hline()

        # Enforce symmetry and return
        return 0.5*(rows + rows.T)
Exemple #32
0
 def _internal_compute(self, gpos, vtens):
     with timer.section('Ewald reci.'):
         return compute_ewald_reci(
             self.system.pos, self.system.charges, self.system.cell, self.alpha,
             self.gmax, self.gcut, self.dielectric, gpos, self.work, vtens, self.n_frame
         )
Exemple #33
0
 def _internal_compute(self, gpos, vtens):
     with timer.section('Ewald reci.'):
         return compute_ewald_reci(self.system.pos, self.system.charges,
                                   self.system.cell, self.alpha, self.gmax,
                                   self.gcut, self.dielectric, gpos,
                                   self.work, vtens)
Exemple #34
0
 def _internal_compute(self, gpos, vtens):
     with timer.section('Ewald corr.'):
         return compute_ewald_corr_dd(self.system.pos, self.system.charges,
                                      self.system.dipoles, self.system.cell,
                                      self.alpha, self.scalings.stab, gpos,
                                      vtens)
Exemple #35
0
 def _internal_compute(self, gpos, vtens):
     with timer.section('Ewald reci.'):
         return compute_ewald_reci_dd(
             self.system.pos, self.system.charges, self.system.dipoles, self.system.cell, self.alpha,
             self.gmax, self.gcut, gpos, self.work, vtens
         )
Exemple #36
0
 def _internal_compute(self, gpos, vtens):
     with timer.section('PP %s' % self.pair_pot.name):
         return self.pair_pot.compute(self.nlist.neighs, self.scalings.stab, gpos, vtens, self.nlist.nneigh)
Exemple #37
0
 def _internal_compute(self, gpos, vtens):
     with timer.section('PP %s' % self.pair_pot.name):
         return self.pair_pot.compute(self.nlist.neighs, self.scalings.stab,
                                      gpos, vtens, self.nlist.nneigh)
Exemple #38
0
 def _internal_compute(self, gpos, vtens):
     with timer.section('Ewald corr.'):
         return compute_ewald_corr_dd(
             self.system.pos, self.system.charges, self.system.dipoles, self.system.cell,
             self.alpha, self.scalings.stab, gpos, vtens
         )
Exemple #39
0
    def run(self, nsteps, mc_moves=None, initial=None, einit=0,
                translation_stepsize=1.0*angstrom,
                volumechange_stepsize=10.0*angstrom**3,
                close_contact=0.4*angstrom):
        """
           Perform Monte-Carlo steps

           **Arguments:**

           nsteps
                Number of Monte-Carlo steps

           **Optional Arguments:**

           mc_moves
                Dictionary containing relative probabilities of the different
                Monte-Carlo moves. It is not required that the probabilities
                sum to 1, they are normalized automatically. Example

           initial
                System instance describing the initial configuration of guest
                molecules

           einit
                The energy of the initial state

           translation_stepsize
                The maximal magnitude of a TrialTranslation

           volumechange_stepsize
                The maximal magnitude of a TrialVolumechange

           close_contact
                Automatically reject TrialMove if atoms are placed shorter
                than this distance apart
        """
        if log.do_warning:
            log.warn("Currently, Yaff does not consider interactions of a guest molecule "
                     "with its periodic images in MC simulations. Make sure that you choose a system size "
                     "that is large compared to the guest dimensions, so it is indeed "
                     "acceptable to neglect these interactions.")
        with log.section(self.log_name), timer.section(self.log_name):
            # Initialization
            self.translation_stepsize = translation_stepsize
            self.volumechange_stepsize = volumechange_stepsize
            self.close_contact = close_contact
            if initial is not None:
                self.N = initial.natom//self.guest.natom
                assert self.guest.natom*self.N==initial.natom, ("Initial configuration does not contain correct number of atoms")
                self.current_configuration = initial
                self.get_ff(self.N).system.pos[:] = initial.pos
                if self.ewald_reci is not None:
                    self.ewald_reci.compute_structurefactors(
                        initial.pos,
                        initial.charges,
                        self.ewald_reci.cosfacs, self.ewald_reci.sinfacs)
            else:
                self.current_configuration = self.get_ff(self.N).system
            self.energy = einit
            if not self.conditions_set:
                raise ValueError("External conditions have not been set!")
            # Normalized probabilities and accompanying methods specifying the trial MC moves
            # Trial moves are sorted alphabetically
            if mc_moves is None: mc_moves = self.default_trials
            trials, probabilities = [], []
            for t in sorted(mc_moves.keys()):
                if not t in self.allowed_trials:
                    raise ValueError("Trial move %s not allowed!"%t)
                trial = getattr(mctrials,"Trial"+t.capitalize(),None)
                if trial is None:
                    raise NotImplementedError("The requested trial move %s is not implemented"%(t))
                # Trials is a list containing instances of Trial classes from the mctrials module
                trials.append(trial(self))
                probabilities.append(mc_moves[t])
            probabilities = np.asarray(probabilities)
            probabilities /= np.sum(probabilities)
            assert np.all(probabilities>=0.0), "Negative probabilities are not allowed!"
            # Take the cumulative sum, makes it a bit easier to determine which MC move is selected
            probabilities = np.cumsum(probabilities)
            # Array to keep track of accepted (1st column) and tried (2nd column)
            # moves, with rows corresponding to different possible moves
            acceptance = np.zeros((len(trials),2), dtype=int)
            # Start performing MC moves
            self.Nmean = self.N
            self.emean = self.energy
            self.Vmean = self.current_configuration.cell.volume
            self.counter = 0
            self.call_hooks()
            for istep in range(nsteps):
                switch = np.random.rand()
                # Select one of the possible MC moves
                imove = np.where(switch<probabilities)[0][0]
                # Call the corresponding method
                accepted = trials[imove]()
                # Update records with accepted and tried MC moves
                acceptance[imove,1] += 1
                if accepted: acceptance[imove,0] += 1
                self.counter += 1
                self.Nmean += (self.N-self.Nmean)/self.counter
                self.emean += (self.energy-self.emean)/self.counter
                self.Vmean += (self.current_configuration.cell.volume-self.Vmean)/self.counter
                self.call_hooks()
            return acceptance
Exemple #40
0
 def _internal_compute(self, gpos, vtens):
     with timer.section('Ewald reci.'):
         return compute_ewald_reci_dd(self.system.pos, self.system.charges,
                                      self.system.dipoles, self.system.cell,
                                      self.alpha, self.gmax, self.gcut,
                                      gpos, self.work, vtens, self.n_frame)