def __init__(self, gd, setups, spos_ac, fft=False): assert gd.comm.size == 1 self.rhot1_G = gd.empty() self.rhot2_G = gd.empty() self.pot_G = gd.empty() self.dv = gd.dv if fft: self.poisson = FFTPoissonSolver() else: self.poisson = PoissonSolver(name='fd', nn=3) self.poisson.set_grid_descriptor(gd) self.setups = setups # Set coarse ghat self.Ghat = LFC(gd, [setup.ghat_l for setup in setups], integral=sqrt(4 * pi)) self.Ghat.set_positions(spos_ac)
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
c.set_positions([(0, 0, 0), (0.5, 0.5, 0.5)]) c.add(a) I0 = gd.integrate(a) a -= gd.integrate(a) / L**3 I = gd.integrate(a) b = gd.zeros() p.solve(b, a, charge=0) #, eps=1e-20) return gd.collect(b, broadcast=1) b1 = f(8, PoissonSolver(nn=1, relax='J')) b2 = f(8, PoissonSolver(nn=1, relax='GS')) err1 = abs(b1[0, 0, 0] - b1[8, 8, 8]) err2 = abs(b2[0, 0, 0] - b2[8, 8, 8]) print err1 print err2 assert err1 < 6e-16 assert err2 < 3e-6 # XXX Shouldn't this be better? from gpaw.mpi import size if size == 1: b3 = f(8, FFTPoissonSolver()) err3 = abs(b3[0, 0, 0] - b3[8, 8, 8]) print err3 assert err3 < 6e-16
def __init__(self, calc, gamma=True, symmetry=False, e_ph=False, communicator=serial_comm): """Inititialize class with a list of atoms. The atoms object must contain a converged ground-state calculation. The set of q-vectors in which the dynamical matrix will be calculated is determined from the ``symmetry`` kwarg. For now, only time-reversal symmetry is used to generate the irrecducible BZ. Add a little note on parallelization strategy here. Parameters ---------- calc: str or Calculator Calculator containing a ground-state calculation. gamma: bool Gamma-point calculation with respect to the q-vector of the dynamical matrix. When ``False``, the Monkhorst-Pack grid from the ground-state calculation is used. symmetry: bool Use symmetries to reduce the q-vectors of the dynamcial matrix (None, False or True). The different options are equivalent to the old style options in a ground-state calculation (see usesymm). e_ph: bool Save the derivative of the effective potential. communicator: Communicator Communicator for parallelization over k-points and real-space domain. """ # XXX assert symmetry in [None, False], "Spatial symmetries not allowed yet" if isinstance(calc, str): self.calc = GPAW(calc, communicator=serial_comm, txt=None) else: self.calc = calc cell_cv = self.calc.atoms.get_cell() setups = self.calc.wfs.setups # XXX - no clue how to get magmom - ignore it for the moment # m_av = magmom_av.round(decimals=3) # round off # id_a = zip(setups.id_a, *m_av.T) id_a = setups.id_a if symmetry is None: self.symmetry = Symmetry(id_a, cell_cv, point_group=False, time_reversal=False) else: self.symmetry = Symmetry(id_a, cell_cv, point_group=False, time_reversal=True) # Make sure localized functions are initialized self.calc.set_positions() # Note that this under some circumstances (e.g. when called twice) # allocates a new array for the P_ani coefficients !! # Store useful objects self.atoms = self.calc.get_atoms() # Get rid of ``calc`` attribute self.atoms.calc = None # Boundary conditions pbc_c = self.calc.atoms.get_pbc() if not pbc_c.any(): self.gamma = True self.dtype = float kpts = None # Multigrid Poisson solver poisson_solver = PoissonSolver('fd') else: if gamma: self.gamma = True self.dtype = float kpts = None else: self.gamma = False self.dtype = complex # Get k-points from ground-state calculation kpts = self.calc.input_parameters.kpts # FFT Poisson solver poisson_solver = FFTPoissonSolver(dtype=self.dtype) # K-point descriptor for the q-vectors of the dynamical matrix # Note, no explicit parallelization here. self.kd = KPointDescriptor(kpts, 1) self.kd.set_symmetry(self.atoms, self.symmetry) self.kd.set_communicator(serial_comm) # Number of occupied bands nvalence = self.calc.wfs.nvalence nbands = nvalence // 2 + nvalence % 2 assert nbands <= self.calc.wfs.bd.nbands # Extract other useful objects # Ground-state k-point descriptor - used for the k-points in the # ResponseCalculator # XXX replace communicators when ready to parallelize kd_gs = self.calc.wfs.kd gd = self.calc.density.gd kpt_u = self.calc.wfs.kpt_u setups = self.calc.wfs.setups dtype_gs = self.calc.wfs.dtype # WaveFunctions wfs = WaveFunctions(nbands, kpt_u, setups, kd_gs, gd, dtype=dtype_gs) # Linear response calculator self.response_calc = ResponseCalculator(self.calc, wfs, dtype=self.dtype) # Phonon perturbation self.perturbation = PhononPerturbation(self.calc, self.kd, poisson_solver, dtype=self.dtype) # Dynamical matrix self.dyn = DynamicalMatrix(self.atoms, self.kd, dtype=self.dtype) # Electron-phonon couplings if e_ph: self.e_ph = ElectronPhononCoupling(self.atoms, gd, self.kd, dtype=self.dtype) else: self.e_ph = None # Initialization flag self.initialized = False # Parallel communicator for parallelization over kpts and domain self.comm = communicator
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