static void refine_cut_cell (FttCell * cell, GfsGenericSurface * s, RefineCut * p) { GTS_OBJECT (s)->reserved = p->surface; GFS_REFINE_SOLID (p->refine)->v->data = s; if (ftt_cell_level (cell) < gfs_function_value (p->refine->maxlevel, cell)) ftt_cell_refine_single (cell, p->domain->cell_init, p->domain->cell_init_data); GFS_REFINE_SOLID (p->refine)->v->data = NULL; }
static void obtain_face_fluxes (const FttCell * cell) { FttCellChildren child; GfsStateVector * s = GFS_STATE (cell); FttDirection d; for (d = 0; d < FTT_NEIGHBORS; d++) { FttCell * neighbor = ftt_cell_neighbor (cell, d); if (neighbor) { if (!FTT_CELL_IS_LEAF (neighbor)) { gint i, n = ftt_cell_children_direction (neighbor, FTT_OPPOSITE_DIRECTION(d), &child); s->f[d].v = 0; for (i = 0; i < n; i++) if (child.c[i]) s->f[d].v += GFS_STATE (child.c[i])->f[FTT_OPPOSITE_DIRECTION(d)].v; s->f[d].v /= n; } else if ((d % 2) > 0 && ftt_cell_level(cell) == ftt_cell_level(neighbor)) s->f[d].v = GFS_STATE (neighbor)->f[FTT_OPPOSITE_DIRECTION(d)].v; } else s->f[d].v = 0; } }
static void traverse_face (FttCell * cell, gpointer * datum) { FttDirection * d = datum[0]; gint max_depth = *((gint *) datum[1]); FttFaceTraverseFunc func = (FttFaceTraverseFunc) datum[2]; gpointer data = datum[3]; gboolean check = *((gboolean *) datum[4]); gboolean boundary_faces = *((gboolean *) datum[5]); FttCellFace face; face.d = *d; face.cell = cell; face.neighbor = ftt_cell_neighbor (cell, face.d); if (face.neighbor) { if (!check || (face.neighbor->flags & FTT_FLAG_TRAVERSED) == 0) { if (FTT_CELL_IS_LEAF (cell) && !FTT_CELL_IS_LEAF (face.neighbor) && (max_depth < 0 || ftt_cell_level (face.neighbor) < max_depth)) { /* coarse -> fine */ FttCellChildren children; guint i, n; face.d = FTT_OPPOSITE_DIRECTION (face.d); n = ftt_cell_children_direction (face.neighbor, face.d, &children); face.neighbor = face.cell; for (i = 0; i < n; i++) if ((face.cell = children.c[i]) && (!check || (face.cell->flags & FTT_FLAG_TRAVERSED) == 0)) (* func) (&face, data); } else (* func) (&face, data); } } else if (boundary_faces) (* func) (&face, data); }
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 } } }
static gboolean refine_maxlevel (FttCell * cell, GfsFunction * maxlevel) { return (ftt_cell_level (cell) < gfs_function_value (maxlevel, cell)); }
static void refine_implicit_cell (FttCell * cell, RefineCut * p) { guint maxlevel = gfs_function_value (p->refine->maxlevel, cell); if (ftt_cell_level (cell) < maxlevel && gfs_cell_is_cut (cell, p->surface, FALSE, maxlevel)) ftt_cell_refine_single (cell, p->domain->cell_init, p->domain->cell_init_data); }
/* 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; } } }