Beispiel #1
0
def numeric_forces(atoms, indices=None, axes=(0, 1, 2), d=0.001,
                   parallel=None, name=None):
    """Evaluate finite-difference forces on several atoms.

    Returns an array of forces for each specified atomic index and
    each specified axis, calculated using finite difference on each
    atom and direction separately.  Array has same shape as if
    returned from atoms.get_forces(); uncalculated elements are zero.

    Calculates all forces by default."""

    if indices is None:
        indices = range(len(atoms))
    F_ai = np.zeros_like(atoms.positions)
    n = len(indices) * len(axes)
    if parallel is None:
        atom_tasks = [atoms] * n
        master = True
        calc_comm = world
    else:
        calc_comm, tasks_comm, tasks_rank = distribute_cpus(parallel, world)
        master = calc_comm.rank == 0
        calculator = atoms.get_calculator()
        calculator.set(communicator=calc_comm)
        atom_tasks = [None] * n
        for i in range(n):
            if ((i - tasks_rank) % tasks_comm.size) == 0:
                atom_tasks[i] = atoms
    for ia, a in enumerate(indices):
        for ii, i in enumerate(axes):
            atoms = atom_tasks[ia * len(axes) + ii]
            if atoms is not None:
                done = 0
                if name:
                    fname = '%s.%d%s.pckl' % (name, a, 'xyz'[i])
                    fd = opencew(fname, calc_comm)
                    if fd is None:
                        if master:
                            try:
                                F_ai[a, i] = pickle.load(open(fname))
                                print '# atom', a, 'xyz'[i], 'done'
                                done = 1
                            except EOFError:
                                pass
                        done = calc_comm.sum(done)
                if not done:
                    print '# rank', rank, 'calculating atom', a, 'xyz'[i]
                    force = numeric_force(atoms, a, i, d)
                    if master:
                        F_ai[a, i] = force
                        if name:
                            fd = open('%s.%d%s.pckl' % (name, a, 'xyz'[i]),
                                      'w')
                            pickle.dump(force, fd)
                            fd.close()
    if parallel is not None:
        world.sum(F_ai)
    return F_ai
Beispiel #2
0
    def calculate_energies_and_forces(self, all=False):
        """Calculate and store the forces and energies for the band."""
        images = self.images

        if all:
            self.forces['real'][0] = images[0].get_forces()
            self.forces['real'][-1] = images[-1].get_forces()
            if not self.integrate_forces:
                self.energies[0] = images[0].get_potential_energy()
                self.energies[-1] = images[-1].get_potential_energy()

        if not self.parallel:
            # Do all images - one at a time:
            for i in range(1, self.nimages - 1):
                self.calculate_image_forces(i)

            for i in range(1, self.nimages - 1):
                self.calculate_image_energies(i)
        else:
            # Parallelize over images: first the forces ...
            i = rank * (self.nimages - 2) // size + 1
            try:
                self.calculate_image_forces(i)
            except:
                # Make sure other images also fail:
                error = world.sum(1.0)
                raise
            else:
                error = world.sum(0.0)
                if error:
                    raise RuntimeError('Parallel NEB failed')
            for i in range(1, self.nimages - 1):
                root = (i - 1) * size // (self.nimages - 2)
                world.broadcast(self.forces['real'][i], root)

            # ... and now the energies
            try:
                self.calculate_image_energies(i)
            except:
                # Make sure other images also fail:
                error = world.sum(1.0)
                raise
            else:
                error = world.sum(0.0)
                if error:
                    raise RuntimeError('Parallel NEB failed')
            for i in range(1, self.nimages - 1):
                root = (i - 1) * size // (self.nimages - 2)
                world.broadcast(self.energies[i : i + 1], root)

        if all and self.integrate_forces:
            # fill in the first and last energies by force integration
            self.energies[0] = 0.
            self.calculate_image_energies(len(self.images)-1)
