Esempio n. 1
0
    def load(self, method):
        """Make sure all necessary attributes have been initialized"""

        assert method in ('real', 'recip_gauss', 'recip_ewald'),\
            str(method) + ' is an invalid method name,\n' +\
            'use either real, recip_gauss, or recip_ewald'

        if method.startswith('recip'):
            if self.gd.comm.size > 1:
                raise RuntimeError("Cannot do parallel FFT, use method='real'")
            if not hasattr(self, 'k2'):
                self.k2, self.N3 = construct_reciprocal(self.gd)
            if method.endswith('ewald') and not hasattr(self, 'ewald'):
                # cutoff radius
                assert self.gd.orthogonal
                rc = 0.5 * np.average(self.gd.cell_cv.diagonal())
                # ewald potential: 1 - cos(k rc)
                self.ewald = (np.ones(self.gd.n_c) -
                              np.cos(np.sqrt(self.k2) * rc))
                # lim k -> 0 ewald / k2
                self.ewald[0, 0, 0] = 0.5 * rc**2
            elif method.endswith('gauss') and not hasattr(self, 'ng'):
                gauss = Gaussian(self.gd)
                self.ng = gauss.get_gauss(0) / sqrt(4 * pi)
                self.vg = gauss.get_gauss_pot(0) / sqrt(4 * pi)
        else:  # method == 'real'
            if not hasattr(self, 'solve'):
                if self.poisson is not None:
                    self.solve = self.poisson.solve
                else:
                    solver = PoissonSolver(nn=2)
                    solver.set_grid_descriptor(self.gd)
                    solver.initialize(load_gauss=True)
                    self.solve = solver.solve
Esempio n. 2
0
 def initialize(self, gd, load_gauss=False):
     # XXX this won't work now, but supposedly this class will be deprecated
     # in favour of FFTPoissonSolver, no?
     self.gd = gd
     if self.gd.comm.size > 1:
         raise RuntimeError('Cannot do parallel FFT.')
     self.k2, self.N3 = construct_reciprocal(self.gd)
     if load_gauss:
         gauss = Gaussian(self.gd)
         self.rho_gauss = gauss.get_gauss(0)
         self.phi_gauss = gauss.get_gauss_pot(0)
Esempio n. 3
0
 def initialize(self, gd, load_gauss=False):
     # XXX this won't work now, but supposedly this class will be deprecated
     # in favour of FFTPoissonSolver, no?
     self.gd = gd
     if self.gd.comm.size > 1:
         raise RuntimeError('Cannot do parallel FFT.')
     self.k2, self.N3 = construct_reciprocal(self.gd)
     if load_gauss:
         gauss = Gaussian(self.gd)
         self.rho_gauss = gauss.get_gauss(0)
         self.phi_gauss = gauss.get_gauss_pot(0)
Esempio n. 4
0
    def load_gauss(self, center=None):
        """Load compensating charge distribution for charged systems.

        See Appendix B of
        A. Held and M. Walter, J. Chem. Phys. 141, 174108 (2014).
        """
        # XXX Check if update is needed (dielectric changed)?
        epsr, dx_epsr, dy_epsr, dz_epsr = self.dielectric.eps_gradeps
        gauss = Gaussian(self.gd, center=center)
        rho_g = gauss.get_gauss(0)
        phi_g = gauss.get_gauss_pot(0)
        x, y, z = gauss.xyz
        fac = 2. * np.sqrt(gauss.a) * np.exp(-gauss.a * gauss.r2)
        fac /= np.sqrt(np.pi) * gauss.r2
        fac -= erf(np.sqrt(gauss.a) * gauss.r) / (gauss.r2 * gauss.r)
        fac *= 2.0 * 1.7724538509055159
        dx_phi_g = fac * x
        dy_phi_g = fac * y
        dz_phi_g = fac * z
        sp = dx_phi_g * dx_epsr + dy_phi_g * dy_epsr + dz_phi_g * dz_epsr
        rho = epsr * rho_g - 1. / (4. * np.pi) * sp
        invnorm = np.sqrt(4. * np.pi) / self.gd.integrate(rho)
        self.phi_gauss = phi_g * invnorm
        self.rho_gauss = rho * invnorm
