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

Stephane Popinet popinet at users.sourceforge.net
Fri May 15 02:51:14 UTC 2009


The following commit has been merged in the upstream branch:
commit 2bcae611752441943880c55658e2f143416a6e6e
Author: Stephane Popinet <popinet at users.sourceforge.net>
Date:   Thu Oct 14 08:12:50 2004 +1000

    Support for binary simulation files (gerris--mainline--0.5--patch-5)
    
    gerris--mainline--0.5--patch-5
    Keywords:
    
    Binary files speed up reading time by a factor of ~5 for big simulations.
    There is no consideration of endianess at this point.
    
    darcs-hash:20041013221250-aabb8-a90871bc9a5f5a6d95ffa7194ddd3acfb3e5a466.gz

diff --git a/src/boundary.c b/src/boundary.c
index 3144016..ae18d5d 100644
--- a/src/boundary.c
+++ b/src/boundary.c
@@ -1019,9 +1019,12 @@ static void gfs_box_write (GtsObject * object, FILE * fp)
   fputs (" }", fp);
   if (domain != NULL && domain->max_depth_write > -2) {
     fputs (" {\n", fp);
-    ftt_cell_write (box->root, domain->max_depth_write, fp, 
-		    (FttCellWriteFunc) gfs_cell_write, 
-		    domain->variables_io);
+    if (domain->binary)
+      ftt_cell_write_binary (box->root, domain->max_depth_write, fp, 
+			     (FttCellWriteFunc) gfs_cell_write_binary, domain->variables_io);
+    else
+      ftt_cell_write (box->root, domain->max_depth_write, fp, 
+		      (FttCellWriteFunc) gfs_cell_write, domain->variables_io);
     fputc ('}', fp);
   }
 }
@@ -1110,8 +1113,20 @@ static void gfs_box_read (GtsObject ** o, GtsFile * fp)
 
     ftt_cell_destroy (b->root, (FttCellCleanupFunc) gfs_cell_cleanup, NULL);
     fp->scope_max++;
-    gts_file_first_token_after (fp, '\n');
-    b->root = ftt_cell_read (fp, (FttCellReadFunc) gfs_cell_read, domain);
+    if (domain->binary) {
+      if (gts_file_getc (fp) != '\n') {
+      	gts_file_error (fp, "expecting a newline");
+      	return;
+      }
+      b->root = ftt_cell_read_binary (fp, (FttCellReadFunc) gfs_cell_read_binary, domain);
+      if (fp->type == GTS_ERROR)
+	return;
+      gts_file_next_token (fp);
+    }
+    else {
+      gts_file_first_token_after (fp, '\n');
+      b->root = ftt_cell_read (fp, (FttCellReadFunc) gfs_cell_read, domain);
+    }
     fp->scope_max--;
     if (fp->type == GTS_ERROR)
       return;
