Example #1
0
def print_pdb(atoms, cell, filedesc=sys.stdout, title="", cell_conv=1.0, atoms_conv=1.0):
    """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 * cell_conv)

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

    natoms = atoms.natoms
    qs = dstrip(atoms.q) * atoms_conv
    lab = dstrip(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")
Example #2
0
def print_json(atoms, cell, filedesc=sys.stdout, title="", cell_conv=1.0, atoms_conv=1.0):
    """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 * cell_conv)

    natoms = atoms.natoms
    # direct access to avoid unnecessary slow-down
    qs = dstrip(atoms.q) * atoms_conv
    lab = dstrip(atoms.names)

    data = {}
    data['natoms'] = natoms
    data['cell'] = [a, b, c, alpha, beta, gamma]
    data['title'] = title
    data['q'] = qs.tolist()
    data['labels'] = lab.tolist()

    filedesc.write(json.dumps(data))
    filedesc.write(" \n")
Example #3
0
def print_xyz(atoms,
              cell,
              filedesc=sys.stdout,
              title="",
              cell_conv=1.0,
              atoms_conv=1.0):
    """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 * cell_conv)

    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 = dstrip(atoms.q) * atoms_conv
    lab = dstrip(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]))
Example #4
0
def print_xyz_path(beads,
                   cell,
                   filedesc=sys.stdout,
                   cell_conv=1.0,
                   atoms_conv=1.0):
    """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 * cell_conv)

    fmt_header = "%d\n# bead: %d CELL(abcABC): %10.5f  %10.5f  %10.5f  %10.5f  %10.5f  %10.5f \n"
    natoms = beads.natoms
    nbeads = beads.nbeads
    for j in range(nbeads):
        filedesc.write(fmt_header % (natoms, j, a, b, c, alpha, beta, gamma))
        for i in range(natoms):
            qs = dstrip(beads.q) * atoms_conv
            lab = dstrip(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]))
Example #5
0
    def __init__(
        self,
        latency=1.0e-3,
        name="",
        pars=None,
        dopbc=False,
        threaded=False,
        init_file="",
        plumeddat="",
        plumedstep=0,
    ):
        """Initialises FFPlumed.

        Args:
           pars: Optional dictionary, giving the parameters needed by the driver.
        """

        # a socket to the communication library is created or linked
        if plumed is None:
            raise ImportError(
                "Cannot find plumed libraries to link to a FFPlumed object/")
        super(FFPlumed, self).__init__(latency,
                                       name,
                                       pars,
                                       dopbc=False,
                                       threaded=threaded)
        self.plumed = plumed.Plumed()
        self.plumeddat = plumeddat
        self.plumedstep = plumedstep
        self.init_file = init_file

        if self.init_file.mode == "xyz":
            infile = open(self.init_file.value, "r")
            myframe = read_file(self.init_file.mode, infile)
            myatoms = myframe["atoms"]
            mycell = myframe["cell"]
            myatoms.q *= unit_to_internal("length", self.init_file.units, 1.0)
            mycell.h *= unit_to_internal("length", self.init_file.units, 1.0)

        self.natoms = myatoms.natoms
        self.plumed.cmd("setNatoms", self.natoms)
        self.plumed.cmd("setPlumedDat", self.plumeddat)
        self.plumed.cmd("setTimestep", 1.0)
        self.plumed.cmd(
            "setMDEnergyUnits", 2625.4996
        )  # Pass a pointer to the conversion factor between the energy unit used in your code and kJ mol-1
        self.plumed.cmd(
            "setMDLengthUnits", 0.052917721
        )  # Pass a pointer to the conversion factor between the length unit used in your code and nm
        self.plumed.cmd("setMDTimeUnits", 2.4188843e-05)
        self.plumedrestart = False
        if self.plumedstep > 0:
            # we are restarting, signal that PLUMED should continue
            self.plumedrestart = True
            self.plumed.cmd("setRestart", 1)
        self.plumed.cmd("init")
        self.charges = dstrip(myatoms.q) * 0.0
        self.masses = dstrip(myatoms.m)
        self.lastq = np.zeros(3 * self.natoms)
