示例#1
0
def print_pdb(atoms, cell, filedesc=sys.stdout, title=""):
    """Prints an atomic configuration into a pdb formatted file.

    Also prints the cell parameters in standard pdb form. Note
    that the angles are in degrees.

    Args:
        atoms: An atoms object giving the atom positions.
        cell: A cell object giving the system box.
        filedesc: An open writable file object. Defaults to standard output.
        title: An optional string of max. 70 characters.
    """

    fmt_cryst = "CRYST1%9.3f%9.3f%9.3f%7.2f%7.2f%7.2f%s%4i\n"
    fmt_atom = "ATOM  %5i %4s%1s%3s %1s%4i%1s   %8.3f%8.3f%8.3f%6.2f%6.2f          %2s%2i\n"

    if title != "":
        filedesc.write("TITLE   %70s\n" % (title))

    a, b, c, alpha, beta, gamma = mt.h2abc_deg(cell.h)

    z = 1
    filedesc.write(fmt_cryst %
                   (a, b, c, alpha, beta, gamma, " P 1        ", z))

    natoms = atoms.natoms
    qs = depstrip(atoms.q)
    lab = depstrip(atoms.names)
    for i in range(natoms):
        data = (i + 1, lab[i], ' ', '  1', ' ', 1, ' ', qs[3 * i],
                qs[3 * i + 1], qs[3 * i + 2], 0.0, 0.0, '  ', 0)
        filedesc.write(fmt_atom % data)

    filedesc.write("END\n")
示例#2
0
    def queue(self, atoms, cell, reqid=-1):
        """Adds a request.

        Note that the pars dictionary need to be sent as a string of a
        standard format so that the initialisation of the driver can be done.

        Args:
            atoms: An Atoms object giving the atom positions.
            cell: A Cell object giving the system box.
            pars: An optional dictionary giving the parameters to be sent to the
                driver for initialisation. Defaults to {}.
            reqid: An optional integer that identifies requests of the same type,
               e.g. the bead index

        Returns:
            A list giving the status of the request of the form {'pos': An array
            giving the atom positions folded back into the unit cell,
            'cell': Cell object giving the system box, 'pars': parameter string,
            'result': holds the result as a list once the computation is done,
            'status': a string labelling the status of the calculation,
            'id': the id of the request, usually the bead number, 'start':
            the starting time for the calculation, used to check for timeouts.}.
        """

        par_str = " "

        if not self.pars is None:
            for k, v in self.pars.items():
                par_str += k + " : " + str(v) + " , "
        else:
            par_str = " "

        pbcpos = depstrip(atoms.q).copy()
        pbcpos2 = depstrip(atoms.q).copy()
        if self.dopbc:
            cell.array_pbc(pbcpos)

        newreq = ForceRequest({
            "id":
            reqid,
            "pos":
            pbcpos,
            "cell": (depstrip(cell.h).copy(), depstrip(cell.ih).copy()),
            "pars":
            par_str,
            "result":
            None,
            "status":
            "Queued",
            "start":
            -1
        })

        self._threadlock.acquire()
        try:
            self.requests.append(newreq)
        finally:
            self._threadlock.release()

        return newreq
示例#3
0
def print_xyz_path(beads, cell, filedesc=sys.stdout):
    """Prints all the bead configurations, into a xyz formatted file.

   Prints all the replicas for each time step separately, rather than all at
   once.

   Args:
      beads: A beads object giving the bead positions.
      cell: A cell object giving the system box.
      filedesc: An open writable file object. Defaults to standard output.
   """

    a, b, c, alpha, beta, gamma = mt.h2abc_deg(cell.h)

    natoms = beads.natoms
    nbeads = beads.nbeads
    for j in range(nbeads):
        filedesc.write(
            "%d\n# bead: %d CELL(abcABC): %10.5f  %10.5f  %10.5f  %10.5f  %10.5f  %10.5f \n"
            % (natoms, j, a, b, c, alpha, beta, gamma))
        for i in range(natoms):
            qs = depstrip(beads.q)
            lab = depstrip(beads.names)
            filedesc.write(
                "%8s %12.5e %12.5e %12.5e\n" %
                (lab[i], qs[j][3 * i], qs[j][3 * i + 1], qs[j][3 * i + 2]))