Beispiel #3
0
def ltidos(cell, eigs, energies, weights=None):
    """DOS from linear tetrahedron interpolation.

    cell: 3x3 ndarray-like
        Unit cell.
    eigs: (n1, n2, n3, nbands)-shaped ndarray
        Eigenvalues on a Monkhorst-Pack grid (not reduced).
    energies: 1-d array-like
        Energies where the DOS is calculated (must be a uniform grid).
    weights: (n1, n2, n3, nbands)-shaped ndarray
        Weights.  Defaults to 1.
    """

    from scipy.spatial import Delaunay

    I, J, K = size = eigs.shape[:3]
    B = (np.linalg.inv(cell) / size).T
    indices = np.array([[i, j, k] for i in [0, 1] for j in [0, 1]
                        for k in [0, 1]])
    dt = Delaunay(np.dot(indices, B))

    dos = np.zeros_like(energies)
    integrate = functools.partial(_lti, energies, dos)

    for s in dt.simplices:
        kpts = dt.points[s]
        try:
            M = np.linalg.inv(kpts[1:, :] - kpts[0, :])
        except np.linalg.linalg.LinAlgError:
            continue
        n = -1
        for i in range(I):
            for j in range(J):
                for k in range(K):
                    n += 1
                    if n % world.size != world.rank:
                        continue
                    E = np.array([
                        eigs[(i + a) % I, (j + b) % J, (k + c) % K]
                        for a, b, c in indices[s]
                    ])
                    if weights is None:
                        integrate(kpts, M, E)
                    else:
                        w = np.array([
                            weights[(i + a) % I, (j + b) % J, (k + c) % K]
                            for a, b, c in indices[s]
                        ])
                        integrate(kpts, M, E, w)

    world.sum(dos)

    return dos * abs(np.linalg.det(cell))
Beispiel #4
0
def opencew(filename, world=None):
    """Create and open filename exclusively for writing.

    If master cpu gets exclusive write access to filename, a file
    descriptor is returned (a dummy file descriptor is returned on the
    slaves).  If the master cpu does not get write access, None is
    returned on all processors."""

    if world is None:
        from ase.parallel import world

    if world.rank == 0:
        try:
            fd = os.open(filename, CEW_FLAGS)
        except OSError as ex:
            error = ex.errno
        else:
            error = 0
            fd = os.fdopen(fd, 'wb')
    else:
        error = 0
        fd = devnull

    # Syncronize:
    error = world.sum(error)
    if error == errno.EEXIST:
        return None
    if error:
        raise OSError(error, 'Error', filename)
    return fd
Beispiel #5
0
def opencew(filename, world=None):
    """Create and open filename exclusively for writing.

    If master cpu gets exclusive write access to filename, a file
    descriptor is returned (a dummy file descriptor is returned on the
    slaves).  If the master cpu does not get write access, None is
    returned on all processors."""

    if world is None:
        from ase.parallel import world

    if world.rank == 0:
        try:
            fd = os.open(filename, CEW_FLAGS)
        except OSError as ex:
            error = ex.errno
        else:
            error = 0
            fd = os.fdopen(fd, 'wb')
    else:
        error = 0
        fd = devnull

    # Syncronize:
    error = world.sum(error)
    if error == errno.EEXIST:
        return None
    if error:
        raise OSError(error, 'Error', filename)
    return fd
Beispiel #6
0
def opencew(filename, world=None):
    """Create and open filename exclusively for writing.

    If master cpu gets exclusive write access to filename, a file
    descriptor is returned (a dummy file descriptor is returned on the
    slaves).  If the master cpu does not get write access, None is
    returned on all processors."""

    if world is None:
        from ase.parallel import world
        
    if world.rank == 0:
        try:
            fd = os.open(filename, os.O_CREAT | os.O_EXCL | os.O_WRONLY)
        except OSError:
            ok = 0
        else:
            ok = 1
            fd = os.fdopen(fd, 'wb')
    else:
        ok = 0
        fd = devnull

    # Syncronize:
    if world.sum(ok) == 0:
        return None
    else:
        return fd