Esempio n. 5
0
Nc = (N, N, N)  # Number of grid points along each axis
gd = GridDescriptor(Nc, (a, a, a), 0)  # Grid-descriptor object
solver = PoissonSolver(nn=3)  # Numerical poisson solver
solver.set_grid_descriptor(gd)
solve = solver.solve
xyz, r2 = coordinates(gd)  # Matrix with the square of the radial coordinate
print(r2.shape)
r = np.sqrt(r2)  # Matrix with the values of the radial coordinate
nH = np.exp(-2 * r) / pi  # Density of the hydrogen atom
gauss = Gaussian(gd)  # An instance of Gaussian

# /------------------------------------------------\
# | Check if Gaussian densities are made correctly |
# \------------------------------------------------/
for gL in range(2, 9):
    g = gauss.get_gauss(gL)  # a gaussian of gL'th order
    print('\nGaussian of order', gL)
    for mL in range(9):
        m = gauss.get_moment(g, mL)  # the mL'th moment of g
        print('  %s\'th moment = %2.6f' % (mL, m))
        equal(m, gL == mL, 1e-4)

# Check the moments of the constructed 1s density
print('\nDensity of Hydrogen atom')
for L in range(4):
    m = gauss.get_moment(nH, L)
    print('  %s\'th moment = %2.6f' % (L, m))
    equal(m, (L == 0) / sqrt(4 * pi), 1.5e-3)

# Check that it is removed correctly
v = gauss.remove_moment(nH, 0)
Esempio n. 6
0
 def load_gauss(self):
     if not hasattr(self, 'rho_gauss'):
         gauss = Gaussian(self.gd)
         self.rho_gauss = gauss.get_gauss(0)
         self.phi_gauss = gauss.get_gauss_pot(0)
gd = GridDescriptor(Nc, (a, a, a), 0)  # Grid-descriptor object
solver = PoissonSolver(nn=3)  # Numerical poisson solver
solver.set_grid_descriptor(gd)
solver.initialize()
solve = solver.solve
xyz, r2 = coordinates(gd)  # Matrix with the square of the radial coordinate
print(r2.shape)
r = np.sqrt(r2)  # Matrix with the values of the radial coordinate
nH = np.exp(-2 * r) / pi  # Density of the hydrogen atom
gauss = Gaussian(gd)  # An instance of Gaussian

# /------------------------------------------------\
# | Check if Gaussian densities are made correctly |
# \------------------------------------------------/
for gL in range(2, 9):
    g = gauss.get_gauss(gL)  # a gaussian of gL'th order
    print("\nGaussian of order", gL)
    for mL in range(9):
        m = gauss.get_moment(g, mL)  # the mL'th moment of g
        print("  %s'th moment = %2.6f" % (mL, m))
        equal(m, gL == mL, 1e-4)

# Check the moments of the constructed 1s density
print("\nDensity of Hydrogen atom")
for L in range(4):
    m = gauss.get_moment(nH, L)
    print("  %s'th moment = %2.6f" % (L, m))
    equal(m, (L == 0) / sqrt(4 * pi), 1.5e-3)

# Check that it is removed correctly
v = gauss.remove_moment(nH, 0)
Esempio n. 8
0
 def load_gauss(self, center=None):
     if not hasattr(self, 'rho_gauss') or center is not None:
         gauss = Gaussian(self.gd, center=center)
         self.rho_gauss = gauss.get_gauss(0)
         self.phi_gauss = gauss.get_gauss_pot(0)