示例#4
0
    def step(self, step=None):
        """ Does one simulation time step
            Attributes:
            ttime: The time taken in applying the thermostat steps.
        """

        self.qtime = -time.time()
        info("\nMD STEP %d" % step, verbosity.debug)

        # Store previous forces for warning exit condition
        self.old_f[:] = self.forces.f

        dq1 = depstrip(self.forces.f)

        # Move direction for steepest descent
        dq1_unit = dq1 / np.sqrt(np.dot(dq1.flatten(), dq1.flatten()))
        info(" @GEOP: Determined SD direction", verbosity.debug)

        #Check for fixatoms
        if len(self.fixatoms) > 0:
            for dqb in dq1_unit:
                dqb[self.fixatoms * 3] = 0.0
                dqb[self.fixatoms * 3 + 1] = 0.0
                dqb[self.fixatoms * 3 + 2] = 0.0

        #Set position and direction inside the mapper
        self.lm.set_dir(depstrip(self.beads.q), dq1_unit)

        # Reuse initial value since we have energy and forces already
        u0, du0 = (self.forces.pot.copy(),
                   np.dot(depstrip(self.forces.f.flatten()),
                          dq1_unit.flatten()))

        # Do one SD iteration; return positions and energy
        #(x, fx,dfx) = min_brent(self.lm, fdf0=(u0, du0), x0=0.0,  #DELETE
        min_brent(self.lm,
                  fdf0=(u0, du0),
                  x0=0.0,
                  tol=self.ls_options["tolerance"] * self.tolerances["energy"],
                  itmax=self.ls_options["iter"],
                  init_step=self.ls_options["step"])
        info("   Number of force calls: %d" % (self.lm.fcount))
        self.lm.fcount = 0

        #Update positions and forces
        self.beads.q = self.lm.dbeads.q
        self.forces.transfer_forces(
            self.lm.dforces)  #This forces the update of the forces

        d_x = np.absolute(np.subtract(self.beads.q, self.lm.x0))
        x = np.linalg.norm(d_x)
        # Automatically adapt the search step for the next iteration.
        # Relaxes better with very small step --> multiply by factor of 0.1 or 0.01

        self.ls_options["step"] = 0.1 * x * self.ls_options["adaptive"] + (
            1 - self.ls_options["adaptive"]) * self.ls_options["step"]

        # Exit simulation step
        d_x_max = np.amax(np.absolute(d_x))
        self.exitstep(self.forces.pot, u0, d_x_max)
示例#5
0
def print_pdb(atoms, cell, filedesc = sys.stdout, title=""):
   """Prints the atom configurations, into a pdb formatted file.

   Also prints the cell parameters in standard pdb form. Note
   that the angles are in degrees.

   Args:
      atoms: An atoms object giving the atom positions.
      cell: A cell object giving the system box.
      filedesc: An open writable file object. Defaults to standard output.
      title: An optional string of max. 70 characters.
   """


   if title != "" :
      filedesc.write("TITLE   %70s\n" % (title))

   a, b, c, alpha, beta, gamma = mt.h2abc_deg(cell.h)

   z = 1
   filedesc.write("CRYST1%9.3f%9.3f%9.3f%7.2f%7.2f%7.2f%s%4i\n" % (a, b, c, alpha, beta, gamma, " P 1        ", z))

   natoms = atoms.natoms
   qs = depstrip(atoms.q)
   lab = depstrip(atoms.names)
   for i in range(natoms):
      filedesc.write("ATOM  %5i %4s%1s%3s %1s%4i%1s   %8.3f%8.3f%8.3f%6.2f%6.2f          %2s%2i\n" % (i+1, lab[i], ' ', '  1', ' ', 1, ' ', qs[3*i], qs[3*i+1], qs[3*i+2], 0.0, 0.0, '  ', 0))

   filedesc.write("END\n")
示例#6
0
def print_pdb_path(beads, cell, filedesc = sys.stdout):
   """Prints all the bead configurations, into a pdb formatted file.

   Prints the ring polymer springs as well as the bead positions using the
   CONECT command. Also prints the cell parameters in standard pdb form. Note
   that the angles are in degrees.

   Args:
      beads: A beads object giving the bead positions.
      cell: A cell object giving the system box.
      filedesc: An open writable file object. Defaults to standard output.
   """

   a, b, c, alpha, beta, gamma = mt.h2abc_deg(cell.h)

   z = 1 #What even is this parameter?
   filedesc.write("CRYST1%9.3f%9.3f%9.3f%7.2f%7.2f%7.2f%s%4i\n" % (a, b, c, alpha, beta, gamma, " P 1        ", z))

   natoms = beads.natoms
   nbeads = beads.nbeads
   for j in range(nbeads):
      for i in range(natoms):
         qs = depstrip(beads.q)
         lab = depstrip(beads.names)
         filedesc.write("ATOM  %5i %4s%1s%3s %1s%4i%1s   %8.3f%8.3f%8.3f%6.2f%6.2f          %2s%2i\n" % (j*natoms+i+1, lab[i],' ','  1',' ',1,' ', qs[j][3*i], qs[j][3*i+1], qs[j][3*i+2],0.0,0.0,'  ',0))

   if nbeads > 1:
      for i in range(natoms):
         filedesc.write("CONECT%5i%5i\n" % (i+1, (nbeads-1)*natoms+i+1))
      for j in range(nbeads-1):
         for i in range(natoms):
            filedesc.write("CONECT%5i%5i\n" % (j*natoms+i+1, (j+1)*natoms+i+1))

   filedesc.write("END\n")
