def test_textfile(): from fileio import TextFile files = get_files() # test empty initialization empty = TextFile() # test read f = TextFile(files['scf.in']) assert(len(f.read())==1225) assert(len(f.lines())==55) assert(len(f.tokens())==125) assert(f.readline()=='&CONTROL\n') assert(f.readline()==" calculation = 'scf'\n") assert(f.readline('celldm')=='celldm(1) = 1.0\n') assert(f.readtokens('ecutwfc')==['ecutwfc', '=', '272']) val = f.readtokensf('CELL_PARAMETERS',float,float,float) ref = [28.34589199, 0.0, 0.0] assert(value_eq(val,ref)) f.close()
def analyze(self): path = self.path infile_name = self.infile_name outfile_name = self.outfile_name pw2c_outfile_name = self.pw2c_outfile_name nx = 0 outfile = os.path.join(path, outfile_name) try: # perform MD analysis f = TextFile(outfile) n = 0 md_res = [] while f.seek('!', 1) != -1: E = float(f.readtokens()[-2]) f.seek('P=', 1) P = float(f.readtokens()[-1]) f.seek('time =', 1) t = float(f.readtokens()[-2]) f.seek('kinetic energy', 1) K = float(f.readtokens()[-2]) f.seek('temperature', 1) T = float(f.readtokens()[-2]) md_res.append((E, P, t, K, T)) n += 1 #end while md_res = array(md_res, dtype=float).T quantities = ('total_energy', 'pressure', 'time', 'kinetic_energy', 'temperature') md = obj() for i, q in enumerate(quantities): md[q] = md_res[i] #end for md.potential_energy = md.total_energy - md.kinetic_energy self.md_data = md self.md_stats = self.md_statistics() if self.info.md_only: return #end if except: nx += 1 if self.info.warn: self.warn('MD analysis failed') #end if #end try try: lines = open(outfile, 'r').read().splitlines() except: nx += 1 if self.info.warn: self.warn('file read failed') #end if #end try try: fermi_energies = [] for l in lines: if l.find('Fermi energ') != -1: toks = l.split()[::-1] assert toks[0] == 'ev' for tok in toks[1:]: try: ef1 = float(tok) fermi_energies.append(ef1) except ValueError: fermi_energies = fermi_energies[::-1] break #end try #end for #end if #end for if len(fermi_energies) == 0: self.Ef = 0.0 else: self.Ef = fermi_energies[-1] #end if self.fermi_energies = array(fermi_energies) except: nx += 1 if self.info.warn: self.warn('fermi energy read failed') #end if #end try try: energies = [] for l in lines: if l.find('! ') != -1: energies.append(float(l.split('=')[1].split()[0])) #end if #end for if len(energies) == 0: self.E = 0.0 else: self.E = energies[-1] #end if self.energies = array(energies) except: nx += 1 if self.info.warn: self.warn('total energy read failed') #end if #end try try: # get bands and occupations nfound = 0 index = -1 bands = obj() bands.up = obj() bands.down = obj() polarized = False if self.input.system.nspin > 1: polarized = True #end if read_kpoints = False read_2pi_alat = False read_rel = False for i in range(len(lines)): l = lines[i] if 'End of self-consistent calculation' in l: # Initialize each time in case a hybrid functional was used if nfound > 0: nfound = 0 index = -1 bands = obj() bands.up = obj() bands.down = obj() #end if #end if if '- SPIN UP -' in l: up_spin = True elif '- SPIN DOWN -' in l: up_spin = False index = -1 #end if if 'number of k points=' in l: try: num_kpoints = int(l.strip().split()[4]) except: print( "Number of k-points {0} is not an integer".format( num_kpoints)) #end try kpoints_2pi_alat = lines[i + 2:i + 2 + num_kpoints] kpoints_rel = lines[i + 4 + num_kpoints:i + 4 + 2 * num_kpoints] kpoints_2pi_alat = array([ k.strip().split()[4:6] + [k.strip().split()[6][0:-2]] for k in kpoints_2pi_alat ], dtype=float) kpoints_rel = array([ k.strip().split()[4:6] + [k.strip().split()[6][0:-2]] for k in kpoints_rel ], dtype=float) #end if if 'bands (ev)' in l: index += 1 nfound += 1 i_occ = -1 j = i while i_occ == -1: j += 1 if 'occupation numbers' in lines[j]: i_occ = j #end if #end while seigs = '' for j in range(i + 1, i_occ): seigs += lines[j] #end for seigs = seigs.replace( '-', ' -' ) # For cases where the eigenvalues "touch", e.g. -144.9938-144.9938 -84.3023 seigs = seigs.strip() eigs = array(seigs.split(), dtype=float) soccs = '' for j in range(i_occ + 1, i_occ + 1 + (i_occ - i) - 2): soccs += lines[j] #end for occs = array(soccs.split(), dtype=float) bk = obj( index=index, kpoint_2pi_alat=kpoints_2pi_alat[index], kpoint_rel=kpoints_rel[index], eigs=eigs, occs=occs, pol='none', ) band_channel = bands.up if polarized: if up_spin: bk.pol = 'up' elif not up_spin: bk.pol = 'down' band_channel = bands.down #end if else: index = nfound - 1 #end if band_channel.append(bk) #if nfound==1: # bands.up = obj( # eigs = eigs, # occs = occs # ) #elif nfound==2: # bands.down = obj( # eigs = eigs, # occs = occs # ) #end if #end if #end for vbm = obj(energy=-1.0e6) cbm = obj(energy=1.0e6) direct_gap = obj(energy=1.0e6) for band_channel in bands: for b in band_channel: e_val = max(b.eigs[b.occs > 0.5]) e_cond = min(b.eigs[b.occs < 0.5]) if e_val > vbm.energy: vbm.energy = e_val vbm.kpoint_rel = b.kpoint_rel vbm.kpoint_2pi_alat = b.kpoint_2pi_alat vbm.index = b.index vbm.pol = b.pol vbm.band_number = max(where(b.occs > 0.5)) #end if if e_cond < cbm.energy: cbm.energy = e_cond cbm.kpoint_rel = b.kpoint_rel cbm.kpoint_2pi_alat = b.kpoint_2pi_alat cbm.index = b.index cbm.pol = b.pol cbm.band_number = min(where(b.occs < 0.5)) #end if if (e_cond - e_val) < direct_gap.energy: direct_gap.energy = e_cond - e_val direct_gap.kpoint_rel = b.kpoint_rel direct_gap.kpoint_2pi_alat = b.kpoint_2pi_alat direct_gap.index = b.index direct_gap.pol = [vbm.pol, cbm.pol] #end if #end for #end for electronic_structure = '' if (vbm.energy + 0.025) >= cbm.energy: if vbm.band_number == cbm.band_number: electronic_structure = 'metallic' else: electronic_structure = 'semi-metal' #end if else: electronic_structure = 'insulating' if not equal(vbm.kpoint_rel, cbm.kpoint_rel).all(): indirect_gap = obj(energy=round(cbm.energy - vbm.energy, 3), kpoints=obj(vbm=vbm, cbm=cbm)) bands.indirect_gap = indirect_gap #end if bands.electronic_structure = electronic_structure bands.vbm = vbm bands.cbm = cbm bands.direct_gap = direct_gap if nfound > 0: self.bands = bands #end if # Kayahan edited --end except: nx += 1 if self.info.warn: self.warn('band read failed') #end if #end try try: # read structures structures = obj() i = 0 found = False cont = False while i < len(lines): l = lines[i] if l.find('CELL_PARAMETERS') != -1 and l.strip().startswith( 'CELL'): conf = obj() axes = [] cont = True for d in (0, 1, 2): i += 1 axes.append(array(lines[i].split(), dtype=float)) #end for conf.axes = array(axes) #end if if l.find('ATOMIC_POSITIONS') != -1: found = True if not cont: conf = obj() #end if atoms = [] positions = [] i += 1 tokens = lines[i].split() while len(tokens) > 0 and tokens[0].lower() != 'end' and ( len(tokens) == 4 or (len(tokens) == 7 and tokens[-1] in '01')): atoms.append(tokens[0]) positions.append(array(tokens[1:4], dtype=float)) i += 1 tokens = lines[i].split() #end while conf.atoms = atoms conf.positions = array(positions) if 'crystal' in l.lower() and 'axes' in conf: conf.positions = dot(conf.positions, conf.axes) #end if nconf = len(structures) structures[nconf] = conf cont = False #end if i += 1 #end while if found: self.structures = structures #end if except: nx += 1 if self.info.warn: self.warn('structure read failed') #end if #end try #begin added by Yubo "Paul" Yang: cell, stress, pressure and volume # 01/21/2016: grab cells in a vc-relax run, one at each optimization step # 09/29/2016: obselete after rev7131 # grab stress, pressure and volume try: press = 0. vol = 0. for l in lines: if l.find('unit-cell volume') != -1: #vol = float( l.split('=')[-1].split()[-2] ) vol = l.split('=')[-1].split()[-2] # end if if (l.find('total') != -1) and (l.find('stress') != -1): press = l.split('=')[-1] # end if # end for self.pressure = float(press) self.volume = float(vol) except: nx += 1 if self.info.warn: self.warn('pressure/volume read failed') #end if #end try try: stress = [] nlines = len(lines) i = 0 while i < nlines: l = lines[i] if l.find('total stress') != -1: for j in range(3): i += 1 stress.append( list(np.array(lines[i].split(), dtype=float))) #end for #end if i += 1 #end while self.stress = stress except: nx += 1 if self.info.warn: self.warn('stress read failed') #end if #end try #end added by Yubo "Paul" Yang try: forces = [] tot_forces = [] i = 0 found = False nlines = len(lines) while i < nlines: l = lines[i] if l.find('Forces acting on atoms') != -1: found = True conf = obj() aforces = [] found_atom = False for j in range(10): i += 1 if i < nlines and 'atom' in lines[i]: found_atom = True break #end if #end for if found_atom: tokens = lines[i].split() while len(tokens) == 9 and tokens[4] == 'force': aforces.append(tokens[6:]) i += 1 tokens = lines[i].split() #end while #end if forces.append(aforces) i += 1 elif 'Total force' in l: tokens = l.split() if len(tokens) == 9 and tokens[1] == 'force': tot_forces.append(float(tokens[3])) #end if #end if i += 1 #end while if found: self.forces = array(forces, dtype=float) self.tot_forces = array(tot_forces) max_forces = [] for f in self.forces: if len(f.shape) == 2: max_forces.append((sqrt((f**2).sum(1))).max()) #end if #end for self.max_forces = array(max_forces) #end if except: nx += 1 if self.info.warn: self.warn('force read failed') #end if #end try try: tc = 0. tw = 0. for l in lines: if l.find('PWSCF :') != -1: t1 = l.split(':')[1].split('CPU') tc = pwscf_time(t1[0]) tw = pwscf_time(t1[1].replace('WALL', '')) break #end if #end for self.cputime = tc self.walltime = tw except: nx += 1 if self.info.warn: self.warn('time read failed') #end if #end try try: # read symmetrized k-points nkpoints = None i = 0 for l in lines: if 'number of k points' in l: tokens = l.replace('=', ' ').split() nkpoints = int(tokens[4]) break #end if i += 1 #end for if nkpoints is not None: i += 2 klines_cart = lines[i:i + nkpoints] i += nkpoints + 2 klines_unit = lines[i:i + nkpoints] kpoints_cart = [] for l in klines_cart: tokens = l.replace('= (', ':').replace('), wk =', ':').split(':') kpoints_cart.append(tokens[1].split()) #end for kpoints_unit = [] kweights = [] for l in klines_unit: tokens = l.replace('= (', ':').replace('), wk =', ':').split(':') kpoints_unit.append(tokens[1].split()) kweights.append(tokens[2]) #end for self.kpoints_cart = array(kpoints_cart, dtype=float) self.kpoints_unit = array(kpoints_unit, dtype=float) self.kweights = array(kweights, dtype=float) #end if except: nx += 1 if self.info.warn: self.warn('symmetrized kpoint read failed') #end if #end try try: if pw2c_outfile_name != None: lines = open(os.path.join(path, pw2c_outfile_name), 'r').readlines() for l in lines: if l.find('Kinetic') != -1: tokens = l.split() self.K = eval(tokens[5]) break #end if #end for #end if except: nx += 1 if self.info.warn: self.warn('pw2casino read failed') #end if #end try if nx > 0 and self.info.warn: self.warn( 'encountered an exception, some quantities will not be available' ) #end try if self.info.xml: self.xmldata = obj(data=None, kpoints=None, failed=False) try: cont = self.input.control datadir = os.path.join(self.path, cont.outdir, cont.prefix + '.save') data_file = os.path.join(datadir, 'data-file.xml') if not os.path.exists(data_file): datadir = os.path.join(self.path, cont.outdir) data_file = os.path.join(datadir, cont.prefix + '.xml') #end if data = read_qexml(data_file) kpdata = data.root.eigenvalues.k_point kpoints = obj() for ki, kpd in kpdata.items(): kp = obj(kpoint=kpd.k_point_coords, weight=kpd.weight) kpoints[ki] = kp for si, dfile in kpd.datafile.items(): efilepath = os.path.join(datadir, dfile.iotk_link) if os.path.exists(efilepath): edata = read_qexml(efilepath) eunits = edata.root.units_for_energies.units.lower( ) if eunits.startswith('ha'): units = 'Ha' elif eunits.startswith('ry'): units = 'Ry' elif eunits.startswith('ev'): units = 'eV' else: units = 'Ha' #end if spin = obj(units=units, eigenvalues=edata.root.eigenvalues, occupations=edata.root.occupations) if si == 1: kp.up = spin elif si == 2: kp.down = spin #end if else: self.xmldata.failed = True #end if #end for #end for self.xmldata.set(data=data, kpoints=kpoints) except Exception as e: if self.info.warn: self.warn( 'encountered an exception during xml read, this data will not be available\nexception encountered: ' + str(e)) #end if self.xmldata.failed = True