def get_rpa(self): """Calculate RPA and Hartree-fock part of the A+-B matrices.""" # shorthands kss = self.fullkss finegrid = self.finegrid yukawa = hasattr(self.xc, 'rsf') and (self.xc.rsf == 'Yukawa') # calculate omega matrix nij = len(kss) print('RPAhyb', nij, 'transitions', file=self.txt) AmB = np.zeros((nij, nij)) ApB = self.ApB # storage place for Coulomb integrals integrals = {} if yukawa: rsf_integrals = {} # setup things for IVOs if self.xc.excitation is not None or self.xc.excited != 0: sin_tri_weight = 1 if self.xc.excitation is not None: ex_type = self.xc.excitation.lower() if ex_type == 'singlet': sin_tri_weight = 2 elif ex_type == 'triplet': sin_tri_weight = 0 h**o = int(self.paw.get_number_of_electrons() // 2) ivo_l = h**o - self.xc.excited - 1 else: ivo_l = None for ij in range(nij): print('RPAhyb kss[' + '%d' % ij + ']=', kss[ij], file=self.txt) timer = Timer() timer.start('init') timer2 = Timer() # smooth density including compensation charges timer2.start('with_compensation_charges 0') rhot_p = kss[ij].with_compensation_charges(finegrid != 0) timer2.stop() # integrate with 1/|r_1-r_2| timer2.start('poisson') phit_p = np.zeros(rhot_p.shape, rhot_p.dtype) self.poisson.solve(phit_p, rhot_p, charge=None) timer2.stop() timer.stop() t0 = timer.get_time('init') timer.start(ij) if finegrid == 1: rhot = kss[ij].with_compensation_charges() phit = self.gd.zeros() self.restrict(phit_p, phit) else: phit = phit_p rhot = rhot_p for kq in range(ij, nij): if kq != ij: # smooth density including compensation charges timer2.start('kq with_compensation_charges') rhot = kss[kq].with_compensation_charges(finegrid == 2) timer2.stop() pre = self.weight_Kijkq(ij, kq) timer2.start('integrate') I = self.Coulomb_integral_kss(kss[ij], kss[kq], phit, rhot) if kss[ij].spin == kss[kq].spin: name = self.Coulomb_integral_name(kss[ij].i, kss[ij].j, kss[kq].i, kss[kq].j, kss[ij].spin) integrals[name] = I ApB[ij, kq] = pre * I timer2.stop() if ij == kq: epsij = kss[ij].get_energy() / kss[ij].get_weight() AmB[ij, kq] += epsij ApB[ij, kq] += epsij timer.stop() # timer2.write() if ij < (nij - 1): print('RPAhyb estimated time left', self.time_left(timer, t0, ij, nij), file=self.txt) # add HF parts and apply symmetry if hasattr(self.xc, 'hybrid'): weight = self.xc.hybrid else: weight = 0.0 for ij in range(nij): print('HF kss[' + '%d' % ij + ']', file=self.txt) timer = Timer() timer.start('init') timer.stop() t0 = timer.get_time('init') timer.start(ij) i = kss[ij].i j = kss[ij].j s = kss[ij].spin for kq in range(ij, nij): if kss[ij].pspin == kss[kq].pspin: k = kss[kq].i q = kss[kq].j ikjq = self.Coulomb_integral_ijkq(i, k, j, q, s, integrals) iqkj = self.Coulomb_integral_ijkq(i, q, k, j, s, integrals) if yukawa: # Yukawa integrals might be caches ikjq -= self.Coulomb_integral_ijkq( i, k, j, q, s, rsf_integrals, yukawa) iqkj -= self.Coulomb_integral_ijkq( i, q, k, j, s, rsf_integrals, yukawa) ApB[ij, kq] -= weight * (ikjq + iqkj) AmB[ij, kq] -= weight * (ikjq - iqkj) ApB[kq, ij] = ApB[ij, kq] AmB[kq, ij] = AmB[ij, kq] timer.stop() if ij < (nij - 1): print('HF estimated time left', self.time_left(timer, t0, ij, nij), file=self.txt) if ivo_l is not None: # IVO RPA after Berman, Kaldor, Chem. Phys. 43 (3) 1979 # doi: 10.1016/0301-0104(79)85205-2 l = ivo_l for ij in range(nij): i = kss[ij].i j = kss[ij].j s = kss[ij].spin for kq in range(ij, nij): if kss[kq].i == i and kss[ij].pspin == kss[kq].pspin: k = kss[kq].i q = kss[kq].j jqll = self.Coulomb_integral_ijkq( j, q, l, l, s, integrals) jllq = self.Coulomb_integral_ijkq( j, l, l, q, s, integrals) if yukawa: jqll -= self.Coulomb_integral_ijkq( j, q, l, l, s, rsf_integrals, yukawa) jllq -= self.Coulomb_integral_ijkq( j, l, l, q, s, rsf_integrals, yukawa) jllq *= sin_tri_weight ApB[ij, kq] += weight * (jqll - jllq) AmB[ij, kq] += weight * (jqll - jllq) ApB[kq, ij] = ApB[ij, kq] AmB[kq, ij] = AmB[ij, kq] return AmB
def get_rpa(self): """calculate RPA part of the omega matrix""" # shorthands kss = self.fullkss finegrid = self.finegrid wfs = self.paw.wfs eh_comm = self.eh_comm # calculate omega matrix nij = len(kss) print('RPA', nij, 'transitions', file=self.txt) Om = self.Om for ij in range(eh_comm.rank, nij, eh_comm.size): print('RPA kss[' + '%d' % ij + ']=', kss[ij], file=self.txt) timer = Timer() timer.start('init') timer2 = Timer() # smooth density including compensation charges timer2.start('with_compensation_charges 0') rhot_p = kss[ij].with_compensation_charges( finegrid is not 0) timer2.stop() # integrate with 1/|r_1-r_2| timer2.start('poisson') phit_p = np.zeros(rhot_p.shape, rhot_p.dtype.char) self.poisson.solve(phit_p, rhot_p, charge=None) timer2.stop() timer.stop() t0 = timer.get_time('init') timer.start(ij) if finegrid == 1: rhot = kss[ij].with_compensation_charges() phit = self.gd.zeros() # print "shapes 0=",phit.shape,rhot.shape self.restrict(phit_p, phit) else: phit = phit_p rhot = rhot_p for kq in range(ij, nij): if kq != ij: # smooth density including compensation charges timer2.start('kq with_compensation_charges') rhot = kss[kq].with_compensation_charges( finegrid is 2) timer2.stop() pre = 2 * sqrt(kss[ij].get_energy() * kss[kq].get_energy() * kss[ij].get_weight() * kss[kq].get_weight()) I = self.Coulomb_integral_kss(kss[ij], kss[kq], rhot, phit, timer2) Om[ij, kq] = pre * I if ij == kq: Om[ij, kq] += kss[ij].get_energy() ** 2 else: Om[kq, ij] = Om[ij, kq] timer.stop() # timer2.write() if ij < (nij - 1): t = timer.get_time(ij) # time for nij-ij calculations t = .5 * t * \ (nij - ij) # estimated time for n*(n+1)/2, n=nij-(ij+1) print('RPA estimated time left', self.timestring(t0 * (nij - ij - 1) + t), file=self.txt)
def get_rpa(self): """Calculate RPA and Hartree-fock part of the A+-B matrices.""" # shorthands kss = self.fullkss finegrid = self.finegrid # calculate omega matrix nij = len(kss) print('RPAhyb', nij, 'transitions', file=self.txt) AmB = np.zeros((nij, nij)) ApB = self.ApB # storage place for Coulomb integrals integrals = {} for ij in range(nij): print('RPAhyb kss[' + '%d' % ij + ']=', kss[ij], file=self.txt) timer = Timer() timer.start('init') timer2 = Timer() # smooth density including compensation charges timer2.start('with_compensation_charges 0') rhot_p = kss[ij].with_compensation_charges(finegrid is not 0) timer2.stop() # integrate with 1/|r_1-r_2| timer2.start('poisson') phit_p = np.zeros(rhot_p.shape, rhot_p.dtype) self.poisson.solve(phit_p, rhot_p, charge=None) timer2.stop() timer.stop() t0 = timer.get_time('init') timer.start(ij) if finegrid == 1: rhot = kss[ij].with_compensation_charges() phit = self.gd.zeros() self.restrict(phit_p, phit) else: phit = phit_p rhot = rhot_p for kq in range(ij, nij): if kq != ij: # smooth density including compensation charges timer2.start('kq with_compensation_charges') rhot = kss[kq].with_compensation_charges(finegrid is 2) timer2.stop() pre = self.weight_Kijkq(ij, kq) timer2.start('integrate') I = self.Coulomb_integral_kss(kss[ij], kss[kq], phit, rhot) if kss[ij].spin == kss[kq].spin: name = self.Coulomb_integral_name(kss[ij].i, kss[ij].j, kss[kq].i, kss[kq].j, kss[ij].spin) integrals[name] = I ApB[ij, kq] = pre * I timer2.stop() if ij == kq: epsij = kss[ij].get_energy() / kss[ij].get_weight() AmB[ij, kq] += epsij ApB[ij, kq] += epsij timer.stop() # timer2.write() if ij < (nij - 1): print('RPAhyb estimated time left', self.time_left(timer, t0, ij, nij), file=self.txt) # add HF parts and apply symmetry if hasattr(self.xc, 'hybrid'): weight = self.xc.hybrid else: weight = 0.0 for ij in range(nij): print('HF kss[' + '%d' % ij + ']', file=self.txt) timer = Timer() timer.start('init') timer.stop() t0 = timer.get_time('init') timer.start(ij) i = kss[ij].i j = kss[ij].j s = kss[ij].spin for kq in range(ij, nij): if kss[ij].pspin == kss[kq].pspin: k = kss[kq].i q = kss[kq].j ikjq = self.Coulomb_integral_ijkq(i, k, j, q, s, integrals) iqkj = self.Coulomb_integral_ijkq(i, q, k, j, s, integrals) ApB[ij, kq] -= weight * (ikjq + iqkj) AmB[ij, kq] -= weight * (ikjq - iqkj) ApB[kq, ij] = ApB[ij, kq] AmB[kq, ij] = AmB[ij, kq] timer.stop() if ij < (nij - 1): print('HF estimated time left', self.time_left(timer, t0, ij, nij), file=self.txt) return AmB
def get_xc(self): """Add xc part of the coupling matrix""" # shorthands paw = self.paw wfs = paw.wfs gd = paw.density.finegd comm = gd.comm eh_comm = self.eh_comm fg = self.finegrid is 2 kss = self.fullkss nij = len(kss) Om_xc = self.Om # initialize densities # nt_sg is the smooth density on the fine grid with spin index if kss.nvspins == 2: # spin polarised ground state calc. nt_sg = paw.density.nt_sg else: # spin unpolarised ground state calc. if kss.npspins == 2: # construct spin polarised densities nt_sg = np.array([.5 * paw.density.nt_sg[0], .5 * paw.density.nt_sg[0]]) else: nt_sg = paw.density.nt_sg # check if D_sp have been changed before D_asp = self.paw.density.D_asp for a, D_sp in D_asp.items(): if len(D_sp) != kss.npspins: if len(D_sp) == 1: D_asp[a] = np.array([0.5 * D_sp[0], 0.5 * D_sp[0]]) else: D_asp[a] = np.array([D_sp[0] + D_sp[1]]) # restrict the density if needed if fg: nt_s = nt_sg else: nt_s = self.gd.zeros(nt_sg.shape[0]) for s in range(nt_sg.shape[0]): self.restrict(nt_sg[s], nt_s[s]) gd = paw.density.gd # initialize vxc or fxc if self.derivativeLevel == 0: raise NotImplementedError if kss.npspins == 2: v_g = nt_sg[0].copy() else: v_g = nt_sg.copy() elif self.derivativeLevel == 1: pass elif self.derivativeLevel == 2: fxc_sg = np.zeros(nt_sg.shape) self.xc.calculate_fxc(gd, nt_sg, fxc_sg) else: raise ValueError('derivativeLevel can only be 0,1,2') # self.paw.my_nuclei = [] ns = self.numscale xc = self.xc print('XC', nij, 'transitions', file=self.txt) for ij in range(eh_comm.rank, nij, eh_comm.size): print('XC kss[' + '%d' % ij + ']', file=self.txt) timer = Timer() timer.start('init') timer2 = Timer() if self.derivativeLevel >= 1: # vxc is available # We use the numerical two point formula for calculating # the integral over fxc*n_ij. The results are # vvt_s smooth integral # nucleus.I_sp atom based correction matrices (pack2) # stored on each nucleus timer2.start('init v grids') vp_s = np.zeros(nt_s.shape, nt_s.dtype.char) vm_s = np.zeros(nt_s.shape, nt_s.dtype.char) if kss.npspins == 2: # spin polarised nv_s = nt_s.copy() nv_s[kss[ij].pspin] += ns * kss[ij].get(fg) xc.calculate(gd, nv_s, vp_s) nv_s = nt_s.copy() nv_s[kss[ij].pspin] -= ns * kss[ij].get(fg) xc.calculate(gd, nv_s, vm_s) else: # spin unpolarised nv = nt_s + ns * kss[ij].get(fg) xc.calculate(gd, nv, vp_s) nv = nt_s - ns * kss[ij].get(fg) xc.calculate(gd, nv, vm_s) vvt_s = (0.5 / ns) * (vp_s - vm_s) timer2.stop() # initialize the correction matrices timer2.start('init v corrections') I_asp = {} for a, P_ni in wfs.kpt_u[kss[ij].spin].P_ani.items(): # create the modified density matrix Pi_i = P_ni[kss[ij].i] Pj_i = P_ni[kss[ij].j] P_ii = np.outer(Pi_i, Pj_i) # we need the symmetric form, hence we can pack P_p = pack(P_ii) D_sp = self.paw.density.D_asp[a].copy() D_sp[kss[ij].pspin] -= ns * P_p setup = wfs.setups[a] I_sp = np.zeros_like(D_sp) self.xc.calculate_paw_correction(setup, D_sp, I_sp) I_sp *= -1.0 D_sp = self.paw.density.D_asp[a].copy() D_sp[kss[ij].pspin] += ns * P_p self.xc.calculate_paw_correction(setup, D_sp, I_sp) I_sp /= 2.0 * ns I_asp[a] = I_sp timer2.stop() timer.stop() t0 = timer.get_time('init') timer.start(ij) for kq in range(ij, nij): weight = self.weight_Kijkq(ij, kq) if self.derivativeLevel == 0: # only Exc is available if kss.npspins == 2: # spin polarised nv_g = nt_sg.copy() nv_g[kss[ij].pspin] += kss[ij].get(fg) nv_g[kss[kq].pspin] += kss[kq].get(fg) Excpp = xc.get_energy_and_potential( nv_g[0], v_g, nv_g[1], v_g) nv_g = nt_sg.copy() nv_g[kss[ij].pspin] += kss[ij].get(fg) nv_g[kss[kq].pspin] -= kss[kq].get(fg) Excpm = xc.get_energy_and_potential( nv_g[0], v_g, nv_g[1], v_g) nv_g = nt_sg.copy() nv_g[kss[ij].pspin] -=\ kss[ij].get(fg) nv_g[kss[kq].pspin] +=\ kss[kq].get(fg) Excmp = xc.get_energy_and_potential( nv_g[0], v_g, nv_g[1], v_g) nv_g = nt_sg.copy() nv_g[kss[ij].pspin] -= \ kss[ij].get(fg) nv_g[kss[kq].pspin] -=\ kss[kq].get(fg) Excpp = xc.get_energy_and_potential( nv_g[0], v_g, nv_g[1], v_g) else: # spin unpolarised nv_g = nt_sg + ns * kss[ij].get(fg)\ + ns * kss[kq].get(fg) Excpp = xc.get_energy_and_potential(nv_g, v_g) nv_g = nt_sg + ns * kss[ij].get(fg)\ - ns * kss[kq].get(fg) Excpm = xc.get_energy_and_potential(nv_g, v_g) nv_g = nt_sg - ns * kss[ij].get(fg)\ + ns * kss[kq].get(fg) Excmp = xc.get_energy_and_potential(nv_g, v_g) nv_g = nt_sg - ns * kss[ij].get(fg)\ - ns * kss[kq].get(fg) Excmm = xc.get_energy_and_potential(nv_g, v_g) Om_xc[ij, kq] += weight *\ 0.25 * \ (Excpp - Excmp - Excpm + Excmm) / (ns * ns) elif self.derivativeLevel == 1: # vxc is available timer2.start('integrate') Om_xc[ij, kq] += weight *\ self.gd.integrate(kss[kq].get(fg) * vvt_s[kss[kq].pspin]) timer2.stop() timer2.start('integrate corrections') Exc = 0. for a, P_ni in wfs.kpt_u[kss[kq].spin].P_ani.items(): # create the modified density matrix Pk_i = P_ni[kss[kq].i] Pq_i = P_ni[kss[kq].j] P_ii = np.outer(Pk_i, Pq_i) # we need the symmetric form, hence we can pack # use pack as I_sp used pack2 P_p = pack(P_ii) Exc += np.dot(I_asp[a][kss[kq].pspin], P_p) Om_xc[ij, kq] += weight * self.gd.comm.sum(Exc) timer2.stop() elif self.derivativeLevel == 2: # fxc is available if kss.npspins == 2: # spin polarised Om_xc[ij, kq] += weight *\ gd.integrate(kss[ij].get(fg) * kss[kq].get(fg) * fxc_sg[kss[ij].pspin, kss[kq].pspin]) else: # spin unpolarised Om_xc[ij, kq] += weight *\ gd.integrate(kss[ij].get(fg) * kss[kq].get(fg) * fxc_sg) # XXX still numeric derivatives for local terms timer2.start('integrate corrections') Exc = 0. for a, P_ni in wfs.kpt_u[kss[kq].spin].P_ani.items(): # create the modified density matrix Pk_i = P_ni[kss[kq].i] Pq_i = P_ni[kss[kq].j] P_ii = np.outer(Pk_i, Pq_i) # we need the symmetric form, hence we can pack # use pack as I_sp used pack2 P_p = pack(P_ii) Exc += np.dot(I_asp[a][kss[kq].pspin], P_p) Om_xc[ij, kq] += weight * self.gd.comm.sum(Exc) timer2.stop() if ij != kq: Om_xc[kq, ij] = Om_xc[ij, kq] timer.stop() # timer2.write() if ij < (nij - 1): print('XC estimated time left', self.time_left(timer, t0, ij, nij), file=self.txt)
def get_rpa(self): """Calculate RPA and Hartree-fock part of the A+-B matrices.""" # shorthands kss = self.fullkss finegrid = self.finegrid # calculate omega matrix nij = len(kss) print("RPAhyb", nij, "transitions", file=self.txt) AmB = np.zeros((nij, nij)) ApB = self.ApB # storage place for Coulomb integrals integrals = {} for ij in range(nij): print("RPAhyb kss[" + "%d" % ij + "]=", kss[ij], file=self.txt) timer = Timer() timer.start("init") timer2 = Timer() # smooth density including compensation charges timer2.start("with_compensation_charges 0") rhot_p = kss[ij].with_compensation_charges(finegrid is not 0) timer2.stop() # integrate with 1/|r_1-r_2| timer2.start("poisson") phit_p = np.zeros(rhot_p.shape, rhot_p.dtype) self.poisson.solve(phit_p, rhot_p, charge=None) timer2.stop() timer.stop() t0 = timer.get_time("init") timer.start(ij) if finegrid == 1: rhot = kss[ij].with_compensation_charges() phit = self.gd.zeros() self.restrict(phit_p, phit) else: phit = phit_p rhot = rhot_p for kq in range(ij, nij): if kq != ij: # smooth density including compensation charges timer2.start("kq with_compensation_charges") rhot = kss[kq].with_compensation_charges(finegrid is 2) timer2.stop() pre = self.weight_Kijkq(ij, kq) timer2.start("integrate") I = self.Coulomb_integral_kss(kss[ij], kss[kq], phit, rhot) if kss[ij].spin == kss[kq].spin: name = self.Coulomb_integral_name(kss[ij].i, kss[ij].j, kss[kq].i, kss[kq].j, kss[ij].spin) integrals[name] = I ApB[ij, kq] = pre * I timer2.stop() if ij == kq: epsij = kss[ij].get_energy() / kss[ij].get_weight() AmB[ij, kq] += epsij ApB[ij, kq] += epsij timer.stop() # timer2.write() if ij < (nij - 1): print("RPAhyb estimated time left", self.time_left(timer, t0, ij, nij), file=self.txt) # add HF parts and apply symmetry if hasattr(self.xc, "hybrid"): weight = self.xc.hybrid else: weight = 0.0 for ij in range(nij): print("HF kss[" + "%d" % ij + "]", file=self.txt) timer = Timer() timer.start("init") timer.stop() t0 = timer.get_time("init") timer.start(ij) i = kss[ij].i j = kss[ij].j s = kss[ij].spin for kq in range(ij, nij): if kss[ij].pspin == kss[kq].pspin: k = kss[kq].i q = kss[kq].j ikjq = self.Coulomb_integral_ijkq(i, k, j, q, s, integrals) iqkj = self.Coulomb_integral_ijkq(i, q, k, j, s, integrals) ApB[ij, kq] -= weight * (ikjq + iqkj) AmB[ij, kq] -= weight * (ikjq - iqkj) ApB[kq, ij] = ApB[ij, kq] AmB[kq, ij] = AmB[ij, kq] timer.stop() if ij < (nij - 1): print("HF estimated time left", self.time_left(timer, t0, ij, nij), file=self.txt) return AmB