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

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


The following commit has been merged in the upstream branch:
commit 16533780f580a230957f9d4de6717d43c90fd1ca
Author: Stephane Popinet <popinet at users.sf.net>
Date:   Wed Mar 15 15:20:29 2006 +1100

    Thin cells are removed
    
    "Thin" cells are topologically complex cut cells which lead to
    inaccurate volume-of-fluid representation of solid surfaces.  In some
    cases the presence of these cells could lead to instabilities in the
    projection. In all cases they would lead to inaccurate velocities.
    
    darcs-hash:20060315042029-d4795-fb87c2f1dc1d923c96e2798029b15eeca37d28f3.gz

diff --git a/src/output.c b/src/output.c
index 4048177..33da9fb 100644
--- a/src/output.c
+++ b/src/output.c
@@ -749,10 +749,12 @@ static gboolean gfs_output_solid_stats_event (GfsEvent * event,
 	     "Total merged solid volume fraction\n"
 	     "    min: %10.3e avg: %10.3e | %10.3e max: %10.3e n: %10d\n"
 	     "Number of cells merged per merged cell\n"
-	     "    min: %10.0f avg: %10.3f | %10.3f max: %10.0f n: %10d\n",
+	     "    min: %10.0f avg: %10.3f | %10.3f max: %10.0f n: %10d\n"
+	     "Number of \"thin\" cells removed: %10d\n",
 	     stats.min, stats.mean, stats.stddev, stats.max, stats.n,
 	     ma.min, ma.mean, ma.stddev, ma.max, ma.n,
-	     mn.min, mn.mean, mn.stddev, mn.max, mn.n);
+	     mn.min, mn.mean, mn.stddev, mn.max, mn.n,
+	     sim->thin);
     return TRUE;
   }
   return FALSE;
diff --git a/src/simulation.c b/src/simulation.c
index fd9ea6c..c6282f2 100644
--- a/src/simulation.c
+++ b/src/simulation.c
@@ -873,9 +873,9 @@ void gfs_simulation_refine (GfsSimulation * sim)
 
   if (sim->surface) {
     gfs_domain_timer_start (domain, "solid_fractions");
-    gfs_domain_init_solid_fractions (domain, sim->surface, TRUE,
-				     (FttCellCleanupFunc) gfs_cell_cleanup, NULL, 
-				     NULL);
+    sim->thin = gfs_domain_init_solid_fractions (domain, sim->surface, TRUE,
+						 (FttCellCleanupFunc) gfs_cell_cleanup, NULL, 
+						 NULL);
     gfs_domain_match (domain);
     gfs_domain_timer_stop (domain, "solid_fractions");
   }
