From 0a8c01374c4bd18f1f685beece4923d6c3b898af Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Franck=20P=C3=A9rignon?= <franck.perignon@imag.fr>
Date: Wed, 22 May 2013 13:14:39 +0000
Subject: [PATCH] Update obstacles + 'plates' in 2D domain and update
 penalization example

---
 Examples/testPenalization.py                  |  15 ++-
 HySoP/hysop/domain/obstacle/cylinder2d.py     | 118 +++++++++---------
 HySoP/hysop/domain/obstacle/plates.py         |  17 ++-
 HySoP/hysop/domain/obstacle/sphere.py         |  33 ++---
 HySoP/hysop/operator/discrete/penalization.py |   2 +-
 5 files changed, 99 insertions(+), 86 deletions(-)

diff --git a/Examples/testPenalization.py b/Examples/testPenalization.py
index 41a63ac12..7aebc8612 100644
--- a/Examples/testPenalization.py
+++ b/Examples/testPenalization.py
@@ -4,7 +4,7 @@ from parmepy.fields.continuous import Field
 from parmepy.operator.analytic import Analytic
 from parmepy.domain.obstacle.sphere import Sphere, HemiSphere
 from parmepy.domain.obstacle.cylinder2d import Cylinder2D, SemiCylinder2D
-from parmepy.domain.obstacle.plates import ZPlates
+from parmepy.domain.obstacle.plates import Plates
 pi = math.pi
 from parmepy.operator.penalization import Penalization
 from parmepy.operator.monitors.printer import Printer
@@ -49,24 +49,27 @@ sphere = Sphere(dom, position=[0., 0., 0.], radius=0.5, porousLayers=[0.13])
 hsphere = HemiSphere(dom, position=[0., 0., 0.],
                      radius=0.5, porousLayers=[0.13])
 
-zplates = ZPlates(dom, epsilon=0.1)
+plates = Plates(dom, normal_dir=0, epsilon=0.1)
+plates2 = Plates(dom2, normal_dir=1, epsilon=0.1)
 
 cyl = Cylinder2D(dom2, position=[0., 0.], radius=0.5, porousLayers=[0.13])
 hcyl = SemiCylinder2D(dom2, position=[0., 0.], radius=0.5, porousLayers=[0.13])
 
 ind = hsphere.discretize(topo)
 
-penal = Penalization(scal2, hcyl, coeff=[1e6, 10.],
-                     resolutions={scal: resol2D})
+penal = Penalization(scal, [hsphere, plates], coeff=[1e6, 10],
+                     resolutions={scal: resol3D})
+penal2 = Penalization(scal2, [hcyl, plates2], coeff=[1e6, 10],
+                      resolutions={scal2: resol2D})
 
 penal.setUp()
-
+penal2.setUp()
 printer = Printer(fields=[scal2], frequency=1)
 printer.setUp()
 print scal.norm()
 
 penal.apply(dt=0.1)
-
+penal2.apply(dt=0.1)
 printer.apply(ite=1)
 print "print ..."
 print scal.norm()
diff --git a/HySoP/hysop/domain/obstacle/cylinder2d.py b/HySoP/hysop/domain/obstacle/cylinder2d.py
index a9a769462..5d7f8b978 100644
--- a/HySoP/hysop/domain/obstacle/cylinder2d.py
+++ b/HySoP/hysop/domain/obstacle/cylinder2d.py
@@ -2,12 +2,12 @@
 @file cylinder2d.py
 Rigid disk.
 """
-from parmepy.domain.obstacle.obstacle import Obstacle
+from parmepy.domain.obstacle.sphere import Sphere, HemiSphere
 import math
 import numpy as np
 
 
-class Cylinder2D(Obstacle):
+class Cylinder2D(Sphere):
     """
     Disk in a 2D domain.
     """
@@ -25,14 +25,9 @@ class Cylinder2D(Obstacle):
         @param vd : velocity of the disk (considered as a rigid body),
         default = 0.
         """
