static void ftt_bbox(FttCell *cell, gpointer data) { FttVector p; ftt_cell_pos(cell,&p); double size = ftt_cell_size(cell)/2.0; bbox_t bb, *pbb = *(bbox_t**)data; bb.x.min = p.x - size; bb.x.max = p.x + size; bb.y.min = p.y - size; bb.y.max = p.y + size; if (pbb) { bbox_t bbx = bbox_join(bb,*pbb); *pbb = bbx; } else { pbb = malloc(sizeof(bbox_t)); *pbb = bb; *(bbox_t**)data = pbb; } }
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 gdouble cell_height (FttCell * cell, FttCellFace * face, GfsSimulation * sim, GfsRefineSurface * refine) { FttVector pos; ftt_cell_pos (cell, &pos); return interpolated_value (GFS_SURFACE (refine->surface)->s, &pos); }
static gdouble cell_distance (FttCell * cell, FttCellFace * face, GfsSimulation * sim, GfsRefineDistance * refine) { FttVector pos; gdouble h = GFS_DIAGONAL*ftt_cell_size (cell), d; GtsPoint p; ftt_cell_pos (cell, &pos); p.x = pos.x; p.y = pos.y; p.z = pos.z; d = gts_bb_tree_point_distance (refine->stree, &p, (GtsBBoxDistFunc) gts_point_triangle_distance, NULL); return d > h ? d - h : 0.; }
static void redistribute_old_face_in_merged (FttCell * cell, FttCell * merged, FttDirection d, GfsVariable * old_solid_v) { gint i; gdouble sc, sm; g_assert (cell != NULL); g_assert (merged != NULL); sc = ftt_cell_volume(cell); sm = ftt_cell_volume(merged); if (sc != sm) printf("Face redistribution not implemented yet for adaptive grid \n"); g_assert (sc == sm); for (i = 0; i < FTT_DIMENSION;i++) if (i != d/2) { FttCellNeighbors neighbors; FttVector pos; ftt_cell_pos(cell,&pos); ftt_cell_neighbors (merged,&neighbors); GfsSolidVector * old_solid_merged = OLD_SOLID (merged); if (!old_solid_merged) { FttDirection c; OLD_SOLID (merged) = old_solid_merged = g_malloc0 (sizeof (GfsSolidVector)); old_solid_merged->a = 1.; for (c = 0; c < FTT_NEIGHBORS; c++) old_solid_merged->s[c] = 1.; } old_solid_merged->s[2*i] += OLD_SOLID (cell)->s[2*i]; if (neighbors.c[2*i]) { GfsSolidVector * old_solid = OLD_SOLID (neighbors.c[2*i]); if (!old_solid) { FttDirection c; OLD_SOLID (neighbors.c[2*i]) = old_solid = g_malloc0 (sizeof (GfsSolidVector)); old_solid->a = 1.; for (c = 0; c < FTT_NEIGHBORS; c++) old_solid->s[c] = 1.; } old_solid->s[ftt_opposite_direction[2*i]] += OLD_SOLID (cell)->s[2*i]; } old_solid_merged->s[2*i+1] += OLD_SOLID (cell)->s[2*i+1]; if (neighbors.c[2*i+1]) { GfsSolidVector * old_solid = OLD_SOLID (neighbors.c[2*i+1]); if (!old_solid) { FttDirection c; OLD_SOLID (neighbors.c[2*i+1]) = old_solid = g_malloc0 (sizeof (GfsSolidVector)); old_solid->a = 1.; for (c = 0; c < FTT_NEIGHBORS; c++) old_solid->s[c] = 1.; } old_solid->s[ftt_opposite_direction[2*i+1]] += OLD_SOLID (cell)->s[2*i+1]; } } }
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 ftt_sample(FttCell *cell, gpointer data) { ftts_t ftts = *((ftts_t*)data); int level = ftt_cell_level(cell); double size = ftt_cell_size(cell); bbox_t bb = bilinear_bbox(ftts.B[0]); FttVector p; ftt_cell_pos(cell,&p); /* the number in each directon we will sample */ int n = POW2(ftts.depth-level); /* cell coordinates at this level */ int ic = (p.x - bb.x.min)/size; int jc = (p.y - bb.y.min)/size; /* subgrid extent */ double xmin = p.x - size/2.0; double ymin = p.y - size/2.0; double d = size/n; #ifdef FFTS_DEBUG printf("%f %f (%i %i %i %i)\n",p.x,p.y,level,n,ic,jc); #endif int i,j; for (i=0 ; i<n ; i++) { double x = xmin + (i+0.5)*d; int ig = ic*n + i; for (j=0 ; j<n ; j++) { double y = ymin + (j+0.5)*d; int jg = jc*n + j; /* ig, jg are the global indicies, so give a sample point for the bilinear struct. Note that (x,y) and (x0,y0) shoule be the same, else the bilinear and octree grids are not aligned. */ #ifdef FFTS_DEBUG double x0, y0; bilinear_getxy(ig, jg, ftts.B[0], &x0, &y0); #endif FttVector p; p.x = x; p.y = y; double u = gfs_interpolate(cell,p,ftts.u), v = gfs_interpolate(cell,p,ftts.v); bilinear_setz(ig,jg,u,ftts.B[0]); bilinear_setz(ig,jg,v,ftts.B[1]); #ifdef FFTS_DEBUG printf(" (%f %f) (%f %f) (%i %i) %f %f (%f %f)\n", x, y, x0, y0, ig, jg, u, v, x-x0, y-y0); #endif } } }
/* d2: cell direction with respect to cellref */ static gdouble interpolate_value_skew (FttCell * cellref, FttDirection d, FttDirection * d2, FaceData * fd) { FttCell * cell; FttComponent c = d/2; if (d2) cell = ftt_cell_neighbor (cellref, *d2); else cell = cellref; if (!cell) { /* Symmetric BC */ if ( d == (*d2) ) return -GFS_VALUE (cellref,fd->velfaces[FTT_OPPOSITE_DIRECTION(d)]); else return GFS_VALUE (cellref,fd->velfaces[d]); } if (!FTT_CELL_IS_LEAF (cell)) { FttDirection corner[FTT_DIMENSION]; FttCell * cell2; gdouble val; #if FTT_2D if ( d == (*d2) ) { FttComponent c1 = FTT_ORTHOGONAL_COMPONENT (c); corner[0]=2*c1; corner[1]=FTT_OPPOSITE_DIRECTION(*d2); cell2 = ftt_cell_child_corner(cell, corner); val = GFS_VALUE (cell2,fd->velfaces[d]); corner[0]=2*c1+1; cell2 = ftt_cell_child_corner(cell, corner); return ( val + GFS_VALUE (cell2,fd->velfaces[d]) ) / 2. ; } else { corner[0]=d; corner[1]=FTT_OPPOSITE_DIRECTION(*d2); cell2 = ftt_cell_child_corner(cell, corner); return GFS_VALUE (cell2,fd->velfaces[d]); } #else static FttComponent orthogonal[FTT_DIMENSION][2] = { {FTT_Y, FTT_Z}, {FTT_X, FTT_Z}, {FTT_X, FTT_Y} }; val = 0.; gint i,j; if ( d == (*d2) ) { FttVector pc; ftt_cell_pos (cell, &pc); corner[0]=FTT_OPPOSITE_DIRECTION(*d2); for ( i = 0; i < 2; i++ ) { for ( j = 0; i < 2; i++ ) { corner[1]=2*orthogonal[c][0]+i; corner[2]=2*orthogonal[c][1]+j; cell2 = ftt_cell_child_corner(cell, corner); val += GFS_VALUE (cell2,fd->velfaces[d]); } } return val / 4.; } else { corner[0]=FTT_OPPOSITE_DIRECTION(*d2); corner[1]=d; FttComponent c2 = (*d2) / 2; if ( c != orthogonal[c2][0] ) c2 = orthogonal[c2][0]; else c2 = orthogonal[c2][1]; for ( i = 0; i < 2; i++ ) { corner[2]=2*c2+i; cell2 = ftt_cell_child_corner(cell, corner); val += GFS_VALUE (cell2,fd->velfaces[d]); } return val / 2.; } #endif } else { if ( ftt_cell_level(cell) == ftt_cell_level(cellref) || d == (*d2) ) return GFS_VALUE (cell,fd->velfaces[d]); else { FttVector pos_next, pos_ref; ftt_cell_pos (cellref, &pos_ref); ftt_cell_pos (cell, &pos_next); if ( ( (&(pos_ref.x))[c] < (&(pos_next.x))[c] && (d % 2) != 0 ) || ( (&(pos_ref.x))[c] > (&(pos_next.x))[c] && (d % 2) == 0 ) ) return GFS_VALUE (cell,fd->velfaces[d]); else return ( GFS_VALUE (cell,fd->velfaces[d]) + GFS_VALUE (cell,fd->velfaces[FTT_OPPOSITE_DIRECTION(d)]) ) / 2; } } }