[SCM] Gerris Flow Solver branch, upstream, updated. b3aa46814a06c9cb2912790b23916ffb44f1f203

Stephane Popinet popinet at users.sf.net
Fri May 15 02:53:55 UTC 2009


The following commit has been merged in the upstream branch:
commit c1fadd48673d6317bd6174b6b01ca60dba76fdb5
Author: Stephane Popinet <popinet at users.sf.net>
Date:   Sun Aug 13 17:34:40 2006 +1000

    Periodic boundary conditions do not use connectivity
    
    This made calculating geometric relationships difficult (e.g. distance between
    cells etc...). Periodic links are now automatically replaced by a new type of
    boundary condition (GfsBoundaryPeriodic). This is also used as a base class
    for a simplified GfsBoundaryMPI implementation.
    
    This should fix the bug when using the diffusion solver with embedded solid
    boundaries combined with periodic boundary conditions.
    
    darcs-hash:20060813073440-d4795-ce386f640fadbcb77db53ef64c4ef3853d053002.gz

diff --git a/src/advection.c b/src/advection.c
index 17dc35e..b6e3450 100644
--- a/src/advection.c
+++ b/src/advection.c
@@ -513,9 +513,7 @@ void gfs_face_advected_normal_velocity (const FttCellFace * face,
   if (GFS_FACE_FRACTION (face) == 0.)
     return;
 
-  GFS_FACE_NORMAL_VELOCITY_LEFT (face) = u =
-    GFS_CELL_IS_BOUNDARY (face->neighbor) ?
-    GFS_STATE (face->neighbor)->f[FTT_OPPOSITE_DIRECTION (face->d)].v :
+  GFS_FACE_NORMAL_VELOCITY_LEFT (face) = u = 
     gfs_face_upwinded_value (face, par->upwinding, par->u);
 
   switch (ftt_face_type (face)) {
diff --git a/src/boundary.c b/src/boundary.c
index 6122d81..8ce2e57 100644
--- a/src/boundary.c
+++ b/src/boundary.c
@@ -799,8 +799,7 @@ static void gfs_boundary_inflow_constant_class_init (GtsObjectClass * klass)
   klass->color   = inflow_color;
 }
 
-static void gfs_boundary_inflow_constant_init 
-  (GfsBoundaryInflowConstant * object)
+static void gfs_boundary_inflow_constant_init (GfsBoundaryInflowConstant * object)
 {
   object->un = gfs_function_new (gfs_function_class (), 0.);
 }
@@ -884,6 +883,300 @@ GfsBoundaryOutflowClass * gfs_boundary_outflow_class (void)
   return klass;
 }
 
