def struct_str(struct): """Convert Structure object to lammps format. The returned string can be written to a file and read in a lammps input file by ``read_data``. Parameters ---------- struct : Structure Returns ------- str : string References ---------- ase.calculators.lammpsrun (ASE 3.8). """ # align cell to [[x,0,0],[xy,y,0],[xz, yz, z]] (row format, the transpose # is what lammps uses) st = struct.copy() st.coords = None st.cell = None st.set_all() head_str = "structure written by pwtools {0}".format(time.asctime()) info_str = '%i atoms\n%i atom types' % (st.natoms, len(st.symbols_unique)) cell_str = "0.0 {x:.14g} xlo xhi\n0.0 {y:.14g} ylo yhi\n0.0 {z:.14g} zlo zhi\n" cell_str += "{tilts} xy xz yz\n" cell_str = cell_str.format(x=st.cell[0, 0], y=st.cell[1, 1], z=st.cell[2, 2], tilts=common.str_arr(np.array([ st.cell[1, 0], st.cell[2, 0], st.cell[2, 1] ]), eps=1e-13, fmt='%.14g', delim=' ')) atoms_str = "Atoms\n\n" for iatom in range(st.natoms): atoms_str += "{iatom} {ispec} {xyz}".format( iatom=iatom + 1, ispec=st.order[st.symbols[iatom]], xyz=common.str_arr(st.coords[iatom, :], eps=1e-13, fmt='%23.16e') + '\n') mass_str = "Masses\n\n" for idx, sy in enumerate(st.symbols_unique): mass_str += "%i %g\n" % (idx + 1, atomic_data.pt[sy]['mass']) return head_str + '\n\n' + info_str + '\n\n' + cell_str + \ '\n' + atoms_str + '\n' + mass_str
def write_input(self, atoms, properties=None, system_changes=None): FileIOCalculator.write_input(self, atoms, properties, system_changes) struct = crys.atoms2struct(atoms) self.cell = common.str_arr(struct.cell) self.kpoints = pwscf.kpoints_str_pwin(kpts2mp(atoms, self.kpts)) if isinstance(self.pp, bytes): pseudos = [ "%s.%s" % (sym, self.pp) for sym in struct.symbols_unique ] else: assert len(self.pp) == struct.ntypat pseudos = [] for sym in struct.symbols_unique: for ppi in self.pp: if ppi.startswith(sym): pseudos.append(ppi) break assert len(pseudos) == struct.ntypat self.atspec = pwscf.atspec_str(symbols=struct.symbols_unique, masses=struct.mass_unique, pseudos=pseudos) self.atpos = pwscf.atpos_str(symbols=struct.symbols, coords=struct.coords_frac) self.natoms = struct.natoms self.ntyp = struct.ntypat if self.backup: for fn in [self.infile, self.outfile]: if os.path.exists(fn): common.backup(fn) common.file_write(self.infile, self.fill_infile_templ())
def _fit(self): # volume[Bohr^3] etot[Ha] for eos.x volume = self.volume * (Ang**3.0 / Bohr**3.0) energy = self.energy * (eV / Ha) data = np.array([volume, energy]).T infn_txt =\ """ %s %i %i %f, %f, %i %i %s """%(self.name, self.natoms, self.etype, volume[0], volume[-1], self.npoints, len(volume), common.str_arr(data)) common.file_write(self.infn, infn_txt) out = common.backtick('cd %s && %s' % (self.dir, self.app_basename)) if self.verbose: print(out) print((open(os.path.join(self.dir, 'PARAM.OUT')).read())) # Remove normalization on natoms. See .../eos/output.f90: # fitev: [volume [Bohr^3] / natoms, energy [Ha] / natoms] # fitpv: [volume [Bohr^3] / natoms, pressure [GPa]] fitev = np.loadtxt(os.path.join(self.dir, 'EVPAI.OUT')) * self.natoms # convert energy back to [Ang^3, eV] fitev[:, 0] *= (Bohr**3 / Ang**3) fitev[:, 1] *= (Ha / eV) self.ev = fitev fitpv = np.loadtxt(os.path.join(self.dir, 'PVPAI.OUT')) fitpv[:, 0] *= (self.natoms * Bohr**3 / Ang**3) self.pv = fitpv
def _fit(self): # volume[Bohr^3] etot[Ha] for eos.x volume = self.volume*(Ang**3.0 / Bohr**3.0) energy = self.energy*(eV / Ha) data = np.array([volume, energy]).T infn_txt =\ """ %s %i %i %f, %f, %i %i %s """%(self.name, self.natoms, self.etype, volume[0], volume[-1], self.npoints, len(volume), common.str_arr(data)) common.file_write(self.infn, infn_txt) out = common.backtick('cd %s && %s' %(self.dir, self.app_basename)) if self.verbose: print out print(open(os.path.join(self.dir,'PARAM.OUT')).read()) # Remove normalization on natoms. See .../eos/output.f90: # fitev: [volume [Bohr^3] / natoms, energy [Ha] / natoms] # fitpv: [volume [Bohr^3] / natoms, pressure [GPa]] fitev = np.loadtxt(os.path.join(self.dir,'EVPAI.OUT')) * self.natoms # convert energy back to [Ang^3, eV] fitev[:,0] *= (Bohr**3 / Ang**3) fitev[:,1] *= (Ha / eV) self.ev = fitev fitpv = np.loadtxt(os.path.join(self.dir,'PVPAI.OUT')) fitpv[:,0] *= (self.natoms * Bohr**3 / Ang**3) self.pv = fitpv
def write_input(self, atoms, properties=None, system_changes=None): FileIOCalculator.write_input(self, atoms, properties, system_changes) struct = crys.atoms2struct(atoms) self.cell = common.str_arr(struct.cell) self.kpoints = pwscf.kpoints_str_pwin(kpts2mp(atoms, self.kpts)) if isinstance(self.pp, types.StringType): pseudos = ["%s.%s" %(sym, self.pp) for sym in struct.symbols_unique] else: assert len(self.pp) == struct.ntypat pseudos = [] for sym in struct.symbols_unique: for ppi in self.pp: if ppi.startswith(sym): pseudos.append(ppi) break assert len(pseudos) == struct.ntypat self.atspec = pwscf.atspec_str(symbols=struct.symbols_unique, masses=struct.mass_unique, pseudos=pseudos) self.atpos = pwscf.atpos_str(symbols=struct.symbols, coords=struct.coords_frac) self.natoms = struct.natoms self.ntyp = struct.ntypat if self.backup: for fn in [self.infile, self.outfile]: if os.path.exists(fn): common.backup(fn) common.file_write(self.infile, self.fill_infile_templ())
def struct_str(struct): """Convert Structure object to lammps format. The returned string can be written to a file and read in a lammps input file by ``read_data``. Parameters ---------- struct : Structure Returns ------- str : string References ---------- ase.calculators.lammpsrun (ASE 3.8). """ # align cell to [[x,0,0],[xy,y,0],[xz, yz, z]] (row format, the transpose # is what lammps uses) st = struct.copy() st.coords = None st.cell = None st.set_all() head_str = "structure written by pwtools {0}".format(time.asctime()) info_str = '%i atoms\n%i atom types' %(st.natoms, len(st.symbols_unique)) cell_str = "0.0 {x:.14g} xlo xhi\n0.0 {y:.14g} ylo yhi\n0.0 {z:.14g} zlo zhi\n" cell_str += "{tilts} xy xz yz\n" cell_str = cell_str.format(x=st.cell[0,0], y=st.cell[1,1], z=st.cell[2,2], tilts=common.str_arr(np.array([st.cell[1,0], st.cell[2,0], st.cell[2,1]]), eps=1e-13, fmt='%.14g', delim=' ')) atoms_str = "Atoms\n\n" for iatom in range(st.natoms): atoms_str += "{iatom} {ispec} {xyz}".format( iatom=iatom+1, ispec=st.order[st.symbols[iatom]], xyz=common.str_arr(st.coords[iatom,:], eps=1e-13, fmt='%23.16e') + '\n') mass_str = "Masses\n\n" for idx,sy in enumerate(st.symbols_unique): mass_str += "%i %g\n" %(idx+1, atomic_data.pt[sy]['mass']) return head_str + '\n\n' + info_str + '\n\n' + cell_str + \ '\n' + atoms_str + '\n' + mass_str
def write_axsf(filename, obj): """Write animated XSF file for Structure (only 1 step) or Trajectory. Note that forces are converted eV / Ang -> Ha / Ang. length: Angstrom forces: Ha / Angstrom Parameters ---------- filename : target file name obj : Structure or Trajectory References ---------- [XSF] http://www.xcrysden.org/doc/XSF.html """ # Notes # ----- # XSF: The XSF spec [XSF] is a little fuzzy about what PRIMCOORD actually # is (fractional or cartesian Angstrom). Only the latter case results # in a correctly displayed structure in xcrsyden. So we use that. # # Speed: The only time-consuming step is calling atpos_str*() in the loop # b/c that transforms *every* single float to a string, which # effectively is a double loop over `ccf`. No way to get faster w/ pure # Python. # traj = crys.struct2traj(obj) # ccf = cartesian coords + forces (6 columns) if traj.is_set_attr('forces'): ccf = np.concatenate((traj.coords, traj.forces*eV/Ha), axis=-1) else: ccf = traj.coords axsf_str = "ANIMSTEPS %i\nCRYSTAL" %traj.nstep for istep in range(traj.nstep): axsf_str += "\nPRIMVEC %i\n%s" %(istep+1, common.str_arr(traj.cell[istep,...])) axsf_str += "\nPRIMCOORD %i\n%i 1\n%s" %(istep+1, traj.natoms, pwscf.atpos_str_fast(traj.symbols, ccf[istep,...])) common.file_write(filename, axsf_str)
def write_axsf(filename, obj): """Write animated XSF file for Structure (only 1 step) or Trajectory. Note that forces are converted eV / Ang -> Ha / Ang. length: Angstrom forces: Ha / Angstrom Parameters ---------- filename : target file name obj : Structure or Trajectory References ---------- [XSF] http://www.xcrysden.org/doc/XSF.html """ # Notes # ----- # XSF: The XSF spec [XSF] is a little fuzzy about what PRIMCOORD actually # is (fractional or cartesian Angstrom). Only the latter case results # in a correctly displayed structure in xcrsyden. So we use that. # # Speed: The only time-consuming step is calling atpos_str*() in the loop # b/c that transforms *every* single float to a string, which # effectively is a double loop over `ccf`. No way to get faster w/ pure # Python. # traj = crys.struct2traj(obj) # ccf = cartesian coords + forces (6 columns) if traj.is_set_attr('forces'): ccf = np.concatenate((traj.coords, traj.forces * eV / Ha), axis=-1) else: ccf = traj.coords axsf_str = "ANIMSTEPS %i\nCRYSTAL" % traj.nstep for istep in range(traj.nstep): axsf_str += "\nPRIMVEC %i\n%s" % ( istep + 1, common.str_arr(traj.cell[istep, ...])) axsf_str += "\nPRIMCOORD %i\n%i 1\n%s" % ( istep + 1, traj.natoms, pwscf.atpos_str_fast(traj.symbols, ccf[istep, ...])) common.file_write(filename, axsf_str)
def atpos_str(symbols, coords, fmt="%.16e", zero_eps=None, eps=EPS, delim=4*' '): """Convenience function to make a string for the ATOMIC_POSITIONS section of a pw.x input file. Parameters ---------- symbols : sequence strings with atom symbols, (natoms,), must match with the rows of coords coords : array (natoms, 3) with atomic coords, can also be (natoms, >3) to add constraints on atomic forces in PWscf eps : float Print values as 0.0 where abs(coords[i,j]) < eps. If eps < 0.0, then disable this. delim : str delimiter between columns Returns ------- string Examples -------- >>> print atpos_str(['Al', 'N'], array([[0,0,0], [0,0,1.]])) Al 0.0000000000 0.0000000000 0.0000000000 N 0.0000000000 0.0000000000 1.0000000000 """ if zero_eps is not None: warnings.warn("`zero_eps` is deprecated, use `eps` > 0 instead", DeprecationWarning) coords = np.asarray(coords) assert len(symbols) == coords.shape[0], "len(symbols) != coords.shape[0]" txt = '\n'.join("%s%s%s" %(symbols[i], delim, str_arr(row, fmt=fmt, eps=eps, delim=delim)) \ for i,row in enumerate(coords)) return txt
scratch='/scratch/schmerler', filename='calc.templ/job.pbs.theo', home='/home/schmerler') templates = [batch.FileTemplate(basename='pw.in')] # rs-AlN st = crys.Structure(coords_frac=np.array([[0.0]*3, [0.5]*3]), symbols=['Al','N'], cryst_const=np.array([2.76]*3 + [60]*3)) params_lst = [] for ecutwfc in np.linspace(30,100,8): params_lst.append([sql.SQLEntry(key='ecutwfc', sqlval=ecutwfc), sql.SQLEntry(key='ecutrho', sqlval=4.0*ecutwfc), sql.SQLEntry(key='cell', sqlval=common.str_arr(st.cell)), sql.SQLEntry(key='natoms', sqlval=st.natoms), sql.SQLEntry(key='atpos', sqlval=pwscf.atpos_str(st.symbols, st.coords_frac)), ]) calc = batch.ParameterStudy(machines=theo, templates=templates, params_lst=params_lst, study_name='convergence_test_cutoff', ) calc.write_input(sleep=0, backup=False, mode='w') if not os.path.exists('calc'): os.symlink('calc_theo', 'calc')
#!/usr/bin/python # Create a PWscf MD "trajectory" where the CELL_PARAMETERS unit changes. This # is for testing if the parser can handle that. The output file consists only # of CELL_PARAMETERS blocks, which is enough for PwVCMDOutputFile.get_gell() . # # usage # ------ # ./make-vc-md-cell.py > ../files/pw.vc-md.cell.out import numpy as np from pwtools import common cell = np.arange(1,10).reshape((3,3)) alat_lst = [2.0, 4.0] for ialat,alat in enumerate(alat_lst): for ii in range(5): cell_str = common.str_arr((cell + 0.02*ii + ialat)/alat) print "CELL_PARAMETERS (alat= %.5f)\n%s" %(alat, cell_str)
&input asr='crystal', XXXMASS flfrc='q2r.fc', flfrq='XXXFNFREQ' / XXXNKS XXXKS """ matdyn_in_fn = 'matdyn.disp.in' matdyn_freq_fn = 'matdyn.freq.disp' mass_str = '\n'.join("amass(%i)=%e" %(ii+1,m) for ii,m in \ enumerate(st.mass_unique)) rules = { 'XXXNKS': ks_path.shape[0], 'XXXKS': common.str_arr(ks_path), 'XXXMASS': mass_str, 'XXXFNFREQ': matdyn_freq_fn, } txt = common.template_replace(templ_txt, rules, conv=True, mode='txt') common.file_write(matdyn_in_fn, txt) common.system("gunzip q2r.fc.gz; matdyn.x < %s; gzip q2r.fc" % matdyn_in_fn) # parse matdyn output and plot # define special points path, used in plot_dis() to plot lines at special # points and make x-labels sp = kpath.SpecialPointsPath(ks=sp_points, ks_frac=sp_points_frac, symbols=sp_symbols)
# test/test_read_matdyn.py . import numpy as np from pwtools.common import str_arr natoms = 2 qpoints = np.array([[0, 0, 0.0], [0, 0, 0.5]]) nqpoints = len(qpoints) nmodes = 3 * natoms freqs = np.empty((nqpoints, nmodes)) vecs = np.empty((nqpoints, nmodes, natoms, 3)) num = 0 for iqpoint in range(nqpoints): print " diagonalizing the dynamical matrix ...\n" print " q = %s" % str_arr(qpoints[iqpoint], fmt="%f") print "*" * 79 for imode in range(nmodes): freqs[iqpoint, imode] = num print " omega(%i) = %f [THz] = %f [cm-1]" % (imode + 1, num * 0.1, num) num += 1 for iatom in range(natoms): vec_str = " (" for icoord in range(3): vecs[iqpoint, imode, iatom, icoord] = num vec_str += " %f %f " % (num, 0.03 * num) num += 1 vec_str += ")" print vec_str print "*" * 79
#!/usr/bin/python # Create a PWscf MD "trajectory" where the CELL_PARAMETERS unit changes. This # is for testing if the parser can handle that. The output file consists only # of CELL_PARAMETERS blocks, which is enough for PwVCMDOutputFile.get_gell() . # # usage # ------ # ./make-vc-md-cell.py > ../files/pw.vc-md.cell.out import numpy as np from pwtools import common if __name__ == '__main__': cell = np.arange(1, 10).reshape((3, 3)) alat_lst = [2.0, 4.0] for ialat, alat in enumerate(alat_lst): for ii in range(5): cell_str = common.str_arr((cell + 0.02 * ii + ialat) / alat) print("CELL_PARAMETERS (alat= %.5f)\n%s" % (alat, cell_str))
templ_txt = """ &input asr='crystal', XXXMASS flfrc='q2r.fc', flfrq='XXXFNFREQ' / XXXNKS XXXKS """ matdyn_in_fn = 'matdyn.disp.in' matdyn_freq_fn = 'matdyn.freq.disp' mass_str = '\n'.join("amass(%i)=%e" %(ii+1,m) for ii,m in \ enumerate(st.mass_unique)) rules = {'XXXNKS': ks_path.shape[0], 'XXXKS': common.str_arr(ks_path), 'XXXMASS': mass_str, 'XXXFNFREQ': matdyn_freq_fn, } txt = common.template_replace(templ_txt, rules, conv=True, mode='txt') common.file_write(matdyn_in_fn, txt) common.system("gunzip q2r.fc.gz; matdyn.x < %s; gzip q2r.fc" %matdyn_in_fn) # parse matdyn output and plot # define special points path, used in plot_dis() to plot lines at special # points and make x-labels sp = kpath.SpecialPointsPath(ks=sp_points, ks_frac=sp_points_frac,
/ CELL_PARAMETERS angstrom {cp_ang} CELL_PARAMETERS bohr {cp_bohr} ATOMIC_SPECIES {atspec} ATOMIC_POSITIONS crystal {atpos_frac} """ rules = {'bar': bar, 'nat': struct.natoms, 'ntyp': struct.ntypat, 'cp_alat': str_arr(struct.cell / struct.cryst_const[0]), 'cp_bohr': str_arr(struct.cell), 'cp_ang': str_arr(struct.cell * Bohr / Angstrom), 'atspec': atspec, 'atpos_frac': atpos_frac, } for ii, cd in enumerate(celldm): rules['cd%i' %(ii+1,)] = cd print out.format(**rules) #------------------------------------------------------------------------------- # ABINIT #------------------------------------------------------------------------------- print "\n" print bar
import numpy as np from pwtools.common import str_arr if __name__ == '__main__': natoms = 2 qpoints = np.array([[0, 0, 0.], [0, 0, 0.5]]) nqpoints = len(qpoints) nmodes = 3 * natoms freqs = np.empty((nqpoints, nmodes)) vecs = np.empty((nqpoints, nmodes, natoms, 3)) num = 0 for iqpoint in range(nqpoints): print(" diagonalizing the dynamical matrix ...\n") print(" q = %s" % str_arr(qpoints[iqpoint], fmt='%f')) print("*" * 79) for imode in range(nmodes): freqs[iqpoint, imode] = num print(" omega(%i) = %f [THz] = %f [cm-1]" % (imode + 1, num * 0.1, num)) num += 1 for iatom in range(natoms): vec_str = " (" for icoord in range(3): vecs[iqpoint, imode, iatom, icoord] = num vec_str += " %f %f " % (num, 0.03 * num) num += 1 vec_str += ")" print(vec_str) print("*" * 79)
CELL_PARAMETERS angstrom {cp_ang} CELL_PARAMETERS bohr {cp_bohr} ATOMIC_SPECIES {atspec} ATOMIC_POSITIONS crystal {atpos_frac} """ rules = { 'bar': bar, 'nat': struct.natoms, 'ntyp': struct.ntypat, 'cp_alat': str_arr(struct.cell / struct.cryst_const[0]), 'cp_bohr': str_arr(struct.cell), 'cp_ang': str_arr(struct.cell * Bohr / Angstrom), 'atspec': atspec, 'atpos_frac': atpos_frac, } for ii, cd in enumerate(celldm): rules['cd%i' % (ii + 1, )] = cd print(out.format(**rules)) #------------------------------------------------------------------------------- # ABINIT #------------------------------------------------------------------------------- print("\n") print(bar)