From 0d9fdb9ae65451ab6c985ae47634087efd1f5461 Mon Sep 17 00:00:00 2001
From: Chloe Mimeau <Chloe.Mimeau@imag.fr>
Date: Fri, 15 Mar 2013 10:29:21 +0000
Subject: [PATCH] 2D poisson solver included in Parmes

---
 HySoP/hysop/f2py/fftw2py.f90                  |   3 +
 HySoP/hysop/operator/diffusion_fft.py         |  47 ++++----
 HySoP/hysop/operator/poisson_fft.py           |  37 +++---
 .../operator/tests/test_diff_poisson_3D.py    | 107 ++++++++++++++++++
 HySoP/hysop/operator/tests/test_poisson_2D.py |  76 +++++++++++++
 5 files changed, 238 insertions(+), 32 deletions(-)
 create mode 100755 HySoP/hysop/operator/tests/test_diff_poisson_3D.py
 create mode 100755 HySoP/hysop/operator/tests/test_poisson_2D.py

diff --git a/HySoP/hysop/f2py/fftw2py.f90 b/HySoP/hysop/f2py/fftw2py.f90
index 8d63c42df..91ed3efa1 100755
--- a/HySoP/hysop/f2py/fftw2py.f90
+++ b/HySoP/hysop/f2py/fftw2py.f90
@@ -71,13 +71,16 @@ contains
   subroutine solve_poisson_2d(omega,velocity_x,velocity_y)
     real(pk),dimension(:,:),intent(in):: omega
     real(pk),dimension(size(omega,1),size(omega,2)),intent(out) :: velocity_x,velocity_y
+    real(pk) :: start
     !f2py intent(in,out) :: velocity_x,velocity_y
+    start = MPI_WTime()
 
     call r2c_2d(omega)
     
     call filter_poisson_2d()
 
     call c2r_2d(velocity_x,velocity_y)
+    print *, "fortran resolution time : ", MPI_WTime() - start
   
   end subroutine solve_poisson_2d
 
diff --git a/HySoP/hysop/operator/diffusion_fft.py b/HySoP/hysop/operator/diffusion_fft.py
index b13a06f65..03cbbec63 100644
--- a/HySoP/hysop/operator/diffusion_fft.py
+++ b/HySoP/hysop/operator/diffusion_fft.py
@@ -33,6 +33,7 @@ class DiffusionFFT(DiscreteOperator):
             self.diff.discreteFieldId[self.diff.vorticity]]
         ## Viscosity.
         self.viscosity = viscosity
+        self.domain = self.diff.domain
         ## Boolean : pure vort diffusion or curl(u) + vort diffusion.
         self.with_curl = with_curl
         self.compute_time = 0.
@@ -48,27 +49,35 @@ class DiffusionFFT(DiscreteOperator):
         """
         self.compute_time = time.time()
 
-        if self.with_curl:
-
-            self.vorticity.data[0], \
-            self.vorticity.data[1], \
-            self.vorticity.data[2] = \
-                fftw2py.solve_curl_diffusion_3d(self.viscosity * dt,
-                                                self.velocity.data[0],
-                                                self.velocity.data[1],
-                                                self.velocity.data[2],
-                                                self.vorticity.data[0],
-                                                self.vorticity.data[1],
-                                                self.vorticity.data[2])
+        if (self.domain.dimension == 2):
+
+            raise ValueError("Not yet implemented")
+
+        elif (self.domain.dimension == 3):
+
+            if self.with_curl:
+                self.vorticity.data[0], \
+                self.vorticity.data[1], \
+                self.vorticity.data[2] = \
+                    fftw2py.solve_curl_diffusion_3d(self.viscosity * dt,
+                                                    self.velocity.data[0],
+                                                    self.velocity.data[1],
+                                                    self.velocity.data[2],
+                                                    self.vorticity.data[0],
+                                                    self.vorticity.data[1],
+                                                    self.vorticity.data[2])
+
+            else:
+                self.vorticity.data[0], \
+                self.vorticity.data[1], \
+                self.vorticity.data[2] = \
+                    fftw2py.solve_diffusion_3d(self.viscosity * dt,
+                                               self.vorticity.data[0],
+                                               self.vorticity.data[1],
+                                               self.vorticity.data[2])
 
         else:
-            self.vorticity.data[0], \
-            self.vorticity.data[1], \
-            self.vorticity.data[2] = \
-                fftw2py.solve_diffusion_3d(self.viscosity * dt,
-                                           self.vorticity.data[0],
-                                           self.vorticity.data[1],
-                                           self.vorticity.data[2])
+            raise ValueError("invalid problem dimension")
 
 
 #        ind0a = self.topology.mesh.local_start[0]
diff --git a/HySoP/hysop/operator/poisson_fft.py b/HySoP/hysop/operator/poisson_fft.py
index d3d85b8ac..fdbf2b62f 100644
--- a/HySoP/hysop/operator/poisson_fft.py
+++ b/HySoP/hysop/operator/poisson_fft.py
@@ -15,7 +15,7 @@ class PoissonFFT(DiscreteOperator):
     """
 
     @debug
