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
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
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)
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
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