Пример #1
0
    def solve(self,
              phi,
              rho,
              charge=None,
              eps=None,
              maxcharge=1e-6,
              zero_initial_phi=False):
        if self.phi_tilde is None:
            self.phi_tilde = self.gd.zeros()
        phi_tilde = self.phi_tilde
        niter_tilde = FDPoissonSolver.solve(self, phi_tilde, rho, None,
                                            self.eps, maxcharge, False)

        epsr, dx_epsr, dy_epsr, dz_epsr = self.dielectric.eps_gradeps
        dx_phi_tilde = self.gd.empty()
        dy_phi_tilde = self.gd.empty()
        dz_phi_tilde = self.gd.empty()
        Gradient(self.gd, 0, 1.0, self.nn).apply(phi_tilde, dx_phi_tilde)
        Gradient(self.gd, 1, 1.0, self.nn).apply(phi_tilde, dy_phi_tilde)
        Gradient(self.gd, 2, 1.0, self.nn).apply(phi_tilde, dz_phi_tilde)

        scalar_product = (dx_epsr * dx_phi_tilde + dy_epsr * dy_phi_tilde +
                          dz_epsr * dz_phi_tilde)

        rho_and_pol = (rho / epsr + scalar_product / (4. * np.pi * epsr**2))

        niter = FDPoissonSolver.solve(self, phi, rho_and_pol, None, eps,
                                      maxcharge, zero_initial_phi)
        return niter_tilde + niter
Пример #2
0
 def solve(self,
           phi,
           rho,
           charge=None,
           eps=None,
           maxcharge=1e-6,
           zero_initial_phi=False):
     if self.gd.pbc_c.all():
         actual_charge = self.gd.integrate(rho)
         if abs(actual_charge) > maxcharge:
             raise NotImplementedError(
                 'charged periodic systems are not implemented')
     return FDPoissonSolver.solve(self, phi, rho, charge, eps, maxcharge,
                                  zero_initial_phi)
Пример #3
0
    def _solve(self,
               phi,
               rho,
               charge=None,
               eps=None,
               maxcharge=1e-6,
               zero_initial_phi=False):
        self._init()
        if eps is None:
            eps = self.eps

        if self.moment_corrections:
            assert not self.gd.pbc_c.any()

            self.timer.start('Multipole moment corrections')

            rho_neutral = rho * 0.0
            phi_cor_k = []
            for gauss, mask_g, mom_j in zip(self.gauss_i, self.mask_ig,
                                            self.mom_ij):
                rho_masked = rho * mask_g
                for mom in mom_j:
                    phi_cor_k.append(gauss.remove_moment(rho_masked, mom))
                rho_neutral += rho_masked

            # Remove multipoles for better initial guess
            for phi_cor in phi_cor_k:
                phi -= phi_cor

            self.timer.stop('Multipole moment corrections')

            self.timer.start('Solve neutral')
            niter = self.solve_neutral(phi, rho_neutral, eps=eps)
            self.timer.stop('Solve neutral')

            self.timer.start('Multipole moment corrections')
            # correct error introduced by removing multipoles
            for phi_cor in phi_cor_k:
                phi += phi_cor
            self.timer.stop('Multipole moment corrections')

            return niter
        else:
            return FDPoissonSolver.solve(self, phi, rho, charge, eps,
                                         maxcharge, zero_initial_phi)
Пример #4
0
 def solve(self,
           phi,
           rho,
           charge=None,
           eps=None,
           maxcharge=1e-6,
           zero_initial_phi=False,
           timer=None):
     self._init()
     if self.gd.pbc_c.all():
         actual_charge = self.gd.integrate(rho)
         if abs(actual_charge) > maxcharge:
             raise NotImplementedError(
                 'charged periodic systems are not implemented')
     self.restrict_op_weights()
     ret = FDPoissonSolver.solve(self, phi, rho, charge, eps, maxcharge,
                                 zero_initial_phi)
     return ret