+/* GfsBoundaryPeriodic: object */
+
+static void boundary_periodic_destroy (GtsObject * object)
+{
+  GfsBoundaryPeriodic * boundary = GFS_BOUNDARY_PERIODIC (object);
+
+  g_array_free (boundary->sndbuf, TRUE);
+  g_array_free (boundary->rcvbuf, TRUE);
+  
+  (* GTS_OBJECT_CLASS (gfs_boundary_periodic_class ())->parent_class->destroy) 
+    (object);
+}
+
+static void boundary_periodic_read (GtsObject ** object, GtsFile * fp)
+{
+  boundary_periodic_destroy (*object);
+}
+
+static void center_periodic (FttCellFace * face, GfsBc * b)
+{
+  GfsBoundaryPeriodic * boundary_periodic = GFS_BOUNDARY_PERIODIC (b->b);
+
+  g_assert (boundary_periodic->sndcount < boundary_periodic->sndbuf->len);
+  g_assert (ftt_face_type (face) == FTT_FINE_FINE);
+  g_assert (!FTT_CELL_IS_LEAF (face->cell) || FTT_CELL_IS_LEAF (face->neighbor));
+  g_array_index (boundary_periodic->sndbuf, gdouble, boundary_periodic->sndcount++) =
+    GFS_VARIABLE (face->neighbor, b->v->i);
+}
+
+static void face_periodic (FttCellFace * face, GfsBc * b)
+{
+  GfsBoundaryPeriodic * boundary_periodic = GFS_BOUNDARY_PERIODIC (b->b);
+
+  g_assert (boundary_periodic->sndcount < boundary_periodic->sndbuf->len);
+  g_array_index (boundary_periodic->sndbuf, gdouble, boundary_periodic->sndcount++) =
+    GFS_STATE (face->neighbor)->f[FTT_OPPOSITE_DIRECTION (face->d)].v;
+}
+
+static void boundary_size (FttCell * cell, guint * count)
+{
+  (*count)++;
+}
+
+static void set_buffers_size (GfsBoundaryPeriodic * boundary)
+{
+  guint count = 0;
+
+  ftt_cell_traverse (GFS_BOUNDARY (boundary)->root, 
+		     FTT_PRE_ORDER, FTT_TRAVERSE_ALL, -1,
+		     (FttCellTraverseFunc) boundary_size, &count);
+  g_array_set_size (boundary->rcvbuf, count);
+  g_array_set_size (boundary->sndbuf, count);
+}
+
+static void boundary_tree (FttCell * cell, GfsBoundaryPeriodic * boundary)
+{
+  gdouble is_leaf = FTT_CELL_IS_LEAF (cell);
+
+  if (boundary->sndcount == boundary->sndbuf->len)
+    g_array_append_val (boundary->sndbuf, is_leaf);
+  else
+    g_array_index (boundary->sndbuf, gdouble, boundary->sndcount) = is_leaf;
+  boundary->sndcount++;
+
+  if (!is_leaf) {
+    FttCellChildren child;
+    guint i, n;
+
+    n = ftt_cell_children_direction (cell, GFS_BOUNDARY (boundary)->d, &child);
+    for (i = 0; i < n; i++) {
+      gdouble is_destroyed = (child.c[i] == NULL);
+      
+      if (boundary->sndcount == boundary->sndbuf->len)
+	g_array_append_val (boundary->sndbuf, is_destroyed);
+      else
+	g_array_index (boundary->sndbuf, gdouble, boundary->sndcount) = is_destroyed;
+      boundary->sndcount++;
+    }
+  }
+}
+
+static void periodic_match (GfsBoundary * boundary)
+{
+  (* gfs_boundary_class ()->match) (boundary);
+
+  g_assert (GFS_BOUNDARY_PERIODIC (boundary)->sndcount == 0);
+  ftt_cell_traverse (boundary->root,
+		     FTT_PRE_ORDER, FTT_TRAVERSE_ALL, -1,
+		     (FttCellTraverseFunc) boundary_tree, boundary);
+}
+
+static void send (GfsBoundary * bb)
+{
+  GfsBoundaryPeriodic * boundary = GFS_BOUNDARY_PERIODIC (bb);
+  GfsBoundaryPeriodic * matching = GFS_BOUNDARY_PERIODIC (boundary->matching->neighbor[bb->d]);
+
+  g_assert (GFS_IS_BOUNDARY_PERIODIC (matching));
+  g_assert (boundary->sndcount <= boundary->sndbuf->len);
+  
+  if (GFS_BOUNDARY (boundary)->type == GFS_BOUNDARY_MATCH_VARIABLE) {
+    if (boundary->sndcount > matching->rcvbuf->len)
+      g_array_set_size (matching->rcvbuf, boundary->sndcount);
+  }
+  memcpy (matching->rcvbuf->data, boundary->sndbuf->data, boundary->sndcount*sizeof (gdouble));
+}
+
+static void center_update (FttCell * cell,
+			   GfsBoundaryPeriodic * boundary)
+{
+  g_assert (boundary->rcvcount < boundary->rcvbuf->len);
+  GFS_VARIABLE (cell, GFS_BOUNDARY (boundary)->v->i) =
+    g_array_index (boundary->rcvbuf, gdouble, boundary->rcvcount++);
+}
+
+static void face_update (FttCellFace * face,
+			 GfsBoundaryPeriodic * boundary)
+{
+  g_assert (boundary->rcvcount < boundary->rcvbuf->len);
+  GFS_STATE (face->cell)->f[face->d].v = 
+    g_array_index (boundary->rcvbuf, gdouble, boundary->rcvcount++);
+}
+
+static void match_ignore (GfsBoundaryPeriodic * boundary)
+{
+  gboolean is_leaf;
+
+  g_assert (boundary->rcvcount < boundary->rcvbuf->len);
+  is_leaf = g_array_index (boundary->rcvbuf, gdouble, boundary->rcvcount++);
+
+  if (!is_leaf) {
+    gboolean is_destroyed[FTT_CELLS/2];
+    guint i;
+
+    for (i = 0; i < FTT_CELLS/2; i++) {
+      g_assert (boundary->rcvcount < boundary->rcvbuf->len);
+      is_destroyed[i] = g_array_index (boundary->rcvbuf, gdouble, boundary->rcvcount++);
+    }
+    for (i = 0; i < FTT_CELLS/2; i++)
+      if (!is_destroyed[i])
+	match_ignore (boundary);
+  }
+}
+
+static void match_update (FttCell * cell,
+			  GfsBoundaryPeriodic * boundary)
+{
+  gboolean is_leaf;
+
+  g_assert (boundary->rcvcount < boundary->rcvbuf->len);
+  is_leaf = g_array_index (boundary->rcvbuf, gdouble, boundary->rcvcount++);
+
+  if (!is_leaf) {
+    GfsDomain * domain = gfs_box_domain (GFS_BOUNDARY (boundary)->box);
+    FttCellChildren child;
+    gboolean is_destroyed[FTT_CELLS/2];
+    guint i, n;
+
+    if (FTT_CELL_IS_LEAF (cell)) {
+      FttCell * neighbor = ftt_cell_neighbor (cell, GFS_BOUNDARY (boundary)->d);
+
+      g_assert (neighbor);
+      ftt_cell_refine_single (cell, (FttCellInitFunc) gfs_cell_fine_init, domain);
+      if (FTT_CELL_IS_LEAF (neighbor))
+	ftt_cell_refine_single (neighbor, (FttCellInitFunc) gfs_cell_fine_init, domain);
+      /* what about solid fractions? */
+      GFS_BOUNDARY (boundary)->changed = TRUE;
+    }
+    n = ftt_cell_children_direction (cell, GFS_BOUNDARY (boundary)->d, &child);
+    for (i = 0; i < n; i++) {
+      g_assert (boundary->rcvcount < boundary->rcvbuf->len);
+      is_destroyed[i] = g_array_index (boundary->rcvbuf, gdouble, boundary->rcvcount++);
+      if (is_destroyed[i] && child.c[i]) {
+	ftt_cell_destroy (child.c[i], (FttCellCleanupFunc) gfs_cell_cleanup, NULL);
+	child.c[i] = NULL;
+	GFS_BOUNDARY (boundary)->changed = TRUE;
+      }
+    }
+    for (i = 0; i < n; i++)
+      if (!is_destroyed[i]) {
+	if (child.c[i])
+	  match_update (child.c[i], boundary);
+	else
+	  match_ignore (boundary);
+      }
+  }
+}
+
+static void receive (GfsBoundary * bb,
+		     FttTraverseFlags flags,
+		     gint max_depth)
+{
+  GfsBoundaryPeriodic * boundary = GFS_BOUNDARY_PERIODIC (bb);
+
+  boundary->rcvcount = 0;
+  switch (GFS_BOUNDARY (boundary)->type) {
+  case GFS_BOUNDARY_FACE_VARIABLE:
+    ftt_face_traverse_boundary (GFS_BOUNDARY (boundary)->root,
+				GFS_BOUNDARY (boundary)->d,
+				FTT_PRE_ORDER, flags, max_depth,
+				(FttFaceTraverseFunc) face_update, boundary);
+    break;
+
+  case GFS_BOUNDARY_MATCH_VARIABLE:
+    match_update (GFS_BOUNDARY (boundary)->root, boundary);
+    ftt_cell_flatten (GFS_BOUNDARY (boundary)->root, 
+		      GFS_BOUNDARY (boundary)->d,
+		      (FttCellCleanupFunc) gfs_cell_cleanup, NULL);
+    break;
+
+  default:
+    ftt_cell_traverse (GFS_BOUNDARY (boundary)->root,
+		       FTT_PRE_ORDER, flags, max_depth,
+		       (FttCellTraverseFunc) center_update, boundary);
+  }
+}
+
+static void synchronize (GfsBoundary * bb)
+{
+  GfsBoundaryPeriodic * boundary = GFS_BOUNDARY_PERIODIC (bb);
+
+  boundary->sndcount = 0;
+  if (bb->type == GFS_BOUNDARY_MATCH_VARIABLE)
+    set_buffers_size (boundary);
+}
+
+static GtsColor periodic_color (GtsObject * o)
+{
+  GtsColor c = { 1., 0., 0. }; /* red */
+
+  return c;
+}
+
+static void gfs_boundary_periodic_class_init (GfsBoundaryClass * klass)
+{
+  GfsBoundaryClass * parent_class = GFS_BOUNDARY_CLASS (klass);
+
+  parent_class->match             = periodic_match;
+  parent_class->send              = send;
+  parent_class->receive           = receive;
+  parent_class->synchronize       = synchronize;
+
+  GTS_OBJECT_CLASS (klass)->color =   periodic_color;
+  GTS_OBJECT_CLASS (klass)->destroy = boundary_periodic_destroy;
+  GTS_OBJECT_CLASS (klass)->read    = boundary_periodic_read;
+}
+
+static void gfs_boundary_periodic_init (GfsBoundaryPeriodic * boundary)
+{
+  GfsBc * b = GFS_BOUNDARY (boundary)->default_bc;
+
+  b->bc                = (FttFaceTraverseFunc) center_periodic;
+  b->homogeneous_bc    = (FttFaceTraverseFunc) center_periodic;
+  b->face_bc           = (FttFaceTraverseFunc) face_periodic;
+
+  boundary->sndbuf = g_array_new (FALSE, FALSE, sizeof (gdouble));
+  boundary->rcvbuf = g_array_new (FALSE, FALSE, sizeof (gdouble));
+  boundary->sndcount = boundary->rcvcount = 0;
+}
+
+GfsBoundaryClass * gfs_boundary_periodic_class (void)
+{
+  static GfsBoundaryClass * klass = NULL;
+
+  if (klass == NULL) {
+    GtsObjectClassInfo gfs_boundary_periodic_info = {
+      "GfsBoundaryPeriodic",
+      sizeof (GfsBoundaryPeriodic),
+      sizeof (GfsBoundaryClass),
+      (GtsObjectClassInitFunc) gfs_boundary_periodic_class_init,
+      (GtsObjectInitFunc) gfs_boundary_periodic_init,
+      (GtsArgSetFunc) NULL,
+      (GtsArgGetFunc) NULL
+    };
+    klass = gts_object_class_new (GTS_OBJECT_CLASS (gfs_boundary_class ()),
+				  &gfs_boundary_periodic_info);
+  }
+
+  return klass;
+}
+
+GfsBoundaryPeriodic * gfs_boundary_periodic_new (GfsBoundaryClass * klass,
+						 GfsBox * box,
+						 FttDirection d,
+						 GfsBox * matching)
+{
+  GfsBoundaryPeriodic * boundary;
+
+  boundary = GFS_BOUNDARY_PERIODIC (gfs_boundary_new (klass, box, d));
+  set_buffers_size (boundary);
+  boundary->matching = matching;
+
+  return boundary;
+}
+
 /* GfsGEdge: Object */
 
 static void gfs_gedge_write (GtsObject * object, FILE * fp)
