def logarithmic_derivative(self, l, energies, rcut): rgd = self.rgd ch = Channel(l) gcut = rgd.round(rcut) N = 0 if l < len(self.waves_l): # Nonlocal PAW stuff: waves = self.waves_l[l] if len(waves) > 0: pt_ng = waves.pt_ng dH_nn = waves.dH_nn dS_nn = waves.dS_nn N = len(pt_ng) u_g = rgd.zeros() u_ng = rgd.zeros(N) dudr_n = np.empty(N) logderivs = [] d0 = 42.0 offset = 0 for e in energies: dudr = ch.integrate_outwards(u_g, rgd, self.vtr_g, gcut, e)[0] u = u_g[gcut] if N: for n in range(N): dudr_n[n] = ch.integrate_outwards(u_ng[n], rgd, self.vtr_g, gcut, e, pt_g=pt_ng[n])[0] A_nn = (dH_nn - e * dS_nn) / (4 * pi) B_nn = rgd.integrate(pt_ng[:, None] * u_ng, -1) c_n = rgd.integrate(pt_ng * u_g, -1) d_n = np.linalg.solve( np.dot(A_nn, B_nn) + np.eye(N), np.dot(A_nn, c_n)) u -= np.dot(u_ng[:, gcut], d_n) dudr -= np.dot(dudr_n, d_n) d1 = np.arctan(dudr / u) / pi + offset if d1 > d0: offset -= 1 d1 -= 1 logderivs.append(d1) d0 = d1 return np.array(logderivs)
def __init__(self, aea, waves, l0, rcmax=0): self.aea = aea self.l0 = l0 self.gd = aea.gd if len(waves) == 0: lmax = -1 else: lmax = max([l for n, l, rc in waves]) self.waves_l = [PAWWaves(l, aea.channels[l].basis) for l in range(lmax + 1)] self.rcmax = rcmax for n, l, rc in waves: ch = aea.channels[l] e = ch.e_n[n - l - 1] f = ch.f_n[n - l - 1] print n,l,rc,e,f phi_g = ch.basis.expand(ch.C_nb[0]) self.waves_l[l].add(phi_g, e, f, rc) self.rcmax = max(rc, self.rcmax) self.gcmax = self.gd.get_index(self.rcmax) self.alpha = log(1.0e4) / self.rcmax**2 # exp(-alpha*rcmax^2)=1.0e-4 self.alpha = round(self.alpha, 2) self.ghat_g = (np.exp(-self.alpha * self.gd.r_g**2) * (self.alpha / pi)**1.5) f0 = 0.0 if l0 == 0: f0 = 1.0 self.zeropot = Channel(l0, 0, [f0], aea.channels[l0].basis) self.vtr_g = None
def add_waves(self, rc): if isinstance(rc, float): radii = [rc] else: radii = rc if self.lmax >= 0: radii += [radii[-1]] * (self.lmax + 1 - len(radii)) del radii[self.lmax + 1:] # remove unused radii self.rcmax = max(radii) self.waves_l = [] for l in range(self.lmax + 1): rcut = radii[l] waves = PAWWaves(self.rgd, l, rcut) e = -1.0 for n in self.states[l]: if isinstance(n, int): # Bound state: ch = self.aea.channels[l] e = ch.e_n[n - l - 1] f = ch.f_n[n - l - 1] phi_g = ch.phi_ng[n - l - 1] else: if n is None: e += 1.0 else: e = n n = -1 f = 0.0 phi_g = self.rgd.zeros() gc = self.rgd.round(2.5 * self.rcmax) ch = Channel(l) a = ch.integrate_outwards(phi_g, self.rgd, self.aea.vr_sg[0], gc, e, self.aea.scalar_relativistic, self.aea.Z)[1] phi_g[1:gc + 1] /= self.rgd.r_g[1:gc + 1] phi_g[0] = a phi_g /= (self.rgd.integrate(phi_g**2) / (4 * pi))**0.5 waves.add(phi_g, n, e, f) self.waves_l.append(waves)
def add_waves(self, rc): if isinstance(rc, float): radii = [rc] else: radii = rc self.rcmax = max(radii) if self.lmax >= 0: radii += [radii[-1]] * (self.lmax + 1 - len(radii)) self.waves_l = [] for l in range(self.lmax + 1): rcut = radii[l] waves = PAWWaves(self.rgd, l, rcut) e = -1.0 for n in self.states[l]: if isinstance(n, int): # Bound state: ch = self.aea.channels[l] e = ch.e_n[n - l - 1] f = ch.f_n[n - l - 1] phi_g = ch.phi_ng[n - l - 1] else: if n is None: e += 1.0 else: e = n n = -1 f = 0.0 phi_g = self.rgd.zeros() gc = self.rgd.round(1.5 * rcut) ch = Channel(l) a = ch.integrate_outwards(phi_g, self.rgd, self.aea.vr_sg[0], gc, e, self.aea.scalar_relativistic, self.aea.Z)[1] phi_g[1:gc + 1] /= self.rgd.r_g[1:gc + 1] phi_g[0] = a phi_g /= (self.rgd.integrate(phi_g**2) / (4 * pi))**0.5 waves.add(phi_g, n, e, f) self.waves_l.append(waves)
def match_local_potential(self, l0, r0, P, e0): self.log('Local potential matching %s-scattering at e=%.3f eV' % ('spdfg'[l0], e0 * Hartree) + ' and r=%.2f Bohr' % r0) g0 = self.rgd.ceil(r0) gc = g0 + 20 ch = Channel(l0) phi_g = self.rgd.zeros() ch.integrate_outwards(phi_g, self.rgd, self.aea.vr_sg[0], gc, e0, self.aea.scalar_relativistic) phi_g[1:gc] /= self.rgd.r_g[1:gc] if l0 == 0: phi_g[0] = phi_g[1] #phit_g, c = self.rgd.pseudize_normalized(phi_g, g0, l=l0, points=P) phit_g, c = self.rgd.pseudize(phi_g, g0, l=l0, points=P) r_g = self.rgd.r_g[1:g0] dgdr_g = 1 / self.rgd.dr_g d2gdr2_g = self.rgd.d2gdr2() a_g = phit_g.copy() a_g[1:] /= self.rgd.r_g[1:]**l0 a_g[0] = c dadg_g = self.rgd.zeros() d2adg2_g = self.rgd.zeros() dadg_g[1:-1] = 0.5 * (a_g[2:] - a_g[:-2]) d2adg2_g[1:-1] = a_g[2:] - 2 * a_g[1:-1] + a_g[:-2] q_g = (((l0 + 1) * dgdr_g + 0.5 * self.rgd.r_g * d2gdr2_g) * dadg_g + 0.5 * self.rgd.r_g * d2adg2_g * dgdr_g**2) q_g[:g0] /= a_g[:g0] q_g += e0 * self.rgd.r_g q_g[0] = 0.0 self.vtr_g = self.aea.vr_sg[0].copy() self.vtr_g[0] = 0.0 self.vtr_g[1:g0] = q_g[1:g0]#e0 * r_g - t_g * r_g**(l0 + 1) / phit_g[1:g0] self.l0 = l0 self.e0 = e0 self.r0 = r0 self.nderiv0 = P
def logarithmic_derivative(self, l, energies, rcut): rgd = self.rgd ch = Channel(l) gcut = rgd.round(rcut) N = 0 if l < len(self.waves_l): # Nonlocal PAW stuff: waves = self.waves_l[l] if len(waves) > 0: pt_ng = waves.pt_ng dH_nn = waves.dH_nn dS_nn = waves.dS_nn N = len(pt_ng) u_g = rgd.zeros() u_ng = rgd.zeros(N) dudr_n = np.empty(N) logderivs = [] for e in energies: dudr = ch.integrate_outwards(u_g, rgd, self.vtr_g, gcut, e) u = u_g[gcut] if N: for n in range(N): dudr_n[n] = ch.integrate_outwards(u_ng[n], rgd, self.vtr_g, gcut, e, pt_g=pt_ng[n]) A_nn = (dH_nn - e * dS_nn) / (4 * pi) B_nn = rgd.integrate(pt_ng[:, None] * u_ng, -1) c_n = rgd.integrate(pt_ng * u_g, -1) d_n = np.linalg.solve(np.dot(A_nn, B_nn) + np.eye(N), np.dot(A_nn, c_n)) u -= np.dot(u_ng[:, gcut], d_n) dudr -= np.dot(dudr_n, d_n) logderivs.append(dudr / u) return logderivs
def match_local_potential(self, r0, P): l0 = self.l0 self.log('Local potential matching %s-scattering at e=0.0 eV' % 'spdfg'[l0] + ' and r=%.2f Bohr' % r0) g0 = self.rgd.ceil(r0) gc = g0 + 20 e0 = 0.0 ch = Channel(l0) phi_g = self.rgd.zeros() a = ch.integrate_outwards(phi_g, self.rgd, self.aea.vr_sg[0], gc, e0, self.aea.scalar_relativistic, self.aea.Z)[1] phi_g[1:gc] /= self.rgd.r_g[1:gc] phi_g[0] = a phit_g, c = self.rgd.pseudize(phi_g, g0, l=l0, points=P) dgdr_g = 1 / self.rgd.dr_g d2gdr2_g = self.rgd.d2gdr2() a_g = phit_g.copy() a_g[1:] /= self.rgd.r_g[1:]**l0 a_g[0] = c dadg_g = self.rgd.zeros() d2adg2_g = self.rgd.zeros() dadg_g[1:-1] = 0.5 * (a_g[2:] - a_g[:-2]) d2adg2_g[1:-1] = a_g[2:] - 2 * a_g[1:-1] + a_g[:-2] q_g = (((l0 + 1) * dgdr_g + 0.5 * self.rgd.r_g * d2gdr2_g) * dadg_g + 0.5 * self.rgd.r_g * d2adg2_g * dgdr_g**2) q_g[:g0] /= a_g[:g0] q_g += e0 * self.rgd.r_g q_g[0] = 0.0 self.vtr_g = self.aea.vr_sg[0].copy() self.vtr_g[0] = 0.0 self.vtr_g[1:g0] = q_g[1:g0]
def create_basis_function(self, l, n, tailnorm, scale): rgd = self.rgd waves = self.waves_l[l] # Find cutoff radii: n_g = np.add.accumulate(waves.phit_ng[n]**2 * rgd.r_g**2 * rgd.dr_g) norm = n_g[-1] g2 = (norm - n_g > tailnorm * norm).sum() r2 = rgd.r_g[g2] r1 = max(0.6 * r2, waves.rcut) g1 = rgd.ceil(r1) # Set up confining potential: r = rgd.r_g[g1:g2] vtr_g = self.vtr_g.copy() vtr_g[g1:g2] += scale * np.exp((r2 - r1) / (r1 - r)) / (r - r2)**2 vtr_g[g2:] = np.inf # Nonlocal PAW stuff: pt_ng = waves.pt_ng dH_nn = waves.dH_nn dS_nn = waves.dS_nn N = len(pt_ng) u_g = rgd.zeros() u_ng = rgd.zeros(N) duodr_n = np.empty(N) a_n = np.empty(N) e = waves.e_n[n] e0 = e ch = Channel(l) while True: duodr, a = ch.integrate_outwards(u_g, rgd, vtr_g, g1, e) for n in range(N): duodr_n[n], a_n[n] = ch.integrate_outwards(u_ng[n], rgd, vtr_g, g1, e, pt_g=pt_ng[n]) A_nn = (dH_nn - e * dS_nn) / (4 * pi) B_nn = rgd.integrate(pt_ng[:, None] * u_ng, -1) c_n = rgd.integrate(pt_ng * u_g, -1) d_n = np.linalg.solve( np.dot(A_nn, B_nn) + np.eye(N), np.dot(A_nn, c_n)) u_g[:g1 + 1] -= np.dot(d_n, u_ng[:, :g1 + 1]) a -= np.dot(d_n, a_n) duodr -= np.dot(duodr_n, d_n) uo = u_g[g1] duidr = ch.integrate_inwards(u_g, rgd, vtr_g, g1, e, gmax=g2) ui = u_g[g1] A = duodr / uo - duidr / ui u_g[g1:] *= uo / ui x = (norm / rgd.integrate(u_g**2, -2) * (4 * pi))**0.5 u_g *= x a *= x if abs(A) < 1e-5: break e += 0.5 * A * u_g[g1]**2 u_g[1:] /= rgd.r_g[1:] u_g[0] = a * 0.0**l return u_g, r1, r2, e - e0
def create_basis_function(self, l, n, tailnorm, scale): rgd = self.rgd waves = self.waves_l[l] # Find cutoff radii: n_g = np.add.accumulate(waves.phit_ng[n]**2 * rgd.r_g**2 * rgd.dr_g) norm = n_g[-1] g2 = (norm - n_g > tailnorm * norm).sum() r2 = rgd.r_g[g2] r1 = max(0.6 * r2, waves.rcut) g1 = rgd.ceil(r1) # Set up confining potential: r = rgd.r_g[g1:g2] vtr_g = self.vtr_g.copy() vtr_g[g1:g2] += scale * np.exp((r2 - r1) / (r1 - r)) / (r - r2)**2 vtr_g[g2:] = np.inf # Nonlocal PAW stuff: pt_ng = waves.pt_ng dH_nn = waves.dH_nn dS_nn = waves.dS_nn N = len(pt_ng) u_g = rgd.zeros() u_ng = rgd.zeros(N) duodr_n = np.empty(N) a_n = np.empty(N) e = waves.e_n[n] e0 = e ch = Channel(l) while True: duodr, a = ch.integrate_outwards(u_g, rgd, vtr_g, g1, e) for n in range(N): duodr_n[n], a_n[n] = ch.integrate_outwards(u_ng[n], rgd, vtr_g, g1, e, pt_g=pt_ng[n]) A_nn = (dH_nn - e * dS_nn) / (4 * pi) B_nn = rgd.integrate(pt_ng[:, None] * u_ng, -1) c_n = rgd.integrate(pt_ng * u_g, -1) d_n = np.linalg.solve(np.dot(A_nn, B_nn) + np.eye(N), np.dot(A_nn, c_n)) u_g[:g1 + 1] -= np.dot(d_n, u_ng[:, :g1 + 1]) a -= np.dot(d_n, a_n) duodr -= np.dot(duodr_n, d_n) uo = u_g[g1] duidr = ch.integrate_inwards(u_g, rgd, vtr_g, g1, e, gmax=g2) ui = u_g[g1] A = duodr / uo - duidr / ui u_g[g1:] *= uo / ui x = (norm / rgd.integrate(u_g**2, -2) * (4 * pi))**0.5 u_g *= x a *= x if abs(A) < 1e-5: break e += 0.5 * A * u_g[g1]**2 u_g[1:] /= rgd.r_g[1:] u_g[0] = a * 0.0**l return u_g, r1, r2, e - e0