示例#7
0
def print_xyz_path(beads, cell, filedesc=sys.stdout):
    """Prints all the bead configurations, into a xyz formatted file.

   Prints all the replicas for each time step separately, rather than all at
   once.

   Args:
      beads: A beads object giving the bead positions.
      cell: A cell object giving the system box.
      filedesc: An open writable file object. Defaults to standard output.
   """

    a, b, c, alpha, beta, gamma = mt.h2abc_deg(cell.h)

    natoms = beads.natoms
    nbeads = beads.nbeads
    for j in range(nbeads):
        filedesc.write(
            "%d\n# bead: %d CELL(abcABC): %10.5f  %10.5f  %10.5f  %10.5f  %10.5f  %10.5f \n"
            % (natoms, j, a, b, c, alpha, beta, gamma)
        )
        for i in range(natoms):
            qs = depstrip(beads.q)
            lab = depstrip(beads.names)
            filedesc.write("%8s %12.5e %12.5e %12.5e\n" % (lab[i], qs[j][3 * i], qs[j][3 * i + 1], qs[j][3 * i + 2]))
示例#8
0
文件: geop.py 项目: robeme/i-pi-dev
    def __call__(self, x):

        self.dbeads.q = self.x0 + self.d * x
        e = self.dforces.pot  # Energy
        g = -np.dot(depstrip(self.dforces.f).flatten(),
                    self.d.flatten())  # Gradient
        return e, g
示例#9
0
    def pconstraints(self):
        """This removes the centre of mass contribution to the kinetic energy.

        Calculates the centre of mass momenta, then removes the mass weighted
        contribution from each atom. If the ensemble defines a thermostat, then
        the contribution to the conserved quantity due to this subtraction is
        added to the thermostat heat energy, as it is assumed that the centre of
        mass motion is due to the thermostat.

        If there is a choice of thermostats, the thermostat
        connected to the centroid is chosen.
        """

        if (self.fixcom):
            pcom = np.zeros(3, float)

            na3 = self.beads.natoms * 3
            nb = self.beads.nbeads
            p = depstrip(self.beads.p)
            m = depstrip(self.beads.m3)[:, 0:na3:3]
            M = self.beads[0].M

            for i in range(3):
                pcom[i] = p[:, i:na3:3].sum()

            self.ensemble.eens += np.dot(pcom, pcom) / (2.0 * M * nb)

            # subtracts COM velocity
            pcom *= 1.0 / (nb * M)
            for i in range(3):
                self.beads.p[:, i:na3:3] -= m * pcom[i]

        if len(self.fixatoms) > 0:
            for bp in self.beads.p:
                m = depstrip(self.beads.m)
                self.ensemble.eens += 0.5 * np.dot(
                    bp[self.fixatoms * 3],
                    bp[self.fixatoms * 3] / m[self.fixatoms])
                self.ensemble.eens += 0.5 * np.dot(
                    bp[self.fixatoms * 3 + 1],
                    bp[self.fixatoms * 3 + 1] / m[self.fixatoms])
                self.ensemble.eens += 0.5 * np.dot(
                    bp[self.fixatoms * 3 + 2],
                    bp[self.fixatoms * 3 + 2] / m[self.fixatoms])
                bp[self.fixatoms * 3] = 0.0
                bp[self.fixatoms * 3 + 1] = 0.0
                bp[self.fixatoms * 3 + 2] = 0.0
示例#10
0
    def __call__(self, x):
        """ computes energy and gradient for optimization step
            determines new position (x0+d*x)"""

        self.fcount += 1
        self.dbeads.q = self.x0 + self.d * x
        e = self.dforces.pot  # Energy
        g = -np.dot(depstrip(self.dforces.f).flatten(),
                    self.d.flatten())  # Gradient
        return e, g
示例#11
0
    def step(self, step=None):
        """Does one simulation time step."""

        # thermostat is applied at the outer loop
        self.ttime = -time.time()
        self.thermostat.step()
        self.pconstraints()
        self.ttime += time.time()

        # bias is applied at the outer loop too
        self.beads.p += depstrip(self.bias.f) * (self.dt * 0.5)

        self.mtsprop(0, 1.0)

        self.beads.p += depstrip(self.bias.f) * (self.dt * 0.5)

        self.ttime -= time.time()
        self.thermostat.step()
        self.pconstraints()
        self.ttime += time.time()