@@ -963,12 +1256,22 @@ void gfs_gedge_link_boxes (GfsGEdge * edge)
   g_return_if_fail (b1->neighbor[edge->d] == NULL);
   g_return_if_fail (b2->neighbor[FTT_OPPOSITE_DIRECTION (edge->d)] == NULL);
 
-  ftt_cell_set_neighbor (b1->root, b2->root, edge->d, 
-			 (FttCellInitFunc) gfs_cell_init, gfs_box_domain (b1));
-  b1->neighbor[edge->d] = GTS_OBJECT (b2);
-  b2->neighbor[FTT_OPPOSITE_DIRECTION (edge->d)] = GTS_OBJECT (b1);
-  if (b1 != b2)
+  GtsObject * periodic = GTS_OBJECT (b1);
+  while (periodic && GFS_IS_BOX (periodic) && GFS_BOX (periodic) != b2)
+    periodic = GFS_BOX (periodic)->neighbor[FTT_OPPOSITE_DIRECTION (edge->d)];
+
+  if (GFS_BOX (periodic) == b2) {
+    gfs_boundary_periodic_new (gfs_boundary_periodic_class (), b1, edge->d, b2);
+    gfs_boundary_periodic_new (gfs_boundary_periodic_class (), b2, 
+			       FTT_OPPOSITE_DIRECTION (edge->d), b1);
+  }
+  else {
+    ftt_cell_set_neighbor (b1->root, b2->root, edge->d, 
+			   (FttCellInitFunc) gfs_cell_init, gfs_box_domain (b1));
+    b1->neighbor[edge->d] = GTS_OBJECT (b2);
+    b2->neighbor[FTT_OPPOSITE_DIRECTION (edge->d)] = GTS_OBJECT (b1);
     gfs_box_set_relative_pos (b2, b1, edge->d);
+  }
 }
 
 /**
diff --git a/src/boundary.h b/src/boundary.h
index 198b457..18b5520 100644
--- a/src/boundary.h
+++ b/src/boundary.h
@@ -214,6 +214,33 @@ struct _GfsBoundaryOutflowClass {
      
 GfsBoundaryOutflowClass * gfs_boundary_outflow_class    (void);
 
+/* GfsBoundaryPeriodic: Header */
+
+typedef struct _GfsBoundaryPeriodic         GfsBoundaryPeriodic;
+
+struct _GfsBoundaryPeriodic {
+  /*< private >*/
+  GfsBoundary parent;
+
+  GfsBox * matching;
+  GArray * sndbuf, * rcvbuf;
+  guint sndcount, rcvcount;
+};
+
+#define GFS_BOUNDARY_PERIODIC(obj)            GTS_OBJECT_CAST (obj,\
+					           GfsBoundaryPeriodic,\
+					           gfs_boundary_periodic_class ())
+#define GFS_IS_BOUNDARY_PERIODIC(obj)         (gts_object_is_from_class (obj,\
+						   gfs_boundary_periodic_class ()))
+     
+GfsBoundaryClass *    gfs_boundary_periodic_class    (void);
+GfsBoundaryPeriodic * gfs_boundary_periodic_new      (GfsBoundaryClass * klass,
+						      GfsBox * box,
+						      FttDirection d,
+						      GfsBox * matching);
+
+/* GfsGEdge: Header */
+  
 typedef struct _GfsGEdge         GfsGEdge;
 typedef struct _GfsGEdgeClass    GfsGEdgeClass;
 
