def test_read_from_file(self): # no becs, so no splitting. The test only checks the parsing ddb = DdbFile(os.path.join(test_dir, "ZnO_gamma_becs_DDB")) phbands = ddb.anaget_phmodes_at_qpoint(qpoint=[0, 0, 0], lo_to_splitting=True) phbands.non_anal_phfreqs
def run_anaddb(self, dipdip=1): print("Run anaddb") #os.system('cp ./abinit.mrgddb.tmpl %s/abinit.mrgddb.in' % self.dirname) gen_mrgddb_input(self.dirname) os.chdir(self.dirname) os.system('mrgddb <abinit.mrgddb.in>abinit.mrgddb.log') myDDB = DdbFile(filepath='abinit_mrgddb.out', read_blocks=True) nqpts = ' '.join(map(str, myDDB._guess_ngqpt())) natifc = len(self.atoms) atifc = ' '.join([str(i + 1) for i in range(len(self.atoms))]) dipdip = dipdip tdict = { 'nqpts': nqpts, 'natifc': natifc, 'atifc': atifc, 'dipdip': dipdip } with open("../abinit_ifc.in.tmpl") as myfile: tmpl = string.Template(myfile.read()) text = tmpl.substitute(tdict) os.system('cp ../abinit_ifc.files.tmpl abinit_ifc.files') with open('abinit_ifc.in', 'w') as myfile: myfile.write(text) #os.system('cp ../abinit_ifc.in.tmpl %s/abinit_ifc.in' % self.dirname) os.system('anaddb <abinit_ifc.files >abinit_ifc.log') os.chdir('../')
def read_DDB_info(name='LiNbO3'): myDDB = DdbFile(filepath='%s/abinit_mrgddb.out' % name, read_blocks=True) #print(myDDB._guess_ngqpt()) #print(myDDB.params) qpoints = OrderedDict([('Gamma', (0, 0, 0)), ('X', (0.5, 0, 0)), ('M', (0.5, 0.5, 0)), ('R', (0.5, 0.5, 0.5))]) #qpoints=OrderedDict() #Full phonon band. # band without LO-TO # band with LO-TO # Born effective charge emacro, becs = myDDB.anaget_emacro_and_becs() #print("") #print("Macroscopic dielectric: ", emacro) #print("Born effective charges: ", becs) # dielectric # piezoelectricity # Analysis for each Q point. for qname in qpoints: #print("=============") #print("Qpoint: %s: %s" % (qname, qpoints[qname], )) #print(myDDB.qindex(qpoints[qname])) myphon_bands = myDDB.anaget_phmodes_at_qpoint(qpoint=qpoints[qname], workdir=None)
def test_read_from_file(self): """Testing non-analytical terms.""" # no becs, so no splitting. The test only checks the parsing with DdbFile(os.path.join(test_dir, "ZnO_gamma_becs_DDB")) as ddb: phbands = ddb.anaget_phmodes_at_qpoint(qpoint=[0, 0, 0], lo_to_splitting=True) assert phbands.amu is not None #print(phbands.amu) # FIXME: I don't like that we Z as key in amu. Should be the symbol self.assert_almost_equal(phbands.amu[30.0], 0.6539e+02) self.assert_almost_equal(phbands.amu[8.0], 0.159994e+02) self.assert_almost_equal(phbands.amu_symbol["Zn"], phbands.amu[30.0]) self.assert_almost_equal(phbands.amu_symbol["O"], phbands.amu[8.0]) assert phbands.non_anal_ph is not None repr(phbands.non_anal_ph) str(phbands.non_anal_ph) assert phbands.structure == phbands.non_anal_ph.structure #assert phbands.non_anal_ph.has_direction(direction=, cartesian=False) # TODO should check numerical values (?) assert phbands.non_anal_phfreqs is not None assert phbands.non_anal_directions is not None assert phbands.non_anal_phdispl_cart is not None assert phbands.non_anal_dyn_mat_eigenvect is not None
def abinp_anaph(options): """Build Anaddb input file for the computation of phonon bands DOS.""" ddb = DdbFile(options.filepath) nqsmall = 10 inp = AnaddbInput.phbands_and_dos(ddb.structure, ddb.guessed_ngqpt, nqsmall, ndivsm=20, q1shft=(0, 0, 0), qptbounds=None, asr=2, chneut=0, dipdip=1, dos_method="tetra", lo_to_splitting=False, anaddb_args=None, anaddb_kwargs=None) return finalize(inp, options)
def test_zno_gamma_ddb_with_becs(self): """Testing DDB for ZnO: Gamma only, with Born effective charges and E_macro.""" with DdbFile(os.path.join(test_dir, "ZnO_gamma_becs_DDB")) as ddb: repr(ddb) str(ddb) assert str(ddb.header) assert ddb.to_string(verbose=2) assert ddb.header["nkpt"] == 486 assert ddb.header.nband == 22 and ddb.header.occopt == 1 self.assert_equal(ddb.header.typat, [1, 1, 2, 2]) assert len(ddb.header.wtk) == ddb.header.nkpt #assert ddb.header.occ.shape = (ddb.header.nsppol, ddb.header.nkpt, ddb.header.nsppol) assert not ddb.has_qpoint([0.345, 0.456, 0.567]) assert ddb.has_qpoint([0, 0, 0]) assert len(ddb.qpoints) == 1 for qpoint in ddb.qpoints: assert ddb.has_qpoint(qpoint) assert ddb.has_qpoint(qpoint.frac_coords) assert qpoint in ddb.computed_dynmat assert len(ddb.computed_dynmat[qpoint].index[0]) == 4 # Test Lru_cache as well assert ddb.has_bec_terms(select="at_least_one") assert ddb.has_bec_terms(select="at_least_one") assert not ddb.has_bec_terms(select="all") assert not ddb.has_bec_terms(select="all") assert ddb.has_emacro_terms() assert ddb.has_lo_to_data() # Get emacro and becs emacro, becs = ddb.anaget_emacro_and_becs(chneut=1, verbose=1) ref_becs_values = [ [[2.15646571e+00, 0.00000000e+00, 3.26402110e-25], [0.00000000e+00, 2.15646571e+00, -5.46500204e-24], [-5.66391495e-25, -6.54012564e-25, 2.19362823e+00]], [[2.15646571e+00, 0.00000000e+00, 1.19680774e-24], [0.00000000e+00, 2.15646571e+00, 8.10327888e-24], [-1.69917448e-24, -1.30802513e-24, 2.19362823e+00]], [[-2.15646571e+00, 6.66133815e-16, -1.84961196e-24], [8.88178420e-16, -2.15646571e+00, 2.82672519e-24], [-3.39834897e-24, -3.27006282e-25, -2.19362823e+00]], [[-2.15646571e+00, -6.66133815e-16, 3.26402110e-25], [-8.88178420e-16, -2.15646571e+00, -5.46500204e-24], [5.66391495e-24, 2.28904397e-24, -2.19362823e+00]] ] self.assert_almost_equal(becs.values, ref_becs_values) #self.assert_almost_equal(emacro.values, ref_emacro_values) repr(becs) str(becs) assert becs.to_string(verbose=2) # get the dielectric tensor generator from anaddb dtg = ddb.anaget_dielectric_tensor_generator(verbose=2) assert dtg is not None and hasattr(dtg, "phfreqs")
def test_alas_ddb_1qpt_phonons(self): """Testing DDB with one q-point""" ddb_fname = os.path.join(test_dir, "AlAs_1qpt_DDB") with DdbFile(ddb_fname) as ddb: print(ddb) # Test qpoints. assert np.all(ddb.qpoints[0] == [0.25, 0, 0]) assert len(ddb.qpoints) == 1 # Test header h = ddb.header assert h.version == 100401 and h.ecut == 3 assert "ecut" in h and h["ecut"] == h.ecut assert h.occ == 4 * [2] assert h.xred.shape == (h.natom, 3) and h.kpt.shape == (h.nkpt, 3) print(h.znucl) assert "ecut" in ddb.params assert np.all( h.symrel[1].T.ravel() == [0, -1, 1, 0, -1, 0, 1, -1, 0]) assert np.all( h.symrel[2].T.ravel() == [-1, 0, 0, -1, 0, 1, -1, 1, 0]) # Test structure struct = ddb.structure assert struct.formula == "Al1 As1" # Test interface with Anaddb. print(ddb.qpoints[0]) assert ddb.qindex(ddb.qpoints[0]) == 0 phbands = ddb.anaget_phmodes_at_qpoint(qpoint=ddb.qpoints[0], verbose=1) assert phbands is not None and hasattr(phbands, "phfreqs") # Wrong qpoint with self.assertRaises(ValueError): ddb.anaget_phmodes_at_qpoint(qpoint=(0, 0, 0), verbose=1) # Wrong ngqpt with self.assertRaises(ddb.AnaddbError): ddb.anaget_phbst_and_phdos_files(ngqpt=(4, 4, 4), verbose=1) # Cannot compute DOS since we need a mesh. with self.assertRaises(ddb.AnaddbError): ddb.anaget_phbst_and_phdos_files(verbose=1) # Test notebook if self.has_nbformat(): ddb.write_notebook(nbpath=self.get_tmpname(text=True))
def run_qlist(self, nqsmall_list, **kwargs): """ """ self.qha_list = [] self.ngqpt_list = [] ddb_list = [DdbFile(p) for p in self.ddb_paths] for nqsmall in nqsmall_list: phdos_paths = [] for i, ddb in enumerate(ddb_list): phbst_file, phdos_file = ddb.anaget_phbst_and_phdos_files( nqsmall=nqsmall, qppa=None, ndivsm=1, line_density=None, asr=2, chneut=1, dipdip=1, dos_method="tetra", lo_to_splitting="automatic", ngqpt=None, qptbounds=None, anaddb_kwargs=None, verbose=0, spell_check=True, mpi_procs=1, workdir=None, manager=None) phdos_paths.append(phdos_file.filepath) if i == 0: # These variables added in abinit v8.11. Use nqsmall is not available. ngqpt = 3 * [nqsmall] if "qptrlatt" in phdos_file.reader.rootgrp.variables: ngqpt = np.diagonal( phdos_file.reader.read_value("qptrlatt").T) #shiftq = phdos_file.reader.read_value("shiftq") self.ngqpt_list.append(ngqpt) phbst_file.close() phdos_file.close() qha = QHA.from_files(self.gsr_paths, phdos_paths) self.qha_list.append(qha) self.ngqpt_list = np.reshape(self.ngqpt_list, (-1, 3)) self.num_qmeshes = len(self.ngqpt_list) for ddb in ddb_list: ddb.close()
def test_alas_ddb_444_nobecs(self): """Testing DDB for AlAs on a 4x4x4x q-mesh without Born effective charges.""" ddb = DdbFile(os.path.join(test_dir, "AlAs_444_nobecs_DDB")) print(ddb) print(ddb.header) ref_qpoints = np.reshape([ 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 2.50000000E-01, 0.00000000E+00, 0.00000000E+00, 5.00000000E-01, 0.00000000E+00, 0.00000000E+00, 2.50000000E-01, 2.50000000E-01, 0.00000000E+00, 5.00000000E-01, 2.50000000E-01, 0.00000000E+00, -2.50000000E-01, 2.50000000E-01, 0.00000000E+00, 5.00000000E-01, 5.00000000E-01, 0.00000000E+00, -2.50000000E-01, 5.00000000E-01, 2.50000000E-01, ], (-1, 3)) assert len(ddb.qpoints) == 8 for qpt, ref_qpt in zip(ddb.qpoints, ref_qpoints): assert qpt == ref_qpt for qpoint in ddb.qpoints: phbands = ddb.anaget_phmodes_at_qpoint(qpoint=qpoint) assert phbands is not None and hasattr(phbands, "phfreqs") assert np.all(ddb.guessed_ngqpt == [4, 4, 4]) # Get bands and Dos phbands_file, phdos_file = ddb.anaget_phbst_and_phdos_files() phbands, phdos = phbands_file.phbands, phdos_file.phdos if have_matplotlib: phbands.plot_with_phdos(phdos, title="Phonon bands and DOS of %s" % phbands.structure.formula, show=False) # Thermodinamics in the Harmonic approximation harmo = phdos.get_harmonic_thermo(tstart=10, tstop=50) harmo.plot(show=False) self.assert_almost_equal(phdos.idos.values[-1], 3 * len(ddb.structure), decimal=1) phbands_file.close() phdos_file.close() c = ddb.anacompare_phdos(nqsmalls=[2, 4, 6], num_cpus=None) c.plotter.plot(show=False) ddb.close()
def from_ddb(cls, ddb, ebands_kpath, ebands_kmesh=None, **kwargs): """ Build the object from the ddb file, invoke anaddb to get phonon properties. This entry point is needed to have phonon plots with LO-TO splitting as AbiPy will generate an anaddb input with the different q --> 0 directions required in phbands.plot to plot the LO-TO splitting correctly. Args: ddb: |DdbFile| or filepath. ebands_kpath: |ElectronBands| with energies on a k-path or filepath. ebands_kpath: (optional) |ElectronBands| with energies on a k-mesh or filepath. kwargs: Passed to anaget_phbst_and_phdos_files """ ddb = DdbFile.as_ddb(ddb) phbst_file, phdos_file = ddb.anaget_phbst_and_phdos_files(**kwargs) return cls(ebands_kpath, phbst_file, phdos_file, ebands_kmesh=ebands_kmesh)
def test_alas_ddb_444_nobecs(self): """Testing DDB for AlAs on a 4x4x4x q-mesh without Born effective charges.""" ddb = DdbFile(os.path.join(test_dir, "AlAs_444_nobecs_DDB")) print(ddb) print(ddb.header) ref_qpoints = np.reshape([ 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 2.50000000E-01, 0.00000000E+00, 0.00000000E+00, 5.00000000E-01, 0.00000000E+00, 0.00000000E+00, 2.50000000E-01, 2.50000000E-01, 0.00000000E+00, 5.00000000E-01, 2.50000000E-01, 0.00000000E+00, -2.50000000E-01, 2.50000000E-01, 0.00000000E+00, 5.00000000E-01, 5.00000000E-01, 0.00000000E+00, -2.50000000E-01, 5.00000000E-01, 2.50000000E-01, ], (-1, 3)) assert len(ddb.qpoints) == 8 for qpt, ref_qpt in zip(ddb.qpoints, ref_qpoints): assert qpt == ref_qpt for qpoint in ddb.qpoints: phbands = ddb.anaget_phmodes_at_qpoint(qpoint=qpoint) assert phbands is not None and hasattr(phbands, "phfreqs") assert np.all(ddb.guessed_ngqpt == [4, 4, 4]) # Get bands and Dos phbands_file, phdos_file = ddb.anaget_phbst_and_phdos_files() phbands, phdos = phbands_file.phbands, phdos_file.phdos if self.has_matplotlib(): phbands.plot_with_phdos(phdos, title="Phonon bands and DOS of %s" % phbands.structure.formula, show=False) # Thermodinamics in the Harmonic approximation harmo = phdos.get_harmonic_thermo(tstart=10, tstop=50) if self.has_matplotlib(): harmo.plot(show=False) self.assert_almost_equal(phdos.idos.values[-1], 3 * len(ddb.structure), decimal=1) phbands_file.close() phdos_file.close() c = ddb.anacompare_phdos(nqsmalls=[2, 4, 6], num_cpus=None) if self.has_matplotlib(): c.plotter.plot(show=False) ddb.close()
def itest_frohlich_zpr_flow(fwp, tvars): """ """ # Build the SCF input. scf_input = make_scf_input() # Build the flow. from abipy.flowtk.effmass_works import FrohlichZPRFlow flow = FrohlichZPRFlow.from_scf_input(fwp.workdir, scf_input, ddb_node=None, ndivsm=2, tolwfr=1e-10, manager=fwp.manager, metadata=dict(mp_id="mp-123")) scheduler = flow.make_scheduler() assert scheduler.start() == 0 flow.check_status(show=True) assert all(work.finalized for work in flow) if not flow.all_ok: flow.debug() raise RuntimeError() assert flow.on_all_ok_num_calls == 1 # Reconstruct python objects from JSON file. data = abilab.mjson_load(flow.outdir.path_in("zprfrohl_results.json")) assert data["metadata"]["mp_id"] == "mp-123" assert data["structure"].formula == 'Ca1 O1' ebands_kpath = data["ebands_kpath"] assert ebands_kpath.nsppol == 1 assert ebands_kpath.kpoints.is_path assert ebands_kpath.homos[0].kpoint == [0, 0, 0] assert ebands_kpath.lumos[0].kpoint == [0.5, 0, 0.5] with DdbFile.from_string(data["ddb_string"]) as ddb: assert ddb.structure.formula == 'Ca1 O1' assert ddb.has_bec_terms(select="at_least_one") assert ddb.has_epsinf_terms(select="at_least_one_diagoterm") assert data["epsinf_cart"].shape == data["eps0_cart"].shape
def test_alas_ddb_1qpt_phonons(self): """Testing DDB with one q-point""" with DdbFile(os.path.join(test_dir, "AlAs_1qpt_DDB")) as ddb: repr(ddb) str(ddb) # Test qpoints. assert len(ddb.qpoints) == 1 assert np.all(ddb.qpoints[0] == [0.25, 0, 0]) assert ddb.natom == len(ddb.structure) s = ddb.get_string() with DdbFile.from_string(s) as same_ddb: assert same_ddb.qpoints[0] == ddb.qpoints[0] assert same_ddb.structure == ddb.structure # Test header h = ddb.header assert h.version == 100401 and h.ecut == 3 assert "ecut" in h and h["ecut"] == h.ecut assert "ixc" in ddb.params assert ddb.params["ixc"] == 7 assert h.occ == 4 * [2] assert h.xred.shape == (h.natom, 3) and h.kpt.shape == (h.nkpt, 3) self.assert_equal(h.znucl, [13, 33]) assert ddb.version == 100401 assert ddb.total_energy is None assert ddb.cart_forces is None assert ddb.cart_stress_tensor is None assert np.all( h.symrel[1].T.ravel() == [0, -1, 1, 0, -1, 0, 1, -1, 0]) assert np.all( h.symrel[2].T.ravel() == [-1, 0, 0, -1, 0, 1, -1, 1, 0]) # Test structure struct = ddb.structure assert struct.formula == "Al1 As1" # Test interface with Anaddb. str(ddb.qpoints[0]) assert ddb.qindex(ddb.qpoints[0]) == 0 phbands = ddb.anaget_phmodes_at_qpoint(qpoint=ddb.qpoints[0], verbose=1) assert phbands is not None and hasattr(phbands, "phfreqs") phbands = ddb.anaget_phmodes_at_qpoint(qpoint=ddb.qpoints[0], lo_to_splitting=False, verbose=1) # Wrong qpoint with self.assertRaises(ValueError): ddb.anaget_phmodes_at_qpoint(qpoint=(0, 0, 0), verbose=1) with self.assertRaises(ValueError): ddb.anaget_phmodes_at_qpoints(qpoints=[[0.1, 0.2, 0.3]], ifcflag=0) # Wrong ngqpt with self.assertRaises(ddb.AnaddbError): try: ddb.anaget_phbst_and_phdos_files(ngqpt=(4, 4, 4), verbose=1) except Exception as exc: # This to test AnaddbError.__str__ str(exc) raise # Cannot compute DOS since we need a mesh. with self.assertRaises(ddb.AnaddbError): ddb.anaget_phbst_and_phdos_files(verbose=1) # Test notebook if self.has_nbformat(): assert ddb.write_notebook(nbpath=self.get_tmpname(text=True)) # Test block parsing. blocks = ddb._read_blocks() assert len(blocks) == 1 assert blocks[0]["qpt"] == [0.25, 0, 0] assert blocks[0]["dord"] == 2 assert blocks[0]["qpt3"] == None lines = blocks[0]["data"] assert lines[0].rstrip( ) == " 2nd derivatives (non-stat.) - # elements : 36" assert lines[2].rstrip( ) == " 1 1 1 1 0.80977066582497D+01 -0.46347282336361D-16" assert lines[-1].rstrip( ) == " 3 2 3 2 0.49482344898401D+01 -0.44885664256253D-17" for qpt in ddb.qpoints: assert ddb.get_block_for_qpoint(qpt) assert ddb.get_block_for_qpoint(qpt.frac_coords) assert ddb.replace_block_for_qpoint(ddb.qpoints[0], blocks[0]["data"]) d_2ord = ddb.get_2nd_ord_dict() assert ddb.qpoints[0] in d_2ord new_qpt = [0.11, 0.22, 3.4] new_block = { "data": [ ' 2nd derivatives (non-stat.) - # elements : 1', ' qpt 1.10000000E-01 2.20000000E-01 3.40000000E+00 1.0', ' 1 1 1 1 0.38964081001769D+01 0.51387831420710D-24' ], "dord": 2, "qpt": new_qpt, "qpt3": None } assert ddb.insert_block(new_block) assert ddb.insert_block(new_block, replace=True) assert not ddb.insert_block(new_block, replace=False) # Write new DDB file. tmp_file = self.get_tmpname(text=True) ddb.write(tmp_file) with DdbFile(tmp_file) as new_ddb: # check that the new qpoint has been written to the file assert new_qpt in new_ddb.qpoints # remove the added block and write again to check that it is equivalent to the original assert ddb.remove_block(dord=2, qpt=new_qpt) ddb.write(tmp_file) with DdbFile(tmp_file) as new_ddb: assert ddb.qpoints == new_ddb.qpoints assert DdbFile.as_ddb(new_ddb) is new_ddb # Call anaddb to check if we can read new DDB phbands = new_ddb.anaget_phmodes_at_qpoint( qpoint=new_ddb.qpoints[0], verbose=1) assert phbands is not None and hasattr(phbands, "phfreqs")
def analyze_all_modes(self): self.results = OrderedDict() self.results[ 'lattice_parameter'] = self.atoms.get_cell_lengths_and_angles() # emacro & BEC myDDB = DdbFile(filepath='%s/abinit_mrgddb.out' % (self.dirname), read_blocks=True) emacro, becs = myDDB.anaget_emacro_and_becs() self.results['dielectric_tensor'] = emacro[0].reduced_tensor self.results['Born_effective_charges'] = becs self.results['number_of_qpoints'] = myDDB._guess_ngqpt() self.results['ecut'] = myDDB.params[u'ecut'] self.results['tsmear'] = myDDB.params[u'tsmear'] self.results['nsppol'] = myDDB.params[u'nsppol'] self.results['nkpt'] = myDDB.params[u'nkpt'] filefname = os.path.join(self.dirname, 'abinit.files') with open(filefname) as myfile: self.results['pseudopotentials'] = [ os.path.split(x)[-1].strip() for x in myfile.readlines()[5:] ] # Phonon self.results['phonon'] = OrderedDict() qpoints = OrderedDict([('Gamma', (0, 0, 0)), ('X', (0.5, 0, 0)), ('M', (0.5, 0.5, 0)), ('R', (0.5, 0.5, 0.5))]) # Phonon: Gamma_reduced qname = 'Gamma_reduced' self.results['phonon'][qname] = OrderedDict() hamk, freqs, evals, evecs, edisps, dc, ds = self.analyze_gamma( ibands=None, label='DYM_Gamma_reduced', is_asr=False) self.results['phonon'][qname]['dynamic_matrix'] = hamk self.results['phonon'][qname]['eigenvalues'] = evals self.results['phonon'][qname]['frequencies'] = freqs self.results['phonon'][qname]['eigenvectors'] = evecs self.results['phonon'][qname]['eigen_displacements'] = edisps self.results['phonon'][qname]['dynamic_matrix_contributions'] = dc self.results['phonon'][qname]['dynamic_matrix_sensitivities'] = ds # Phonon: Other Qpoints for qname in qpoints: qpoint = qpoints[qname] self.results['phonon'][qname] = OrderedDict() self.results['phonon'][qname]['qpoint'] = qpoint hamk, freqs, evals, evecs, edisps, dc, ds = self.analyze_qpoint( qpoint=qpoint, qpt_name=qname, ibands=None) self.results['phonon'][qname]['dynamic_matrix'] = hamk self.results['phonon'][qname]['eigenvalues'] = evals self.results['phonon'][qname]['frequencies'] = freqs self.results['phonon'][qname]['eigenvectors'] = evecs self.results['phonon'][qname]['eigen_displacements'] = edisps self.results['phonon'][qname]['dynamic_matrix_contributions'] = dc self.results['phonon'][qname]['dynamic_matrix_sensitivities'] = ds #with open('data/%s.json' % (self.dirname), 'w') as myfile: # json.dump(self.results, myfile) with open('data/%s.pickle' % (self.dirname), 'wb') as myfile: cPickle.dump(self.results, myfile) datadir = 'data/%s' % self.dirname if not os.path.exists(datadir): os.makedirs(datadir) os.system('cp %s/*.in %s' % (self.dirname, datadir)) os.system('cp %s/*.nc %s' % (self.dirname, datadir)) os.system('cp %s/*DDB %s' % (self.dirname, datadir)) os.system('cp %s/*.files %s' % (self.dirname, datadir)) os.system('cp %s/CONTCAR %s' % (self.dirname, datadir)) os.system('cp %s/*.txt %s' % (self.dirname, datadir)) os.system('cp %s/*.out %s' % (self.dirname, datadir)) os.system('tar -zcvf data/%s.tar.gz %s' % (self.dirname, datadir))
def test_alas_ddb_444_nobecs(self): """Testing DDB for AlAs on a 4x4x4x q-mesh without Born effective charges.""" ddb = DdbFile(os.path.join(test_dir, "AlAs_444_nobecs_DDB")) repr(ddb); str(ddb) assert str(ddb.header) assert ddb.to_string(verbose=2) assert ddb.header["nkpt"] == 256 assert ddb.header.nsym == 24 and ddb.header.ntypat == 2 self.assert_equal(ddb.header.znucl, [13, 33]) self.assert_equal(ddb.header.acell, [1, 1, 1]) self.assert_equal(ddb.header.ngfft, [10, 10, 10]) self.assert_equal(ddb.header.spinat, 0.0) #assert ddb.header.occ.shape = (ddb.header.nsppol, ddb.header.nkpt, ddb.header.nsppol) assert not ddb.has_qpoint([0.345, 0.456, 0.567]) assert ddb.has_qpoint([0, 0, 0]) for qpoint in ddb.qpoints: assert ddb.has_qpoint(qpoint) assert ddb.has_qpoint(qpoint.frac_coords) assert qpoint in ddb.computed_dynmat assert len(ddb.computed_dynmat[qpoint].index[0]) == 4 assert ddb.has_bec_terms(select="at_least_one") assert not ddb.has_bec_terms(select="all") assert not ddb.has_epsinf_terms() assert not ddb.has_lo_to_data() assert not ddb.has_internalstrain_terms() assert not ddb.has_piezoelectric_terms() assert not ddb.has_strain_terms() assert ddb.has_at_least_one_atomic_perturbation() ref_qpoints = np.reshape([ 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 2.50000000E-01, 0.00000000E+00, 0.00000000E+00, 5.00000000E-01, 0.00000000E+00, 0.00000000E+00, 2.50000000E-01, 2.50000000E-01, 0.00000000E+00, 5.00000000E-01, 2.50000000E-01, 0.00000000E+00, -2.50000000E-01, 2.50000000E-01, 0.00000000E+00, 5.00000000E-01, 5.00000000E-01, 0.00000000E+00, -2.50000000E-01, 5.00000000E-01, 2.50000000E-01, ], (-1, 3)) assert len(ddb.qpoints) == 8 for qpt, ref_qpt in zip(ddb.qpoints, ref_qpoints): assert qpt == ref_qpt for qpoint in ddb.qpoints: phbands = ddb.anaget_phmodes_at_qpoint(qpoint=qpoint, verbose=1) assert phbands is not None and hasattr(phbands, "phfreqs") assert np.all(ddb.guessed_ngqpt == [4, 4, 4]) # Get bands and Dos phbands_file, phdos_file = ddb.anaget_phbst_and_phdos_files(verbose=1) phbands, phdos = phbands_file.phbands, phdos_file.phdos assert ddb.view_phononwebsite(verbose=1, dryrun=True) == 0 if self.has_matplotlib(): assert phbands.plot_with_phdos(phdos, show=False, title="Phonon bands and DOS of %s" % phbands.structure.formula) assert phbands_file.plot_phbands(show=False) # Get emacro and becs emacro, becs = ddb.anaget_emacro_and_becs(chneut=1, verbose=1) assert np.all(becs.values == 0) #assert np.all(emacro.values == 0) repr(becs); str(becs) assert becs.to_string(verbose=2) self.assert_almost_equal(phdos.idos.values[-1], 3 * len(ddb.structure), decimal=1) phbands_file.close() phdos_file.close() # Test DOS computation via anaddb. c = ddb.anacompare_phdos(nqsmalls=[2, 3, 4], dipdip=0, num_cpus=1, verbose=2) assert c.phdoses and c.plotter is not None if self.has_matplotlib(): assert c.plotter.combiplot(show=False) # Use threads and gaussian DOS. c = ddb.anacompare_phdos(nqsmalls=[2, 3, 4], dos_method="gaussian", dipdip=0, asr=0, num_cpus=2, verbose=2) assert c.phdoses and c.plotter is not None # Execute anaddb to compute the interatomic forces. ifc = ddb.anaget_ifc() str(ifc); repr(ifc) #assert ifc.to_string(verbose=2) assert ifc.structure == ddb.structure assert ifc.number_of_atoms == len(ddb.structure) if self.has_matplotlib(): assert ifc.plot_longitudinal_ifc(show=False) assert ifc.plot_longitudinal_ifc_short_range(show=False) assert ifc.plot_longitudinal_ifc_ewald(show=False) ddb.close()
def setUpClass(cls): cls.ddb = DdbFile(os.path.join(test_dir, "AlAs_444_nobecs_DDB")) cls.ifc = cls.ddb.anaget_ifc(ifcout=40, ngqpt=[4, 4, 4], verbose=1)
def test_zno_gamma_ddb_with_becs(self): """Testing DDB for ZnO: Gamma only, with Born effective charges and E_macro.""" with DdbFile(os.path.join(test_dir, "ZnO_gamma_becs_DDB")) as ddb: repr(ddb) str(ddb) assert str(ddb.header) assert ddb.to_string(verbose=2) assert ddb.header["nkpt"] == 486 assert ddb.header.nband == 22 and ddb.header.occopt == 1 self.assert_equal(ddb.header.typat, [1, 1, 2, 2]) assert len(ddb.header.wtk) == ddb.header.nkpt #assert ddb.header.occ.shape = (ddb.header.nsppol, ddb.header.nkpt, ddb.header.nsppol) assert not ddb.has_qpoint([0.345, 0.456, 0.567]) assert ddb.has_qpoint([0, 0, 0]) assert len(ddb.qpoints) == 1 for qpoint in ddb.qpoints: assert ddb.has_qpoint(qpoint) assert ddb.has_qpoint(qpoint.frac_coords) assert qpoint in ddb.computed_dynmat assert len(ddb.computed_dynmat[qpoint].index[0]) == 4 # Test Lru_cache as well assert ddb.has_bec_terms(select="at_least_one") assert ddb.has_bec_terms(select="at_least_one") assert ddb.has_bec_terms(select="all") assert ddb.has_bec_terms(select="all") assert ddb.has_epsinf_terms() assert ddb.has_lo_to_data() # Get epsinf and becs epsinf, becs = ddb.anaget_epsinf_and_becs(chneut=1, verbose=1) ref_becs_values = [ [[2.15646571e+00, 0.00000000e+00, 3.26402110e-25], [0.00000000e+00, 2.15646571e+00, -5.46500204e-24], [-5.66391495e-25, -6.54012564e-25, 2.19362823e+00]], [[2.15646571e+00, 0.00000000e+00, 1.19680774e-24], [0.00000000e+00, 2.15646571e+00, 8.10327888e-24], [-1.69917448e-24, -1.30802513e-24, 2.19362823e+00]], [[-2.15646571e+00, 6.66133815e-16, -1.84961196e-24], [8.88178420e-16, -2.15646571e+00, 2.82672519e-24], [-3.39834897e-24, -3.27006282e-25, -2.19362823e+00]], [[-2.15646571e+00, -6.66133815e-16, 3.26402110e-25], [-8.88178420e-16, -2.15646571e+00, -5.46500204e-24], [5.66391495e-24, 2.28904397e-24, -2.19362823e+00]] ] ref_epsinf = [[5.42055574e+00, 8.88178420e-16, -1.30717901e-25], [-8.88178420e-16, 5.42055574e+00, -2.26410045e-25], [-1.30717901e-25, 2.26410045e-25, 4.98835236e+00]] self.assert_almost_equal(becs.values, ref_becs_values) self.assert_almost_equal(np.array(epsinf), ref_epsinf) repr(becs) str(becs) assert becs.to_string(verbose=2) for arr, z in zip(becs.values, becs.zstars): self.assert_equal(arr, z) df = becs.get_voigt_dataframe(view="all", select_symbols="O", verbose=1) assert len(df) == 2 # Equivalent atoms should have same determinant. self.assert_almost_equal(df["determinant"].values, df["determinant"].values[0]) # get the dielectric tensor generator from anaddb dtg = ddb.anaget_dielectric_tensor_generator(verbose=2) assert dtg is not None and hasattr(dtg, "phfreqs") assert dtg.to_string(verbose=2)
def test_alas_ddb_444_nobecs(self): """Testing DDB for AlAs on a 4x4x4x q-mesh without Born effective charges.""" ddb = DdbFile(os.path.join(test_dir, "AlAs_444_nobecs_DDB")) repr(ddb) str(ddb) assert str(ddb.header) assert ddb.to_string(verbose=2) assert ddb.header["nkpt"] == 256 assert ddb.header.nsym == 24 and ddb.header.ntypat == 2 self.assert_equal(ddb.header.znucl, [13, 33]) self.assert_equal(ddb.header.acell, [1, 1, 1]) self.assert_equal(ddb.header.ngfft, [10, 10, 10]) self.assert_equal(ddb.header.spinat, 0.0) #assert ddb.header.occ.shape = (ddb.header.nsppol, ddb.header.nkpt, ddb.header.nsppol) assert not ddb.has_qpoint([0.345, 0.456, 0.567]) assert ddb.has_qpoint([0, 0, 0]) for qpoint in ddb.qpoints: assert ddb.has_qpoint(qpoint) assert ddb.has_qpoint(qpoint.frac_coords) assert qpoint in ddb.computed_dynmat assert len(ddb.computed_dynmat[qpoint].index[0]) == 4 assert ddb.has_bec_terms(select="at_least_one") assert not ddb.has_bec_terms(select="all") assert not ddb.has_epsinf_terms() assert not ddb.has_lo_to_data() assert not ddb.has_internalstrain_terms() assert not ddb.has_piezoelectric_terms() assert not ddb.has_strain_terms() assert ddb.has_at_least_one_atomic_perturbation() ref_qpoints = np.reshape([ 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 2.50000000E-01, 0.00000000E+00, 0.00000000E+00, 5.00000000E-01, 0.00000000E+00, 0.00000000E+00, 2.50000000E-01, 2.50000000E-01, 0.00000000E+00, 5.00000000E-01, 2.50000000E-01, 0.00000000E+00, -2.50000000E-01, 2.50000000E-01, 0.00000000E+00, 5.00000000E-01, 5.00000000E-01, 0.00000000E+00, -2.50000000E-01, 5.00000000E-01, 2.50000000E-01, ], (-1, 3)) assert len(ddb.qpoints) == 8 for qpt, ref_qpt in zip(ddb.qpoints, ref_qpoints): assert qpt == ref_qpt for qpoint in ddb.qpoints: phbands = ddb.anaget_phmodes_at_qpoint(qpoint=qpoint, verbose=1) assert phbands is not None and hasattr(phbands, "phfreqs") assert np.all(ddb.guessed_ngqpt == [4, 4, 4]) # Get bands and Dos phbands_file, phdos_file = ddb.anaget_phbst_and_phdos_files(verbose=1) phbands, phdos = phbands_file.phbands, phdos_file.phdos assert ddb.view_phononwebsite(verbose=1, dryrun=True) == 0 if self.has_matplotlib(): assert phbands.plot_with_phdos(phdos, show=False, title="Phonon bands and DOS of %s" % phbands.structure.formula) assert phbands_file.plot_phbands(show=False) # Get epsinf and becs r = ddb.anaget_epsinf_and_becs(chneut=1, verbose=1) epsinf, becs = r.epsinf, r.becs assert np.all(becs.values == 0) repr(becs) str(becs) assert becs.to_string(verbose=2) self.assert_almost_equal(phdos.idos.values[-1], 3 * len(ddb.structure), decimal=1) phbands_file.close() phdos_file.close() # Test DOS computation via anaddb. c = ddb.anacompare_phdos(nqsmalls=[2, 3, 4], dipdip=0, num_cpus=1, verbose=2) assert c.phdoses and c.plotter is not None if self.has_matplotlib(): assert c.plotter.combiplot(show=False) # Use threads and gaussian DOS. c = ddb.anacompare_phdos(nqsmalls=[2, 3, 4], dos_method="gaussian", dipdip=0, asr=0, num_cpus=2, verbose=2) assert c.phdoses and c.plotter is not None # Execute anaddb to compute the interatomic force constants. ifc = ddb.anaget_ifc() str(ifc) repr(ifc) assert ifc.to_string(verbose=2) assert ifc.structure == ddb.structure assert ifc.number_of_atoms == len(ddb.structure) if self.has_matplotlib(): assert ifc.plot_longitudinal_ifc(show=False) assert ifc.plot_longitudinal_ifc_short_range(show=False) assert ifc.plot_longitudinal_ifc_ewald(show=False) # Test get_coarse. coarse_ddb = ddb.get_coarse([2, 2, 2]) # Check whether anaddb can read the coarse DDB. coarse_phbands_file, coarse_phdos_file = coarse_ddb.anaget_phbst_and_phdos_files( nqsmall=4, ndivsm=1, verbose=1) coarse_phbands_file.close() coarse_phdos_file.close() coarse_ddb.close() ddb.close()
def test_alas_ddb_444_nobecs(self): """Testing DDB for AlAs on a 4x4x4x q-mesh without Born effective charges.""" ddb = DdbFile(os.path.join(test_dir, "AlAs_444_nobecs_DDB")) print(ddb) print(ddb.header) ref_qpoints = np.reshape([ 0.00000000E+00, 0.00000000E+00, 0.00000000E+00, 2.50000000E-01, 0.00000000E+00, 0.00000000E+00, 5.00000000E-01, 0.00000000E+00, 0.00000000E+00, 2.50000000E-01, 2.50000000E-01, 0.00000000E+00, 5.00000000E-01, 2.50000000E-01, 0.00000000E+00, -2.50000000E-01, 2.50000000E-01, 0.00000000E+00, 5.00000000E-01, 5.00000000E-01, 0.00000000E+00, -2.50000000E-01, 5.00000000E-01, 2.50000000E-01, ], (-1, 3)) assert len(ddb.qpoints) == 8 for qpt, ref_qpt in zip(ddb.qpoints, ref_qpoints): assert qpt == ref_qpt for qpoint in ddb.qpoints: phbands = ddb.anaget_phmodes_at_qpoint(qpoint=qpoint, verbose=1) assert phbands is not None and hasattr(phbands, "phfreqs") assert np.all(ddb.guessed_ngqpt == [4, 4, 4]) # Get bands and Dos phbands_file, phdos_file = ddb.anaget_phbst_and_phdos_files(verbose=1) phbands, phdos = phbands_file.phbands, phdos_file.phdos if self.has_matplotlib(): phbands.plot_with_phdos(phdos, title="Phonon bands and DOS of %s" % phbands.structure.formula, show=False) # Get emacro and becs emacro, becs = ddb.anaget_emacro_and_becs(chneut=1, verbose=1) assert np.all(becs.values == 0) assert np.all(becs.becs == 0) print(becs) self.assert_almost_equal(phdos.idos.values[-1], 3 * len(ddb.structure), decimal=1) phbands_file.close() phdos_file.close() # Test DOS computation via anaddb. c = ddb.anacompare_phdos(nqsmalls=[2, 4, 6], num_cpus=None) if self.has_matplotlib(): c.plotter.plot(show=False) # Execute anaddb to compute the interatomic forces. ifc = ddb.anaget_ifc() assert ifc.structure == ddb.structure assert ifc.number_of_atoms == len(ddb.structure) if self.has_matplotlib(): ifc.plot_longitudinal_ifc(show=False) ifc.plot_longitudinal_ifc_short_range(show=False) ifc.plot_longitudinal_ifc_ewald(show=False) ddb.close()
def test_alas_ddb_1qpt_phonons(self): """Testing DDB with one q-point""" with DdbFile(os.path.join(test_dir, "AlAs_1qpt_DDB")) as ddb: repr(ddb) print(ddb) # Test qpoints. assert len(ddb.qpoints) == 1 assert np.all(ddb.qpoints[0] == [0.25, 0, 0]) assert ddb.natom == len(ddb.structure) # Test header h = ddb.header assert h.version == 100401 and h.ecut == 3 assert "ecut" in h and h["ecut"] == h.ecut assert "ixc" in ddb.params assert ddb.params["ixc"] == 7 assert h.occ == 4 * [2] assert h.xred.shape == (h.natom, 3) and h.kpt.shape == (h.nkpt, 3) self.assert_equal(h.znucl, [13, 33]) assert ddb.version == 100401 assert ddb.total_energy is None assert ddb.cart_forces is None assert ddb.cart_stress_tensor is None assert np.all( h.symrel[1].T.ravel() == [0, -1, 1, 0, -1, 0, 1, -1, 0]) assert np.all( h.symrel[2].T.ravel() == [-1, 0, 0, -1, 0, 1, -1, 1, 0]) # Test structure struct = ddb.structure assert struct.formula == "Al1 As1" # Test interface with Anaddb. print(ddb.qpoints[0]) assert ddb.qindex(ddb.qpoints[0]) == 0 phbands = ddb.anaget_phmodes_at_qpoint(qpoint=ddb.qpoints[0], verbose=1) assert phbands is not None and hasattr(phbands, "phfreqs") phbands = ddb.anaget_phmodes_at_qpoint(qpoint=ddb.qpoints[0], lo_to_splitting=False, verbose=1) # Wrong qpoint with self.assertRaises(ValueError): ddb.anaget_phmodes_at_qpoint(qpoint=(0, 0, 0), verbose=1) # Wrong ngqpt with self.assertRaises(ddb.AnaddbError): try: ddb.anaget_phbst_and_phdos_files(ngqpt=(4, 4, 4), verbose=1) except Exception as exc: # This to test AnaddbError.__str__ print(exc) raise # Cannot compute DOS since we need a mesh. with self.assertRaises(ddb.AnaddbError): ddb.anaget_phbst_and_phdos_files(verbose=1) # Test notebook if self.has_nbformat(): assert ddb.write_notebook(nbpath=self.get_tmpname(text=True)) # Test block parsing. blocks = ddb._read_blocks() assert len(blocks) == 1 assert blocks[0]["qpt"] == [0.25, 0, 0] assert blocks[0]["dord"] == 2 lines = blocks[0]["data"] assert lines[0].rstrip( ) == " 2nd derivatives (non-stat.) - # elements : 36" assert lines[2].rstrip( ) == " 1 1 1 1 0.80977066582497D+01 -0.46347282336361D-16" assert lines[-1].rstrip( ) == " 3 2 3 2 0.49482344898401D+01 -0.44885664256253D-17" for qpt in ddb.qpoints: assert ddb.get_block_for_qpoint(qpt) assert ddb.get_block_for_qpoint(qpt.frac_coords) assert ddb.replace_block_for_qpoint(ddb.qpoints[0], blocks[0]["data"]) # Write new DDB file. tmp_file = self.get_tmpname(text=True) ddb.write(tmp_file) with DdbFile(tmp_file) as new_ddb: assert ddb.qpoints == new_ddb.qpoints assert DdbFile.as_ddb(new_ddb) is new_ddb # Call anaddb to check if we can read new DDB phbands = new_ddb.anaget_phmodes_at_qpoint( qpoint=new_ddb.qpoints[0], verbose=1) assert phbands is not None and hasattr(phbands, "phfreqs")
def phonopy_to_abinit(unit_cell, supercell_matrix, out_ddb_path, ngqpt=None, qpt_list=None, force_constants=None, force_sets=None, born=None, primitive_matrix="auto", symprec=1e-5, tolsym=None, supercell=None, calculator=None, manager=None, workdir=None, pseudos=None, verbose=False): """ Converts the data from phonopy to an abinit DDB file. The data can be provided in form of arrays or paths to the phonopy files that should be parsed. The minimal input should contains the FORCE_CONSTANTS or FORCE_SETS. If BORN is present the Born effective charges (BEC) and dielectric tensor will also be added to the DDB. The best agreement is obtained with supercell_matrix and ngqpt being equivalent (i.e. supercell_matrix a diagonal matrix with ngqpt as diagonal elements). Non diagonal supercell_matrix are allowed as well, but the information encoded in the DDB will be the result of an interpolation done through phonopy. Phonopy is used to convert the IFC to the dynamical matrix. However, in order to determine the list of q-points in the irreducible Brillouin zone and to prepare the base for the final DDB file, abinit will be called for a very short and inexpensive run. Performs a check to verify if the two codes identify the same symmetries and it gives a warning in case of failure. Mismatching symmetries may lead to incorrect conversions. Args: unit_cell: a |Structure| object that identifies the unit cell used for the phonopy calculation. supercell_matrix: a 3x3 array representing the supercell matrix used to generated the forces with phonopy. out_ddb_path: a full path to the file where the new DDB will be written ngqpt: a list of 3 elements indicating the grid of q points that will be used in the DDB. qpt_list: alternatively to ngqpt an explicit list of q-points can be provided here. At least one among ngqpt and qpt_list should be defined. force_constants: an array with shape (num atoms unit cell, num atoms supercell, 3, 3) containing the force constants. Alternatively a string with the path to the FORCE_CONSTANTS file. This or force_set should be defined. If both given this has precedence. force_sets: a dictionary obtained from the force sets generated with phonopy. Alternatively a string with the path to the FORCE_SETS file. This or force_constants should be defined. born: a dictionary with "dielectric" and "born" keywords as obtained from the nac_params in phonopy. Alternatively a string with the path to the BORN file. Notice that the "factor" attribute is not taken into account, so the values should be in default phonopy units. primitive_matrix: a 3x3 array with the primitive matrix passed to Phonopy. "auto" will use spglib to try to determine it automatically. If the DDB file should contain the actual unit cell this should be the identity matrix. symprec: distance tolerance in Cartesian coordinates to find crystal symmetry in phonopy. It might be that the value should be tuned so that it leads to the the same symmetries as in the abinit calculation. tolsym: Gives the tolerance to identify symmetries in abinit. See abinit documentation for more details. supercell: if given it should represent the supercell used to get the force constants, without any perturbation. It will be used to match it to the phonopy supercell and sort the IFC in the correct order. calculator: a string with the name of the calculator. Will be used to set the conversion factor for the force constants coming from phonopy. manager: |TaskManager| object. If None, the object is initialized from the configuration file pseudos: List of filenames or list of |Pseudo| objects or |PseudoTable| object. It will be used by abinit to generate the base DDB file. If None the abipy.data.hgh_pseudos.HGH_TABLE table will be used. verbose: verbosity level. Set it to a value > 0 to get more information workdir: path to the directory where the abinit calculation will be executed. Returns: a DdbFile instance of the file written in out_ddb_path. """ if ngqpt is None and qpt_list is None: raise ValueError( "at least one among nqgpt and qpt_list should be defined") if force_sets is None and force_constants is None: raise ValueError( "at least one of force_sets and force_constants should be provided" ) phon_at = get_phonopy_structure(unit_cell) if isinstance(force_constants, str): force_constants = parse_FORCE_CONSTANTS(filename=force_constants) elif force_constants is not None: force_constants = np.array(force_constants) force_sets = None if isinstance(force_sets, str): force_sets = parse_FORCE_SETS(filename=force_sets) # no nac_params here, otherwise they will be used for the interpolation phonon = Phonopy(phon_at, supercell_matrix, primitive_matrix=primitive_matrix, nac_params=None, symprec=symprec, calculator=calculator) primitive = get_pmg_structure(phonon.primitive) if isinstance(born, str): born = parse_BORN(phonon.primitive, filename=born) if supercell is not None: ph_supercell = get_pmg_structure(phonon.supercell) if not np.allclose(supercell.lattice.matrix, ph_supercell.lattice.matrix): raise RuntimeError("The lattice of the supercells do not match") sc_mapping = [] for i, site_orig in enumerate(supercell): for j, site_ph in enumerate(ph_supercell): d = supercell.lattice.get_distance_and_image( site_orig.frac_coords, site_ph.frac_coords)[0] if d < 1e-5: sc_mapping.append(j) break else: raise RuntimeError( f"Could not find a match for site {i} with coords " f"{site_orig.cart_coords} in the supercell.") # cross check that the same atom was not matched twice n_matches = len(set(sc_mapping)) if n_matches < len(supercell): raise RuntimeError( f"Found matches for {n_matches} different atoms in the supercell: {sc_mapping}" ) force_constants = force_constants[:, sc_mapping] if force_constants is not None: phonon.set_force_constants(force_constants) else: phonon.dataset = force_sets phonon.produce_force_constants() if calculator: units = get_default_physical_units(calculator) fc_factor = get_force_constant_conversion_factor( units["force_constants_unit"], None) phonon.set_force_constants(phonon.force_constants * fc_factor) if pseudos is None: from abipy.data.hgh_pseudos import HGH_TABLE pseudos = HGH_TABLE inp = minimal_scf_input(primitive, pseudos) # get the qpoints list if not defined if qpt_list is None: inp["ngkpt"] = ngqpt qpt_list = inp.abiget_ibz(verbose=verbose)[0] dm_list = get_dm(phonon, qpt_list, primitive) if born is not None: # for the conversion of the BEC the zion (i.e. the ionic charge of the pseudo) # it is an additive factor and should be the same that goes in the header of the DDB, # so take it from the pseudos used to generate it. zion = inp.valence_electrons_per_atom born_data = generate_born_deriv(born, zion, primitive) else: born_data = None inp = minimal_scf_input(primitive, pseudos) if tolsym is not None: inp["tolsym"] = tolsym task = inp.run_in_shell(workdir=workdir, manager=manager, verbose=verbose) # use the output of abinit to check that the spacegroup identified by # phonopy and abinit are the same. with GsrFile(task.opath_from_ext("GSR.nc")) as gsr: abi_spg = gsr.structure.abi_spacegroup.spgid spglib_spg = phonon.symmetry.dataset["number"] if abi_spg != spglib_spg: warnings.warn( "The space group number obtained based on the DDB symmetries differs " f"from the one calculated with spglib: {abi_spg} versus " f"{spglib_spg}. The convertion may be incorrect. Try changing symprec or tolsym." ) tmp_ddb_path = task.opath_from_ext("DDB") ddb = DdbFile(tmp_ddb_path) # remove the blocks generated by the calculation and that are meaningless ddb.remove_block(dord=0) ddb.remove_block(dord=1) add_data_ddb(ddb, dm_list, qpt_list, born_data) ddb.write(out_ddb_path) new_ddb = DdbFile(out_ddb_path) return new_ddb
def from_ddb_list(cls, ddb_list, nqsmall=10, qppa=None, ndivsm=20, line_density=None, asr=2, chneut=1, dipdip=1, dos_method="tetra", lo_to_splitting="automatic", ngqpt=None, qptbounds=None, anaddb_kwargs=None, verbose=0, mpi_procs=1, workdir=None, manager=None): """ Execute anaddb to compute generate the object from a list of ddbs. Args: ddb_list: A list with the paths to the ddb_files at different volumes. There should be an odd number of DDB files and the volume increment must be constant. The DDB files will be ordered according to the volume of the unit cell and the middle one will be considered as the DDB at the relaxed volume. nqsmall: Defines the homogeneous q-mesh used for the DOS. Gives the number of divisions used to sample the smallest lattice vector. If 0, DOS is not computed and (phbst, None) is returned. qppa: Defines the homogeneous q-mesh used for the DOS in units of q-points per reciprocal atom. Overrides nqsmall. ndivsm: Number of division used for the smallest segment of the q-path. line_density: Defines the a density of k-points per reciprocal atom to plot the phonon dispersion. Overrides ndivsm. asr, chneut, dipdip: Anaddb input variable. See official documentation. dos_method: Technique for DOS computation in Possible choices: "tetra", "gaussian" or "gaussian:0.001 eV". In the later case, the value 0.001 eV is used as gaussian broadening. lo_to_splitting: Allowed values are [True, False, "automatic"]. Defaults to "automatic" If True the LO-TO splitting will be calculated and the non_anal_directions and the non_anal_phfreqs attributes will be addeded to the phonon band structure. "automatic" activates LO-TO if the DDB file contains the dielectric tensor and Born effective charges. ngqpt: Number of divisions for the q-mesh in the DDB file. Auto-detected if None (default). qptbounds: Boundaries of the path. If None, the path is generated from an internal database depending on the input structure. anaddb_kwargs: additional kwargs for anaddb. verbose: verbosity level. Set it to a value > 0 to get more information. mpi_procs: Number of MPI processes to use. workdir: Working directory. If None, a temporary directory is created. manager: |TaskManager| object. If None, the object is initialized from the configuration file. Returns: A GrunsNcFile object. """ if len(ddb_list) % 2 != 1: raise ValueError("An odd number of ddb file paths should be provided") ddbs = [DdbFile(d) for d in ddb_list] ddbs = sorted(ddbs, key=lambda d: d.structure.volume) iv0 = int((len(ddbs) - 1) / 2) ddb0 = ddbs[iv0] # update list of paths with absolute paths in the correct order ddb_list = [d.filepath for d in ddbs] if ngqpt is None: ngqpt = ddb0.guessed_ngqpt if lo_to_splitting == "automatic": lo_to_splitting = ddb0.has_lo_to_data() and dipdip != 0 if lo_to_splitting and not ddb0.has_lo_to_data(): cprint("lo_to_splitting is True but Emacro and Becs are not available in DDB: %s" % ddb0.filepath, "yellow") inp = AnaddbInput.phbands_and_dos( ddb0.structure, ngqpt=ngqpt, ndivsm=ndivsm, nqsmall=nqsmall, qppa=qppa, line_density=line_density, q1shft=(0, 0, 0), qptbounds=qptbounds, asr=asr, chneut=chneut, dipdip=dipdip, dos_method=dos_method, lo_to_splitting=lo_to_splitting, anaddb_kwargs=anaddb_kwargs) inp["gruns_ddbs"] = ['"'+p+'"\n' for p in ddb_list] inp["gruns_nddbs"] = len(ddb_list) task = AnaddbTask.temp_shell_task(inp, ddb_node=ddb0.filepath, workdir=workdir, manager=manager, mpi_procs=mpi_procs) if verbose: print("ANADDB INPUT:\n", inp) print("workdir:", task.workdir) # Run the task here. task.start_and_wait(autoparal=False) report = task.get_event_report() if not report.run_completed: raise ddb0.AnaddbError(task=task, report=report) gruns = cls.from_file(os.path.join(task.workdir, "run.abo_GRUNS.nc")) return gruns
def from_ddb(cls, ddb_path, directions=None, labels=None, num_points=20, qpt_norm=0.1, ignore_neg_freqs=True, asr=2, chneut=1, dipdip=1, ngqpt=None, spell_check=True, anaddb_kwargs=None, verbose=0, mpi_procs=1, workdir=None, manager=None): """ Creates and instance of the object. Runs anaddb along the specified directions or the standard directions in the standard paths given in :cite:`Setyawan2010`. The values of the speed of sound will be calculated as the slope of the linear fits along each direction. Args: ddb_path (str): path to the ddb file. directions (list): list of qpoints identifying the directions for the calculation of the speed of sound. In fractional coordinates. labels (list): list of string with the name of the directions. num_points (int): number of points calculated along each direction and used to fit the speed of sound. qpt_norm (float): Norm of the largest point in fractional coordinates for each of the directions considered. ignore_neg_freqs (bool): if True points with negative frequencies will not be considered in the fit, in order to ignore inaccuracies in the long range behavior. asr, chneut, dipdip: Anaddb input variable. See official documentation. ngqpt: Number of divisions for the q-mesh in the DDB file. Auto-detected if None (default). anaddb_kwargs: additional kwargs for anaddb. verbose: verbosity level. Set it to a value > 0 to get more information. mpi_procs: Number of MPI processes to use. workdir: Working directory. If None, a temporary directory is created. manager: |TaskManager| object. If None, the object is initialized from the configuration file. long. Returns: an instance of SoundVelocity """ with DdbFile(ddb_path) as ddb: if ngqpt is None: ngqpt = ddb.guessed_ngqpt inp = AnaddbInput(ddb.structure, comment="ANADDB input for speed of sound", anaddb_kwargs=anaddb_kwargs, spell_check=spell_check) q1shft = [[0, 0, 0]] inp.set_vars( ifcflag=1, ngqpt=np.array(ngqpt), q1shft=q1shft, nqshft=len(q1shft), asr=asr, chneut=chneut, dipdip=dipdip, ) if not directions: hs = ddb.structure.hsym_kpath kpath = hs.kpath directions = [] labels = [] for chunk in kpath["path"]: for i, q in enumerate(chunk): if "Gamma" in q: if i > 0 and q not in labels: new_q = kpath["kpoints"][chunk[i - 1]] directions.append(new_q) labels.append(chunk[i - 1]) if i < len(chunk) - 1 and q not in labels: new_q = kpath["kpoints"][chunk[i + 1]] directions.append(new_q) labels.append(chunk[i + 1]) qpts = [] for q in directions: q = qpt_norm * q / np.linalg.norm(q) steps = q / num_points qpts.extend((steps[:, None] * np.arange(num_points)).T) n_qpoints = len(qpts) qph1l = np.zeros((n_qpoints, 4)) qph1l[:, :-1] = qpts qph1l[:, -1] = 1 inp['qph1l'] = qph1l.tolist() inp['nph1l'] = n_qpoints task = ddb._run_anaddb_task(inp, mpi_procs=mpi_procs, workdir=workdir, manager=manager, verbose=verbose) phbst_path = os.path.join(task.workdir, "run.abo_PHBST.nc") return cls.from_phbst(phbst_path, ignore_neg_freqs=ignore_neg_freqs, labels=labels)