def read_dynmat_ir_raman(filename='dynmat.out', natoms=None, cols={1: 'freqs', 3:'ir', 4: 'raman', 5: 'depol'}): """Read ``dynmat.x`` text output file and extract IR and Raman intensities. Parameters ---------- filename : str dynmat.x text output file (e.g. from ``dynmat.x < dynmat.in > dynmat.out``) natoms : int number of atoms in the cell cols : dict column numbers of the text block Returns ------- cols = None Return the parsed array as found in the file cols = dict Return dict with keys from `cols` and 1d arrays ``{'freqs': <array>, 'ir': <array>, 'raman': <array>, 'depol': <array>}``. If a column is not present, the array is None. Notes ----- The parsed textblock looks like this:: # mode [cm-1] [THz] IR Raman depol.fact 1 0.00 0.0000 0.0000 0.0005 0.7414 2 0.00 0.0000 0.0000 0.0005 0.7465 3 0.00 0.0000 0.0000 0.0018 0.2647 4 252.27 7.5627 0.0000 0.0073 0.7500 5 252.27 7.5627 0.0000 0.0073 0.7500 6 548.44 16.4419 0.0000 0.0000 0.7434 7 603.32 18.0872 35.9045 18.9075 0.7366 8 656.82 19.6910 0.0000 7.9317 0.7500 9 656.82 19.6910 0.0000 7.9317 0.7500 10 669.67 20.0762 31.5712 5.0265 0.7500 11 738.22 22.1311 0.0000 0.0000 0.7306 12 922.64 27.6600 31.5712 5.0265 0.7500 Some columns (e.g. IR, Raman) may be missing. """ assert natoms is not None, ("natoms is None") cmd = "grep -A{0} 'mode.*cm-1' {1} | grep -v mode".format(3*natoms, filename) arr = parse.arr2d_from_txt(common.backtick(cmd)) if cols is None: return arr else: dct = {} for ii,name in cols.items(): if arr.shape[1] >= (ii+1): dct[name] = arr[:,ii] else: dct[name] = None return dct
def read_dynmat_ir_raman(filename='dynmat.out', natoms=None, cols={1: 'freqs', 3:'ir', 4: 'raman', 5: 'depol'}): """Read ``dynmat.x`` text output file and extract IR and Raman intensities. Parameters ---------- filename : str dynmat.x text output file (e.g. from ``dynmat.x < dynmat.in > dynmat.out``) natoms : int number of atoms in the cell cols : dict column numbers of the text block Returns ------- cols = None Return the parsed array as found in the file cols = dict Return dict with keys from `cols` and 1d arrays ``{'freqs': <array>, 'ir': <array>, 'raman': <array>, 'depol': <array>}``. If a column is not present, the array is None. Notes ----- The parsed textblock looks like this:: # mode [cm-1] [THz] IR Raman depol.fact 1 0.00 0.0000 0.0000 0.0005 0.7414 2 0.00 0.0000 0.0000 0.0005 0.7465 3 0.00 0.0000 0.0000 0.0018 0.2647 4 252.27 7.5627 0.0000 0.0073 0.7500 5 252.27 7.5627 0.0000 0.0073 0.7500 6 548.44 16.4419 0.0000 0.0000 0.7434 7 603.32 18.0872 35.9045 18.9075 0.7366 8 656.82 19.6910 0.0000 7.9317 0.7500 9 656.82 19.6910 0.0000 7.9317 0.7500 10 669.67 20.0762 31.5712 5.0265 0.7500 11 738.22 22.1311 0.0000 0.0000 0.7306 12 922.64 27.6600 31.5712 5.0265 0.7500 Some columns (e.g. IR, Raman) may be missing. """ assert natoms is not None, ("natoms is None") cmd = "grep -A{0} 'mode.*cm-1' {1} | grep -v mode".format(3*natoms, filename) arr = parse.arr2d_from_txt(common.backtick(cmd)) if cols is None: return arr else: dct = {} for ii,name in cols.iteritems(): if arr.shape[1] >= (ii+1): dct[name] = arr[:,ii] else: dct[name] = None return dct
def test_pwscf_calculator(): if not have_ase(): skip("no ASE found, skipping test") elif not have_pwx(): skip("no pw.x found, skipping test") else: pseudo_dir = pj(testdir, prefix, 'pseudo') print(common.backtick("mkdir -pv {p}; cp files/qe_pseudos/*.gz {p}/; \ gunzip {p}/*".format(p=pseudo_dir))) at = get_atoms_with_calc_pwscf(pseudo_dir) print("scf") # trigger calculation here forces = at.get_forces() etot = at.get_potential_energy() stress = at.get_stress(voigt=False) # 3x3 st = io.read_pw_scf(at.calc.label + '.out') assert np.allclose(forces, st.forces) assert np.allclose(etot, st.etot) assert np.allclose(st.stress, -stress * constants.eV_by_Ang3_to_GPa) # files/ase/pw.scf.out.start is a norm-conserving LDA struct, # calculated with pz-vbc.UPF, so the PBE vc-relax will make the cell # a bit bigger print("vc-relax") from ase.optimize import BFGS from ase.constraints import UnitCellFilter opt = BFGS(UnitCellFilter(at)) cell = parse.arr2d_from_txt(""" -1.97281509 0. 1.97281509 0. 1.97281509 1.97281509 -1.97281509 1.97281509 0.""") assert np.allclose(cell, at.get_cell()) opt.run(fmax=0.05) # run only 2 steps cell = parse.arr2d_from_txt(""" -2.01837531 0. 2.01837531 0. 2.01837531 2.01837531 -2.01837531 2.01837531 0""") assert np.allclose(cell, at.get_cell()) # at least 1 backup files must exist: pw.*.0 is the SCF run, backed up # in the first iter of the vc-relax assert os.path.exists(at.calc.infile + '.0')
def test_pwscf_calculator(): if not have_ase(): skip("no ASE found, skipping test") elif not have_pwx(): skip("no pw.x found, skipping test") else: pseudo_dir = pj(testdir, prefix, 'pseudo') print common.backtick("mkdir -pv {p}; cp files/qe_pseudos/*.gz {p}/; \ gunzip {p}/*".format(p=pseudo_dir)) at = get_atoms_with_calc_pwscf(pseudo_dir) print "scf" # trigger calculation here forces = at.get_forces() etot = at.get_potential_energy() stress = at.get_stress(voigt=False) # 3x3 st = io.read_pw_scf(at.calc.label + '.out') assert np.allclose(forces, st.forces) assert np.allclose(etot, st.etot) assert np.allclose(st.stress, -stress * constants.eV_by_Ang3_to_GPa) # files/ase/pw.scf.out.start is a norm-conserving LDA struct, # calculated with pz-vbc.UPF, so the PBE vc-relax will make the cell # a bit bigger print "vc-relax" from ase.optimize import BFGS from ase.constraints import UnitCellFilter opt = BFGS(UnitCellFilter(at)) cell = parse.arr2d_from_txt(""" -1.97281509 0. 1.97281509 0. 1.97281509 1.97281509 -1.97281509 1.97281509 0.""") assert np.allclose(cell, at.get_cell()) opt.run(fmax=0.05) # run only 2 steps cell = parse.arr2d_from_txt(""" -2.01837531 0. 2.01837531 0. 2.01837531 2.01837531 -2.01837531 2.01837531 0""") assert np.allclose(cell, at.get_cell()) # at least 1 backup files must exist: pw.*.0 is the SCF run, backed up # in the first iter of the vc-relax assert os.path.exists(at.calc.infile + '.0')
def test_write_lammps(): st = crys.Structure(coords_frac=rand(20, 3), cell=rand(3, 3), symbols=['Al'] * 10 + ['N'] * 10) # align cell to lammps standard [[x,0,0],...] st.coords = None st.cell = None st.set_all() st_fn = common.pj(testdir, 'lmp.struct') io.write_lammps(st_fn, st) symbols = common.file_read(st_fn + '.symbols').split() assert st.symbols == symbols cmd = r"grep -A22 Atoms %s | grep '^[0-9]'" % st_fn arr = parse.arr2d_from_txt(common.backtick(cmd)) assert arr.shape == (20, 5) assert np.allclose(st.coords, arr[:, 2:])
def test_write_lammps(): st = crys.Structure(coords_frac=rand(20,3), cell=rand(3,3), symbols=['Al']*10+['N']*10) # align cell to lammps standard [[x,0,0],...] st.coords = None st.cell = None st.set_all() st_fn = common.pj(testdir, 'lmp.struct') io.write_lammps(st_fn, st) symbols = common.file_read(st_fn + '.symbols').split() assert st.symbols == symbols cmd = r"grep -A22 Atoms %s | grep '^[0-9]'" %st_fn arr = parse.arr2d_from_txt(common.backtick(cmd)) assert arr.shape == (20,5) assert np.allclose(st.coords, arr[:,2:])
def read_dyn(filename, natoms=None): """Read one dynamical matrix file (for 1 qpoint) produced by ``ph.x`` and extract the same as :func:`read_matdyn_modes` for this qpoint only. All arrays have one dim less compared to :func:`read_matdyn_modes`. Parameters ---------- filename : str Name of dyn file. Example: "ph.dyn3" for qpoint 3. natoms : int number of atoms in the cell (used for nmodes=3*natoms only) Returns ------- qpoints, freqs, vecs qpoints : 1d array (3,) The qpoint of the dyn file. freqs : 1d array, (nmodes,) where nmodes = 3*natoms 3*natoms phonon frequencies in [cm^-1] at the q-point. vecs : 3d complex array (nmodes, natoms, 3) Complex eigenvectors of the dynamical matrix for the q-point. """ assert natoms is not None cmd = r"egrep 'q.*=.*\(' %s | tail -n1 | sed -re 's/.*q\s*=.*\((.*)\)/\1/'" %filename qpoints = np.fromstring(common.backtick(cmd), sep=' ') assert qpoints.shape == (3,) nmodes = 3*natoms cmd = r"grep -v 'q.*=' %s | grep '^[ ]*(' | sed -re 's/^\s*\((.*)\)/\1/g'" %filename # vecs_file_flat: (nmodes * natoms, 6) # this line is the bottleneck vecs_file_flat = parse.arr2d_from_txt(common.backtick(cmd)) vecs_flat = np.empty((vecs_file_flat.shape[0], 3), dtype=complex) vecs_flat[:,0] = vecs_file_flat[:,0] + 1j*vecs_file_flat[:,1] vecs_flat[:,1] = vecs_file_flat[:,2] + 1j*vecs_file_flat[:,3] vecs_flat[:,2] = vecs_file_flat[:,4] + 1j*vecs_file_flat[:,5] vecs = vecs_flat.flatten().reshape(nmodes, natoms, 3) cmd = r"grep omega %s | sed -re \ 's/.*omega.*=.*\[.*=(.*)\s*\[.*/\1/g'" %filename freqs = np.fromstring(common.backtick(cmd), sep=' ') return qpoints, freqs, vecs
def read_dyn(filename, natoms=None): """Read one dynamical matrix file (for 1 qpoint) produced by ``ph.x`` and extract the same as :func:`read_matdyn_modes` for this qpoint only. All arrays have one dim less compared to :func:`read_matdyn_modes`. Parameters ---------- filename : str Name of dyn file. Example: "ph.dyn3" for qpoint 3. natoms : int number of atoms in the cell (used for nmodes=3*natoms only) Returns ------- qpoints, freqs, vecs qpoints : 1d array (3,) The qpoint of the dyn file. freqs : 1d array, (nmodes,) where nmodes = 3*natoms 3*natoms phonon frequencies in [cm^-1] at the q-point. vecs : 3d complex array (nmodes, natoms, 3) Complex eigenvectors of the dynamical matrix for the q-point. """ assert natoms is not None cmd = r"egrep 'q.*=.*\(' %s | tail -n1 | sed -re 's/.*q\s*=.*\((.*)\)/\1/'" %filename qpoints = np.fromstring(common.backtick(cmd), sep=' ') assert qpoints.shape == (3,) nmodes = 3*natoms cmd = r"grep -v 'q.*=' %s | grep '^[ ]*(' | sed -re 's/^\s*\((.*)\)/\1/g'" %filename # vecs_file_flat: (nmodes * natoms, 6) # this line is the bottleneck vecs_file_flat = parse.arr2d_from_txt(common.backtick(cmd)) vecs_flat = np.empty((vecs_file_flat.shape[0], 3), dtype=complex) vecs_flat[:,0] = vecs_file_flat[:,0] + 1j*vecs_file_flat[:,1] vecs_flat[:,1] = vecs_file_flat[:,2] + 1j*vecs_file_flat[:,3] vecs_flat[:,2] = vecs_file_flat[:,4] + 1j*vecs_file_flat[:,5] vecs = vecs_flat.flatten().reshape(nmodes, natoms, 3) cmd = r"grep omega %s | sed -re \ 's/.*omega.*=.*\[.*=(.*)\s*\[.*/\1/g'" %filename freqs = np.fromstring(common.backtick(cmd), sep=' ') return qpoints, freqs, vecs
def test_lammps_calculator(): if not have_ase(): skip("no ASE found, skipping test") elif not have_lmp(): skip("no lammps found, skipping test") else: at = get_atoms_with_calc_lammps() at.rattle(stdev=0.001, seed=int(time.time())) common.makedirs(at.calc.directory) print(common.backtick("cp -v utils/lammps/AlN.tersoff {p}/".format( p=at.calc.directory))) print("scf") forces = at.get_forces() etot = at.get_potential_energy() stress = at.get_stress(voigt=False) # 3x3 st = io.read_lammps_md_txt(at.calc.label + '.out')[0] assert np.allclose(forces, st.forces) assert np.allclose(etot, st.etot) assert np.allclose(st.stress, -stress * constants.eV_by_Ang3_to_GPa, atol=1e-10) print("relax") from ase.optimize import BFGS opt = BFGS(at, maxstep=0.04) opt.run(fmax=0.001, steps=10) coords_frac = parse.arr2d_from_txt(""" 3.3333341909920072e-01 6.6666683819841532e-01 4.4325467247779138e-03 6.6666681184103216e-01 3.3333362368205072e-01 5.0443254824788963e-01 3.3333341909918301e-01 6.6666683819838046e-01 3.8356759709402671e-01 6.6666681184101539e-01 3.3333362368201563e-01 8.8356759861713752e-01 """) assert np.allclose(coords_frac, at.get_scaled_positions(), atol=1e-2) # at least 1 backup files must exist assert os.path.exists(at.calc.infile + '.0') assert os.path.exists(at.calc.outfile + '.0') assert os.path.exists(at.calc.dumpfile + '.0') assert os.path.exists(at.calc.structfile + '.0')
def test_lammps_calculator(): if not have_ase(): skip("no ASE found, skipping test") elif not have_lmp(): skip("no lammps found, skipping test") else: at = get_atoms_with_calc_lammps() at.rattle(stdev=0.001, seed=int(time.time())) common.makedirs(at.calc.directory) print common.backtick("cp -v utils/lammps/AlN.tersoff {p}/".format( p=at.calc.directory)) print "scf" forces = at.get_forces() etot = at.get_potential_energy() stress = at.get_stress(voigt=False) # 3x3 st = io.read_lammps_md_txt(at.calc.label + '.out')[0] assert np.allclose(forces, st.forces) assert np.allclose(etot, st.etot) assert np.allclose(st.stress, -stress * constants.eV_by_Ang3_to_GPa, atol=1e-10) print "relax" from ase.optimize import BFGS opt = BFGS(at, maxstep=0.04) opt.run(fmax=0.001, steps=10) coords_frac = parse.arr2d_from_txt(""" 3.3333341909920072e-01 6.6666683819841532e-01 4.4325467247779138e-03 6.6666681184103216e-01 3.3333362368205072e-01 5.0443254824788963e-01 3.3333341909918301e-01 6.6666683819838046e-01 3.8356759709402671e-01 6.6666681184101539e-01 3.3333362368201563e-01 8.8356759861713752e-01 """) assert np.allclose(coords_frac, at.get_scaled_positions(), atol=1e-2) # at least 1 backup files must exist assert os.path.exists(at.calc.infile + '.0') assert os.path.exists(at.calc.outfile + '.0') assert os.path.exists(at.calc.dumpfile + '.0') assert os.path.exists(at.calc.structfile + '.0')
def read_matdyn_modes(filename, natoms=None): """Parse modes file produced by QE's matdyn.x. Parameters ---------- filename : str File to parse (usually "matdyn.modes") natoms : int Number of atoms. Returns ------- qpoints, freqs, vecs qpoints : 2d array (nqpoints, 3) All qpoints on the grid. freqs : 2d array, (nqpoints, nmodes) where nmodes = 3*natoms Each row: 3*natoms phonon frequencies in [cm^-1] at each q-point. vecs : 4d complex array (nqpoints, nmodes, natoms, 3) Complex eigenvectors of the dynamical matrix for each q-point. Examples -------- >>> qpoints,freqs,vecs=read_matdyn_modes('matdyn.modes',natoms=27) # how many q-points? -> 8 >>> qpoints.shape (8,3) # 1st q-point in file, mode #3 (out of 3*27) -> vectors on all 27 atoms >>> vecs[0,2,...].shape (27,3) # 1st q-point in file, mode #3, vector on atom #15 >>> vecs[0,2,14,:].real array([-0.010832, 0.026063, -0.089511]) >>> vecs[0,2,14,:].imag array([ 0., 0., 0.]) Notes ----- The file to be parsed looks like this:: diagonalizing the dynamical matrix ... q = 0.0000 0.0000 0.0000 ************************************************************************** omega( 1) = -26.663631 [THz] = -889.402992 [cm-1] ( -0.218314 0.000000 -0.025643 0.000000 -0.116601 0.000000 ) ( -0.086633 0.000000 0.108966 0.000000 -0.066513 0.000000 ) [... natoms lines: x_real x_imag y_real y_imag z_real z_imag ... until next omega ...] omega( 2) = -16.330246 [THz] = -544.718372 [cm-1] ( 0.172149 0.000000 0.008336 0.000000 -0.121991 0.000000 ) ( -0.061497 0.000000 0.003782 0.000000 -0.018304 0.000000 ) [... until omega(3*natoms) ...] ************************************************************************** diagonalizing the dynamical matrix ... [... until next q-point ...] q = 0.0000 0.0000 -0.5000 ************************************************************************** omega( 1) = -24.881828 [THz] = -829.968443 [cm-1] ( -0.225020 0.000464 -0.031584 0.000061 -0.130217 0.000202 ) ( -0.085499 0.000180 0.107383 -0.000238 -0.086854 0.000096 ) [...] ************************************************************************** """ assert natoms is not None cmd = r"grep 'q.*=' %s | sed -re 's/.*q\s*=(.*)/\1/'" %filename qpoints = parse.arr2d_from_txt(common.backtick(cmd)) nqpoints = qpoints.shape[0] nmodes = 3*natoms cmd = r"grep '^[ ]*(' %s | sed -re 's/^\s*\((.*)\)/\1/g'" %filename # vecs_file_flat: (nqpoints * nmodes * natoms, 6) # this line is the bottleneck vecs_file_flat = parse.arr2d_from_txt(common.backtick(cmd)) vecs_flat = np.empty((vecs_file_flat.shape[0], 3), dtype=complex) vecs_flat[:,0] = vecs_file_flat[:,0] + 1j*vecs_file_flat[:,1] vecs_flat[:,1] = vecs_file_flat[:,2] + 1j*vecs_file_flat[:,3] vecs_flat[:,2] = vecs_file_flat[:,4] + 1j*vecs_file_flat[:,5] vecs = vecs_flat.flatten().reshape(nqpoints, nmodes, natoms, 3) cmd = r"grep omega %s | sed -re \ 's/.*omega.*=.*\[.*=(.*)\s*\[.*/\1/g'" %filename freqs = np.fromstring(common.backtick(cmd), sep=' ').reshape((nqpoints, nmodes)) return qpoints, freqs, vecs
def read_matdyn_modes(filename, natoms=None): """Parse modes file produced by QE's matdyn.x. Parameters ---------- filename : str File to parse (usually "matdyn.modes") natoms : int Number of atoms. Returns ------- qpoints, freqs, vecs qpoints : 2d array (nqpoints, 3) All qpoints on the grid. freqs : 2d array, (nqpoints, nmodes) where nmodes = 3*natoms Each row: 3*natoms phonon frequencies in [cm^-1] at each q-point. vecs : 4d complex array (nqpoints, nmodes, natoms, 3) Complex eigenvectors of the dynamical matrix for each q-point. Examples -------- >>> qpoints,freqs,vecs=read_matdyn_modes('matdyn.modes',natoms=27) # how many q-points? -> 8 >>> qpoints.shape (8,3) # 1st q-point in file, mode #3 (out of 3*27) -> vectors on all 27 atoms >>> vecs[0,2,...].shape (27,3) # 1st q-point in file, mode #3, vector on atom #15 >>> vecs[0,2,14,:].real array([-0.010832, 0.026063, -0.089511]) >>> vecs[0,2,14,:].imag array([ 0., 0., 0.]) Notes ----- The file to be parsed looks like this:: diagonalizing the dynamical matrix ... q = 0.0000 0.0000 0.0000 ************************************************************************** omega( 1) = -26.663631 [THz] = -889.402992 [cm-1] ( -0.218314 0.000000 -0.025643 0.000000 -0.116601 0.000000 ) ( -0.086633 0.000000 0.108966 0.000000 -0.066513 0.000000 ) [... natoms lines: x_real x_imag y_real y_imag z_real z_imag ... until next omega ...] omega( 2) = -16.330246 [THz] = -544.718372 [cm-1] ( 0.172149 0.000000 0.008336 0.000000 -0.121991 0.000000 ) ( -0.061497 0.000000 0.003782 0.000000 -0.018304 0.000000 ) [... until omega(3*natoms) ...] ************************************************************************** diagonalizing the dynamical matrix ... [... until next q-point ...] q = 0.0000 0.0000 -0.5000 ************************************************************************** omega( 1) = -24.881828 [THz] = -829.968443 [cm-1] ( -0.225020 0.000464 -0.031584 0.000061 -0.130217 0.000202 ) ( -0.085499 0.000180 0.107383 -0.000238 -0.086854 0.000096 ) [...] ************************************************************************** """ assert natoms is not None cmd = r"grep 'q.*=' %s | sed -re 's/.*q\s*=(.*)/\1/'" %filename qpoints = parse.arr2d_from_txt(common.backtick(cmd)) nqpoints = qpoints.shape[0] nmodes = 3*natoms cmd = r"grep '^[ ]*(' %s | sed -re 's/^\s*\((.*)\)/\1/g'" %filename # vecs_file_flat: (nqpoints * nmodes * natoms, 6) # this line is the bottleneck vecs_file_flat = parse.arr2d_from_txt(common.backtick(cmd)) vecs_flat = np.empty((vecs_file_flat.shape[0], 3), dtype=complex) vecs_flat[:,0] = vecs_file_flat[:,0] + 1j*vecs_file_flat[:,1] vecs_flat[:,1] = vecs_file_flat[:,2] + 1j*vecs_file_flat[:,3] vecs_flat[:,2] = vecs_file_flat[:,4] + 1j*vecs_file_flat[:,5] vecs = vecs_flat.flatten().reshape(nqpoints, nmodes, natoms, 3) cmd = r"grep omega %s | sed -re \ 's/.*omega.*=.*\[.*=(.*)\s*\[.*/\1/g'" %filename freqs = np.fromstring(common.backtick(cmd), sep=' ').reshape((nqpoints, nmodes)) return qpoints, freqs, vecs
# Test parsing the correct SCF cell from a [vc-]relax run (QE 5.x only, IIRC), # which performs a final SCF run after the relax has converged. import os import numpy as np from pwtools import common, crys, parse, io # from pw.out: "reduced cell" = cell / alat cell_2d_red_ref = parse.arr2d_from_txt(""" 1.000000 0.000000 0.000000 0.000000 2.902399 0.000000 0.000000 0.000000 2.304846 """) def test_scf_cell(): filename = 'files/pw.vc_relax_coords_fixed.out' common.system('gunzip %s.gz' % filename) pp = parse.PwSCFOutputFile(filename, use_alat=False) cell_2d_red = pp.get_cell() assert np.allclose(cell_2d_red, cell_2d_red_ref, atol=1e-15, rtol=0) pp = parse.PwSCFOutputFile(filename, use_alat=True) assert np.allclose(pp.get_cell(), cell_2d_red * pp.get_alat(), atol=1e-15, rtol=0) st = io.read_pw_scf(filename) tr = io.read_pw_md(filename)
def test_read_dynmat(): table_txt = """ # mode [cm-1] [THz] IR Raman depol.fact 1 0.00 0.0000 0.0000 0.0005 0.7414 2 0.00 0.0000 0.0000 0.0005 0.7465 3 0.00 0.0000 0.0000 0.0018 0.2647 4 252.27 7.5627 0.0000 0.0073 0.7500 5 252.27 7.5627 0.0000 0.0073 0.7500 6 548.44 16.4419 0.0000 0.0000 0.7434 7 603.32 18.0872 35.9045 18.9075 0.7366 8 656.82 19.6910 0.0000 7.9317 0.7500 9 656.82 19.6910 0.0000 7.9317 0.7500 10 669.67 20.0762 31.5712 5.0265 0.7500 11 738.22 22.1311 0.0000 0.0000 0.7306 12 922.64 27.6600 31.5712 5.0265 0.7500 """ vecs_txt = """ 0.03895 -0.03122 -0.00290 0.03895 -0.03122 -0.00290 0.03895 -0.03122 -0.00290 0.03895 -0.03122 -0.00290 -0.03116 -0.03906 0.00186 -0.03116 -0.03906 0.00186 -0.03116 -0.03906 0.00186 -0.03116 -0.03906 0.00186 0.00343 -0.00036 0.04988 0.00343 -0.00036 0.04988 0.00343 -0.00036 0.04988 0.00343 -0.00036 0.04988 0.02589 -0.04674 0.00000 -0.02589 0.04674 0.00000 -0.02244 0.04051 0.00000 0.02244 -0.04051 0.00000 0.04674 0.02589 0.00000 -0.04674 -0.02589 0.00000 -0.04051 -0.02244 0.00000 0.04051 0.02244 0.00000 0.00000 0.00000 0.07029 0.00000 0.00000 -0.07029 0.00000 0.00000 -0.00766 0.00000 0.00000 0.00766 0.00000 0.00000 -0.03258 0.00000 0.00000 -0.03258 0.00000 0.00000 0.06276 0.00000 0.00000 0.06276 -0.02867 -0.00445 0.00000 0.02867 0.00445 0.00000 -0.06372 -0.00990 0.00000 0.06372 0.00990 0.00000 0.00445 -0.02867 0.00000 -0.00445 0.02867 0.00000 0.00990 -0.06372 0.00000 -0.00990 0.06372 0.00000 0.00000 0.03258 0.00000 0.00000 0.03258 0.00000 0.00000 -0.06276 0.00000 0.00000 -0.06276 0.00000 0.00000 0.00000 -0.00399 0.00000 0.00000 0.00399 0.00000 0.00000 -0.07060 0.00000 0.00000 0.07060 -0.03258 0.00000 0.00000 -0.03258 0.00000 0.00000 0.06276 0.00000 0.00000 0.06276 0.00000 0.00000 """ arr = parse.arr2d_from_txt(table_txt) freqs_ref = arr[:,1] ir_ref = arr[:,3] raman_ref = arr[:,4] depol_ref = arr[:,5] vecs_flat = parse.arr2d_from_txt(vecs_txt) natoms = 4 nmodes = 3*natoms vecs_ref = np.empty((nmodes, natoms, 3), dtype=float) for imode in range(nmodes): for iatom in range(natoms): idx = imode*natoms + iatom vecs_ref[imode, iatom,:] = vecs_flat[idx, :] qpoints,freqs,vecs = pwscf.read_dynmat(path='files/dynmat', filename='dynmat_all.out', axsf='dynmat.axsf', natoms=natoms) assert np.allclose(freqs_ref, freqs) assert np.allclose(vecs_ref, vecs) assert (qpoints == np.array([0,0,0])).all() dct = pwscf.read_dynmat_ir_raman(filename='files/dynmat/dynmat_all.out', natoms=natoms) assert np.allclose(dct['freqs'], freqs_ref) assert np.allclose(dct['ir'], ir_ref) assert np.allclose(dct['raman'], raman_ref) assert np.allclose(dct['depol'], depol_ref) dct = pwscf.read_dynmat_ir_raman(filename='files/dynmat/dynmat_min.out', natoms=natoms) assert np.allclose(dct['freqs'], freqs_ref) assert np.allclose(dct['ir'], ir_ref) assert dct['raman'] is None assert dct['depol'] is None
# Test parsing the correct SCF cell from a [vc-]relax run (QE 5.x only, IIRC), # which performs a final SCF run after the relax has converged. import os import numpy as np from pwtools import common, crys, parse, io # from pw.out: "reduced cell" = cell / alat cell_2d_red_ref = parse.arr2d_from_txt(""" 1.000000 0.000000 0.000000 0.000000 2.902399 0.000000 0.000000 0.000000 2.304846 """) def test_scf_cell(): filename = 'files/pw.vc_relax_coords_fixed.out' common.system('gunzip %s.gz' %filename) pp = parse.PwSCFOutputFile(filename, use_alat=False) cell_2d_red = pp.get_cell() assert np.allclose(cell_2d_red, cell_2d_red_ref, atol=1e-15, rtol=0) pp = parse.PwSCFOutputFile(filename, use_alat=True) assert np.allclose(pp.get_cell(), cell_2d_red*pp.get_alat(), atol=1e-15, rtol=0) st = io.read_pw_scf(filename) tr = io.read_pw_md(filename)