Esempio n. 9
0
# solver = HelmholtzSolver(0.16)  # Numerical poisson solver
solver.set_grid_descriptor(gd)
solver.initialize()
xyz, r2 = coordinates(gd)     # Matrix with the square of the radial coordinate
gauss = Gaussian(gd, a=inv_width)          # An instance of Gaussian
test_screened_poisson = ScreenedPoissonGaussian(gd, a=inv_width)

# /-------------------------------------------------\
# | Check if Gaussian potentials are made correctly |
# \-------------------------------------------------/

# Array for storing the potential
pot = gd.zeros(dtype=float, global_array=False)
solver.load_gauss()
vg = test_screened_poisson.get_phi(-coupling)  # esp. for dampening
# Get analytic functions
ng = gauss.get_gauss(0)
#    vg = solver.phi_gauss
# Solve potential numerically
niter = solver.solve(pot, ng, charge=None, zero_initial_phi=True)
# Determine residual
# residual = norm(pot - vg)
residual = gd.integrate((pot - vg)**2)**0.5

    # print result
print 'residual %s'%(
    residual)
assert residual < 0.003

# mpirun -np 2 python gauss_func.py --gpaw-parallel --gpaw-debug
Esempio n. 10
0
 def load_gauss(self):
     if not hasattr(self, 'rho_gauss'):
         gauss = Gaussian(self.gd)
         self.rho_gauss = gauss.get_gauss(0)
         self.phi_gauss = gauss.get_gauss_pot(0)
Esempio n. 11
0
psolvers = (WeightedFDPoissonSolver, ADM12PoissonSolver,
            PolarizationPoissonSolver)

# test neutral system with constant permittivity
parprint('neutral, constant permittivity')
epsinf = 80.
eps = gd.zeros()
eps.fill(epsinf)
qs = (-1., 1.)
shifts = (-1., 1.)
rho = gd.zeros()
phi_expected = gd.zeros()
for q, shift in zip(qs, shifts):
    gauss_norm = q / np.sqrt(4 * np.pi)
    gauss = Gaussian(gd, center=(box / 2. + shift) * np.ones(3) / Bohr)
    rho += gauss_norm * gauss.get_gauss(0)
    phi_expected += gauss_norm * gauss.get_gauss_pot(0) / epsinf

for ps in psolvers:
    phi = solve(ps, eps, rho)
    parprint(ps, np.abs(phi - phi_expected).max())
    equal(phi, phi_expected, 1e-3)

# test charged system with constant permittivity
parprint('charged, constant permittivity')
epsinf = 80.
eps = gd.zeros()
eps.fill(epsinf)
q = -2.
gauss_norm = q / np.sqrt(4 * np.pi)
gauss = Gaussian(gd, center=(box / 2. + 1.) * np.ones(3) / Bohr)
Esempio n. 12
0
Nc = (N, N, N)                # Number of grid points along each axis
gd = GridDescriptor(Nc, (a, a, a), 0)    # Grid-descriptor object
solver = PoissonSolver(nn=3, use_charge_center=True)
solver.set_grid_descriptor(gd)
solver.initialize()
gauss = Gaussian(gd, a=inv_width, center=center_of_charge)
test_poisson = Gaussian(gd, a=inv_width, center=center_of_charge)

# /-------------------------------------------------\
# | Check if Gaussian potentials are made correctly |
# \-------------------------------------------------/

# Array for storing the potential
pot = gd.zeros(dtype=float, global_array=False)
solver.load_gauss()
vg = test_poisson.get_gauss_pot(0)
# Get analytic functions
ng = gauss.get_gauss(0)
#    vg = solver.phi_gauss
# Solve potential numerically
niter = solver.solve(pot, ng, charge=1.0, zero_initial_phi=False)
# Determine residual
# residual = norm(pot - vg)
residual = gd.integrate((pot - vg)**2)**0.5

print('residual %s' % (
    residual))
assert residual < 1e-5  # Better than 5.x

# mpirun -np 2 python gauss_func.py --gpaw-parallel --gpaw-debug