示例#12
0
def print_xyz(atoms, cell, filedesc=sys.stdout, title=""):
    """Prints an atomic configuration into an XYZ formatted file.

    Args:
        atoms: An atoms object giving the centroid positions.
        cell: A cell object giving the system box.
        filedesc: An open writable file object. Defaults to standard output.
        title: This gives a string to be appended to the comment line.
    """

    a, b, c, alpha, beta, gamma = mt.h2abc_deg(cell.h)

    natoms = atoms.natoms
    fmt_header = "%d\n# CELL(abcABC): %10.5f  %10.5f  %10.5f  %10.5f  %10.5f  %10.5f  %s\n"
    filedesc.write(fmt_header % (natoms, a, b, c, alpha, beta, gamma, title))
    # direct access to avoid unnecessary slow-down
    qs = depstrip(atoms.q)
    lab = depstrip(atoms.names)
    for i in range(natoms):
        filedesc.write("%8s %12.5e %12.5e %12.5e\n" %
                       (lab[i], qs[3 * i], qs[3 * i + 1], qs[3 * i + 2]))
示例#13
0
def print_xyz(atoms, cell, filedesc=sys.stdout, title=""):
    """Prints the centroid configurations, into a xyz formatted file.

   Args:
      atoms: An atoms object giving the centroid positions.
      cell: A cell object giving the system box.
      filedesc: An open writable file object. Defaults to standard output.
      title: This gives a string to be appended to the comment line.
   """

    a, b, c, alpha, beta, gamma = mt.h2abc_deg(cell.h)

    natoms = atoms.natoms
    filedesc.write(
        "%d\n# CELL(abcABC): %10.5f  %10.5f  %10.5f  %10.5f  %10.5f  %10.5f  %s\n"
        % (natoms, a, b, c, alpha, beta, gamma, title)
    )
    # direct access to avoid unnecessary slow-down
    qs = depstrip(atoms.q)
    lab = depstrip(atoms.names)
    for i in range(natoms):
        filedesc.write("%8s %12.5e %12.5e %12.5e\n" % (lab[i], qs[3 * i], qs[3 * i + 1], qs[3 * i + 2]))
示例#14
0
def print_json(atoms, cell, filedesc=sys.stdout, title=""):
    """Prints an atomic configuration into an XYZ formatted file.

    Args:
        atoms: An atoms object giving the centroid positions.
        cell: A cell object giving the system box.
        filedesc: An open writable file object. Defaults to standard output.
        title: This gives a string to be appended to the comment line.
    """

    a, b, c, alpha, beta, gamma = mt.h2abc_deg(cell.h)

    natoms = atoms.natoms
    # direct access to avoid unnecessary slow-down
    qs = depstrip(atoms.q)
    lab = depstrip(atoms.names)
    filedesc.write(
        json.dumps([
            natoms, a, b, c, alpha, beta, gamma, title,
            qs.tolist(),
            lab.tolist()
        ]))
    filedesc.write("\n")
示例#15
0
文件: sockets.py 项目: h314to/i-pi
    def queue(self, atoms, cell, pars=None, reqid=0):
        """Adds a request.

      Note that the pars dictionary need to be sent as a string of a
      standard format so that the initialisation of the driver can be done.

      Args:
         atoms: An Atoms object giving the atom positions.
         cell: A Cell object giving the system box.
         pars: An optional dictionary giving the parameters to be sent to the
            driver for initialisation. Defaults to {}.
         reqid: An optional integer that identifies requests of the same type,
            e.g. the bead index

      Returns:
         A list giving the status of the request of the form {'atoms': Atoms
         object giving the atom positions, 'cell': Cell object giving the
         system box, 'pars': parameter string, 'result': holds the result as a
         list once the computation is done, 'status': a string labelling the
         status, 'id': the id of the request, usually the bead number, 'start':
         the starting time for the calculation, used to check for timeouts.}.
      """

        par_str = " "

        if not pars is None:
            for k, v in pars.items():
                par_str += k + " : " + str(v) + " , "
        else:
            par_str = " "

        # APPLY PBC -- this is useful for codes such as LAMMPS that don't do full PBC when computing distances
        pbcpos = depstrip(atoms.q).copy()
        if self.dopbc:
            cell.array_pbc(pbcpos)

        newreq = {
            "pos": pbcpos,
            "cell": cell,
            "pars": par_str,
            "result": None,
            "status": "Queued",
            "id": reqid,
            "start": -1,
        }

        self.requests.append(newreq)
        return newreq
