Beispiel #1
0
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.;
}
Beispiel #2
0
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);
    }
  }
}
Beispiel #3
0
static void poisson_coeff_por (FttCellFace * face,
                           PoissonCoeff_por * p)
{
  gdouble alpha = p->alpha ? (gfs_function_face_value (p->alpha, face)*gfs_function_face_value (p->phi, face)) : gfs_function_face_value (p->phi, face);
  gdouble v = p->lambda2[face->d/2]*alpha*gfs_domain_face_fraction (p->domain, face)/
    gfs_domain_face_scale_metric (p->domain, face, face->d/2);

  if (alpha <= 0. && p->positive) {
    FttVector p;
    ftt_face_pos (face, &p);
    g_log (G_LOG_DOMAIN, G_LOG_LEVEL_ERROR,
           "alpha is negative (%g) at face (%g,%g,%g).\n"
           "Please check your definition.",
           alpha, p.x, p.y, p.z);
  }
  GFS_STATE (face->cell)->f[face->d].v += v;

  switch (ftt_face_type (face)) {
  case FTT_FINE_FINE:
    GFS_STATE (face->neighbor)->f[FTT_OPPOSITE_DIRECTION (face->d)].v += v;
    break;
  case FTT_FINE_COARSE:
    GFS_STATE (face->neighbor)->f[FTT_OPPOSITE_DIRECTION (face->d)].v +=
      v/FTT_CELLS_DIRECTION (face->d);
    break;
  default:
    g_assert_not_reached ();
  }
}
Beispiel #4
0
static void face_coeff_from_below_por (FttCell * cell)
{
  FttDirection d;
  GfsFaceStateVector * f = GFS_STATE (cell)->f;
  guint neighbors = 0;

  for (d = 0; d < FTT_NEIGHBORS; d++) {
    FttCellChildren child;
    guint i, n;

    f[d].v = 0.;
    n = ftt_cell_children_direction (cell, d, &child);
    for (i = 0; i < n; i++)
      if (child.c[i])
        f[d].v += GFS_STATE (child.c[i])->f[d].v;
    f[d].v /= n;
    /* fixme: this stuff may not be necessary anymore? The 'dumbell'
       test case seems to work fine without this */
    FttCell * neighbor;
    if (f[d].v != 0. &&
        (neighbor = ftt_cell_neighbor (cell, d)) && !GFS_CELL_IS_BOUNDARY (neighbor))
      neighbors++;
  }

  if (neighbors == 1)
    for (d = 0; d < FTT_NEIGHBORS; d++)
      f[d].v = 0.;
}
Beispiel #5
0
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.;
}
Beispiel #6
0
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]);
  }
}
Beispiel #7
0
static void correct_face_velocity (FttCell * cell)
{                               
  FttDirection d;
  for (d = 0; d < FTT_NEIGHBORS; d++) {
    FttCellFace face = gfs_cell_face(cell, d);
    if (GFS_FACE_FRACTION_RIGHT (&face) != 0. && face.neighbor) {

    switch (ftt_face_type (&face)) {
      case FTT_FINE_FINE:
        GFS_STATE (face.neighbor)->f[FTT_OPPOSITE_DIRECTION(face.d)].un = GFS_STATE (cell)->f[face.d].un;
        break;
      case FTT_FINE_COARSE:
        GFS_STATE (cell)->f[face.d].un = GFS_STATE (face.neighbor)->f[FTT_OPPOSITE_DIRECTION(face.d)].un;
        break;
      default:
        g_assert_not_reached ();
    }
    }
  }
}
Beispiel #8
0
static void diffusion_term (FttCell * cell, DataDif * data)
{
  /* fixme: I need to account for the metric */
  gdouble size, sizenext, size_ratio;
  gdouble un, unext, unprev;

  FttDirection d0;
  for (d0 = 0; d0 < FTT_NEIGHBORS; d0++) {

  FttCellFace face = gfs_cell_face(cell, d0);
  gdouble flux = 0.;  
  gdouble invdens = data->alpha ? gfs_function_face_value (data->alpha, &face) : 1.;
  gdouble visc = gfs_diffusion_cell (data->d->D, cell);

  GfsStateVector * s = GFS_STATE (cell);

  FttDirection od = FTT_OPPOSITE_DIRECTION(d0);

  un = interpolate_value_skew (cell, d0, NULL, data->fd);

  if ((d0 % 2) != 0) {
    unext    = interpolate_value_skew (cell, od , NULL, data->fd);
    unprev   = interpolate_value_skew (cell, d0 , &(d0) , data->fd); 
    sizenext = ftt_cell_size (cell); 
    size     = get_size_next (cell, d0);
  }
  else {
    unext    = interpolate_value_skew (cell, d0, &(d0), data->fd);
    unprev   = interpolate_value_skew (cell, od,      NULL,    data->fd);
    size     = ftt_cell_size (cell); 
    sizenext = get_size_next (cell, d0);
  } 
  size_ratio = ( 1. + sizenext / size ) / 2;
  flux = ( (unext - un)/sizenext - (un - unprev)/size );

  FttComponent c = d0/2;
#if FTT_2D
  FttComponent oc = FTT_ORTHOGONAL_COMPONENT (c);
  flux += size_ratio * transverse_diffusion(cell, oc, d0, un, data->fd);
#else
  static FttComponent orthogonal[FTT_DIMENSION][2] = {
    {FTT_Y, FTT_Z}, {FTT_X, FTT_Z}, {FTT_X, FTT_Y}
  };
  flux += size_ratio * transverse_diffusion(cell, orthogonal[c][0], d0, un, data->fd);
  flux += size_ratio * transverse_diffusion(cell, orthogonal[c][1], d0, un, data->fd);
#endif 

  s->f[d0].v -= invdens*visc*flux;
  }
}
Beispiel #9
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;
  }
}
Beispiel #10
0
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;
  }
}
Beispiel #11
0
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;
  }
}
Beispiel #12
0
static void swap_fractions_back (FttCell * cell, GfsVariable * old_solid_v) 
{
  if (OLD_SOLID (cell))
    if (GFS_STATE(cell)->solid) {
      GfsSolidVector * tmp = OLD_SOLID (cell);
      OLD_SOLID (cell) = GFS_STATE(cell)->solid;
      GFS_STATE(cell)->solid = tmp;
      tmp = NULL;
    }
    else {
      GFS_STATE(cell)->solid = OLD_SOLID (cell);
      OLD_SOLID (cell) = NULL;
    }
  else
    if (GFS_STATE(cell)->solid) {
      OLD_SOLID (cell) = GFS_STATE(cell)->solid;
      GFS_STATE(cell)->solid = NULL;
    }
}
Beispiel #13
0
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
  }
}
Beispiel #14
0
static void swap_fractions (FttCell * cell, GfsVariable * old_solid_v) {
  FttDirection c;
  
  g_assert (cell);
  
  if (FTT_CELL_IS_LEAF(cell)) {
    if (OLD_SOLID (cell)) {
      GfsSolidVector * solid_old = OLD_SOLID (cell);
      
      if (GFS_STATE (cell)->solid) {
	GfsSolidVector * solid = GFS_STATE (cell)->solid;
	
	OLD_SOLID (cell)->merged = GFS_STATE (cell)->solid->merged;
	
	for (c = 0; c < 2*FTT_DIMENSION; c++) 
	  if (solid->s[c] == 0.)
	    solid_old->s[c] = 0;
	  else
	    solid_old->s[c] = (solid_old->s[c]+solid->s[c])/2. ;	
      }
      else {
	OLD_SOLID (cell)->merged = NULL;
	
	for (c = 0; c < 2*FTT_DIMENSION; c++)
	  solid_old->s[c] = (solid_old->s[c]+1.)/2. ;
	
      }
    }
    else if (GFS_STATE (cell)->solid) {
      GfsSolidVector * solid = GFS_STATE (cell)->solid;
      GfsSolidVector * solid_old = OLD_SOLID (cell) = g_malloc0 (sizeof (GfsSolidVector));
      OLD_SOLID (cell)->a= 1.;
      OLD_SOLID (cell)->merged = GFS_STATE (cell)->solid->merged;
      
      for (c = 0; c < 2*FTT_DIMENSION; c++) 
	solid_old->s[c] = 1.;	
      
      for (c = 0; c < 2*FTT_DIMENSION; c++) 
	if (solid->s[c] == 0.)
	  solid_old->s[c] = 0;
	else
	  solid_old->s[c] = (solid_old->s[c]+solid->s[c])/2. ;
    }
  }
  
  if (OLD_SOLID (cell)) {
    if (GFS_STATE(cell)->solid) {
      GfsSolidVector * tmp = OLD_SOLID (cell);
      OLD_SOLID (cell)->merged = GFS_STATE (cell)->solid->merged;
      OLD_SOLID (cell) = GFS_STATE(cell)->solid;
      GFS_STATE(cell)->solid = tmp;
      tmp = NULL;
    }
    else {
      OLD_SOLID (cell)->merged = NULL;
      GFS_STATE(cell)->solid = OLD_SOLID (cell);
      OLD_SOLID (cell) = NULL;
    }
  }
  else if (GFS_STATE(cell)->solid) {
    OLD_SOLID (cell) = GFS_STATE(cell)->solid;
    GFS_STATE(cell)->solid = NULL;
  }
  
  
  /* Check for negative fractions and fix */
  if (GFS_STATE(cell)->solid)
    for (c = 0; c < 2*FTT_DIMENSION; c++)
      if (GFS_STATE(cell)->solid->s[c] < 0.) {
	if (OLD_SOLID (cell)) 
	  if (OLD_SOLID (cell)->s[c] >= 0.)
	    GFS_STATE(cell)->solid->s[c] = OLD_SOLID (cell)->s[c];
	  else
	    GFS_STATE(cell)->solid->s[c] = 1.;
	else
	  GFS_STATE(cell)->solid->s[c] = 0.;
      }
  
  if (OLD_SOLID (cell)) 
    for (c = 0; c < 2*FTT_DIMENSION; c++)
      if (OLD_SOLID (cell)->s[c] < 0.){
	if (GFS_STATE(cell)->solid)
	  if (GFS_STATE(cell)->solid->s[c] >= 0.)
	    OLD_SOLID (cell)->s[c] = GFS_STATE(cell)->solid->s[c];
	  else
	    OLD_SOLID (cell)->s[c] = 1.;
	else
	  OLD_SOLID (cell)->s[c] = 0.;
      }
}
Beispiel #15
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;
  }
}
Beispiel #16
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;
}