示例#1
0
/** For two quadrants on either side of a face, estimate the derivative normal
 * to the face.
 *
 * This function matches the p4est_iter_face_t prototype used by
 * p4est_iterate().
 *
 * \param [in] info          the information about this quadrant that has been
 *                           populated by p4est_iterate()
 * \param [in] user_data the user_data given to p4est_iterate(): in this case,
 *                       it points to the ghost_data array, which contains the
 *                       step3_data_t data for all of the ghost cells, which
 *                       was populated by p4est_ghost_exchange_data()
 */
static void
step3_minmod_estimate (p4est_iter_face_info_t * info, void *user_data)
{
  int                 i, j;
  p4est_iter_face_side_t *side[2];
  sc_array_t         *sides = &(info->sides);
  step3_data_t       *ghost_data = (step3_data_t *) user_data;
  step3_data_t       *udata;
  p4est_quadrant_t   *quad;
  double              uavg[2];
  double              h[2];
  double              du_est, du_old;
  int                 which_dir;

  /* because there are no boundaries, every face has two sides */
  P4EST_ASSERT (sides->elem_count == 2);

  side[0] = p4est_iter_fside_array_index_int (sides, 0);
  side[1] = p4est_iter_fside_array_index_int (sides, 1);

  which_dir = side[0]->face / 2;        /* 0 == x, 1 == y, 2 == z */

  for (i = 0; i < 2; i++) {
    uavg[i] = 0;
    if (side[i]->is_hanging) {
      /* there are 2^(d-1) (P4EST_HALF) subfaces */
      for (j = 0; j < P4EST_HALF; j++) {
        quad = side[i]->is.hanging.quad[j];
        h[i] =
          (double) P4EST_QUADRANT_LEN (quad->level) / (double) P4EST_ROOT_LEN;
        if (side[i]->is.hanging.is_ghost[j]) {
          udata = &ghost_data[side[i]->is.hanging.quadid[j]];
        }
        else {
          udata = (step3_data_t *) side[i]->is.hanging.quad[j]->p.user_data;
        }
        uavg[i] += udata->u;
      }
      uavg[i] /= P4EST_HALF;
    }
    else {
      quad = side[i]->is.full.quad;
      h[i] =
        (double) P4EST_QUADRANT_LEN (quad->level) / (double) P4EST_ROOT_LEN;
      if (side[i]->is.full.is_ghost) {
        udata = &ghost_data[side[i]->is.full.quadid];
      }
      else {
        udata = (step3_data_t *) side[i]->is.full.quad->p.user_data;
      }
      uavg[i] = udata->u;
    }
  }
  du_est = (uavg[1] - uavg[0]) / ((h[0] + h[1]) / 2.);
  for (i = 0; i < 2; i++) {
    if (side[i]->is_hanging) {
      /* there are 2^(d-1) (P4EST_HALF) subfaces */
      for (j = 0; j < P4EST_HALF; j++) {
        quad = side[i]->is.hanging.quad[j];
        if (!side[i]->is.hanging.is_ghost[j]) {
          udata = (step3_data_t *) quad->p.user_data;
          du_old = udata->du[which_dir];
          if (du_old == du_old) {
            /* there has already been an update */
            if (du_est * du_old >= 0.) {
              if (fabs (du_est) < fabs (du_old)) {
                udata->du[which_dir] = du_est;
              }
            }
            else {
              udata->du[which_dir] = 0.;
            }
          }
          else {
            udata->du[which_dir] = du_est;
          }
        }
      }
    }
    else {
      quad = side[i]->is.full.quad;
      if (!side[i]->is.full.is_ghost) {
        udata = (step3_data_t *) quad->p.user_data;
        du_old = udata->du[which_dir];
        if (du_old == du_old) {
          /* there has already been an update */
          if (du_est * du_old >= 0.) {
            if (fabs (du_est) < fabs (du_old)) {
              udata->du[which_dir] = du_est;
            }
          }
          else {
            udata->du[which_dir] = 0.;
          }
        }
        else {
          udata->du[which_dir] = du_est;
        }
      }
    }
  }
}
void test_disk_domain_compare_xyz_on_boundary_callback(p4est_iter_face_info_t * info, void *user_data){

  int i;
  /* dgmath_jit_dbase_t * dgmath_jit_dbase = (dgmath_jit_dbase_t*) user_data; */
  sc_array_t *sides = &(info->sides);
  double* xyz_on_f_p [(P4EST_DIM)];
  double* xyz_on_f_p_reoriented [(P4EST_DIM)];
  double* xyz_on_f_m_reoriented [(P4EST_DIM)];
  double* xyz_on_f_m [(P4EST_DIM)];

  test_curved_data_t* test_curved_data = (test_curved_data_t*)info->p4est->user_pointer;
  dgmath_jit_dbase_t* dgmath_jit_dbase = (dgmath_jit_dbase_t*)user_data;
  /* geometric_factors_t* geom_factors = test_curved_data->geom_factors; */
  
  int s_m = 0;
  int s_p = 1;
  /* check if it's an interface boundary, otherwise it's a physical boundary */
  if (sides->elem_count == 2){
    p4est_iter_face_side_t *side[2];
 
    side[0] = p4est_iter_fside_array_index_int(sides,0);
    side[1] = p4est_iter_fside_array_index_int(sides,1);

    curved_element_data_t* e_m = (curved_element_data_t *) side[s_m]->is.full.quad->p.user_data;
    curved_element_data_t* e_p = (curved_element_data_t *) side[s_p]->is.full.quad->p.user_data;

    int face_nodes_m = dgmath_get_nodes( (P4EST_DIM) - 1, e_m->deg);
    int face_nodes_p = dgmath_get_nodes( (P4EST_DIM) - 1, e_p->deg);
    int f_m = side[s_m]->face;
    int f_p = side[s_p]->face;
    mpi_assert( face_nodes_m == face_nodes_p );

    
    /* double* tmp = P4EST_ALLOC(double, face_nodes_p); */
    for (int d = 0; d < (P4EST_DIM); d++){
      xyz_on_f_p[d] = P4EST_ALLOC(double, face_nodes_p);
      xyz_on_f_p_reoriented[d] = P4EST_ALLOC(double, face_nodes_p);
      xyz_on_f_m_reoriented[d] = P4EST_ALLOC(double, face_nodes_p);
      xyz_on_f_m[d] = P4EST_ALLOC(double, face_nodes_m);
      
      dgmath_apply_slicer
        (
         dgmath_jit_dbase,
         (e_m->xyz[d]),
         (P4EST_DIM),
         f_m,
         e_m->deg,
         &(xyz_on_f_m[d][0])
        );

      dgmath_reorient_face_data
        (
         dgmath_jit_dbase,
         &(xyz_on_f_m[d][0]),
         (P4EST_DIM) - 1,
         e_p->deg,
         info->orientation,
         f_m,
         f_p,
         &(xyz_on_f_m_reoriented[d][0])
        );
      
      dgmath_apply_slicer
        (
         dgmath_jit_dbase,
         (e_p->xyz[d]),
         (P4EST_DIM),
         f_p,
         e_p->deg,
         &(xyz_on_f_p[d][0])
        );

      dgmath_reorient_face_data
        (
         dgmath_jit_dbase,
         &(xyz_on_f_p[d][0]),
         (P4EST_DIM) - 1,
         e_p->deg,
         info->orientation,
         f_m,
         f_p,
         &(xyz_on_f_p_reoriented[d][0])
        );

    }
    /* P4EST_FREE(tmp); */

    int c_m [2*((P4EST_DIM)-1)];
    int c_p [2*((P4EST_DIM)-1)];

    for (i = 0; i < 2; i++){
      c_m[i] = p4est_face_corners[f_m][i];
      c_p[i] = p4est_face_corners[f_p][i];
      if (f_m <= f_p)
        c_p[i] = p4est_connectivity_face_neighbor_corner_orientation(c_m[i], f_m, f_p, info->orientation);
      else
        c_m[i] = p4est_connectivity_face_neighbor_corner_orientation(c_p[i], f_p, f_m, info->orientation);
    }

    int ftransform [9];
    p4est_expand_face_transform
      (
       ((f_m <= f_p) ? f_m : f_p),
       4*info->orientation + ((f_m <= f_p) ? f_p : f_m),
       ftransform
      );
   
    if (test_curved_data->print){
      printf("orientation %d, tree_boundary %d\n", info->orientation, info->tree_boundary);
      printf("side m: treeid = %d face = %d is_hanging = %d, corners %d,%d= \n", side[s_m]->treeid, side[s_m]->face, side[s_m]->is_hanging, c_m[0], c_m[1]);
      printf("side p: treeid = %d face = %d is_hanging = %d, corners %d,%d \n", side[s_p]->treeid, side[s_p]->face, side[s_p]->is_hanging, c_p[0], c_p[1]);
    }

   /*  printf */
   /*    ( */
   /*     "face_transform = \n %d,%d,%d \n %d,%d,%d \n %d,%d,%d \n", */
   /*     ftransform[0], */
   /*     ftransform[1], */
   /*     ftransform[2], */
   /*     ftransform[3], */
   /*     ftransform[4], */
   /*     ftransform[5], */
   /*     ftransform[6], */
   /*     ftransform[7], */
   /*     ftransform[8] */
   /*    ); */

   /*  printf */
   /*    ( */
   /*     "f_m corner 0 = %f,%f,%f // f_p corner 0 = %f,%f,%f\n", */
   /*     xyz_on_f_m[0][0], */
   /*     xyz_on_f_m[1][0], */
   /*     xyz_on_f_m[2][0], */
   /*     xyz_on_f_p[0][0], */
   /*     xyz_on_f_p[1][0], */
   /*     xyz_on_f_p[2][0] */
   /*    ); */


   /*  printf */
   /*    ( */
   /*     "f_m corner 1 = %f,%f,%f // f_p corner 1 = %f,%f,%f\n", */
   /*     xyz_on_f_m[0][e_m->deg], */
   /*     xyz_on_f_m[1][e_m->deg], */
   /*     xyz_on_f_m[2][e_m->deg], */
   /*     xyz_on_f_p[0][e_m->deg], */
   /*     xyz_on_f_p[1][e_m->deg], */
   /*     xyz_on_f_p[2][e_m->deg] */
   /*    ); */


   /* printf */
   /*    ( */
   /*     "f_m corner 2 = %f,%f,%f // f_p corner 2 = %f,%f,%f\n", */
   /*     xyz_on_f_m[0][face_nodes_m - 1 - e_m->deg], */
   /*     xyz_on_f_m[1][face_nodes_m - 1 - e_m->deg], */
   /*     xyz_on_f_m[2][face_nodes_m - 1 - e_m->deg], */
   /*     xyz_on_f_p[0][face_nodes_m - 1 - e_m->deg], */
   /*     xyz_on_f_p[1][face_nodes_m - 1 - e_m->deg], */
   /*     xyz_on_f_p[2][face_nodes_m - 1 - e_m->deg] */
   /*    ); */

   /* printf */
   /*    ( */
   /*     "f_m corner 3 = %f,%f,%f // f_p corner 3 = %f,%f,%f\n", */
   /*     xyz_on_f_m[0][face_nodes_m - 1], */
   /*     xyz_on_f_m[1][face_nodes_m - 1], */
   /*     xyz_on_f_m[2][face_nodes_m - 1], */
   /*     xyz_on_f_p[0][face_nodes_m - 1], */
   /*     xyz_on_f_p[1][face_nodes_m - 1], */
   /*     xyz_on_f_p[2][face_nodes_m - 1] */
   /*    ); */

    int j;
    for (j = 0; j < face_nodes_m; j++){
      double err = 0.;
      double err_re = 0.;
      double err_re2 = 0.;
      err += fabs(xyz_on_f_m[0][j] - xyz_on_f_p[0][j]);
      err += fabs(xyz_on_f_m[1][j] - xyz_on_f_p[1][j]);
      err_re += fabs(xyz_on_f_m[0][j] - xyz_on_f_p_reoriented[0][j]);
      err_re += fabs(xyz_on_f_m[1][j] - xyz_on_f_p_reoriented[1][j]);
      err_re2 += fabs(xyz_on_f_p[0][j] - xyz_on_f_m_reoriented[0][j]);
      err_re2 += fabs(xyz_on_f_p[1][j] - xyz_on_f_m_reoriented[1][j]);
      if (test_curved_data->print)
        printf("%d %d %f %f %f  %f %f %f %f %f %s %s %s\n",
               e_m->id,
               e_p->id,
               (xyz_on_f_m[0][j]),
               (xyz_on_f_m[1][j]),
               (xyz_on_f_p[0][j]),
               (xyz_on_f_p[1][j]),
               (xyz_on_f_p_reoriented[0][j]),
               (xyz_on_f_p_reoriented[1][j]),
               (xyz_on_f_m_reoriented[0][j]),
               (xyz_on_f_m_reoriented[1][j]),
               (err > .00001) ? "ERR_BAD" : "ERR_OK",
               (err_re > .00001) ? "ERR_STILL_BAD" : "ERR_NOW_OK",
               (err_re2 > .00001) ? "ERR_STILL_STILL_BAD" : "ERR_NOW_NOW_OK"
              );
      test_curved_data->err += err;
      test_curved_data->err_re += err_re;
      test_curved_data->err_re2 += err_re2;
    }
    for (int d = 0; d < (P4EST_DIM); d++){
      P4EST_FREE(xyz_on_f_p[d]);
      P4EST_FREE(xyz_on_f_p_reoriented[d]);
      P4EST_FREE(xyz_on_f_m_reoriented[d]);
      P4EST_FREE(xyz_on_f_m[d]);
    }

  }
示例#3
0
/** Approximate the flux across a boundary between quadrants.
 *
 * We use a very simple upwind numerical flux.
 *
 * This function matches the p4est_iter_face_t prototype used by
 * p4est_iterate().
 *
 * \param [in] info the information about the quadrants on either side of the
 *                  interface, populated by p4est_iterate()
 * \param [in] user_data the user_data given to p4est_iterate(): in this case,
 *                       it points to the ghost_data array, which contains the
 *                       step3_data_t data for all of the ghost cells, which
 *                       was populated by p4est_ghost_exchange_data()
 */
static void
step3_upwind_flux (p4est_iter_face_info_t * info, void *user_data)
{
  int                 i, j;
  p4est_t            *p4est = info->p4est;
  step3_ctx_t        *ctx = (step3_ctx_t *) p4est->user_pointer;
  step3_data_t       *ghost_data = (step3_data_t *) user_data;
  step3_data_t       *udata;
  p4est_quadrant_t   *quad;
  double              vdotn = 0.;
  double              uavg;
  double              q;
  double              h, facearea;
  int                 which_face;
  int                 upwindside;
  p4est_iter_face_side_t *side[2];
  sc_array_t         *sides = &(info->sides);

  /* because there are no boundaries, every face has two sides */
  P4EST_ASSERT (sides->elem_count == 2);

  side[0] = p4est_iter_fside_array_index_int (sides, 0);
  side[1] = p4est_iter_fside_array_index_int (sides, 1);

  /* which of the quadrant's faces the interface touches */
  which_face = side[0]->face;

  switch (which_face) {
  case 0:                      /* -x side */
    vdotn = -ctx->v[0];
    break;
  case 1:                      /* +x side */
    vdotn = ctx->v[0];
    break;
  case 2:                      /* -y side */
    vdotn = -ctx->v[1];
    break;
  case 3:                      /* +y side */
    vdotn = ctx->v[1];
    break;
#ifdef P4_TO_P8
  case 4:                      /* -z side */
    vdotn = -ctx->v[2];
    break;
  case 5:                      /* +z side */
    vdotn = ctx->v[2];
    break;
#endif
  }
  upwindside = vdotn >= 0. ? 0 : 1;

  /* Because we have non-conforming boundaries, one side of an interface can
   * either have one large ("full") quadrant or 2^(d-1) small ("hanging")
   * quadrants: we have to compute the average differently in each case.  The
   * info populated by p4est_iterate() gives us the context we need to
   * proceed. */
  uavg = 0;
  if (side[upwindside]->is_hanging) {
    /* there are 2^(d-1) (P4EST_HALF) subfaces */
    for (j = 0; j < P4EST_HALF; j++) {
      if (side[upwindside]->is.hanging.is_ghost[j]) {
        /* *INDENT-OFF* */
        udata =
          (step3_data_t *) &ghost_data[side[upwindside]->is.hanging.quadid[j]];
        /* *INDENT-ON* */
      }
      else {
        udata =
          (step3_data_t *) side[upwindside]->is.hanging.quad[j]->p.user_data;
      }
      uavg += udata->u;
    }
    uavg /= P4EST_HALF;
  }
  else {
    if (side[upwindside]->is.full.is_ghost) {
      udata = (step3_data_t *) & ghost_data[side[upwindside]->is.full.quadid];
    }
    else {
      udata = (step3_data_t *) side[upwindside]->is.full.quad->p.user_data;
    }
    uavg = udata->u;
  }
  /* flux from side 0 to side 1 */
  q = vdotn * uavg;
  for (i = 0; i < 2; i++) {
    if (side[i]->is_hanging) {
      /* there are 2^(d-1) (P4EST_HALF) subfaces */
      for (j = 0; j < P4EST_HALF; j++) {
        quad = side[i]->is.hanging.quad[j];
        h =
          (double) P4EST_QUADRANT_LEN (quad->level) / (double) P4EST_ROOT_LEN;
#ifndef P4_TO_P8
        facearea = h;
#else
        facearea = h * h;
#endif
        if (!side[i]->is.hanging.is_ghost[j]) {
          udata = (step3_data_t *) quad->p.user_data;
          if (i == upwindside) {
            udata->dudt += vdotn * udata->u * facearea * (i ? 1. : -1.);
          }
          else {
            udata->dudt += q * facearea * (i ? 1. : -1.);
          }
        }
      }
    }
    else {
      quad = side[i]->is.full.quad;
      h = (double) P4EST_QUADRANT_LEN (quad->level) / (double) P4EST_ROOT_LEN;
#ifndef P4_TO_P8
      facearea = h;
#else
      facearea = h * h;
#endif
      if (!side[i]->is.full.is_ghost) {
        udata = (step3_data_t *) quad->p.user_data;
        udata->dudt += q * facearea * (i ? 1. : -1.);
      }
    }
  }
}