/** 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]); } }
/** 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.); } } } }