-        Obstacle.__init__(self, domain, vd=vd)
+        Sphere.__init__(self, domain, position, radius, vd, porousLayers)
         assert self.domain.dimension == 2
 
-        ## Radius of the disk
-        self.radius = radius
-        ## Center position
-        self.position = np.asarray(position)
-
         def dist(x, y, R):
             """
             """
@@ -40,28 +35,27 @@ class Cylinder2D(Obstacle):
                              + (y - self.position[1]) ** 2) - R
         self.chi = [np.vectorize(dist)]
         ## List of thicknesses for porous layers
-        self.layers = porousLayers
 
-    def discretize(self, topo):
-        # first check if we have already compute indices for
-        # this topology
-        if topo not in self.ind.keys():
-            currentRadius = self.radius
-            self.ind[topo] = []
-            # for each indicator function
-            for thickness in self.layers:
-                # apply indicator function on topo local mesh
-                args = (currentRadius,)
-                condA = self.chi[0](*(topo.mesh.coords + args)) <= 0
-                args = (currentRadius - thickness,)
-                condB = self.chi[0](*(topo.mesh.coords + args)) > 0
-                self.ind[topo].append(np.logical_and(condA, condB))
-                # update current radius
-                currentRadius = currentRadius - thickness
-            # and finally the 'internal' sphere
-            args = (currentRadius,)
-            self.ind[topo].append(self.chi[0](*(topo.mesh.coords + args)) <= 0)
-        return self.ind[topo]
+    ## def discretize(self, topo):
+    ##     # first check if we have already compute indices for
+    ##     # this topology
+    ##     if topo not in self.ind.keys():
+    ##         currentRadius = self.radius
+    ##         self.ind[topo] = []
+    ##         # for each indicator function
+    ##         for thickness in self.layers:
+    ##             # apply indicator function on topo local mesh
+    ##             args = (currentRadius,)
+    ##             condA = self.chi[0](*(topo.mesh.coords + args)) <= 0
+    ##             args = (currentRadius - thickness,)
+    ##             condB = self.chi[0](*(topo.mesh.coords + args)) > 0
+    ##             self.ind[topo].append(np.logical_and(condA, condB))
+    ##             # update current radius
+    ##             currentRadius = currentRadius - thickness
+    ##         # and finally the 'internal' sphere
+    ##         args = (currentRadius,)
+    ##         self.ind[topo].append(self.chi[0](*(topo.mesh.coords + args)) <= 0)
+    ##     return self.ind[topo]
 
     def __str__(self):
         """ToString method"""
@@ -70,7 +64,7 @@ class Cylinder2D(Obstacle):
         return s
 
 
-class SemiCylinder2D(Cylinder2D):
+class SemiCylinder2D(HemiSphere):
     """
     Half disk in a 2D domain.
     """