diff --git a/src/simulation.h b/src/simulation.h
index cfd172f..9cfd50e 100644
--- a/src/simulation.h
+++ b/src/simulation.h
@@ -65,6 +65,7 @@ struct _GfsSimulation {
   GfsAdvectionParams advection_params;
 
   GtsSurface * surface;
+  guint thin;
   gboolean output_surface;
 
   GtsSListContainer * refines;
diff --git a/src/solid.c b/src/solid.c
index b1726f7..40ec980 100644
--- a/src/solid.c
+++ b/src/solid.c
@@ -263,17 +263,20 @@ static gboolean solid_face_is_thin (CellFace * f)
  * @s: a #GtsSurface.
  *
  * Sets the 2D volume fractions of @cell cut by @s.
+ *
+ * Returns: %TRUE if the cell is thin, %FALSE otherwise;
  */
-void gfs_set_2D_solid_fractions_from_surface (FttCell * cell,
-					      GtsSurface * s)
+gboolean gfs_set_2D_solid_fractions_from_surface (FttCell * cell,
+						  GtsSurface * s)
 {
   GfsSolidVector * solid;
   FttVector h;
   CellFace f;
   guint i, n1 = 0;
+  gboolean thin = FALSE;
 
-  g_return_if_fail (cell != NULL);
-  g_return_if_fail (s != NULL);
+  g_return_val_if_fail (cell != NULL, FALSE);
+  g_return_val_if_fail (s != NULL, FALSE);
 
   h.x = h.y = ftt_cell_size (cell);
   face_new (&f, cell, s, &h);
@@ -294,7 +297,10 @@ void gfs_set_2D_solid_fractions_from_surface (FttCell * cell,
       GFS_STATE (cell)->solid = NULL;
     }
     break;
-  case 2: case 4: {
+  case 4:
+    thin = TRUE;
+    /* fall through */
+  case 2: {
     if (!solid)
       GFS_STATE (cell)->solid = solid = g_malloc (sizeof (GfsSolidVector));
     face_fractions (&f, solid, &h);
@@ -304,11 +310,28 @@ void gfs_set_2D_solid_fractions_from_surface (FttCell * cell,
     g_log (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR,
 	   "the surface is probably not closed (n1 = %d)", n1);
   }
+  return thin;
 }
 
+typedef struct {
+  gboolean destroy_solid;
+  FttCellCleanupFunc cleanup;
+  gpointer data;
+  GfsVariable * status;
+  guint thin;
+} InitSolidParams;
+
 #if FTT_2D /* 2D */
 
-# define set_solid_fractions_from_surface gfs_set_2D_solid_fractions_from_surface
+static void set_solid_fractions_from_surface (FttCell * cell,
+					      GtsSurface * s,
+					      InitSolidParams * p)
+{
+  if (gfs_set_2D_solid_fractions_from_surface (cell, s)) {
+    GFS_VARIABLE (cell, p->status->i) = 1.;
+    p->thin++;
+  }
+}
 
 /**
  * gfs_solid_is_thin:
@@ -446,7 +469,7 @@ static void cube_new (CellCube * cube, FttCell * cell, GtsSurface * s, FttVector
   gts_surface_foreach_face (s, (GtsFunc) triangle_cube_intersection, cube);  
 }
 
-static void set_solid_fractions_from_surface3D (FttCell * cell, GtsSurface * s)
+static void set_solid_fractions_from_surface (FttCell * cell, GtsSurface * s, InitSolidParams * p)
 {
   GfsSolidVector * solid = GFS_STATE (cell)->solid;
   CellCube cube;
@@ -581,13 +604,8 @@ static void set_solid_fractions_from_surface3D (FttCell * cell, GtsSurface * s)
   else {
     solid->cm = solid->ca;
     solid->a = 0.;
-    for (i = 0; i < FTT_NEIGHBORS; i++)
-      solid->a += solid->s[i];
-    solid->a /= FTT_NEIGHBORS;
-    if (solid->a == 0. || solid->a == 1.) {
-      g_free (solid);
-      GFS_STATE (cell)->solid = NULL;
-    }
+    GFS_VARIABLE (cell, p->status->i) = 1.;
+    p->thin++;
   }
 }
 
@@ -626,8 +644,6 @@ gboolean gfs_solid_is_thin (FttCell * cell, GtsSurface * s)
   return (topology (&cube) > 1);
 }
 
-# define set_solid_fractions_from_surface set_solid_fractions_from_surface3D
-
 #endif /* 2D3 or 3D */
 
 static gdouble solid_sa (GfsSolidVector * s)
@@ -752,7 +768,7 @@ static void push_leaf (GtsFifo * fifo, FttCell * cell, FttDirection d, gdouble a
 	GFS_VARIABLE (child.c[i], status->i) = a;
 	gts_fifo_push (fifo, child.c[i]);
       }
-  }  
+  }
 }
 
 static void paint_leaf (GtsFifo * fifo, gdouble a, GfsVariable * status)
@@ -803,13 +819,6 @@ static void paint_mixed_leaf (FttCell * cell, GfsVariable * status)
   }
 }
 
