[gpaw-users] vdW calculations

Janne Blomqvist Janne.Blomqvist at tkk.fi
Sun Apr 4 11:12:47 CEST 2010


On Fri, Mar 26, 2010 at 01:21:39PM +0100, Jens Jørgen Mortensen wrote:
> On Fri, 2010-03-26 at 13:41 +0200, Janne Blomqvist wrote:
> > On way to slightly reduce memory consumption is to use real->complex 
> > FFT's instead of complex-complex. Jens-Jörgen posted a patch to trac, 
> > and I have a half-done effort at this lying around in my home dir, but 
> > AFAIK nothing has been committed to trunk yet.
> 
> My patch seemed to work, but I didn't have time to polish and test it
> carefully.  If someone could finish that work, that would be very
> welcome!

I have tested this a bit more (small molecule, big surface system,
pbc, no pbc with padding, relaxation), and so far the results seem to
be identical to the current implementation. I think it's ready to be
committed.

In JJ's original patch there was some unrelated cruft that I have
removed, fixed patch attached.

-- 
Janne Blomqvist
-------------- next part --------------
--- vdw.orig.py	2010-04-03 11:31:40.000000000 +0300
+++ vdw.py	2010-04-03 13:47:19.000000000 +0300
@@ -17,7 +17,7 @@ import pickle
 from math import sin, cos, exp, pi, log, sqrt, ceil
 
 import numpy as np
-from numpy.fft import fftn, fftfreq, fft, ifftn
+from numpy.fft import fft, rfftn, irfftn
 
 from gpaw.utilities.timing import nulltimer
 from gpaw.xc_functional import XCFunctional
@@ -615,7 +615,9 @@ class FFTVDWFunctional(VDWFunctional):
             
         scale_c1 = (self.shape / (1.0 * gd.N_c))[:, np.newaxis]
         gdfft = GridDescriptor(self.shape, gd.cell_cv * scale_c1, True)
-        k_k = construct_reciprocal(gdfft)[0]**0.5
+        k_k = construct_reciprocal(gdfft)[0][:,
+                                             :,
+                                             :self.shape[2] // 2 + 1]**0.5
         k_k[0, 0, 0] = 0.0
 
 
@@ -669,7 +671,7 @@ class FFTVDWFunctional(VDWFunctional):
             self.timer.stop('hmm2')
             del C_pg
             self.timer.start('FFT')
-            theta_ak[a] = fftn(n_g * pa_g, self.shape).copy()
+            theta_ak[a] = rfftn(n_g * pa_g, self.shape).copy()
             if extra_parameters.get('vdw0'):
                 theta_ak[a][0, 0, 0] = 0.0
             self.timer.stop()
@@ -694,7 +696,9 @@ class FFTVDWFunctional(VDWFunctional):
         energy = 0.0
         for a in range(N):
             ranka = a * world.size // N
-            F_k = np.zeros(self.shape, complex)
+            F_k = np.zeros((self.shape[0],
+                            self.shape[1],
+                            self.shape[2] // 2 + 1), complex)
             for b in self.alphas:
                 self.timer.start('Convolution')
                 _gpaw.vdw2(self.phi_aajp[a, b], self.j_k, dj_k,
@@ -708,7 +712,10 @@ class FFTVDWFunctional(VDWFunctional):
             if world.rank == ranka:
                 if not self.energy_only:
                     F_ak[a] = F_k
-                energy += np.vdot(theta_ak[a], F_k).real
+                energy += np.vdot(theta_ak[a][:, :, 0], F_k[:, :, 0]).real
+                energy += np.vdot(theta_ak[a][:, :, -1], F_k[:, :, -1]).real
+                energy += 2 * np.vdot(theta_ak[a][:, :, 1:-1],
+                                      F_k[:, :, 1:-1]).real
 
             if self.verbose:
                 print a,
@@ -724,7 +731,7 @@ class FFTVDWFunctional(VDWFunctional):
             for a in self.alphas:
                 n1, n2, n3 = gd.get_size_of_global_array()
                 self.timer.start('iFFT')
-                F_ag[a] = ifftn(F_ak[a]).real[:n1, :n2, :n3].copy()
+                F_ag[a] = irfftn(F_ak[a]).real[:n1, :n2, :n3].copy()
                 self.timer.stop()
 
             self.timer.start('potential')


More information about the gpaw-users mailing list