@@ -84,38 +78,46 @@ class SemiCylinder2D(Cylinder2D):
         @param vd : velocity of the disk (considered as a rigid body),
         default = 0.
         """
-        Cylinder2D.__init__(self, domain, position, radius, vd, porousLayers)
+        HemiSphere.__init__(self, domain, position, radius, vd, porousLayers)
+        assert self.domain.dimension == 2
+
+        def dist(x, y, R):
+            """
+            """
+            return math.sqrt((x - self.position[0]) ** 2
+                             + (y - self.position[1]) ** 2) - R
+        self.chi = [np.vectorize(dist)]
 
-        def HalfPlane(x, y):
+        def LeftBox(x, y):
             return x - self.position[0]
 
-        self.HalfPlane = np.vectorize(HalfPlane)
+        self.LeftBox = np.vectorize(LeftBox)
 
-    def discretize(self, topo):
-        # first check if we have already compute indices for
-        # this topology
-        if topo not in self.ind.keys():
-            currentRadius = self.radius
-            self.ind[topo] = []
-            # First cond : we must be in the left half plane
-            cond0 = self.HalfPlane(*(topo.mesh.coords)) <= 0
-            # for each indicator function
-            for thickness in self.layers:
-                # apply indicator function on topo local mesh
-                args = (currentRadius,)
-                condA = self.chi[0](*(topo.mesh.coords + args)) <= 0
-                args = (currentRadius - thickness,)
-                condB = self.chi[0](*(topo.mesh.coords + args)) > 0
-                np.logical_and(condA, condB, condA)
-                np.logical_and(condA, cond0, condA)
-                self.ind[topo].append(condA)
-                # update current radius
-                currentRadius = currentRadius - thickness
-            # and finally the 'internal' sphere
-            args = (currentRadius,)
-            condA = self.chi[0](*(topo.mesh.coords + args)) <= 0
-            self.ind[topo].append(np.logical_and(condA, cond0))
-        return self.ind[topo]
+    ## def discretize(self, topo):
+    ##     # first check if we have already compute indices for
+    ##     # this topology
+    ##     if topo not in self.ind.keys():
+    ##         currentRadius = self.radius
+    ##         self.ind[topo] = []
+    ##         # First cond : we must be in the left half plane
+    ##         cond0 = self.HalfPlane(*(topo.mesh.coords)) <= 0
+    ##         # for each indicator function
+    ##         for thickness in self.layers:
+    ##             # apply indicator function on topo local mesh
+    ##             args = (currentRadius,)
+    ##             condA = self.chi[0](*(topo.mesh.coords + args)) <= 0
+    ##             args = (currentRadius - thickness,)
+    ##             condB = self.chi[0](*(topo.mesh.coords + args)) > 0
+    ##             np.logical_and(condA, condB, condA)
+    ##             np.logical_and(condA, cond0, condA)
+    ##             self.ind[topo].append(condA)
+    ##             # update current radius
+    ##             currentRadius = currentRadius - thickness
+    ##         # and finally the 'internal' sphere
+    ##         args = (currentRadius,)
+    ##         condA = self.chi[0](*(topo.mesh.coords + args)) <= 0
+    ##         self.ind[topo].append(np.logical_and(condA, cond0))
+    ##     return self.ind[topo]
 
     def __str__(self):
         s = '2D semi-cylinder of radius ' + str(self.radius)
diff --git a/HySoP/hysop/domain/obstacle/plates.py b/HySoP/hysop/domain/obstacle/plates.py
index fe7f54747..79632643e 100644
--- a/HySoP/hysop/domain/obstacle/plates.py
+++ b/HySoP/hysop/domain/obstacle/plates.py
@@ -6,7 +6,7 @@ from parmepy.domain.obstacle.obstacle import Obstacle
 import numpy as np
 
 
-class ZPlates(Obstacle):
+class Plates(Obstacle):
     """
     Top and down (z-axis) plate-like sub-domains.
     Defines two areas on the min and max z position of
@@ -16,7 +16,7 @@ class ZPlates(Obstacle):
     \ or \ z_{min} - \epsilon \leq z \leq z_{min}\f$
     """
 
-    def __init__(self, domain, epsilon=0.1, vd=0.0):
+    def __init__(self, domain, normal_dir, epsilon=0.1, vd=0.0):
         """
         Description of a sphere in a domain.
         @param domain : the physical domain that contains the sphere.
@@ -28,12 +28,16 @@ class ZPlates(Obstacle):
         assert epsilon > 0.0, 'Plate thickness must be positive'
         ## Thickness/2
         self.epsilon = epsilon
+        ## Direction of the normal to the plate (0:x, 1:y, 2:z))
+        self.normal = normal_dir
+        assert self.normal < domain.dimension and self.normal >= 0
 
-        def Upper(x, y, z):
-            return domain.max[-1] - self.epsilon - z
+        def Upper(*args):
+            return domain.max[self.normal] - self.epsilon - args[self.normal]
 
-        def Lower(x, y, z):
-            return z - self.epsilon - domain.origin[-1]
+        def Lower(*args):
+            return args[self.normal] - self.epsilon - \
+                domain.origin[self.normal]
 
         self.Upper = np.vectorize(Upper)
         self.Lower = np.vectorize(Lower)
