def __init__(self, gd, bd, block_comm, dtype, nao, timer=nulltimer): KohnShamLayouts.__init__(self, gd, bd, block_comm, dtype, timer) self.mMdescriptor = MatrixDescriptor(nao, nao) self.nMdescriptor = MatrixDescriptor(bd.mynbands, nao) self.Mstart = 0 self.Mstop = nao self.Mmax = nao self.mynao = nao self.nao = nao self.orbital_comm = bd.comm
def __init__(self, blacsgrid, M, N, mb, nb, rsrc=0, csrc=0): assert M > 0 assert N > 0 assert 1 <= mb assert 1 <= nb if mb > M: mb = M if nb > N: nb = N assert 0 <= rsrc < blacsgrid.nprow assert 0 <= csrc < blacsgrid.npcol self.blacsgrid = blacsgrid self.M = M # global size 1 self.N = N # global size 2 self.mb = mb # block cyclic distr dim 1 self.nb = nb # and 2. How many rows or columns are on this processor # more info: # http://www.netlib.org/scalapack/slug/node75.html self.rsrc = rsrc self.csrc = csrc if blacsgrid.is_active(): locN, locM = _gpaw.get_blacs_local_shape(self.blacsgrid.context, self.N, self.M, self.nb, self.mb, self.csrc, self.rsrc) # max 1 is nonsensical, but appears # to be required by PBLAS self.lld = max(1, locN) else: # ScaLAPACK has no requirements as to what these values on an # inactive blacsgrid should be. This seemed reasonable to me # at the time. locN, locM = 0, 0 # This applies only to empty matrices. Some functions will # complain about lld<1, so lld=1 will make those happy. self.lld = 1 # locM, locN is not allowed to be negative. This will cause the # redistributor to fail. This could happen on active blacsgrid # which does not contain any piece of the distribute matrix. # This is why there is a final check on the value of locM, locN. MatrixDescriptor.__init__(self, max(0, locM), max(0, locN)) # This is the definition of inactive descriptor; can occur # on an active or inactive blacs grid. self.active = locM > 0 and locN > 0 self.bshape = (self.mb, self.nb) # Shape of one block self.gshape = (M, N) # Global shape of array
def __init__(self, blacsgrid, M, N, mb, nb, rsrc, csrc): assert M > 0 assert N > 0 assert 1 <= mb assert 1 <= nb if mb > M: mb = M if nb > N: nb = N assert 0 <= rsrc < blacsgrid.nprow assert 0 <= csrc < blacsgrid.npcol self.blacsgrid = blacsgrid self.M = M # global size 1 self.N = N # global size 2 self.mb = mb # block cyclic distr dim 1 self.nb = nb # and 2. How many rows or columns are on this processor # more info: # http://www.netlib.org/scalapack/slug/node75.html self.rsrc = rsrc self.csrc = csrc if blacsgrid.is_active(): locN, locM = _gpaw.get_blacs_local_shape(self.blacsgrid.context, self.N, self.M, self.nb, self.mb, self.csrc, self.rsrc) self.lld = max(1, locN) # max 1 is nonsensical, but appears # to be required by PBLAS else: # ScaLAPACK has no requirements as to what these values on an # inactive blacsgrid should be. This seemed reasonable to me # at the time. locN, locM = 0, 0 self.lld = 0 # locM, locN is not allowed to be negative. This will cause the # redistributor to fail. This could happen on active blacsgrid # which does not contain any piece of the distribute matrix. # This is why there is a final check on the value of locM, locN. MatrixDescriptor.__init__(self, max(0, locM), max(0, locN)) # This is the definition of inactive descriptor; can occur # on an active or inactive blacs grid. self.active = locM > 0 and locN > 0 self.bshape = (self.mb, self.nb) # Shape of one block self.gshape = (M, N) # Global shape of array
def __init__(self, gd, bd, dtype, nao, timer=nulltimer): KohnShamLayouts.__init__(self, gd, bd, dtype, timer) self.mMdescriptor = MatrixDescriptor(nao, nao) self.nMdescriptor = MatrixDescriptor(bd.mynbands, nao) self.Mstart = 0 self.Mstop = nao self.Mmax = nao self.mynao = nao self.nao = nao # a problem with forces when # domain-decomposition = (1, 1, 1) # bd.comm.size > 1 # kpt.comm.size > 1 # Uncomment line 145 in gpaw/test/parallel/lcao_parallel.py self.orbital_comm = serial_comm
def iterate_one_k_point(self, ham, wfs, kpt): """Setup H and S matries and diagonalize for the kpoint""" self.timer.start('DirectPW') H_GG, S_GG = wfs.hs(ham, kpt.q, kpt.s) npw = len(H_GG) eps_n = np.empty(npw) md = MatrixDescriptor(npw, npw) psit_nG = md.empty(dtype=complex) md.general_diagonalize_dc(H_GG, S_GG, psit_nG, eps_n, iu=wfs.bd.nbands) kpt.eps_n[:] = eps_n[:wfs.bd.nbands] wfs.pt.integrate(kpt.psit_nG, kpt.P_ani, kpt.q) self.timer.stop('DirectPW') error = 0.0 return error
def diagonalize_full_hamiltonian(self, ham, atoms, occupations, txt, nbands=None, scalapack=None, expert=False): assert self.dtype == complex if nbands is None: nbands = self.pd.ngmin // self.bd.comm.size * self.bd.comm.size else: assert nbands <= self.pd.ngmin if expert: iu = nbands else: iu = None self.bd = bd = BandDescriptor(nbands, self.bd.comm) p = functools.partial(print, file=txt) p('Diagonalizing full Hamiltonian ({0} lowest bands)'.format(nbands)) p('Matrix size (min, max): {0}, {1}'.format(self.pd.ngmin, self.pd.ngmax)) mem = 3 * self.pd.ngmax**2 * 16 / bd.comm.size / 1024**2 p('Approximate memory usage per core: {0:.3f} MB'.format(mem)) if bd.comm.size > 1: if isinstance(scalapack, (list, tuple)): nprow, npcol, b = scalapack else: nprow = int(round(bd.comm.size**0.5)) while bd.comm.size % nprow != 0: nprow -= 1 npcol = bd.comm.size // nprow b = 64 p('ScaLapack grid: {0}x{1},'.format(nprow, npcol), 'block-size:', b) bg = BlacsGrid(bd.comm, bd.comm.size, 1) bg2 = BlacsGrid(bd.comm, nprow, npcol) scalapack = True else: nprow = npcol = 1 scalapack = False self.pt.set_positions(atoms.get_scaled_positions()) self.kpt_u[0].P_ani = None self.allocate_arrays_for_projections(self.pt.my_atom_indices) myslice = bd.get_slice() pb = ProgressBar(txt) nkpt = len(self.kpt_u) for u, kpt in enumerate(self.kpt_u): pb.update(u / nkpt) npw = len(self.pd.Q_qG[kpt.q]) if scalapack: mynpw = -(-npw // bd.comm.size) md = BlacsDescriptor(bg, npw, npw, mynpw, npw) md2 = BlacsDescriptor(bg2, npw, npw, b, b) else: md = md2 = MatrixDescriptor(npw, npw) with self.timer('Build H and S'): H_GG, S_GG = self.hs(ham, kpt.q, kpt.s, md) if scalapack: r = Redistributor(bd.comm, md, md2) H_GG = r.redistribute(H_GG) S_GG = r.redistribute(S_GG) psit_nG = md2.empty(dtype=complex) eps_n = np.empty(npw) with self.timer('Diagonalize'): if not scalapack: md2.general_diagonalize_dc(H_GG, S_GG, psit_nG, eps_n, iu=iu) else: md2.general_diagonalize_dc(H_GG, S_GG, psit_nG, eps_n) del H_GG, S_GG kpt.eps_n = eps_n[myslice].copy() if scalapack: md3 = BlacsDescriptor(bg, npw, npw, bd.mynbands, npw) r = Redistributor(bd.comm, md2, md3) psit_nG = r.redistribute(psit_nG) kpt.psit_nG = psit_nG[:bd.mynbands].copy() del psit_nG with self.timer('Projections'): self.pt.integrate(kpt.psit_nG, kpt.P_ani, kpt.q) kpt.f_n = None pb.finish() occupations.calculate(self)
def diagonalize_full_hamiltonian(self, ham, atoms, occupations, log, nbands=None, ecut=None, scalapack=None, expert=False): if self.dtype != complex: raise ValueError('Your wavefunctions are not complex as ' 'required by the PW diagonalization routine.\n' 'Please supply GPAW(..., dtype=complex, ...) ' 'as an argument to the calculator to enforce ' 'complex wavefunctions.') if nbands is None and ecut is None: nbands = self.pd.ngmin // self.bd.comm.size * self.bd.comm.size elif nbands is None: ecut /= units.Hartree vol = abs(np.linalg.det(self.gd.cell_cv)) nbands = int(vol * ecut**1.5 * 2**0.5 / 3 / pi**2) else: assert nbands <= self.pd.ngmin if expert: iu = nbands else: iu = None self.bd = bd = BandDescriptor(nbands, self.bd.comm) log('Diagonalizing full Hamiltonian ({0} lowest bands)'.format(nbands)) log('Matrix size (min, max): {0}, {1}'.format(self.pd.ngmin, self.pd.ngmax)) mem = 3 * self.pd.ngmax**2 * 16 / bd.comm.size / 1024**2 log('Approximate memory usage per core: {0:.3f} MB'.format(mem)) if bd.comm.size > 1: if isinstance(scalapack, (list, tuple)): nprow, npcol, b = scalapack else: nprow = int(round(bd.comm.size**0.5)) while bd.comm.size % nprow != 0: nprow -= 1 npcol = bd.comm.size // nprow b = 64 log('ScaLapack grid: {0}x{1},'.format(nprow, npcol), 'block-size:', b) bg = BlacsGrid(bd.comm, bd.comm.size, 1) bg2 = BlacsGrid(bd.comm, nprow, npcol) scalapack = True else: nprow = npcol = 1 scalapack = False self.set_positions(atoms.get_scaled_positions()) self.kpt_u[0].P_ani = None self.allocate_arrays_for_projections(self.pt.my_atom_indices) myslice = bd.get_slice() pb = ProgressBar(log.fd) nkpt = len(self.kpt_u) for u, kpt in enumerate(self.kpt_u): pb.update(u / nkpt) npw = len(self.pd.Q_qG[kpt.q]) if scalapack: mynpw = -(-npw // bd.comm.size) md = BlacsDescriptor(bg, npw, npw, mynpw, npw) md2 = BlacsDescriptor(bg2, npw, npw, b, b) else: md = md2 = MatrixDescriptor(npw, npw) with self.timer('Build H and S'): H_GG, S_GG = self.hs(ham, kpt.q, kpt.s, md) if scalapack: r = Redistributor(bd.comm, md, md2) H_GG = r.redistribute(H_GG) S_GG = r.redistribute(S_GG) psit_nG = md2.empty(dtype=complex) eps_n = np.empty(npw) with self.timer('Diagonalize'): if not scalapack: md2.general_diagonalize_dc(H_GG, S_GG, psit_nG, eps_n, iu=iu) else: md2.general_diagonalize_dc(H_GG, S_GG, psit_nG, eps_n) del H_GG, S_GG kpt.eps_n = eps_n[myslice].copy() if scalapack: md3 = BlacsDescriptor(bg, npw, npw, bd.mynbands, npw) r = Redistributor(bd.comm, md2, md3) psit_nG = r.redistribute(psit_nG) kpt.psit_nG = psit_nG[:bd.mynbands].copy() del psit_nG with self.timer('Projections'): self.pt.integrate(kpt.psit_nG, kpt.P_ani, kpt.q) kpt.f_n = None pb.finish() occupations.calculate(self) return nbands