diff --git a/src/domain.c b/src/domain.c
index f53b6ee..a17d1ce 100644
--- a/src/domain.c
+++ b/src/domain.c
@@ -1865,6 +1865,42 @@ void gfs_cell_copy (const FttCell * from,
 }
 
 /**
+ * gfs_cell_write:
+ * @cell: a #FttCell.
+ * @fp: a file pointer.
+ * @variables: the #GfsVariable to be written.
+ *
+ * Writes in @fp the fluid data associated with @cell and described by
+ * @variables. This function is generally used in association with
+ * ftt_cell_write().  
+ */
+void gfs_cell_write (const FttCell * cell, FILE * fp,
+		     GfsVariable * variables)
+{
+  g_return_if_fail (cell != NULL);
+  g_return_if_fail (fp != NULL);
+
+  if (GFS_IS_MIXED (cell)) {
+    GfsStateVector * s = GFS_STATE (cell);
+    guint i;
+
+    for (i = 0; i < FTT_NEIGHBORS; i++)
+      fprintf (fp, " %g", s->solid->s[i]);
+    fprintf (fp, " %g", s->solid->a);
+    for (i = 0; i < FTT_DIMENSION; i++)
+      fprintf (fp, " %g", (&s->solid->cm.x)[i]);
+  }
+  else
+    fputs (" -1", fp);
+  
+  while (variables) {
+    if (variables->name)
+      fprintf (fp, " %g", GFS_VARIABLE (cell, variables->i));
+    variables = variables->next;
+  }
+}
+
+/**
  * gfs_cell_read:
  * @cell: a #FttCell.
  * @fp: a #GtsFile.
@@ -1936,6 +1972,103 @@ void gfs_cell_read (FttCell * cell, GtsFile * fp, GfsDomain * domain)
 }
 
 /**
+ * gfs_cell_write_binary:
+ * @cell: a #FttCell.
+ * @fp: a file pointer.
+ * @variables: the #GfsVariable to be written.
+ *
+ * Writes in @fp the fluid data associated with @cell and described by
+ * @variables. This function is generally used in association with
+ * ftt_cell_write_binary().
+ */
+void gfs_cell_write_binary (const FttCell * cell, FILE * fp,
+			    GfsVariable * variables)
+{
+  g_return_if_fail (cell != NULL);
+  g_return_if_fail (fp != NULL);
+
+  if (GFS_IS_MIXED (cell)) {
+    GfsStateVector * s = GFS_STATE (cell);
+
+    fwrite (s->solid->s, sizeof (gdouble), FTT_NEIGHBORS, fp);
+    fwrite (&s->solid->a, sizeof (gdouble), 1, fp);
+    fwrite (&s->solid->cm.x, sizeof (gdouble), FTT_DIMENSION, fp);
+  }
+  else {
+    gdouble a = -1.;
+    fwrite (&a, sizeof (gdouble), 1, fp);
+  }
+  
+  while (variables) {
+    if (variables->name) {
+      gdouble a = GFS_VARIABLE (cell, variables->i);
+      fwrite (&a, sizeof (gdouble), 1, fp);
+    }
+    variables = variables->next;
+  }
+}
+
+/**
+ * gfs_cell_read_binary:
+ * @cell: a #FttCell.
+ * @fp: a #GtsFile.
+ * @domain: the #GfsDomain containing @cell.
+ *
+ * Reads from @fp the fluid data associated with @cell and described
+ * by @domain->variables_io. This function is generally used in
+ * association with ftt_cell_read_binary().
+ */
+void gfs_cell_read_binary (FttCell * cell, GtsFile * fp, GfsDomain * domain)
+{
+  gdouble s0;
+  GfsStateVector * s;
+  GfsVariable * v;
+
+  g_return_if_fail (cell != NULL);
+  g_return_if_fail (fp != NULL);
+  g_return_if_fail (domain != NULL);
+
+  if (gts_file_read (fp, &s0, sizeof (gdouble), 1) != 1) {
+    gts_file_error (fp, "expecting a number (solid->s[0])");
+    return;
+  }
+
+  gfs_cell_init (cell, domain);
+  s = cell->data;
+  if (s0 >= 0.) {
+    guint i;
+
+    s->solid = g_malloc0 (sizeof (GfsSolidVector));
+    s->solid->s[0] = s0;
+    
+    if (gts_file_read (fp, &s->solid->s[1], sizeof (gdouble), FTT_NEIGHBORS - 1) != FTT_NEIGHBORS - 1) {
+      gts_file_error (fp, "expecting numbers (solid->s[1..%d])", FTT_NEIGHBORS - 1);
+      return;
+    }
+    if (gts_file_read (fp, &s->solid->a, sizeof (gdouble), 1) != 1) {
+      gts_file_error (fp, "expecting a number (solid->a)");
+      return;
+    }
+    if (gts_file_read (fp, &s->solid->cm.x, sizeof (gdouble), FTT_DIMENSION) != FTT_DIMENSION) {
+      gts_file_error (fp, "expecting numbers (solid->cm[0..%d])", FTT_DIMENSION - 1);
+      return;
+    }
+  }
+
+  v = domain->variables_io;
+  while (v) {
+    gdouble a;
+
+    if (gts_file_read (fp, &a, sizeof (gdouble), 1) != 1) {
+      gts_file_error (fp, "expecting a number (%s)", v->name);
+      return;
+    }
+    GFS_VARIABLE (cell, v->i) = a;
+    v = v->next;
+  }
+}
+
+/**
  * gfs_domain_replace_variable:
  * @domain: a #GfsDomain.
  * @v: the #GfsVariable to replace.
diff --git a/src/domain.h b/src/domain.h
index c61b070..f99c0a0 100644
--- a/src/domain.h
+++ b/src/domain.h
@@ -176,6 +176,15 @@ void         gfs_cell_copy                    (const FttCell * from,
 void         gfs_cell_read                    (FttCell * cell, 
 					       GtsFile * fp,
 					       GfsDomain * domain);
+void         gfs_cell_write                   (const FttCell * cell, 
+					       FILE * fp,
+					       GfsVariable * variables);
+void         gfs_cell_read_binary             (FttCell * cell, 
+					       GtsFile * fp,
+					       GfsDomain * domain);
+void         gfs_cell_write_binary            (const FttCell * cell, 
+					       FILE * fp,
+					       GfsVariable * variables);
 void         gfs_domain_replace_variable      (GfsDomain * domain,
 					       GfsVariable * v,
 					       GfsVariable * with);
diff --git a/src/fluid.c b/src/fluid.c
index 703d4c4..b164be3 100644
--- a/src/fluid.c
+++ b/src/fluid.c
@@ -819,7 +819,7 @@ static gboolean face_bilinear (const FttCellFace * face,
     (*cell_pos) (n[i + 1], &cm);
     cm.x = (cm.x - o->x)/size;
     cm.y = (cm.y - o->y)/size;
-    g_assert (fabs (cm.x) <= 5./2. && fabs (cm.y) <= 5./2.);
+    g_assert (fabs (cm.x) <= 4. && fabs (cm.y) <= 4.);
     m[i][0] = cm.x;
     m[i][1] = cm.y; 
     m[i][2] = cm.x*cm.y;
@@ -1793,42 +1793,6 @@ void gfs_cell_traverse_mixed (FttCell * root,
 }
 
 /**
- * gfs_cell_write:
- * @cell: a #FttCell.
- * @fp: a file pointer.
- * @variables: the #GfsVariable to be written.
- *
- * Writes in @fp the fluid data associated with @cell and described by
- * @variables. This function is generally used in association with
- * ftt_cell_write().  
- */
-void gfs_cell_write (const FttCell * cell, FILE * fp, 
-		     GfsVariable * variables)
-{
-  g_return_if_fail (cell != NULL);
-  g_return_if_fail (fp != NULL);
-
-  if (GFS_IS_MIXED (cell)) {
-    GfsStateVector * s = GFS_STATE (cell);
-    guint i;
-
-    for (i = 0; i < FTT_NEIGHBORS; i++)
-      fprintf (fp, " %g", s->solid->s[i]);
-    fprintf (fp, " %g", s->solid->a);
-    for (i = 0; i < FTT_DIMENSION; i++)
-      fprintf (fp, " %g", (&s->solid->cm.x)[i]);
-  }
-  else
-    fputs (" -1", fp);
-  
-  while (variables) {
-    if (variables->name)
-      fprintf (fp, " %g", GFS_VARIABLE (cell, variables->i));
-    variables = variables->next;
-  }
-}
-
-/**
  * gfs_interpolate:
  * @cell: a #FttCell containing location @p.
  * @p: the location at which to interpolate.
diff --git a/src/fluid.h b/src/fluid.h
index a46ecc2..010de42 100644
--- a/src/fluid.h
+++ b/src/fluid.h
@@ -183,9 +183,6 @@ GTS_C_VAR GfsVariable * gfs_derived_first, * gfs_derived_last;
 void                  gfs_cell_cleanup              (FttCell * cell);
 void                  gfs_cell_reset                (FttCell * cell, 
 						     GfsVariable * v);
-void                  gfs_cell_write                (const FttCell * cell, 
-						     FILE * fp,
-						     GfsVariable * variables);
 void                  gfs_get_from_above            (FttCell * cell, 
 						     const GfsVariable * v);
 void                  gfs_get_from_below_intensive  (FttCell * cell, 
diff --git a/src/ftt.c b/src/ftt.c
index f5cfe68..de4d844 100644
--- a/src/ftt.c
+++ b/src/ftt.c
@@ -1698,13 +1698,8 @@ void ftt_cell_destroy (FttCell * cell,
 	g_assert (opneighbor == cell);
 	FTT_ROOT_CELL (neighbor.c[i])->neighbors.c[od] = NULL;
       }
-      if (!FTT_CELL_IS_LEAF (neighbor.c[i])) {
-	FttOct * children = neighbor.c[i]->children;
-	FttCell * opneighbor = children->neighbors.c[od];
-	
-	/* g_assert (opneighbor == NULL || opneighbor == cell); */
-	children->neighbors.c[od] = NULL;
-      }
+      if (!FTT_CELL_IS_LEAF (neighbor.c[i]))
+	neighbor.c[i]->children->neighbors.c[od] = NULL;
     }
   
   if (FTT_CELL_IS_ROOT (cell))
