void gfs_post_projection (GfsDomain *domain, GfsPorous *por, guint dimension) { GfsVariable **v; FttComponent c; gpointer data[3]; g_return_if_fail (domain != NULL); data[0] = v = gfs_domain_velocity (domain); data[1] = &dimension; data[2] = por; gfs_domain_cell_traverse (domain, FTT_PRE_ORDER, FTT_TRAVERSE_LEAFS, -1, (FttCellTraverseFunc) correct_por_undo, data); for (c = 0; c < dimension; c++) gfs_domain_bc (domain, FTT_TRAVERSE_LEAFS, -1, v[c]); printf("\nvelocity correction undo !!!\n"); }
static gboolean gfs_init_stokes_wave_event (GfsEvent * event, GfsSimulation * sim) { if ((* GFS_EVENT_CLASS (GTS_OBJECT_CLASS (gfs_init_stokes_wave_class ())->parent_class)->event) (event, sim)) { GfsVariable ** velocity = gfs_domain_velocity (GFS_DOMAIN (sim)); GfsVariable * t = gfs_variable_from_name (GFS_DOMAIN (sim)->variables, "T"); g_assert (velocity); g_assert (t); gfs_domain_cell_traverse (GFS_DOMAIN (sim), FTT_PRE_ORDER, FTT_TRAVERSE_LEAFS, -1, (FttCellTraverseFunc) init_velocity, velocity); GfsSurface * surface = GFS_SURFACE (gts_object_new (GTS_OBJECT_CLASS (gfs_surface_class ()))); surface->f = gfs_function_spatial_new (gfs_function_spatial_class (), stokes_height); gfs_object_simulation_set (surface->f, sim); gfs_domain_init_fraction (GFS_DOMAIN (sim), GFS_GENERIC_SURFACE (surface), t); gts_object_destroy (GTS_OBJECT (surface)); return TRUE; } return FALSE; }
void gfs_update_gradients_por (GfsDomain * domain, GfsPorous * por, GfsVariable * p, GfsFunction * alpha, GfsVariable ** g) { g_return_if_fail (domain != NULL); g_return_if_fail (p != NULL); g_return_if_fail (g != NULL); /* Add face sources */ gfs_reset_gradients (domain, FTT_DIMENSION, g); gfs_velocity_face_sources (domain, gfs_domain_velocity (domain), 0., alpha, g); /* Initialize face coefficients */ gfs_poisson_coefficients_por (domain, por, alpha, TRUE, TRUE, TRUE); /* Add pressure gradient */ gfs_correct_normal_velocities (domain, FTT_DIMENSION, p, g, 0.); gfs_scale_gradients (domain, FTT_DIMENSION, g); }
void gfs_approximate_projection_por (GfsDomain * domain, GfsPorous * por, GfsMultilevelParams * par, gdouble dt, GfsVariable * p, GfsFunction * alpha, GfsVariable * res, GfsVariable ** g, void (* divergence_hook) (GfsDomain * domain, gdouble dt, GfsVariable * div) ) { g_return_if_fail (domain != NULL); g_return_if_fail (par != NULL); g_return_if_fail (p != NULL); g_return_if_fail (g != NULL); gfs_domain_timer_start (domain, "approximate_projection"); gfs_pre_projection (domain, por, FTT_DIMENSION); /* compute MAC velocities from centered velocities */ 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, gfs_domain_velocity (domain)); mac_projection_por (domain, por, par, dt, p, alpha, res, g, divergence_hook); gfs_correct_centered_velocities (domain, FTT_DIMENSION, g, dt); gfs_post_projection (domain, por, FTT_DIMENSION); gfs_domain_timer_stop (domain, "approximate_projection"); if (par->residual.infty > par->tolerance) g_warning ("approx projection: max residual %g > %g", par->residual.infty, par->tolerance); }
static void darcy_coefficients (GfsSourceDarcy * sd, FttCell * cell, GfsVariable ** u, FttComponent c1, gdouble f[2]) { GfsPorous * por = GFS_POROUS (gfs_object_simulation (sd)); GfsDomain * domain = GFS_DOMAIN(por); GfsFunction * porosity = por->porosity; GfsFunction * K = por->K; gdouble viscosity = 0.001; GfsVariable ** U = gfs_domain_velocity (domain); GfsSourceVelocity * sv = GFS_SOURCE_VELOCITY (domain); GfsSourceDiffusion * d = source_diffusion_viscosity (U[0]); if (d) viscosity = gfs_diffusion_cell (d->D, cell); f[0] = (viscosity * gfs_function_value (porosity,cell))/gfs_function_value (K,cell); gdouble modu; modu = fabs(sqrt(GFS_VALUE (cell, sv->v[0])*GFS_VALUE (cell, sv->v[0]) + GFS_VALUE (cell, sv->v[1])*GFS_VALUE (cell, sv->v[1]))); f[1] = (gfs_function_value (porosity,cell))/sqrt(gfs_function_value (K,cell))*modu; }
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 mac_projection_por (GfsDomain * domain, GfsPorous * por, GfsMultilevelParams * par, gdouble dt, GfsVariable * p, GfsFunction * alpha, GfsVariable * res, GfsVariable ** g, void (* divergence_hook) (GfsDomain * domain, gdouble dt, GfsVariable * div) ) { /* Add face sources */ gfs_reset_gradients (domain, FTT_DIMENSION, g); gfs_velocity_face_sources (domain, gfs_domain_velocity (domain), dt, alpha, g); GfsVariable * dia = gfs_temporary_variable (domain); GfsVariable * div = gfs_temporary_variable (domain); GfsVariable * res1 = res ? res : gfs_temporary_variable (domain); /* Initialize face coefficients */ gfs_poisson_coefficients_por (domain, por, alpha, TRUE, TRUE, TRUE); /* hydrostatic pressure */ GSList * i = domain->variables; while (i) { if (GFS_IS_HYDROSTATIC_PRESSURE (i->data)) gfs_correct_normal_velocities (domain, FTT_DIMENSION, i->data, g, dt); i = i->next; } /* Initialize diagonal coefficient */ gfs_domain_cell_traverse (domain, FTT_PRE_ORDER, FTT_TRAVERSE_ALL, -1, (FttCellTraverseFunc) gfs_cell_reset, dia); /* compute MAC divergence */ gfs_domain_cell_traverse (domain, FTT_PRE_ORDER, FTT_TRAVERSE_LEAFS, -1, (FttCellTraverseFunc) gfs_normal_divergence, div); /* Divergence hook */ if (divergence_hook) (* divergence_hook) (domain, dt, div); /* add volume sources (if any) */ if (p->sources) volume_sources (domain, p, div); /* Scale divergence */ gpointer data[2]; data[0] = div; data[1] = &dt; gfs_domain_cell_traverse (domain, FTT_PRE_ORDER, FTT_TRAVERSE_LEAFS, -1, (FttCellTraverseFunc) scale_divergence, data); #if 0 { FILE * fp = fopen ("/tmp/mac", "wt"); GfsNorm norm; gfs_write_mac_velocity (domain, 0.9, FTT_TRAVERSE_LEAFS, -1, NULL, fp); fclose (fp); norm = gfs_domain_norm_variable (domain, div, FTT_TRAVERSE_LEAFS, -1); fprintf (stderr, "mac div before: %g %g %g\n", norm.first, norm.second, norm.infty); } #endif par->poisson_solve (domain, par, p, div, res1, dia, dt); gts_object_destroy (GTS_OBJECT (dia)); gts_object_destroy (GTS_OBJECT (div)); if (!res) gts_object_destroy (GTS_OBJECT (res1)); gfs_correct_normal_velocities (domain, FTT_DIMENSION, p, g, dt); gfs_scale_gradients (domain, FTT_DIMENSION, g); }