Example #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
Example #2
0
    def __init__(self, nn=3, relax='J', eps=2e-10, maxiter=1000,
                 moment_corrections=None,
                 extended=None,
                 timer=nulltimer):

        FDPoissonSolver.__init__(self, nn=nn, relax=relax,
                                 eps=eps, maxiter=maxiter,
                                 remove_moment=None)

        self.timer = timer

        if moment_corrections is None:
            self.moment_corrections = None
        elif isinstance(moment_corrections, int):
            self.moment_corrections = [{'moms': range(moment_corrections),
                                        'center': None}]
        else:
            self.moment_corrections = moment_corrections

        self.is_extended = False
        # Broadcast over band, kpt, etc. communicators required?
        self.requires_broadcast = False
        if extended is not None:
            self.is_extended = True
            self.extended = extended
            assert 'gpts' in extended.keys(), 'gpts parameter is missing'
            self.extended['gpts'] = np.array(self.extended['gpts'])
            # Multiply gpts by 2 to get gpts on fine grid
            self.extended['finegpts'] = self.extended['gpts'] * 2
            assert 'useprev' in extended.keys(), 'useprev parameter is missing'
            if self.extended.get('comm') is not None:
                self.requires_broadcast = True
Example #3
0
 def estimate_memory(self, mem):
     FDPoissonSolver.estimate_memory(self, mem)
     gdbytes = self.gd.bytecount()
     if self.is_extended:
         mem.subnode('extended arrays', 2 * gdbytes)
     if self.moment_corrections is not None:
         mem.subnode('moment_corrections masks',
                     len(self.moment_corrections) * gdbytes)
Example #4
0
 def set_grid_descriptor(self, gd):
     if self.is_extended:
         self.gd_original = gd
         assert np.all(self.gd_original.N_c <= self.extended['finegpts']), \
             'extended grid has to be larger than the original one'
         gd, _, _ = extended_grid_descriptor(
             gd,
             N_c=self.extended['finegpts'],
             extcomm=self.extended.get('comm'))
     FDPoissonSolver.set_grid_descriptor(self, gd)
Example #5
0
 def __init__(self,
              k2=0.0,
              nn='M',
              relax='GS',
              eps=2e-10,
              use_charge_center=True):
     assert k2 <= 0, 'Currently only defined for k^2<=0'
     FDPoissonSolver.__init__(self,
                              nn,
                              relax,
                              eps,
                              use_charge_center=use_charge_center)
     self.k2 = k2
Example #6
0
    def initialize(self, load_gauss=False):
        FDPoissonSolver.initialize(self, load_gauss=load_gauss)

        if self.is_extended:
            if not self.gd.orthogonal or self.gd.pbc_c.any():
                raise NotImplementedError('Only orthogonal unit cells' +
                                          'and non-periodic boundary' +
                                          'conditions are tested')
            self.rho_g = self.gd.zeros()
            self.phi_g = self.gd.zeros()

        if self.moment_corrections is not None:
            if not self.gd.orthogonal or self.gd.pbc_c.any():
                raise NotImplementedError('Only orthogonal unit cells' +
                                          'and non-periodic boundary' +
                                          'conditions are tested')
            self.load_moment_corrections_gauss()
Example #7
0
 def __init__(self,
              nn=3,
              relax='J',
              eps=2e-10,
              maxiter=1000,
              remove_moment=None,
              use_charge_center=True):
     if remove_moment is not None:
         raise NotImplementedError(
             'Removing arbitrary multipole moments '
             'is not implemented for SolvationPoissonSolver!')
     FDPoissonSolver.__init__(self,
                              nn,
                              relax,
                              eps,
                              maxiter,
                              remove_moment,
                              use_charge_center=use_charge_center)
Example #8
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)
Example #9
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)
Example #10
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
Example #11
0
    def get_description(self):
        description = FDPoissonSolver.get_description(self)

        lines = [description]

        if self.is_extended:
            lines.extend(['    Extended %d*%d*%d grid' % tuple(self.gd.N_c)])
            lines.extend(['    Use previous is %s' % self.extended['useprev']])

        if self.moment_corrections:
            lines.extend(
                ['    %d moment corrections:' % len(self.moment_corrections)])
            lines.extend([
                '      %s' %
                ('[%s] %s' %
                 ('center' if mom['center'] is None else
                  (', '.join(['%.2f' % (x * Bohr)
                              for x in mom['center']])), mom['moms']))
                for mom in self.moment_corrections
            ])

        return '\n'.join(lines)
Example #12
0
import numpy as np
from ase import Atoms
from gpaw import GPAW
from gpaw.lrtddft import LrTDDFT
from gpaw.inducedfield.inducedfield_lrtddft import LrTDDFTInducedField
from gpaw.poisson import FDPoissonSolver
from gpaw.test import equal

do_print_values = False  # Use this for printing the reference values
poisson_eps = 1e-12
density_eps = 1e-6

# 0) PoissonSolver
poissonsolver = FDPoissonSolver(eps=poisson_eps)

# 1) Ground state calculation with empty states
atoms = Atoms(symbols='Na2', positions=[(0, 0, 0), (3.0, 0, 0)], pbc=False)
atoms.center(vacuum=3.0)

calc = GPAW(nbands=20,
            h=0.6,
            setups={'Na': '1'},
            poissonsolver=poissonsolver,
            experimental={'niter_fixdensity': 2},
            convergence={'density': density_eps})