示例#16
0
    def queue(self, atoms, cell, pars=None, reqid=0):
        """Adds a request.

      Note that the pars dictionary need to be sent as a string of a
      standard format so that the initialisation of the driver can be done.

      Args:
         atoms: An Atoms object giving the atom positions.
         cell: A Cell object giving the system box.
         pars: An optional dictionary giving the parameters to be sent to the
            driver for initialisation. Defaults to {}.
         reqid: An optional integer that identifies requests of the same type,
            e.g. the bead index

      Returns:
         A list giving the status of the request of the form {'atoms': Atoms
         object giving the atom positions, 'cell': Cell object giving the
         system box, 'pars': parameter string, 'result': holds the result as a
         list once the computation is done, 'status': a string labelling the
         status, 'id': the id of the request, usually the bead number, 'start':
         the starting time for the calculation, used to check for timeouts.}.
      """

        par_str = " "

        if not pars is None:
            for k, v in pars.items():
                par_str += k + " : " + str(v) + " , "
        else:
            par_str = " "

        # APPLY PBC -- this is useful for codes such as LAMMPS that don't do full PBC when computing distances
        pbcpos = depstrip(atoms.q).copy()
        if self.dopbc:
            cell.array_pbc(pbcpos)

        newreq = {
            "pos": pbcpos,
            "cell": cell,
            "pars": par_str,
            "result": None,
            "status": "Queued",
            "id": reqid,
            "start": -1
        }

        self.requests.append(newreq)
        return newreq
示例#17
0
    def step(self, step=None):
        """ Does one simulation time step
            Attributes:
            ttime: The time taken in applying the thermostat steps.
        """

        self.qtime = -time.time()

        info("\nMD STEP %d" % step, verbosity.debug)

        if step == 0:
            info(" @GEOP: Initializing L-BFGS", verbosity.debug)
            self.d += depstrip(self.forces.f) / np.sqrt(
                np.dot(self.forces.f.flatten(), self.forces.f.flatten()))

        self.old_x[:] = self.beads.q
        self.old_u[:] = self.forces.pot
        self.old_f[:] = self.forces.f
        if len(self.fixatoms) > 0:

            for dqb in self.old_f:
                dqb[self.fixatoms * 3] = 0.0
                dqb[self.fixatoms * 3 + 1] = 0.0
                dqb[self.fixatoms * 3 + 2] = 0.0

        fdf0 = (self.old_u, -self.old_f)
        #d_x,new_d, new_qlist, new_glist = L_BFGS(self.old_x,
        # Note that the line above is not needed anymore because we update everything
        # within L_BFGS (and all other calls).
        L_BFGS(self.old_x, self.d, self.gm, self.qlist, self.glist, fdf0,
               self.big_step,
               self.ls_options["tolerance"] * self.tolerances["energy"],
               self.ls_options["iter"], self.corrections, self.scale, step)

        info("   Number of force calls: %d" % (self.gm.fcount))
        self.gm.fcount = 0
        #Update positions and forces
        self.beads.q = self.gm.dbeads.q
        self.forces.transfer_forces(
            self.gm.dforces)  #This forces the update of the forces

        # Exit simulation step
        d_x_max = np.amax(np.absolute(np.subtract(self.beads.q, self.old_x)))
        self.exitstep(self.forces.pot, self.old_u, d_x_max)
示例#18
0
    def step(self, step=None):
        """ Does one simulation time step.
            Attributes:
            qtime: The time taken in updating the positions.
        """

        self.qtime = -time.time()
        info("\nMD STEP %d" % step, verbosity.debug)

        if step == 0:
            info(" @GEOP: Initializing BFGS", verbosity.debug)
            self.d += depstrip(self.forces.f) / np.sqrt(
                np.dot(self.forces.f.flatten(), self.forces.f.flatten()))

        self.old_x[:] = self.beads.q
        self.old_u[:] = self.forces.pot
        self.old_f[:] = self.forces.f

        if len(self.fixatoms) > 0:
            for dqb in self.old_f:
                dqb[self.fixatoms * 3] = 0.0
                dqb[self.fixatoms * 3 + 1] = 0.0
                dqb[self.fixatoms * 3 + 2] = 0.0

        fdf0 = (self.old_u, -self.old_f)

        # Do one iteration of BFGS
        # The invhessian and the directions are updated inside.
        BFGS(self.old_x, self.d, self.gm, fdf0, self.invhessian, self.big_step,
             self.ls_options["tolerance"] * self.tolerances["energy"],
             self.ls_options["iter"])

        info("   Number of force calls: %d" % (self.gm.fcount))
        self.gm.fcount = 0
        #Update positions and forces
        self.beads.q = self.gm.dbeads.q
        self.forces.transfer_forces(
            self.gm.dforces)  #This forces the update of the forces

        # Exit simulation step
        d_x_max = np.amax(np.absolute(np.subtract(self.beads.q, self.old_x)))
        self.exitstep(self.forces.pot, self.old_u, d_x_max)
示例#19
0
 def qcstep(self, alpha=1.0):
     """Velocity Verlet centroid position propagator."""
     self.nm.qnm[0, :] += depstrip(self.nm.pnm)[0, :] / depstrip(
         self.beads.m3)[0] * self.dt / alpha