-    def __init__(self, poisson, method='', domain=None):
+    def __init__(self, poisson, method=''):
         """
         Constructor.
         @param velocity : descretized velocity to update from vorticity.
@@ -31,7 +31,7 @@ class PoissonFFT(DiscreteOperator):
         self.vorticity = self.poisson.vorticity.discreteField[
             self.poisson.discreteFieldId[self.poisson.vorticity]]
         self.method = method
-        self.domain = domain
+        self.domain = self.poisson.domain
         self.compute_time = 0.
 
     @debug
@@ -51,21 +51,32 @@ class PoissonFFT(DiscreteOperator):
         self.compute_time = time.time()
 
         #=== RECOVER VELOCITY FIELD FROM VORTICITY FIELD ===
-        self.velocity.data[0],\
-        self.velocity.data[1],\
-        self.velocity.data[2] = \
-            fftw2py.solve_poisson_3d(self.vorticity.data[0],
-                                     self.vorticity.data[1],
-                                     self.vorticity.data[2],
-                                     self.velocity.data[0],
-                                     self.velocity.data[1],
-                                     self.velocity.data[2])
+        if (self.domain.dimension == 2):
+            self.velocity.data[0],\
+            self.velocity.data[1] =\
+                fftw2py.solve_poisson_2d(self.vorticity.data,
+                                        self.velocity.data[0],
+                                        self.velocity.data[1])
+
+        elif (self.domain.dimension == 3):
+            self.velocity.data[0],\
+            self.velocity.data[1],\
+            self.velocity.data[2] = \
+                fftw2py.solve_poisson_3d(self.vorticity.data[0],
+                                        self.vorticity.data[1],
+                                        self.vorticity.data[2],
+                                        self.velocity.data[0],
+                                        self.velocity.data[1],
+                                        self.velocity.data[2])
+
+        else:
+            raise ValueError("invalid problem dimension")
 
 
         #============== VELOCITY CORRECTION ================
 
-        surf = (self.domain.length[1]-self.domain.origin[1]) * \
-               (self.domain.length[2]-self.domain.origin[2])
+#        surf = (self.domain.length[1]-self.domain.origin[1]) * \
+#               (self.domain.length[2]-self.domain.origin[2])
 
         #============= CORRECTION VEL X : u_x ==============
 
diff --git a/HySoP/hysop/operator/tests/test_diff_poisson_3D.py b/HySoP/hysop/operator/tests/test_diff_poisson_3D.py
new file mode 100755
index 000000000..4e9698a3c
--- /dev/null
+++ b/HySoP/hysop/operator/tests/test_diff_poisson_3D.py
@@ -0,0 +1,107 @@
+# -*- coding: utf-8 -*-
+import time
+
+import parmepy as pp
+import numpy as np
+from parmepy.constants import PARMES_REAL, ORDER
+from parmepy.fields.analytical import AnalyticalField
+from parmepy.operator.poisson import Poisson
+from parmepy.operator.diffusion import Diffusion
+from parmepy.problem.navier_stokes import NSProblem
+from parmepy.operator.monitors.energy_enstrophy import Energy_enstrophy
+from math import sqrt, pi, exp
+
+
+def computeVel(x, y, z):
+    vx = 0.
+    vy = 0.
+    vz = 0.
+    return vx, vy, vz
+
+def computeVort(x, y, z):
+    xc = 1. / 2.
+    yc = 1. / 2.
+    zc = 1. / 4.
+    R = 0.2
+    sigma = R / 2.
+    Gamma = 0.0075
+    dist = sqrt((x-xc) ** 2 + (y-yc) ** 2)
+    s2 = (z - zc) ** 2 + (dist - R) ** 2
+    wx = 0.
+    wy = 0.
+    wz = 0.
+    if (dist != 0.):
+        cosTheta = (x - xc) / dist
+        sinTheta = (y - yc) / dist
+        wTheta = Gamma / (pi * sigma ** 2) * \
+                 exp(-(s2 / sigma ** 2))
+        wx = - wTheta * sinTheta
+        wy = wTheta * cosTheta
+        wz = 0.
+    return wx, wy, wz
+
+def test_Diff_Poisson():
+    # Parameters
+    nb = 65
+    dim = 3
+    boxLength = [1., 1., 1.]
+    boxMin = [0., 0., 0.]
+    nbElem = [nb, nb, nb]
+
+    timeStep = 0.01
+    finalTime = 150 * timeStep
+    outputFilePrefix = './Energies'
+    outputModulo = 10
+
+    t0 = time.time()
+
+    ## Domain
+    box = pp.Box(dim, length=boxLength, origin=boxMin)
+
+    ## Fields
+    velo = AnalyticalField(domain=box, formula=computeVel, 
+                           name='Velocity', vector=True)
+    vorti = AnalyticalField(domain=box, formula=computeVort, 
+                            name='Vorticity', vector=True)
+
+    ## FFT Diffusion operators and FFT Poisson solver
+    diffusion = Diffusion(velo, vorti,
+                          resolutions={velo: nbElem,
+                                       vorti: nbElem},
+                          method='',
+                          viscosity=0.002, 
+                          with_curl=False
+                         )
+
+    poisson = Poisson(velo, vorti,
+                      resolutions={velo: nbElem,
+                                   vorti: nbElem},
+                      method=''
+                     )
+
+    ## Problem
+    pb = NSProblem([diffusion, poisson],
+                    monitors=[Energy_enstrophy(
+                                fields=[velo, vorti],
+                                frequency=outputModulo,
+                                outputPrefix=outputFilePrefix)])
+
+
+    ## Setting solver to Problem
+    pb.setUp(finalTime, timeStep)
+
+    t1 = time.time()
+
+    ## Solve problem
+    timings = pb.solve()
+
+    tf = time.time()
+
+    print "\n"
+    print "Total time : ", tf - t0, "sec (CPU)"
+    print "Init time : ", t1 - t0, "sec (CPU)"
+    print "Solving time : ", tf - t1, "sec (CPU)"
+
+
+if __name__ == "__main__":
+    test_Diff_Poisson()
diff --git a/HySoP/hysop/operator/tests/test_poisson_2D.py b/HySoP/hysop/operator/tests/test_poisson_2D.py
new file mode 100755
index 000000000..ab0c362c9
--- /dev/null
+++ b/HySoP/hysop/operator/tests/test_poisson_2D.py
@@ -0,0 +1,76 @@
+# -*- coding: utf-8 -*-
+import time
+
+import parmepy as pp
+import numpy as np
+from parmepy.constants import PARMES_REAL, ORDER
+from parmepy.fields.analytical import AnalyticalField
+from parmepy.operator.poisson import Poisson
+from parmepy.operator.diffusion import Diffusion
+from parmepy.problem.navier_stokes import NSProblem
+from parmepy.operator.monitors.energy_enstrophy import Energy_enstrophy
+from math import sqrt, pi, exp
+
+
+def computeVel(x, y):
+    vx = 0.
+    vy = 0.
+    return vx, vy
+
+def computeVort(x, y):
+    w = np.cos(y) * np.cos(x)
+    return w
+
+def test_Diff_Poisson():
+    # Parameters
+    nb = 65
+    dim = 2
+    boxLength = [1., 1.]
+    boxMin = [0., 0.]
+    nbElem = [nb, nb]
+
+    timeStep = 0.01
+    finalTime = 150 * timeStep
+    outputFilePrefix = './Energies'
+    outputModulo = 10
+
+    t0 = time.time()
+
+    ## Domain
+    box = pp.Box(dim, length=boxLength, origin=boxMin)
+
+    ## Fields
+    velo = AnalyticalField(domain=box, formula=computeVel, 
+                           name='Velocity', vector=True)
+    vorti = AnalyticalField(domain=box, formula=computeVort, 
+                            name='Vorticity', vector=False)
+
+    ## FFT Poisson solver
+    poisson = Poisson(velo, vorti,
+                      resolutions={velo: nbElem,
+                                   vorti: nbElem},
+                      method=''
+                     )
+
+    ## Problem
+    pb = NSProblem([poisson])
+
+
+    ## Setting solver to Problem
+    pb.setUp(finalTime, timeStep)
+
+    t1 = time.time()
+
+    ## Solve problem
+    timings = pb.solve()
+
+    tf = time.time()
+
+    print "\n"
+    print "Total time : ", tf - t0, "sec (CPU)"
+    print "Init time : ", t1 - t0, "sec (CPU)"
+    print "Solving time : ", tf - t1, "sec (CPU)"
+
+
+if __name__ == "__main__":
+    test_Diff_Poisson()
-- 
GitLab