static double new_solid_old_solid (FttCell * cell, FttDirection d1, GfsVariable * old_solid, GfsVariable ** sold2) { FttDirection d; FttCellNeighbors neighbors; double s1, s2; g_assert(cell); s1 = GFS_STATE (cell)->solid->s[d1]; ftt_cell_neighbors (cell,&neighbors); for (d = 0; d < 2*FTT_DIMENSION;d++) if (d != 2*(d1/2) && d != 2*(d1/2)+1) if (neighbors.c[d] && !cell_is_corner(neighbors.c[d]) && !cell_was_corner(neighbors.c[d], old_solid, sold2)) { if ((GFS_IS_MIXED(neighbors.c[d]) && GFS_STATE(neighbors.c[d])->solid->s[d1] == 1.) || !GFS_IS_MIXED(neighbors.c[d])) { if (SOLD2 (neighbors.c[d], d1) != 1.){ s2 = 1.-SOLD2 (neighbors.c[d], d1); return s1/(s1+s2); } } else if ((GFS_STATE(cell)->solid->s[d1] == 0. && GFS_IS_MIXED(neighbors.c[d])) ) { s1 = SOLD2 (cell, d1); s2 = 1.-GFS_STATE(neighbors.c[d])->solid->s[d1]; return s2/(s1+s2); } } return -1.; }
static void poisson_mixed_coeff_por (FttCell * cell, PoissonCoeff_por * p) { if (GFS_IS_MIXED (cell)) { gdouble alpha = p->alpha ? (gfs_function_value (p->alpha, cell)*gfs_function_value (p->phi , cell)) : gfs_function_value (p->phi, cell); if (((cell)->flags & GFS_FLAG_DIRICHLET) == 0) /* Neumann condition (prescribed flux) */ GFS_STATE (cell)->solid->v.x += alpha; else { /* Dirichlet */ GfsSolidVector * s = GFS_STATE (cell)->solid; FttVector m = {1.,1.,1.}; gfs_domain_solid_metric (p->domain, cell, &m); FttComponent c; for (c = 0; c < FTT_DIMENSION; c++) (&s->v.x)[c] += alpha*(&m.x)[c]*(s->s[2*c + 1] - s->s[2*c]); } if (alpha <= 0. && p->positive) { FttVector p; ftt_cell_pos (cell, &p); g_log (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR, "alpha is negative (%g) at cell (%g,%g,%g).\n" "Please check your definition.", alpha, p.x, p.y, p.z); } } }
static void reset_coeff_por (FttCell * cell, PoissonCoeff_por * p) { FttDirection d; GfsFaceStateVector * f = GFS_STATE (cell)->f; if (GFS_IS_MIXED (cell)) { FttVector v = {0.,0.,0.}; GFS_STATE (cell)->solid->v = v; } for (d = 0; d < FTT_NEIGHBORS; d++) f[d].v = 0.; }
static int cell_is_corner (FttCell * cell) { FttDirection d, d1, d2; gdouble norm; FttCellNeighbors neighbors; FttVector n1, n2; g_assert (cell); ftt_cell_neighbors (cell,&neighbors); d1 = d2 = -1; if (!GFS_IS_MIXED(cell)) return 0; for (d = 0; d < FTT_NEIGHBORS; d ++) if (GFS_STATE(cell)->solid->s[d] != 1. && GFS_STATE(cell)->solid->s[d] != 0. && d1 == -1 && d2 == -1) d1 = d; else if (GFS_STATE(cell)->solid->s[d] != 1. && GFS_STATE(cell)->solid->s[d] != 0 && d2 == -1) d2 = d; else if (GFS_STATE(cell)->solid->s[d] != 1. && GFS_STATE(cell)->solid->s[d] != 0.) g_assert_not_reached (); if ( d1 == -1 || d2 == -1) { FttVector pos; ftt_cell_pos (cell,&pos); g_warning ("REA: %f, %f \n", pos.x, pos.y); g_warning ("d1: %i d2: %i \n", d1,d2); g_assert_not_reached (); } gfs_solid_normal (neighbors.c[d1], &n1); norm = sqrt (n1.x*n1.x + n1.y*n1.y); if (norm != 0.) { n1.x /= norm; n1.y /= norm; } gfs_solid_normal (neighbors.c[d2], &n2); norm = sqrt (n2.x*n2.x + n2.y*n2.y); if (norm != 0.) { n2.x /= norm; n2.y /= norm; } if (d1/2 == d2/2) return 0; else { if (neighbors.c[d2]) if ( neighbors.c[d1]) if (GFS_IS_MIXED (neighbors.c[d2]) && GFS_IS_MIXED (neighbors.c[d1])) if (fabs(n1.x*n2.x+n1.y*n2.y) < 0.70) { if (GFS_STATE(neighbors.c[d1])->solid->s[d1] > 0 && GFS_STATE(neighbors.c[d1])->solid->s[d1] < 1) return 1; if (GFS_STATE(neighbors.c[d2])->solid->s[d2] > 0 && GFS_STATE(neighbors.c[d2])->solid->s[d2] < 1) return 1; } return 0; } }
static void second_order_face_fractions (FttCell * cell, GfsSimulationMoving * sim) { #ifndef FTT_2D /* 3D */ g_assert_not_implemented (); #endif GfsVariable * old_solid_v = sim->old_solid; GfsVariable ** sold2 = sim->sold2; gdouble dt1, dt2, dto1, dto2, s1, s2; gint d1, d2, d, do1, do2; FttCellNeighbors neighbors; dt1 = dt2 = dto1 = dto2 = -2; d1 = d2 = do1 = do2 = -1; s1 = s2 = -1; g_assert(cell); ftt_cell_neighbors (cell,&neighbors); if (!OLD_SOLID (cell) && !GFS_IS_MIXED(cell)) return; if (!OLD_SOLID (cell)) { FttDirection c; OLD_SOLID (cell) = g_malloc0 (sizeof (GfsSolidVector)); OLD_SOLID (cell)->a = 1.; for (c = 0; c < FTT_NEIGHBORS; c++) OLD_SOLID (cell)->s[c] = 1.; } /* Find directions of intersection */ if (GFS_IS_MIXED(cell)) for (d = 0; d < FTT_NEIGHBORS; d ++) { if (GFS_STATE(cell)->solid->s[d] != 1. && GFS_STATE(cell)->solid->s[d] != 0. && d1 == -1 && d2 == -1) d1 = d; else if (GFS_STATE(cell)->solid->s[d] != 1. && GFS_STATE(cell)->solid->s[d] != 0 && d2 == -1) d2 = d; else if (GFS_STATE(cell)->solid->s[d] != 1. && GFS_STATE(cell)->solid->s[d] != 0.) g_assert_not_reached (); } for (d = 0; d < FTT_NEIGHBORS; d ++) { if (SOLD2 (cell, d) != 1. && SOLD2 (cell, d) != 0. && do1 == -1 && do2 == -1) do1 = d; else if (SOLD2 (cell, d) != 1. && SOLD2 (cell, d) != 0 && do2 == -1) do2 = d; else if (SOLD2 (cell, d) != 1. && SOLD2 (cell, d) != 0.) g_assert_not_reached (); } /* Treats easy cases */ if (d1 != -1 && d1 == do1) OLD_SOLID (cell)->s[d1] = SOLD2 (cell, d1); if (d2 != -1 && d2 == do2) OLD_SOLID (cell)->s[d2] = SOLD2 (cell, d2); if (d1 == do1 && d2 == do2) return; /* Finds timescale for d1/do1 */ if (d1 != -1) { if (SOLD2 (cell, d1) == 1.) { dt1 = new_solid_old_fluid (cell, d1, old_solid_v, sold2); if (dt1 == -1) if (neighbors.c[d1]){ FttDirection dop = ftt_opposite_direction[d1]; dt1 = new_solid_old_fluid (neighbors.c[d1], dop, old_solid_v, sold2); } } else if (SOLD2 (cell, d1) == 0.){ dt1 = new_solid_old_solid (cell, d1, old_solid_v, sold2); } } if (do1 != -1 && do1 != d1 && do1 != d2) { if (GFS_IS_MIXED(cell) && GFS_STATE(cell)->solid->s[do1] == 0.) dto1 = new_solid_old_solid (cell, do1, old_solid_v, sold2); else dto1 = new_fluid_old_solid (cell, do1, old_solid_v, sold2); } /* Finds timescale for d2/do2 */ if (d2 != -1) { if (SOLD2 (cell, d2) == 1.) { dt2 = new_solid_old_fluid (cell, d2, old_solid_v, sold2); if (dt2 == -1 && neighbors.c[d2]) { FttDirection dop = ftt_opposite_direction[d2]; dt2 = new_solid_old_fluid (neighbors.c[d2], dop, old_solid_v, sold2); } } else if (SOLD2 (cell, d2) == 0.) dt2 = new_solid_old_solid (cell, d2, old_solid_v, sold2); } if (do2 != -1 && do2 != d1 && do2 != d2) { if (GFS_IS_MIXED(cell) && GFS_STATE(cell)->solid->s[do2] == 0.) dto2 = new_solid_old_solid (cell, do2, old_solid_v, sold2); else dto2 = new_fluid_old_solid (cell, do2, old_solid_v, sold2); } /* Uses time-scale from other faces if one is missing */ if (dt1 == -1) { if (dto1 != -2) dt1 = dto1; else if (dt2 != -2) dt1 = dt2; else if (dto2 != -2) dt1 = dto2; } if (dt2 == -1) { if (dt1 != -2) dt2 = dt1; else if (dto2 != -2) dt2 = dto2; else if (dto1 != -2) dt2 = dto1; } if (dto1 == -1) { if (dt1 != -2) dto1 = dt1; else if (dt2 != -2) dto1 = dt2; else if (dto2 != -2) dto1 = dto2; } if (dto2 == -1) { if (dt1 != -2) dto2 = dt1; else if (dt2 != -2) dto2 = dt2; else if (dto1 != -2) dto2 = dto1; } /* Treats cell is corner */ if (dt1 != -2 && dt2 != -2) { if (dt1 != dt2 && d1/2 != d2/2) { if (cell_is_corner (cell)) { if (dt1 < dt2) dt2 = dt1; else dt1 = dt2; }}} /* Treats cell was corner */ if (dto1 != -2 && dto2 != -2 && dto1 != dto2 && do1/2 != do2/2 && cell_was_corner (cell, old_solid_v, sold2)) { if (dto1 < dto2) dto2 = dto1; else dto1 = dto2; } /* Compute the t^n+1/2 contribution of the face */ if (do1 > -1) if (do1 != d1 && do1 != d2) { OLD_SOLID (cell)->s[do1]=SOLD2 (cell, do1)*(1-dto1)+dto1; if (neighbors.c[do1]) if (!OLD_SOLID (neighbors.c[do1]) || !GFS_IS_MIXED(neighbors.c[do1])) { if (!OLD_SOLID (neighbors.c[do1])) { FttDirection c; OLD_SOLID (neighbors.c[do1]) = g_malloc0 (sizeof (GfsSolidVector)); OLD_SOLID (neighbors.c[do1])->a = 1.; for (c = 0; c < FTT_NEIGHBORS; c++) OLD_SOLID (neighbors.c[do1])->s[c] = 1.; } OLD_SOLID (neighbors.c[do1])->s[ftt_opposite_direction[do1]] = SOLD2 (cell, do1)*(1-dto1)+dto1; } } if (do2 > -1) if (do2 != d1 && do2 != d2) { OLD_SOLID (cell)->s[do2]=SOLD2 (cell, do2)*(1-dto2)+dto2; if (neighbors.c[do2]) if (!OLD_SOLID (neighbors.c[do2]) || !GFS_IS_MIXED(neighbors.c[do2])) { if (!OLD_SOLID (neighbors.c[do2])) { FttDirection c; OLD_SOLID (neighbors.c[do2]) = g_malloc0 (sizeof (GfsSolidVector)); OLD_SOLID (neighbors.c[do2])->a = 1.; for (c = 0; c < FTT_NEIGHBORS; c++) OLD_SOLID (neighbors.c[do2])->s[c] = 1.; } OLD_SOLID (neighbors.c[do2])->s[ftt_opposite_direction[do2]] = SOLD2 (cell, do2)*(1-dto2)+dto2; } } if (d1 > -1) { if (SOLD2 (cell, d1) == 0.) OLD_SOLID (cell)->s[d1] = GFS_STATE(cell)->solid->s[d1]*(dt1-1.); else if (SOLD2 (cell, d1) == 1.) OLD_SOLID (cell)->s[d1] = (dt1-1.)*GFS_STATE(cell)->solid->s[d1]+2.-dt1; } if (d2 > -1) { if (SOLD2 (cell, d2) == 0.) OLD_SOLID (cell)->s[d2] = GFS_STATE(cell)->solid->s[d2]*(dt2-1.); else if (SOLD2 (cell, d2) == 1.) OLD_SOLID (cell)->s[d2] = (dt2-1.)*GFS_STATE(cell)->solid->s[d2]+2.-dt2; } if (d1/2 == d2/2 && do1 == -1 && do2 == -1) /* third face has to be treated for the timescale determined on the other faces */ for (d = 0; d < FTT_NEIGHBORS; d ++) if (d/2 != d1/2 && SOLD2 (cell, d) == 0.) OLD_SOLID (cell)->s[d] = -1.+dt1+dt2; if (do1/2 == do2/2 && d1 == -1 && d2 == -1) for (d = 0; d < FTT_NEIGHBORS; d++) if (d/2 != do1/2 && SOLD2 (cell, d) == 0.) OLD_SOLID (cell)->s[d] = -1.+dto1+dto2; }