Example #6
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

        # Check for fixatoms
        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

        dq1 = dstrip(self.old_f)

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

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

        # Reuse initial value since we have energy and forces already
        u0, du0 = (self.forces.pot.copy(),
                   np.dot(dstrip(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)
Example #7
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

        # Check for fixatoms
        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

        dq1 = dstrip(self.old_f)

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

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

        # Reuse initial value since we have energy and forces already
        u0, du0 = (self.forces.pot.copy(), np.dot(dstrip(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)
Example #8
0
    def b2tob1(self, q):
        """Transforms a matrix from one value of beads to another.

        Args:
           q: A matrix with nbeads2 rows, in the bead representation.
        """

        if self.noop:
            # still must return a copy, as the contraction is meant to return new data, not a view
            q_scal = dstrip(q).copy()
        else:
            # see b1tob2 for an explanation of the rationale for dealing with open path transformations
            q_scal = np.tensordot(self._b2tob1, q, axes=(1, 0))
            if len(self._open) > 0:
                if len(q_scal.shape) == 2:
                    for io in self._open:
                        q_scal[:, 3 * io] = np.tensordot(self._o_b2tob1,
                                                         q[:, 3 * io],
                                                         axes=(1, 0))
                        q_scal[:, 3 * io + 1] = np.tensordot(self._o_b2tob1,
                                                             q[:, 3 * io + 1],
                                                             axes=(1, 0))
                        q_scal[:, 3 * io + 2] = np.tensordot(self._o_b2tob1,
                                                             q[:, 3 * io + 2],
                                                             axes=(1, 0))
                    else:
                        q_scal = np.tensordot(self._o_b2tob1, q, axes=(1, 0))
        return q_scal
Example #9
0
File: geop.py Project: tomspur/i-pi
    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)
            print self.d
            self.d += dstrip(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

            # Reduce the dimensionality
            masked_old_x = self.old_x[:, self.gm.fixatoms_mask]
            masked_d = self.d[:, self.gm.fixatoms_mask]
            # self.gm is reduced inside its __init__() and __call__() functions
            masked_qlist = self.qlist[:, self.gm.fixatoms_mask]
            masked_glist = self.glist[:, self.gm.fixatoms_mask]
            fdf0 = (self.old_u, -self.old_f[:, self.gm.fixatoms_mask])

            # We update everything within L_BFGS (and all other calls).
            L_BFGS(masked_old_x, masked_d, self.gm, masked_qlist, masked_glist, fdf0,
                   self.big_step, self.ls_options["tolerance"] * self.tolerances["energy"],
                   self.ls_options["iter"], self.corrections, self.scale, step)

            # Restore the dimensionality
            self.d[:, self.gm.fixatoms_mask] = masked_d
            self.qlist[:, self.gm.fixatoms_mask] = masked_qlist
            self.glist[:, self.gm.fixatoms_mask] = masked_glist

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

            # 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)
Example #10
0
    def geop_thread(self, ieval, nstr, nevent, ostr=None):
        self.geop[ieval].reset()
        ipot = self.dforces[ieval].pot

        for i in xrange(self.nstep):
            # print "geop ", i, self.dforces[ieval].pot
            self.geop[ieval].step(i)
            #if self.geop[ieval].converged[0]: break
        newq = dstrip(self.dbeads[ieval].q[0]).copy()
        newpot = self.dforces[ieval].pot

        # print "geop ", self.nstep, self.dforces[ieval].pot
        with self._threadlock:
            self.ecache[nstr] = newpot
            self.qcache[nstr] = newq
            self.ncache += 1
            nevent[2] = self.ecache[nstr]
            nevent[3] = self.qcache[nstr]

        # launches TS calculation
        #if not ostr is None:
        #    self.ts_thread(ieval, ostr, nstr, nevent)
        #else:
        #    with self._threadlock:
        #        self.feval[ieval] = 1
        with self._threadlock:
            self.feval[ieval] = 1

        with self._threadlock:
            print "Finished ", nstr
            print "Energy, initial - TS - final: ", ipot, nevent[-1], newpot
Example #11
0
    def initialize(self, step):

        if step == 0:
            info(" @GEOP: Initializing instanton", verbosity.low)

            if self.beads.nbeads == 1:
                raise ValueError("We can not perform an splitting calculation with nbeads =1")

            else:
                if ((self.beads.q - self.beads.q[0]) == 0).all():
                    # If the coordinates in all the imaginary time slices are the same
                    self.initial_geo()
                else:
                    info(" @GEOP: Starting from the provided geometry in the extended phase space", verbosity.low)

        # This must be done after the stretching and before the self.d.
        if self.im.f is None:
            self.im(self.beads.q, ret=False)  # Init instanton mapper

        if (self.optarrays["old_x"] == np.zeros((self.beads.nbeads, 3 * self.beads.natoms), float)).all():
            self.optarrays["old_x"][:] = self.beads.q

        # Specific for LBFGS
        if np.linalg.norm(self.optarrays["d"]) == 0.0:
            f = self.forces.f + self.im.f
            self.optarrays["d"] += dstrip(f) / np.sqrt(np.dot(f.flatten(), f.flatten()))

        self.update_old_pos_for()
        self.init = True
Example #12
0
    def b1tob2(self, q):
        """Transforms a matrix from one value of beads to another.

        Args:
           q: A matrix with nbeads1 rows, in the bead representation.
        """

        if self.noop:
            # still must return a copy, as the contraction is meant to return new data, not a view
            q_scal = dstrip(q).copy()
        else:
            # this applies to both bead property arrays (e.g. potentials) and bead vector properties (e.g. positions, forces)
            q_scal = np.dot(self._b1tob2, q)
            if len(self._open) > 0:
                if len(q_scal.shape) == 2:
                    for io in self._open:
                        q_scal[:, 3 * io] = np.dot(self._o_b1tob2, q[:, 3 * io])
                        q_scal[:, 3 * io + 1] = np.dot(self._o_b1tob2, q[:, 3 * io + 1])
                        q_scal[:, 3 * io + 2] = np.dot(self._o_b1tob2, q[:, 3 * io + 2])
                else:
                    # this applies the open path contraction to EVERYTHING because otherwise we don't know how to handle
                    # the fact that only some beads are open. clearly this is a hack, and in practice the point is that
                    # a "per bead" NM transformation of the potential is not well-defined when different beads have different
                    # NM transformations
                    q_scal = np.dot(self._o_b1tob2, q)

        return q_scal
Example #13
0
def print_pdb_path(beads,
                   cell,
                   filedesc=sys.stdout,
                   cell_conv=1.0,
                   atoms_conv=1.0):
    """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.
    """

    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"
    fmt_conect = "CONECT%5i%5i\n"

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

    z = 1  # What even is this parameter?
    filedesc.write(fmt_cryst %
                   (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 = dstrip(beads.q) * atoms_conv
            lab = dstrip(beads.names)
            data = (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)
            filedesc.write(fmt_atom % data)

    if nbeads > 1:
        for i in range(natoms):
            filedesc.write(fmt_conect % (i + 1, (nbeads - 1) * natoms + i + 1))
        for j in range(nbeads - 1):
            for i in range(natoms):
                filedesc.write(fmt_conect % (j * natoms + i + 1,
                                             (j + 1) * natoms + i + 1))

    filedesc.write("END\n")
Example #14
0
File: geop.py Project: tomspur/i-pi
    def __call__(self, x):
        """ computes energy and gradient for optimization step
            determines new position (x0+d*x)"""

        self.fcount += 1
        self.dbeads.q[:, self.fixatoms_mask] = self.x0[:, self.fixatoms_mask] + self.d * x
        e = self.dforces.pot   # Energy
        g = - np.dot(dstrip(self.dforces.f[:, self.fixatoms_mask]).flatten(), self.d.flatten())   # Gradient
        return e, g
Example #15
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(dstrip(self.dforces.f).flatten(), self.d.flatten())   # Gradient
        return e, g
Example #16
0
def print_xyz(atoms, cell, filedesc=sys.stdout, title="", cell_conv=1.0, atoms_conv=1.0):
    """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 * cell_conv)

    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 = dstrip(atoms.q) * atoms_conv
    lab = dstrip(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]))
Example #17
0
    def __init__(self, latency=1.0e-3, name="", pars=None, dopbc=False, init_file="", plumeddat="", precision=8, plumedstep=0):
        """Initialises FFPlumed.

        Args:
           pars: Optional dictionary, giving the parameters needed by the driver.
        """

        # a socket to the communication library is created or linked
        if plumed is None:
            raise ImportError("Cannot find plumed libraries to link to a FFPlumed object/")
        super(FFPlumed, self).__init__(latency, name, pars, dopbc=False)
        self.plumed = plumed.Plumed(precision)
        self.precision = precision
        self.plumeddat = plumeddat
        self.plumedstep = plumedstep
        self.init_file = init_file

        if self.init_file.mode == "xyz":
            infile = open(self.init_file.value, "r")
            myframe = read_file(self.init_file.mode, infile)
            myatoms = myframe['atoms']
            mycell = myframe['cell']
            myatoms.q *= unit_to_internal("length", self.init_file.units, 1.0)
            mycell.h *= unit_to_internal("length", self.init_file.units, 1.0)

        self.natoms = myatoms.natoms
        self.plumed.cmd("setNatoms", self.natoms)
        self.plumed.cmd("setPlumedDat", self.plumeddat)
        self.plumed.cmd("setTimestep", 1.)
        self.plumed.cmd("setMDEnergyUnits", 2625.4996)        # Pass a pointer to the conversion factor between the energy unit used in your code and kJ mol-1
        self.plumed.cmd("setMDLengthUnits", 0.052917721)        # Pass a pointer to the conversion factor between the length unit used in your code and nm
        self.plumed.cmd("setMDTimeUnits", 2.4188843e-05)
        self.plumedrestart = False
        if self.plumedstep > 0:
            # we are restarting, signal that PLUMED should continue
            self.plumedrestart = True
            self.plumed.cmd("setRestart", 1)
        self.plumed.cmd("init")
        self.charges = dstrip(myatoms.q) * 0.0
        self.masses = dstrip(myatoms.m)
        self.lastq = np.zeros(3 * self.natoms)
Example #18
0
def print_xyz_path(beads, cell, filedesc=sys.stdout, cell_conv=1.0, atoms_conv=1.0):
    """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 * cell_conv)

    fmt_header = "%d\n# bead: %d CELL(abcABC): %10.5f  %10.5f  %10.5f  %10.5f  %10.5f  %10.5f \n"
    natoms = beads.natoms
    nbeads = beads.nbeads
    for j in range(nbeads):
        filedesc.write(fmt_header % (natoms, j, a, b, c, alpha, beta, gamma))
        for i in range(natoms):
            qs = dstrip(beads.q) * atoms_conv
            lab = dstrip(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]))
Example #19
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 += dstrip(self.forces.f) / np.sqrt(
                np.dot(self.forces.f.flatten(), self.forces.f.flatten()))
            if len(self.fixatoms) > 0:
                for dqb in self.d:
                    dqb[self.fixatoms * 3] = 0.0
                    dqb[self.fixatoms * 3 + 1] = 0.0
                    dqb[self.fixatoms * 3 + 2] = 0.0

        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)
Example #20
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 += dstrip(self.forces.f) / np.sqrt(np.dot(self.forces.f.flatten(), self.forces.f.flatten()))
            if len(self.fixatoms) > 0:
                for dqb in self.d:
                    dqb[self.fixatoms * 3] = 0.0
                    dqb[self.fixatoms * 3 + 1] = 0.0
                    dqb[self.fixatoms * 3 + 2] = 0.0

        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)
Example #21
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 += dstrip(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)

        # 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)
Example #22
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 = dstrip(atoms.q).copy()

        # Indexes come from input in a per atom basis and we need to make a per atom-coordinate basis
        # Reformat indexes for full system (default) or piece of system
        #        fullat=True
        if self.active[0] == -1:
            activehere = np.array([i for i in range(len(pbcpos))])
        else:
            activehere = np.array([[3 * n, 3 * n + 1, 3 * n + 2]
                                   for n in self.active])


#           fullat=False
#
#        if (self.active[0]!=-1 and fullat==False):
#           temp=np.array([[3*n, 3*n+1, 3*n+2] for n in self.active])

# Reassign active indexes in order to use them
        activehere = activehere.flatten()

        # Perform sanity check for active atoms
        if (len(activehere) > len(pbcpos) or activehere[-1] >
            (len(pbcpos) - 1)):
            raise ValueError("There are more active atoms than atoms!")

        if self.dopbc:
            cell.array_pbc(pbcpos)

        newreq = ForceRequest({
            "id":
            reqid,
            "pos":
            pbcpos,
            "active":
            activehere,
            "cell": (dstrip(cell.h).copy(), dstrip(cell.ih).copy()),
            "pars":
            par_str,
            "result":
            None,
            "status":
            "Queued",
            "start":
            -1,
            "t_queued":
            time.time(),
            "t_dispatched":
            0,
            "t_finished":
            0
        })

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

        return newreq
Example #23
0
    def queue(self, atoms, cell, reqid=-1, template=None):
        """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
            template: a dict giving a base model for the request item -
               e.g. to add entries that are not needed for the base class execution

        Returns:
            A dict 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 self.pars is not None:
            for k, v in list(self.pars.items()):
                par_str += k + " : " + str(v) + " , "
        else:
            par_str = " "

        pbcpos = dstrip(atoms.q).copy()

        # Indexes come from input in a per atom basis and we need to make a per atom-coordinate basis
        # Reformat indexes for full system (default) or piece of system
        # active atoms do not change but we only know how to build this array once we get the positions once
        if self.iactive is None:
            if self.active[0] == -1:
                activehere = np.arange(len(pbcpos))
            else:
                activehere = np.array([[3 * n, 3 * n + 1, 3 * n + 2]
                                       for n in self.active])

            # Reassign active indexes in order to use them
            activehere = activehere.flatten()

            # Perform sanity check for active atoms
            if len(activehere) > len(pbcpos) or activehere[-1] > (len(pbcpos) -
                                                                  1):
                raise ValueError("There are more active atoms than atoms!")

            self.iactive = activehere

        if self.dopbc:
            cell.array_pbc(pbcpos)

        if template is None:
            template = {}
        template.update({
            "id": reqid,
            "pos": pbcpos,
            "active": self.iactive,
            "cell": (dstrip(cell.h).copy(), dstrip(cell.ih).copy()),
            "pars": par_str,
            "result": None,
            "status": "Queued",
            "start": -1,
            "t_queued": time.time(),
            "t_dispatched": 0,
            "t_finished": 0,
        })

        newreq = ForceRequest(template)

        with self._threadlock:
            self.requests.append(newreq)

        if not self.threaded:
            self.poll()

        return newreq
Example #24
0
File: geop.py Project: tomspur/i-pi
    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 = dstrip(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 = dstrip(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(dstrip(self.beads.q), dq1_unit)

        # Reuse initial value since we have energy and forces already
        u0, du0 = (self.forces.pot.copy(), np.dot(dstrip(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)
Example #25
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 = dstrip(atoms.q).copy()

        # Indexes come from input in a per atom basis and we need to make a per atom-coordinate basis
        # Reformat indexes for full system (default) or piece of system
        # active atoms do not change but we only know how to build this array once we get the positions once
        if self.iactive is None:
            if self.active[0] == -1:
                activehere = np.arange(len(pbcpos))
            else:
                activehere = np.array([[3 * n, 3 * n + 1, 3 * n + 2] for n in self.active])

            # Reassign active indexes in order to use them
            activehere = activehere.flatten()

            # Perform sanity check for active atoms
            if (len(activehere) > len(pbcpos) or activehere[-1] > (len(pbcpos) - 1)):
                raise ValueError("There are more active atoms than atoms!")

            self.iactive = activehere

        if self.dopbc:
            cell.array_pbc(pbcpos)

        newreq = ForceRequest({
            "id": reqid,
            "pos": pbcpos,
            "active": self.iactive,
            "cell": (dstrip(cell.h).copy(), dstrip(cell.ih).copy()),
            "pars": par_str,
            "result": None,
            "status": "Queued",
            "start": -1,
            "t_queued": time.time(),
            "t_dispatched": 0,
            "t_finished": 0
        })

        with self._threadlock:
            self.requests.append(newreq)

        if not self.threaded:
            self.poll()

        return newreq
Example #26
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 = dstrip(beads.q)
        f = dstrip(forces.q)
        qc = dstrip(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()
Example #27
0
    def step(self, step=None):

        kT = Constants.kb * self.ensemble.temp
        # computes current energy (if not already stored)
        ostr = "".join(
            self.state
        )  # this is a unique id string that charactrizes the current state
        self.tscache[ostr] = {}
        if not ostr in self.ecache:
            self.dbeads[0].q[0, :] = self.sites[self.unique_idx(
                self.state)].flatten()
            rv = [0, 0, 0, 0, 0]
            self.geop_thread(0, ostr, rv)
            #self.beads.q[0,:] = self.dbeads[0].q[0,:] # also updates current position
            # self.forces.transfer_forces(self.dforces[0]) # forces have already been computed here...

        ecurr = self.ecache[ostr]

        # enumerates possible reactive events (vacancy swaps)
        levents = []
        ethreads = [None] * self.neval
        # loops over the vacancy
        for ivac in xrange(self.natoms, self.natoms + self.nvac):
            svac = self.idx[ivac]  # lattice site associated with this vacancy
            if self.state[svac] != "V":
                raise IndexError(
                    "Something got screwed and a vacancy state is not a vacancy anymore!"
                )
            # loops over the neighbors of the selected vacancy
            for sneigh in self.neigh[svac]:
                # if the neighbor is a vacancy, move on. does not make sense to swap two vacancies!
                if self.state[sneigh] == "V": continue

                # creates a new state vector with swapped atoms-vacancy and the associated label string
                nstate = self.state.copy()
                nstate[svac], nstate[sneigh] = self.state[sneigh], self.state[
                    svac]
                nstr = "".join(
                    nstate
                )  # this is the string that corresponds to the new state
                if not nstr in self.ecache:
                    # new state, must compute!
                    # creates a swapped index
                    nidx = self.idx.copy()
                    if self.ridx[svac] != ivac or self.idx[ivac] != svac:
                        raise IndexError(
                            "Something got screwed and the index does not correspond anymore to site occupancy"
                        )

                    #ivac = self.ridx[svac]
                    ineigh = self.ridx[
                        sneigh]  # gets index of atom associated with the neighboring site
                    nidx[ivac], nidx[ineigh] = self.idx[ineigh], self.idx[ivac]

                    ieval = self.find_eval(ethreads)
                    # launches evaluator
                    self.dbeads[ieval].q[0, :] = self.sites[self.unique_idx(
                        nstate)].flatten()

                    nevent = [svac, sneigh, 0.0, 0.0, 0.0]

                    # runs a geometry optimization
                    #self.geop_thread(ieval=ieval, nstr=nstr, nevent=nevent)
                    st = threading.Thread(target=self.geop_thread,
                                          name=str(ieval),
                                          kwargs={
                                              "ieval": ieval,
                                              "nstr": nstr,
                                              "nevent": nevent,
                                              "ostr": ostr
                                          })
                    st.daemon = True
                    st.start()
                    ethreads[ieval] = st
                else:
                    print "Found state ", nstr, " retrieving cached energy ", self.ecache[
                        nstr]

                    # fetch energy from previous calculation
                    nevent = [
                        svac, sneigh, self.ecache[nstr], self.qcache[nstr], 0.0
                    ]

                    # EVALUATION OF TS ENERGY IS DISABLED FOR THE MOMENT...
                    # we might still need to compute the TS energy!
                    # if not nstr in self.tscache[ostr]:
                    #   print "Computing TS"
                    #   ieval = self.find_eval(ethreads)
                    #    st = threading.Thread(target=self.ts_thread, name=str(ieval), kwargs={"ieval":ieval, "ostr": ostr, "nstr":nstr, "nevent" : nevent})
                    #    st.daemon = True
                    #    st.start()
                    #    ethreads[ieval] = st
                    #else:
                    #    print "Found TS"
                    #    nevent[3] = self.tscache[ostr][nstr]
                nevent[-1] = self.state[sneigh]
                levents.append(nevent)
        # wait for all evaluators to finish
        for st in ethreads:
            while not st is None and st.isAlive():
                st.join(2)

        print "Computed ", len(
            levents), " possible reactions. Cache len ", len(self.ecache)

        # get list of rates
        rates = np.zeros(len(levents), float)
        crates = np.zeros(len(levents), float)
        cdf = 0.0
        for i in xrange(len(levents)):
            #print ("Barrier, naive: %f, static: %f" % (0.5*(ecurr + levents[i][2]) + self.diffusion_barrier_al, levents[i][4]))

            ets = 0.5 * (ecurr + levents[i][2]) + self.barriers[
                levents[i][-1]]  #naive heuristic for the ts energy
            print "Event ", i, levents[i][-1], ecurr, ">>", ets, ">>", levents[
                i][2]
            rates[i] = self.prefactors[levents[i][-1]] * np.exp(
                -(ets - ecurr) / kT)
            cdf += rates[i]
            crates[i] = cdf

        # KMC selection rule based on the rate
        fpick = self.prng.u * cdf
        isel = 0
        while fpick > crates[isel]:
            isel += 1
        dt = -1.0 / cdf * np.log(1.0 - self.prng.u)
        print("Time spent %12.5e at %s nrg %12.5e" % (dt, ostr, ecurr))
        print "Selected event ", isel, " with rate ", rates[isel], " / ", cdf

        iev = levents[isel]  # levents[self.prng.randint(len(levents))]
        svac, sneigh = iev[0], iev[1]
        ivac, ineigh = self.ridx[svac], self.ridx[sneigh]

        # does the swap (never reject, for the moment)
        self.state[svac], self.state[sneigh] = self.state[sneigh], self.state[
            svac]
        self.ridx[svac], self.ridx[sneigh] = self.ridx[sneigh], self.ridx[svac]
        self.idx[ivac], self.idx[ineigh] = self.idx[ineigh], self.idx[ivac]

        # we got a new configuration but the residence time is linked to the previous configuration so we output that
        self.kmcfile.write("%12.5e  %12.5e  %18.11e  %s\n" %
                           (self.tottime, dt, ecurr, ostr))
        self.kmcfile.flush()
        self.tottime += dt
        self.ensemble.time += dt  # updates time counter
        print "Finishing step at ", "".join(self.state)

        # updates the positions
        self.cell.h = self.dcell.h

        uidx = self.unique_idx(self.state)
        ruidx = np.zeros(self.nsites, int)
        ruidx[uidx] = range(self.nsites)

        self.sites[self.unique_idx(self.state)]
        oldq = dstrip(self.beads.q[0]).copy()

        newq = np.zeros(self.nsites * 3, float)
        # we want continuity (modulo PBC jumps, that we'll take care of later...)
        for i in xrange(self.nsites):
            # in which site sits atom i?
            isite = self.idx[i]
            # which atom sits in this site in the unique-mapped structure?
            iuid = ruidx[self.idx[i]]
            newq[3 * i:3 * i + 3] = iev[3][3 * iuid:3 * (iuid + 1)]
        newq -= oldq
        self.cell.array_pbc(newq)
        self.beads.q[0] += newq
Example #28
0
    def step(self, step=None):
        """ Does one simulation time step."""

        self.qtime = -time.time()
        info("\n Instanton optimization STEP %d" % step, verbosity.low)

        if step == 0:
            info(" @GEOP: Initializing instanton", verbosity.low)

            if self.beads.nbeads == 1:
                raise ValueError("We can not perform an splitting calculation with nbeads =1")
                # get_hessian(self.hessian, self.gm, self.beads.q)
            else:
                if ((self.beads.q - self.beads.q[0]) == 0).all():  # If the coordinates in all the imaginary time slices are the same
                    info(" @GEOP: We stretch the initial geometry with an 'amplitud' of %4.2f" % self.delta, verbosity.low)
                    imvector = get_imvector(self.initial_hessian, self.beads.m3[0].flatten())
                    for i in range(self.beads.nbeads):

                        self.beads.q[i, :] += self.delta * np.cos(i * np.pi / float(self.beads.nbeads - 1)) * imvector[:]
                else:
                    info(" @GEOP: Starting from the provided geometry in the extended phase space", verbosity.low)

            # Update positions and forces
            self.old_x[:] = self.beads.q
            self.old_u[:] = self.forces.pots
            self.old_f[:] = self.forces.f

        # This must be done after the stretching and before the self.d.
        if type(self.im.f) == type(None):
            self.im(self.beads.q, ret=False)  # Init instanton mapper

        # Specific for LBFGS
        if np.linalg.norm(self.d) == 0.0:
            f = self.forces.f + self.im.f  # ALBERTO1
            self.d += dstrip(f) / np.sqrt(np.dot(f.flatten(), f.flatten()))

        if (self.old_x == np.zeros((self.beads.nbeads, 3 * self.beads.natoms), float)).all():
            self.old_x[:] = self.beads.q

        if self.exit:
            softexit.trigger("Geometry optimization converged. Exiting simulation")

        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

        e, g = self.fm(self.beads.q)
        fdf0 = (e, g)

        # Do one step. Update hessian for the new position. Update the position and force inside the mapper.
        L_BFGS(self.old_x, self.d, self.fm, self.qlist, self.glist,
               fdf0, self.big_step, self.ls_options["tolerance"] * self.tolerances["energy"],
               self.ls_options["iter"], self.corrections, self.scale, step)
        # ALBERTO2

        # 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.exit = self.exitstep(self.forces.pot, self.old_u.sum(), d_x_max, self.exit, step)

        # Update positions and forces
        self.old_x[:] = self.beads.q
        self.old_u[:] = self.forces.pots
        self.old_f[:] = self.forces.f

        # Print current instanton geometry and hessian
        if (self.save > 0 and np.mod(step, self.save) == 0) or self.exit:
            print_instanton_geo(self.prefix, step, self.im.dbeads.nbeads, self.im.dbeads.natoms, self.im.dbeads.names,
                                self.im.dbeads.q, self.old_u, self.cell, self.energy_shift, self.output_maker)
Example #29
0
    def step(self, step=None):
        """ Does one simulation time step."""

        self.qtime = -time.time()
        info("\n Instanton optimization STEP %d" % step, verbosity.low)

        if step == 0:
            info(" @GEOP: Initializing INSTANTON", verbosity.low)

            if self.beads.nbeads == 1:
                raise ValueError(
                    "We can not perform an splitting calculation with nbeads =1"
                )
                # get_hessian(self.hessian, self.gm, self.beads.q)
            else:
                if ((self.beads.q - self.beads.q[0]) == 0).all(
                ):  # If the coordinates in all the imaginary time slices are the same
                    info(
                        " @GEOP: We stretch the initial geometry with an 'amplitud' of %4.2f"
                        % self.delta, verbosity.low)
                    imvector = get_imvector(self.initial_hessian,
                                            self.beads.m3[0].flatten())
                    for i in range(self.beads.nbeads):

                        self.beads.q[i, :] += self.delta * np.cos(
                            i * np.pi /
                            float(self.beads.nbeads - 1)) * imvector[:]
                else:
                    info(
                        " @GEOP: Starting from the provided geometry in the extended phase space",
                        verbosity.low)

            # Update positions and forces
            self.old_x[:] = self.beads.q
            self.old_u[:] = self.forces.pots
            self.old_f[:] = self.forces.f

        # This must be done after the stretching and before the self.d.
        if type(self.im.f) == type(None):
            self.im(self.beads.q, ret=False)  # Init instanton mapper

        # Specific for LBFGS
        if np.linalg.norm(self.d) == 0.0:
            f = self.forces.f + self.im.f  #ALBERTO1
            self.d += dstrip(f) / np.sqrt(np.dot(f.flatten(), f.flatten()))

        if (self.old_x == np.zeros((self.beads.nbeads, 3 * self.beads.natoms),
                                   float)).all():
            self.old_x[:] = self.beads.q

        if self.exit:
            softexit.trigger(
                "Geometry optimization converged. Exiting simulation")

        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

        e, g = self.fm(self.beads.q)
        fdf0 = (e, g)

        # Do one step. Update hessian for the new position. Update the position and force inside the mapper.
        L_BFGS(self.old_x, self.d, self.fm, self.qlist, self.glist, fdf0,
               self.big_step,
               self.ls_options["tolerance"] * self.tolerances["energy"],
               self.ls_options["iter"], self.corrections, self.scale, step)
        # ALBERTO2

        # 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.exit = self.exitstep(self.forces.pot, self.old_u.sum(), d_x_max,
                                  self.exit, step)

        # Update positions and forces
        self.old_x[:] = self.beads.q
        self.old_u[:] = self.forces.pots
        self.old_f[:] = self.forces.f

        # Print current instanton geometry and hessian
        if (self.save > 0 and np.mod(step, self.save) == 0) or self.exit:
            print_instanton_geo(self.prefix, step, self.im.dbeads.nbeads,
                                self.im.dbeads.natoms, self.im.dbeads.names,
                                self.im.dbeads.q, self.old_u, self.cell,
                                self.energy_shift)
Example #30
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 = dstrip(beads.q)
        f = dstrip(forces.q)
        qc = dstrip(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()
Example #31
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 = dstrip(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 = dstrip(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(dstrip(self.beads.q), dq1_unit)

        # Reuse initial value since we have energy and forces already
        u0, du0 = (self.forces.pot.copy(), np.dot(dstrip(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)