Beispiel #7
0
def _opencew(filename, world=None):
    if world is None:
        from ase.parallel import world

    closelater = []

    def opener(file, flags):
        return os.open(file, flags | CEW_FLAGS)

    try:
        error = 0
        if world.rank == 0:
            try:
                fd = open(filename, 'wb', opener=opener)
            except OSError as ex:
                error = ex.errno
            else:
                closelater.append(fd)
        else:
            fd = open(os.devnull, 'wb')
            closelater.append(fd)

        # Synchronize:
        error = world.sum(error)
        if error == errno.EEXIST:
            return None
        if error:
            raise OSError(error, 'Error', filename)

        return fd
    except BaseException:
        for fd in closelater:
            fd.close()
        raise
Beispiel #8
0
def opencew(filename, world=None):
    """Create and open filename exclusively for writing.

    If master cpu gets exclusive write access to filename, a file
    descriptor is returned (a dummy file descriptor is returned on the
    slaves).  If the master cpu does not get write access, None is
    returned on all processors."""

    if world is None:
        from ase.parallel import world

    if world.rank == 0:
        try:
            fd = os.open(filename, os.O_CREAT | os.O_EXCL | os.O_WRONLY)
        except OSError:
            ok = 0
        else:
            ok = 1
            fd = os.fdopen(fd, 'w')
    else:
        ok = 0
        fd = devnull

    # Syncronize:
    if world.sum(ok) == 0:
        return None
    else:
        return fd
Beispiel #9
0
def lti_dos(simplices, eigs, weights, energies, dos, world):
    shape = eigs.shape[:3]
    nweights = weights.shape[-1]
    dos[:] = 0.0
    n = -1
    for index in np.indices(shape).reshape((3, -1)).T:
        n += 1
        if n % world.size != world.rank:
            continue
        i = ((index + simplices) % shape).T
        E = eigs[i[0], i[1], i[2]].reshape((4, -1))
        W = weights[i[0], i[1], i[2]].reshape((4, -1, nweights))
        for e, w in zip(E.T, W.transpose((1, 0, 2))):
            lti_dos1(e, w, energies, dos)

    dos /= 6.0
    world.sum(dos)
Beispiel #10
0
    def __init__(self,
                 atoms,
                 control=None,
                 eigenmodes=None,
                 random_seed=None,
                 **kwargs):
        self.minmode_init = True
        self.atoms = atoms

        # Initialize to None to avoid strange behaviour due to __getattr__
        self.eigenmodes = eigenmodes
        self.curvatures = None

        if control is None:
            self.control = DimerControl(**kwargs)
            w = 'Missing control object in ' + self.__class__.__name__ + \
                '. Using default: DimerControl()'
            warnings.warn(w, UserWarning)
            if self.control.logfile is not None:
                self.control.logfile.write('DIM:WARN: ' + w + '\n')
                self.control.logfile.flush()
        else:
            self.control = control
            logfile = self.control.get_logfile()
            mlogfile = self.control.get_eigenmode_logfile()
            for key in kwargs:
                if key == 'logfile':
                    logfile = kwargs[key]
                elif key == 'eigenmode_logfile':
                    mlogfile = kwargs[key]
                else:
                    self.control.set_parameter(key, kwargs[key])
            self.control.initialize_logfiles(logfile=logfile,
                                             eigenmode_logfile=mlogfile)

        # Seed the randomness
        if random_seed is None:
            t = time.time()
            if world.size > 1:
                t = world.sum(t) / world.size
            # Harvest the latter part of the current time
            random_seed = int(('%30.9f' % t)[-9:])
        self.random_state = np.random.RandomState(random_seed)

        # Check the order
        self.order = self.control.get_parameter('order')

        # Construct the curvatures list
        self.curvatures = [100.0] * self.order

        # Save the original state of the atoms.
        self.atoms0 = self.atoms.copy()
        self.save_original_forces()

        # Get a reference to the log files
        self.logfile = self.control.get_logfile()
        self.mlogfile = self.control.get_eigenmode_logfile()