diff --git a/src/domain.c b/src/domain.c
index d13b3fa..1953d00 100644
--- a/src/domain.c
+++ b/src/domain.c
@@ -151,9 +151,19 @@ static void removed_list (GfsBox * box, gpointer * data)
   GfsDomain * domain = data[0];
   GSList ** removed = data[1];
   guint * np = data[2];
-
   if (box->pid != domain->pid)
     *removed = g_slist_prepend (*removed, box);
+  else {
+    FttDirection d;
+    GfsBox * matching;
+
+    for (d = 0; d < FTT_NEIGHBORS; d++)
+      if (GFS_IS_BOUNDARY_PERIODIC (box->neighbor[d]) &&
+	  (matching = GFS_BOUNDARY_PERIODIC (box->neighbor[d])->matching)->pid != domain->pid) {
+	gts_object_destroy (GTS_OBJECT (box->neighbor[d]));
+	gfs_boundary_mpi_new (gfs_boundary_mpi_class (), box, d, matching->pid, matching->id);
+      }
+  }
   if (box->pid > *np)
     *np = box->pid;
 }
@@ -166,8 +176,7 @@ static void mpi_links (GfsBox * box, GfsDomain * domain)
   gint id = box->id;
 
   for (d = 0; d < FTT_NEIGHBORS; d++)
-    if (GFS_IS_BOX (box->neighbor[d]) && 
-	GFS_BOX (box->neighbor[d])->pid == domain->pid)
+    if (GFS_IS_BOX (box->neighbor[d]) && GFS_BOX (box->neighbor[d])->pid == domain->pid)
       neighbor[d] = box->neighbor[d];
     else
       neighbor[d] = NULL;
@@ -591,14 +600,13 @@ void gfs_domain_face_bc (GfsDomain * domain,
   datum[1] = &max_depth;
   datum[2] = v;
   datum[3] = &c;
-
   gts_container_foreach (GTS_CONTAINER (domain), 
 			 (GtsFunc) box_face_bc, datum);
   gts_container_foreach (GTS_CONTAINER (domain), 
 			 (GtsFunc) box_receive_bc, datum);
   gts_container_foreach (GTS_CONTAINER (domain),
 			 (GtsFunc) box_synchronize, &c);
-  
+
   if (domain->profile_bc)
     gfs_domain_timer_stop (domain, "face_bc");
 }
