def __init__(self, width, orbitals): FermiDirac.__init__(self, width) self.orbitals = orbitals self.norbitals = len(self.orbitals) self.cnoe = 0.0 for orb in self.orbitals: self.cnoe += orb[0]
def calculate_band_energy(self, wfs): FermiDirac.calculate_band_energy(self, wfs) de_band = 0.0 for kpt in wfs.kpt_u: if hasattr(kpt, 'c_on'): for ne, c_n in zip(kpt.ne_o, kpt.c_on): de_band += ne * np.dot(np.abs(c_n)**2, kpt.eps_n) self.e_band += wfs.band_comm.sum(wfs.kpt_comm.sum(de_band))
def calculate_band_energy(self, wfs): FermiDirac.calculate_band_energy(self, wfs) de_band = 0.0 for kpt in wfs.kpt_u: if hasattr(kpt, 'c_on'): for ne, c_n in zip(kpt.ne_o, kpt.c_on): de_band += ne * np.dot(np.abs(c_n)**2, kpt.eps_n) self.e_band += wfs.bd.comm.sum(wfs.kd.comm.sum(de_band))
def get_paw(): """Return calculator object.""" c = {'energy': 0.001, 'eigenstates': 0.001, 'density': 0.001} return GPAW(convergence=c, eigensolver=RMMDIIS(), xc='LCY-PBE:omega=0.83:unocc=True', parallel={'domain': world.size}, h=0.35, occupations=FermiDirac(width=0.0, fixmagmom=True))
def get_paw(): """Return calculator object.""" c = {'energy': 0.05, 'eigenstates': 0.05, 'density': 0.05} return GPAW(convergence=c, eigensolver=RMMDIIS(), nbands=3, xc='PBE', # experimental={'niter_fixdensity': 2}, parallel={'domain': world.size}, h=0.35, occupations=FermiDirac(width=0.0, fixmagmom=True))
def setup_calculator(self): hund = (len(self.system) == 1) self.system.set_calculator( GPAW(xc=self.xc, h=self.h, hund=hund, setups=self.setups, txt=self.name + '.txt', mode=self.mode, spinpol=True, occupations=FermiDirac(0, fixmagmom=True)))
def calculate(self, wfs): FermiDirac.calculate(self, wfs) # Get the expansion coefficients c_un for each dscf-orbital # and incorporate their respective occupations into kpt.ne_o c_oun = [] for orb in self.orbitals: ef = self.fermilevel if self.fixmagmom: fermilevels = [ef + 0.5 * self.split, ef - 0.5 * self.split] else: fermilevels = ef c_oun.append(orb[1].expand(fermilevels, wfs)) for u, kpt in enumerate(wfs.kpt_u): kpt.ne_o = np.zeros(self.norbitals, dtype=float) kpt.c_on = np.zeros((self.norbitals, len(kpt.f_n)), dtype=complex) for o, orb in enumerate(self.orbitals): #TODO XXX false if orb[0]<0 since abs(c_n)**2>0 #kpt.c_on[o,:] = abs(orb[0])**0.5 * c_oun[o][u] kpt.ne_o[o] = orb[0] kpt.c_on[o,:] = c_oun[o][u] if wfs.nspins == 2: assert orb[2] in range(2), 'Invalid spin index' if orb[2] == kpt.s: kpt.ne_o[o] *= kpt.weight else: kpt.ne_o[o] = 0.0 else: kpt.ne_o[o] *= 0.5 * kpt.weight # Correct the magnetic moment for orb in self.orbitals: if orb[2] == 0: self.magmom += orb[0] elif orb[2] == 1: self.magmom -= orb[0]
def calculate(self, wfs): FermiDirac.calculate(self, wfs) # Get the expansion coefficients c_un for each dscf-orbital # and incorporate their respective occupations into kpt.ne_o c_oun = [] for orb in self.orbitals: ef = self.fermilevel if self.fixmagmom: fermilevels = [ef + 0.5 * self.split, ef - 0.5 * self.split] else: fermilevels = ef c_oun.append(orb[1].expand(fermilevels, wfs, self.fixmagmom)) for u, kpt in enumerate(wfs.kpt_u): kpt.ne_o = np.zeros(self.norbitals, dtype=float) kpt.c_on = np.zeros((self.norbitals, len(kpt.f_n)), dtype=complex) for o, orb in enumerate(self.orbitals): # TODO XXX false if orb[0]<0 since abs(c_n)**2>0 #kpt.c_on[o,:] = abs(orb[0])**0.5 * c_oun[o][u] kpt.ne_o[o] = orb[0] kpt.c_on[o, :] = c_oun[o][u] if wfs.nspins == 2: assert orb[2] in range(2), 'Invalid spin index' if orb[2] == kpt.s: kpt.ne_o[o] *= kpt.weight else: kpt.ne_o[o] = 0.0 else: kpt.ne_o[o] *= 0.5 * kpt.weight # Correct the magnetic moment for orb in self.orbitals: if orb[2] == 0: self.magmom += orb[0] elif orb[2] == 1: self.magmom -= orb[0]
def efield(efield=0.05, n=30): printit('running GS calculation for {}'.format(efield)) fname = "sb_relaxed.cif" a = read(fname) atom = read(fname) wire = make_supercell(atom, [[n, 0, 0], [0, 1, 0], [ 0, 0, 1]], wrap=True, tol=1e-05) wire.center(vacuum=15, axis=0) a = wire.copy() if not os.path.isfile('gs_{}.gpw'.format(efield)): calc = GPAW( # mode='lcao', mode='fd', basis='szp(dzp)', # eigensolver='cg', #mixer=Mixer(beta=0.2, nmaxold=3, weight=70.0), xc='PBE', # poissonsolver=DipoleCorrection(PoissonSolver(relax='GS'), 2), mixer=Mixer(beta=0.06, nmaxold=5, weight=100.0), occupations=FermiDirac(width=0.1), kpts={'density': 4.5}, txt='gs_output_{}.txt'.format(efield), h=0.20, external=ConstantElectricField(efield, [0, 0, 1])) a.set_calculator(calc) a.get_potential_energy() calc.write('gs_{}.gpw'.format(efield)) calc = GPAW('gs_{}.gpw'.format(efield), nbands=-100, fixdensity=True, symmetry='off', kpts={'path': 'XGX', 'npoints': 100}, convergence={'bands': 'CBM+1'}, txt='gs_output_{}.txt'.format(efield)) calc.get_potential_energy() bs = calc.band_structure() bs.plot(filename='bandstructure_{}.png'.format( efield), show=False, emax=calc.get_fermi_level()+1, emin=calc.get_fermi_level()-1) bs.write('bs_{}.json'.format( efield)) try: gap, p1, p2 = get_gap(calc) printit("{} {} {} {}".format(efield, gap, p1, p2), fname="gaps.dat") except: None
def do_gs_calc(fname): printit('running GS calculation') a = read(fname) calc = GPAW(mode='lcao', basis='dzp', xc='PBE', occupations=FermiDirac(width=0.01), kpts={ 'size': (1, 20, 1), 'gamma': True }, txt='gs_output.txt') a.set_calculator(calc) a.get_potential_energy() calc.write('gs_' + fname + '.gpw', mode='all') printit('GS calculation done')
def set_calculator(calc, e_km, v_knm=None, width=None): from gpaw.occupations import FermiDirac from ase.units import Hartree if width is None: width = calc.occupations.width * Hartree calc.wfs.bd.nbands *= 2 calc.wfs.nspins = 1 for kpt in calc.wfs.kpt_u: kpt.eps_n = e_km[kpt.k] / Hartree kpt.f_n = np.zeros_like(kpt.eps_n) kpt.weight /= 2 ef = calc.occupations.fermilevel calc.occupations = FermiDirac(width) calc.occupations.nvalence = calc.wfs.setups.nvalence - calc.density.charge calc.occupations.fermilevel = ef calc.occupations.calculate_occupation_numbers(calc.wfs) for kpt in calc.wfs.kpt_u: kpt.f_n *= 2 kpt.weight *= 2
def calculate(element, h, vacuum, xc, magmom): atom = Atoms([Atom(element, (0, 0, 0))]) if magmom > 0.0: mms = [magmom for i in range(len(atom))] atom.set_initial_magnetic_moments(mms) atom.center(vacuum=vacuum) mixer = MixerSum(beta=0.2) if element == 'O': mixer = MixerSum(nmaxold=1, weight=100) atom.set_positions(atom.get_positions() + [0.0, 0.0, 0.0001]) calc_atom = GPAW(h=h, xc=data[element][xc][2], occupations=FermiDirac(0.0, fixmagmom=True), mixer=mixer, nbands=-2, txt='%s.%s.txt' % (element, xc)) atom.set_calculator(calc_atom) mixer = Mixer(beta=0.2, weight=100) compound = molecule(element + '2') if compound == 'O2': mixer = MixerSum(beta=0.2) mms = [1.0 for i in range(len(compound))] compound.set_initial_magnetic_moments(mms) calc = GPAW(h=h, xc=data[element][xc][2], mixer=mixer, txt='%s2.%s.txt' % (element, xc)) compound.set_distance(0, 1, data[element]['R_AA_B3LYP']) compound.center(vacuum=vacuum) compound.set_calculator(calc) if data[element][xc][3] == 'hyb_gga': # only for hybrids e_atom = atom.get_potential_energy() e_compound = compound.get_potential_energy() calc_atom.set(xc=xc) calc.set(xc=xc) if 0: qn = QuasiNewton(compound) qn.attach( PickleTrajectory(element + '2' + '_' + xc + '.traj', 'w', compound).write) qn.run(fmax=0.02) e_atom = atom.get_potential_energy() e_compound = compound.get_potential_energy() dHf_0 = (e_compound - 2 * e_atom + data[element]['ZPE_AA_B3LYP'] + 2 * data[element]['dHf_0_A']) dHf_298 = (dHf_0 + data[element]['H_298_H_0_AA_B3LYP'] - 2 * data[element]['H_298_H_0_A']) * (mol / kcal) dist_compound = compound.get_distance(0, 1) de = dHf_298 - data[element][xc][1] E[element][xc] = de if rank == 0: print(xc, h, vacuum, dHf_298, data[element][xc][1], de, de / data[element][xc][1]) if element == 'H': equal(dHf_298, data[element][xc][1], 0.25, msg=xc + ': ') # kcal/mol elif element == 'O': equal(dHf_298, data[element][xc][1], 7.5, msg=xc + ': ') # kcal/mol else: equal(dHf_298, data[element][xc][1], 2.15, msg=xc + ': ') # kcal/mol equal(de, E_ref[element][xc], 0.06, msg=xc + ': ') # kcal/mol
def read(self, reader): """Read state from file.""" r = reader version = r['version'] assert version >= 0.3 self.xc = r['XCFunctional'] self.nbands = r.dimension('nbands') self.spinpol = (r.dimension('nspins') == 2) bzk_kc = r.get('BZKPoints', broadcast=True) if r.has_array('NBZKPoints'): self.kpts = r.get('NBZKPoints', broadcast=True) if r.has_array('MonkhorstPackOffset'): offset_c = r.get('MonkhorstPackOffset', broadcast=True) if offset_c.any(): self.kpts = monkhorst_pack(self.kpts) + offset_c else: self.kpts = bzk_kc if version < 4: self.symmetry = usesymm2symmetry(r['UseSymmetry']) else: self.symmetry = {'point_group': r['SymmetryOnSwitch'], 'symmorphic': r['SymmetrySymmorphicSwitch'], 'time_reversal': r['SymmetryTimeReversalSwitch'], 'tolerance': r['SymmetryToleranceCriterion']} try: self.basis = r['BasisSet'] except KeyError: pass if version >= 2: try: h = r['GridSpacing'] except KeyError: # CMR can't handle None! h = None if h is not None: self.h = Bohr * h if r.has_array('GridPoints'): self.gpts = r.get('GridPoints') else: if version >= 0.9: h = r['GridSpacing'] else: h = None gpts = ((r.dimension('ngptsx') + 1) // 2 * 2, (r.dimension('ngptsy') + 1) // 2 * 2, (r.dimension('ngptsz') + 1) // 2 * 2) if h is None: self.gpts = gpts else: self.h = Bohr * h self.lmax = r['MaximumAngularMomentum'] self.setups = r['SetupTypes'] self.fixdensity = r['FixDensity'] if version <= 0.4: # Old version: XXX print(('# Warning: Reading old version 0.3/0.4 restart files ' + 'will be disabled some day in the future!')) self.convergence['eigenstates'] = r['Tolerance'] else: nbtc = r['NumberOfBandsToConverge'] if not isinstance(nbtc, (int, str)): # The string 'all' was eval'ed to the all() function! nbtc = 'all' if version < 5: force_crit = None else: force_crit = r['ForcesConvergenceCriterion'] if force_crit is not None: force_crit *= (Hartree / Bohr) self.convergence = {'density': r['DensityConvergenceCriterion'], 'energy': r['EnergyConvergenceCriterion'] * Hartree, 'eigenstates': r['EigenstatesConvergenceCriterion'], 'bands': nbtc, 'forces': force_crit} if version < 1: # Volume per grid-point: dv = (abs(np.linalg.det(r.get('UnitCell'))) / (gpts[0] * gpts[1] * gpts[2])) self.convergence['eigenstates'] *= Hartree**2 * dv if version <= 0.6: mixer = 'Mixer' weight = r['MixMetric'] elif version <= 0.7: mixer = r['MixClass'] weight = r['MixWeight'] metric = r['MixMetric'] if metric is None: weight = 1.0 else: mixer = r['MixClass'] weight = r['MixWeight'] if mixer == 'Mixer': from gpaw.mixer import Mixer elif mixer == 'MixerSum': from gpaw.mixer import MixerSum as Mixer elif mixer == 'MixerSum2': from gpaw.mixer import MixerSum2 as Mixer elif mixer == 'MixerDif': from gpaw.mixer import MixerDif as Mixer elif mixer == 'DummyMixer': from gpaw.mixer import DummyMixer as Mixer else: Mixer = None if Mixer is None: self.mixer = None else: self.mixer = Mixer(r['MixBeta'], r['MixOld'], weight) if version == 0.3: # Old version: XXX print(('# Warning: Reading old version 0.3 restart files is ' + 'dangerous and will be disabled some day in the future!')) self.stencils = (2, 3) self.charge = 0.0 fixmom = False else: self.stencils = (r['KohnShamStencil'], r['InterpolationStencil']) if r['PoissonStencil'] == 999: self.poissonsolver = FFTPoissonSolver() else: self.poissonsolver = PoissonSolver(nn=r['PoissonStencil']) self.charge = r['Charge'] fixmom = r['FixMagneticMoment'] self.occupations = FermiDirac(r['FermiWidth'] * Hartree, fixmagmom=fixmom) try: self.mode = r['Mode'] except KeyError: self.mode = 'fd' if self.mode == 'pw': self.mode = PW(ecut=r['PlaneWaveCutoff'] * Hartree) if len(bzk_kc) == 1 and not bzk_kc[0].any(): # Gamma point only: if r['DataType'] == 'Complex': self.dtype = complex
atoms = Atoms('N2', positions=[(0, 0, 0), (0, 0, d_bond + d_disp)]) atoms.set_pbc(False) atoms.center(vacuum=6.0) cell_c = np.sum(atoms.get_cell()**2, axis=1)**0.5 N_c = 8 * np.round(cell_c / (0.2 * 8)) calc = GPAW(gpts=N_c, nbands=5, basis='dzp', # TODO xc='PBE' txt=name + '_gs.txt', parallel={'band': 1}) atoms.set_calculator(calc) # QuasiNewton relaxation before we increase the number of bands qn = BFGS(atoms, logfile=name + '_gs.log', trajectory=name + '_gs.traj') qn.run(0.01, steps=100) # Converge enough unoccupied bands for dSCF expansion calc.set(nbands=10, spinpol=True, occupations=FermiDirac(0.1), convergence={'bands': -2, 'eigenstates': 1.0e-9}) atoms.get_potential_energy() calc.write(name + '_gs.gpw', mode='all') del qn, calc, atoms time.sleep(10) while not os.path.isfile(name + '_gs.gpw'): print('Node %d waiting for %s...' % (world.rank, name + '_gs.gpw')) time.sleep(10) world.barrier() if not os.path.isfile(name + '_es.gpw'): # Resume ground state calculator and use as basis for excited state calc = GPAW(name + '_gs.gpw', txt=name + '_es.txt',
L = 7.00 basis = BasisMaker('Na').generate(1, 1, energysplit=0.3) atoms = Atoms('Na9', pbc=(0, 0, 1), cell=[L, L, 9 * a]) atoms.positions[:9, 2] = [i * a for i in range(9)] atoms.positions[:, :2] = L / 2. atoms.center() pl_atoms1 = range(4) pl_atoms2 = range(5, 9) pl_cell1 = (L, L, 4 * a) pl_cell2 = pl_cell1 t = Transport(h=0.3, xc='LDA', basis={'Na': basis}, kpts=(1, 1, 1), occupations=FermiDirac(0.1), mode='lcao', poissonsolver=PoissonSolver(nn=2, relax='GS'), txt='Na_lcao.txt', mixer=Mixer(0.1, 5, weight=100.0), pl_atoms=[pl_atoms1, pl_atoms2], pl_cells=[pl_cell1, pl_cell2], pl_kpts=(1, 1, 5), edge_atoms=[[0, 3], [0, 8]], mol_atoms=[4], guess_steps=1, fixed_boundary=False) atoms.set_calculator(t) t.calculate_iv(0.5, 2)
from gpaw.elf import ELF # Graphene nanoribbon ribbon = graphene_nanoribbon(5, 6, type='armchair', saturated=True, vacuum=3.5) # Gold adsorbate pos = (ribbon[35].position + ribbon[60].position) / 2.0 pos[1] += 2.2 adsorbate = Atoms('Au', (pos, )) ribbon += adsorbate ribbon.center(axis=1, vacuum=3.5) txt = 'output_p_{}.txt'.format(size) ribbon.calc = GPAW( h=0.22, xc='PBE', txt=txt, occupations=FermiDirac(0.2), eigensolver=RMMDIIS(), ) ribbon.get_potential_energy() # Calculate electron localization function elf = ELF(ribbon.calc) elf.update() elf_g = elf.get_electronic_localization_function(gridrefinement=2) if rank == 0: write('elf_ribbon.cube', ribbon, data=elf_g)
yukawa_gamma=0.83, gpernode=149) h = 0.35 be = Cluster(Atoms('Be', positions=[[0, 0, 0]])) be.minimal_box(3.0, h=h) c = {'energy': 0.05, 'eigenstates': 0.05, 'density': 0.05} IP = 8.79 xc = HybridXC('LCY-PBE', omega=0.83) fname = 'Be_rsf.gpw' calc = GPAW(txt='Be.txt', xc=xc, convergence=c, eigensolver=RMMDIIS(), h=h, occupations=FermiDirac(width=0.0), spinpol=False) be.set_calculator(calc) # energy = na2.get_potential_energy() # calc.set(xc=xc) energy_083 = be.get_potential_energy() (eps_homo, eps_lumo) = calc.get_homo_lumo() equal(eps_homo, -IP, 0.15) xc2 = 'LCY-PBE' energy_075 = calc.get_xc_difference(HybridXC(xc2)) equal(energy_083 - energy_075, 21.13, 0.2, 'wrong energy difference') calc.write(fname) calc2 = GPAW(fname) func = calc2.get_xc_functional() assert func['name'] == 'LCY-PBE', 'wrong name for functional' assert func['omega'] == 0.83, 'wrong value for RSF omega'
def calculate(element, h, vacuum, xc, magmom): atom = Atoms([Atom(element, (0, 0, 0))]) if magmom > 0.0: mms = [magmom for i in range(len(atom))] atom.set_initial_magnetic_moments(mms) atom.center(vacuum=vacuum) mixer = MixerSum(beta=0.4) if element == 'O': mixer = MixerSum(0.4, nmaxold=1, weight=100) atom.set_positions(atom.get_positions() + [0.0, 0.0, 0.0001]) calc_atom = GPAW(h=h, xc=_xc(data[element][xc][2]), experimental={'niter_fixdensity': 2}, eigensolver='rmm-diis', occupations=FermiDirac(0.0, fixmagmom=True), mixer=mixer, parallel=dict(augment_grids=True), nbands=-2, txt='%s.%s.txt' % (element, xc)) atom.set_calculator(calc_atom) mixer = Mixer(beta=0.4, weight=100) compound = molecule(element + '2') if compound == 'O2': mixer = MixerSum(beta=0.4) mms = [1.0 for i in range(len(compound))] compound.set_initial_magnetic_moments(mms) calc = GPAW(h=h, xc=_xc(data[element][xc][2]), experimental={'niter_fixdensity': 2}, eigensolver='rmm-diis', mixer=mixer, parallel=dict(augment_grids=True), txt='%s2.%s.txt' % (element, xc)) compound.set_distance(0, 1, data[element]['R_AA_B3LYP']) compound.center(vacuum=vacuum) compound.set_calculator(calc) if data[element][xc][3] == 'hyb_gga': # only for hybrids e_atom = atom.get_potential_energy() e_compound = compound.get_potential_energy() calc_atom.set(xc=_xc(xc)) calc.set(xc=_xc(xc)) e_atom = atom.get_potential_energy() e_compound = compound.get_potential_energy() dHf_0 = (e_compound - 2 * e_atom + data[element]['ZPE_AA_B3LYP'] + 2 * data[element]['dHf_0_A']) dHf_298 = (dHf_0 + data[element]['H_298_H_0_AA_B3LYP'] - 2 * data[element]['H_298_H_0_A']) * (mol / kcal) de = dHf_298 - data[element][xc][1] E[element][xc] = de if rank == 0: print((xc, h, vacuum, dHf_298, data[element][xc][1], de, de / data[element][xc][1])) if element == 'H': equal(dHf_298, data[element][xc][1], 0.25, msg=xc + ': ') # kcal/mol elif element == 'O': equal(dHf_298, data[element][xc][1], 7.5, msg=xc + ': ') # kcal/mol else: equal(dHf_298, data[element][xc][1], 2.15, msg=xc + ': ') # kcal/mol equal(de, E_ref[element][xc], 0.06, msg=xc + ': ') # kcal/mol
def dscf_collapse_orbitals(paw, nbands_max='occupied', f_tol=1e-4, verify_density=True, nt_tol=1e-5, D_tol=1e-3): bd, gd, kd = paw.wfs.bd, paw.wfs.gd, paw.wfs.kd if bd.comm.size != 1: raise NotImplementedError('Undefined action for band parallelization.') f_skn = np.empty((kd.nspins, kd.nibzkpts, bd.nbands), dtype=float) for s, f_kn in enumerate(f_skn): for k, f_n in enumerate(f_kn): kpt_rank, myu = kd.get_rank_and_index(s, k) if kd.comm.rank == kpt_rank: f_n[:] = paw.wfs.kpt_u[myu].f_n kd.comm.broadcast(f_n, kpt_rank) # Find smallest band index, from which all bands have negligeble occupations n0 = np.argmax(f_skn<f_tol, axis=-1).max() assert np.all(f_skn[...,n0:]<f_tol) # XXX use f_skn[...,n0:].sum()<f_tol # Read the number of Delta-SCF orbitals norbitals = paw.occupations.norbitals if debug: mpi_debug('n0=%d, norbitals=%d, bd:%d, gd:%d, kd:%d' % (n0,norbitals,bd.comm.size,gd.comm.size,kd.comm.size)) if nbands_max < 0: nbands_max = n0 + norbitals - nbands_max elif nbands_max == 'occupied': nbands_max = n0 + norbitals assert nbands_max >= n0 + norbitals, 'Too few bands to include occupations.' ncut = nbands_max-norbitals if debug: mpi_debug('nbands_max=%d' % nbands_max) paw.wfs.initialize_wave_functions_from_restart_file() # hurts memmory for kpt in paw.wfs.kpt_u: mol = kpt.P_ani.keys() # XXX stupid (f_o, eps_o, wf_oG, P_aoi,) = dscf_reconstruct_orbitals_k_point(paw, norbitals, mol, kpt) assert np.abs(f_o-1).max() < 1e-9, 'Orbitals must be properly normalized.' f_o = kpt.ne_o # actual ocupatiion numbers # Crop band-data and inject data for Delta-SCF orbitals kpt.f_n = np.hstack((kpt.f_n[:n0], f_o, kpt.f_n[n0:ncut])) kpt.eps_n = np.hstack((kpt.eps_n[:n0], eps_o, kpt.eps_n[n0:ncut])) for a, P_ni in kpt.P_ani.items(): kpt.P_ani[a] = np.vstack((P_ni[:n0], P_aoi[a], P_ni[n0:ncut])) old_psit_nG = kpt.psit_nG kpt.psit_nG = gd.empty(nbands_max, dtype=old_psit_nG.dtype) if isinstance(old_psit_nG, FileReference): assert old_psit_nG.shape[-3:] == wf_oG.shape[-3:], 'Shape mismatch!' # Read band-by-band to save memory as full psit_nG may be large for n,psit_G in enumerate(kpt.psit_nG): if n < n0: full_psit_G = old_psit_nG[n] elif n in range(n0,n0+norbitals): full_psit_G = wf_oG[n-n0] else: full_psit_G = old_psit_nG[n-norbitals] gd.distribute(full_psit_G, psit_G) else: kpt.psit_nG[:n0] = old_psit_nG[:n0] kpt.psit_nG[n0:n0+norbitals] = wf_oG kpt.psit_nG[n0+norbitals:] = old_psit_nG[n0:ncut] del kpt.ne_o, kpt.c_on, old_psit_nG del paw.occupations.norbitals # Change various parameters related to new number of bands paw.wfs.bd = BandDescriptor(nbands_max, bd.comm, bd.strided) if paw.wfs.eigensolver: paw.wfs.eigensolver.initialized = False del bd # Crop convergence criteria nbands_converge to new number of bands par = paw.input_parameters if 'convergence' in par: cc = par['convergence'] if 'bands' in cc: cc['bands'] = min(nbands_max, cc['bands']) # Replace occupations class with a fixed variant (gets the magmom right) XXX?!? fermilevel, magmom = paw.occupations.fermilevel, paw.occupations.magmom paw.occupations = FermiDirac(paw.occupations.width * Hartree, paw.occupations.fixmagmom) paw.occupations.fermilevel = fermilevel paw.occupations.magmom = magmom del fermilevel, magmom # For good measure, self-consistency information should be destroyed paw.scf.reset() if verify_density: paw.initialize_positions() # Re-calculate pseudo density and watch for changes old_nt_sG = paw.density.nt_sG.copy() paw.density.calculate_pseudo_density(paw.wfs) if debug: mpi_debug('delta-density: %g' % np.abs(old_nt_sG-paw.density.nt_sG).max()) assert np.abs(paw.density.nt_sG-old_nt_sG).max() < nt_tol, 'Density changed!' # Re-calculate atomic density matrices and watch for changes old_D_asp = {} for a,D_sp in paw.density.D_asp.items(): old_D_asp[a] = D_sp.copy() paw.wfs.calculate_atomic_density_matrices(paw.density.D_asp) if debug: mpi_debug('delta-D_asp: %g' % max([0]+[np.abs(D_sp-old_D_asp[a]).max() for a,D_sp in paw.density.D_asp.items()])) for a,D_sp in paw.density.D_asp.items(): assert np.abs(D_sp-old_D_asp[a]).max() < D_tol, 'Atom %d changed!' % a
# IP for CO using LCY-PBE with gamma=0.81 after # dx.doi.org/10.1021/acs.jctc.8b00238 IP = 14.31 if setup_paths[0] != '.': setup_paths.insert(0, '.') for atom in ['C', 'O']: gen(atom, xcname='PBE', scalarrel=True, exx=True, yukawa_gamma=0.81) h = 0.30 co = Atoms('CO', positions=[(0, 0, 0), (0, 0, 1.15)]) co.minimal_box(5) # c = {'energy': 0.005, 'eigenstates': 1e-4} # Usable values c = {'energy': 0.1, 'eigenstates': 3, 'density': 3} # Values for test calc = GPAW(txt='CO.txt', xc='LCY-PBE:omega=0.81', convergence=c, eigensolver=RMMDIIS(), h=h, poissonsolver=PoissonSolver(use_charge_center=True), occupations=FermiDirac(width=0.0), spinpol=False) co.set_calculator(calc) co.get_potential_energy() (eps_homo, eps_lumo) = calc.get_homo_lumo() equal(eps_homo, -IP, 0.15)
def __init__(self, width, *args, **kwargs): raise NotImplementedError FermiDirac.__init__(self, width, fermi) self.set_fermi_level(epsF) self.niter = 0
def wrap_old_gpw_reader(filename): warnings.warn('You are reading an old-style gpw-file. Please check ' 'the results carefully!') r = Reader(filename) data = { 'version': -1, 'gpaw_version': '1.0', 'ha': Ha, 'bohr': Bohr, 'scf.': { 'converged': True }, 'atoms.': {}, 'wave_functions.': {} } class DictBackend: def write(self, **kwargs): data['atoms.'].update(kwargs) write_atoms(DictBackend(), read_atoms(r)) e_total_extrapolated = r.get('PotentialEnergy').item() * Ha magmom_a = r.get('MagneticMoments') data['results.'] = { 'energy': e_total_extrapolated, 'magmoms': magmom_a, 'magmom': magmom_a.sum() } if r.has_array('CartesianForces'): data['results.']['forces'] = r.get('CartesianForces') * Ha / Bohr p = data['parameters.'] = {} p['xc'] = r['XCFunctional'] p['nbands'] = r.dimension('nbands') p['spinpol'] = (r.dimension('nspins') == 2) bzk_kc = r.get('BZKPoints', broadcast=True) if r.has_array('NBZKPoints'): p['kpts'] = r.get('NBZKPoints', broadcast=True) if r.has_array('MonkhorstPackOffset'): offset_c = r.get('MonkhorstPackOffset', broadcast=True) if offset_c.any(): p['kpts'] = monkhorst_pack(p['kpts']) + offset_c else: p['kpts'] = bzk_kc if r['version'] < 4: usesymm = r['UseSymmetry'] if usesymm is None: p['symmetry'] = {'time_reversal': False, 'point_group': False} elif usesymm: p['symmetry'] = {'time_reversal': True, 'point_group': True} else: p['symmetry'] = {'time_reversal': True, 'point_group': False} else: p['symmetry'] = { 'point_group': r['SymmetryOnSwitch'], 'symmorphic': r['SymmetrySymmorphicSwitch'], 'time_reversal': r['SymmetryTimeReversalSwitch'], 'tolerance': r['SymmetryToleranceCriterion'] } p['basis'] = r['BasisSet'] try: h = r['GridSpacing'] except KeyError: # CMR can't handle None! h = None if h is not None: p['h'] = Bohr * h if r.has_array('GridPoints'): p['gpts'] = r.get('GridPoints') p['lmax'] = r['MaximumAngularMomentum'] p['setups'] = r['SetupTypes'] p['fixdensity'] = r['FixDensity'] nbtc = r['NumberOfBandsToConverge'] if not isinstance(nbtc, (int, str)): # The string 'all' was eval'ed to the all() function! nbtc = 'all' p['convergence'] = { 'density': r['DensityConvergenceCriterion'], 'energy': r['EnergyConvergenceCriterion'] * Ha, 'eigenstates': r['EigenstatesConvergenceCriterion'], 'bands': nbtc } mixer = r['MixClass'] weight = r['MixWeight'] for key in ['basis', 'setups']: dct = p[key] if isinstance(dct, dict) and None in dct: dct['default'] = dct.pop(None) if mixer == 'Mixer': from gpaw.mixer import Mixer elif mixer == 'MixerSum': from gpaw.mixer import MixerSum as Mixer elif mixer == 'MixerSum2': from gpaw.mixer import MixerSum2 as Mixer elif mixer == 'MixerDif': from gpaw.mixer import MixerDif as Mixer elif mixer == 'DummyMixer': from gpaw.mixer import DummyMixer as Mixer else: Mixer = None if Mixer is None: p['mixer'] = None else: p['mixer'] = Mixer(r['MixBeta'], r['MixOld'], weight) p['stencils'] = (r['KohnShamStencil'], r['InterpolationStencil']) vt_sG = r.get('PseudoPotential') * Ha ps = r['PoissonStencil'] if isinstance(ps, int) or ps == 'M': poisson = {'name': 'fd'} poisson['nn'] = ps if data['atoms.']['pbc'] == [1, 1, 0]: v1, v2 = vt_sG[0, :, :, [0, -1]].mean(axis=(1, 2)) if abs(v1 - v2) > 0.01: warnings.warn('I am guessing that this calculation was done ' 'with a dipole-layer correction?') poisson['dipolelayer'] = 'xy' p['poissonsolver'] = poisson p['charge'] = r['Charge'] fixmom = r['FixMagneticMoment'] p['occupations'] = FermiDirac(r['FermiWidth'] * Ha, fixmagmom=fixmom) p['mode'] = r['Mode'] if p['mode'] == 'pw': p['mode'] = PW(ecut=r['PlaneWaveCutoff'] * Ha) if len(bzk_kc) == 1 and not bzk_kc[0].any(): # Gamma point only: if r['DataType'] == 'Complex': p['dtype'] = complex data['occupations.'] = { 'fermilevel': r['FermiLevel'] * Ha, 'split': r.parameters.get('FermiSplit', 0) * Ha, 'h**o': np.nan, 'lumo': np.nan } data['density.'] = { 'density': r.get('PseudoElectronDensity') * Bohr**-3, 'atomic_density_matrices': r.get('AtomicDensityMatrices') } data['hamiltonian.'] = { 'e_coulomb': r['Epot'] * Ha, 'e_entropy': -r['S'] * Ha, 'e_external': r['Eext'] * Ha, 'e_kinetic': r['Ekin'] * Ha, 'e_total_extrapolated': e_total_extrapolated, 'e_xc': r['Exc'] * Ha, 'e_zero': r['Ebar'] * Ha, 'potential': vt_sG, 'atomic_hamiltonian_matrices': r.get('NonLocalPartOfHamiltonian') * Ha } data['hamiltonian.']['e_total_free'] = (sum( data['hamiltonian.'][e] for e in [ 'e_coulomb', 'e_entropy', 'e_external', 'e_kinetic', 'e_xc', 'e_zero' ])) if r.has_array('GLLBPseudoResponsePotential'): data['hamiltonian.']['xc.'] = { 'gllb_pseudo_response_potential': r.get('GLLBPseudoResponsePotential') * Ha, 'gllb_dxc_pseudo_response_potential': r.get('GLLBDxcPseudoResponsePotential') * Ha / Bohr, 'gllb_atomic_density_matrices': r.get('GLLBAtomicDensityMatrices'), 'gllb_atomic_response_matrices': r.get('GLLBAtomicResponseMatrices'), 'gllb_dxc_atomic_density_matrices': r.get('GLLBDxcAtomicDensityMatrices'), 'gllb_dxc_atomic_response_matrices': r.get('GLLBDxcAtomicResponseMatrices') } special = [('eigenvalues', 'Eigenvalues'), ('occupations', 'OccupationNumbers'), ('projections', 'Projections')] if r['Mode'] == 'pw': special.append(('coefficients', 'PseudoWaveFunctions')) try: data['wave_functions.']['indices'] = r.get('PlaneWaveIndices') except KeyError: pass elif r['Mode'] == 'fd': special.append(('values', 'PseudoWaveFunctions')) else: special.append(('coefficients', 'WaveFunctionCoefficients')) for name, old in special: try: fd, shape, size, dtype = r.get_file_object(old, ()) except KeyError: continue offset = fd data['wave_functions.'][name + '.'] = { 'ndarray': (shape, dtype.name, offset) } new = ulm.Reader(devnull, data=data, little_endian=r.byteswap ^ np.little_endian) for ref in new._data['wave_functions']._data.values(): try: ref.fd = ref.offset except AttributeError: continue ref.offset = 0 return new
xc = 'PBE' fit = (5, 0.02) w = 0.06 ecut = 1200 kd = 8.0 tag = 'dcdft_%s_gpaw_pw' % xc.lower() task = Task( calcfactory=Factory( xc=xc, mode=PW(ecut), occupations=FermiDirac(w), maxiter=250, kptdensity=kd, ), tag=tag, fit=fit, use_lock_files=True, ) if __name__ == '__main__': if element is None: keys = set(parameters.keys()).intersection(set(task.collection.names)) for s in elements_slow: keys.remove(s) # those are slow, run separately else: keys = [element]
def read(self, reader): """Read state from file.""" if isinstance(reader, str): reader = gpaw.io.open(reader, 'r') r = reader version = r['version'] assert version >= 0.3 self.xc = r['XCFunctional'] self.nbands = r.dimension('nbands') self.spinpol = (r.dimension('nspins') == 2) if r.has_array('NBZKPoints'): self.kpts = r.get('NBZKPoints') else: self.kpts = r.get('BZKPoints') self.usesymm = r['UseSymmetry'] try: self.basis = r['BasisSet'] except KeyError: pass self.gpts = ((r.dimension('ngptsx') + 1) // 2 * 2, (r.dimension('ngptsy') + 1) // 2 * 2, (r.dimension('ngptsz') + 1) // 2 * 2) self.lmax = r['MaximumAngularMomentum'] self.setups = r['SetupTypes'] self.fixdensity = r['FixDensity'] if version <= 0.4: # Old version: XXX print('# Warning: Reading old version 0.3/0.4 restart files ' + 'will be disabled some day in the future!') self.convergence['eigenstates'] = r['Tolerance'] else: self.convergence = { 'density': r['DensityConvergenceCriterion'], 'energy': r['EnergyConvergenceCriterion'] * Hartree, 'eigenstates': r['EigenstatesConvergenceCriterion'], 'bands': r['NumberOfBandsToConverge'] } if version <= 0.6: mixer = 'Mixer' weight = r['MixMetric'] elif version <= 0.7: mixer = r['MixClass'] weight = r['MixWeight'] metric = r['MixMetric'] if metric is None: weight = 1.0 else: mixer = r['MixClass'] weight = r['MixWeight'] if mixer == 'Mixer': from gpaw.mixer import Mixer elif mixer == 'MixerSum': from gpaw.mixer import MixerSum as Mixer elif mixer == 'MixerSum2': from gpaw.mixer import MixerSum2 as Mixer elif mixer == 'MixerDif': from gpaw.mixer import MixerDif as Mixer elif mixer == 'DummyMixer': from gpaw.mixer import DummyMixer as Mixer else: Mixer = None if Mixer is None: self.mixer = None else: self.mixer = Mixer(r['MixBeta'], r['MixOld'], weight) if version == 0.3: # Old version: XXX print('# Warning: Reading old version 0.3 restart files is ' + 'dangerous and will be disabled some day in the future!') self.stencils = (2, 3) self.charge = 0.0 fixmom = False else: self.stencils = (r['KohnShamStencil'], r['InterpolationStencil']) if r['PoissonStencil'] == 999: self.poissonsolver = FFTPoissonSolver() else: self.poissonsolver = PoissonSolver(nn=r['PoissonStencil']) self.charge = r['Charge'] fixmom = r['FixMagneticMoment'] self.occupations = FermiDirac(r['FermiWidth'] * Hartree, fixmagmom=fixmom) try: self.mode = r['Mode'] except KeyError: self.mode = 'fd' try: dtype = r['DataType'] if dtype == 'Float': self.dtype = float else: self.dtype = complex except KeyError: self.dtype = float
k = KPoint() def f(occ, x): k.eps_n[0] = x n, dnde, x, S = occ.distribution(k, 0.0) return n, dnde, S def test(occ): print(occ) for e in [-0.3 / Hartree, 0, 0.1 / Hartree, 1.2 / Hartree]: n0, d0, S0 = f(occ, e) x = 0.000001 np, dp, Sp = f(occ, e + x) nm, dm, Sm = f(occ, e - x) d = -(np - nm) / (2 * x) dS = Sm - Sp dn = np - nm print(d - d0, dS - e * dn) assert abs(d - d0) < 3e-5 assert abs(dS - e * dn) < 1e-13 for w in [0.1, 0.5]: test(FermiDirac(w)) for n in range(4): test(MethfesselPaxton(w, n))
print("#" * 60) print("GPAW benchmark: Carbon Fullerenes on a Lead Surface") print(" grid spacing: h=%f" % h) print(" Brillouin-zone sampling: kpts=" + str(kpts)) print(" MPI tasks: %d" % size) print(" using CUDA (GPGPU): " + str(use_cuda)) print(" using pyMIC (KNC) : " + str(use_mic)) print(" using CPU (or KNL): " + str(use_cpu)) print("#" * 60) print("") # setup parameters args = { 'h': h, 'nbands': -180, 'occupations': FermiDirac(0.2), 'kpts': kpts, 'xc': 'PBE', 'mixer': Mixer(0.1, 5, 100), 'eigensolver': 'rmm-diis', 'maxiter': maxiter, 'xc_thread': False, 'txt': txt } if use_cuda: args['gpu'] = {'cuda': True, 'hybrid_blas': False} try: args['parallel'] = parallel except: pass
h = 0.3 # No energies - simpley convergence test, esp. for 3d TM # for atom in ['F', 'Cl', 'Br', 'Cu', 'Ag']: for atom in ['Ti']: gen(atom, xcname='PBE', scalarrel=False, exx=True) work_atom = Cluster(Atoms(atom, [(0, 0, 0)])) work_atom.minimal_box(4, h=h) work_atom.translate([0.01, 0.02, 0.03]) work_atom.set_initial_magnetic_moments([2.0]) calculator = GPAW(convergence={ 'energy': 0.01, 'eigenstates': 3, 'density': 3 }, eigensolver=RMMDIIS(), poissonsolver=PoissonSolver(use_charge_center=True), occupations=FermiDirac(width=0.0, fixmagmom=True), h=h, maxiter=35) # Up to 24 are needed by now calculator.set(xc=HybridXC('PBE0')) calculator.set(txt=atom + '-PBE0.txt') work_atom.set_calculator(calculator) try: work_atom.get_potential_energy() except KohnShamConvergenceError: pass assert calculator.scf.converged, 'Calculation not converged'