Beispiel #11
0
    def __init__(self, atoms, control=None, eigenmodes=None, basis=None, random_seed=None, **kwargs):
        self.minmode_init = True
        self.atoms = atoms

        # Initialize to None to avoid strange behaviour due to __getattr__
        self.eigenmodes = eigenmodes
        self.basis = basis
        self.curvatures = None

        if control is None:
            self.control = DimerControl(**kwargs)
            w = 'Missing control object in ' + self.__class__.__name__ + \
                '. Using default: DimerControl()'
            warnings.warn(w, UserWarning)
            if self.control.logfile is not None:
                self.control.logfile.write('DIM:WARN: ' + w + '\n')
                self.control.logfile.flush()
        else:
            self.control = control
            logfile = self.control.get_logfile()
            mlogfile = self.control.get_eigenmode_logfile()
            for key in kwargs:
                if key == 'logfile':
                    logfile = kwargs[key]
                elif key == 'eigenmode_logfile':
                    mlogfile = kwargs[key]
                else:
                    self.control.set_parameter(key, kwargs[key])
            self.control.initialize_logfiles(logfile = logfile,
                                             eigenmode_logfile = mlogfile)

        # Print the log header
        self.control.log_header()

        # Seed the randomness
        if random_seed is None:
            t = time.time()
            if size > 1:
                t = world.sum(t) / float(size)
            # Harvest the latter part of the current time
            random_seed = int(('%30.9f' % t)[-9:])
        self.random_state = np.random.RandomState(random_seed)

        # Check the order
        self.order = self.control.get_parameter('order')

        # Construct the curvatures list
        self.curvatures = [100.0] * self.order

        # Save the original state of the atoms.
        self.atoms0 = self.atoms.copy()
        self.save_original_forces()

        # Get a reference to the log files
        self.logfile = self.control.get_logfile()
        self.mlogfile = self.control.get_eigenmode_logfile()
Beispiel #12
0
def numeric_forces(atoms,
                   indices=None,
                   axes=(0, 1, 2),
                   d=0.001,
                   parallel=None):
    """Evaluate finite-difference forces on several atoms.

    Returns an array of forces for each specified atomic index and
    each specified axis, calculated using finite difference on each
    atom and direction separately.  Array has same shape as if
    returned from atoms.get_forces(); uncalculated elements are zero.

    Calculates all forces by default."""

    if indices is None:
        indices = range(len(atoms))
    F_ai = np.zeros_like(atoms.positions)
    n = len(indices) * len(axes)
    if parallel is None:
        atom_tasks = [atoms] * n
        master = True
    else:
        calc_comm, tasks_comm, tasks_rank = distribute_cpus(parallel, world)
        master = calc_comm.rank == 0
        calculator = atoms.get_calculator()
        calculator.set(communicator=calc_comm)
        atom_tasks = [None] * n
        for i in range(n):
            if ((i - tasks_rank) % tasks_comm.size) == 0:
                atom_tasks[i] = atoms
    for ia, a in enumerate(indices):
        for ii, i in enumerate(axes):
            atoms = atom_tasks[ia * len(axes) + ii]
            if atoms is not None:
                print '# rank', rank, 'calculating atom', a, 'xyz'[i]
                force = numeric_force(atoms, a, i, d)
                if master:
                    F_ai[a, i] = force
    if parallel is not None:
        world.sum(F_ai)
    return F_ai
Beispiel #13
0
    def calculate_eigenmodes(self):
        if self.parallel:
            i = rank * (self.nimages - 2) // size + 1
            try:
                self.calculate_image_eigenmode(i)
            except:
                # Make sure other images also fail:
                error = world.sum(1.0)
                raise
            else:
                error = world.sum(0.0)
                if error:
                    raise RuntimeError('Parallel ERM failed during eigenmode calculations.')
            for i in range(1, self.nimages - 1):
                if self.images[i].eigenmodes is None:
                    self.images[i].eigenmodes = [np.zeros(self.images[i].get_positions().shape)]
                root = (i - 1) * size // (self.nimages - 2)
                world.broadcast(self.images[i].eigenmodes[0], root)
#                world.broadcast(self.images[i : i + 1].curvatures, root)
        else:
            for i in range(1, self.nimages - 1):
                self.calculate_image_eigenmode(i)