@@ -1984,6 +1979,48 @@ void ftt_cell_write (const FttCell * root,
   }
 }
 
+/**
+ * ftt_cell_write_binary:
+ * @root: a #FttCell.
+ * @max_depth: the maximum depth at which to stop writing (-1 means no limit).
+ * @fp: a file pointer.
+ * @write: a #FttCellWriteFunc function or %NULL.
+ * @data: user data to pass to @write.
+ *
+ * Writes in the file pointed to by @fp a binary representation of the
+ * cell tree starting at @root. If not %NULL, the user-defined
+ * function @write is used to write the extra user data associated
+ * with each cell.  
+ */
+void ftt_cell_write_binary (const FttCell * root,
+			    gint max_depth,
+			    FILE * fp,
+			    FttCellWriteFunc write,
+			    gpointer data)
+{
+  guint flags;
+
+  g_return_if_fail (root != NULL);
+  g_return_if_fail (fp != NULL);
+
+  flags = root->flags;
+  if (FTT_CELL_IS_LEAF (root) || ftt_cell_level (root) == max_depth)
+    flags |= FTT_FLAG_LEAF;
+
+  fwrite (&flags, sizeof (guint), 1, fp);
+  if (write && !FTT_CELL_IS_DESTROYED (root))
+    (* write) (root, fp, data);
+
+  if ((flags & FTT_FLAG_LEAF) == 0) {
+    FttOct * oct;
+    guint i;
+
+    oct = root->children;
+    for (i = 0; i < FTT_CELLS; i++)
+      ftt_cell_write_binary (&(oct->cell[i]), max_depth, fp, write, data);
+  }
+}
+
 #define FTT_CELL_IS_FLAGGED_LEAF(cell) (((cell)->flags & FTT_FLAG_LEAF) != 0)
 
 static gboolean oct_read (FttCell * parent, 
@@ -2093,6 +2130,105 @@ FttCell * ftt_cell_read (GtsFile * fp,
   return root;
 }
 
+static gboolean oct_read_binary (FttCell * parent, 
+				 GtsFile * fp,
+				 FttCellReadFunc read,
+				 gpointer data);
+
+static gboolean cell_read_binary (FttCell * cell, 
+				  GtsFile * fp,
+				  FttCellReadFunc read,
+				  gpointer data)
+{
+  guint flags;
+
+  if (gts_file_read (fp, &flags, sizeof (guint), 1) != 1) {
+    gts_file_error (fp, "expecting an integer (flags)");
+    return FALSE;
+  }
+  if (FTT_CELL_ID (cell) != (flags & FTT_FLAG_ID)) {
+    gts_file_error (fp, "flags `%d' != (flags & FTT_FLAG_ID) `%d'",
+		    flags, (flags & FTT_FLAG_ID));
+    return FALSE;
+  }
+  cell->flags = flags;
+
+  if (read && !FTT_CELL_IS_DESTROYED (cell))
+    (* read) (cell, fp, data);
+  if (fp->type == GTS_ERROR)
+    return FALSE;
+
+  if (!FTT_CELL_IS_DESTROYED (cell) && !FTT_CELL_IS_FLAGGED_LEAF (cell))
+    return oct_read_binary (cell, fp, read, data);
+
+  cell->flags &= ~FTT_FLAG_LEAF;
+  return TRUE;
+}
+
+static gboolean oct_read_binary (FttCell * parent,
+				 GtsFile * fp,
+				 FttCellReadFunc read,
+				 gpointer data)
+{
+  FttOct * oct;
+  guint n;
+
+  oct = g_malloc0 (sizeof (FttOct));
+  oct->level = ftt_cell_level (parent);
+  oct->parent = parent;
+#ifdef FTT_2D3
+  oct->dz = ftt_cell_dz (parent);
+#endif
+  parent->children = oct;
+  ftt_cell_pos (parent, &(oct->pos));
+  
+  for (n = 0; n < FTT_CELLS; n++) {
+    oct->cell[n].parent = oct;
+    oct->cell[n].flags = n;
+  }
+
+  for (n = 0; n < FTT_CELLS; n++)
+    if (!cell_read_binary (&(oct->cell[n]), fp, read, data))
+      return FALSE;
+  
+  return TRUE;
+}
+
+/**
+ * ftt_cell_read_binary:
+ * @fp: a #GtsFile.
+ * @read: a #FttCellReadFunc function or %NULL.
+ * @data: user data to pass to @read.
+ *
+ * If an error occurs (i.e. corrupted file or file format incorrect),
+ * the @error field of @fp is set. A possibly incomplete tree is then
+ * returned.
+ *
+ * Returns: the root cell of the tree contained in the file pointed to
+ * by @fp. If not %NULL, the user-defined function @read is used to
+ * read the extra user data associated with each cell.  
+ */
+FttCell * ftt_cell_read_binary (GtsFile * fp,
+				FttCellReadFunc read,
+				gpointer data)
+{
+  FttCell * root;
+  guint l, depth;
+
+  g_return_val_if_fail (fp != NULL, NULL);
+
+  root = ftt_cell_new (NULL, NULL);
+  cell_read_binary (root, fp, read, data);
+
+  depth = ftt_cell_depth (root);
+  for (l = 0; l < depth; l++)
+    ftt_cell_traverse (root, FTT_PRE_ORDER, 
+		       FTT_TRAVERSE_LEVEL|FTT_TRAVERSE_NON_LEAFS, l, 
+		       (FttCellTraverseFunc) set_neighbors, NULL);
+
+  return root;
+}
+
 /**
  * ftt_refine_corner:
  * @cell: a #FttCell.
diff --git a/src/ftt.h b/src/ftt.h
index 2b7dea9..31c3715 100644
--- a/src/ftt.h
+++ b/src/ftt.h
@@ -711,12 +711,20 @@ void                 ftt_cell_write                  (const FttCell * root,
 						      FILE * fp,
 						      FttCellWriteFunc write,
 						      gpointer data);
+void                 ftt_cell_write_binary           (const FttCell * root,
+						      gint max_depth,
+						      FILE * fp,
+						      FttCellWriteFunc write,
+						      gpointer data);
 typedef void      (* FttCellReadFunc)                (FttCell * cell,
 						      GtsFile * fp,
 						      gpointer data);
 FttCell *            ftt_cell_read                   (GtsFile * fp,
 						      FttCellReadFunc read,
 						      gpointer data);
+FttCell *            ftt_cell_read_binary            (GtsFile * fp,
+						      FttCellReadFunc read,
+						      gpointer data);
 typedef void      (* FttCellCleanupFunc)             (FttCell * cell,
 						      gpointer data);
 void                 ftt_cell_destroy           (FttCell * cell,
diff --git a/src/gerris.c b/src/gerris.c
index 80e829f..f02ce24 100644
--- a/src/gerris.c
+++ b/src/gerris.c
@@ -120,7 +120,7 @@ int main (int argc, char * argv[])
     return 1; /* failure */
   }
 
