static void get_cell_values (FttCell * cell, FaceData * fd) { FttComponent c; for (c = 0; c < FTT_DIMENSION; c++) GFS_VALUE (cell, fd->u[c]) = (GFS_VALUE (cell, fd->velfaces[2*c]) + GFS_VALUE (cell, fd->velfaces[2*c + 1]))/2.; }
static void moving_divergence_distribution_second_order (GSList * merged, DivergenceData * p) { if (merged->next != NULL && merged->next->data != merged->data) { gdouble total_volume = 0., total_div = 0.; GfsVariable * old_solid_v = GFS_SIMULATION_MOVING (p->domain)->old_solid; GSList * i = merged; while (i) { FttCell * cell = i->data; g_assert (FTT_CELL_IS_LEAF (cell)); gdouble a = OLD_SOLID (cell) ? OLD_SOLID (cell)->a : 1.; total_volume += a*ftt_cell_volume (cell); total_div += GFS_VALUE (cell, p->div); i = i->next; } total_div /= total_volume; i = merged; while (i) { FttCell * cell = i->data; gdouble a = OLD_SOLID (cell) ? OLD_SOLID (cell)->a : 1.; GFS_VALUE (cell, p->div) = total_div*a*ftt_cell_volume (cell); i = i->next; } } }
/* see gfs_face_velocity_advection_flux() for the initial implementation with static boundaries */ static void moving_face_velocity_advection_flux (const FttCellFace * face, const GfsAdvectionParams * par) { gdouble flux; FttComponent c = par->v->component; g_return_if_fail (c >= 0 && c < FTT_DIMENSION); /* fixme: what's up with face mapping? */ flux = face_fraction_half (face, par)*GFS_FACE_NORMAL_VELOCITY (face)* par->dt/ftt_cell_size (face->cell); #if 0 if (c == face->d/2) /* normal component */ flux *= GFS_FACE_NORMAL_VELOCITY (face); else /* tangential component */ #else flux *= gfs_face_upwinded_value (face, par->upwinding, par->u) /* pressure correction */ - gfs_face_interpolated_value (face, par->g[c]->i)*par->dt/2.; #endif if (!FTT_FACE_DIRECT (face)) flux = - flux; GFS_VALUE (face->cell, par->fv) -= flux; switch (ftt_face_type (face)) { case FTT_FINE_FINE: GFS_VALUE (face->neighbor, par->fv) += flux; break; case FTT_FINE_COARSE: GFS_VALUE (face->neighbor, par->fv) += flux/FTT_CELLS; break; default: g_assert_not_reached (); } }
static void implicit_darcy_2D (FttCell * cell, GfsSourceDarcy * s) { GfsSourceVelocity * sv = GFS_SOURCE_VELOCITY (s); gdouble m[2][2]; gdouble f[2]; GfsSimulation * sim = gfs_object_simulation (s); gdouble dt = sim->advection_params.dt; darcy_coefficients (s, cell, sv->v, FTT_X, f); gdouble d = s->darcycoeff ? gfs_function_value (s->darcycoeff, cell):0.; gdouble e = s->forchhicoeff ? gfs_function_value (s->forchhicoeff, cell):0.; f[0] *= d; f[1] *= e; m[0][0] = 1. + (f[0]+f[1])*dt; m[0][1] = 0; darcy_coefficients (s, cell, sv->v, FTT_Y, f); m[1][0] = 0; m[1][1] = 1. + (f[0]+f[1])*dt; gdouble det = m[0][0]*m[1][1] - m[0][1]*m[1][0]; gdouble u = GFS_VALUE (cell, sv->v[0]); gdouble v = GFS_VALUE (cell, sv->v[1]); GFS_VALUE (cell, sv->v[0]) = ( m[1][1]*u - m[0][1]*v)/det; GFS_VALUE (cell, sv->v[1]) = (- m[1][0]*u + m[0][0]*v)/det; }
static gdouble gfs_source_darcy_mac_value (GfsSourceGeneric * s, FttCell * cell, GfsVariable * v) { GfsSourceVelocity * sv = GFS_SOURCE_VELOCITY (s); GfsSourceDarcy * sd = GFS_SOURCE_DARCY (s); #if FTT_2D gdouble f[2]; darcy_coefficients (sd, cell, sv->v, v->component, f); switch (v->component) { case FTT_X: return -(f[0]+f[1])*GFS_VALUE (cell, sv->v[0]); case FTT_Y: return -(f[0]+f[1])*GFS_VALUE (cell, sv->v[1]); default: g_assert_not_reached (); } #else /* 3D */ gdouble f = gfs_function_value (sd->darcycoeff, cell); //gdouble e = sd->forchhi ? gfs_function_value (sd->forchhi, cell) : 0.; switch (v->component) { case FTT_X: return - f*GFS_VALUE (cell, sv->v[0]); case FTT_Y: return - f*GFS_VALUE (cell, sv->v[1]); case FTT_Z: return - f*GFS_VALUE (cell, sv->v[2]); default: g_assert_not_reached (); } #endif /* 3D */ return 0.; }
static void init_fd (FttCellFace * face, FaceInitData * fd) { if (face->d % 2 != 0) GFS_VALUE (face->cell, fd->v2) = gfs_function_face_value (fd->f, face); else GFS_VALUE (face->cell, fd->v1) = gfs_function_face_value (fd->f, face); }
static void advance_face_values (FttCell * cell, FaceData * fd) { FttDirection d; for (d = 0; d < FTT_NEIGHBORS; d++) GFS_VALUE (cell, fd->velfaces[d]) = ((1.0 + fd->beta)*GFS_VALUE (cell, fd->velfaces[d]) - fd->beta*GFS_VALUE (cell, fd->velold[d])); }
static void init_velocity (FttCell * cell, GfsVariable ** velocity) { FttVector p; gfs_cell_cm (cell, &p); float x = (p.x + 0.5)*WAVELENGTH, y = p.y*WAVELENGTH, t = 0., u, v, ut, vt, du, dv, etah; KMTS_F77 (&order, &x, &y, &t, &u, &v, &ut, &vt, &du, &dv, &etah); GFS_VALUE (cell, velocity[0]) = u/sqrt(WAVELENGTH*9.81); GFS_VALUE (cell, velocity[1]) = v/sqrt(WAVELENGTH*9.81); }
static void get_velfaces (FttCell * cell, FaceData * fd) { GfsStateVector * s = GFS_STATE (cell); FttDirection d; for (d = 0; d < FTT_NEIGHBORS; d++) { GFS_VALUE (cell, fd->velfaces[d]) = s->f[d].un; s->f[d].un = ( fd->beta + 0.5 ) * s->f[d].un - ( fd->beta - 0.5 ) * GFS_VALUE (cell, fd->velold[d]); } }
static void solid_flux (FttCell * cell, SolidFluxParams * par) { gfs_normal_divergence (cell, par->div); if (GFS_VALUE (cell, par->div) < 0.) { gdouble h = ftt_cell_size (cell); GFS_VALUE (cell, par->fv) = GFS_VALUE (cell, par->div)*par->p->dt* GFS_VALUE (cell, par->p->v)/(h*h); } else GFS_VALUE (cell, par->fv) = 0.; }
static void get_face_values (FttCell * cell, FaceData * fd) { GfsStateVector * s = GFS_STATE (cell); FttDirection d; for (d = 0; d < FTT_NEIGHBORS; d++) { FttComponent c = d/2; s->f[d].un = GFS_VALUE (cell, fd->u[c])/2.; if (ftt_cell_neighbor (cell, d)) s->f[d].un += GFS_VALUE (ftt_cell_neighbor (cell, d), fd->u[c])/2.; else s->f[d].un = 0; } }
static void diffusion (FttCell * cell, GSEData * p) { gdouble h2 = ftt_cell_size (cell); h2 *= h2; /* off-diagonal */ FttComponent j; for (j = 0; j < 2; j++) if (j != p->dF->component) GFS_VALUE (cell, p->F) += p->D[j][p->dF->component]*gfs_center_regular_gradient (cell, j, p->dF)/h2; /* diagonal */ GFS_VALUE (cell, p->F) += p->D[p->dF->component][p->dF->component]* gfs_center_regular_2nd_derivative (cell, p->dF->component, p->Fn)/h2; }
static void init_energy (FttCell * cell, GfsInitWave * event) { GfsWave * wave = GFS_WAVE (gfs_object_simulation (event)); for (wave->ik = 0; wave->ik < wave->nk; wave->ik++) for (wave->ith = 0; wave->ith < wave->ntheta; wave->ith++) GFS_VALUE (cell, wave->F[wave->ik][wave->ith]) = gfs_function_value (event->d, cell); }
static void reset_unold (FttCell * cell, FaceData * fd) { FttDirection d; for (d = 0; d < FTT_NEIGHBORS; d++) GFS_VALUE (cell, fd->velold[d]) = 0.; }
static void sold2_fine_init (FttCell * parent, GfsVariable * v) { FttCellChildren child; guint n; ftt_cell_children (parent, &child); for (n = 0; n < FTT_CELLS; n++) if (child.c[n]) GFS_VALUE (child.c[n], v) = 1.; }
static void correct_por_undo (FttCell * cell, gpointer * data) { FttComponent c; GfsVariable **v = data[0]; guint * dimension = data[1]; GfsPorous *por = data[2]; for (c = 0; c < *dimension; c++) GFS_VALUE (cell, v[c]) *= (1/gfs_function_value (por->porosity, cell)); }
static void scale_energy (FttCell * cell, GfsInitWave * event) { GfsWave * wave = GFS_WAVE (gfs_object_simulation (event)); gdouble E = cell_E (cell, NULL, GFS_DOMAIN (wave)); if (E > 0.) { gdouble Hs = gfs_function_value (event->hs, cell); gdouble scaling = Hs*Hs/(16.*E); guint ik, ith; for (ik = 0; ik < wave->nk; ik++) for (ith = 0; ith < wave->ntheta; ith++) GFS_VALUE (cell, wave->F[ik][ith]) *= scaling; } }
/* see gfs_face_advection_flux() for the initial implementation with static boundaries */ static void moving_face_advection_flux (const FttCellFace * face, const GfsAdvectionParams * par) { gdouble flux; /* fixme: what's up with face mapping? */ flux = face_fraction_half (face, par)*GFS_FACE_NORMAL_VELOCITY (face)*par->dt* gfs_face_upwinded_value (face, GFS_FACE_UPWINDING, NULL)/ftt_cell_size (face->cell); if (!FTT_FACE_DIRECT (face)) flux = - flux; GFS_VALUE (face->cell, par->fv) -= flux; switch (ftt_face_type (face)) { case FTT_FINE_FINE: GFS_VALUE (face->neighbor, par->fv) += flux; break; case FTT_FINE_COARSE: GFS_VALUE (face->neighbor, par->fv) += flux/FTT_CELLS; break; default: g_assert_not_reached (); } }
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 gdouble cell_E (FttCell * cell, FttCellFace * face, GfsDomain * domain) { GfsWave * wave = GFS_WAVE (domain); GfsVariable *** F = wave->F; guint ik, ith; gdouble E = 0., sigma = 2.*M_PI*GFS_WAVE_F0, sgamma = (GFS_WAVE_GAMMA - 1./GFS_WAVE_GAMMA)/2.; for (ik = 0; ik < wave->nk; ik++) { gdouble df = sigma*sgamma; gdouble dE = 0.; for (ith = 0; ith < wave->ntheta; ith++) dE += GFS_VALUE (cell, F[ik][ith]); E += dE*df; sigma *= GFS_WAVE_GAMMA; } return E*2.*M_PI/wave->ntheta; }
static void update_vel (FttCell * cell, FaceData * fd) { GfsStateVector * s = GFS_STATE (cell); gdouble size; FttDirection d; for (d = 0; d < FTT_NEIGHBORS; d++) { size = ( ftt_cell_size (cell) + get_size_next (cell, d) ) / 2; GFS_VALUE (cell, fd->velfaces[d]) = (GFS_VALUE (cell, fd->velfaces[d]) + fd->beta*GFS_VALUE (cell, fd->velold[d]))/(1.+fd->beta); s->f[d].un = (2*fd->beta*GFS_VALUE (cell, fd->velfaces[d]) + (0.5-fd->beta)*GFS_VALUE (cell, fd->velold[d]) - s->f[d].v*(*fd->dt)/size)/(0.5+fd->beta); GFS_VALUE (cell, fd->velold[d]) = GFS_VALUE (cell, fd->velfaces[d]); s->f[d].v = s->f[d].un; } }
static void advection_term (FttCell * cell, FaceData * fd) { gdouble un, unext, unprev; FttDirection d0; for (d0 = 0; d0 < FTT_NEIGHBORS; d0++) { GfsStateVector * s = GFS_STATE (cell); FttComponent c = d0/2; FttDirection d; gboolean cond; un = GFS_VALUE (cell,fd->velfaces[d0]); if ((d0 % 2 ) != 0 ) { cond = TRUE; d = FTT_OPPOSITE_DIRECTION (d0); unext = interpolate_value_skew (cell, d, NULL , fd); unprev = interpolate_value_skew (cell, d0, &d0, fd); } else { cond = FALSE; d = d0; unext = interpolate_value_skew (cell, d, &d, fd); unprev = interpolate_value_skew (cell, FTT_OPPOSITE_DIRECTION(d), NULL, fd); } s->f[d0].v = ((un + unext)*unext - (un + unprev)*unprev) / 4.; #if FTT_2D s->f[d0].v += transverse_advection (cell, FTT_ORTHOGONAL_COMPONENT (c), d, un, fd, cond); #else /* FTT_3D */ static FttComponent orthogonal[FTT_DIMENSION][2] = { {FTT_Y, FTT_Z}, {FTT_X, FTT_Z}, {FTT_X, FTT_Y} }; s->f[d0].v += transverse_advection (cell, orthogonal[c][0], d, un, fd, cond); s->f[d0].v += transverse_advection (cell, orthogonal[c][1], d, un, fd, cond); #endif } }
static void save_darcy (FttCell * cell, GfsSourceDarcy * s) { GfsSourceVelocity * sv = GFS_SOURCE_VELOCITY (s); gdouble f[2]; darcy_coefficients (s, cell, sv->v, FTT_X, f); darcy_coefficients (s, cell, sv->v, FTT_Y, f); gdouble d = s->darcycoeff ? gfs_function_value (s->darcycoeff, cell)*(1. - s->beta):0.; gdouble e = s->forchhicoeff ? gfs_function_value (s->forchhicoeff, cell)*(1. - s->beta) : 0.; d *= f[0]; e *= f[1]; GFS_VALUE (cell, s->u[0]) = - (d+e)*GFS_VALUE (cell, sv->v[0]); GFS_VALUE (cell, s->u[1]) = - (d+e)*GFS_VALUE (cell, sv->v[1]); #if !FTT_2D GFS_VALUE (cell, s->u[2]) = - (d+e)*GFS_VALUE (cell, sv->v[2]); #endif /* 3D */ }
static gdouble gfs_source_darcy_centered_value (GfsSourceGeneric * s, FttCell * cell, GfsVariable * v) { return GFS_VALUE (cell, GFS_SOURCE_DARCY (s)->u[v->component]); }
static void initialize_unold (FttCell * cell, FaceData * fd) { FttDirection d; for (d = 0; d < FTT_NEIGHBORS; d++) GFS_VALUE (cell, fd->velold[d]) = GFS_VALUE (cell, fd->velfaces[d]); }
/* 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; } } }
static void compute_gradient (FttCell * cell, GSEData * p) { GFS_VALUE (cell, p->dF) = gfs_center_regular_gradient (cell, p->dF->component, p->Fn); }
static void copy_F (FttCell * cell, GSEData * p) { GFS_VALUE (cell, p->Fn) = GFS_VALUE (cell, p->F); }