Beispiel #14
0
def numeric_forces(atoms, indices=None, axes=(0, 1, 2), d=0.001,
                   parallel=None):
    """Evaluate finite-difference forces on several atoms.

    Returns an array of forces for each specified atomic index and
    each specified axis, calculated using finite difference on each
    atom and direction separately.  Array has same shape as if
    returned from atoms.get_forces(); uncalculated elements are zero.

    Calculates all forces by default."""

    if indices is None:
        indices = range(len(atoms))
    F_ai = np.zeros_like(atoms.positions)
    n = len(indices) * len(axes)
    if parallel is None:
        atom_tasks = [atoms] * n
        master = True
    else:
        calc_comm, tasks_comm, tasks_rank = distribute_cpus(parallel, world)
        master = calc_comm.rank == 0 
        calculator = atoms.get_calculator()
        calculator.set(communicator=calc_comm)
        atom_tasks = [None] * n
        for i in range(n):
            if ((i - tasks_rank) % tasks_comm.size) == 0:
                atom_tasks[i] = atoms
    for ia, a in enumerate(indices):
        for ii, i in enumerate(axes):
            atoms = atom_tasks[ia * len(axes) + ii]
            if atoms is not None:
                print '# rank', rank, 'calculating atom', a, 'xyz'[i]
                force = numeric_force(atoms, a, i, d)
                if master:
                    F_ai[a, i] = force
    if parallel is not None:
        world.sum(F_ai)
    return F_ai
Beispiel #15
0
def isfile(filename):
    """Check if a file is opened, taking into account the MPI environment
    
    input:
        filename
    output:
        0 when the file does not exist, 1 if it does
    """

    if world.rank == 0:
        isf = os.path.isfile(filename)
    else:
        isf = 0
    # Synchronize:
    return world.sum(isf)
Beispiel #16
0
    def calculate_energies_and_forces(self):
        images = self.images

        if not self.parallel:
            # Do all images - one at a time:
            for i in range(1, self.nimages - 1):
                self.calculate_image_energies_and_forces(i)
        else:
            # Parallelize over images:
            i = rank * (self.nimages - 2) // size + 1
            try:
                self.calculate_image_energies_and_forces(i)
            except:
                # Make sure other images also fail:
                error = world.sum(1.0)
                raise
            else:
                error = world.sum(0.0)
                if error:
                    raise RuntimeError('Parallel NEB failed')
            for i in range(1, self.nimages - 1):
                root = (i - 1) * size // (self.nimages - 2)
                world.broadcast(self.energies[i : i + 1], root)
                world.broadcast(self.forces['real'][i], root)
Beispiel #17
0
    def calculate(self, atoms):
        self.positions = atoms.get_positions().copy()
        self.cell = atoms.get_cell().copy()
        self.pbc = atoms.get_pbc().copy()
        natoms = len(atoms)
        nH2O = natoms // 3

        assert self.pbc.all()
        C = self.cell.diagonal()
        assert not (self.cell - np.diag(C)).any()
        assert (C >= 2 * self.rc2).all()
        self.numbers = atoms.get_atomic_numbers()
        Z = self.numbers.reshape((-1, 3))
        assert (Z[:, 1:] == 1).all() and (Z[:, 0] == 8).all()

        R = self.positions.reshape((nH2O, 3, 3))
        RO = R[:, 0]
        
        self.energy = 0.0
        self.forces = np.zeros((natoms, 3))
        
        if world is None:
            mya = range(nH2O - 1)
        else:
            rank = world.rank
            size = world.size
            assert nH2O // (2 * size) == 0
            mynH2O = nH2O // 2 // size
            mya = (range(rank * n, (rank + 1) * n) +
                   range((size - rank - 1) * n, (size - rank) * n))

        q = np.empty(3)
        q[:] = qH * (units.Hartree * units.Bohr)**0.5
        q[0] *= -2
        
        for a in mya:
            DOO = (RO[a + 1:] - RO[a] + 0.5 * C) % C - 0.5 * C
            dOO = (DOO**2).sum(axis=1)**0.5
            x1 = dOO > self.rc1
            x2 = dOO < self.rc2
            f = np.zeros(nH2O - a - 1)
            f[x2] = 1.0
            dfdd = np.zeros(nH2O - a - 1)
            x12 = np.logical_and(x1, x2)
            d = (dOO[x12] - self.rc1) / (self.rc2 - self.rc1)
            f[x12] -= d**2 * (3.0 - 2.0 * d)
            dfdd[x12] -= 6.0 / (self.rc2 - self.rc1) * d * (1.0 - d)

            y = (sigma0 / dOO)**6
            y2 = y**2
            e = 4 * epsilon0 * (y2 - y)
            self.energy += np.dot(e, f)
            dedd = 24 * epsilon0 * (2 * y2 - y) / dOO * f - e * dfdd
            F = (dedd / dOO)[:, np.newaxis] * DOO
            self.forces[(a + 1) * 3::3] += F
            self.forces[a * 3] -= F.sum(axis=0)

            for i in range(3):
                D = (R[a + 1:] - R[a, i] + 0.5 * C) % C - 0.5 * C
                d = (D**2).sum(axis=2)**0.5
                e = q[i] * q / d
                self.energy += np.dot(f, e).sum()
                F = (e / d**2 * f[:, np.newaxis])[:, :, np.newaxis] * D
                F[:, 0] -= (e.sum(axis=1) * dfdd / dOO)[:, np.newaxis] * DOO 
                self.forces[(a + 1) * 3:] += F.reshape((-1, 3))
                self.forces[a * 3 + i] -= F.sum(axis=0).sum(axis=0)

        if world is not None:
            self.energy = world.sum(self.energy)
            world.sum(self.forces)