示例#20
0
    def step(self, step=None):
        """Does one simulation time step
           Attributes:
           ptime: The time taken in updating the velocities.
           qtime: The time taken in updating the positions.
           ttime: The time taken in applying the thermostat steps.
        """

        self.ptime = 0.0
        self.ttime = 0.0
        self.qtime = -time.time()

        info("\nMD STEP %d" % step, verbosity.debug)

        if step == 0:
            gradf1 = dq1 = depstrip(self.forces.f)

            # Move direction for 1st conjugate gradient step
            dq1_unit = dq1 / np.sqrt(np.dot(gradf1.flatten(),
                                            gradf1.flatten()))
            info(" @GEOP: Determined SD direction", verbosity.debug)

        else:

            gradf0 = self.old_f
            dq0 = self.d
            gradf1 = depstrip(self.forces.f)
            beta = np.dot(
                (gradf1.flatten() - gradf0.flatten()), gradf1.flatten()) / (
                    np.dot(gradf0.flatten(), gradf0.flatten()))
            dq1 = gradf1 + max(0.0, beta) * dq0
            dq1_unit = dq1 / np.sqrt(np.dot(dq1.flatten(), dq1.flatten()))
            info(" @GEOP: Determined CG direction", verbosity.debug)

        # Store force and direction for next CG step
        self.d[:] = dq1
        self.old_f[:] = gradf1

        if len(self.fixatoms) > 0:
            for dqb in dq1_unit:
                dqb[self.fixatoms * 3] = 0.0
                dqb[self.fixatoms * 3 + 1] = 0.0
                dqb[self.fixatoms * 3 + 2] = 0.0

        self.lm.set_dir(depstrip(self.beads.q), dq1_unit)

        # Reuse initial value since we have energy and forces already
        u0, du0 = (self.forces.pot.copy(),
                   np.dot(depstrip(self.forces.f.flatten()),
                          dq1_unit.flatten()))

        # Do one CG iteration; return positions and energy
        min_brent(self.lm,
                  fdf0=(u0, du0),
                  x0=0.0,
                  tol=self.ls_options["tolerance"] * self.tolerances["energy"],
                  itmax=self.ls_options["iter"],
                  init_step=self.ls_options["step"])
        info("   Number of force calls: %d" % (self.lm.fcount))
        self.lm.fcount = 0

        #Update positions and forces
        self.beads.q = self.lm.dbeads.q
        self.forces.transfer_forces(
            self.lm.dforces)  #This forces the update of the forces

        d_x = np.absolute(np.subtract(self.beads.q, self.lm.x0))
        x = np.linalg.norm(d_x)
        # Automatically adapt the search step for the next iteration.
        # Relaxes better with very small step --> multiply by factor of 0.1 or 0.01

        self.ls_options["step"] = 0.1 * x * self.ls_options["adaptive"] + (
            1 - self.ls_options["adaptive"]) * self.ls_options["step"]

        # Exit simulation step
        d_x_max = np.amax(np.absolute(d_x))
        self.exitstep(self.forces.pot, u0, d_x_max)
示例#21
0
    def pstep(self):
        """Velocity Verlet momenta propagator."""

        self.beads.p += depstrip(self.forces.f) * (self.dt * 0.5)
        # also adds the bias force
        self.beads.p += depstrip(self.bias.f) * (self.dt * 0.5)