@@ -56,3 +60,4 @@ class ZPlates(Obstacle):
         s = 'Upper and lower (z-axis) plane areas of thickness '
         s += str(2 * self.epsilon) + '.'
         return s
+
diff --git a/HySoP/hysop/domain/obstacle/sphere.py b/HySoP/hysop/domain/obstacle/sphere.py
index b02063b34..99fa9cb31 100644
--- a/HySoP/hysop/domain/obstacle/sphere.py
+++ b/HySoP/hysop/domain/obstacle/sphere.py
@@ -50,19 +50,20 @@ class Sphere(Obstacle):
         if topo not in self.ind.keys():
             currentRadius = self.radius
             self.ind[topo] = []
+            # First, internal sphere
+            args = (currentRadius,)
+            self.ind[topo].append(self.chi[0](*(topo.mesh.coords + args)) <= 0)
+            # Then each layer from inside to outside
             # for each indicator function
             for thickness in self.layers:
                 # apply indicator function on topo local mesh
                 args = (currentRadius,)
-                condA = self.chi[0](*(topo.mesh.coords + args)) <= 0
-                args = (currentRadius - thickness,)
-                condB = self.chi[0](*(topo.mesh.coords + args)) > 0
+                condA = self.chi[0](*(topo.mesh.coords + args)) > 0
+                args = (currentRadius + thickness,)
+                condB = self.chi[0](*(topo.mesh.coords + args)) <= 0
                 self.ind[topo].append(np.logical_and(condA, condB))
                 # update current radius
-                currentRadius = currentRadius - thickness
-            # and finally the 'internal' sphere
-            args = (currentRadius,)
-            self.ind[topo].append(self.chi[0](*(topo.mesh.coords + args)) <= 0)
+                currentRadius = currentRadius + thickness
 
         return self.ind[topo]
 
@@ -107,22 +108,24 @@ class HemiSphere(Sphere):
             self.ind[topo] = []
             # check if we are in the left half-box
             cond0 = self.LeftBox(*(topo.mesh.coords)) <= 0
+            # First, internal sphere
+            args = (currentRadius,)
+            condA = self.chi[0](*(topo.mesh.coords + args)) <= 0
+            self.ind[topo].append(np.logical_and(condA, cond0))
+            # Then each layer from inside to outside
             # for each indicator function
             for thickness in self.layers:
                 # apply indicator function on topo local mesh
                 args = (currentRadius,)
-                condA = self.chi[0](*(topo.mesh.coords + args)) <= 0
-                args = (currentRadius - thickness,)
-                condB = self.chi[0](*(topo.mesh.coords + args)) > 0
+                condA = self.chi[0](*(topo.mesh.coords + args)) > 0
+                args = (currentRadius + thickness,)
+                condB = self.chi[0](*(topo.mesh.coords + args)) <= 0
                 np.logical_and(condA, condB, condA)
                 np.logical_and(condA, cond0, condA)
                 self.ind[topo].append(condA)
                 # update current radius
-                currentRadius = currentRadius - thickness
-            # and finally the 'internal' sphere
-            args = (currentRadius,)
-            condA = self.chi[0](*(topo.mesh.coords + args)) <= 0
-            self.ind[topo].append(np.logical_and(condA, cond0))
+                currentRadius = currentRadius + thickness
+
         return self.ind[topo]
 
     def __str__(self):
diff --git a/HySoP/hysop/operator/discrete/penalization.py b/HySoP/hysop/operator/discrete/penalization.py
index a83a649cc..eeca52502 100644
--- a/HySoP/hysop/operator/discrete/penalization.py
+++ b/HySoP/hysop/operator/discrete/penalization.py
@@ -46,7 +46,7 @@ class Penalization_d(DiscreteOperator):
             else:
                 lsize = min(len(self.cond), len(cond))
                 for c in xrange(lsize):
-                    self.cond[c] = cond[c] == self.cond[c]
+                    np.logical_or(cond[c], self.cond[c], self.cond[c])
                 for c in xrange(lsize + 1, len(cond)):
                     self.cond[c] = cond[c]
         assert self.factor.size == len(self.cond)
-- 
GitLab