Beispiel #18
0
    def calculate(self, atoms):
        self.positions = atoms.get_positions().copy()
        self.cell = atoms.get_cell().copy()
        self.pbc = atoms.get_pbc().copy()
        natoms = len(atoms)
        nH2O = natoms // 3

        assert self.pbc.all()
        C = self.cell.diagonal()
        assert not (self.cell - np.diag(C)).any()
        assert (C >= 2 * self.rc2).all()
        self.numbers = atoms.get_atomic_numbers()
        Z = self.numbers.reshape((-1, 3))
        assert (Z[:, 1:] == 1).all() and (Z[:, 0] == 8).all()

        R = self.positions.reshape((nH2O, 3, 3))
        RO = R[:, 0]
        
        self.energy = 0.0
        self.forces = np.zeros((natoms, 3))
        
        if world.size == 1:
            mya = list(range(nH2O - 1))
        else:
            rank = world.rank
            size = world.size
            assert nH2O // (2 * size) == 0
            mynH2O = nH2O // 2 // size
            mya = (list(range(rank * n, (rank + 1) * n)) +
                   list(range((size - rank - 1) * n, (size - rank) * n)))

        q = np.empty(3)
        q[:] = qH * (units.Hartree * units.Bohr)**0.5
        q[0] *= -2
        
        for a in mya:
            DOO = (RO[a + 1:] - RO[a] + 0.5 * C) % C - 0.5 * C
            dOO = (DOO**2).sum(axis=1)**0.5
            x1 = dOO > self.rc1
            x2 = dOO < self.rc2
            f = np.zeros(nH2O - a - 1)
            f[x2] = 1.0
            dfdd = np.zeros(nH2O - a - 1)
            x12 = np.logical_and(x1, x2)
            d = (dOO[x12] - self.rc1) / (self.rc2 - self.rc1)
            f[x12] -= d**2 * (3.0 - 2.0 * d)
            dfdd[x12] -= 6.0 / (self.rc2 - self.rc1) * d * (1.0 - d)

            y = (sigma0 / dOO)**6
            y2 = y**2
            e = 4 * epsilon0 * (y2 - y)
            self.energy += np.dot(e, f)
            dedd = 24 * epsilon0 * (2 * y2 - y) / dOO * f - e * dfdd
            F = (dedd / dOO)[:, np.newaxis] * DOO
            self.forces[(a + 1) * 3::3] += F
            self.forces[a * 3] -= F.sum(axis=0)

            for i in range(3):
                D = (R[a + 1:] - R[a, i] + 0.5 * C) % C - 0.5 * C
                d = (D**2).sum(axis=2)**0.5
                e = q[i] * q / d
                self.energy += np.dot(f, e).sum()
                F = (e / d**2 * f[:, np.newaxis])[:, :, np.newaxis] * D
                F[:, 0] -= (e.sum(axis=1) * dfdd / dOO)[:, np.newaxis] * DOO 
                self.forces[(a + 1) * 3:] += F.reshape((-1, 3))
                self.forces[a * 3 + i] -= F.sum(axis=0).sum(axis=0)

        self.energy = world.sum(self.energy)
        world.sum(self.forces)