示例#22
0
    def step(self, step=None):
        """Does one simulation time step."""

        self.ptime = 0.0
        self.ttime = 0.0
        self.qtime = -time.time()

        info("\nMD STEP %d" % step, verbosity.debug)

        if self.mode == "bfgs":

            # BFGS Minimization
            # Initialize approximate Hessian inverse to the identity and direction
            # to the steepest descent direction
            if step == 0:   # or np.sqrt(np.dot(self.bfgsm.d, self.bfgsm.d)) == 0.0: <-- this part for restarting at claimed minimum (optional)
                info(" @GEOP: Initializing BFGS", verbosity.debug)
                self.bfgsm.d = depstrip(self.forces.f) / np.sqrt(np.dot(self.forces.f.flatten(), self.forces.f.flatten()))
                self.bfgsm.xold = self.beads.q.copy()

            # Current energy and forces
            u0 = self.forces.pot.copy()
            du0 = - self.forces.f

            # Store previous forces
            self.cg_old_f[:] = self.forces.f

            # Do one iteration of BFGS, return new point, function value,
            # move direction, and current Hessian to use for next iteration
            self.beads.q, fx, self.bfgsm.d, self.invhessian = BFGS(self.beads.q,
                self.bfgsm.d, self.bfgsm, fdf0=(u0, du0), invhessian=self.invhessian,
                max_step=self.max_step, tol=self.ls_options["tolerance"],
                itmax=self.ls_options["iter"])

            # x = current position - previous position; use for exit tolerance
            x = np.amax(np.absolute(np.subtract(self.beads.q, self.bfgsm.xold)))

            # Store old position
            self.bfgsm.xold[:] = self.beads.q

            info(" @GEOP: Updating bead positions", verbosity.debug)

        elif self.mode == "lbfgs":

            # L-BFGS Minimization
            # Initialize approximate Hessian inverse to the identity and direction
            # to the steepest descent direction
            # Initialize lists of previous positions and gradient
            if step == 0:   # or np.sqrt(np.dot(self.bfgsm.d, self.bfgsm.d)) == 0.0: <-- this part for restarting at claimed minimum (optional)
                info(" @GEOP: Initializing L-BFGS", verbosity.debug)
                self.bfgsm.d = depstrip(self.forces.f) / np.sqrt(np.dot(self.forces.f.flatten(), self.forces.f.flatten()))
                self.bfgsm.xold = self.beads.q.copy()
                self.qlist = np.zeros((self.corrections, len(self.beads.q.flatten())))
                self.glist = np.zeros((self.corrections, len(self.beads.q.flatten())))

            # Current energy and force
            u0, du0 = (self.forces.pot.copy(), - self.forces.f)

            # Store previous forces
            self.cg_old_f[:] = self.forces.f.reshape(len(self.cg_old_f))

            # Do one iteration of L-BFGS, return new point, function value,
            # move direction, and current Hessian to use for next iteration
            self.beads.q, fx, self.bfgsm.d, self.qlist, self.glist = L_BFGS(self.beads.q,
                self.bfgsm.d, self.bfgsm, self.qlist, self.glist,
                fdf0=(u0, du0), max_step=self.max_step, tol=self.ls_options["tolerance"],
                itmax=self.ls_options["iter"],
                m=self.corrections, k=step)

            info(" @GEOP: Updated position list", verbosity.debug)
            info(" @GEOP: Updated gradient list", verbosity.debug)

            # x = current position - old position. Used for convergence tolerance
            x = np.amax(np.absolute(np.subtract(self.beads.q, self.bfgsm.xold)))

            # Store old position
            self.bfgsm.xold[:] = self.beads.q

            info(" @GEOP: Updated bead positions", verbosity.debug)

        # Routine for steepest descent and conjugate gradient
        else:
            if (self.mode == "sd" or step == 0):

                # Steepest descent minimization
                # gradf1 = force at current atom position
                # dq1 = direction of steepest descent
                # dq1_unit = unit vector of dq1
                gradf1 = dq1 = depstrip(self.forces.f)

                # Move direction for steepest descent and 1st conjugate gradient step
                dq1_unit = dq1 / np.sqrt(np.dot(gradf1.flatten(), gradf1.flatten()))
                info(" @GEOP: Determined SD direction", verbosity.debug)

            else:

                # Conjugate gradient, Polak-Ribiere
                # gradf1: force at current atom position
                # gradf0: force at previous atom position
                # dq1 = direction to move
                # dq0 = previous direction
                # dq1_unit = unit vector of dq1
                gradf0 = self.cg_old_f
                dq0 = self.cg_old_d
                gradf1 = depstrip(self.forces.f)
                beta = np.dot((gradf1.flatten() - gradf0.flatten()), gradf1.flatten()) / (np.dot(gradf0.flatten(), gradf0.flatten()))
                dq1 = gradf1 + max(0.0, beta) * dq0
                dq1_unit = dq1 / np.sqrt(np.dot(dq1.flatten(), dq1.flatten()))
                info(" @GEOP: Determined CG direction", verbosity.debug)

            # Store force and direction for next CG step
            self.cg_old_d[:] = dq1
            self.cg_old_f[:] = gradf1

            if len(self.fixatoms) > 0:
                for dqb in dq1_unit:
                    dqb[self.fixatoms*3] = 0.0
                    dqb[self.fixatoms*3+1] = 0.0
                    dqb[self.fixatoms*3+2] = 0.0

            self.lm.set_dir(depstrip(self.beads.q), dq1_unit)

            # Reuse initial value since we have energy and forces already
            u0, du0 = (self.forces.pot.copy(), np.dot(depstrip(self.forces.f.flatten()), dq1_unit.flatten()))

            # Do one SD/CG iteration; return positions and energy
            (x, fx) = min_brent(self.lm, fdf0=(u0, du0), x0=0.0,
                    tol=self.ls_options["tolerance"],
                    itmax=self.ls_options["iter"], init_step=self.ls_options["step"])

            # Automatically adapt the search step for the next iteration.
            # Relaxes better with very small step --> multiply by factor of 0.1 or 0.01
            self.ls_options["step"] = 0.1 * x * self.ls_options["adaptive"] + (1 - self.ls_options["adaptive"]) * self.ls_options["step"]

            self.beads.q += dq1_unit * x
            info(" @GEOP: Updated bead positions", verbosity.debug)

        self.qtime += time.time()

        # Determine conditions for converged relaxation
        if ((fx - u0) / self.beads.natoms <= self.tolerances["energy"])\
                and ((np.amax(np.absolute(self.forces.f)) <= self.tolerances["force"])
                    or (np.sqrt(np.dot(self.forces.f.flatten() - self.cg_old_f.flatten(),
                        self.forces.f.flatten() - self.cg_old_f.flatten())) == 0.0))\
                and (x <= self.tolerances["position"]):
            softexit.trigger("Geometry optimization converged. Exiting simulation")
