Example #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
Example #2
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
Example #3
0
    def __init__(self, lrtddft, d=0.001, txt=None, parallel=None):
        """Finite difference calculator for LrTDDFT.

        parallel: Can be used to parallelize the numerical force 
        calculation over images
        """
        self.timer = Timer()
        self.atoms = None

        world = mpi.world
        if lrtddft is not None:
            self.lrtddft = lrtddft
            self.calculator = self.lrtddft.calculator
            self.atoms = self.calculator.atoms
            if self.calculator.initialized:
                world = self.calculator.wfs.world

            if txt is None:
                self.txt = self.lrtddft.txt
            else:
                self.txt, firsttime = initialize_text_stream(
                    txt, world.rank)
        prnt('#', self.__class__.__name__, version, file=self.txt)
                                                              
        self.d = d
        self.parallel = {
            'world' : world, 'mycomm' : world, 'ncalcs' : 1, 'icalc' : 0 }
        if world.size < 2:
            if parallel > 0:
                prnt('#', (self.__class__.__name__ + ':'), 
                     'Serial calculation, keyword parallel ignored.',
                     file=self.txt)
        elif parallel > 0:
            mycomm, ncalcs, icalc = distribute_cpus(parallel, world)
            if type(ncalcs) != type(1):
                # this is ase < r3431
                ncalcs = world.size / parallel
            self.parallel = { 'world' : world, 'mycomm' : mycomm, 
                              'ncalcs' : ncalcs, 'icalc' : icalc }
            self.calculator.set(communicator=mycomm)
    def __init__(self, lrtddft, d=0.001, txt=None, parallel=None):
        """Finite difference calculator for LrTDDFT.

        parallel: Can be used to parallelize the numerical force
        calculation over images
        """
        self.timer = Timer()
        self.atoms = None

        world = mpi.world
        if lrtddft is not None:
            self.lrtddft = lrtddft
            self.calculator = self.lrtddft.calculator
            self.atoms = self.calculator.atoms
            if self.calculator.initialized:
                world = self.calculator.wfs.world

            if txt is None:
                self.txt = self.lrtddft.txt
            else:
                self.txt = get_txt(txt, world.rank)
        prnt('#', self.__class__.__name__, version, file=self.txt)

        self.d = d
        self.parallel = {
            'world': world, 'mycomm': world, 'ncalcs': 1, 'icalc': 0}
        if world.size < 2:
            if parallel > 0:
                prnt('#', (self.__class__.__name__ + ':'),
                     'Serial calculation, keyword parallel ignored.',
                     file=self.txt)
        elif parallel > 0:
            mycomm, ncalcs, icalc = distribute_cpus(parallel, world)
            if type(ncalcs) != type(1):
                # this is ase < r3431
                ncalcs = world.size / parallel
            self.parallel = {'world': world, 'mycomm': mycomm,
                             'ncalcs': ncalcs, 'icalc': icalc}
            self.calculator.set(communicator=mycomm)
Example #5
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
Example #6
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
Example #7
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
Example #8
0
File: test.py Project: grhawk/ASE
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