def dftb_read_input(folder): """Read a DFTB+ output non-destructively. Args: directory (str): path to a directory to load DFTB+ results Returns: atoms (ase.Atoms): an atomic structure with the results attached in a SinglePointCalculator """ atoms = io.read(os.path.join(folder, 'geo_end.gen')) atoms.info['name'] = os.path.split(folder)[-1] results_file = os.path.join(folder, "results.tag") if os.path.isfile(results_file): # DFTB+ was used to perform the optimisation temp_file = os.path.join(folder, "results.tag.bak") # We need to backup the results file here because # .read_results() will remove the results file with BackupFile(results_file, temp_file): calc = Dftb(atoms=atoms) calc.atoms_input = atoms calc.directory = folder calc.do_forces = True try: calc.read_results() except: # Failed for ANY reason atoms.set_calculator(None) return atoms energy = calc.get_potential_energy() forces = calc.get_forces() charges = calc.get_charges(atoms) calc = SinglePointCalculator(atoms, energy=energy, forces=forces, charges=charges) atoms.set_calculator(calc) return atoms
def create_spinpol_dftbp_calculator(calc=None, param_set='3ob-3-1', kpts=None): """Create a calculator containing all necessary parameters for a DFTB+ SCC spin polarised calculation""" from pymuonsuite.data.dftb_pars import DFTBArgs if not isinstance(calc, Dftb): calc = Dftb() else: calc = deepcopy(calc) # A bit of a hack for the k-points if kpts is not None: kc = Dftb(kpts=kpts) kargs = {k: v for k, v in kc.parameters.items() if 'KPoints' in k} calc.parameters.update(kargs) # Create the arguments dargs = DFTBArgs(param_set) # Make it spin polarised try: dargs.set_optional('spinpol.json', True) except KeyError: raise ValueError('DFTB+ parameter set does not allow spin polarised' ' calculations') # Fix a few things, and add a spin on the muon args = dargs.args del (args['Hamiltonian_SpinPolarisation']) args['Hamiltonian_SpinPolarisation_'] = 'Colinear' args['Hamiltonian_SpinPolarisation_UnpairedElectrons'] = 1 args['Hamiltonian_SpinPolarisation_InitialSpins_'] = '' args['Hamiltonian_SpinPolarisation_InitialSpins_Atoms'] = '-1' args['Hamiltonian_SpinPolarisation_InitialSpins_SpinPerAtom'] = 1 calc.parameters.update(args) calc.do_forces = True return calc
def read(self, folder, sname=None, read_spinpol=False, read_phonons=False, **kwargs): ''' Read a DFTB+ output non-destructively. | | Args: | folder (str) : path to a directory to load DFTB+ results | sname (str): name to label the atoms with and/or of the | .phonons.pkl file to be read | Returns: | atoms (ase.Atoms): an atomic structure with the results | attached in a SinglePointCalculator ''' try: with silence_stdio(): atoms = io.read(os.path.join(folder, 'geo_end.gen')) except IOError: raise IOError("ERROR: No geo_end.gen file found in {}." .format(os.path.abspath(folder))) except Exception as e: raise IOError("ERROR: Could not read {file}, due to error: {error}" .format(file='geo_end.gen', error=e)) if sname is None: atoms.info['name'] = os.path.split(folder)[-1] else: atoms.info['name'] = sname results_file = os.path.join(folder, "results.tag") if os.path.isfile(results_file): # DFTB+ was used to perform the optimisation temp_file = os.path.join(folder, "results.tag.bak") # We need to backup the results file here because # .read_results() will remove the results file with BackupFile(results_file, temp_file): calc = Dftb(atoms=atoms) calc.atoms_input = atoms calc.directory = folder calc.do_forces = True calc.read_results() energy = calc.get_potential_energy() forces = calc.get_forces() charges = calc.get_charges(atoms) calc = SinglePointCalculator(atoms, energy=energy, forces=forces, charges=charges) atoms.calc = calc if read_spinpol: try: pops = parse_spinpol_dftb(folder) hfine = [] for i in range(len(atoms)): hf = compute_hfine_mullpop(atoms, pops, self_i=i, fermi=True, fermi_neigh=True) hfine.append(hf) atoms.set_array('hyperfine', np.array(hfine)) except (IndexError, IOError) as e: raise IOError('Could not read hyperfine details due to error: ' '{0}'.format(e)) if read_phonons: try: if sname is not None: phonon_source_file = os.path.join(folder, sname + '.phonons.pkl') else: print("Phonons filename was not given, searching for any" " .phonons.pkl file.") phonon_source_file = glob.glob( os.path.join(folder, '*.phonons.pkl'))[0] self._read_dftb_phonons(atoms, phonon_source_file) except IndexError: raise IOError("No .phonons.pkl files found in {}." .format(os.path.abspath(folder))) except IOError: raise IOError("{} could not be found." .format(phonon_source_file)) except Exception as e: raise IOError('Could not read {file} due to error: {error}' .format(file=phonon_source_file, error=e)) return atoms