diff --git a/src/fluid.c b/src/fluid.c
index 9fc2909..168284e 100644
--- a/src/fluid.c
+++ b/src/fluid.c
@@ -461,8 +461,6 @@ gdouble gfs_center_gradient (FttCell * cell,
   g_return_val_if_fail (c < FTT_DIMENSION, 0.);
 
   f1 = gfs_cell_face (cell, FTT_OPPOSITE_DIRECTION (d));
-  if (f1.neighbor == cell) /* periodic */
-    return 0.;
   v0 = GFS_VARIABLE (cell, v);
   if (f1.neighbor) {
     FttCellFace f2 = gfs_cell_face (cell, d);
@@ -550,8 +548,6 @@ gdouble gfs_center_van_leer_gradient (FttCell * cell,
   g_return_val_if_fail (c < FTT_DIMENSION, 0.);
 
   f1 = gfs_cell_face (cell, FTT_OPPOSITE_DIRECTION (d));
-  if (f1.neighbor == cell) /* periodic */
-    return 0.;
   if (f1.neighbor) {
     FttCellFace f2 = gfs_cell_face (cell, d);
     
@@ -971,7 +967,6 @@ static gboolean face_bilinear (const FttCellFace * face,
 
     for (j = 0; j < FTT_DIMENSION; j++) {
       (&cm.x)[j] -= (&o->x)[j];
-      /* fixme: this does not work for periodic boundaries */      
       (&cm.x)[j] /= size;
       g_assert (fabs ((&cm.x)[j]) <= 4.);
     }
@@ -1027,7 +1022,6 @@ static gboolean face_bilinear (const FttCellFace * face,
 
     for (j = 0; j < FTT_DIMENSION; j++) {
       (&cm.x)[j] -= (&o->x)[j];
-      /* fixme: this does not work for periodic boundaries */      
       (&cm.x)[j] /= size;
       if (fabs ((&cm.x)[j]) > 4.)
 	output_error_mesh (n);
@@ -2602,7 +2596,6 @@ static gdouble distance (FttVector * c, FttCell * cell, gboolean centered)
   else {
     FttVector cm;
     gfs_cell_cm (cell, &cm);
-    /* fixme: what about periodic boundaries? */
     return sqrt ((cm.x - c->x)*(cm.x - c->x) + (cm.y - c->y)*(cm.y - c->y)
 #if (!FTT_2D)
       + (cm.z - c->z)*(cm.z - c->z)
diff --git a/src/mpi_boundary.c b/src/mpi_boundary.c
index 9a51576..9f8e552 100644
--- a/src/mpi_boundary.c
+++ b/src/mpi_boundary.c
@@ -29,98 +29,10 @@ static guint tag_shift = 32767/FTT_NEIGHBORS;
 #define MATCHING_TAG(boundary)  (tag_shift*FTT_OPPOSITE_DIRECTION ((boundary)->d) +\
                                  GFS_BOUNDARY_MPI (boundary)->id)
 
-static void boundary_mpi_destroy (GtsObject * object)
-{
-  GfsBoundaryMpi * boundary = GFS_BOUNDARY_MPI (object);
-
-  g_array_free (boundary->sndbuf, TRUE);
-  g_array_free (boundary->rcvbuf, TRUE);
-  
-  (* GTS_OBJECT_CLASS (gfs_boundary_mpi_class ())->parent_class->destroy) 
-    (object);
-}
-
-static void boundary_mpi_read (GtsObject ** object, GtsFile * fp)
-{
-  boundary_mpi_destroy (*object);
-}
-
-static void center_mpi (FttCellFace * face, GfsBc * b)
-{
-  GfsBoundaryMpi * boundary_mpi = GFS_BOUNDARY_MPI (b->b);
-
-  g_assert (boundary_mpi->sndcount < boundary_mpi->sndbuf->len);
-  g_assert (ftt_face_type (face) == FTT_FINE_FINE);
-  g_assert (!FTT_CELL_IS_LEAF (face->cell) || FTT_CELL_IS_LEAF (face->neighbor));
-  g_array_index (boundary_mpi->sndbuf, gdouble, boundary_mpi->sndcount++) =
-    GFS_VARIABLE (face->neighbor, b->v->i);
-}
-
-static void face_mpi (FttCellFace * face, GfsBc * b)
-{
-  GfsBoundaryMpi * boundary_mpi = GFS_BOUNDARY_MPI (b->b);
-
-  g_assert (boundary_mpi->sndcount < boundary_mpi->sndbuf->len);
-  g_array_index (boundary_mpi->sndbuf, gdouble, boundary_mpi->sndcount++) =
-    GFS_STATE (face->neighbor)->f[FTT_OPPOSITE_DIRECTION (face->d)].v;
-}
-
-static void boundary_size (FttCell * cell, guint * count)
-{
-  (*count)++;
-}
-
-static void set_buffers_size (GfsBoundaryMpi * boundary)
-{
-  guint count = 0;
-
-  ftt_cell_traverse (GFS_BOUNDARY (boundary)->root, 
-		     FTT_PRE_ORDER, FTT_TRAVERSE_LEAFS, -1,
-		     (FttCellTraverseFunc) boundary_size, &count);
-  g_array_set_size (boundary->rcvbuf, count);
-  g_array_set_size (boundary->sndbuf, count);
-}
-
-static void boundary_tree (FttCell * cell, GfsBoundaryMpi * boundary)
-{
-  gdouble is_leaf = FTT_CELL_IS_LEAF (cell);
-
-  if (boundary->sndcount == boundary->sndbuf->len)
-    g_array_append_val (boundary->sndbuf, is_leaf);
-  else
-    g_array_index (boundary->sndbuf, gdouble, boundary->sndcount) = is_leaf;
-  boundary->sndcount++;
-
-  if (!is_leaf) {
-    FttCellChildren child;
-    guint i, n;
-
-    n = ftt_cell_children_direction (cell, GFS_BOUNDARY (boundary)->d, &child);
-    for (i = 0; i < n; i++) {
-      gdouble is_destroyed = (child.c[i] == NULL);
-      
-      if (boundary->sndcount == boundary->sndbuf->len)
-	g_array_append_val (boundary->sndbuf, is_destroyed);
-      else
-	g_array_index (boundary->sndbuf, gdouble, boundary->sndcount) = is_destroyed;
-      boundary->sndcount++;
-    }
-  }
-}
-
-static void match (GfsBoundary * boundary)
-{
-  (* gfs_boundary_class ()->match) (boundary);
-
-  g_assert (GFS_BOUNDARY_MPI (boundary)->sndcount == 0);
-  ftt_cell_traverse (boundary->root,
-		     FTT_PRE_ORDER, FTT_TRAVERSE_ALL, -1,
-		     (FttCellTraverseFunc) boundary_tree, boundary);
-}
-
 static void send (GfsBoundary * bb)
 {
-  GfsBoundaryMpi * boundary = GFS_BOUNDARY_MPI (bb);
+  GfsBoundaryPeriodic * boundary = GFS_BOUNDARY_PERIODIC (bb);
+  GfsBoundaryMpi * mpi = GFS_BOUNDARY_MPI (bb);
   GfsDomain * domain = gfs_box_domain (bb->box);
 
   g_assert (boundary->sndcount <= boundary->sndbuf->len);
@@ -132,10 +44,10 @@ fprintf (stderr, "%d send %d tag: %d\n",
 	 TAG (GFS_BOUNDARY (boundary)));
 #endif
     MPI_Isend (&boundary->sndcount, 1, MPI_UNSIGNED,
-	       boundary->process,
+	       mpi->process,
 	       TAG (GFS_BOUNDARY (boundary)),
-	       boundary->comm,
-	       &(boundary->request[boundary->nrequest++]));
+	       mpi->comm,
+	       &(mpi->request[mpi->nrequest++]));
     gts_range_add_value (&domain->mpi_messages, sizeof (guint));
   }
 #ifdef DEBUG
@@ -146,100 +58,20 @@ fprintf (stderr, "%d send %d tag: %d size: %d\n",
 	 boundary->sndcount);
 #endif
   MPI_Isend (boundary->sndbuf->data, boundary->sndcount, MPI_DOUBLE,
-	     boundary->process,
+	     mpi->process,
 	     TAG (GFS_BOUNDARY (boundary)),
-	     boundary->comm,
-	     &(boundary->request[boundary->nrequest++]));
+	     mpi->comm,
+	     &(mpi->request[mpi->nrequest++]));
   gts_range_add_value (&domain->mpi_messages, 
                        sizeof (gdouble)*boundary->sndcount);
 }
 
-static void center_update (FttCell * cell,
-			   GfsBoundaryMpi * boundary)
-{
-  g_assert (boundary->rcvcount < boundary->rcvbuf->len);
-  GFS_VARIABLE (cell, GFS_BOUNDARY (boundary)->v->i) =
-    g_array_index (boundary->rcvbuf, gdouble, boundary->rcvcount++);
-}
-
-static void face_update (FttCellFace * face,
-			 GfsBoundaryMpi * boundary)
-{
-  g_assert (boundary->rcvcount < boundary->rcvbuf->len);
-  GFS_STATE (face->cell)->f[face->d].v = 
-    g_array_index (boundary->rcvbuf, gdouble, boundary->rcvcount++);
-}
-
-static void match_ignore (GfsBoundaryMpi * boundary)
-{
-  gboolean is_leaf;
-
-  g_assert (boundary->rcvcount < boundary->rcvbuf->len);
-  is_leaf = g_array_index (boundary->rcvbuf, gdouble, boundary->rcvcount++);
-
-  if (!is_leaf) {
-    gboolean is_destroyed[FTT_CELLS/2];
-    guint i;
-
-    for (i = 0; i < FTT_CELLS/2; i++) {
-      g_assert (boundary->rcvcount < boundary->rcvbuf->len);
-      is_destroyed[i] = g_array_index (boundary->rcvbuf, gdouble, boundary->rcvcount++);
-    }
-    for (i = 0; i < FTT_CELLS/2; i++)
-      if (!is_destroyed[i])
-	match_ignore (boundary);
-  }
-}
-
-static void match_update (FttCell * cell,
-			  GfsBoundaryMpi * boundary)
-{
-  gboolean is_leaf;
-
-  g_assert (boundary->rcvcount < boundary->rcvbuf->len);
-  is_leaf = g_array_index (boundary->rcvbuf, gdouble, boundary->rcvcount++);
-
-  if (!is_leaf) {
-    GfsDomain * domain = gfs_box_domain (GFS_BOUNDARY (boundary)->box);
-    FttCellChildren child;
-    gboolean is_destroyed[FTT_CELLS/2];
-    guint i, n;
-
-    if (FTT_CELL_IS_LEAF (cell)) {
-      FttCell * neighbor = ftt_cell_neighbor (cell, GFS_BOUNDARY (boundary)->d);
-
-      g_assert (neighbor);
-      ftt_cell_refine_single (cell, (FttCellInitFunc) gfs_cell_fine_init, domain);
-      if (FTT_CELL_IS_LEAF (neighbor))
-	ftt_cell_refine_single (neighbor, (FttCellInitFunc) gfs_cell_fine_init, domain);
-      /* what about solid fractions? */
-      GFS_BOUNDARY (boundary)->changed = TRUE;
-    }
-    n = ftt_cell_children_direction (cell, GFS_BOUNDARY (boundary)->d, &child);
-    for (i = 0; i < n; i++) {
-      g_assert (boundary->rcvcount < boundary->rcvbuf->len);
-      is_destroyed[i] = g_array_index (boundary->rcvbuf, gdouble, boundary->rcvcount++);
-      if (is_destroyed[i] && child.c[i]) {
-	ftt_cell_destroy (child.c[i], (FttCellCleanupFunc) gfs_cell_cleanup, NULL);
-	child.c[i] = NULL;
-	GFS_BOUNDARY (boundary)->changed = TRUE;
-      }
-    }
-    for (i = 0; i < n; i++)
-      if (!is_destroyed[i]) {
-	if (child.c[i])
-	  match_update (child.c[i], boundary);
-	else
-	  match_ignore (boundary);
-      }
-  }
-}
-
 static void receive (GfsBoundary * bb,
 		     FttTraverseFlags flags,
 		     gint max_depth)
 {
-  GfsBoundaryMpi * boundary = GFS_BOUNDARY_MPI (bb);
+  GfsBoundaryPeriodic * boundary = GFS_BOUNDARY_PERIODIC (bb);
+  GfsBoundaryMpi * mpi = GFS_BOUNDARY_MPI (bb);
   MPI_Status status;
   gint count;
 #ifdef PROFILE_MPI
@@ -257,9 +89,9 @@ fprintf (stderr, "%d wait %d %d match variable\n",
 	 MATCHING_TAG (GFS_BOUNDARY (boundary)));
 #endif
     MPI_Recv (&boundary->rcvcount, 1, MPI_UNSIGNED,
-	      boundary->process,
+	      mpi->process,
 	      MATCHING_TAG (GFS_BOUNDARY (boundary)),
-	      boundary->comm,
+	      mpi->comm,
 	      &status);
 #ifdef PROFILE_MPI
     end = MPI_Wtime ();
@@ -281,9 +113,9 @@ fprintf (stderr, "%d wait %d %d\n",
   MPI_Recv (boundary->rcvbuf->data,
 	    boundary->rcvcount,
 	    MPI_DOUBLE,
-	    boundary->process,
+	    mpi->process,
 	    MATCHING_TAG (GFS_BOUNDARY (boundary)),
-	    boundary->comm,
+	    mpi->comm,
 	    &status);
   MPI_Get_count (&status, MPI_DOUBLE, &count);
   g_assert (count == boundary->rcvcount);
@@ -291,30 +123,9 @@ fprintf (stderr, "%d wait %d %d\n",
 #ifdef PROFILE_MPI
   end = MPI_Wtime ();
   gts_range_add_value (&domain->mpi_wait, end - start);
-#endif /* PROFILE_MPI */ 
- 
-  boundary->rcvcount = 0;
-  switch (GFS_BOUNDARY (boundary)->type) {
-  case GFS_BOUNDARY_FACE_VARIABLE:
-    ftt_face_traverse_boundary (GFS_BOUNDARY (boundary)->root,
-				GFS_BOUNDARY (boundary)->d,
-				FTT_PRE_ORDER, flags, max_depth,
-				(FttFaceTraverseFunc) face_update, boundary);
-    break;
-
-  case GFS_BOUNDARY_MATCH_VARIABLE:
-    match_update (GFS_BOUNDARY (boundary)->root, boundary);
-    ftt_cell_flatten (GFS_BOUNDARY (boundary)->root, 
-		      GFS_BOUNDARY (boundary)->d,
-		      (FttCellCleanupFunc) gfs_cell_cleanup, NULL);
-    break;
+#endif /* PROFILE_MPI */
 
-  default:
-    ftt_cell_traverse (GFS_BOUNDARY (boundary)->root,
-		       FTT_PRE_ORDER, flags, max_depth,
-		       (FttCellTraverseFunc) center_update, boundary);
-  }
-  g_assert (boundary->rcvcount == count);
+  (* gfs_boundary_periodic_class ()->receive) (bb, flags, max_depth);
 }
 
 static void synchronize (GfsBoundary * bb)
@@ -337,60 +148,35 @@ static void synchronize (GfsBoundary * bb)
   gts_range_add_value (&domain->mpi_wait, end - start);
 #endif /* PROFILE_MPI */
   boundary->nrequest = 0;
-  boundary->sndcount = 0;
 
-  if (bb->type == GFS_BOUNDARY_MATCH_VARIABLE)
-    set_buffers_size (boundary);
+  (* gfs_boundary_periodic_class ()->synchronize) (bb);
 }
 
-static GtsColor mpi_color (GtsObject * o)
+static void gfs_boundary_mpi_class_init (GfsBoundaryClass * klass)
 {
-  GtsColor c = { 1., 0., 0. }; /* red */
-
-  return c;
-}
-
-static void gfs_boundary_mpi_class_init (GfsBoundaryMpiClass * klass)
-{
-  GfsBoundaryClass * parent_class = GFS_BOUNDARY_CLASS (klass);
-
-  parent_class->match             = match;
-  parent_class->send              = send;
-  parent_class->receive           = receive;
-  parent_class->synchronize       = synchronize;
-
-  GTS_OBJECT_CLASS (klass)->color = mpi_color;
-  GTS_OBJECT_CLASS (klass)->destroy = boundary_mpi_destroy;
-  GTS_OBJECT_CLASS (klass)->read    = boundary_mpi_read;
+  klass->send        = send;
+  klass->receive     = receive;
+  klass->synchronize = synchronize;
 }
 
 static void gfs_boundary_mpi_init (GfsBoundaryMpi * boundary)
 {
-  GfsBc * b = GFS_BOUNDARY (boundary)->default_bc;
-
-  b->bc                = (FttFaceTraverseFunc) center_mpi;
-  b->homogeneous_bc    = (FttFaceTraverseFunc) center_mpi;
-  b->face_bc           = (FttFaceTraverseFunc) face_mpi;
-
   boundary->comm = MPI_COMM_WORLD;
   boundary->process = -1; 
   boundary->id = -1;
 
   boundary->nrequest = 0;
-  boundary->sndbuf = g_array_new (FALSE, FALSE, sizeof (gdouble));
-  boundary->rcvbuf = g_array_new (FALSE, FALSE, sizeof (gdouble));
-  boundary->sndcount = boundary->rcvcount = 0;
 }
 
-GfsBoundaryMpiClass * gfs_boundary_mpi_class (void)
+GfsBoundaryClass * gfs_boundary_mpi_class (void)
 {
-  static GfsBoundaryMpiClass * klass = NULL;
+  static GfsBoundaryClass * klass = NULL;
 
   if (klass == NULL) {
     GtsObjectClassInfo gfs_boundary_mpi_info = {
       "GfsBoundaryMpi",
       sizeof (GfsBoundaryMpi),
-      sizeof (GfsBoundaryMpiClass),
+      sizeof (GfsBoundaryClass),
       (GtsObjectClassInitFunc) gfs_boundary_mpi_class_init,
       (GtsObjectInitFunc) gfs_boundary_mpi_init,
       (GtsArgSetFunc) NULL,
@@ -398,7 +184,7 @@ GfsBoundaryMpiClass * gfs_boundary_mpi_class (void)
     };
     int * tagub, flag, maxtag;
 
-    klass = gts_object_class_new (GTS_OBJECT_CLASS (gfs_boundary_class ()),
+    klass = gts_object_class_new (GTS_OBJECT_CLASS (gfs_boundary_periodic_class ()),
 				  &gfs_boundary_mpi_info);
     MPI_Attr_get (MPI_COMM_WORLD, MPI_TAG_UB, &tagub, &flag);
     if (flag)
@@ -411,7 +197,7 @@ GfsBoundaryMpiClass * gfs_boundary_mpi_class (void)
   return klass;
 }
 
-GfsBoundaryMpi * gfs_boundary_mpi_new (GfsBoundaryMpiClass * klass,
+GfsBoundaryMpi * gfs_boundary_mpi_new (GfsBoundaryClass * klass,
 				       GfsBox * box,
 				       FttDirection d,
 				       gint process,
@@ -424,9 +210,7 @@ GfsBoundaryMpi * gfs_boundary_mpi_new (GfsBoundaryMpiClass * klass,
 
   g_return_val_if_fail (process >= 0 && process < comm_size, NULL);
 
-  boundary = GFS_BOUNDARY_MPI (gfs_boundary_new (GFS_BOUNDARY_CLASS (klass),
-					       box,
-					       d));
+  boundary = GFS_BOUNDARY_MPI (gfs_boundary_periodic_new (klass, box, d, NULL));
   boundary->process = process;
   boundary->id = id;
 
@@ -434,7 +218,5 @@ GfsBoundaryMpi * gfs_boundary_mpi_new (GfsBoundaryMpiClass * klass,
     g_warning ("GfsBoundaryMpi id (%d) is larger than the maximum MPI tag value\n"
 	       "allowed on this system (%d)", id, tag_shift);
 
-  set_buffers_size (boundary);
-
   return boundary;
 }
diff --git a/src/mpi_boundary.h b/src/mpi_boundary.h
index 67beb23..737aef5 100644
--- a/src/mpi_boundary.h
+++ b/src/mpi_boundary.h
@@ -28,41 +28,30 @@ extern "C" {
 #endif /* __cplusplus */
 
 typedef struct _GfsBoundaryMpi         GfsBoundaryMpi;
-typedef struct _GfsBoundaryMpiClass    GfsBoundaryMpiClass;
 
 struct _GfsBoundaryMpi {
   /*< private >*/
-  GfsBoundary parent;
+  GfsBoundaryPeriodic parent;
 
   MPI_Comm comm;
   gint process, id;
 
   MPI_Request request[2];
   guint nrequest;
-
-  GArray * sndbuf, * rcvbuf;
-  unsigned int sndcount, rcvcount;
-};
-
-struct _GfsBoundaryMpiClass {
-  GfsBoundaryClass parent_class;
 };
 
 #define GFS_BOUNDARY_MPI(obj)            GTS_OBJECT_CAST (obj,\
 					           GfsBoundaryMpi,\
 					           gfs_boundary_mpi_class ())
-#define GFS_BOUNDARY_MPI_CLASS(klass)    GTS_OBJECT_CLASS_CAST (klass,\
-						       GfsBoundaryMpiClass,\
-						       gfs_boundary_mpi_class())
 #define GFS_IS_BOUNDARY_MPI(obj)         (gts_object_is_from_class (obj,\
 						   gfs_boundary_mpi_class ()))
      
-GfsBoundaryMpiClass * gfs_boundary_mpi_class    (void);
-GfsBoundaryMpi *      gfs_boundary_mpi_new      (GfsBoundaryMpiClass * klass,
-					       GfsBox * box,
-					       FttDirection d,
-					       gint process,
-					       gint id);
+GfsBoundaryClass *    gfs_boundary_mpi_class    (void);
+GfsBoundaryMpi *      gfs_boundary_mpi_new      (GfsBoundaryClass * klass,
+						 GfsBox * box,
+						 FttDirection d,
+						 gint process,
+						 gint id);
 
 #ifdef __cplusplus
 }

-- 
Gerris Flow Solver



More information about the debian-science-commits mailing list