Beispiel #19
0
    def numeric_forces(self,atoms, axes=(0, 1, 2), d=0.001,
                       parallel=None, name=None):
        """Evaluate finite-difference forces on several atoms.

        Returns an array of forces for each specified atomic index and
        each specified axis, calculated using finite difference on each
        atom and direction separately.  Array has same shape as if
        returned from atoms.get_forces(); uncalculated elements are zero.

        Calculates all forces by default."""

        import numpy as np
        from ase.parallel import world, rank, distribute_cpus
        from ase.utils import opencew

        indices = range(len(atoms))
        F_ai = np.zeros_like(atoms.positions)
        n = len(indices) * len(axes)
        total_calculation = len(indices)*len(axes)

        if parallel is None:
            atom_tasks = [atoms] * n
            master = True
            calc_comm = world
        else:
            calc_comm, tasks_comm, tasks_rank = distribute_cpus(parallel, world)
            master = calc_comm.rank == 0
            calculator = atoms.get_calculator()
            calculator.set(communicator=calc_comm)
            atom_tasks = [None] * n
            for i in range(n):
                if ((i - tasks_rank) % tasks_comm.size) == 0:
                    atom_tasks[i] = atoms
        counter = 0
        for ia, a in enumerate(indices):
            for ii, i in enumerate(axes):
                atoms = atom_tasks[ia * len(axes) + ii]
                if atoms is not None:
                    done = 0
                    if name:
                        fname = '%s.%d%s.pckl' % (name, a, 'xyz'[i])
                        fd = opencew(fname, calc_comm)
                        if fd is None:
                            if master:
                                try:
                                    F_ai[a, i] = pickle.load(open(fname))
                                    print '# atom', a, 'xyz'[i], 'done'
                                    done = 1
                                except EOFError:
                                    pass
                            done = calc_comm.sum(done)
                    if not done:
                        # print '# rank', rank, 'calculating atom', a, 'xyz'[i]
                        force = self.__numeric_force(atoms, a, i, d)
                        if master:
                            F_ai[a, i] = force
                            if name:
                                fd = open('%s.%d%s.pckl' % (name, a, 'xyz'[i]),
                                          'w')
                                pickle.dump(force, fd)
                                fd.close()
                counter += 1
                fan = ['-', '\\', '|', '/']
                sys.stderr.write("\r[%-100s]%3.1f%% %1s" % tuple([int(float(counter)/float(total_calculation)*100)*'=',float(counter)/float(total_calculation)*100,fan[counter%4]]))
                sys.stderr.flush()
        if parallel is not None:
            world.sum(F_ai)
        return F_ai