-  fptr = fopen (argv[optind], "rt");
+  fptr = fopen (argv[optind], "r");
   if (fptr == NULL) {
     fprintf (stderr, "gerris: unable to open file `%s'\n", argv[optind]);
     return 1;
diff --git a/src/output.c b/src/output.c
index a73c607..d076cfe 100644
--- a/src/output.c
+++ b/src/output.c
@@ -1162,12 +1162,15 @@ static gboolean output_simulation_event (GfsEvent * event, GfsSimulation * sim)
   if ((* GFS_EVENT_CLASS (gfs_output_class())->event) (event, sim)) {
     GfsDomain * domain = GFS_DOMAIN (sim);
     GfsVariable * var = domain->variables_io;
+    gboolean binary = domain->binary;
 
     domain->variables_io = GFS_OUTPUT_SIMULATION (event)->var;
-    gfs_simulation_write (sim, 
-			 GFS_OUTPUT_SIMULATION (event)->max_depth,
-			 GFS_OUTPUT (event)->file->fp);
+    domain->binary = GFS_OUTPUT_SIMULATION (event)->binary;
+    gfs_simulation_write (sim,
+			  GFS_OUTPUT_SIMULATION (event)->max_depth,
+			  GFS_OUTPUT (event)->file->fp);
     domain->variables_io = var;
+    domain->binary = binary;
     fflush (GFS_OUTPUT (event)->file->fp);
     return TRUE;
   }
@@ -1179,8 +1182,7 @@ static void output_simulation_write (GtsObject * o, FILE * fp)
   GfsOutputSimulation * output = GFS_OUTPUT_SIMULATION (o);
   GfsVariable * v = output->var;
 
-  (* GTS_OBJECT_CLASS (gfs_output_simulation_class ())->parent_class->write) 
-    (o, fp);
+  (* GTS_OBJECT_CLASS (gfs_output_simulation_class ())->parent_class->write) (o, fp);
 
   fputs (" {", fp);
   if (output->max_depth != -1)
@@ -1194,14 +1196,17 @@ static void output_simulation_write (GtsObject * o, FILE * fp)
       v = v->next;
     }
   }