示例#23
0
def main(prefix, temp):

    T = float(temp)
    fns_pos = sorted(glob.glob(prefix + ".pos*"))
    fns_for = sorted(glob.glob(prefix + ".for*"))
    fn_out_kin = prefix + ".kin.xyz"
    fn_out_kod = prefix + ".kod.xyz"

    # check that we found the same number of positions and forces files
    nbeads = len(fns_pos)
    if nbeads != len(fns_for):
        print fns_pos
        print fns_for
        raise ValueError(
            "Mismatch between number of input files for forces and positions.")

    # print some information
    print 'temperature = {:f} K'.format(T)
    print
    print 'number of beads = {:d}'.format(nbeads)
    print
    print 'positions and forces file names:'
    for fn_pos, fn_for in zip(fns_pos, fns_for):
        print '{:s}   {:s}'.format(fn_pos, fn_for)
    print
    print 'output file names:'
    print fn_out_kin
    print fn_out_kod
    print

    temp = unit_to_internal("energy", "kelvin", T)

    # open input and output files
    ipos = [open(fn, "r") for fn in fns_pos]
    ifor = [open(fn, "r") for fn in fns_for]
    ikin = open(fn_out_kin, "w")
    ikod = open(fn_out_kod, "w")

    natoms = 0
    ifr = 0
    while True:

        # print progress
        if ifr % 100 == 0:
            print '\rProcessing frame {:d}'.format(ifr),
            sys.stdout.flush()

        # load one frame
        try:
            for i in range(nbeads):
                ret = read_file("xyz", ipos[i])
                pos = ret["atoms"]
                ret = read_file("xyz", ifor[i])
                force = ret["atoms"]
                if natoms == 0:
                    natoms = pos.natoms
                    beads = Beads(natoms, nbeads)
                    forces = Beads(natoms, nbeads)
                    kcv = np.zeros((natoms, 6), float)
                beads[i].q = pos.q
                forces[i].q = force.q
        except EOFError:
            # finished reading files
            break

        # calculate kinetic energies
        q = depstrip(beads.q)
        f = depstrip(forces.q)
        qc = depstrip(beads.qc)
        kcv[:] = 0
        for j in range(nbeads):
            for i in range(natoms):
                kcv[i,
                    0] += (q[j, i * 3 + 0] - qc[i * 3 + 0]) * f[j, i * 3 + 0]
                kcv[i,
                    1] += (q[j, i * 3 + 1] - qc[i * 3 + 1]) * f[j, i * 3 + 1]
                kcv[i,
                    2] += (q[j, i * 3 + 2] - qc[i * 3 + 2]) * f[j, i * 3 + 2]
                kcv[i, 3] += (
                    q[j, i * 3 + 0] - qc[i * 3 + 0]) * f[j, i * 3 + 1] + (
                        q[j, i * 3 + 1] - qc[i * 3 + 1]) * f[j, i * 3 + 0]
                kcv[i, 4] += (
                    q[j, i * 3 + 0] - qc[i * 3 + 0]) * f[j, i * 3 + 2] + (
                        q[j, i * 3 + 2] - qc[i * 3 + 2]) * f[j, i * 3 + 0]
                kcv[i, 5] += (
                    q[j, i * 3 + 1] - qc[i * 3 + 1]) * f[j, i * 3 + 2] + (
                        q[j, i * 3 + 2] - qc[i * 3 + 2]) * f[j, i * 3 + 1]
        kcv *= -0.5 / nbeads
        kcv[:, 0:3] += 0.5 * Constants.kb * temp
        kcv[:, 3:6] *= 0.5

        # write output
        ikin.write(
            "%d\n# Centroid-virial kinetic energy estimator [a.u.] - diagonal terms: xx yy zz\n"
            % natoms)
        ikod.write(
            "%d\n# Centroid-virial kinetic energy estimator [a.u.] - off-diag terms: xy xz yz\n"
            % natoms)
        for i in range(natoms):
            ikin.write("%8s %12.5e %12.5e %12.5e\n" %
                       (pos.names[i], kcv[i, 0], kcv[i, 1], kcv[i, 2]))
            ikod.write("%8s %12.5e %12.5e %12.5e\n" %
                       (pos.names[i], kcv[i, 3], kcv[i, 4], kcv[i, 5]))

        ifr += 1

    print '\rProcessed {:d} frames.'.format(ifr)

    ikin.close()
    ikod.close()