-typedef struct {
-  gboolean destroy_solid;
-  FttCellCleanupFunc cleanup;
-  gpointer data;
-  GfsVariable * status;
-} InitSolidParams;
-
 static void solid_fractions_from_children (FttCell * cell, InitSolidParams * p)
 {
   if (!FTT_CELL_IS_LEAF (cell)) {
@@ -856,28 +865,33 @@ static void match_fractions (FttCell * cell, GfsVariable * status)
   if (GFS_IS_MIXED (cell)) {
     FttCellNeighbors neighbor;
     guint level = ftt_cell_level (cell);
+    GfsSolidVector * solid = GFS_STATE (cell)->solid;
     FttDirection d;
 
     ftt_cell_neighbors (cell, &neighbor);
     for (d = 0; d < FTT_NEIGHBORS; d++)
       if (neighbor.c[d] &&
-	  !GFS_CELL_IS_BOUNDARY (neighbor.c[d]) &&
-	  GFS_VARIABLE (neighbor.c[d], status->i) != 1.) {
+	  !GFS_CELL_IS_BOUNDARY (neighbor.c[d])) {
 	if (!FTT_CELL_IS_LEAF (neighbor.c[d])) {
 	  FttCellChildren child;
 	  FttDirection od = FTT_OPPOSITE_DIRECTION (d);
 	  guint i, n = ftt_cell_children_direction (neighbor.c[d], od, &child);
 	  gdouble s = 0.;
 
+	  g_assert (GFS_VARIABLE (neighbor.c[d], status->i) != 1.);
 	  for (i = 0; i < n; i++)
 	    if (child.c[i] && GFS_VARIABLE (child.c[i], status->i) != 1.)
 	      s += GFS_IS_MIXED (child.c[i]) ? GFS_STATE (child.c[i])->solid->s[od] : 1.;
-	  GFS_STATE (cell)->solid->s[d] = s/n;
+	  solid->s[d] = s/n;
 	}
-	else if (!GFS_IS_MIXED (neighbor.c[d]) && GFS_STATE (cell)->solid->s[d] < 1.) {
-	  g_assert (ftt_cell_level (neighbor.c[d]) == level - 1);
-	  GFS_STATE (cell)->solid->s[d] = 1.;
+	else if (GFS_VARIABLE (neighbor.c[d], status->i) != 1.) {
+	  if (!GFS_IS_MIXED (neighbor.c[d]) && solid->s[d] < 1.) {
+	    g_assert (ftt_cell_level (neighbor.c[d]) == level - 1);
+	    solid->s[d] = 1.;
+	  }
 	}
+	else if (GFS_IS_MIXED (neighbor.c[d])) /* this is a thin cell */
+	  solid->s[d] = 0.;
       }
   }
 }
@@ -895,27 +909,30 @@ static void match_fractions (FttCell * cell, GfsVariable * status)
  *
  * If @destroy_solid is set to %TRUE, the cells entirely contained in
  * the solid are destroyed using @cleanup as cleanup function.  
+ *
+ * Returns: the number of thin cells.
  */
-void gfs_domain_init_solid_fractions (GfsDomain * domain,
-				      GtsSurface * s,
-				      gboolean destroy_solid,
-				      FttCellCleanupFunc cleanup,
-				      gpointer data,
-				      GfsVariable * status)
+guint gfs_domain_init_solid_fractions (GfsDomain * domain,
+				       GtsSurface * s,
+				       gboolean destroy_solid,
+				       FttCellCleanupFunc cleanup,
+				       gpointer data,
+				       GfsVariable * status)
 {
   InitSolidParams p;
 
-  g_return_if_fail (domain != NULL);
-  g_return_if_fail (s != NULL);
+  g_return_val_if_fail (domain != NULL, 0);
+  g_return_val_if_fail (s != NULL, 0);
 
   p.destroy_solid = destroy_solid;
   p.cleanup = cleanup;
   p.data = data;
   p.status = status ? status : gfs_temporary_variable (domain);
-  gfs_domain_traverse_cut (domain, s, FTT_PRE_ORDER, FTT_TRAVERSE_LEAFS,
-			   (FttCellTraverseCutFunc) set_solid_fractions_from_surface, NULL);
+  p.thin = 0;
   gfs_domain_cell_traverse (domain, FTT_PRE_ORDER, FTT_TRAVERSE_LEAFS, -1,
 			    (FttCellTraverseFunc) gfs_cell_reset, p.status);
+  gfs_domain_traverse_cut (domain, s, FTT_PRE_ORDER, FTT_TRAVERSE_LEAFS,
+			   (FttCellTraverseCutFunc) set_solid_fractions_from_surface, &p);
   gfs_domain_cell_traverse (domain, FTT_PRE_ORDER, FTT_TRAVERSE_LEAFS, -1,
 			    (FttCellTraverseFunc) paint_mixed_leaf, p.status);
   gfs_domain_cell_traverse (domain, FTT_PRE_ORDER, FTT_TRAVERSE_LEAFS, -1,
@@ -923,6 +940,8 @@ void gfs_domain_init_solid_fractions (GfsDomain * domain,
   gts_container_foreach (GTS_CONTAINER (domain), (GtsFunc) foreach_box, &p);
   if (status == NULL)
     gts_object_destroy (GTS_OBJECT (p.status));
+
+  return p.thin;
 }
 
 static gboolean check_area_fractions (const FttCell * root)
diff --git a/src/solid.h b/src/solid.h
index d1648ec..1cfda72 100644
--- a/src/solid.h
+++ b/src/solid.h
@@ -31,9 +31,9 @@ extern "C" {
 void         gfs_cell_fluid                              (FttCell * cell);
 gboolean     gfs_solid_is_thin                           (FttCell * cell, 
 							  GtsSurface * s);
-void         gfs_set_2D_solid_fractions_from_surface     (FttCell * cell,
+gboolean     gfs_set_2D_solid_fractions_from_surface     (FttCell * cell,
 							  GtsSurface * s);
-void         gfs_domain_init_solid_fractions             (GfsDomain * domain,
+guint        gfs_domain_init_solid_fractions             (GfsDomain * domain,
 							  GtsSurface * s,
 							  gboolean destroy_solid,
 							  FttCellCleanupFunc cleanup,
diff --git a/src/timestep.c b/src/timestep.c
index f786179..ce0e4fa 100644
--- a/src/timestep.c
+++ b/src/timestep.c
@@ -80,10 +80,11 @@ static void scale_gradients (FttCell * cell, gpointer * data)
   if (GFS_IS_MIXED (cell)) {
     GfsSolidVector * s = GFS_STATE (cell)->solid;
 
-    for (c = 0; c < *dimension; c++) {
-      g_assert (s->s[2*c] + s->s[2*c + 1] > 0.);
-      GFS_VARIABLE (cell, g[c]->i) /= s->s[2*c] + s->s[2*c + 1];
-    }
+    for (c = 0; c < *dimension; c++)
+      if (s->s[2*c] + s->s[2*c + 1] > 0.)
+	GFS_VARIABLE (cell, g[c]->i) /= s->s[2*c] + s->s[2*c + 1];
+      else
+	g_assert (GFS_VARIABLE (cell, g[c]->i) == 0.);
   }
   else {
     FttCellNeighbors n;

-- 
Gerris Flow Solver



More information about the debian-science-commits mailing list