atoms.set_calculator(calc)
energy = atoms.get_potential_energy()
calc.write('na2_gs_casida.gpw', mode='all')

# 2) Casida calculation
calc = GPAW('na2_gs_casida.gpw')
Example #13
0
 def load_gauss(self, center=None):
     return FDPoissonSolver.load_gauss(self, center=center)
Example #14
0
from gpaw.poisson import NonPeriodicLauePoissonSolver, GeneralizedLauePoissonSolver, FDPoissonSolver, idst2, dst2
from gpaw.grid_descriptor import GridDescriptor
import numpy as np

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)
Example #15
0
from __future__ import print_function
import numpy as np
from ase.build import molecule

from gpaw import GPAW
from gpaw.poisson import FDPoissonSolver
from gpaw.lcao.projected_wannier import get_lcao_projections_HSP

atoms = molecule('C2H2')
atoms.center(vacuum=3.0)
calc = GPAW(gpts=(32, 32, 48),
            experimental={'niter_fixdensity': 2},
            poissonsolver=FDPoissonSolver(),
            eigensolver='rmm-diis')
atoms.set_calculator(calc)
atoms.get_potential_energy()

V_qnM, H_qMM, S_qMM, P_aqMi = get_lcao_projections_HSP(calc,
                                                       bfs=None,
                                                       spin=0,
                                                       projectionsonly=False)

# Test H and S
eig = sorted(np.linalg.eigvals(np.linalg.solve(S_qMM[0], H_qMM[0])).real)
eig_ref = np.array([
    -17.879390089021275, -13.248786165187855, -11.431259875271436,
    -7.125783046831621, -7.125783046831554, 0.5927193710189584,
    0.5927193710191426, 3.9251078324544673, 7.450995963662965,
    26.734277387029234
])
print(eig)
Example #16
0
    p.set_grid_descriptor(gd)
    cut = N / 2.0 * 0.9
    s = Spline(l=0, rmax=cut, f_g=np.array([1, 0.5, 0.0]))
    c = LFC(gd, [[s], [s]])
    c.set_positions([(0, 0, 0), (0.5, 0.5, 0.5)])
    c.add(a)

    I0 = gd.integrate(a)
    a -= I0 / L**3

    b = gd.zeros()
    p.solve(b, a, charge=0, eps=1e-20)
    return gd.collect(b, broadcast=1)


b1 = f(8, FDPoissonSolver(nn=1, relax='J'))
b2 = f(8, FDPoissonSolver(nn=1, relax='GS'))
b3 = f(8, PoissonSolver(nn=1))
err1 = abs(b1[0, 0, 0] - b1[8, 8, 8])
err2 = abs(b2[0, 0, 0] - b2[8, 8, 8])
err3 = abs(b1[0, 0, 0] - b3[8, 8, 8])
print(err1)
print(err2)
print(err3)
assert err3 < 1e-10
assert err1 < 6e-16
assert err2 < 3e-6  # XXX Shouldn't this be better?

b4 = f(8, FFTPoissonSolver())
err4 = abs(b4[0, 0, 0] - b4[8, 8, 8])
print(err4)
Example #17
0
from gpaw.test import equal, gen

# Generate setup for oxygen with half a core-hole:
gen('O', name='hch1s', corehole=(1, 0, 0.5))

a = 5.0
d = 0.9575
t = pi / 180 * 104.51
H2O = Atoms([Atom('O', (0, 0, 0)),
             Atom('H', (d, 0, 0)),
             Atom('H', (d * cos(t), d * sin(t), 0))],
            cell=(a, a, a), pbc=False)
H2O.center()
calc = GPAW(nbands=10, h=0.2, setups={'O': 'hch1s'},
            experimental={'niter_fixdensity': 2},
            poissonsolver=FDPoissonSolver(use_charge_center=True))
H2O.set_calculator(calc)
e = H2O.get_potential_energy()
niter = calc.get_number_of_iterations()

import gpaw.mpi as mpi

if mpi.size == 1:
    xas = XAS(calc)
    x, y = xas.get_spectra()
    e1_n = xas.eps_n
    de1 = e1_n[1] - e1_n[0]

calc.write('h2o-xas.gpw')

if mpi.size == 1:
Example #18
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
Example #19
0
def poisson_solve(gd, rho_g, poisson):
    phi_g = gd.zeros()
    npoisson = poisson.solve(phi_g, rho_g)
    return phi_g, npoisson


def compare(phi1_g, phi2_g, val):
    big_phi1_g = gd.collect(phi1_g)
    big_phi2_g = gd.collect(phi2_g)
    if gd.comm.rank == 0:
        equal(np.max(np.absolute(big_phi1_g - big_phi2_g)), val,
              np.sqrt(poissoneps))


# Get reference from default poissonsolver
poisson = PoissonSolver(eps=poissoneps)
poisson.set_grid_descriptor(gd)
phiref_g, npoisson = poisson_solve(gd, rho_g, poisson)

# Test agreement with default
poisson = ExtendedPoissonSolver(eps=poissoneps)
poisson.set_grid_descriptor(gd)
phi_g, npoisson = poisson_solve(gd, rho_g, poisson)
plot_phi(phi_g)
compare(phi_g, phiref_g, 0.0)

# Test moment_corrections=int
poisson = ExtendedPoissonSolver(eps=poissoneps, moment_corrections=4)
poisson.set_grid_descriptor(gd)
phi_g, npoisson = poisson_solve(gd, rho_g, poisson)
plot_phi(phi_g)