Пример #5
0
def test(cellno, cellname, cell_cv, idiv, pbc, nn):
    N_c = h2gpts(0.12, cell_cv, idiv=idiv)
    if idiv == 1:
        N_c += 1 - N_c % 2  # We want especially to test uneven grids
    gd = GridDescriptor(N_c, cell_cv, pbc_c=pbc)
    rho_g = gd.zeros()
    phi_g = gd.zeros()
    rho_g[:] = -0.3 + rng.rand(*rho_g.shape)

    # Neutralize charge:
    charge = gd.integrate(rho_g)
    magic = gd.get_size_of_global_array().prod()
    rho_g -= charge / gd.dv / magic
    charge = gd.integrate(rho_g)
    assert abs(charge) < 1e-12

    # Check use_cholesky=True/False ?
    from gpaw.poisson import FDPoissonSolver
    ps = FastPoissonSolver(nn=nn)
    #print('setgrid')

    # Will raise BadAxesError for some pbc/cell combinations
    ps.set_grid_descriptor(gd)

    ps.solve(phi_g, rho_g)

    laplace = Laplace(gd, scale=-1.0 / (4.0 * np.pi), n=nn)

    def get_residual_err(phi_g):
        rhotest_g = gd.zeros()
        laplace.apply(phi_g, rhotest_g)
        residual = np.abs(rhotest_g - rho_g)
        # Residual is not accurate at end of non-periodic directions
        # except for nn=1 (since effectively we use the right stencil
        # only for nn=1 at the boundary).
        #
        # To do this check correctly, the Laplacian should have lower
        # nn at the boundaries.  Therefore we do not test the residual
        # at these ends, only in between, by zeroing the bad ones:
        if nn > 1:
            exclude_points = nn - 1
            for c in range(3):
                if nn > 1 and not pbc[c]:
                    # get view ehere axis c refers becomes zeroth dimension:
                    X = residual.transpose(c, (c + 1) % 3, (c + 2) % 3)

                    if gd.beg_c[c] == 1:
                        X[:exclude_points] = 0.0
                    if gd.end_c[c] == gd.N_c[c]:
                        X[-exclude_points:] = 0.0
        return residual.max()

    maxerr = get_residual_err(phi_g)
    pbcstring = '{}{}{}'.format(*pbc)

    if 0:
        ps2 = FDPoissonSolver(relax='J', nn=nn, eps=1e-18)
        ps2.set_grid_descriptor(gd)
        phi2_g = gd.zeros()
        ps2.solve(phi2_g, rho_g)

        phimaxerr = np.abs(phi2_g - phi_g).max()
        maxerr2 = get_residual_err(phi2_g)
        msg = ('{:2d} {:8s} pbc={} err={:8.5e} err[J]={:8.5e} '
               'err[phi]={:8.5e} nn={:1d}'
               .format(cellno, cellname, pbcstring, maxerr, maxerr2,
                       phimaxerr, nn))

    state = 'ok' if maxerr < tolerance else 'FAIL'

    msg = ('{:2d} {:8s} grid={} pbc={} err[fast]={:8.5e} nn={:1d} {}'
           .format(cellno, cellname, N_c, pbcstring, maxerr, nn, state))
    if world.rank == 0:
        print(msg)

    return maxerr
Пример #6
0
gd = GridDescriptor((10,12,42), (4, 5, 20), pbc_c=(True,True,False))
poisson = GeneralizedLauePoissonSolver(nn=2)
poisson.set_grid_descriptor(gd)

poisson2 = FDPoissonSolver(nn=2, eps=1e-28)
poisson2.set_grid_descriptor(gd)

phi_g = gd.zeros()
phi2_g = gd.zeros()
rho_g = gd.zeros()
rho_g[4,5,6] = 1.0
rho_g[4,5,7] = -1.0

poisson.solve(phi_g, rho_g)
poisson2.solve(phi2_g, rho_g)
print("this", phi_g[4,5,:])
print("ref", phi2_g[4,5,:])
print("diff", phi_g[4,5,:]-phi2_g[4,5,:])

assert np.linalg.norm(phi_g-phi2_g) < 1e-10

gd = GridDescriptor((10,12,42), (10, 12, 42), pbc_c=(False,False,False))
poisson = NonPeriodicLauePoissonSolver(nn=1)
poisson.set_grid_descriptor(gd)
print("eigs", poisson.eigs_c[0])
poisson2 = FDPoissonSolver(nn=1, eps=1e-24)
poisson2.set_grid_descriptor(gd)

phi_g = gd.zeros()
phi2_g = gd.zeros()