[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