Beispiel #20
0
    def numeric_forces(self,
                       atoms,
                       axes=(0, 1, 2),
                       d=0.001,
                       parallel=None,
                       name=None):
        """Evaluate finite-difference forces on several atoms.

        Returns an array of forces for each specified atomic index and
        each specified axis, calculated using finite difference on each
        atom and direction separately.  Array has same shape as if
        returned from atoms.get_forces(); uncalculated elements are zero.

        Calculates all forces by default."""

        import numpy as np
        from ase.parallel import world, rank, distribute_cpus
        from ase.utils import opencew

        indices = range(len(atoms))
        F_ai = np.zeros_like(atoms.positions)
        n = len(indices) * len(axes)
        total_calculation = len(indices) * len(axes)

        if parallel is None:
            atom_tasks = [atoms] * n
            master = True
            calc_comm = world
        else:
            calc_comm, tasks_comm, tasks_rank = distribute_cpus(
                parallel, world)
            master = calc_comm.rank == 0
            calculator = atoms.get_calculator()
            calculator.set(communicator=calc_comm)
            atom_tasks = [None] * n
            for i in range(n):
                if ((i - tasks_rank) % tasks_comm.size) == 0:
                    atom_tasks[i] = atoms
        counter = 0
        for ia, a in enumerate(indices):
            for ii, i in enumerate(axes):
                atoms = atom_tasks[ia * len(axes) + ii]
                if atoms is not None:
                    done = 0
                    if name:
                        fname = '%s.%d%s.pckl' % (name, a, 'xyz'[i])
                        fd = opencew(fname, calc_comm)
                        if fd is None:
                            if master:
                                try:
                                    F_ai[a, i] = pickle.load(open(fname))
                                    print '# atom', a, 'xyz'[i], 'done'
                                    done = 1
                                except EOFError:
                                    pass
                            done = calc_comm.sum(done)
                    if not done:
                        # print '# rank', rank, 'calculating atom', a, 'xyz'[i]
                        force = self.__numeric_force(atoms, a, i, d)
                        if master:
                            F_ai[a, i] = force
                            if name:
                                fd = open('%s.%d%s.pckl' % (name, a, 'xyz'[i]),
                                          'w')
                                pickle.dump(force, fd)
                                fd.close()
                counter += 1
                fan = ['-', '\\', '|', '/']
                sys.stderr.write("\r[%-100s]%3.1f%% %1s" % tuple([
                    int(float(counter) / float(total_calculation) * 100) * '=',
                    float(counter) / float(total_calculation) * 100,
                    fan[counter % 4]
                ]))
                sys.stderr.flush()
        if parallel is not None:
            world.sum(F_ai)
        return F_ai
Beispiel #21
0
 def __len__(self):
     return world.sum(len(self.backend))
Beispiel #22
0
 def __len__(self):
     return world.sum(len(self.backend))
Beispiel #23
0
def numeric_forces(atoms,
                   indices=None,
                   axes=(0, 1, 2),
                   d=0.001,
                   parallel=None,
                   name=None):
    """Evaluate finite-difference forces on several atoms.

    Returns an array of forces for each specified atomic index and
    each specified axis, calculated using finite difference on each
    atom and direction separately.  Array has same shape as if
    returned from atoms.get_forces(); uncalculated elements are zero.

    Calculates all forces by default."""

    if indices is None:
        indices = range(len(atoms))
    F_ai = np.zeros_like(atoms.positions)
    n = len(indices) * len(axes)
    if parallel is None:
        atom_tasks = [atoms] * n
        master = True
        calc_comm = world
    else:
        calc_comm, tasks_comm, tasks_rank = distribute_cpus(parallel, world)
        master = calc_comm.rank == 0
        calculator = atoms.get_calculator()
        calculator.set(communicator=calc_comm)
        atom_tasks = [None] * n
        for i in range(n):
            if ((i - tasks_rank) % tasks_comm.size) == 0:
                atom_tasks[i] = atoms
    for ia, a in enumerate(indices):
        for ii, i in enumerate(axes):
            atoms = atom_tasks[ia * len(axes) + ii]
            if atoms is not None:
                done = 0
                if name:
                    fname = '%s.%d%s.pckl' % (name, a, 'xyz'[i])
                    fd = opencew(fname, calc_comm)
                    if fd is None:
                        if master:
                            try:
                                F_ai[a, i] = pickle.load(open(fname))
                                print '# atom', a, 'xyz'[i], 'done'
                                done = 1
                            except EOFError:
                                pass
                        done = calc_comm.sum(done)
                if not done:
                    print '# rank', rank, 'calculating atom', a, 'xyz'[i]
                    force = numeric_force(atoms, a, i, d)
                    if master:
                        F_ai[a, i] = force
                        if name:
                            fd = open('%s.%d%s.pckl' % (name, a, 'xyz'[i]),
                                      'w')
                            pickle.dump(force, fd)
                            fd.close()
    if parallel is not None:
        world.sum(F_ai)
    return F_ai