+  if (output->binary)
+    fputs (" binary = 1", fp);
   fputs (" }", fp);
 }
 
 static void output_simulation_read (GtsObject ** o, GtsFile * fp)
 {
   GtsFileVariable var[] = {
-    {GTS_INT,    "depth", TRUE},
+    {GTS_INT,    "depth",     TRUE},
     {GTS_STRING, "variables", TRUE},
+    {GTS_INT,    "binary",    TRUE},
     {GTS_NONE}
   };
   gchar * variables = NULL;
@@ -1215,6 +1220,7 @@ static void output_simulation_read (GtsObject ** o, GtsFile * fp)
 
   var[0].data = &output->max_depth;
   var[1].data = &variables;
+  var[2].data = &output->binary;
   gts_file_assign_variables (fp, var);
   if (fp->type == GTS_ERROR) {
     g_free (variables);
diff --git a/src/output.h b/src/output.h
index d7527cf..e4072b0 100644
--- a/src/output.h
+++ b/src/output.h
@@ -132,6 +132,7 @@ struct _GfsOutputSimulation {
 
   gint max_depth;
   GfsVariable * var;
+  gboolean binary;
 };
 
 #define GFS_OUTPUT_SIMULATION(obj)            GTS_OBJECT_CAST (obj,\

-- 
Gerris Flow Solver



More information about the debian-science-commits mailing list