static void gfs_refine_refine (GfsRefine * refine, GfsSimulation * sim) { gfs_catch_floating_point_exceptions (); gts_container_foreach (GTS_CONTAINER (sim), (GtsFunc) refine_box, refine->maxlevel); gfs_restore_fpe_for_function (refine->maxlevel); }
static void swap_face_fractions (GfsSimulation * sim) { GfsDomain * domain = GFS_DOMAIN (sim); gfs_domain_cell_traverse (domain, FTT_PRE_ORDER, FTT_TRAVERSE_ALL, -1, (FttCellTraverseFunc) swap_fractions, GFS_SIMULATION_MOVING (sim)->old_solid); gts_container_foreach (GTS_CONTAINER (domain), (GtsFunc) foreach_box, NULL); }
/** * gts_graph_bisection_check: * @bg: a #GtsGraphBisection. * * Checks that the boundary of @bg is correctly defined (used for * debugging purposes). * * Returns: %TRUE if @bg is ok, %FALSE otherwise. */ gboolean gts_graph_bisection_check (GtsGraphBisection * bg) { gboolean ok = TRUE; guint nb; gpointer data[4]; g_return_val_if_fail (bg != NULL, FALSE); nb = 0; data[0] = bg->bg1; data[1] = bg->g2; data[2] = &ok; data[3] = &nb; gts_container_foreach (GTS_CONTAINER (bg->g1), (GtsFunc) check_bg, data); g_return_val_if_fail (g_hash_table_size (bg->bg1) == nb, FALSE); nb = 0; data[0] = bg->bg2; data[1] = bg->g1; gts_container_foreach (GTS_CONTAINER (bg->g2), (GtsFunc) check_bg, data); g_return_val_if_fail (g_hash_table_size (bg->bg2) == nb, FALSE); return ok; }
/** * gts_graph_bisection_bkl_refine: * @bg: a #GtsGraphBisection. * @mmax: the maximum number of unsuccessful successive moves. * @imbalance: the maximum relative imbalance allowed between the * weights of both halves of the partition. * * An implementation of the simplified boundary Kernighan-Lin * algorithm for graph bisection refinement as described in Karypis * and Kumar (1997). * * The algorithm stops if @mmax consecutive modes do not lead to a * decrease in the number of edges cut. This last @mmax moves are * undone. * * Returns: the decrease in the weight of the edges cut by the bisection. */ gdouble gts_graph_bisection_bkl_refine (GtsGraphBisection * bg, guint mmax, gfloat imbalance) { GtsEHeap * h1, * h2; GtsGNode * n; guint nm = 0, i; GtsGNode ** moves; gdouble bestcost = 0., totalcost = 0., best_balance; gboolean balanced = FALSE; g_return_val_if_fail (bg != NULL, 0.); g_return_val_if_fail (mmax > 0, 0.); g_return_val_if_fail (imbalance >= 0. && imbalance <= 1., 0.); h1 = gts_eheap_new ((GtsKeyFunc) node_move_cost1, bg); gts_eheap_freeze (h1); g_hash_table_foreach (bg->bg1, (GHFunc) build_bheap, h1); gts_eheap_thaw (h1); h2 = gts_eheap_new ((GtsKeyFunc) node_move_cost2, bg); gts_eheap_freeze (h2); g_hash_table_foreach (bg->bg2, (GHFunc) build_bheap, h2); gts_eheap_thaw (h2); moves = g_malloc (sizeof (GtsGNode *)*mmax); imbalance *= gts_graph_weight (bg->g); best_balance = fabs (gts_graph_weight (bg->g1) - gts_graph_weight (bg->g2)); if (best_balance <= imbalance) balanced = TRUE; do { GtsGraph * g1, * g2; GHashTable * bg1, * bg2; gdouble cost; if (gts_graph_weight (bg->g1) > gts_graph_weight (bg->g2)) { n = gts_eheap_remove_top (h1, &cost); g1 = bg->g1; g2 = bg->g2; bg1 = bg->bg1; bg2 = bg->bg2; } else { n = gts_eheap_remove_top (h2, &cost); g1 = bg->g2; g2 = bg->g1; bg1 = bg->bg2; bg2 = bg->bg1; } if (n) { gdouble balance; GTS_OBJECT (n)->reserved = n; gts_container_add (GTS_CONTAINER (g2), GTS_CONTAINEE (n)); gts_container_remove (GTS_CONTAINER (g1), GTS_CONTAINEE (n)); g_hash_table_remove (bg1, n); if (gts_gnode_degree (n, g1)) g_hash_table_insert (bg2, n, n); update_neighbors (n, bg, h1, h2); totalcost += cost; balance = fabs (gts_graph_weight (g1) - gts_graph_weight (g2)); if (!balanced && balance <= imbalance) { bestcost = totalcost; best_balance = balance; balanced = TRUE; nm = 0; } else if (totalcost < bestcost && (balance < best_balance || balance <= imbalance)) { bestcost = totalcost; best_balance = balance; nm = 0; } else if (totalcost == bestcost && balance < best_balance) { best_balance = balance; nm = 0; } else moves[nm++] = n; } } while (n && nm < mmax); gts_container_foreach (GTS_CONTAINER (bg->g), (GtsFunc) gts_object_reset_reserved, NULL); gts_eheap_destroy (h1); gts_eheap_destroy (h2); /* undo last nm moves */ for (i = 0; i < nm; i++) { GtsGNode * n = moves[i]; GtsGraph * g1, * g2; GHashTable * bg1, * bg2; if (gts_containee_is_contained (GTS_CONTAINEE (n), GTS_CONTAINER (bg->g1))) { g1 = bg->g1; g2 = bg->g2; bg1 = bg->bg1; bg2 = bg->bg2; } else { g1 = bg->g2; g2 = bg->g1; bg1 = bg->bg2; bg2 = bg->bg1; } gts_container_add (GTS_CONTAINER (g2), GTS_CONTAINEE (n)); gts_container_remove (GTS_CONTAINER (g1), GTS_CONTAINEE (n)); g_hash_table_remove (bg1, n); if (gts_gnode_degree (n, g1)) g_hash_table_insert (bg2, n, n); update_neighbors (n, bg, NULL, NULL); } g_free (moves); return bestcost; }
/** * gts_graph_bisection_kl_refine: * @bg: a #GtsGraphBisection. * @mmax: the maximum number of unsuccessful successive moves. * * An implementation of the simplified Kernighan-Lin algorithm for * graph bisection refinement as described in Karypis and Kumar * (1997). * * The algorithm stops if @mmax consecutive modes do not lead to a * decrease in the number of edges cut. This last @mmax moves are * undone. * * Returns: the decrease in the weight of the edges cut by the bisection. */ gdouble gts_graph_bisection_kl_refine (GtsGraphBisection * bg, guint mmax) { GtsEHeap * h1, * h2; GtsGNode * n; guint nm = 0, i; GtsGNode ** moves; gdouble bestcost = 0., totalcost = 0., best_balance; g_return_val_if_fail (bg != NULL, 0.); g_return_val_if_fail (mmax > 0, 0.); h1 = gts_eheap_new ((GtsKeyFunc) node_move_cost1, bg); gts_eheap_freeze (h1); gts_container_foreach (GTS_CONTAINER (bg->g1), (GtsFunc) build_heap, h1); gts_eheap_thaw (h1); h2 = gts_eheap_new ((GtsKeyFunc) node_move_cost2, bg); gts_eheap_freeze (h2); gts_container_foreach (GTS_CONTAINER (bg->g2), (GtsFunc) build_heap, h2); gts_eheap_thaw (h2); moves = g_malloc (sizeof (GtsGNode *)*mmax); best_balance = fabs (gts_graph_weight (bg->g1) - gts_graph_weight (bg->g2)); do { GtsGraph * g1, * g2; gdouble cost; if (gts_graph_weight (bg->g1) > gts_graph_weight (bg->g2)) { n = gts_eheap_remove_top (h1, &cost); g1 = bg->g1; g2 = bg->g2; } else { n = gts_eheap_remove_top (h2, &cost); g1 = bg->g2; g2 = bg->g1; } if (n) { GSList * i; GTS_OBJECT (n)->reserved = NULL; gts_container_add (GTS_CONTAINER (g2), GTS_CONTAINEE (n)); gts_container_remove (GTS_CONTAINER (g1), GTS_CONTAINEE (n)); totalcost += cost; if (totalcost < bestcost) { bestcost = totalcost; nm = 0; } else if (totalcost == bestcost) { gdouble balance = fabs (gts_graph_weight (g1) - gts_graph_weight (g2)); if (balance < best_balance) { best_balance = balance; nm = 0; } } else moves[nm++] = n; i = GTS_SLIST_CONTAINER (n)->items; while (i) { GtsGNode * n1 = GTS_GNODE_NEIGHBOR (n, i->data); if (GTS_OBJECT (n1)->reserved && gts_containee_is_contained (GTS_CONTAINEE (n1), GTS_CONTAINER (bg->g))) { GtsEHeap * h = gts_containee_is_contained (GTS_CONTAINEE (n1), GTS_CONTAINER (bg->g1)) ? h1 : h2; gts_eheap_remove (h, GTS_OBJECT (n1)->reserved); GTS_OBJECT (n1)->reserved = gts_eheap_insert (h, n1); } i = i->next; } } } while (n && nm < mmax); gts_eheap_foreach (h1, (GFunc) gts_object_reset_reserved, NULL); gts_eheap_foreach (h2, (GFunc) gts_object_reset_reserved, NULL); gts_eheap_destroy (h1); gts_eheap_destroy (h2); /* undo last nm moves */ for (i = 0; i < nm; i++) { GtsGNode * n = moves[i]; GtsGraph * g1 = gts_containee_is_contained (GTS_CONTAINEE (n), GTS_CONTAINER (bg->g1)) ? bg->g1 : bg->g2; GtsGraph * g2 = g1 == bg->g1 ? bg->g2 : bg->g1; gts_container_add (GTS_CONTAINER (g2), GTS_CONTAINEE (n)); gts_container_remove (GTS_CONTAINER (g1), GTS_CONTAINEE (n)); } g_free (moves); return bestcost; }
/** * gts_graph_bfgg_bisection: * @g: a #GtsGraph. * @ntry: the number of randomly selected initial seeds. * * An implementation of a "Breadth-First Graph Growing" algorithm. * * @ntry randomly chosen seeds are used and the best partition is retained. * * Returns: a new #GtsGraphBisection of @g. */ GtsGraphBisection * gts_graph_bfgg_bisection (GtsGraph * g, guint ntry) { gfloat size, bestcost = G_MAXFLOAT, smin; GtsGraph * bestg1 = NULL, * bestg2 = NULL; GtsEHeap * degree_heap; GtsGNode * seed; GtsGraphBisection * bg; g_return_val_if_fail (g != NULL, NULL); bg = g_malloc (sizeof (GtsGraphBisection)); bg->g = g; size = gts_graph_weight (g)/2.; smin = 0.9*size; degree_heap = gts_eheap_new ((GtsKeyFunc) degree_cost, g); gts_eheap_freeze (degree_heap); gts_container_foreach (GTS_CONTAINER (g), (GtsFunc) add_seed, degree_heap); gts_eheap_thaw (degree_heap); while (ntry && ((seed = gts_eheap_remove_top (degree_heap, NULL)))) { GtsGraph * g1, * g2; GtsGNode * n; gdouble cost; GtsGraphTraverse * t = gts_graph_traverse_new (g, seed, GTS_BREADTH_FIRST, TRUE); g1 = gts_graph_new (GTS_GRAPH_CLASS (GTS_OBJECT (g)->klass), g->node_class, g->edge_class); g2 = gts_graph_new (GTS_GRAPH_CLASS (GTS_OBJECT (g)->klass), g->node_class, g->edge_class); while ((n = gts_graph_traverse_next (t))) if (gts_graph_weight (g1) + gts_gnode_weight (n) <= size) { gts_container_add (GTS_CONTAINER (g1), GTS_CONTAINEE (n)); GTS_OBJECT (n)->reserved = n; } gts_graph_traverse_destroy (t); gts_container_foreach (GTS_CONTAINER (g), (GtsFunc) add_unused, g2); cost = gts_graph_edges_cut_weight (g1); if (!bestg1 || (cost < bestcost && gts_graph_weight (g1) >= smin)) { if (bestg1) bestcost = cost; if (bestg1) gts_object_destroy (GTS_OBJECT (bestg1)); if (bestg2) gts_object_destroy (GTS_OBJECT (bestg2)); bestg1 = g1; bestg2 = g2; } else { gts_object_destroy (GTS_OBJECT (g1)); gts_object_destroy (GTS_OBJECT (g2)); } ntry--; } gts_eheap_destroy (degree_heap); #ifdef DEBUG fprintf (stderr, "bestcost: %5g g1: %5g|%5d g2: %5g|%5d\n", bestcost, gts_graph_weight (bestg1), gts_container_size (GTS_CONTAINER (bestg1)), gts_graph_weight (bestg2), gts_container_size (GTS_CONTAINER (bestg2))); #endif bg->g1 = bestg1; bg->g2 = bestg2; /* boundary nodes */ bg->bg1 = g_hash_table_new (NULL, NULL); gts_container_foreach (GTS_CONTAINER (bg->g1), (GtsFunc) boundary_node1, bg); bg->bg2 = g_hash_table_new (NULL, NULL); gts_container_foreach (GTS_CONTAINER (bg->g2), (GtsFunc) boundary_node2, bg); return bg; }
/** * gts_graph_ggg_bisection: * @g: a #GtsGraph. * @ntry: the number of randomly selected initial seeds. * * An implementation of the "Greedy Graph Growing" algorithm of * Karypis and Kumar (1997). * * @ntry randomly chosen seeds are used and the best partition is retained. * * Returns: a new #GtsGraphBisection of @g. */ GtsGraphBisection * gts_graph_ggg_bisection (GtsGraph * g, guint ntry) { gfloat size, bestcost = G_MAXFLOAT, smin; GtsGraph * bestg1 = NULL, * bestg2 = NULL; gboolean balanced = FALSE; GtsEHeap * degree_heap; GtsGNode * seed; GtsGraphBisection * bg; g_return_val_if_fail (g != NULL, NULL); bg = g_malloc (sizeof (GtsGraphBisection)); bg->g = g; size = gts_graph_weight (g)/2.; smin = 0.9*size; degree_heap = gts_eheap_new ((GtsKeyFunc) degree_cost, g); gts_eheap_freeze (degree_heap); gts_container_foreach (GTS_CONTAINER (g), (GtsFunc) add_seed, degree_heap); gts_eheap_thaw (degree_heap); while (ntry && ((seed = gts_eheap_remove_top (degree_heap, NULL)))) { GtsGraph * g1, * g2; GtsGNode * n; gdouble cost; gpointer data[2]; GtsEHeap * heap; g1 = gts_graph_new (GTS_GRAPH_CLASS (GTS_OBJECT (g)->klass), g->node_class, g->edge_class); g2 = gts_graph_new (GTS_GRAPH_CLASS (GTS_OBJECT (g)->klass), g->node_class, g->edge_class); data[0] = g; data[1] = g1; heap = gts_eheap_new ((GtsKeyFunc) node_cost, data); gts_container_add (GTS_CONTAINER (g1), GTS_CONTAINEE (seed)); GTS_OBJECT (seed)->reserved = seed; gts_gnode_foreach_neighbor (seed, g, (GtsFunc) add_neighbor, heap); while ((n = gts_eheap_remove_top (heap, &cost))) if (gts_graph_weight (g1) + gts_gnode_weight (n) <= size) { gts_container_add (GTS_CONTAINER (g1), GTS_CONTAINEE (n)); GTS_OBJECT (n)->reserved = n; gts_gnode_foreach_neighbor (n, g, (GtsFunc) add_neighbor, heap); } else GTS_OBJECT (n)->reserved = NULL; gts_eheap_destroy (heap); gts_container_foreach (GTS_CONTAINER (g), (GtsFunc) add_unused, g2); cost = gts_graph_edges_cut_weight (g1); if (!bestg1 || (!balanced && gts_graph_weight (g1) >= smin) || (cost < bestcost && gts_graph_weight (g1) >= smin)) { if (bestg1) bestcost = cost; if (bestg1) gts_object_destroy (GTS_OBJECT (bestg1)); if (bestg2) gts_object_destroy (GTS_OBJECT (bestg2)); bestg1 = g1; bestg2 = g2; if (gts_graph_weight (g1) >= smin) balanced = TRUE; } else { gts_object_destroy (GTS_OBJECT (g1)); gts_object_destroy (GTS_OBJECT (g2)); } ntry--; } gts_eheap_destroy (degree_heap); #ifdef DEBUG fprintf (stderr, "bestcost: %5g g1: %5g|%5d g2: %5g|%5d\n", bestcost, gts_graph_weight (bestg1), gts_container_size (GTS_CONTAINER (bestg1)), gts_graph_weight (bestg2), gts_container_size (GTS_CONTAINER (bestg2))); #endif g_assert (bestg1 != NULL); bg->g1 = bestg1; g_assert (bestg2 != NULL); bg->g2 = bestg2; /* boundary nodes */ bg->bg1 = g_hash_table_new (NULL, NULL); gts_container_foreach (GTS_CONTAINER (bg->g1), (GtsFunc) boundary_node1, bg); bg->bg2 = g_hash_table_new (NULL, NULL); gts_container_foreach (GTS_CONTAINER (bg->g2), (GtsFunc) boundary_node2, bg); return bg; }
/** * gts_graph_bubble_partition: * @g: a #GtsGraph. * @np: number of partitions. * @niter: the maximum number of iterations. * @step_info: a #GtsFunc or %NULL. * @data: user data to pass to @step_info. * * An implementation of the "bubble partitioning algorithm" of * Diekmann, Preis, Schlimbach and Walshaw (2000). The maximum number * of iteration on the positions of the graph growing seeds is * controlled by @niter. * * If not %NULL @step_info is called after each iteration on the seeds * positions passing the partition (a GSList) as argument. * * Returns: a list of @np new #GtsGraph representing the partition. */ GSList * gts_graph_bubble_partition (GtsGraph * g, guint np, guint niter, GtsFunc step_info, gpointer data) { GSList * list = NULL, * seeds = NULL; GtsGNode * seed = NULL; guint min = G_MAXINT/2 - 1; gpointer info[3]; GtsGraph * g1; gboolean changed = TRUE; g_return_val_if_fail (g != NULL, NULL); g_return_val_if_fail (np > 0, NULL); info[0] = &seed; info[1] = g; info[2] = &min; gts_container_foreach (GTS_CONTAINER (g), (GtsFunc) find_smallest_degree, info); if (seed == NULL) return NULL; g1 = GTS_GRAPH (gts_object_new (GTS_OBJECT (g)->klass)); gts_container_add (GTS_CONTAINER (g1), GTS_CONTAINEE (seed)); list = g_slist_prepend (list, g1); GTS_OBJECT (g1)->reserved = seed; seeds = g_slist_prepend (seeds, seed); while (--np && seed) if ((seed = gts_graph_farthest (g, seeds))) { g1 = GTS_GRAPH (gts_object_new (GTS_OBJECT (g)->klass)); gts_container_add (GTS_CONTAINER (g1), GTS_CONTAINEE (seed)); list = g_slist_prepend (list, g1); GTS_OBJECT (g1)->reserved = seed; seeds = g_slist_prepend (seeds, seed); } g_slist_free (seeds); partition_update (list, g); while (changed && niter--) { GSList * i; changed = FALSE; i = list; while (i) { GtsGraph * g1 = i->data; GtsGNode * seed = GTS_OBJECT (g1)->reserved; GtsGNode * new_seed = graph_new_seed (g1, seed); if (new_seed != seed) { changed = TRUE; GTS_OBJECT (g1)->reserved = new_seed; } i = i->next; } if (changed) { i = list; while (i) { GtsGraph * g1 = i->data; GtsGNode * seed = GTS_OBJECT (g1)->reserved; gts_object_destroy (GTS_OBJECT (g1)); i->data = g1 = GTS_GRAPH (gts_object_new (GTS_OBJECT (g)->klass)); gts_container_add (GTS_CONTAINER (g1), GTS_CONTAINEE (seed)); GTS_OBJECT (g1)->reserved = seed; i = i->next; } partition_update (list, g); if (step_info) (* step_info) (list, data); } } g_slist_foreach (list, (GFunc) gts_object_reset_reserved, NULL); return list; }
static void wave_run (GfsSimulation * sim) { GfsDomain * domain = GFS_DOMAIN (sim); GfsWave * wave = GFS_WAVE (sim); SolidFluxParams par; par.div = gfs_variable_from_name (domain->variables, "P"); g_assert (par.div); par.p = &sim->advection_params; par.fv = gfs_temporary_variable (domain); gfs_simulation_refine (sim); gfs_simulation_init (sim); while (sim->time.t < sim->time.end && sim->time.i < sim->time.iend) { gdouble tstart = gfs_clock_elapsed (domain->timer); gts_container_foreach (GTS_CONTAINER (sim->events), (GtsFunc) gfs_event_do, sim); /* get global timestep */ gfs_domain_face_traverse (domain, FTT_XYZ, FTT_PRE_ORDER, FTT_TRAVERSE_LEAFS, -1, (FttFaceTraverseFunc) gfs_face_reset_normal_velocity, NULL); gfs_simulation_set_timestep (sim); gdouble dt = sim->advection_params.dt; gdouble g = sim->physical_params.g/sim->physical_params.L; gdouble tnext = sim->tnext; /* spatial advection */ guint ik, ith; for (ik = 0; ik < wave->nk; ik++) { FttVector cg; group_velocity (ik, 0, &cg, wave->ntheta, g); gfs_domain_face_traverse (domain, FTT_XYZ, FTT_PRE_ORDER, FTT_TRAVERSE_LEAFS, -1, (FttFaceTraverseFunc) set_group_velocity, &cg); if (wave->alpha_s > 0.) { /* stability criterion for GSE diffusion */ gdouble cfl = sim->advection_params.cfl; sim->advection_params.cfl = MIN (cfl, 2./(4.*wave->alpha_s*M_PI/wave->ntheta)); /* fixme: this should be: sim->advection_params.cfl = MIN (cfl, sqrt(3.)/(wave->alpha_s*2.*M_PI/wave->ntheta)); */ gfs_simulation_set_timestep (sim); sim->advection_params.cfl = cfl; } else gfs_simulation_set_timestep (sim); /* subcycling */ guint n = rint (dt/sim->advection_params.dt); g_assert (fabs (sim->time.t + sim->advection_params.dt*n - tnext) < 1e-12); while (n--) { for (ith = 0; ith < wave->ntheta; ith++) { FttVector cg; group_velocity (ik, ith, &cg, wave->ntheta, g); gfs_domain_face_traverse (domain, FTT_XYZ, FTT_PRE_ORDER, FTT_TRAVERSE_LEAFS, -1, (FttFaceTraverseFunc) set_group_velocity, &cg); GfsVariable * t = GFS_WAVE (sim)->F[ik][ith]; sim->advection_params.v = t; gfs_domain_traverse_leaves (domain, (FttCellTraverseFunc) solid_flux, &par); gfs_tracer_advection_diffusion (domain, &sim->advection_params, NULL); sim->advection_params.fv = par.fv; gfs_domain_traverse_merged (domain, (GfsMergedTraverseFunc) gfs_advection_update, &sim->advection_params); if (wave->alpha_s > 0.) gse_alleviation_diffusion (domain, t, &cg, sim->advection_params.dt); gfs_domain_bc (domain, FTT_TRAVERSE_LEAFS, -1, t); gfs_domain_cell_traverse (domain, FTT_POST_ORDER, FTT_TRAVERSE_NON_LEAFS, -1, (FttCellTraverseFunc) t->fine_coarse, t); } gts_container_foreach (GTS_CONTAINER (sim->events), (GtsFunc) redo_some_events, sim); gfs_simulation_adapt (sim); } } sim->advection_params.dt = dt; /* source terms */ if (wave->source) (* wave->source) (wave); sim->time.t = sim->tnext = tnext; sim->time.i++; gts_range_add_value (&domain->timestep, gfs_clock_elapsed (domain->timer) - tstart); gts_range_update (&domain->timestep); gts_range_add_value (&domain->size, gfs_domain_size (domain, FTT_TRAVERSE_LEAFS, -1)); gts_range_update (&domain->size); } gts_container_foreach (GTS_CONTAINER (sim->events), (GtsFunc) gfs_event_do, sim); gts_container_foreach (GTS_CONTAINER (sim->events), (GtsFunc) gts_object_destroy, NULL); gts_object_destroy (GTS_OBJECT (par.fv)); }
static void gfs_skew_symmetric_run (GfsSimulation * sim) { GfsVariable * p, * res = NULL, * gmac[FTT_DIMENSION]; GfsDomain * domain; GSList * i; domain = GFS_DOMAIN (sim); p = gfs_variable_from_name (domain->variables, "P"); g_assert (p); FttComponent c; for (c = 0; c < FTT_DIMENSION; c++) gmac[c] = gfs_temporary_variable (domain); gfs_variable_set_vector (gmac, FTT_DIMENSION); gfs_simulation_refine (sim); gfs_simulation_init (sim); i = domain->variables; while (i) { if (GFS_IS_VARIABLE_RESIDUAL (i->data)) res = i->data; i = i->next; } gfs_simulation_set_timestep (sim); GfsVariable ** u = gfs_domain_velocity (domain); GfsVariable ** velfaces = GFS_SKEW_SYMMETRIC(sim)->velfaces; GfsVariable ** velold = GFS_SKEW_SYMMETRIC(sim)->velold; FaceData fd = { velfaces, velold, u, p, &sim->advection_params.dt, GFS_SKEW_SYMMETRIC(sim)->beta}; if (sim->time.i == 0) { gfs_domain_cell_traverse (domain, FTT_PRE_ORDER, FTT_TRAVERSE_LEAFS, -1, (FttCellTraverseFunc) reset_unold, &fd); gfs_domain_cell_traverse (domain, FTT_PRE_ORDER, FTT_TRAVERSE_LEAFS, -1, (FttCellTraverseFunc) get_face_values, &fd); gfs_mac_projection (domain, &sim->projection_params, sim->advection_params.dt/2., p, sim->physical_params.alpha, gmac, NULL); gfs_domain_cell_traverse (domain, FTT_PRE_ORDER, FTT_TRAVERSE_LEAFS, -1, (FttCellTraverseFunc) get_velfaces, &fd); gfs_domain_cell_traverse (domain, FTT_PRE_ORDER, FTT_TRAVERSE_LEAFS, -1, (FttCellTraverseFunc) initialize_unold, &fd); } while (sim->time.t < sim->time.end && sim->time.i < sim->time.iend) { gdouble tstart = gfs_clock_elapsed (domain->timer); gts_container_foreach (GTS_CONTAINER (sim->events), (GtsFunc) gfs_event_do, sim); gfs_skew_symmetric_momentum (sim, &fd, gmac); gfs_mac_projection (domain, &sim->projection_params, sim->advection_params.dt/2., p, sim->physical_params.alpha, gmac, NULL); gfs_domain_cell_traverse (domain, FTT_PRE_ORDER, FTT_TRAVERSE_LEAFS, -1, (FttCellTraverseFunc) correct_face_velocity, NULL); gts_container_foreach (GTS_CONTAINER (sim->events), (GtsFunc) gfs_event_half_do, sim); gfs_domain_cell_traverse (domain, FTT_PRE_ORDER, FTT_TRAVERSE_LEAFS, -1, (FttCellTraverseFunc) get_velfaces, &fd); gfs_domain_cell_traverse (domain, FTT_PRE_ORDER, FTT_TRAVERSE_LEAFS, -1, (FttCellTraverseFunc) get_cell_values, &fd); gfs_domain_cell_traverse (domain, FTT_POST_ORDER, FTT_TRAVERSE_NON_LEAFS, -1, (FttCellTraverseFunc) gfs_cell_coarse_init, domain); gfs_simulation_adapt (sim); sim->time.t = sim->tnext; sim->time.i++; gfs_simulation_set_timestep (sim); gfs_advance_tracers (sim, sim->advection_params.dt); gts_range_add_value (&domain->timestep, gfs_clock_elapsed (domain->timer) - tstart); gts_range_update (&domain->timestep); gts_range_add_value (&domain->size, gfs_domain_size (domain, FTT_TRAVERSE_LEAFS, -1)); gts_range_update (&domain->size); } gts_container_foreach (GTS_CONTAINER (sim->events), (GtsFunc) gfs_event_do, sim); gts_container_foreach (GTS_CONTAINER (sim->events), (GtsFunc) gts_object_destroy, NULL); for (c = 0; c < FTT_DIMENSION; c++) gts_object_destroy (GTS_OBJECT (gmac[c])); }
static void gfs_porous_run (GfsSimulation * sim) { GfsVariable * p, * pmac, * res = NULL, * g[FTT_DIMENSION], * gmac[FTT_DIMENSION]; GfsVariable ** gc = sim->advection_params.gc ? g : NULL; GfsDomain * domain; GfsPorous *por; GSList * i; domain = GFS_DOMAIN (sim); por = GFS_POROUS (sim); p = gfs_variable_from_name (domain->variables, "P"); g_assert (p); pmac = gfs_variable_from_name (domain->variables, "Pmac"); g_assert (pmac); FttComponent c; for (c = 0; c < FTT_DIMENSION; c++) { gmac[c] = gfs_temporary_variable (domain); if (sim->advection_params.gc) g[c] = gfs_temporary_variable (domain); else g[c] = gmac[c]; } gfs_variable_set_vector (gmac, FTT_DIMENSION); gfs_variable_set_vector (g, FTT_DIMENSION); gfs_simulation_refine (sim); gfs_simulation_init (sim); i = domain->variables; while (i) { if (GFS_IS_VARIABLE_RESIDUAL (i->data)) res = i->data; i = i->next; } gfs_simulation_set_timestep (sim); if (sim->time.i == 0) { /*inserted changes inside this function*/ gfs_approximate_projection_por (domain, por, &sim->approx_projection_params, sim->advection_params.dt, p, sim->physical_params.alpha, res, g, NULL); gfs_simulation_set_timestep (sim); gfs_advance_tracers (sim, sim->advection_params.dt/2.); } else if (sim->advection_params.gc) gfs_update_gradients_por (domain, por, p, sim->physical_params.alpha, g); while (sim->time.t < sim->time.end && sim->time.i < sim->time.iend) { gdouble tstart = gfs_clock_elapsed (domain->timer); gts_container_foreach (GTS_CONTAINER (sim->events), (GtsFunc) gfs_event_do, sim); /*inserted changes */ gfs_pre_projection (domain, por, FTT_DIMENSION); if (sim->advection_params.linear) { /* linearised advection */ gfs_domain_face_traverse (domain, FTT_XYZ, FTT_PRE_ORDER, FTT_TRAVERSE_LEAFS, -1, (FttFaceTraverseFunc) gfs_face_reset_normal_velocity, NULL); gfs_domain_face_traverse (domain, FTT_XYZ, FTT_PRE_ORDER, FTT_TRAVERSE_LEAFS, -1, (FttFaceTraverseFunc) gfs_face_interpolated_normal_velocity, sim->u0); } else gfs_predicted_face_velocities (domain, FTT_DIMENSION, &sim->advection_params); gfs_variables_swap (p, pmac); gfs_mac_projection_por (domain, por, &sim->projection_params, sim->advection_params.dt/2., p, sim->physical_params.alpha, gmac, NULL); gfs_variables_swap (p, pmac); gts_container_foreach (GTS_CONTAINER (sim->events), (GtsFunc) gfs_event_half_do, sim); gfs_centered_velocity_advection_diffusion (domain, FTT_DIMENSION, &sim->advection_params, gmac, sim->time.i > 0 || !gc ? gc : gmac, sim->physical_params.alpha); if (gc) { gfs_source_darcy_implicit (domain, sim->advection_params.dt); gfs_correct_centered_velocities (domain, FTT_DIMENSION, sim->time.i > 0 ? gc : gmac, -sim->advection_params.dt); /*inserted changes*/ gfs_post_projection (domain, por, FTT_DIMENSION); } else if (gfs_has_source_coriolis (domain)) { gfs_correct_centered_velocities (domain, FTT_DIMENSION, gmac, sim->advection_params.dt); gfs_source_darcy_implicit (domain, sim->advection_params.dt); gfs_correct_centered_velocities (domain, FTT_DIMENSION, gmac, -sim->advection_params.dt); /*inserted changes*/ gfs_post_projection (domain, por, FTT_DIMENSION); } gfs_domain_cell_traverse (domain, FTT_POST_ORDER, FTT_TRAVERSE_NON_LEAFS, -1, (FttCellTraverseFunc) gfs_cell_coarse_init, domain); gfs_simulation_adapt (sim); /*inserted changes */ gfs_approximate_projection_por (domain, por, &sim->approx_projection_params, sim->advection_params.dt, p, sim->physical_params.alpha, res, g, NULL); /*inserted changes */ sim->time.t = sim->tnext; sim->time.i++; gfs_simulation_set_timestep (sim); gfs_advance_tracers (sim, sim->advection_params.dt); gts_range_add_value (&domain->timestep, gfs_clock_elapsed (domain->timer) - tstart); gts_range_update (&domain->timestep); gts_range_add_value (&domain->size, gfs_domain_size (domain, FTT_TRAVERSE_LEAFS, -1)); gts_range_update (&domain->size); } gts_container_foreach (GTS_CONTAINER (sim->events), (GtsFunc) gfs_event_do, sim); gts_container_foreach (GTS_CONTAINER (sim->events), (GtsFunc) gts_object_destroy, NULL); for (c = 0; c < FTT_DIMENSION; c++) { gts_object_destroy (GTS_OBJECT (gmac[c])); if (sim->advection_params.gc) gts_object_destroy (GTS_OBJECT (g[c])); } }