static void
curved_sipg_weak_flux_scalar_interface
(
 curved_element_data_t** e_m,
 int faces_m,
 int f_m,
 curved_element_data_t** e_p,
 int faces_p,
 int f_p,
 int* e_m_is_ghost,
 int orientation,
 dgmath_jit_dbase_t* dgmath_jit_dbase,
 p4est_geometry_t* geom,     
 void* params
)
{
  int stride;
  int deg_p [(P4EST_HALF)];
  int max_deg_p = -1;
  int face_nodes_p [(P4EST_HALF)];
  int deg_m [(P4EST_HALF)];
  int face_nodes_m [(P4EST_HALF)];
  int max_deg_m = -1;
  
  int deg_mortar [(P4EST_HALF)];
  int nodes_mortar [(P4EST_HALF)];
  int faces_mortar = (faces_m > faces_p) ? faces_m : faces_p;
  
  curved_element_data_t* e_p_oriented [(P4EST_HALF)];
  curved_element_data_reorient_f_p_elements_to_f_m_order(e_p, (P4EST_DIM)-1, f_m, f_p, orientation, faces_p, e_p_oriented);
  
  /* calculate degs and nodes of each face of (-) side */
  int total_side_nodes_m = 0;
  for (int i = 0; i < faces_m; i++){
    deg_m[i] = e_m[i]->deg;
    if (e_m[i]->deg > max_deg_m) max_deg_m = e_m[i]->deg;
    face_nodes_m[i] = dgmath_get_nodes( (P4EST_DIM) - 1, e_m[i]->deg );
    total_side_nodes_m += face_nodes_m[i];
  }

  /* calculate degs and nodes of each face of (+) side  */
  int total_side_nodes_p = 0;
  for (int i = 0; i < faces_p; i++){
    deg_p[i] = e_p_oriented[i]->deg;
    if (e_p_oriented[i]->deg > max_deg_p) max_deg_p = e_p_oriented[i]->deg;
    face_nodes_p[i] = dgmath_get_nodes( (P4EST_DIM) - 1, e_p_oriented[i]->deg );
    total_side_nodes_p += face_nodes_p[i];
  }    

  /* calculate degs and nodes of the mortar faces */
  int total_nodes_mortar = 0;
  for (int i = 0; i < faces_m; i++)
    for (int j = 0; j < faces_p; j++){
      /* find max degree for each face pair of the two sides*/
      deg_mortar[i+j] = util_max_int( e_m[i]->deg, e_p_oriented[j]->deg );
      nodes_mortar[i+j] = dgmath_get_nodes( (P4EST_DIM) - 1, deg_mortar[i+j] );     
      total_nodes_mortar += nodes_mortar[i+j];
    }

  
  /* scalar and scalar fields on each of the (-) and (+) elements */
  double* u_m_on_f_m = P4EST_ALLOC(double, total_side_nodes_m);
  double* u_p_on_f_p = P4EST_ALLOC(double, total_side_nodes_p);

  /* projections of f_m slices to max_deg space */
  double* u_m_on_f_m_mortar = P4EST_ALLOC(double, total_nodes_mortar);
  double* u_p_on_f_p_mortar = P4EST_ALLOC(double, total_nodes_mortar);
  
  double* ustar_min_u_mortar = P4EST_ALLOC(double, total_nodes_mortar);
  double* sj_n_ustar_min_u_mortar = P4EST_ALLOC(double, total_nodes_mortar);
  double* M_sj_n_ustar_min_u_mortar = P4EST_ALLOC(double, total_nodes_mortar);
  double* proj_M_sj_n_ustar_min_u_mortar = P4EST_ALLOC(double, total_side_nodes_m);

  double* sj_on_f_m_mortar = P4EST_ALLOC(double, total_nodes_mortar);
  double* n_on_f_m_mortar [(P4EST_DIM)];

  for (int i = 0; i < (P4EST_DIM); i++){
    n_on_f_m_mortar[i] = P4EST_ALLOC(double, total_nodes_mortar);
  }

  stride = 0;
  for (int i = 0; i < faces_m; i++){
    
    dgmath_apply_slicer
      (
       dgmath_jit_dbase,
       &(e_m[i]->u_elem[0]),
       (P4EST_DIM),
       f_m,
       e_m[i]->deg,
       &u_m_on_f_m[stride]
      );   
    
     stride += face_nodes_m[i];
  }

  stride = 0;
  double* tmp = P4EST_ALLOC(double, total_side_nodes_p);
  for (int i = 0; i < faces_p; i++){
    dgmath_apply_slicer
      (
       dgmath_jit_dbase,
       &(e_p_oriented[i]->u_elem[0]),
       (P4EST_DIM),
       f_p,
       e_p_oriented[i]->deg,
       tmp
      );
    dgmath_reorient_face_data
      (
       dgmath_jit_dbase,
       tmp,
       ((P4EST_DIM) - 1),
       e_p_oriented[i]->deg,
       orientation,
       f_m,
       f_p,
       &u_p_on_f_p[stride]
      );
    stride += face_nodes_p[i];
  }
  P4EST_FREE(tmp);
  
  /* project (-)-side u trace scalar onto mortar space */ 
  dgmath_project_side_onto_mortar_space
    (
     dgmath_jit_dbase,
     u_m_on_f_m,
     faces_m,
     deg_m,
     u_m_on_f_m_mortar,
     faces_mortar,
     deg_mortar
    );

  /* project (+)-side u trace scalar onto mortar space */
  dgmath_project_side_onto_mortar_space
    (
     dgmath_jit_dbase,
     u_p_on_f_p,
     faces_p,
     deg_p,
     u_p_on_f_p_mortar,
     faces_mortar,
     deg_mortar
    );

  curved_element_data_compute_mortar_normal_and_sj_using_face_data
    (
     e_m,
     faces_m,
     faces_mortar,
     &deg_mortar[0],
     f_m,
     n_on_f_m_mortar,
     sj_on_f_m_mortar,
     geom,
     dgmath_jit_dbase
    );

  /* calculate symmetric interior penalty flux */
  int k;
  int f;
  stride = 0;
  for (f = 0; f < faces_mortar; f++){
    for (k = 0; k < nodes_mortar[f]; k++){
      int ks = k + stride;
      ustar_min_u_mortar[ks] = .5*(u_p_on_f_p_mortar[ks] + u_m_on_f_m_mortar[ks]);
    }
    stride += nodes_mortar[f];
  }
    
  for (int d = 0; d < (P4EST_DIM); d++){

    stride = 0;
    for (int f = 0; f < faces_mortar; f++){
      for (int k = 0; k < nodes_mortar[f]; k++){
        int ks = k + stride;
        sj_n_ustar_min_u_mortar[ks] = sj_on_f_m_mortar[ks]*n_on_f_m_mortar[d][ks]*ustar_min_u_mortar[ks];
      }
      dgmath_apply_Mij(dgmath_jit_dbase, &sj_n_ustar_min_u_mortar[stride], (P4EST_DIM)-1, deg_mortar[f], &M_sj_n_ustar_min_u_mortar[stride]);
      stride += nodes_mortar[f];
    }
      
    /* project mortar data back onto the (-) side */
    dgmath_project_mass_mortar_onto_side
      (
       dgmath_jit_dbase,
       M_sj_n_ustar_min_u_mortar,
       faces_mortar,
       deg_mortar,
       proj_M_sj_n_ustar_min_u_mortar,
       faces_m,
       deg_m
      );

  
    /* copy result back to element */
    stride = 0;
    for (int i = 0; i < faces_m; i++){
      if(e_m_is_ghost[i] == 0)
        linalg_copy_1st_to_2nd
          (
           &proj_M_sj_n_ustar_min_u_mortar[stride],
           &(e_m[i]->M_ustar_min_u_n[d][f_m*face_nodes_m[i]]),
           face_nodes_m[i]
          );
      stride += face_nodes_m[i];
    }    
  }

  for (int d = 0; d < (P4EST_DIM); d++){
    P4EST_FREE(n_on_f_m_mortar[d]);
  }
  
  P4EST_FREE(ustar_min_u_mortar);
  P4EST_FREE(sj_n_ustar_min_u_mortar);
  P4EST_FREE(M_sj_n_ustar_min_u_mortar);
  P4EST_FREE(proj_M_sj_n_ustar_min_u_mortar);
  P4EST_FREE(u_p_on_f_p_mortar);
  P4EST_FREE(u_m_on_f_m_mortar);
  P4EST_FREE(sj_on_f_m_mortar);
  P4EST_FREE(u_p_on_f_p);
  P4EST_FREE(u_m_on_f_m);
}
예제 #2
0
int
p6est_vtk_write_point_scalar (p6est_t * p6est,
                              const char *filename,
                              const char *scalar_name, const double *values)
{
  const int           mpirank = p6est->mpirank;
  const p4est_locidx_t Ncells = (p4est_locidx_t) p6est->layers->elem_count;
  const p4est_locidx_t Ncorners = P8EST_CHILDREN * Ncells;      /* type ok */
  int                 retval;
  p4est_locidx_t      il;
#ifndef P4EST_VTK_ASCII
  P4EST_VTK_FLOAT_TYPE *float_data;
#endif
  char                vtufilename[BUFSIZ];
  FILE               *vtufile;

  /* Have each proc write to its own file */
  snprintf (vtufilename, BUFSIZ, "%s_%04d.vtu", filename, mpirank);
  /* To be able to fseek in a file you cannot open in append mode.
   * so you need to open with "r+" and fseek to SEEK_END.
   */
  vtufile = fopen (vtufilename, "rb+");
  if (vtufile == NULL) {
    P4EST_LERRORF ("Could not open %s for output\n", vtufilename);
    return -1;
  }
  retval = fseek (vtufile, 0L, SEEK_END);
  if (retval) {
    P4EST_LERRORF ("Could not fseek %s for output\n", vtufilename);
    fclose (vtufile);
    return -1;
  }

  /* write point position data */
  fprintf (vtufile, "        <DataArray type=\"%s\" Name=\"%s\""
           " format=\"%s\">\n",
           P4EST_VTK_FLOAT_NAME, scalar_name, P4EST_VTK_FORMAT_STRING);

#ifdef P4EST_VTK_ASCII
  for (il = 0; il < Ncorners; ++il) {
#ifdef P4EST_VTK_DOUBLES
    fprintf (vtufile, "     %24.16e\n", values[il]);
#else
    fprintf (vtufile, "          %16.8e\n", values[il]);
#endif
  }
#else
  float_data = P4EST_ALLOC (P4EST_VTK_FLOAT_TYPE, Ncorners);
  for (il = 0; il < Ncorners; ++il) {
    float_data[il] = (P4EST_VTK_FLOAT_TYPE) values[il];
  }

  fprintf (vtufile, "          ");
  /* TODO: Don't allocate the full size of the array, only allocate
   * the chunk that will be passed to zlib and do this a chunk
   * at a time.
   */
  retval = p6est_vtk_write_binary (vtufile, (char *) float_data,
                                   sizeof (*float_data) * Ncorners);
  fprintf (vtufile, "\n");
  if (retval) {
    P4EST_LERROR ("p6est_vtk: Error encoding points\n");
    fclose (vtufile);
    return -1;
  }
  P4EST_FREE (float_data);
#endif
  fprintf (vtufile, "        </DataArray>\n");

  if (ferror (vtufile)) {
    P4EST_LERROR ("p6est_vtk: Error writing point scalar\n");
    fclose (vtufile);
    return -1;
  }
  if (fclose (vtufile)) {
    P4EST_LERROR ("p6est_vtk: Error closing point scalar\n");
    return -1;
  }
  vtufile = NULL;

  /* Only have the root write to the parallel vtk file */
  if (mpirank == 0) {
    char                pvtufilename[BUFSIZ];
    FILE               *pvtufile;
    snprintf (pvtufilename, BUFSIZ, "%s.pvtu", filename);

    pvtufile = fopen (pvtufilename, "ab");
    if (!pvtufile) {
      P4EST_LERRORF ("Could not open %s for output\n", vtufilename);
      return -1;
    }

    fprintf (pvtufile, "      <PDataArray type=\"%s\" Name=\"%s\""
             " format=\"%s\"/>\n",
             P4EST_VTK_FLOAT_NAME, scalar_name, P4EST_VTK_FORMAT_STRING);

    if (ferror (pvtufile)) {
      P4EST_LERROR ("p6est_vtk: Error writing parallel point scalar\n");
      fclose (pvtufile);
      return -1;
    }
    if (fclose (pvtufile)) {
      P4EST_LERROR ("p6est_vtk: Error closing parallel point scalar\n");
      return -1;
    }
  }

  return 0;
}
예제 #3
0
int
p6est_comm_parallel_env_reduce_ext (p6est_t ** p6est_supercomm,
                                    sc_MPI_Group group_add,
                                    int add_to_beginning, int **ranks_subcomm)
{
  p6est_t            *p6est = *p6est_supercomm;
  int                 mpisize = p6est->mpisize;
  int                 mpiret;
  p4est_gloidx_t     *global_first_layer = p6est->global_first_layer;

  p4est_gloidx_t     *n_quadrants;
  int                 submpisize;
  sc_MPI_Comm         submpicomm;
  int                *ranks;
  int                 i;
  int                 is_nonempty;

  /* reduce MPI communicator of column layout */
  is_nonempty =
    p4est_comm_parallel_env_reduce_ext (&(p6est->columns), group_add,
                                        add_to_beginning, &ranks);

  /* destroy p4est and exit if this rank is empty */
  if (!is_nonempty) {
    p6est->columns = NULL;
    p6est_destroy (p6est);
    *p6est_supercomm = NULL;
    if (ranks_subcomm) {
      *ranks_subcomm = NULL;
    }
    P4EST_ASSERT (ranks == NULL);
    return 0;
  }

  /* get sub-communicator */
  submpicomm = p6est->columns->mpicomm;

  /* update size of new MPI communicator */
  mpiret = sc_MPI_Comm_size (submpicomm, &submpisize);
  SC_CHECK_MPI (mpiret);
  if (submpisize == p6est->mpisize) {
    P4EST_ASSERT (ranks == NULL);
    return 1;
  }

  /* set new parallel environment */
  p6est_comm_parallel_env_release (p6est);
  p6est_comm_parallel_env_assign (p6est, submpicomm);
  if (p6est->columns->mpicomm_owned) {
    p6est->columns->mpicomm_owned = 0;
    p6est->mpicomm_owned = 1;
  }
  P4EST_ASSERT (p6est->mpisize == submpisize);

  /* create array of non-empty processes that will be included to sub-comm */
  n_quadrants = P4EST_ALLOC (p4est_gloidx_t, mpisize);
  for (i = 0; i < mpisize; i++) {
    n_quadrants[i] = global_first_layer[i + 1] - global_first_layer[i];
  }

  /* allocate and set global layer count */
  P4EST_FREE (p6est->global_first_layer);
  p6est->global_first_layer = P4EST_ALLOC (p4est_gloidx_t, submpisize + 1);
  p6est->global_first_layer[0] = 0;
  for (i = 0; i < submpisize; i++) {
    P4EST_ASSERT (ranks[i] != sc_MPI_UNDEFINED);
    P4EST_ASSERT (group_add != sc_MPI_GROUP_NULL
                  || 0 < n_quadrants[ranks[i]]);
    p6est->global_first_layer[i + 1] =
      p6est->global_first_layer[i] + n_quadrants[ranks[i]];
  }
  P4EST_FREE (n_quadrants);
  if (ranks_subcomm) {
    *ranks_subcomm = ranks;
  }
  else {
    P4EST_FREE (ranks);
  }

  /* return that p6est exists on this rank */
  return 1;
}
예제 #4
0
int
p6est_profile_sync (p6est_profile_t * profile)
{
  p4est_lnodes_t     *lnodes = profile->lnodes;
  p4est_locidx_t      nln = lnodes->num_local_nodes;
  sc_array_t          lrview;
  p4est_lnodes_buffer_t *countbuf;
  sc_array_t         *sharers;
  size_t              zz, nsharers;
  int                 nleft;
  int8_t             *recv, *send;
  int                *array_of_indices;
  p4est_locidx_t      recv_total;
  p4est_locidx_t     *recv_offsets, recv_offset;
  p4est_locidx_t      send_total;
  p4est_locidx_t     *send_offsets, send_offset;
  p4est_locidx_t (*lr)[2];
  sc_array_t         *lc = profile->lnode_columns;
  sc_MPI_Request     *recv_request, *send_request;
  sc_array_t         *work;
  int                 any_change = 0;
  int                 any_global_change;
  int                 mpiret, mpirank;
  int                 evenodd = profile->evenodd;

  lr = (p4est_locidx_t (*)[2]) profile->lnode_ranges;
  sharers = lnodes->sharers;
  nsharers = sharers->elem_count;

  mpiret = sc_MPI_Comm_rank (lnodes->mpicomm, &mpirank);
  SC_CHECK_MPI (mpiret);

  sc_array_init_data (&lrview, lr, 2 * sizeof (p4est_locidx_t), nln);

  countbuf = p4est_lnodes_share_all_begin (&lrview, lnodes);
  send_offsets = P4EST_ALLOC (p4est_locidx_t, nsharers + 1);
  send_offset = 0;
  for (zz = 0; zz < nsharers; zz++) {
    p4est_lnodes_rank_t *sharer;
    sc_array_t         *send_buf;
    size_t              zy, nnodes;

    send_offsets[zz] = send_offset;
    sharer = p4est_lnodes_rank_array_index (sharers, zz);
    if (sharer->rank == mpirank) {
      continue;
    }
    send_buf = (sc_array_t *) sc_array_index (countbuf->send_buffers, zz);
    nnodes = sharer->shared_nodes.elem_count;

    P4EST_ASSERT (nnodes == send_buf->elem_count);

    P4EST_ASSERT (send_buf->elem_size == 2 * sizeof (p4est_locidx_t));
    for (zy = 0; zy < nnodes; zy++) {
      p4est_locidx_t     *lp =
        (p4est_locidx_t *) sc_array_index (send_buf, zy);
      P4EST_ASSERT (lp[0] >= 0);
      P4EST_ASSERT (lp[1] >= 0);
      send_offset += lp[1];
    }
  }
  send_total = send_offsets[nsharers] = send_offset;

  p4est_lnodes_share_all_end (countbuf);
  recv_offsets = P4EST_ALLOC (p4est_locidx_t, nsharers + 1);
  recv_offset = 0;
  for (zz = 0; zz < nsharers; zz++) {
    p4est_lnodes_rank_t *sharer;
    sc_array_t         *recv_buf;
    size_t              zy, nnodes;

    recv_offsets[zz] = recv_offset;
    sharer = p4est_lnodes_rank_array_index (sharers, zz);
    if (sharer->rank == mpirank) {
      continue;
    }
    recv_buf = (sc_array_t *) sc_array_index (countbuf->recv_buffers, zz);
    nnodes = sharer->shared_nodes.elem_count;

    P4EST_ASSERT (nnodes == recv_buf->elem_count);

    P4EST_ASSERT (recv_buf->elem_size == 2 * sizeof (p4est_locidx_t));
    for (zy = 0; zy < nnodes; zy++) {
      p4est_locidx_t     *lp =
        (p4est_locidx_t *) sc_array_index (recv_buf, zy);
      P4EST_ASSERT (lp[0] >= 0);
      P4EST_ASSERT (lp[1] >= 0);
      recv_offset += lp[1];
    }
  }
  recv_total = recv_offsets[nsharers] = recv_offset;

  recv = P4EST_ALLOC (int8_t, recv_total);
  recv_request = P4EST_ALLOC (sc_MPI_Request, nsharers);
  send = P4EST_ALLOC (int8_t, send_total);
  send_request = P4EST_ALLOC (sc_MPI_Request, nsharers);

  /* post receives */
  nleft = 0;
  for (zz = 0; zz < nsharers; zz++) {
    p4est_lnodes_rank_t *sharer;
    int                 icount = recv_offsets[zz + 1] - recv_offsets[zz];

    sharer = p4est_lnodes_rank_array_index (sharers, zz);
    if (sharer->rank == mpirank) {
      recv_request[zz] = sc_MPI_REQUEST_NULL;
      continue;
    }
    if (icount) {
      mpiret =
        sc_MPI_Irecv (recv + recv_offsets[zz], icount * sizeof (int8_t),
                      sc_MPI_BYTE, sharer->rank, P6EST_COMM_BALANCE,
                      lnodes->mpicomm, recv_request + zz);
      SC_CHECK_MPI (mpiret);
      nleft++;
    }
    else {
      recv_request[zz] = sc_MPI_REQUEST_NULL;
    }
  }

  /* post sends */
  for (zz = 0; zz < nsharers; zz++) {
    p4est_lnodes_rank_t *sharer;
    size_t              zy, nnodes;
    int                 icount;
    sc_array_t         *shared_nodes;

    sharer = p4est_lnodes_rank_array_index (sharers, zz);
    if (sharer->rank == mpirank) {
      send_request[zz] = sc_MPI_REQUEST_NULL;
      continue;
    }
    shared_nodes = &sharer->shared_nodes;
    nnodes = shared_nodes->elem_count;
    icount = 0;
    for (zy = 0; zy < nnodes; zy++) {
      p4est_locidx_t      nidx;
      int8_t             *c;

      nidx = *((p4est_locidx_t *) sc_array_index (shared_nodes, zy));

      if (lr[nidx][1]) {
        c = (int8_t *) sc_array_index (lc, lr[nidx][0]);
        memcpy (send + send_offsets[zz] + icount, c,
                lr[nidx][1] * sizeof (int8_t));
        icount += lr[nidx][1];
      }
      else {
        P4EST_ASSERT (!lr[nidx][0]);
      }
    }
    P4EST_ASSERT (icount == send_offsets[zz + 1] - send_offsets[zz]);
    if (icount) {
      mpiret =
        sc_MPI_Isend (send + send_offsets[zz], icount * sizeof (int8_t),
                      sc_MPI_BYTE, sharer->rank, P6EST_COMM_BALANCE,
                      lnodes->mpicomm, send_request + zz);
      SC_CHECK_MPI (mpiret);
    }
    else {
      send_request[zz] = sc_MPI_REQUEST_NULL;
    }
  }

  work = sc_array_new (sizeof (int8_t));
  array_of_indices = P4EST_ALLOC (int, nsharers);
  while (nleft) {
    int                 outcount;
    int                 i;

    mpiret = sc_MPI_Waitsome (nsharers, recv_request, &outcount,
                              array_of_indices, sc_MPI_STATUSES_IGNORE);
    SC_CHECK_MPI (mpiret);

    for (i = 0; i < outcount; i++) {
      p4est_lnodes_rank_t *sharer;
      size_t              zy, nnode;
      sc_array_t         *shared_nodes;
      sc_array_t         *recv_buf;

      zz = array_of_indices[i];
      sharer = p4est_lnodes_rank_array_index (sharers, zz);
      shared_nodes = &sharer->shared_nodes;
      recv_buf = (sc_array_t *) sc_array_index (countbuf->recv_buffers, zz);
      nnode = shared_nodes->elem_count;
      P4EST_ASSERT (nnode == recv_buf->elem_count);

      recv_offset = recv_offsets[zz];
      for (zy = 0; zy < nnode; zy++) {
        p4est_locidx_t     *lp;
        p4est_locidx_t      nidx;
        sc_array_t          oldview, newview;

        nidx = *((p4est_locidx_t *) sc_array_index (shared_nodes, zy));
        lp = (p4est_locidx_t *) sc_array_index (recv_buf, zy);

        sc_array_init_view (&oldview, lc, lr[nidx][0], lr[nidx][1]);
        sc_array_init_data (&newview, recv + recv_offset, sizeof (int8_t),
                            lp[1]);
        if (profile->ptype == P6EST_PROFILE_UNION) {
          p6est_profile_union (&oldview, &newview, work);

          if (work->elem_count > oldview.elem_count) {
            int8_t             *c;

            any_change = 1;
            lr[nidx][0] = lc->elem_count;
            lr[nidx][1] = work->elem_count;
            profile->lnode_changed[evenodd][nidx] = 1;

            c = (int8_t *) sc_array_push_count (lc, work->elem_count);
            memcpy (c, work->array, work->elem_count * work->elem_size);
          }
        }
        else {
          p6est_profile_intersection (&oldview, &newview, work);
          P4EST_ASSERT (work->elem_count <= oldview.elem_count);
          if (work->elem_count < oldview.elem_count) {
            lr[nidx][1] = work->elem_count;
            memcpy (oldview.array, work->array,
                    work->elem_count * work->elem_size);
          }
        }

        recv_offset += lp[1];
      }
      P4EST_ASSERT (recv_offset == recv_offsets[zz + 1]);
    }

    nleft -= outcount;
    P4EST_ASSERT (nleft >= 0);
  }
  P4EST_FREE (array_of_indices);
  sc_array_destroy (work);

  p6est_profile_compress (profile);
  p4est_lnodes_buffer_destroy (countbuf);

  P4EST_FREE (recv_request);
  P4EST_FREE (recv_offsets);
  P4EST_FREE (recv);

  {
    mpiret = sc_MPI_Waitall (nsharers, send_request, sc_MPI_STATUSES_IGNORE);

    SC_CHECK_MPI (mpiret);
    P4EST_FREE (send_request);
    P4EST_FREE (send_offsets);
    P4EST_FREE (send);

    any_global_change = any_change;
    mpiret = sc_MPI_Allreduce (&any_change, &any_global_change, 1, sc_MPI_INT,
                               sc_MPI_LOR, lnodes->mpicomm);

    SC_CHECK_MPI (mpiret);
  }

  return any_global_change;
}
예제 #5
0
static void
p4est_check_local_order (p4est_t * p4est, p4est_connectivity_t * connectivity)
{
  const double        intsize = 1.0 / P4EST_ROOT_LEN;
  double             *vertices;
  double              h, eta1, eta2;
  double              v0x, v0y, v0z, v1x, v1y, v1z;
  double              v2x, v2y, v2z, v3x, v3y, v3z;
  double              w0x, w0y, w0z, w1x, w1y, w1z;
  double              w2x, w2y, w2z, w3x, w3y, w3z;
  size_t              iz;
  size_t              num_quads;
  size_t              quad_count;
  p4est_topidx_t      jt;
  p4est_topidx_t     *tree_to_vertex;
  p4est_topidx_t      first_local_tree;
  p4est_topidx_t      last_local_tree;
  p4est_topidx_t      v0, v1, v2, v3;
  p4est_locidx_t      kl;
  p4est_locidx_t      lv0, lv1, lv2, lv3;
  p4est_locidx_t      num_uniq_local_vertices;
  p4est_locidx_t     *quadrant_to_local_vertex;
  p4est_qcoord_t      inth;
  p4est_tree_t       *tree;
  p4est_quadrant_t   *quad;
  p4est_vert_t       *vert_locations;
  p4est_nodes_t      *nodes;
  sc_array_t         *trees;
  sc_array_t         *quadrants;

  nodes = p4est_nodes_new (p4est, NULL);
  quadrant_to_local_vertex = nodes->local_nodes;
  num_uniq_local_vertices = nodes->num_owned_indeps;
  SC_CHECK_ABORT ((size_t) num_uniq_local_vertices ==
                  nodes->indep_nodes.elem_count, "Node count mismatch");

  P4EST_INFOF ("Unique local vertices %lld\n",
               (long long) num_uniq_local_vertices);

  vert_locations = P4EST_ALLOC (p4est_vert_t, num_uniq_local_vertices);
  for (kl = 0; kl < num_uniq_local_vertices; ++kl) {
    vert_locations[kl].treeid = -1;
  }

  tree_to_vertex = connectivity->tree_to_vertex;
  vertices = connectivity->vertices;
  first_local_tree = p4est->first_local_tree;
  last_local_tree = p4est->last_local_tree;
  trees = p4est->trees;

  for (jt = first_local_tree, quad_count = 0; jt <= last_local_tree; ++jt) {
    tree = p4est_tree_array_index (trees, jt);

    P4EST_ASSERT (0 <= jt && jt < connectivity->num_trees);

    v0 = tree_to_vertex[jt * 4 + 0];
    v1 = tree_to_vertex[jt * 4 + 1];
    v2 = tree_to_vertex[jt * 4 + 2];
    v3 = tree_to_vertex[jt * 4 + 3];

    P4EST_ASSERT (0 <= v0 && v0 < connectivity->num_vertices);
    P4EST_ASSERT (0 <= v1 && v1 < connectivity->num_vertices);
    P4EST_ASSERT (0 <= v2 && v2 < connectivity->num_vertices);
    P4EST_ASSERT (0 <= v3 && v3 < connectivity->num_vertices);

    v0x = vertices[v0 * 3 + 0];
    v0y = vertices[v0 * 3 + 1];
    v0z = vertices[v0 * 3 + 2];
    v1x = vertices[v1 * 3 + 0];
    v1y = vertices[v1 * 3 + 1];
    v1z = vertices[v1 * 3 + 2];
    v2x = vertices[v2 * 3 + 0];
    v2y = vertices[v2 * 3 + 1];
    v2z = vertices[v2 * 3 + 2];
    v3x = vertices[v3 * 3 + 0];
    v3y = vertices[v3 * 3 + 1];
    v3z = vertices[v3 * 3 + 2];

    quadrants = &tree->quadrants;
    num_quads = quadrants->elem_count;

    /* loop over the elements in the tree */
    for (iz = 0; iz < num_quads; ++iz, ++quad_count) {
      quad = p4est_quadrant_array_index (quadrants, iz);
      inth = P4EST_QUADRANT_LEN (quad->level);
      h = intsize * inth;
      eta1 = intsize * quad->x;
      eta2 = intsize * quad->y;

      w0x = v0x * (1.0 - eta1) * (1.0 - eta2)
        + v1x * (eta1) * (1.0 - eta2)
        + v2x * (1.0 - eta1) * (eta2)
        + v3x * (eta1) * (eta2);

      w0y = v0y * (1.0 - eta1) * (1.0 - eta2)
        + v1y * (eta1) * (1.0 - eta2)
        + v2y * (1.0 - eta1) * (eta2)
        + v3y * (eta1) * (eta2);

      w0z = v0z * (1.0 - eta1) * (1.0 - eta2)
        + v1z * (eta1) * (1.0 - eta2)
        + v2z * (1.0 - eta1) * (eta2)
        + v3z * (eta1) * (eta2);

      w1x = v0x * (1.0 - eta1 - h) * (1.0 - eta2)
        + v1x * (eta1 + h) * (1.0 - eta2)
        + v2x * (1.0 - eta1 - h) * (eta2)
        + v3x * (eta1 + h) * (eta2);

      w1y = v0y * (1.0 - eta1 - h) * (1.0 - eta2)
        + v1y * (eta1 + h) * (1.0 - eta2)
        + v2y * (1.0 - eta1 - h) * (eta2)
        + v3y * (eta1 + h) * (eta2);

      w1z = v0z * (1.0 - eta1 - h) * (1.0 - eta2)
        + v1z * (eta1 + h) * (1.0 - eta2)
        + v2z * (1.0 - eta1 - h) * (eta2)
        + v3z * (eta1 + h) * (eta2);

      w2x = v0x * (1.0 - eta1) * (1.0 - eta2 - h)
        + v1x * (eta1) * (1.0 - eta2 - h)
        + v2x * (1.0 - eta1) * (eta2 + h)
        + v3x * (eta1) * (eta2 + h);

      w2y = v0y * (1.0 - eta1) * (1.0 - eta2 - h)
        + v1y * (eta1) * (1.0 - eta2 - h)
        + v2y * (1.0 - eta1) * (eta2 + h)
        + v3y * (eta1) * (eta2 + h);

      w2z = v0z * (1.0 - eta1) * (1.0 - eta2 - h)
        + v1z * (eta1) * (1.0 - eta2 - h)
        + v2z * (1.0 - eta1) * (eta2 + h)
        + v3z * (eta1) * (eta2 + h);

      w3x = v0x * (1.0 - eta1 - h) * (1.0 - eta2 - h)
        + v1x * (eta1 + h) * (1.0 - eta2 - h)
        + v2x * (1.0 - eta1 - h) * (eta2 + h)
        + v3x * (eta1 + h) * (eta2 + h);

      w3y = v0y * (1.0 - eta1 - h) * (1.0 - eta2 - h)
        + v1y * (eta1 + h) * (1.0 - eta2 - h)
        + v2y * (1.0 - eta1 - h) * (eta2 + h)
        + v3y * (eta1 + h) * (eta2 + h);

      w3z = v0z * (1.0 - eta1 - h) * (1.0 - eta2 - h)
        + v1z * (eta1 + h) * (1.0 - eta2 - h)
        + v2z * (1.0 - eta1 - h) * (eta2 + h)
        + v3z * (eta1 + h) * (eta2 + h);

      P4EST_ASSERT ((p4est_locidx_t) quad_count < p4est->local_num_quadrants);

      lv0 = quadrant_to_local_vertex[4 * quad_count + 0];
      lv1 = quadrant_to_local_vertex[4 * quad_count + 1];
      lv2 = quadrant_to_local_vertex[4 * quad_count + 2];
      lv3 = quadrant_to_local_vertex[4 * quad_count + 3];

      P4EST_ASSERT (0 <= lv0 && lv0 < num_uniq_local_vertices);
      P4EST_ASSERT (0 <= lv1 && lv1 < num_uniq_local_vertices);
      P4EST_ASSERT (0 <= lv2 && lv2 < num_uniq_local_vertices);
      P4EST_ASSERT (0 <= lv3 && lv3 < num_uniq_local_vertices);

      vert_locations[lv0].x = w0x;
      vert_locations[lv0].y = w0y;
      vert_locations[lv0].z = w0z;
      P4EST_ASSERT (vert_locations[lv0].treeid == -1 ||
                    vert_locations[lv0].treeid == jt);
      vert_locations[lv0].treeid = jt;

      vert_locations[lv1].x = w1x;
      vert_locations[lv1].y = w1y;
      vert_locations[lv1].z = w1z;
      P4EST_ASSERT (vert_locations[lv1].treeid == -1 ||
                    vert_locations[lv1].treeid == jt);
      vert_locations[lv1].treeid = jt;

      vert_locations[lv2].x = w2x;
      vert_locations[lv2].y = w2y;
      vert_locations[lv2].z = w2z;
      P4EST_ASSERT (vert_locations[lv2].treeid == -1 ||
                    vert_locations[lv2].treeid == jt);
      vert_locations[lv2].treeid = jt;

      vert_locations[lv3].x = w3x;
      vert_locations[lv3].y = w3y;
      vert_locations[lv3].z = w3z;
      P4EST_ASSERT (vert_locations[lv3].treeid == -1 ||
                    vert_locations[lv3].treeid == jt);
      vert_locations[lv3].treeid = jt;
    }
  }

  qsort (vert_locations, num_uniq_local_vertices, sizeof (p4est_vert_t),
         p4est_vert_compare);

  /* Check to make sure that we don't have any duplicates in the list */
  for (kl = 0; kl < num_uniq_local_vertices - 1; ++kl) {
    SC_CHECK_ABORT (p4est_vert_compare (vert_locations + kl,
                                        vert_locations + kl + 1) != 0,
                    "local ordering not unique");
  }

  P4EST_FREE (vert_locations);
  p4est_nodes_destroy (nodes);
}
예제 #6
0
int
p4est_wrap_partition (p4est_wrap_t * pp, int weight_exponent,
                      p4est_locidx_t * unchanged_first,
                      p4est_locidx_t * unchanged_length,
                      p4est_locidx_t * unchanged_old_first)
{
  int                 changed;
  p4est_gloidx_t      pre_me, pre_next;
  p4est_gloidx_t      post_me, post_next;

  P4EST_ASSERT (!pp->hollow);

  P4EST_ASSERT (pp->ghost != NULL);
  P4EST_ASSERT (pp->mesh != NULL);
  P4EST_ASSERT (pp->ghost_aux != NULL);
  P4EST_ASSERT (pp->mesh_aux != NULL);
  P4EST_ASSERT (pp->match_aux == 1);

  p4est_mesh_destroy (pp->mesh);
  p4est_ghost_destroy (pp->ghost);
  pp->match_aux = 0;

  /* Remember the window onto global quadrant sequence before partition */
  pre_me = pp->p4est->global_first_quadrant[pp->p4est->mpirank];
  pre_next = pp->p4est->global_first_quadrant[pp->p4est->mpirank + 1];

  /* Initialize output for the case that the partition does not change */
  if (unchanged_first != NULL) {
    *unchanged_first = 0;
  }
  if (unchanged_length != NULL) {
    *unchanged_length = pp->p4est->local_num_quadrants;
  }
  if (unchanged_old_first != NULL) {
    *unchanged_old_first = 0;
  }

  /* In the future the flags could be used to pass partition weights */
  /* We need to lift the restriction on 64 bits for the global weight sum */
  P4EST_ASSERT (weight_exponent == 0 || weight_exponent == 1);
  pp->weight_exponent = weight_exponent;
  changed =
    p4est_partition_ext (pp->p4est, 1,
                         weight_exponent ? partition_weight : NULL) > 0;

  if (changed) {
    P4EST_FREE (pp->flags);
    pp->flags = P4EST_ALLOC_ZERO (uint8_t, pp->p4est->local_num_quadrants);

    pp->ghost = p4est_ghost_new (pp->p4est, pp->btype);
    pp->mesh = p4est_mesh_new_ext (pp->p4est, pp->ghost, 1, 1, pp->btype);

    /* Query the window onto global quadrant sequence after partition */
    if (unchanged_first != NULL || unchanged_length != NULL ||
        unchanged_old_first != NULL) {

      /* compute new windof of local quadrants */
      post_me = pp->p4est->global_first_quadrant[pp->p4est->mpirank];
      post_next = pp->p4est->global_first_quadrant[pp->p4est->mpirank + 1];

      /* compute the range of quadrants that have stayed on this processor */
      p4est_wrap_partition_unchanged (pre_me, pre_next, post_me, post_next,
                                      unchanged_first, unchanged_length,
                                      unchanged_old_first);
    }
  }
  else {
    memset (pp->flags, 0, sizeof (uint8_t) * pp->p4est->local_num_quadrants);

    pp->ghost = pp->ghost_aux;
    pp->mesh = pp->mesh_aux;
    pp->ghost_aux = NULL;
    pp->mesh_aux = NULL;
  }

  return changed;
}
static void
sipg_flux_vector_dirichlet
(
 element_data_t* e_m,
 int f_m,
 grid_fcn_t bndry_fcn,
 dgmath_jit_dbase_t* dgmath_jit_dbase,
 void* params
)
{
  ip_flux_params_t* ip_params = (ip_flux_params_t*) params;
  double sipg_flux_penalty_prefactor = ip_params->ip_flux_penalty_prefactor;
  penalty_calc_t sipg_flux_penalty_calculate_fcn = ip_params->ip_flux_penalty_calculate_fcn;
  
  grid_fcn_t u_at_bndry = bndry_fcn;
  double sigma = sipg_flux_penalty_calculate_fcn
                 (
                  e_m->deg,
                  e_m->h,
                  e_m->deg,
                  e_m->h,
                  sipg_flux_penalty_prefactor
                 );
  int face_nodes_m = dgmath_get_nodes ( (P4EST_DIM) - 1, e_m->deg );
  int vol_nodes_m = dgmath_get_nodes ( (P4EST_DIM) , e_m->deg );
  double* tmp = P4EST_ALLOC(double, face_nodes_m);
  double* xyz_on_f_m [(P4EST_DIM)];
  double* u_m_on_f_m = P4EST_ALLOC(double, face_nodes_m);
  double* du_m_on_f_m = P4EST_ALLOC(double, face_nodes_m);
  double* du_m = P4EST_ALLOC(double, vol_nodes_m);
  double* q_m_on_f_m = P4EST_ALLOC(double, face_nodes_m);
  
  /* get solution variable on this face */
  dgmath_apply_slicer(dgmath_jit_dbase, e_m->u_elem, (P4EST_DIM), f_m, e_m->deg, u_m_on_f_m);

  /* get xyz on this face */
  int dir;
  for (dir = 0; dir < (P4EST_DIM); dir++){
    xyz_on_f_m[dir] = P4EST_ALLOC(double, face_nodes_m);

    double* rst = dgmath_fetch_xyz_nd(dgmath_jit_dbase, (P4EST_DIM), e_m->deg, dir);
    dgmath_apply_slicer(dgmath_jit_dbase, rst, (P4EST_DIM), f_m, e_m->deg, tmp);
    
    dgmath_rtox_array(tmp, e_m->xyz_corner[dir], e_m->h, xyz_on_f_m[dir], face_nodes_m);
  }

  /* get boundary values on this face */
  int i;
  for (i = 0; i < face_nodes_m; i++){
    tmp[i] = u_at_bndry(xyz_on_f_m[0][i],
                             xyz_on_f_m[1][i]
#if (P4EST_DIM)==3
                             ,
                             xyz_on_f_m[2][i]
#endif                          
                            );

    /* printf("u_at_bndry(%f,%f) = %f\n", xyz_on_f_m[0][i], xyz_on_f_m[1][i], tmp[i]); */
  }

  double n [3];
  dgmath_get_normal(f_m, (P4EST_DIM), &n[0]);

  for (dir = 0; dir < (P4EST_DIM); dir++){
    /* calculate gradient of solution variable */
    dgmath_apply_Dij(dgmath_jit_dbase, e_m->u_elem, (P4EST_DIM), e_m->deg, dir, du_m);
    linalg_vec_scale(2./e_m->h, du_m, vol_nodes_m);

    /* get gradient on this face */
    dgmath_apply_slicer(dgmath_jit_dbase, du_m, (P4EST_DIM), f_m, e_m->deg, du_m_on_f_m);
    dgmath_apply_slicer(dgmath_jit_dbase, e_m->q_elem[dir], (P4EST_DIM), f_m, e_m->deg, q_m_on_f_m);
    
    /* calculate qstar - q(-) */
    for(i = 0; i < face_nodes_m; i++){
      /* calculate qstar */
      /* double u_p_on_f_p = 2*tmp[i] - u_m_on_f_m[i]; */
      /* e_m->qstar_min_q[dir][f_m*face_nodes_m + i] = du_m_on_f_m[i] - sigma*n[dir]*(u_m_on_f_m[i] - tmp[i]); */

      /* e_m->qstar_min_q[dir][f_m*face_nodes_m + i] = du_m_on_f_m[i] - sigma*n[dir]*(u_m_on_f_m[i] - u_p_on_f_p); */
      /* printf(" qstar[%d] = %f\n", i,  e_m->qstar_min_q[dir][f_m*face_nodes_m + i]); */

      /* e_m->qstar_min_q[dir][f_m*face_nodes_m + i] = du_m_on_f_m[i] - sigma*n[dir]*(u_m_on_f_m[i] - tmp[i]); */
      /* e_m->qstar_min_q[dir][f_m*face_nodes_m + i] -= q_m_on_f_m[i]; */

      
      /* e_m->qstar_min_q[dir][f_m*face_nodes_m + i] = du_m_on_f_m[i] - sigma*n[dir]*(u_m_on_f_m[i] - tmp[i]); */
      /* e_m->qstar_min_q[dir][f_m*face_nodes_m + i] -= q_m_on_f_m[i]; */

      e_m->qstar_min_q[dir][f_m*face_nodes_m + i] = du_m_on_f_m[i] - sigma*n[dir]*(u_m_on_f_m[i] - tmp[i]);
      e_m->qstar_min_q[dir][f_m*face_nodes_m + i] -= q_m_on_f_m[i];

      /* e_m->qstar_min_q[dir][f_m*face_nodes_m + i] = - sigma*n[dir]*(u_m_on_f_m[i] - tmp[i]); */
    }
  }

  for (dir = 0; dir < (P4EST_DIM); dir++){
    P4EST_FREE(xyz_on_f_m[dir]);
  }
  P4EST_FREE(du_m_on_f_m);
  P4EST_FREE(q_m_on_f_m);
  P4EST_FREE(du_m);
  P4EST_FREE(u_m_on_f_m);
  P4EST_FREE(tmp);
}
void
problem_init
(
 int argc,
 char* argv [],
 p4est_t* p4est,
 p4est_geometry_t* p4est_geom,
 dgmath_jit_dbase_t* dgmath_jit_dbase,
 int proc_size,
 sc_MPI_Comm mpicomm,
 int load_from_checkpoint
)
{
  mpi_assert((P4EST_DIM) == 2 || (P4EST_DIM) == 3);
  int world_rank, world_size;
  sc_MPI_Comm_rank(sc_MPI_COMM_WORLD, &world_rank);
  sc_MPI_Comm_size(sc_MPI_COMM_WORLD, &world_size);

  double* Au = P4EST_ALLOC_ZERO(double, 1);
  double* rhs = P4EST_ALLOC_ZERO(double, 1);
  double* u = P4EST_ALLOC_ZERO(double, 1);
  double* f = P4EST_ALLOC_ZERO(double, 1);
  double* u_analytic = P4EST_ALLOC_ZERO(double, 1);
  int local_nodes = 1;

  problem_input_t input = problem_input("options.input");
  
  int endlevel = input.endlevel;
  int degree = input.degree;         

  ip_flux_params_t ip_flux_params;
  ip_flux_params.ip_flux_penalty_prefactor = input.ip_flux_penalty;
  ip_flux_params.ip_flux_penalty_calculate_fcn = sipg_flux_vector_calc_penalty_maxp2_over_minh;
  
  p4est_ghost_t* ghost = p4est_ghost_new (p4est, P4EST_CONNECT_FACE);
  /* create space for storing the ghost data */
  element_data_t* ghost_data = P4EST_ALLOC (element_data_t,
                                                   ghost->ghosts.elem_count);

  p4est_partition(p4est, 0, NULL);
  p4est_balance (p4est, P4EST_CONNECT_FACE, NULL);

  grid_fcn_t boundary_flux_fcn = zero_fcn;
  
  problem_data_t prob_vecs;
  prob_vecs.rhs = rhs;
  prob_vecs.Au = Au;
  prob_vecs.u = u;
  prob_vecs.f = f;
  prob_vecs.local_nodes = local_nodes;
  
  for (int level = 0; level < endlevel; ++level){

    if (level != 0){
      p4est_refine_ext(p4est,
                       0,
                       -1,
                       refine_function,
                       NULL,
                       NULL
                      );

      p4est_balance_ext
        (
         p4est,
         P4EST_CONNECT_FACE,
         NULL,
         NULL
        );

      p4est_ghost_destroy(ghost);
      P4EST_FREE(ghost_data);

      ghost = p4est_ghost_new(p4est, P4EST_CONNECT_FACE);
      ghost_data = P4EST_ALLOC(element_data_t, ghost->ghosts.elem_count);      
    }

  }


  p4est_partition(p4est, 1, NULL);


  p4est_balance_ext
    (
     p4est,
     P4EST_CONNECT_FACE,
     NULL,
     NULL
    );

  p4est_ghost_destroy(ghost);
  P4EST_FREE(ghost_data);

  ghost = p4est_ghost_new(p4est, P4EST_CONNECT_FACE);
  ghost_data = P4EST_ALLOC(element_data_t, ghost->ghosts.elem_count);      
  

  
  weakeqn_ptrs_t prob_fcns;
  prob_fcns.apply_lhs = problem_apply_aij;
     
  element_data_init(p4est, degree);
  local_nodes = element_data_get_local_nodes(p4est);

  printf("RANK %d: Nodes = %d\n", world_rank, local_nodes);
  
  Au = P4EST_REALLOC(Au, double, local_nodes);
  u = P4EST_REALLOC(u, double, local_nodes);
  f = P4EST_REALLOC(f, double, local_nodes);
  rhs = P4EST_REALLOC(rhs, double, local_nodes);
  u_analytic = P4EST_REALLOC(u_analytic, double, local_nodes);

  prob_vecs.Au = Au;
  prob_vecs.u = u;
  prob_vecs.f = f;
  prob_vecs.rhs = rhs;
  prob_vecs.local_nodes = local_nodes;

  linalg_fill_vec(u, 0., local_nodes);
  element_data_init_node_vec(p4est,f,f_fcn,dgmath_jit_dbase);

  prob_vecs.vector_flux_fcn_data
    = sipg_flux_vector_dirichlet_fetch_fcns
    (
     boundary_fcn,
     &ip_flux_params
    );
  
  prob_vecs.scalar_flux_fcn_data
    = sipg_flux_scalar_dirichlet_fetch_fcns
    (
     boundary_flux_fcn
    );


  problem_build_rhs
    (
     p4est,
     &prob_vecs,
     &prob_fcns,
     ghost,
     ghost_data,
     dgmath_jit_dbase
    );

  clock_t begin = 0;
  clock_t end = -1;

  if (world_rank == 0){
    begin = clock();
  }  

  int vcycle_iter = 3;
  double vcycle_rtol = 1e-3;
  double vcycle_atol = 0.;
  int smooth_iter = 8;
  int cg_eigs_iter = 10;
  double max_eig_factor = 1.1;
  int max_eig_reuse = 1;
  double lmax_lmin_rat = 30.;
  int coarse_iter = 100;
  double coarse_rtol = 1e-8;
  int save_vtk_snapshot = 0;
  int perform_checksum = 0;
  
  multigrid_data_t* mg_data
    = multigrid_data_init
    (
     world_rank,
     endlevel,
     vcycle_iter,
     vcycle_rtol,
     vcycle_atol,
     smooth_iter,
     cg_eigs_iter,
     max_eig_factor,
     max_eig_reuse,
     lmax_lmin_rat,
     CG,
     coarse_iter,
     coarse_rtol,
     save_vtk_snapshot,
     perform_checksum,
     RES_AND_EIG_LOG,
     dgmath_jit_dbase
    );


  multigrid_solve
    (
     p4est,
     &prob_vecs,
     &prob_fcns,
     mg_data,
     &ghost,
     &ghost_data
    );
  
  
  multigrid_data_destroy(mg_data);
  
  element_data_init_node_vec(p4est, u_analytic, analytic_solution_fcn, dgmath_jit_dbase);    
  linalg_vec_axpy(-1., u, u_analytic, local_nodes);

  double local_l2_norm_sqr =  element_data_compute_l2_norm_sqr_no_local
                              (
                               p4est,
                               u_analytic,
                               dgmath_jit_dbase
                              );
  
  double local_nodes_dbl = (double)local_nodes;
  double local_reduce [2];
  local_reduce[0] = local_nodes_dbl;
  local_reduce[1] = local_l2_norm_sqr;

  double global_reduce [2];

  sc_reduce
    (
     &local_reduce[0],
     &global_reduce[0],
     2,
     sc_MPI_DOUBLE,
     sc_MPI_SUM,
     0,
     sc_MPI_COMM_WORLD
    );

  double global_nodes_dbl = global_reduce[0];
  double global_l2_norm_sqr = global_reduce[1];
    
  if (world_rank == 0){
    end = clock();
    double time_spent = (double)(end - begin) / CLOCKS_PER_SEC;
    printf
      (
       "\n\n[HP_AMR]: %d %d %d %.25f %f \n\n",
       degree,
       (int)p4est->global_num_quadrants,
       (int)global_nodes_dbl,
       sqrt(global_l2_norm_sqr),
       /* info.iterations, */
       /* info.residual_norm, */
       time_spent
      );
  }


  
  if (ghost) {
    p4est_ghost_destroy (ghost);
    P4EST_FREE (ghost_data);
    ghost = NULL;
    ghost_data = NULL;
  }


  
  P4EST_FREE(f);
  P4EST_FREE(Au);
  P4EST_FREE(rhs);
  P4EST_FREE(u_analytic);
  P4EST_FREE(u);
}
예제 #9
0
파일: p4est_step3.c 프로젝트: 00liujj/p4est
/** Timestep the advection problem.
 *
 * Update the state, refine, repartition, and write the solution to file.
 *
 * \param [in,out] p4est the forest, whose state is updated
 * \param [in] time      the end time
 */
static void
step3_timestep (p4est_t * p4est, double time)
{
  double              t = 0.;
  double              dt = 0.;
  int                 i;
  step3_data_t       *ghost_data;
  step3_ctx_t        *ctx = (step3_ctx_t *) p4est->user_pointer;
  int                 refine_period = ctx->refine_period;
  int                 repartition_period = ctx->repartition_period;
  int                 write_period = ctx->write_period;
  int                 recursive = 0;
  int                 allowed_level = P4EST_QMAXLEVEL;
  int                 allowcoarsening = 1;
  int                 callbackorphans = 0;
  int                 mpiret;
  double              orig_max_err = ctx->max_err;
  double              umax, global_umax;
  p4est_ghost_t      *ghost;

  /* create the ghost quadrants */
  ghost = p4est_ghost_new (p4est, P4EST_CONNECT_FULL);
  /* create space for storing the ghost data */
  ghost_data = P4EST_ALLOC (step3_data_t, ghost->ghosts.elem_count);
  /* synchronize the ghost data */
  p4est_ghost_exchange_data (p4est, ghost, ghost_data);

  /* initialize du/dx estimates */
  p4est_iterate (p4est, ghost, (void *) ghost_data,     /* pass in ghost data that we just exchanged */
                 step3_reset_derivatives,       /* blank the previously calculated derivatives */
                 step3_minmod_estimate, /* compute the minmod estimate of each cell's derivative */
#ifdef P4_TO_P8
                 NULL,          /* there is no callback for the edges between quadrants */
#endif
                 NULL);         /* there is no callback for the corners between quadrants */

  for (t = 0., i = 0; t < time; t += dt, i++) {
    P4EST_GLOBAL_PRODUCTIONF ("time %f\n", t);

    /* refine */
    if (!(i % refine_period)) {
      if (i) {
        /* compute umax */
        umax = 0.;
        /* initialize derivative estimates */
        p4est_iterate (p4est, NULL, (void *) &umax,     /* pass in ghost data that we just exchanged */
                       step3_compute_max,       /* blank the previously calculated derivatives */
                       NULL,    /* there is no callback for the faces between quadrants */
#ifdef P4_TO_P8
                       NULL,    /* there is no callback for the edges between quadrants */
#endif
                       NULL);   /* there is no callback for the corners between quadrants */

        mpiret =
          sc_MPI_Allreduce (&umax, &global_umax, 1, sc_MPI_DOUBLE, sc_MPI_MAX,
                            p4est->mpicomm);
        SC_CHECK_MPI (mpiret);
        ctx->max_err = orig_max_err * global_umax;
        P4EST_GLOBAL_PRODUCTIONF ("u_max %f\n", global_umax);

        /* adapt */
        p4est_refine_ext (p4est, recursive, allowed_level,
                          step3_refine_err_estimate, NULL,
                          step3_replace_quads);
        p4est_coarsen_ext (p4est, recursive, callbackorphans,
                           step3_coarsen_err_estimate, NULL,
                           step3_replace_quads);
        p4est_balance_ext (p4est, P4EST_CONNECT_FACE, NULL,
                           step3_replace_quads);

        p4est_ghost_destroy (ghost);
        P4EST_FREE (ghost_data);
        ghost = NULL;
        ghost_data = NULL;
      }
      dt = step3_get_timestep (p4est);
    }

    /* repartition */
    if (i && !(i % repartition_period)) {
      p4est_partition (p4est, allowcoarsening, NULL);

      if (ghost) {
        p4est_ghost_destroy (ghost);
        P4EST_FREE (ghost_data);
        ghost = NULL;
        ghost_data = NULL;
      }
    }

    /* write out solution */
    if (!(i % write_period)) {
      step3_write_solution (p4est, i);
    }

    /* synchronize the ghost data */
    if (!ghost) {
      ghost = p4est_ghost_new (p4est, P4EST_CONNECT_FULL);
      ghost_data = P4EST_ALLOC (step3_data_t, ghost->ghosts.elem_count);
      p4est_ghost_exchange_data (p4est, ghost, ghost_data);
    }

    /* compute du/dt */
    /* *INDENT-OFF* */
    p4est_iterate (p4est,                 /* the forest */
                   ghost,                 /* the ghost layer */
                   (void *) ghost_data,   /* the synchronized ghost data */
                   step3_quad_divergence, /* callback to compute each quad's
                                             interior contribution to du/dt */
                   step3_upwind_flux,     /* callback to compute each quads'
                                             faces' contributions to du/du */
#ifdef P4_TO_P8
                   NULL,                  /* there is no callback for the
                                             edges between quadrants */
#endif
                   NULL);                 /* there is no callback for the
                                             corners between quadrants */
    /* *INDENT-ON* */

    /* update u */
    p4est_iterate (p4est, NULL, /* ghosts are not needed for this loop */
                   (void *) &dt,        /* pass in dt */
                   step3_timestep_update,       /* update each cell */
                   NULL,        /* there is no callback for the faces between quadrants */
#ifdef P4_TO_P8
                   NULL,        /* there is no callback for the edges between quadrants */
#endif
                   NULL);       /* there is no callback for the corners between quadrants */

    /* synchronize the ghost data */
    p4est_ghost_exchange_data (p4est, ghost, ghost_data);

    /* update du/dx estimate */
    p4est_iterate (p4est, ghost, (void *) ghost_data,   /* pass in ghost data that we just exchanged */
                   step3_reset_derivatives,     /* blank the previously calculated derivatives */
                   step3_minmod_estimate,       /* compute the minmod estimate of each cell's derivative */
#ifdef P4_TO_P8
                   NULL,        /* there is no callback for the edges between quadrants */
#endif
                   NULL);       /* there is no callback for the corners between quadrants */
  }

  P4EST_FREE (ghost_data);
  p4est_ghost_destroy (ghost);
}
예제 #10
0
int
main (int argc, char **argv)
{
  int                 rank;
  int                 num_procs;
  int                 mpiret;
  sc_MPI_Comm         mpicomm;
  p4est_t            *p4est, *copy;
  p4est_connectivity_t *connectivity;
  int                 i;
  p4est_topidx_t      t;
  size_t              qz;
  p4est_locidx_t      num_quadrants_on_last;
  p4est_locidx_t     *num_quadrants_in_proc;
  p4est_gloidx_t     *pertree1, *pertree2;
  p4est_quadrant_t   *quad;
  p4est_tree_t       *tree;
  user_data_t        *user_data;
  int64_t             sum;
  unsigned            crc;

  mpiret = sc_MPI_Init (&argc, &argv);
  SC_CHECK_MPI (mpiret);
  mpicomm = sc_MPI_COMM_WORLD;
  mpiret = sc_MPI_Comm_rank (mpicomm, &rank);
  SC_CHECK_MPI (mpiret);

  sc_init (mpicomm, 1, 1, NULL, SC_LP_DEFAULT);

  /* create connectivity and forest structures */
#ifdef P4_TO_P8
  connectivity = p8est_connectivity_new_twocubes ();
#else
  connectivity = p4est_connectivity_new_corner ();
#endif
  p4est = p4est_new_ext (mpicomm, connectivity, 15, 0, 0,
                         sizeof (user_data_t), init_fn, NULL);

  pertree1 = P4EST_ALLOC (p4est_gloidx_t, p4est->connectivity->num_trees + 1);
  pertree2 = P4EST_ALLOC (p4est_gloidx_t, p4est->connectivity->num_trees + 1);
  num_procs = p4est->mpisize;
  num_quadrants_in_proc = P4EST_ALLOC (p4est_locidx_t, num_procs);

  /* refine and balance to make the number of elements interesting */
  test_pertree (p4est, NULL, pertree1);
  p4est_refine (p4est, 1, refine_fn, init_fn);
  test_pertree (p4est, NULL, pertree1);

  /* Set an arbitrary partition.
   *
   * Since this is just a test we assume the global number of
   * quadrants will fit in an int32_t
   */
  num_quadrants_on_last = (p4est_locidx_t) p4est->global_num_quadrants;
  for (i = 0; i < num_procs - 1; ++i) {
    num_quadrants_in_proc[i] = (p4est_locidx_t) i + 1;  /* type ok */
    num_quadrants_on_last -= (p4est_locidx_t) i + 1;    /* type ok */
  }
  num_quadrants_in_proc[num_procs - 1] = num_quadrants_on_last;
  SC_CHECK_ABORT (num_quadrants_on_last > 0,
                  "Negative number of quadrants on the last processor");

  /* Save a checksum of the original forest */
  crc = p4est_checksum (p4est);

  /* partition the forest */
  (void) p4est_partition_given (p4est, num_quadrants_in_proc);
  test_pertree (p4est, pertree1, pertree2);

  /* Double check that we didn't loose any quads */
  SC_CHECK_ABORT (crc == p4est_checksum (p4est),
                  "bad checksum, missing a quad");

  /* count the actual number of quadrants per proc */
  SC_CHECK_ABORT (num_quadrants_in_proc[rank]
                  == p4est->local_num_quadrants,
                  "partition failed, wrong number of quadrants");

  /* check user data content */
  for (t = p4est->first_local_tree; t <= p4est->last_local_tree; ++t) {
    tree = p4est_tree_array_index (p4est->trees, t);
    for (qz = 0; qz < tree->quadrants.elem_count; ++qz) {
      quad = p4est_quadrant_array_index (&tree->quadrants, qz);
      user_data = (user_data_t *) quad->p.user_data;
      sum = quad->x + quad->y + quad->level;

      SC_CHECK_ABORT (user_data->a == t, "bad user_data, a");
      SC_CHECK_ABORT (user_data->sum == sum, "bad user_data, sum");
    }
  }

  /* do a weighted partition with uniform weights */
  p4est_partition (p4est, 0, weight_one);
  test_pertree (p4est, pertree1, pertree2);
  SC_CHECK_ABORT (crc == p4est_checksum (p4est),
                  "bad checksum after uniformly weighted partition");

  /* copy the p4est */
  copy = p4est_copy (p4est, 1);
  SC_CHECK_ABORT (crc == p4est_checksum (copy), "bad checksum after copy");

  /* do a weighted partition with many zero weights */
  weight_counter = 0;
  weight_index = (rank == 1) ? 1342 : 0;
  p4est_partition (copy, 0, weight_once);
  test_pertree (copy, pertree1, pertree2);
  SC_CHECK_ABORT (crc == p4est_checksum (copy),
                  "bad checksum after unevenly weighted partition 1");

  /* do a weighted partition with many zero weights */
  weight_counter = 0;
  weight_index = 0;
  p4est_partition (copy, 0, weight_once);
  test_pertree (copy, pertree1, pertree2);
  SC_CHECK_ABORT (crc == p4est_checksum (copy),
                  "bad checksum after unevenly weighted partition 2");

  /* do a weighted partition with many zero weights
   *
   * Since this is just a test we assume the local number of
   * quadrants will fit in an int
   */
  weight_counter = 0;
  weight_index =
    (rank == num_procs - 1) ? ((int) copy->local_num_quadrants - 1) : 0;
  p4est_partition (copy, 0, weight_once);
  test_pertree (copy, pertree1, pertree2);
  SC_CHECK_ABORT (crc == p4est_checksum (copy),
                  "bad checksum after unevenly weighted partition 3");

  /* check user data content */
  for (t = copy->first_local_tree; t <= copy->last_local_tree; ++t) {
    tree = p4est_tree_array_index (copy->trees, t);
    for (qz = 0; qz < tree->quadrants.elem_count; ++qz) {
      quad = p4est_quadrant_array_index (&tree->quadrants, qz);
      user_data = (user_data_t *) quad->p.user_data;
      sum = quad->x + quad->y + quad->level;

      SC_CHECK_ABORT (user_data->a == t, "bad user_data, a");
      SC_CHECK_ABORT (user_data->sum == sum, "bad user_data, sum");
    }
  }

  /* Add another test.  Overwrites pertree1, pertree2 */
  test_partition_circle (mpicomm, connectivity, pertree1, pertree2);

  /* clean up and exit */
  P4EST_FREE (pertree1);
  P4EST_FREE (pertree2);
  P4EST_FREE (num_quadrants_in_proc);
  p4est_destroy (p4est);
  p4est_destroy (copy);
  p4est_connectivity_destroy (connectivity);
  sc_finalize ();

  mpiret = sc_MPI_Finalize ();
  SC_CHECK_MPI (mpiret);

  return 0;
}
예제 #11
0
int
main (int argc, char **argv)
{
  sc_MPI_Comm         mpicomm;
  int                 mpiret;
  int                 mpirank;
  int                 first_arg;
  const char         *prefix;
  p4est_connectivity_t *connectivity;
  sc_options_t       *opt;

  /* initialize MPI */
  mpiret = sc_MPI_Init (&argc, &argv);
  SC_CHECK_MPI (mpiret);
  mpicomm = sc_MPI_COMM_WORLD;
  mpiret = sc_MPI_Comm_rank (mpicomm, &mpirank);
  SC_CHECK_MPI (mpiret);

  /* initialize libsc and p4est */
  sc_init (mpicomm, 1, 1, NULL, SC_LP_DEFAULT);
  p4est_init (NULL, SC_LP_DEFAULT);

  /* handle command line options */
  opt = sc_options_new (argv[0]);
  sc_options_add_int (opt, 'l', "level", &refine_level,
                      default_refine_level, "Refinement level");
  sc_options_add_string (opt, 'o', "oprefix", &prefix,
                         P4EST_STRING, "Output prefix");
  first_arg = sc_options_parse (p4est_package_id, SC_LP_INFO,
                                opt, argc, argv);
  SC_CHECK_ABORT (first_arg >= 0, "Option error");

  /* create connectivity */
#ifndef P4_TO_P8
  connectivity = p4est_connectivity_new_star ();
#else
  connectivity = p8est_connectivity_new_rotcubes ();
#endif

  /* test with vertex information */
  test_loadsave (connectivity, prefix, mpicomm, mpirank);

  /* test without vertex information */
  connectivity->num_vertices = 0;
  P4EST_FREE (connectivity->vertices);
  connectivity->vertices = NULL;
  P4EST_FREE (connectivity->tree_to_vertex);
  connectivity->tree_to_vertex = NULL;
  p4est_connectivity_set_attr (connectivity, 1);
  memset (connectivity->tree_to_attr, 0,
          connectivity->num_trees * sizeof (int8_t));
  test_loadsave (connectivity, prefix, mpicomm, mpirank);

  /* clean up and exit */
  p4est_connectivity_destroy (connectivity);
  sc_options_destroy (opt);
  sc_finalize ();

  mpiret = sc_MPI_Finalize ();
  SC_CHECK_MPI (mpiret);

  return 0;
}
예제 #12
0
static void
test_partition_circle (sc_MPI_Comm mpicomm,
                       p4est_connectivity_t * connectivity,
                       p4est_gloidx_t * pertree1, p4est_gloidx_t * pertree2)
{
  int                 i, j;
  int                 num_procs;
  int                 empty_proc1, empty_proc2;
  unsigned            crc1, crc2;
  p4est_gloidx_t      global_num;
  p4est_locidx_t     *new_counts;
  p4est_t            *p4est, *copy;

  /* Create a forest and make a copy */

  circle_count = 0;
  p4est = p4est_new_ext (mpicomm, connectivity, 0, 3, 1,
                         sizeof (int), circle_init, NULL);
  num_procs = p4est->mpisize;
  test_pertree (p4est, NULL, pertree1);

  global_num = p4est->global_num_quadrants;
  crc1 = p4est_checksum (p4est);
  copy = p4est_copy (p4est, 1);
  P4EST_ASSERT (p4est_checksum (copy) == crc1);

  new_counts = P4EST_ALLOC (p4est_locidx_t, num_procs);

  /* Partition with one empty processor */
  if (num_procs > 1) {
    P4EST_GLOBAL_INFO ("First circle partition\n");
    empty_proc1 = num_procs / 3;
    j = 0;
    for (i = 0; i < num_procs; ++i) {
      if (i == empty_proc1) {
        new_counts[i] = 0;
      }
      else {
        new_counts[i] =
          p4est_partition_cut_gloidx (global_num, j + 1, num_procs - 1) -
          p4est_partition_cut_gloidx (global_num, j, num_procs - 1);
        P4EST_ASSERT (new_counts[i] >= 0);
        ++j;
      }
    }
    P4EST_ASSERT (j == num_procs - 1);
    p4est_partition_given (p4est, new_counts);
    test_pertree (p4est, pertree1, pertree2);
    crc2 = p4est_checksum (p4est);
    SC_CHECK_ABORT (crc1 == crc2, "First checksum mismatch");
  }

  /* Partition with two empty processors */
  if (num_procs > 2) {
    P4EST_GLOBAL_INFO ("Second circle partition\n");
    empty_proc1 = (2 * num_procs) / 3 - 2;
    empty_proc2 = (2 * num_procs) / 3;
    j = 0;
    for (i = 0; i < num_procs; ++i) {
      if (i == empty_proc1 || i == empty_proc2) {
        new_counts[i] = 0;
      }
      else {
        new_counts[i] =
          p4est_partition_cut_gloidx (global_num, j + 1, num_procs - 2) -
          p4est_partition_cut_gloidx (global_num, j, num_procs - 2);
        P4EST_ASSERT (new_counts[i] >= 0);
        ++j;
      }
    }
    P4EST_ASSERT (j == num_procs - 2);
    p4est_partition_given (p4est, new_counts);
    test_pertree (p4est, pertree1, pertree2);
    crc2 = p4est_checksum (p4est);
    SC_CHECK_ABORT (crc1 == crc2, "Second checksum mismatch");
  }

  /* Uniform partition */
  P4EST_GLOBAL_INFO ("Third circle partition\n");
  p4est_partition (p4est, 0, NULL);
  test_pertree (p4est, pertree1, pertree2);
  crc2 = p4est_checksum (p4est);
  SC_CHECK_ABORT (crc1 == crc2, "Third checksum mismatch");
  SC_CHECK_ABORT (p4est_is_equal (p4est, copy, 1), "Forest mismatch");

  P4EST_FREE (new_counts);
  p4est_destroy (copy);
  p4est_destroy (p4est);
}
예제 #13
0
static void
mesh_iter_corner (p4est_iter_corner_info_t * info, void *user_data)
{
  int                 i, j;
  int                 f1, f2, code, orientation;
  int                 fc1, fc2, diagonal;
#ifdef P4_TO_P8
  int                 pref, pset;
#endif
  int                 visited[P4EST_CHILDREN];
  int8_t             *pccorner;
  size_t              cz, zz;
  sc_array_t         *trees;
  p4est_locidx_t      qoffset, qid1, qid2;
  p4est_locidx_t      cornerid_offset, cornerid;
  p4est_locidx_t     *pcquad;
  p4est_mesh_t       *mesh = (p4est_mesh_t *) user_data;
  p4est_iter_corner_side_t *side1, *side2;
  p4est_tree_t       *tree1, *tree2;
  p4est_connectivity_t *conn;

  /* Check the case when the corner does not involve neighbors */
  cz = info->sides.elem_count;
  P4EST_ASSERT (cz > 0);
  P4EST_ASSERT (info->tree_boundary || cz == P4EST_CHILDREN);
  if (cz == 1) {
    return;
  }
  conn = info->p4est->connectivity;
  trees = info->p4est->trees;
  cornerid_offset = mesh->local_num_quadrants + mesh->ghost_num_quadrants;

  if (info->tree_boundary == P4EST_CONNECT_FACE) {
    /* This corner is inside an inter-tree face */
    if (cz == P4EST_HALF) {
      /* This is a tree face boundary, no corner neighbors exist */
      return;
    }
    P4EST_ASSERT (cz == P4EST_CHILDREN);

    /* Process a corner in pairs of diagonal inter-tree neighbors */
    memset (visited, 0, P4EST_CHILDREN * sizeof (int));
    for (i = 0; i < P4EST_HALF; ++i) {
      side1 = side2 = NULL;
      f1 = -1;
      fc1 = -1;
      qid1 = -3;
      for (j = 0; j < P4EST_CHILDREN; ++j) {
        if (visited[j]) {
          continue;
        }

        /* Remember the first side we want to pair up */
        if (side1 == NULL) {
          side1 =
            (p4est_iter_corner_side_t *) sc_array_index_int (&info->sides, j);
          P4EST_ASSERT (side1->quad != NULL);
          f1 = tree_face_quadrant_corner_face (side1->quad, side1->corner);
          fc1 = p4est_corner_face_corners[side1->corner][f1];
          P4EST_ASSERT (0 <= fc1 && fc1 < P4EST_HALF);
          tree1 = p4est_tree_array_index (trees, side1->treeid);
          qid1 = side1->quadid + (side1->is_ghost ? mesh->local_num_quadrants
                                  : tree1->quadrants_offset);
          visited[j] = 1;
          continue;
        }

        /* Examine a potential second side */
        P4EST_ASSERT (side2 == NULL);
        side2 =
          (p4est_iter_corner_side_t *) sc_array_index_int (&info->sides, j);
        P4EST_ASSERT (side2->quad != NULL);
        f2 = tree_face_quadrant_corner_face (side2->quad, side2->corner);
        if (side1->treeid == side2->treeid && f1 == f2) {
          /* Periodicity allows for equal trees and unequal faces */
          side2 = NULL;
          continue;
        }

        /* This side as in the opposite tree */
        fc2 = p4est_corner_face_corners[side2->corner][f2];
        P4EST_ASSERT (0 <= fc2 && fc2 < P4EST_HALF);
        code = conn->tree_to_face[P4EST_FACES * side1->treeid + f1];
        orientation = code / P4EST_FACES;
        P4EST_ASSERT (f2 == code % P4EST_FACES);
#ifdef P4_TO_P8
        pref = p8est_face_permutation_refs[f1][f2];
        pset = p8est_face_permutation_sets[pref][orientation];
        diagonal = (p8est_face_permutations[pset][fc1] ^ fc2) == 3;
#else
        diagonal = (fc1 ^ fc2) != orientation;
#endif
        if (!diagonal) {
          side2 = NULL;
          continue;
        }

        /* We have found a diagonally opposite second side */
        tree2 = p4est_tree_array_index (trees, side2->treeid);
        qid2 = side2->quadid + (side2->is_ghost ? mesh->local_num_quadrants
                                : tree2->quadrants_offset);
        if (!side1->is_ghost) {
          P4EST_ASSERT (0 <= qid1 && qid1 < mesh->local_num_quadrants);
          P4EST_ASSERT (mesh->quad_to_corner[P4EST_CHILDREN * qid1 +
                                             side1->corner] == -1);
          cornerid = mesh_corner_allocate (mesh, 1, &pcquad, &pccorner);
          mesh->quad_to_corner[P4EST_CHILDREN * qid1 + side1->corner] =
            cornerid_offset + cornerid;
          *pcquad = qid2;
          *pccorner = side2->corner;
        }
        if (!side2->is_ghost) {
          P4EST_ASSERT (0 <= qid2 && qid2 < mesh->local_num_quadrants);
          P4EST_ASSERT (mesh->quad_to_corner[P4EST_CHILDREN * qid2 +
                                             side2->corner] == -1);
          cornerid = mesh_corner_allocate (mesh, 1, &pcquad, &pccorner);
          mesh->quad_to_corner[P4EST_CHILDREN * qid2 + side2->corner] =
            cornerid_offset + cornerid;
          *pcquad = qid1;
          *pccorner = side1->corner;
        }
        visited[j] = 1;
        break;
      }
      P4EST_ASSERT (side1 != NULL && side2 != NULL);
    }
    return;
  }

#ifdef P4_TO_P8
  if (info->tree_boundary == P8EST_CONNECT_EDGE) {
    /* Tree corner neighbors across an edge are not implemented: set to -2 */
    for (zz = 0; zz < cz; ++zz) {
      side1 = (p4est_iter_corner_side_t *) sc_array_index (&info->sides, zz);
      if (!side1->is_ghost) {
        tree1 = p4est_tree_array_index (trees, side1->treeid);
        qid1 = side1->quadid + tree1->quadrants_offset;
        P4EST_ASSERT (0 <= qid1 && qid1 < mesh->local_num_quadrants);
        P4EST_ASSERT (mesh->quad_to_corner[P4EST_CHILDREN * qid1 +
                                           side1->corner] == -1);
        mesh->quad_to_corner[P4EST_CHILDREN * qid1 + side1->corner] = -2;
      }
    }
    return;
  }
#endif

  if (info->tree_boundary == P4EST_CONNECT_CORNER) {
    int                 c1, ncorner[P4EST_DIM];
    int                 nface[P4EST_DIM];
    int                 ignore;
    size_t              z2;
    int8_t             *ccorners;
    p4est_topidx_t      t1, ntree[P4EST_DIM];
    p4est_locidx_t      goodones;
    p4est_locidx_t     *cquads;

    /* Loop through all corner sides, that is the quadrants touching it.  For
     * each of these quadrants, determine the corner sides that can potentially
     * occur by being a face neighbor as well.  Exclude these face neighbors
     * and the quadrant itself, record all others as corner neighbors.
     */
    cquads = P4EST_ALLOC (p4est_locidx_t, cz - 1);
    ccorners = P4EST_ALLOC (int8_t, cz - 1);
    for (zz = 0; zz < cz; ++zz) {
      side1 = (p4est_iter_corner_side_t *) sc_array_index (&info->sides, zz);
      if (!side1->is_ghost) {
        /* We only create corner information for processor-local quadrants */
        t1 = side1->treeid;
        c1 = (int) side1->corner;
        tree1 = p4est_tree_array_index (trees, t1);
        qid1 = side1->quadid + tree1->quadrants_offset;
        P4EST_ASSERT (0 <= qid1 && qid1 < mesh->local_num_quadrants);
        P4EST_ASSERT (mesh->quad_to_corner[P4EST_CHILDREN * qid1 + c1] == -1);

        /* Check all quadrant faces that touch this corner */
        for (i = 0; i < P4EST_DIM; ++i) {
          f1 = p4est_corner_faces[c1][i];
          ntree[i] = conn->tree_to_tree[P4EST_FACES * t1 + f1];
          nface[i] = conn->tree_to_face[P4EST_FACES * t1 + f1];
          if (ntree[i] == t1 && nface[i] == f1) {
            /* This is a physical face boundary, no face neighbor present */
            ncorner[i] = -1;
            continue;
          }
          /* We have a face neighbor */
          orientation = nface[i] / P4EST_FACES;
          nface[i] %= P4EST_FACES;
          ncorner[i] = p4est_connectivity_face_neighbor_corner
            (c1, f1, nface[i], orientation);
        }

        /* Go through corner neighbors and collect the true corners */
        goodones = 0;
        for (z2 = 0; z2 < cz; ++z2) {
          if (z2 == zz) {
            /* We do not count ourselves as a neighbor */
            continue;
          }
          ignore = 0;
          side2 =
            (p4est_iter_corner_side_t *) sc_array_index (&info->sides, z2);
          P4EST_ASSERT (side2->corner >= 0);
          for (i = 0; i < P4EST_DIM; ++i) {
            /* Ignore if this is one of the face neighbors' corners */
            if (ncorner[i] == (int) side2->corner &&
                ntree[i] == side2->treeid) {
              ignore = 1;
              break;
            }
          }
          if (ignore) {
            continue;
          }

          /* Record this corner neighbor */
          tree2 = p4est_tree_array_index (trees, side2->treeid);
          qid2 = side2->quadid + (side2->is_ghost ? mesh->local_num_quadrants
                                  : tree2->quadrants_offset);
          cquads[goodones] = qid2;
          ccorners[goodones] = (int) side2->corner;
          ++goodones;
        }
        P4EST_ASSERT ((size_t) goodones < cz);
        if (goodones == 0) {
          continue;
        }

        /* Allocate and fill corner information in the mesh structure */
        cornerid = mesh_corner_allocate (mesh, goodones, &pcquad, &pccorner);
        mesh->quad_to_corner[P4EST_CHILDREN * qid1 + c1] =
          cornerid_offset + cornerid;
        memcpy (pcquad, cquads, goodones * sizeof (p4est_locidx_t));
        memcpy (pccorner, ccorners, goodones * sizeof (int8_t));
      }
    }
    P4EST_FREE (cquads);
    P4EST_FREE (ccorners);
    return;
  }

  /* Process a corner inside the tree in pairs of diagonal neighbors */
  P4EST_ASSERT (!info->tree_boundary);
  side1 = (p4est_iter_corner_side_t *) sc_array_index (&info->sides, 0);
  tree1 = p4est_tree_array_index (trees, side1->treeid);
  qoffset = tree1->quadrants_offset;
  memset (visited, 0, P4EST_CHILDREN * sizeof (int));
  for (i = 0; i < P4EST_HALF; ++i) {
    side1 = side2 = NULL;
    qid1 = -3;
    for (j = 0; j < P4EST_CHILDREN; ++j) {
      if (visited[j]) {
        continue;
      }

      /* Remember the first side we want to pair up */
      if (side1 == NULL) {
        side1 =
          (p4est_iter_corner_side_t *) sc_array_index_int (&info->sides, j);
        qid1 = side1->quadid +
          (side1->is_ghost ? mesh->local_num_quadrants : qoffset);
        visited[j] = 1;
        continue;
      }

      /* Examine a potential second side */
      P4EST_ASSERT (side2 == NULL);
      side2 =
        (p4est_iter_corner_side_t *) sc_array_index_int (&info->sides, j);
      P4EST_ASSERT (side1->treeid == side2->treeid);
      if (side1->corner + side2->corner != P4EST_CHILDREN - 1) {
        side2 = NULL;
        continue;
      }

      /* We have found a diagonally opposite second side */
      qid2 = side2->quadid +
        (side2->is_ghost ? mesh->local_num_quadrants : qoffset);
      if (!side1->is_ghost) {
        P4EST_ASSERT (0 <= qid1 && qid1 < mesh->local_num_quadrants);
        P4EST_ASSERT (mesh->quad_to_corner[P4EST_CHILDREN * qid1 +
                                           side1->corner] == -1);
        mesh->quad_to_corner[P4EST_CHILDREN * qid1 + side1->corner] = qid2;
      }
      if (!side2->is_ghost) {
        P4EST_ASSERT (0 <= qid2 && qid2 < mesh->local_num_quadrants);
        P4EST_ASSERT (mesh->quad_to_corner[P4EST_CHILDREN * qid2 +
                                           side2->corner] == -1);
        mesh->quad_to_corner[P4EST_CHILDREN * qid2 + side2->corner] = qid1;
      }
      visited[j] = 1;
      break;
    }
    P4EST_ASSERT (side1 != NULL && side2 != NULL);
  }
}
static void
curved_sipg_weak_flux_scalar_dirichlet
(
 curved_element_data_t* e_m,
 int f_m,
 grid_fcn_t bndry_fcn,
 dgmath_jit_dbase_t* dgmath_jit_dbase,
 p4est_geometry_t* geom,
 void* params
)
{
  grid_fcn_t u_at_bndry = bndry_fcn;
  /* int vol_nodes_m = dgmath_get_nodes( (P4EST_DIM), e_m->deg); */
  int face_nodes_m = dgmath_get_nodes( (P4EST_DIM) - 1, e_m->deg);

  double* xyz_on_f_m [(P4EST_DIM)];
  double* n_on_f_m [(P4EST_DIM)];
  double* u_m_on_f_m = P4EST_ALLOC(double, face_nodes_m);
  double* sj_on_f_m = P4EST_ALLOC(double, face_nodes_m);
  double* ustar_min_u_on_f_m = P4EST_ALLOC(double, face_nodes_m);
  double* sj_n_ustar_min_u_on_f_m = P4EST_ALLOC(double, face_nodes_m);

  for (int i = 0; i < (P4EST_DIM); i++) {
    xyz_on_f_m[i] = P4EST_ALLOC(double, face_nodes_m);    
    n_on_f_m[i] = P4EST_ALLOC(double, face_nodes_m);    
  }
 
  dgmath_apply_slicer(dgmath_jit_dbase, e_m->u_elem, (P4EST_DIM), f_m, e_m->deg, u_m_on_f_m);
  
  for (int d = 0; d < (P4EST_DIM); d++){
    dgmath_apply_slicer
      (
       dgmath_jit_dbase,
       e_m->xyz[d],
       (P4EST_DIM),
       f_m,
       e_m->deg,
       xyz_on_f_m[d]
      );
  }
  
  curved_element_data_compute_mortar_normal_and_sj_using_face_data
    (
     &e_m,
     1,
     1,
     &e_m->deg,
     f_m,
     n_on_f_m,
     sj_on_f_m,
     geom,
     dgmath_jit_dbase
    );  
  

  for (int i = 0; i < face_nodes_m; i++){
    ustar_min_u_on_f_m[i] = u_at_bndry(xyz_on_f_m[0][i],
                                       xyz_on_f_m[1][i]
#if (P4EST_DIM)==3
                                       ,
                                       xyz_on_f_m[2][i]
#endif                          
                                      );
  }
  
  for (int d = 0; d < (P4EST_DIM); d++){
    for (int i = 0; i < face_nodes_m; i++){
        sj_n_ustar_min_u_on_f_m[i] = sj_on_f_m[i]
                                     *n_on_f_m[d][i]
                                     *ustar_min_u_on_f_m[i];
    }
    dgmath_apply_Mij
      (
       dgmath_jit_dbase,
       sj_n_ustar_min_u_on_f_m,
       (P4EST_DIM) - 1,
       e_m->deg,
       &e_m->M_ustar_min_u_n[d][f_m*face_nodes_m]
        );
  }
  
  for (int dir = 0; dir < (P4EST_DIM); dir++){
    P4EST_FREE(xyz_on_f_m[dir]);
    P4EST_FREE(n_on_f_m[dir]);
  }
  
  P4EST_FREE(u_m_on_f_m);
  P4EST_FREE(sj_n_ustar_min_u_on_f_m);
  P4EST_FREE(ustar_min_u_on_f_m);
  P4EST_FREE(sj_on_f_m);
}
예제 #15
0
END_TEST


START_TEST(test_surface_plot)
{
  int test_check = 1;
  int startlevel = 0;
  int endlevel = 2;
  int degree = 3;
  int level;

  p4est_reset_data(global_p4est_pointer, sizeof(element_data_t), NULL, NULL);  
  element_data_init(global_p4est_pointer,degree);
  
  for (level = startlevel; level < endlevel; ++level){
    /* p4est_refine(global_p4est_pointer, 0, refine_h, NULL); */
    p4est_refine_ext(global_p4est_pointer, 0, -1, refine_uni, NULL, NULL);
  }
  p4est_balance_ext (global_p4est_pointer, P4EST_CONNECT_FACE, NULL, NULL);
  
  element_data_init(global_p4est_pointer,degree);
  /* element_data_print(global_p4est_pointer); */

  p4est_t* p4est = global_p4est_pointer;
  
  int local_nodes = element_data_get_local_nodes(global_p4est_pointer);
  double* u = P4EST_ALLOC(double, local_nodes);
  element_data_init_node_vec(p4est, u, sin_wave);

  double* xyz [(P4EST_DIM)];

  int i;
  for (i = 0; i < (P4EST_DIM); i++)
    xyz[i] = P4EST_ALLOC(double, local_nodes);

  element_data_get_xyz(p4est, xyz);

  plot_data x_data;
  x_data.N = local_nodes;
  x_data.data = xyz[0];
  plot_data y_data;
  y_data.N = local_nodes;
  y_data.data = xyz[1];
  plot_data z_data;
  z_data.N = local_nodes;
  z_data.data = u;

  plot_features features_surface;
  features_surface.saveas = "test_plot_surface.png";
  features_surface.save = 1;

  plot_features features_contour;
  features_contour.saveas = "test_plot_contour.png";
  features_contour.save = 1;

  /* matplotlib_wrapper_init(); */
  matplotlib_wrapper_surfaceplot(&x_data,&y_data,&z_data,NULL,&features_surface);
  matplotlib_wrapper_contourplot(&x_data,&y_data,&z_data,NULL,&features_contour);
  matplotlib_wrapper_exit();
  
  for (i = 0; i < (P4EST_DIM); i++)
    P4EST_FREE(xyz[i]);
  P4EST_FREE(u);
  ck_assert_int_eq(test_check,1);
}
예제 #16
0
파일: p6est_lnodes.c 프로젝트: tamiko/p4est
p6est_lnodes_t     *
p6est_lnodes_new (p6est_t * p6est, p6est_ghost_t * ghost, int degree)
{
  p6est_lnodes_t     *lnodes;
  p6est_profile_t    *profile;
  p4est_lnodes_t     *clnodes;
  int                 nperelem = (degree + 1) * (degree + 1) * (degree + 1);
  /* int nperface = (degree - 1) * (degree - 1); */
  /* int nperedge = (degree - 1); */
  p4est_locidx_t      ncid, cid, enid, *en;
  p4est_locidx_t      nnodecols;
  p4est_locidx_t      nelemcols;
  p4est_locidx_t      nll;
  p4est_locidx_t      nlayers;
  p4est_locidx_t     *layernodecount;
  p4est_locidx_t     *layernodeoffsets;
  p4est_locidx_t (*lr)[2];
  p4est_locidx_t      ncolnodes;
  p4est_locidx_t     *global_owned_count;
  p4est_locidx_t      num_owned, num_local;
  p4est_gloidx_t      gnum_owned, offset;
  p4est_gloidx_t     *owned_offsets;
  int                 i, j, k;
  int                 mpisize = p6est->mpisize;
  int                 mpiret;
  sc_array_t          lnoview;
  size_t              zz, nsharers;
  int                 Nrp = degree + 1;

  if (degree == 1) {
    p4est_locidx_t      eid, nid, enid2, nid2;
    p4est_locidx_t     *newnum, newlocal, newowned;

    P4EST_GLOBAL_PRODUCTION ("Into adapt p6est_lnodes_new for degree = 1\n");
    p4est_log_indent_push ();
    /* adapt 2 to 1 */

    lnodes = p6est_lnodes_new (p6est, ghost, 2);
    nll = p6est->layers->elem_count;
    num_local = lnodes->num_local_nodes;
    num_owned = lnodes->owned_count;

    en = lnodes->element_nodes;

    newnum = P4EST_ALLOC (p4est_locidx_t, P8EST_INSUL * nll);
    memset (newnum, -1, P8EST_INSUL * nll * sizeof (p4est_locidx_t));

    for (enid = 0, eid = 0; eid < nll; eid++) {
      for (k = 0; k < 3; k++) {
        for (j = 0; j < 3; j++) {
          for (i = 0; i < 3; i++, enid++) {
            if (k != 1 && j != 1 && i != 1) {
              newnum[en[enid]] = 0;
            }
          }
        }
      }
    }

    newlocal = 0;
    newowned = 0;
    for (nid = 0; nid < num_local; nid++) {
      if (newnum[nid] >= 0) {
        newnum[nid] = newlocal++;
        if (nid < num_owned) {
          newowned++;
        }
      }
    }

    /* compress en */
    enid2 = 0;
    for (enid = 0, eid = 0; eid < nll; eid++) {
      for (k = 0; k < 3; k++) {
        for (j = 0; j < 3; j++) {
          for (i = 0; i < 3; i++, enid++) {
            if (k != 1 && j != 1 && i != 1) {
              en[enid2++] = newnum[en[enid]];
            }
          }
        }
      }
    }
    P4EST_ASSERT (enid2 == P8EST_CHILDREN * nll);
    lnodes->element_nodes =
      P4EST_REALLOC (en, p4est_locidx_t, P8EST_CHILDREN * nll);

    owned_offsets = P4EST_ALLOC (p4est_gloidx_t, mpisize + 1);

    mpiret = sc_MPI_Allgather (&newowned, 1, P4EST_MPI_LOCIDX,
                               lnodes->global_owned_count, 1,
                               P4EST_MPI_LOCIDX, p6est->mpicomm);

    owned_offsets[0] = 0;
    for (i = 0; i < mpisize; i++) {
      owned_offsets[i + 1] = owned_offsets[i] + lnodes->global_owned_count[i];
    }
    lnodes->global_offset = owned_offsets[p6est->mpirank];
    lnodes->num_local_nodes = newlocal;
    lnodes->owned_count = newowned;
    lnodes->degree = 1;
    lnodes->vnodes = P8EST_CHILDREN;

    lnodes->nonlocal_nodes =
      P4EST_REALLOC (lnodes->nonlocal_nodes, p4est_gloidx_t,
                     newlocal - newowned);

    nsharers = lnodes->sharers->elem_count;
    for (zz = 0; zz < nsharers; zz++) {
      size_t              nshared, zy, zw;
      p6est_lnodes_rank_t *rank = p6est_lnodes_rank_array_index
        (lnodes->sharers, zz);

      if (rank->owned_count) {
        if (rank->rank != p6est->mpirank) {
          p4est_locidx_t      newrankowned = 0;
          p4est_locidx_t      newrankoffset = -1;

          for (nid = rank->owned_offset; nid < rank->owned_offset +
               rank->owned_count; nid++) {
            if (newnum[nid] >= 0) {
              lnodes->nonlocal_nodes[newnum[nid] - newowned] =
                owned_offsets[rank->rank];
              newrankowned++;
              if (newrankoffset < 0) {
                newrankoffset = newnum[nid];
              }
            }
          }
          rank->owned_offset = newrankoffset;
          rank->owned_count = newrankowned;
        }
        else {
          rank->owned_offset = 0;
          rank->owned_count = newowned;
        }
      }
      rank->shared_mine_count = 0;
      rank->shared_mine_offset = -1;
      zw = 0;
      nshared = rank->shared_nodes.elem_count;
      for (zy = 0; zy < nshared; zy++) {

        nid = *((p4est_locidx_t *) sc_array_index (&rank->shared_nodes, zy));
        if (newnum[nid] >= 0) {
          p4est_locidx_t     *lp;

          lp = (p4est_locidx_t *) sc_array_index (&rank->shared_nodes, zw++);
          *lp = newnum[nid];
          if (newnum[nid] < newowned) {
            rank->shared_mine_count++;
            if (rank->shared_mine_offset == -1) {
              rank->shared_mine_offset = zw - 1;
            }
          }
        }
      }
      sc_array_resize (&rank->shared_nodes, zw);
    }

    /* send local numbers to others */
    {
      sc_array_t          view;

      sc_array_init_data (&view, newnum, sizeof (p4est_locidx_t), newlocal);

      p6est_lnodes_share_owned (&view, lnodes);
    }

    nid2 = 0;
    for (nid = num_owned; nid < num_local; nid++) {
      if (newnum[nid] >= 0) {
        lnodes->nonlocal_nodes[nid2++] += (p4est_gloidx_t) newnum[nid];
      }
    }
    P4EST_ASSERT (nid2 == newlocal - newowned);

    P4EST_FREE (owned_offsets);
    P4EST_FREE (newnum);

    p4est_log_indent_pop ();
    P4EST_GLOBAL_PRODUCTION ("Done adapt p6est_lnodes_new for degree = 1\n");

    return lnodes;
  }

  P4EST_GLOBAL_PRODUCTION ("Into p6est_lnodes_new\n");
  p4est_log_indent_push ();

  P4EST_ASSERT (degree >= 1);

  lnodes = P4EST_ALLOC (p6est_lnodes_t, 1);

  /* first get the profile */
  profile = p6est_profile_new_local (p6est, ghost, P6EST_PROFILE_INTERSECTION,
                                     P8EST_CONNECT_FULL, degree);
  p6est_profile_sync (profile);

  lr = (p4est_locidx_t (*)[2]) profile->lnode_ranges;

  clnodes = profile->lnodes;

  nnodecols = clnodes->num_local_nodes;
  nelemcols = clnodes->num_local_elements;
  en = clnodes->element_nodes;
  layernodecount = P4EST_ALLOC_ZERO (p4est_locidx_t, nnodecols);
  layernodeoffsets = P4EST_ALLOC_ZERO (p4est_locidx_t, nnodecols + 1);
  for (cid = 0, enid = 0; cid < nelemcols; cid++) {
    for (j = 0; j < Nrp; j++) {
      for (i = 0; i < Nrp; i++, enid++) {
        ncid = en[enid];
        nlayers = lr[ncid][1];
        P4EST_ASSERT (nlayers);
        ncolnodes = nlayers * degree + 1;
        layernodecount[ncid] = ncolnodes;
      }
    }
  }

  num_owned = 0;
  num_local = 0;
  for (ncid = 0; ncid < nnodecols; ncid++) {
    num_local += layernodecount[ncid];
    if (ncid < clnodes->owned_count) {
      num_owned += layernodecount[ncid];
    }
  }

  P4EST_VERBOSEF ("p6est_lnodes: %d owned %d local\n", num_owned, num_local);

  if (nnodecols) {
    layernodeoffsets[0] = 0;
    for (ncid = 0; ncid < nnodecols; ncid++) {
      layernodeoffsets[ncid + 1] = layernodeoffsets[ncid] +
        layernodecount[ncid];
    }
  }

  gnum_owned = num_owned;

  owned_offsets = P4EST_ALLOC (p4est_gloidx_t, mpisize + 1);
  global_owned_count = P4EST_ALLOC (p4est_locidx_t, mpisize);

  mpiret = sc_MPI_Allgather (&gnum_owned, 1, P4EST_MPI_GLOIDX,
                             owned_offsets, 1, P4EST_MPI_GLOIDX,
                             p6est->mpicomm);
  SC_CHECK_MPI (mpiret);

  offset = 0;
  for (i = 0; i < mpisize; i++) {
    global_owned_count[i] = (p4est_locidx_t) owned_offsets[i];
    gnum_owned = owned_offsets[i];
    owned_offsets[i] = offset;
    offset += gnum_owned;
  }
  owned_offsets[mpisize] = offset;

  nll = p6est->layers->elem_count;
  nsharers = clnodes->sharers->elem_count;

  lnodes->mpicomm = p6est->mpicomm;
  lnodes->num_local_nodes = num_local;
  lnodes->owned_count = num_owned;
  lnodes->global_offset = owned_offsets[p6est->mpirank];
  lnodes->nonlocal_nodes =
    P4EST_ALLOC (p4est_gloidx_t, num_local - num_owned);
  lnodes->sharers =
    sc_array_new_size (sizeof (p6est_lnodes_rank_t), nsharers);
  lnodes->global_owned_count = global_owned_count;

  lnodes->degree = degree;
  lnodes->vnodes = nperelem;
  lnodes->num_local_elements = nll;
  lnodes->face_code = P4EST_ALLOC (p6est_lnodes_code_t, nll);
  lnodes->element_nodes = P4EST_ALLOC (p4est_locidx_t, nperelem * nll);

  p6est_profile_element_to_node (p6est, profile, layernodeoffsets,
                                 lnodes->element_nodes, lnodes->face_code);

  for (zz = 0; zz < nsharers; zz++) {
    p4est_lnodes_rank_t *crank = p4est_lnodes_rank_array_index
      (clnodes->sharers, zz);
    p6est_lnodes_rank_t *rank = p6est_lnodes_rank_array_index
      (lnodes->sharers, zz);
    size_t              zy;
    size_t              nshared;

    rank->rank = crank->rank;
    sc_array_init (&rank->shared_nodes, sizeof (p4est_locidx_t));
    nshared = crank->shared_nodes.elem_count;

    rank->owned_offset = -1;
    rank->owned_count = 0;
    rank->shared_mine_count = 0;
    rank->shared_mine_offset = -1;
    for (zy = 0; zy < nshared; zy++) {
      p4est_locidx_t      cnid =
        *((p4est_locidx_t *) sc_array_index (&crank->shared_nodes, zy));
      p4est_locidx_t     *lp;
      p4est_locidx_t      nthis, il;
      p4est_locidx_t      old_count = rank->shared_nodes.elem_count;

      nthis = layernodecount[cnid];
      lp =
        (p4est_locidx_t *) sc_array_push_count (&rank->shared_nodes, nthis);

      for (il = 0; il < nthis; il++) {
        lp[il] = layernodeoffsets[cnid] + il;
        if (zy >= (size_t) crank->shared_mine_offset
            && (p4est_locidx_t) zy - crank->shared_mine_offset <
            crank->shared_mine_count) {
          rank->shared_mine_count++;
          if (rank->shared_mine_offset == -1) {
            rank->shared_mine_offset = old_count + il;
          }
        }
        if (cnid >= crank->owned_offset
            && cnid - crank->owned_offset < crank->owned_count) {
          rank->owned_count++;
          if (rank->owned_offset == -1) {
            rank->owned_offset = lp[il];
          }
        }
      }
    }
    if (rank->rank == p6est->mpirank) {
      rank->owned_offset = 0;
      rank->owned_count = num_owned;
    }
  }

  memcpy (layernodecount, layernodeoffsets,
          nnodecols * sizeof (p4est_locidx_t));
  sc_array_init_data (&lnoview, layernodecount, sizeof (p4est_locidx_t),
                      (size_t) nnodecols);

  p4est_lnodes_share_owned (&lnoview, clnodes);

  for (zz = 0; zz < nsharers; zz++) {
    p4est_lnodes_rank_t *crank = p4est_lnodes_rank_array_index
      (clnodes->sharers, zz);

    if (crank->rank == p6est->mpirank) {
      continue;
    }

    for (ncid = crank->owned_offset;
         ncid < crank->owned_offset + crank->owned_count; ncid++) {
      p4est_gloidx_t      owners_offset;
      p4est_locidx_t      nid;

      P4EST_ASSERT (ncid >= clnodes->owned_count);
      owners_offset = owned_offsets[crank->rank] + layernodecount[ncid];
      for (nid = layernodeoffsets[ncid]; nid < layernodeoffsets[ncid + 1];
           nid++) {
        P4EST_ASSERT (nid >= num_owned);
        P4EST_ASSERT (nid < num_local);
        lnodes->nonlocal_nodes[nid - num_owned] = owners_offset++;
      }
    }
  }

  p6est_profile_destroy (profile);

  P4EST_FREE (owned_offsets);
  P4EST_FREE (layernodecount);
  P4EST_FREE (layernodeoffsets);

  p4est_log_indent_pop ();
  P4EST_GLOBAL_PRODUCTION ("Done p6est_lnodes_new\n");

  return lnodes;
}
예제 #17
0
int
p4est_wrap_adapt (p4est_wrap_t * pp)
{
  int                 changed;
#ifdef P4EST_ENABLE_DEBUG
  p4est_locidx_t      jl, local_num;
#endif
  p4est_gloidx_t      global_num;
  p4est_t            *p4est = pp->p4est;

  P4EST_ASSERT (!pp->hollow);
  P4EST_ASSERT (pp->coarsen_delay >= 0);

  P4EST_ASSERT (pp->mesh != NULL);
  P4EST_ASSERT (pp->ghost != NULL);
  P4EST_ASSERT (pp->mesh_aux == NULL);
  P4EST_ASSERT (pp->ghost_aux == NULL);
  P4EST_ASSERT (pp->match_aux == 0);

  P4EST_ASSERT (pp->temp_flags == NULL);
  P4EST_ASSERT (pp->num_refine_flags >= 0 &&
                pp->num_refine_flags <= p4est->local_num_quadrants);

  /* This allocation is optimistic when not all refine requests are honored */
  pp->temp_flags = P4EST_ALLOC_ZERO (uint8_t, p4est->local_num_quadrants +
                                     (P4EST_CHILDREN - 1) *
                                     pp->num_refine_flags);

  /* Execute refinement */
  pp->inside_counter = pp->num_replaced = 0;
#ifdef P4EST_ENABLE_DEBUG
  local_num = p4est->local_num_quadrants;
#endif
  global_num = p4est->global_num_quadrants;
  p4est_refine_ext (p4est, 0, -1, refine_callback, NULL, replace_on_refine);
  P4EST_ASSERT (pp->inside_counter == local_num);
  P4EST_ASSERT (p4est->local_num_quadrants - local_num ==
                pp->num_replaced * (P4EST_CHILDREN - 1));
  changed = global_num != p4est->global_num_quadrants;

  /* Execute coarsening */
  pp->inside_counter = pp->num_replaced = 0;
#ifdef P4EST_ENABLE_DEBUG
  local_num = p4est->local_num_quadrants;
#endif
  global_num = p4est->global_num_quadrants;
  p4est_coarsen_ext (p4est, 0, 1, coarsen_callback, NULL,
                     pp->coarsen_delay ? replace_on_coarsen : pp->replace_fn);
  P4EST_ASSERT (pp->inside_counter == local_num);
  P4EST_ASSERT (local_num - p4est->local_num_quadrants ==
                pp->num_replaced * (P4EST_CHILDREN - 1));
  changed = changed || global_num != p4est->global_num_quadrants;

  /* Free temporary flags */
  P4EST_FREE (pp->temp_flags);
  pp->temp_flags = NULL;

  /* Only if refinement and/or coarsening happened do we need to balance */
  if (changed) {
    P4EST_FREE (pp->flags);
    p4est_balance_ext (p4est, pp->btype, NULL, pp->coarsen_delay ?
                       replace_on_balance : pp->replace_fn);
    pp->flags = P4EST_ALLOC_ZERO (uint8_t, p4est->local_num_quadrants);

    pp->ghost_aux = p4est_ghost_new (p4est, pp->btype);
    pp->mesh_aux = p4est_mesh_new_ext (p4est, pp->ghost_aux, 1, 1, pp->btype);
    pp->match_aux = 1;
  }
#ifdef P4EST_ENABLE_DEBUG
  else {
    for (jl = 0; jl < p4est->local_num_quadrants; ++jl) {
      P4EST_ASSERT (pp->flags[jl] == 0);
    }
  }
#endif
  pp->num_refine_flags = 0;

  return changed;
}
예제 #18
0
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]);
    }

  }
static void
sipg_flux_vector_interface
(
 element_data_t** e_m,
 int faces_m,
 int f_m,
 element_data_t** e_p,
 int faces_p,
 int f_p,
 int* e_m_is_ghost,
 dgmath_jit_dbase_t* dgmath_jit_dbase,
 void* params
)
{
  ip_flux_params_t* ip_params = (ip_flux_params_t*) params;
  double sipg_flux_penalty_prefactor = ip_params->ip_flux_penalty_prefactor;
  penalty_calc_t sipg_flux_penalty_calculate_fcn = ip_params->ip_flux_penalty_calculate_fcn;
  
  int stride;
  int deg_p [(P4EST_HALF)];
  int max_deg_p = -1;
  int face_nodes_p [(P4EST_HALF)];
  int deg_m [(P4EST_HALF)];
  int face_nodes_m [(P4EST_HALF)];
  int max_deg_m = -1;
  int nodes_mortar [(P4EST_HALF)];

  double penalty_mortar [(P4EST_HALF)];
  int deg_mortar [(P4EST_HALF)];
  int faces_mortar = (faces_m > faces_p) ? faces_m : faces_p;

  double n [(P4EST_DIM)];
  dgmath_get_normal(f_m, (P4EST_DIM), &n[0]);
  
  int i,j;
  
  /* calculate degs and nodes of each face of (-) side */
  int total_side_nodes_m = 0;
  for (i = 0; i < faces_m; i++){
    deg_m[i] = e_m[i]->deg;
    if (e_m[i]->deg > max_deg_m) max_deg_m = e_m[i]->deg;
    face_nodes_m[i] = dgmath_get_nodes( (P4EST_DIM) - 1, e_m[i]->deg );
    total_side_nodes_m += face_nodes_m[i];
  }

  /* calculate degs and nodes of each face of (+) side  */
  int total_side_nodes_p = 0;
  for (i = 0; i < faces_p; i++){
    deg_p[i] = e_p[i]->deg;
    if (e_p[i]->deg > max_deg_p) max_deg_p = e_p[i]->deg;
    face_nodes_p[i] = dgmath_get_nodes( (P4EST_DIM) - 1, e_p[i]->deg );
    total_side_nodes_p += face_nodes_p[i];
  }    

  /* calculate degs and nodes of the mortar faces */
  int total_nodes_mortar = 0;
  for (i = 0; i < faces_m; i++)
    for (j = 0; j < faces_p; j++){
      /* find max degree for each face pair of the two sides*/
      deg_mortar[i+j] = util_max_int( e_m[i]->deg, e_p[j]->deg );

      /* find IP penalty parameter for each face pair of the two sides*/

      penalty_mortar[i+j] = sipg_flux_penalty_calculate_fcn
                            (
                             e_m[i]->deg,
                             e_m[i]->h,
                             e_p[j]->deg,
                             e_p[j]->h,
                             sipg_flux_penalty_prefactor
                            );

      /* printf("penalty_mortar[%d] = %f\n", i+j, penalty_mortar[i+j]); */
      nodes_mortar[i+j] = dgmath_get_nodes( (P4EST_DIM) - 1, deg_mortar[i+j] );
      
      total_nodes_mortar += nodes_mortar[i+j];
    }

  /* scalar and vector fields on each of the (-) and (+) elements */
  double* du_m = P4EST_ALLOC(double, dgmath_get_nodes((P4EST_DIM), max_deg_m));
  double* du_p = P4EST_ALLOC(double, dgmath_get_nodes((P4EST_DIM), max_deg_p));
  /* slices of scalar/vector fields of (-) onto f_m and (+) onto f_p */
  double* u_m_on_f_m = P4EST_ALLOC(double, total_side_nodes_m);
  double* du_m_on_f_m = P4EST_ALLOC(double, total_side_nodes_m); 
  double* q_m_on_f_m = P4EST_ALLOC(double, total_side_nodes_m);
  double* du_p_on_f_p = P4EST_ALLOC(double, total_side_nodes_p);
  double* u_p_on_f_p = P4EST_ALLOC(double, total_side_nodes_p);
  /* projections of f_m slices to max_deg space */
  double* u_m_on_f_m_mortar = P4EST_ALLOC(double, total_nodes_mortar);
  double* du_m_on_f_m_mortar= P4EST_ALLOC(double, total_nodes_mortar); 
  double* q_m_on_f_m_mortar= P4EST_ALLOC(double, total_nodes_mortar);  
  double* du_p_on_f_p_mortar= P4EST_ALLOC(double, total_nodes_mortar);
  double* u_p_on_f_p_mortar= P4EST_ALLOC(double, total_nodes_mortar);

  double* qstar_min_q_mortar = P4EST_ALLOC(double, total_nodes_mortar);
  double* qstar_min_q_m = P4EST_ALLOC(double, total_side_nodes_m);

  stride = 0;
  for (i = 0; i < faces_m; i++){
    dgmath_apply_slicer
      (
       dgmath_jit_dbase,
       &(e_m[i]->u_storage[0]),
       (P4EST_DIM),
       f_m,
       e_m[i]->deg,
       &u_m_on_f_m[stride]
      );
    stride += face_nodes_m[i];
  }
 
  stride = 0;
  for (i = 0; i < faces_p; i++){
    dgmath_apply_slicer
      (
       dgmath_jit_dbase,
       &(e_p[i]->u_storage[0]),
       (P4EST_DIM),
       f_p,
       e_p[i]->deg,
       &u_p_on_f_p[stride]
      );
    stride += face_nodes_p[i];
  }
  
  /* project (-)-side u trace vector onto mortar space */ 
  dgmath_project_side_onto_mortar_space
    (
     dgmath_jit_dbase,
     u_m_on_f_m,
     faces_m,
     deg_m,
     u_m_on_f_m_mortar,
     faces_mortar,
     deg_mortar
    );

  /* project (+)-side u trace vector onto mortar space */
  dgmath_project_side_onto_mortar_space
    (
     dgmath_jit_dbase,
     u_p_on_f_p,
     faces_p,
     deg_p,
     u_p_on_f_p_mortar,
     faces_mortar,
     deg_mortar
    );

  /* For each component of the vector */
  int dir;
  for (dir = 0; dir < (P4EST_DIM); dir++){

    /* compute the (-)-u-derivative and project on the (-)-side faces and project q onto the (-)-side faces */
    stride = 0;
    for (i = 0; i < faces_m; i++){
      dgmath_apply_Dij(dgmath_jit_dbase, e_m[i]->u_elem, (P4EST_DIM), e_m[i]->deg, dir, du_m);
      linalg_vec_scale(2./e_m[i]->h, du_m, dgmath_get_nodes((P4EST_DIM), e_m[i]->deg) );

      dgmath_apply_slicer
        (
         dgmath_jit_dbase,
         du_m,
         (P4EST_DIM),
         f_m,
         e_m[i]->deg,
         &du_m_on_f_m[stride]
        );
    
      dgmath_apply_slicer
        (
         dgmath_jit_dbase,
         e_m[i]->q_elem[dir],
         (P4EST_DIM),
         f_m,
         e_m[i]->deg,
         &q_m_on_f_m[stride]
        );

      stride += face_nodes_m[i];
    }

    /* compute the (+)-u-derivative and project on the (+)-side faces and project q onto the (+)-side faces */
    stride = 0;
    for (i = 0; i < faces_p; i++){
      dgmath_apply_Dij(dgmath_jit_dbase, &(e_p[i]->u_storage[0]), (P4EST_DIM), e_p[i]->deg, dir, du_p);
      linalg_vec_scale(2./e_p[i]->h, du_p, dgmath_get_nodes((P4EST_DIM), e_p[i]->deg));

      dgmath_apply_slicer
        (
         dgmath_jit_dbase,
         du_p,
         (P4EST_DIM),
         f_p,
         e_p[i]->deg,
         &du_p_on_f_p[stride]
        );

      stride += face_nodes_p[i];
    }

    /* project the derivatives from (-) and (+) sides onto the mortar space */
    dgmath_project_side_onto_mortar_space
      (
       dgmath_jit_dbase,
       du_m_on_f_m,
       faces_m,
       deg_m,
       du_m_on_f_m_mortar,
       faces_mortar,
       deg_mortar
      );

    dgmath_project_side_onto_mortar_space
      (
       dgmath_jit_dbase,
       du_p_on_f_p,
       faces_p,
       deg_p,
       du_p_on_f_p_mortar,
       faces_mortar,
       deg_mortar
      );

    /* project q from the (-) side onto the mortar space */
    dgmath_project_side_onto_mortar_space
      (
       dgmath_jit_dbase,
       q_m_on_f_m,
       faces_m,
       deg_m,
       q_m_on_f_m_mortar,
       faces_mortar,
       deg_mortar
      );

    /* util_print_matrix(du_m_on_f_m_mortar, total_nodes_mortar, 1, "du_m_on_f_m_mortar = ", 0); */
    /* util_print_matrix(du_p_on_f_p_mortar, total_nodes_mortar, 1, "du_p_on_f_p_mortar = ", 0); */
    /* util_print_matrix(u_m_on_f_m_mortar, total_nodes_mortar, 1, "u_m_on_f_m_mortar = ", 0); */
    /* util_print_matrix(u_p_on_f_p_mortar, total_nodes_mortar, 1, "u_p_on_f_p_mortar = ", 0); */
    /* util_print_matrix(&n[0], (P4EST_DIM), 1, "n = ", 0); */
    /* util_print_matrix(&penalty_mortar[0], faces_mortar, 1, "penalty_mortar = ", 0); */
    /* printf("faces_mortar = %d\n", faces_mortar); */

    /* calculate symmetric interior penalty flux */
    int k;
    int f;
    stride = 0;
    for (f = 0; f < faces_mortar; f++){
      double sigma = penalty_mortar[f];
      for (k = 0; k < nodes_mortar[f]; k++){
        int ks = k + stride;
        qstar_min_q_mortar[ks] = .5*(du_p_on_f_p_mortar[ks] + du_m_on_f_m_mortar[ks]);
        qstar_min_q_mortar[ks] -= -sigma*n[dir]*u_p_on_f_p_mortar[ks];
        qstar_min_q_mortar[ks] -= sigma*n[dir]*u_m_on_f_m_mortar[ks];
        /* printf(" qflux_proj[%d] = %f\n", ks,  qstar_min_q_mortar[ks]); */
        qstar_min_q_mortar[ks] -= q_m_on_f_m_mortar[ks];
      }
      stride += nodes_mortar[f];
    }

    /* project mortar data back onto the (-) side */
    dgmath_project_mortar_onto_side
      (
       dgmath_jit_dbase,
       qstar_min_q_mortar,
       faces_mortar,
       deg_mortar,
       qstar_min_q_m,
       faces_m,
       deg_m
      );

    /* copy result back to element */
    stride = 0;
    for (i = 0; i < faces_m; i++){
      if(e_m_is_ghost[i] == 0)
        linalg_copy_1st_to_2nd
          (
           &qstar_min_q_m[stride],
           &(e_m[i]->qstar_min_q[dir][f_m*face_nodes_m[i]]),
           face_nodes_m[i]
          );
      stride += face_nodes_m[i];                     
    }
  }

  P4EST_FREE(u_p_on_f_p_mortar);
  P4EST_FREE(du_p_on_f_p_mortar);
  P4EST_FREE(q_m_on_f_m_mortar);
  P4EST_FREE(du_m_on_f_m_mortar);
  P4EST_FREE(u_m_on_f_m_mortar);
  P4EST_FREE(u_p_on_f_p);
  P4EST_FREE(du_p_on_f_p);
  P4EST_FREE(q_m_on_f_m);
  P4EST_FREE(du_m_on_f_m);
  P4EST_FREE(u_m_on_f_m);
  P4EST_FREE(du_p);
  P4EST_FREE(du_m);
  P4EST_FREE(qstar_min_q_m);
  P4EST_FREE(qstar_min_q_mortar);
}
예제 #20
0
/**
 * Runs all tests.
 */
int
main (int argc, char **argv)
{
  const char         *this_fn_name = P4EST_STRING "_test_subcomm";
  /* options */
  const p4est_locidx_t min_quadrants = 15;
  const int           min_level = 4;
  const int           fill_uniform = 0;
  /* parallel environment */
  sc_MPI_Comm         mpicomm = sc_MPI_COMM_WORLD;
  int                 mpisize, submpisize;
  int                 mpiret;
#ifdef P4EST_ENABLE_DEBUG
  int                 rank;
#endif
  /* p4est */
  p4est_connectivity_t *connectivity;
  p4est_t            *p4est;
  p4est_locidx_t     *partition;

  /* initialize MPI */
  mpiret = sc_MPI_Init (&argc, &argv);
  SC_CHECK_MPI (mpiret);

  /* exit if MPI communicator cannot be reduced */
  mpiret = sc_MPI_Comm_size (mpicomm, &mpisize);
  SC_CHECK_MPI (mpiret);
  if (mpisize == 1) {
    mpiret = sc_MPI_Finalize ();
    SC_CHECK_MPI (mpiret);
    return 0;
  }

  /* initialize p4est */
  sc_init (mpicomm, 1, 1, NULL, SC_LP_DEFAULT);
  p4est_init (NULL, SC_LP_DEFAULT);

  /* create connectivity */
#ifdef P4_TO_P8
  connectivity = p8est_connectivity_new_unitcube ();
#else
  connectivity = p4est_connectivity_new_unitsquare ();
#endif

  /* create p4est object */
  p4est = p4est_new_ext (mpicomm, connectivity,
                         min_quadrants, min_level, fill_uniform,
                         0, NULL, NULL);

  /* write vtk: new */
  p4est_vtk_write_file (p4est, NULL, P4EST_STRING "_subcomm_new");

  /* set variables pertaining to the parallel environment */
#ifdef P4EST_ENABLE_DEBUG
  rank = p4est->mpirank;
#endif
  submpisize = mpisize / 2;
  P4EST_ASSERT (submpisize <= p4est->global_num_quadrants);

  /* construct partitioning with empty ranks */
  {
    p4est_locidx_t      n_quads_per_proc, n_quads_leftover;
    int                 p;

    partition = P4EST_ALLOC (p4est_locidx_t, mpisize);
    n_quads_per_proc = p4est->global_num_quadrants / submpisize;
    n_quads_leftover = p4est->global_num_quadrants -
      (n_quads_per_proc * submpisize);
    for (p = 0; p < mpisize; p++) {
      if (p % 2) {              /* if this rank will get quadrants */
        partition[p] = n_quads_per_proc;
      }
      else {                    /* if this rank will be empty */
        partition[p] = 0;
      }
    }
    partition[1] += n_quads_leftover;

    /* check partitioning */
#ifdef P4EST_ENABLE_DEBUG
    {
      p4est_gloidx_t      sum = 0;

      for (p = 0; p < mpisize; p++) {
        sum += (p4est_gloidx_t) partition[p];
      }
      P4EST_ASSERT (sum == p4est->global_num_quadrants);
    }
#endif
  }

  /*
   * Test 1: Reduce MPI communicator to non-empty ranks
   */

  P4EST_GLOBAL_INFOF ("%s: Into test 1\n", this_fn_name);
  {
    p4est_t            *p4est_subcomm;
    int                 is_nonempty;

    /* create p4est copy and re-partition */
    p4est_subcomm = p4est_copy_ext (p4est, 1, 1);
    (void) p4est_partition_given (p4est_subcomm, partition);

    /* write vtk: partitioned */
    p4est_vtk_write_file (p4est_subcomm, NULL, P4EST_STRING "_subcomm_part");

    /* reduce MPI communicator to non-empty ranks */
    is_nonempty = p4est_comm_parallel_env_reduce (&p4est_subcomm);
    P4EST_ASSERT ((is_nonempty && 0 < partition[rank]) ||
                  (!is_nonempty && 0 == partition[rank]));

    if (is_nonempty) {
      /* write vtk: reduced communicator */
      p4est_vtk_write_file (p4est_subcomm, NULL,
                            P4EST_STRING "_subcomm_sub1");

      /* destroy the p4est that has a reduced MPI communicator */
      p4est_destroy (p4est_subcomm);
    }
  }
  mpiret = sc_MPI_Barrier (mpicomm);
  SC_CHECK_MPI (mpiret);
  P4EST_GLOBAL_INFOF ("%s: Done test 1\n", this_fn_name);

  /*
   * Test 2: Reduce MPI communicator to non-empty ranks, but now the MPI
   * communicator is not owned
   */

  P4EST_GLOBAL_INFOF ("%s: Into test 2\n", this_fn_name);
  {
    p4est_t            *p4est_subcomm;
    int                 is_nonempty;

    /* create p4est copy and re-partition */
    p4est_subcomm = p4est_copy_ext (p4est, 1, 0 /* don't dup. comm. */ );
    (void) p4est_partition_given (p4est_subcomm, partition);

    /* reduce MPI communicator to non-empty ranks */
    is_nonempty = p4est_comm_parallel_env_reduce (&p4est_subcomm);
    P4EST_ASSERT ((is_nonempty && 0 < partition[rank]) ||
                  (!is_nonempty && 0 == partition[rank]));

    if (is_nonempty) {
      /* destroy the p4est that has a reduced MPI communicator */
      p4est_destroy (p4est_subcomm);
    }
  }
  mpiret = sc_MPI_Barrier (mpicomm);
  SC_CHECK_MPI (mpiret);
  P4EST_GLOBAL_INFOF ("%s: Done test 2\n", this_fn_name);

  /*
   * Test 3: Reduce MPI communicator to non-empty ranks, but keep rank 0
   */

  P4EST_GLOBAL_INFOF ("%s: Into test 3\n", this_fn_name);
  {
    p4est_t            *p4est_subcomm;
    int                 sub_exists;
    sc_MPI_Group        group, group_reserve;
    int                 reserve_range[1][3];

    /* create group of full MPI communicator */
    mpiret = sc_MPI_Comm_group (mpicomm, &group);
    SC_CHECK_MPI (mpiret);

    /* create sub-group containing only rank 0 */
    reserve_range[0][0] = 0;
    reserve_range[0][1] = 0;
    reserve_range[0][2] = 1;
    mpiret =
      sc_MPI_Group_range_incl (group, 1, reserve_range, &group_reserve);
    SC_CHECK_MPI (mpiret);

    /* create p4est copy and re-partition */
    p4est_subcomm = p4est_copy_ext (p4est, 1, 1);
    (void) p4est_partition_given (p4est_subcomm, partition);

    /* reduce MPI communicator to non-empty ranks, but keep rank 0 */
    sub_exists = p4est_comm_parallel_env_reduce_ext (&p4est_subcomm,
                                                     group_reserve, 1, NULL);
    P4EST_ASSERT ((sub_exists && (0 < partition[rank] || rank == 0)) ||
                  (!sub_exists && 0 == partition[rank]));

    if (sub_exists) {
      /* write vtk: reduced communicator */
      p4est_vtk_write_file (p4est_subcomm, NULL,
                            P4EST_STRING "_subcomm_sub3");

      /* destroy the p4est that has a reduced MPI communicator */
      p4est_destroy (p4est_subcomm);
    }
  }
  mpiret = sc_MPI_Barrier (mpicomm);
  SC_CHECK_MPI (mpiret);
  P4EST_GLOBAL_INFOF ("%s: Done test 3\n", this_fn_name);

  /*
   * Test 4: Reduce MPI communicator to non-empty ranks, but keep last 2 ranks
   */

  P4EST_GLOBAL_INFOF ("%s: Into test 4\n", this_fn_name);
  {
    p4est_t            *p4est_subcomm;
    int                 sub_exists;
    sc_MPI_Group        group, group_reserve;
    int                 reserve_range[1][3];

    /* create group of full MPI communicator */
    mpiret = sc_MPI_Comm_group (mpicomm, &group);
    SC_CHECK_MPI (mpiret);

    /* create sub-group containing only last 2 ranks */
    reserve_range[0][0] = SC_MAX (0, mpisize - 2);
    reserve_range[0][1] = mpisize - 1;
    reserve_range[0][2] = 1;
    mpiret =
      sc_MPI_Group_range_incl (group, 1, reserve_range, &group_reserve);
    SC_CHECK_MPI (mpiret);

    /* create p4est copy and re-partition */
    p4est_subcomm = p4est_copy_ext (p4est, 1, 1);
    (void) p4est_partition_given (p4est_subcomm, partition);

    /* reduce MPI communicator to non-empty ranks, but keep last 2 ranks */
    sub_exists = p4est_comm_parallel_env_reduce_ext (&p4est_subcomm,
                                                     group_reserve, 0, NULL);
    P4EST_ASSERT ((sub_exists && (0 < partition[rank] || mpisize - 2 <= rank))
                  || (!sub_exists && 0 == partition[rank]));

    if (sub_exists) {
      /* write vtk: reduced communicator */
      p4est_vtk_write_file (p4est_subcomm, NULL,
                            P4EST_STRING "_subcomm_sub4");

      /* destroy the p4est that has a reduced MPI communicator */
      p4est_destroy (p4est_subcomm);
    }
  }
  mpiret = sc_MPI_Barrier (mpicomm);
  SC_CHECK_MPI (mpiret);
  P4EST_GLOBAL_INFOF ("%s: Done test 4\n", this_fn_name);

  /* destroy */
  P4EST_FREE (partition);
  p4est_destroy (p4est);
  p4est_connectivity_destroy (connectivity);

  /* finalize */
  sc_finalize ();
  mpiret = sc_MPI_Finalize ();
  SC_CHECK_MPI (mpiret);

  return 0;
}
예제 #21
0
static void
p6est_profile_element_to_node_col (p6est_profile_t * profile,
                                   p4est_locidx_t cid,
                                   p4est_locidx_t * offsets,
                                   p4est_locidx_t * e_to_n,
                                   p6est_lnodes_code_t * fc)
{
  p4est_locidx_t (*lr)[2] = (p4est_locidx_t (*)[2]) profile->lnode_ranges;
  p4est_locidx_t      nelem;
  p4est_locidx_t    **elem_to_node;
  int                 i, j, k;
  p4est_locidx_t      ll;
  sc_array_t          elem, node;
  sc_array_t         *lc = profile->lnode_columns;
  p4est_locidx_t      ncid, nid;
  p4est_lnodes_code_t fc4 = profile->lnodes->face_code[cid];
  p4est_locidx_t     *en = profile->lnodes->element_nodes;
  int                 degree = profile->lnodes->degree;
  int                 Nrp = degree + 1;
  int                 Nfp = (degree + 1) * (degree + 1);

  P4EST_ASSERT (degree > 1);

  ncid = en[Nfp * cid + Nrp * (Nrp / 2) + (Nrp / 2)];
  nelem = lr[ncid][1];

  sc_array_init_view (&elem, lc, lr[ncid][0], nelem);

  elem_to_node = P4EST_ALLOC (p4est_locidx_t *, nelem);

  for (ll = 0; ll < nelem; ll++) {
    fc[ll] = (p6est_lnodes_code_t) fc4;
  }
  for (k = 0, j = 0; j < Nrp; j++) {
    for (i = 0; i < Nrp; i++, k++) {
      nid = en[Nfp * cid + k];
      sc_array_init_view (&node, lc, lr[nid][0], lr[nid][1]);
      for (ll = 0; ll < nelem; ll++) {
        elem_to_node[ll] = e_to_n +
          (degree + 1) * (degree + 1) * (degree + 1) * ll + (degree + 1) * k;
      }
      if (!(i % degree) && !(j % degree)) {
        int                 c = 2 * (! !j) + (! !i);

        p6est_profile_element_to_node_single (&elem, &node, degree,
                                              offsets[nid], elem_to_node, fc,
                                              4 + c);
      }
      else if ((i % degree) && (j % degree)) {
        p6est_profile_element_to_node_single (&elem, &elem, degree,
                                              offsets[nid], elem_to_node,
                                              NULL, -1);
      }
      else {
        int                 f = 2 * !(j % degree) + (i == degree
                                                     || j == degree);

        p6est_profile_element_to_node_single (&elem, &node, degree,
                                              offsets[nid], elem_to_node, fc,
                                              f);
      }
    }
  }
  P4EST_FREE (elem_to_node);
}
static void
bi_est_dirichlet
(
 element_data_t* e_m,
 int f_m,
 grid_fcn_t bndry_fcn,
 dgmath_jit_dbase_t* dgmath_jit_dbase,
 void* params
)
{
  grid_fcn_t u_at_bndry = bndry_fcn;
  double prefactor = bi_est_u_dirichlet_prefactor_calculate_fcn
                 (
                  e_m->deg,
                  e_m->h,
                  e_m->deg,
                  e_m->h,
                  bi_est_sipg_flux_penalty_prefactor
                 );

  /* printf("prefactor = %f\n", prefactor); */
  
  int face_nodes_m = dgmath_get_nodes ( (P4EST_DIM) - 1, e_m->deg );
  double* tmp = P4EST_ALLOC(double, face_nodes_m);
  double* xyz_on_f_m [(P4EST_DIM)];
  double* u_m_on_f_m = P4EST_ALLOC(double, face_nodes_m);
  
  /* get solution variable on this face */
  dgmath_apply_slicer(
                      dgmath_jit_dbase,
                      e_m->u_elem,
                      (P4EST_DIM),
                      f_m,
                      e_m->deg,
                      u_m_on_f_m);

  /* get xyz on this face */
  int dir;
  for (dir = 0; dir < (P4EST_DIM); dir++){
    xyz_on_f_m[dir] = P4EST_ALLOC(double, face_nodes_m);

    double* rst = dgmath_fetch_xyz_nd(dgmath_jit_dbase, (P4EST_DIM), e_m->deg, dir);
    dgmath_apply_slicer(dgmath_jit_dbase, rst, (P4EST_DIM), f_m, e_m->deg, tmp);
    
    dgmath_rtox_array(tmp, e_m->xyz_corner[dir], e_m->h, xyz_on_f_m[dir], face_nodes_m);
  }

  /* get boundary values on this face */
  int i;
  for (i = 0; i < face_nodes_m; i++){
    tmp[i] = u_at_bndry(xyz_on_f_m[0][i],
                             xyz_on_f_m[1][i]
#if (P4EST_DIM)==3
                             ,
                             xyz_on_f_m[2][i]
#endif                          
                            );
  }

  double n [3];
  dgmath_get_normal(f_m, (P4EST_DIM), &n[0]);

  for (dir = 0; dir < (P4EST_DIM); dir++){
    /* calculate qstar - q(-) */
    for(i = 0; i < face_nodes_m; i++){
      e_m->ustar_min_u[f_m*face_nodes_m + i] = 0.;
      /* printf("tmp[%d] = %f", tmp[i]); */
      /* the ||mu \del u|| term does not contribute at the boundary to eta2*/
      e_m->qstar_min_q[dir][f_m*face_nodes_m + i] = n[dir]*(u_m_on_f_m[i] - tmp[i]);//
      e_m->qstar_min_q[dir][f_m*face_nodes_m + i] *= prefactor;
    }
  }

  for (dir = 0; dir < (P4EST_DIM); dir++){
    P4EST_FREE(xyz_on_f_m[dir]);
  }

  P4EST_FREE(u_m_on_f_m);
  P4EST_FREE(tmp);
}
예제 #23
0
파일: mesh2.c 프로젝트: holke/p4est
static void
mesh_run (mpi_context_t * mpi, p4est_connectivity_t * connectivity,
          int uniform, int compute_tree_index, int compute_level_lists,
          p4est_connect_type_t mesh_btype)
{
  int                 mpiret;
  unsigned            crc;
  long                local_used[4], global_used[4];
  p4est_t            *p4est;
  p4est_ghost_t      *ghost;
  p4est_mesh_t       *mesh;
  user_data_t        *ghost_data;

  p4est = p4est_new (mpi->mpicomm, connectivity,
                     sizeof (user_data_t), init_fn, NULL);
  if (!uniform)
    p4est_vtk_write_file (p4est, NULL, P4EST_STRING "_mesh_new");

  /* refinement */
  if (uniform) {
    p4est_refine (p4est, 1, refine_uniform, init_fn);
  }
  else {
    p4est_refine (p4est, 1, refine_normal, init_fn);
    p4est_vtk_write_file (p4est, NULL, P4EST_STRING "_mesh_refined");
  }

  /* balance */
  p4est_balance (p4est, P4EST_CONNECT_FULL, init_fn);
  if (!uniform)
    p4est_vtk_write_file (p4est, NULL, P4EST_STRING "_mesh_balanced");

  /* partition */
  p4est_partition (p4est, 0, NULL);
  if (!uniform) {
    p4est_vtk_write_file (p4est, NULL, P4EST_STRING "_mesh_partition");
  }
  crc = p4est_checksum (p4est);

  /* print and verify forest checksum */
  P4EST_GLOBAL_STATISTICSF ("Tree %s checksum 0x%08x\n",
                            uniform ? "uniform" : "adapted", crc);

  /* create ghost layer and mesh */
  ghost = p4est_ghost_new (p4est, P4EST_CONNECT_FULL);
  ghost_data = P4EST_ALLOC (user_data_t, ghost->ghosts.elem_count);
  p4est_ghost_exchange_data (p4est, ghost, ghost_data);
  mesh = p4est_mesh_new_ext (p4est, ghost,
                             compute_tree_index, compute_level_lists,
                             mesh_btype);
  test_mesh (p4est, ghost, mesh,
             compute_tree_index, compute_level_lists, mesh_btype,
             ghost_data, uniform);

  /* compute memory used */
  local_used[0] = (long) p4est_connectivity_memory_used (p4est->connectivity);
  local_used[1] = (long) p4est_memory_used (p4est);
  local_used[2] = (long) p4est_ghost_memory_used (ghost);
  local_used[3] = (long) p4est_mesh_memory_used (mesh);
  mpiret = sc_MPI_Allreduce (local_used, global_used, 4, sc_MPI_LONG,
                             sc_MPI_SUM, mpi->mpicomm);
  SC_CHECK_MPI (mpiret);
  P4EST_GLOBAL_PRODUCTIONF ("Total %s memory used %ld %ld %ld %ld\n",
                            uniform ? "uniform" : "adapted",
                            global_used[0], global_used[1],
                            global_used[2], global_used[3]);

  /* destroy ghost layer and mesh */
  P4EST_FREE (ghost_data);
  p4est_mesh_destroy (mesh);
  p4est_ghost_destroy (ghost);

  /* destroy the p4est structure */
  p4est_destroy (p4est);
}
static void
bi_est_interface
(
 element_data_t** e_m,
 int faces_m,
 int f_m,
 element_data_t** e_p,
 int faces_p,
 int f_p,
 int* e_m_is_ghost,
 dgmath_jit_dbase_t* dgmath_jit_dbase,
 void* params
)
{
  int deg_p [(P4EST_HALF)];
  int max_deg_p = -1;
  int face_nodes_p [(P4EST_HALF)];
  int deg_m [(P4EST_HALF)];
  int face_nodes_m [(P4EST_HALF)];
  int max_deg_m = -1;
  
  int deg_mortar [(P4EST_HALF)];
  int faces_mortar = (faces_m > faces_p) ? faces_m : faces_p;
  int nodes_mortar [(P4EST_HALF)];
  
  double gradu_prefactor_mortar [(P4EST_HALF)];
  double u_prefactor_mortar [(P4EST_HALF)];
  
  double n [(P4EST_DIM)];
  dgmath_get_normal(f_m, (P4EST_DIM), &n[0]);
  
  int i,j;
  
  /* calculate degs and nodes of each face of (-) side */
  int total_side_nodes_m = 0;
  for (i = 0; i < faces_m; i++){
    deg_m[i] = e_m[i]->deg;
    if (e_m[i]->deg > max_deg_m) max_deg_m = e_m[i]->deg;
    face_nodes_m[i] = dgmath_get_nodes( (P4EST_DIM) - 1, e_m[i]->deg );
    total_side_nodes_m += face_nodes_m[i];
  }

  /* calculate degs and nodes of each face of (+) side  */
  int total_side_nodes_p = 0;
  for (i = 0; i < faces_p; i++){
    deg_p[i] = e_p[i]->deg;
    if (e_p[i]->deg > max_deg_p) max_deg_p = e_p[i]->deg;
    face_nodes_p[i] = dgmath_get_nodes( (P4EST_DIM) - 1, e_p[i]->deg );
    total_side_nodes_p += face_nodes_p[i];
  }    

  /* calculate degs and nodes of the mortar faces */
  int total_nodes_mortar = 0;
  for (i = 0; i < faces_m; i++)
    for (j = 0; j < faces_p; j++){
      /* find max degree for each face pair of the two sides*/
      deg_mortar[i+j] = util_max_int( e_m[i]->deg, e_p[j]->deg );

      /* find IP penalty parameter for each face pair of the two sides*/
      gradu_prefactor_mortar[i+j] = bi_est_gradu_prefactor_calculate_fcn
                            (
                             e_m[i]->deg,
                             e_m[i]->h,
                             e_p[j]->deg,
                             e_p[j]->h,
                             bi_est_sipg_flux_penalty_prefactor
                            );

      u_prefactor_mortar[i+j] = bi_est_u_prefactor_calculate_fcn
                            (
                             e_m[i]->deg,
                             e_m[i]->h,
                             e_p[j]->deg,
                             e_p[j]->h,
                             bi_est_sipg_flux_penalty_prefactor
                            );    

      /* printf("Je1_prefactor_mortar, Je2_prefactor_mortar = %f,%f\n", gradu_prefactor_mortar[i], u_prefactor_mortar[i]); */
      
      nodes_mortar[i+j] = dgmath_get_nodes( (P4EST_DIM) - 1, deg_mortar[i+j] );
      
      total_nodes_mortar += nodes_mortar[i+j];
    }

  /* scalar and vector fields on each of the (-) and (+) elements */
  double* du_m = P4EST_ALLOC(double, dgmath_get_nodes((P4EST_DIM), max_deg_m));
  double* du_p = P4EST_ALLOC(double, dgmath_get_nodes((P4EST_DIM), max_deg_p));
  /* slices of scalar/vector fields of (-) onto f_m and (+) onto f_p */
  double* u_m_on_f_m = P4EST_ALLOC(double, total_side_nodes_m);
  double* du_m_on_f_m = P4EST_ALLOC(double, total_side_nodes_m); 
  double* du_p_on_f_p = P4EST_ALLOC(double, total_side_nodes_p);
  double* u_p_on_f_p = P4EST_ALLOC(double, total_side_nodes_p);
  /* projections of f_m slices to max_deg space */
  double* u_m_on_f_m_mortar = P4EST_ALLOC(double, total_nodes_mortar);
  double* du_m_on_f_m_mortar= P4EST_ALLOC(double, total_nodes_mortar); 
  double* du_p_on_f_p_mortar= P4EST_ALLOC(double, total_nodes_mortar);
  double* u_p_on_f_p_mortar= P4EST_ALLOC(double, total_nodes_mortar);

  double* qstar_min_q_mortar = P4EST_ALLOC(double, total_nodes_mortar);

  /* NOTE THE SUBTLE ALLOC_ZERO here, we want to zero out ustar_min_u_mortar because it's a dot product */
  double* ustar_min_u_mortar = P4EST_ALLOC_ZERO(double, total_nodes_mortar);
  double* qstar_min_q_m = P4EST_ALLOC(double, total_side_nodes_m);
  double* ustar_min_u_m = P4EST_ALLOC(double, total_side_nodes_m);

  int stride = 0;
  for (i = 0; i < faces_m; i++){
    dgmath_apply_slicer
      (
       dgmath_jit_dbase,
       &(e_m[i]->u_storage[0]),
       (P4EST_DIM),
       f_m,
       e_m[i]->deg,
       &u_m_on_f_m[stride]
      );
    stride += face_nodes_m[i];
  }
 
  stride = 0;
  for (i = 0; i < faces_p; i++){
    dgmath_apply_slicer
      (
       dgmath_jit_dbase,
       &(e_p[i]->u_storage[0]),
       (P4EST_DIM),
       f_p,
       e_p[i]->deg,
       &u_p_on_f_p[stride]
      );
    stride += face_nodes_p[i];
  }
  
  /* project (-)-side u trace vector onto mortar space */ 
  dgmath_project_side_onto_mortar_space
    (
     dgmath_jit_dbase,
     u_m_on_f_m,
     faces_m,
     deg_m,
     u_m_on_f_m_mortar,
     faces_mortar,
     deg_mortar
    );

  /* project (+)-side u trace vector onto mortar space */
  dgmath_project_side_onto_mortar_space
    (
     dgmath_jit_dbase,
     u_p_on_f_p,
     faces_p,
     deg_p,
     u_p_on_f_p_mortar,
     faces_mortar,
     deg_mortar
    );

  /* For each component of the vector */
  int dir;
  for (dir = 0; dir < (P4EST_DIM); dir++){

    /* compute the (-)-u-derivative and project on the (-)-side faces and project q onto the (-)-side faces */
    stride = 0;
    for (i = 0; i < faces_m; i++){
      dgmath_apply_Dij
        (
         dgmath_jit_dbase,
         e_m[i]->u_elem,
         (P4EST_DIM),
         e_m[i]->deg,
         dir,
         du_m
        );
      
      linalg_vec_scale(2./e_m[i]->h, du_m, dgmath_get_nodes((P4EST_DIM), e_m[i]->deg));

      dgmath_apply_slicer
        (
         dgmath_jit_dbase,
         du_m,
         (P4EST_DIM),
         f_m,
         e_m[i]->deg,
         &du_m_on_f_m[stride]
        );
    
       stride += face_nodes_m[i];
    }

    /* compute the (+)-u-derivative and project on the (+)-side faces and project q onto the (+)-side faces */
    stride = 0;
    for (i = 0; i < faces_p; i++){
      dgmath_apply_Dij(dgmath_jit_dbase, &(e_p[i]->u_storage[0]), (P4EST_DIM), e_p[i]->deg, dir, du_p);
      linalg_vec_scale(2./e_p[i]->h, du_p, dgmath_get_nodes((P4EST_DIM), e_p[i]->deg));

      dgmath_apply_slicer
        (
         dgmath_jit_dbase,
         du_p,
         (P4EST_DIM),
         f_p,
         e_p[i]->deg,
         &du_p_on_f_p[stride]
        );

      stride += face_nodes_p[i];
    }

    /* project the derivatives from (-) and (+) sides onto the mortar space */
    dgmath_project_side_onto_mortar_space
      (
       dgmath_jit_dbase,
       du_m_on_f_m,
       faces_m,
       deg_m,
       du_m_on_f_m_mortar,
       faces_mortar,
       deg_mortar
      );

    dgmath_project_side_onto_mortar_space
      (
       dgmath_jit_dbase,
       du_p_on_f_p,
       faces_p,
       deg_p,
       du_p_on_f_p_mortar,
       faces_mortar,
       deg_mortar
      );

    /* calculate symmetric interior penalty flux */
    int k;
    int f;
    stride = 0;
    for (f = 0; f < faces_mortar; f++){
      for (k = 0; k < nodes_mortar[f]; k++){
        int ks = k + stride;
        qstar_min_q_mortar[ks] = n[dir]*u_m_on_f_m_mortar[ks];
        qstar_min_q_mortar[ks] -= n[dir]*u_p_on_f_p_mortar[ks];
        qstar_min_q_mortar[ks] *= u_prefactor_mortar[f];
        ustar_min_u_mortar[ks] += gradu_prefactor_mortar[f]*n[dir]*(du_m_on_f_m_mortar[ks] - du_p_on_f_p_mortar[ks]);

        /* printf("ustar_min_u_mortar[%d]\n", ks, ustar_min_u_mortar[ks]); */
        /* printf("qstar_min_q_mortar[%d]\n", ks, qstar_min_q_mortar[ks]); */
      }
      stride += nodes_mortar[f];
    }

    /* project mortar data back onto the (-) side */
    dgmath_project_mortar_onto_side
      (
       dgmath_jit_dbase,
       qstar_min_q_mortar,
       faces_mortar,
       deg_mortar,
       qstar_min_q_m,
       faces_m,
       deg_m
      );

    dgmath_project_mortar_onto_side
      (
       dgmath_jit_dbase,
       ustar_min_u_mortar,
       faces_mortar,
       deg_mortar,
       ustar_min_u_m,
       faces_m,
       deg_m
      );  

    /* copy result back to element */
    stride = 0;
    for (i = 0; i < faces_m; i++){
      if(e_m_is_ghost[i] == 0){
        linalg_copy_1st_to_2nd
          (
           &qstar_min_q_m[stride],
           &(e_m[i]->qstar_min_q[dir][f_m*face_nodes_m[i]]),
           face_nodes_m[i]
          );
        linalg_copy_1st_to_2nd
          (
           &ustar_min_u_m[stride],
           &(e_m[i]->ustar_min_u[f_m*face_nodes_m[i]]),
           face_nodes_m[i]
          );
      }
      stride += face_nodes_m[i];                     
    }
  }

  P4EST_FREE(u_p_on_f_p_mortar);
  P4EST_FREE(du_p_on_f_p_mortar);
  P4EST_FREE(du_m_on_f_m_mortar);
  P4EST_FREE(u_m_on_f_m_mortar);
  P4EST_FREE(u_p_on_f_p);
  P4EST_FREE(du_p_on_f_p);
  P4EST_FREE(du_m_on_f_m);
  P4EST_FREE(u_m_on_f_m);
  P4EST_FREE(du_p);
  P4EST_FREE(du_m);
  P4EST_FREE(qstar_min_q_m);
  P4EST_FREE(ustar_min_u_m);
  P4EST_FREE(qstar_min_q_mortar);
  P4EST_FREE(ustar_min_u_mortar);
}
예제 #25
0
int
p6est_vtk_write_header (p6est_t * p6est,
                        double scale, int write_tree, int write_rank,
                        int wrap_rank, const char *point_scalars,
                        const char *point_vectors, const char *filename)
{
  p6est_connectivity_t *connectivity = p6est->connectivity;
  p4est_t            *p4est = p6est->columns;
  sc_array_t         *layers = p6est->layers;
  sc_array_t         *trees = p4est->trees;
  const int           mpirank = p4est->mpirank;
  const double        intsize = 1.0 / P4EST_ROOT_LEN;
  double              v[24];
  const p4est_topidx_t first_local_tree = p4est->first_local_tree;
  const p4est_topidx_t last_local_tree = p4est->last_local_tree;
  const p4est_locidx_t Ncells = (p4est_locidx_t) layers->elem_count;
  const p4est_locidx_t Ncorners = P8EST_CHILDREN * Ncells;
#ifdef P4EST_VTK_ASCII
  double              wx, wy, wz;
  p4est_locidx_t      sk;
#else
  int                 retval;
  uint8_t            *uint8_data;
  p4est_locidx_t     *locidx_data;
#endif
  int                 xi, yi, j, k;
  int                 zi;
  double              h2, h2z, eta_x, eta_y, eta_z = 0.;
  double              xyz[3];   /* 3 not P4EST_DIM */
  size_t              num_cols, zz, zy, first, last;
  p4est_topidx_t      jt;
  p4est_locidx_t      quad_count, Ntotal;
  p4est_locidx_t      il;
  P4EST_VTK_FLOAT_TYPE *float_data;
  sc_array_t         *columns;
  p4est_tree_t       *tree;
  p4est_quadrant_t   *col;
  p2est_quadrant_t   *layer;
  char                vtufilename[BUFSIZ];
  FILE               *vtufile;

  SC_CHECK_ABORT (connectivity->conn4->num_vertices > 0,
                  "Must provide connectivity with vertex information");

  P4EST_ASSERT (0. <= scale && scale <= 1. && wrap_rank >= 0);

  Ntotal = Ncorners;
  if (scale == 1.) {
    scale = 1. - 2. * SC_EPS;
    P4EST_ASSERT (scale < 1.);
  }

  /* Have each proc write to its own file */
  snprintf (vtufilename, BUFSIZ, "%s_%04d.vtu", filename, mpirank);
  /* Use "w" for writing the initial part of the file.
   * For further parts, use "r+" and fseek so write_compressed succeeds.
   */
  vtufile = fopen (vtufilename, "wb");
  if (vtufile == NULL) {
    P4EST_LERRORF ("Could not open %s for output\n", vtufilename);
    return -1;
  }

  fprintf (vtufile, "<?xml version=\"1.0\"?>\n");
  fprintf (vtufile, "<VTKFile type=\"UnstructuredGrid\" version=\"0.1\"");
#if defined P4EST_VTK_BINARY && defined P4EST_VTK_COMPRESSION
  fprintf (vtufile, " compressor=\"vtkZLibDataCompressor\"");
#endif
#ifdef SC_IS_BIGENDIAN
  fprintf (vtufile, " byte_order=\"BigEndian\">\n");
#else
  fprintf (vtufile, " byte_order=\"LittleEndian\">\n");
#endif
  fprintf (vtufile, "  <UnstructuredGrid>\n");
  fprintf (vtufile,
           "    <Piece NumberOfPoints=\"%lld\" NumberOfCells=\"%lld\">\n",
           (long long) Ntotal, (long long) Ncells);
  fprintf (vtufile, "      <Points>\n");

  float_data = P4EST_ALLOC (P4EST_VTK_FLOAT_TYPE, 3 * Ntotal);

  /* write point position data */
  fprintf (vtufile, "        <DataArray type=\"%s\" Name=\"Position\""
           " NumberOfComponents=\"3\" format=\"%s\">\n",
           P4EST_VTK_FLOAT_NAME, P4EST_VTK_FORMAT_STRING);

  /* loop over the trees */
  for (jt = first_local_tree, quad_count = 0; jt <= last_local_tree; ++jt) {
    tree = p4est_tree_array_index (trees, jt);
    columns = &tree->quadrants;
    num_cols = columns->elem_count;
    p6est_tree_get_vertices (connectivity, jt, v);

    /* loop over the elements in tree and calculated vertex coordinates */
    for (zz = 0; zz < num_cols; ++zz) {
      col = p4est_quadrant_array_index (columns, zz);
      P6EST_COLUMN_GET_RANGE (col, &first, &last);
      for (zy = first; zy < last; zy++, quad_count++) {
        layer = p2est_quadrant_array_index (layers, zy);
        h2 = .5 * intsize * P4EST_QUADRANT_LEN (col->level);
        h2z = .5 * intsize * P4EST_QUADRANT_LEN (layer->level);
        k = 0;
        for (zi = 0; zi < 2; ++zi) {
          for (yi = 0; yi < 2; ++yi) {
            for (xi = 0; xi < 2; ++xi) {
              P4EST_ASSERT (0 <= k && k < P8EST_CHILDREN);
              eta_x = intsize * col->x + h2 * (1. + (xi * 2 - 1) * scale);
              eta_y = intsize * col->y + h2 * (1. + (yi * 2 - 1) * scale);
              eta_z = intsize * layer->z + h2z * (1. + (zi * 2 - 1) * scale);
              for (j = 0; j < 3; ++j) {
                /* *INDENT-OFF* */
                xyz[j] =
                        ((1. - eta_z) * ((1. - eta_y) * ((1. - eta_x) * v[3 * 0 + j] +
                                                         eta_x  * v[3 * 1 + j]) +
                                         eta_y  * ((1. - eta_x) * v[3 * 2 + j] +
                                                   eta_x  * v[3 * 3 + j]))
                         +     eta_z  * ((1. - eta_y) * ((1. - eta_x) * v[3 * 4 + j] +
                                                         eta_x  * v[3 * 5 + j]) +
                                         eta_y  * ((1. - eta_x) * v[3 * 6 + j] +
                                                   eta_x  * v[3 * 7 + j]))
                        );
                /* *INDENT-ON* */
              }
              for (j = 0; j < 3; ++j) {
                float_data[3 * (P8EST_CHILDREN * quad_count + k) +
                           j] = (P4EST_VTK_FLOAT_TYPE) xyz[j];
              }
              ++k;
            }
          }
        }
        P4EST_ASSERT (k == P8EST_CHILDREN);
      }
    }
  }
  P4EST_ASSERT (P8EST_CHILDREN * quad_count == Ntotal);

#ifdef P4EST_VTK_ASCII
  for (il = 0; il < Ntotal; ++il) {
    wx = float_data[3 * il + 0];
    wy = float_data[3 * il + 1];
    wz = float_data[3 * il + 2];

#ifdef P4EST_VTK_DOUBLES
    fprintf (vtufile, "     %24.16e %24.16e %24.16e\n", wx, wy, wz);
#else
    fprintf (vtufile, "          %16.8e %16.8e %16.8e\n", wx, wy, wz);
#endif
  }
#else
  fprintf (vtufile, "          ");
  /* TODO: Don't allocate the full size of the array, only allocate
   * the chunk that will be passed to zlib and do this a chunk
   * at a time.
   */
  retval = p6est_vtk_write_binary (vtufile, (char *) float_data,
                                   sizeof (*float_data) * 3 * Ntotal);
  fprintf (vtufile, "\n");
  if (retval) {
    P4EST_LERROR ("p6est_vtk: Error encoding points\n");
    fclose (vtufile);
    return -1;
  }
#endif
  P4EST_FREE (float_data);
  fprintf (vtufile, "        </DataArray>\n");
  fprintf (vtufile, "      </Points>\n");
  fprintf (vtufile, "      <Cells>\n");

  /* write connectivity data */
  fprintf (vtufile, "        <DataArray type=\"%s\" Name=\"connectivity\""
           " format=\"%s\">\n", P4EST_VTK_LOCIDX, P4EST_VTK_FORMAT_STRING);
#ifdef P4EST_VTK_ASCII
  for (sk = 0, il = 0; il < Ncells; ++il) {
    fprintf (vtufile, "         ");
    for (k = 0; k < P8EST_CHILDREN; ++sk, ++k) {
      fprintf (vtufile, " %lld", (long long) sk);
    }
    fprintf (vtufile, "\n");
  }
#else
  locidx_data = P4EST_ALLOC (p4est_locidx_t, Ncorners);
  fprintf (vtufile, "          ");
  for (il = 0; il < Ncorners; ++il) {
    locidx_data[il] = il;
  }
  retval = p6est_vtk_write_binary (vtufile, (char *) locidx_data,
                                   sizeof (*locidx_data) * Ncorners);
  fprintf (vtufile, "\n");
  if (retval) {
    P4EST_LERROR ("p6est_vtk: Error encoding connectivity\n");
    fclose (vtufile);
    return -1;
  }
#endif
  fprintf (vtufile, "        </DataArray>\n");

  /* write offset data */
  fprintf (vtufile, "        <DataArray type=\"%s\" Name=\"offsets\""
           " format=\"%s\">\n", P4EST_VTK_LOCIDX, P4EST_VTK_FORMAT_STRING);
#ifdef P4EST_VTK_ASCII
  fprintf (vtufile, "         ");
  for (il = 1, sk = 1; il <= Ncells; ++il, ++sk) {
    fprintf (vtufile, " %lld", (long long) (P8EST_CHILDREN * il));
    if (!(sk % 8) && il != Ncells)
      fprintf (vtufile, "\n         ");
  }
  fprintf (vtufile, "\n");
#else
  for (il = 1; il <= Ncells; ++il)
    locidx_data[il - 1] = P8EST_CHILDREN * il;  /* same type */

  fprintf (vtufile, "          ");
  retval = p6est_vtk_write_binary (vtufile, (char *) locidx_data,
                                   sizeof (*locidx_data) * Ncells);
  fprintf (vtufile, "\n");
  if (retval) {
    P4EST_LERROR ("p6est_vtk: Error encoding offsets\n");
    fclose (vtufile);
    return -1;
  }
#endif
  fprintf (vtufile, "        </DataArray>\n");

  /* write type data */
  fprintf (vtufile, "        <DataArray type=\"UInt8\" Name=\"types\""
           " format=\"%s\">\n", P4EST_VTK_FORMAT_STRING);
#ifdef P4EST_VTK_ASCII
  fprintf (vtufile, "         ");
  for (il = 0, sk = 1; il < Ncells; ++il, ++sk) {
    fprintf (vtufile, " %d", P4EST_VTK_CELL_TYPE);
    if (!(sk % 20) && il != (Ncells - 1))
      fprintf (vtufile, "\n         ");
  }
  fprintf (vtufile, "\n");
#else
  uint8_data = P4EST_ALLOC (uint8_t, Ncells);
  for (il = 0; il < Ncells; ++il)
    uint8_data[il] = P4EST_VTK_CELL_TYPE;

  fprintf (vtufile, "          ");
  retval = p6est_vtk_write_binary (vtufile, (char *) uint8_data,
                                   sizeof (*uint8_data) * Ncells);
  P4EST_FREE (uint8_data);
  fprintf (vtufile, "\n");
  if (retval) {
    P4EST_LERROR ("p6est_vtk: Error encoding types\n");
    fclose (vtufile);
    return -1;
  }
#endif
  fprintf (vtufile, "        </DataArray>\n");
  fprintf (vtufile, "      </Cells>\n");

  if (write_rank || write_tree) {
    fprintf (vtufile, "      <CellData Scalars=\"%s\">\n",
             !write_tree ? "mpirank" : !write_rank ? "treeid" :
             "mpirank,treeid");
  }
  if (write_rank) {
    const int           wrapped_rank =
      wrap_rank > 0 ? mpirank % wrap_rank : mpirank;

    fprintf (vtufile, "        <DataArray type=\"%s\" Name=\"mpirank\""
             " format=\"%s\">\n", P4EST_VTK_LOCIDX, P4EST_VTK_FORMAT_STRING);
#ifdef P4EST_VTK_ASCII
    fprintf (vtufile, "         ");
    for (il = 0, sk = 1; il < Ncells; ++il, ++sk) {
      fprintf (vtufile, " %d", wrapped_rank);
      if (!(sk % 20) && il != (Ncells - 1))
        fprintf (vtufile, "\n         ");
    }
    fprintf (vtufile, "\n");
#else
    for (il = 0; il < Ncells; ++il)
      locidx_data[il] = (p4est_locidx_t) wrapped_rank;

    fprintf (vtufile, "          ");
    retval = p6est_vtk_write_binary (vtufile, (char *) locidx_data,
                                     sizeof (*locidx_data) * Ncells);
    fprintf (vtufile, "\n");
    if (retval) {
      P4EST_LERROR ("p6est_vtk: Error encoding types\n");
      fclose (vtufile);
      return -1;
    }
#endif
    fprintf (vtufile, "        </DataArray>\n");
  }
  if (write_tree) {
    fprintf (vtufile, "        <DataArray type=\"%s\" Name=\"treeid\""
             " format=\"%s\">\n", P4EST_VTK_LOCIDX, P4EST_VTK_FORMAT_STRING);
#ifdef P4EST_VTK_ASCII
    fprintf (vtufile, "         ");
    for (il = 0, sk = 1, jt = first_local_tree; jt <= last_local_tree; ++jt) {
      tree = p4est_tree_array_index (trees, jt);
      num_cols = tree->quadrants.elem_count;
      columns = &tree->quadrants;
      for (zz = 0; zz < num_cols; ++zz) {
        col = p4est_quadrant_array_index (columns, zz);
        P6EST_COLUMN_GET_RANGE (col, &first, &last);
        for (zy = first; zy < last; zy++, sk++, il++) {
          fprintf (vtufile, " %lld", (long long) jt);
          if (!(sk % 20) && il != (Ncells - 1))
            fprintf (vtufile, "\n         ");
        }
      }
    }
    fprintf (vtufile, "\n");
#else
    for (il = 0, jt = first_local_tree; jt <= last_local_tree; ++jt) {
      tree = p4est_tree_array_index (trees, jt);
      num_cols = tree->quadrants.elem_count;
      columns = &tree->quadrants;
      for (zz = 0; zz < num_cols; ++zz) {
        col = p4est_quadrant_array_index (columns, zz);
        P6EST_COLUMN_GET_RANGE (col, &first, &last);
        for (zy = first; zy < last; zy++, il++) {
          locidx_data[il] = (p4est_locidx_t) jt;
        }
      }
    }
    fprintf (vtufile, "          ");
    retval = p6est_vtk_write_binary (vtufile, (char *) locidx_data,
                                     sizeof (*locidx_data) * Ncells);
    fprintf (vtufile, "\n");
    if (retval) {
      P4EST_LERROR ("p6est_vtk: Error encoding types\n");
      fclose (vtufile);
      return -1;
    }
#endif
    fprintf (vtufile, "        </DataArray>\n");
    P4EST_ASSERT (il == Ncells);
  }
  if (write_rank || write_tree) {
    fprintf (vtufile, "      </CellData>\n");
  }
#ifndef P4EST_VTK_ASCII
  P4EST_FREE (locidx_data);
#endif

  fprintf (vtufile, "      <PointData");
  if (point_scalars != NULL)
    fprintf (vtufile, " Scalars=\"%s\"", point_scalars);
  if (point_vectors != NULL)
    fprintf (vtufile, " Vectors=\"%s\"", point_vectors);
  fprintf (vtufile, ">\n");

  if (ferror (vtufile)) {
    P4EST_LERROR ("p6est_vtk: Error writing header\n");
    fclose (vtufile);
    return -1;
  }
  if (fclose (vtufile)) {
    P4EST_LERROR ("p6est_vtk: Error closing header\n");
    return -1;
  }
  vtufile = NULL;

  /* Only have the root write to the parallel vtk file */
  if (mpirank == 0) {
    char                pvtufilename[BUFSIZ];
    FILE               *pvtufile;

    snprintf (pvtufilename, BUFSIZ, "%s.pvtu", filename);

    pvtufile = fopen (pvtufilename, "wb");
    if (!pvtufile) {
      P4EST_LERRORF ("Could not open %s for output\n", vtufilename);
      return -1;
    }

    fprintf (pvtufile, "<?xml version=\"1.0\"?>\n");
    fprintf (pvtufile, "<VTKFile type=\"PUnstructuredGrid\" version=\"0.1\"");
#if defined P4EST_VTK_BINARY && defined P4EST_VTK_COMPRESSION
    fprintf (pvtufile, " compressor=\"vtkZLibDataCompressor\"");
#endif
#ifdef SC_IS_BIGENDIAN
    fprintf (pvtufile, " byte_order=\"BigEndian\">\n");
#else
    fprintf (pvtufile, " byte_order=\"LittleEndian\">\n");
#endif

    fprintf (pvtufile, "  <PUnstructuredGrid GhostLevel=\"0\">\n");
    fprintf (pvtufile, "    <PPoints>\n");
    fprintf (pvtufile, "      <PDataArray type=\"%s\" Name=\"Position\""
             " NumberOfComponents=\"3\" format=\"%s\"/>\n",
             P4EST_VTK_FLOAT_NAME, P4EST_VTK_FORMAT_STRING);
    fprintf (pvtufile, "    </PPoints>\n");
    if (write_rank || write_tree) {
      fprintf (pvtufile, "    <PCellData Scalars=\"%s\">\n",
               !write_tree ? "mpirank" : !write_rank ? "treeid" :
               "mpirank,treeid");
    }
    if (write_rank) {
      fprintf (pvtufile, "      "
               "<PDataArray type=\"%s\" Name=\"mpirank\" format=\"%s\"/>\n",
               P4EST_VTK_LOCIDX, P4EST_VTK_FORMAT_STRING);
    }
    if (write_tree) {
      fprintf (pvtufile, "      "
               "<PDataArray type=\"%s\" Name=\"treeid\" format=\"%s\"/>\n",
               P4EST_VTK_LOCIDX, P4EST_VTK_FORMAT_STRING);
    }
    if (write_rank || write_tree) {
      fprintf (pvtufile, "    </PCellData>\n");
    }
    fprintf (pvtufile, "    <PPointData>\n");

    if (ferror (pvtufile)) {
      P4EST_LERROR ("p6est_vtk: Error writing parallel header\n");
      fclose (pvtufile);
      return -1;
    }
    if (fclose (pvtufile)) {
      P4EST_LERROR ("p6est_vtk: Error closing parallel header\n");
      return -1;
    }
  }

  return 0;
}
static void
curved_bi_est_dirichlet
(
 curved_element_data_t* e_m,
 int f_m,
 grid_fcn_t bndry_fcn,
 dgmath_jit_dbase_t* dgmath_jit_dbase,
 p4est_geometry_t* geom,
 void* params
)
{
  
  grid_fcn_t u_at_bndry = bndry_fcn;
  /* int vol_nodes_m = dgmath_get_nodes ( (P4EST_DIM) , e_m->deg ); */

  int face_nodes_m = dgmath_get_nodes( (P4EST_DIM) - 1, e_m->deg);
  double* u_m_on_f_m = P4EST_ALLOC(double, face_nodes_m);

  double* Je2 = P4EST_ALLOC(double, face_nodes_m);
  double* sje2 = P4EST_ALLOC(double, face_nodes_m);
  double* MJe2 = P4EST_ALLOC(double, face_nodes_m);

  double* xyz_on_f_m [(P4EST_DIM)];
  double* n_on_f_m [(P4EST_DIM)];
  double* du_m_on_f_m = P4EST_ALLOC(double, face_nodes_m);
  double* sj_on_f_m = P4EST_ALLOC(double, face_nodes_m);

  for (int d = 0; d < (P4EST_DIM); d++){
    xyz_on_f_m[d] = P4EST_ALLOC(double, face_nodes_m);
    n_on_f_m[d] = P4EST_ALLOC(double, face_nodes_m);
  }

  
  dgmath_apply_slicer(dgmath_jit_dbase,
                      e_m->u_elem,
                      (P4EST_DIM),
                      f_m,
                      e_m->deg,
                      u_m_on_f_m);


  for (int d = 0; d < (P4EST_DIM); d++){
    dgmath_apply_slicer
      (
       dgmath_jit_dbase,
       &e_m->xyz[d][0],
       (P4EST_DIM),
       f_m,
       e_m->deg,
       xyz_on_f_m[d]
      );
  }

  
  curved_element_data_compute_mortar_normal_and_sj_using_face_data
    (
     &e_m,
     1,
     1,
     &e_m->deg,
     f_m,
     n_on_f_m,
     sj_on_f_m,
     geom,
     dgmath_jit_dbase
    );  

  
  double h = (e_m->volume/e_m->surface_area[f_m]);
  /* find IP penalty parameter for each face pair of the two sides*/
  double Je2_prefactor = curved_bi_est_u_dirichlet_prefactor_calculate_fcn
                  (
                   e_m->deg,
                   h,
                   e_m->deg,
                   h,
                   curved_bi_est_sipg_flux_penalty_prefactor
                  );
    
  int dim;
  for (dim = 0; dim < (P4EST_DIM); dim++){
    /* calculate qstar - q(-) */
    for(int i = 0; i < face_nodes_m; i++){
      Je2[i] = Je2_prefactor*n_on_f_m[dim][i]*(u_m_on_f_m[i]
                                              -
                                              u_at_bndry
                                              (
                                               xyz_on_f_m[0][i],
                                               xyz_on_f_m[1][i]
#if (P4EST_DIM)==3
                                                ,
                                               xyz_on_f_m[2][i]
#endif
                                              )
                                             );
      sje2[i] = sj_on_f_m[i]*Je2[i];
    }

    dgmath_apply_Mij
      (
       dgmath_jit_dbase, 
       sje2,
       (P4EST_DIM) - 1,
       e_m->deg,
       MJe2
      );

    double Je2MJe2 = linalg_vec_dot(Je2, MJe2, face_nodes_m);
    e_m->local_estimator += Je2MJe2;
  }

  for (int d = 0; d < (P4EST_DIM); d++){
    P4EST_FREE(n_on_f_m[d]);
    P4EST_FREE(xyz_on_f_m[d]);
  }

  P4EST_FREE(du_m_on_f_m);
  P4EST_FREE(Je2);
  P4EST_FREE(sje2);
  P4EST_FREE(MJe2);
  P4EST_FREE(u_m_on_f_m);
  P4EST_FREE(sj_on_f_m);
}
예제 #27
0
void
p6est_vtk_write_all (p6est_t * p6est,
                     double scale, int write_tree,
                     int write_rank, int wrap_rank,
                     int num_scalars, int num_vectors,
                     const char *filename, ...)
{
  int                 retval;
  int                 i, all;
  int                 scalar_strlen, vector_strlen;
  char                point_scalars[BUFSIZ], point_vectors[BUFSIZ];
  const char         *name, **names;
  double            **values;
  va_list             ap;

  P4EST_ASSERT (num_scalars >= 0 && num_vectors >= 0);

  values = P4EST_ALLOC (double *, num_scalars + num_vectors);
  names = P4EST_ALLOC (const char *, num_scalars + num_vectors);

  va_start (ap, filename);
  all = 0;
  scalar_strlen = 0;
  point_scalars[0] = '\0';
  for (i = 0; i < num_scalars; ++all, ++i) {
    name = names[all] = va_arg (ap, const char *);
    retval = snprintf (point_scalars + scalar_strlen, BUFSIZ - scalar_strlen,
                       "%s%s", i == 0 ? "" : ",", name);
    SC_CHECK_ABORT (retval > 0, "p6est_vtk: Error collecting point scalars");
    scalar_strlen += retval;
    values[all] = va_arg (ap, double *);
  }
  vector_strlen = 0;
  point_vectors[0] = '\0';
  for (i = 0; i < num_vectors; ++all, ++i) {
    name = names[all] = va_arg (ap, const char *);
    retval = snprintf (point_vectors + vector_strlen, BUFSIZ - vector_strlen,
                       "%s%s", i == 0 ? "" : ",", name);
    SC_CHECK_ABORT (retval > 0, "p6est_vtk: Error collecting point vectors");
    vector_strlen += retval;
    values[all] = va_arg (ap, double *);
  }
  va_end (ap);

  retval = p6est_vtk_write_header (p6est, scale,
                                   write_tree, write_rank, wrap_rank,
                                   num_scalars > 0 ? point_scalars : NULL,
                                   num_vectors > 0 ? point_vectors : NULL,
                                   filename);
  SC_CHECK_ABORT (!retval, "p6est_vtk: Error writing header");

  all = 0;
  for (i = 0; i < num_scalars; ++all, ++i) {
    retval = p6est_vtk_write_point_scalar (p6est, filename,
                                           names[all], values[all]);
    SC_CHECK_ABORT (!retval, "p6est_vtk: Error writing point scalars");
  }
  for (i = 0; i < num_vectors; ++all, ++i) {
    retval = p6est_vtk_write_point_vector (p6est, filename,
                                           names[all], values[all]);
    SC_CHECK_ABORT (!retval, "p6est_vtk: Error writing point vectors");
  }

  retval = p6est_vtk_write_footer (p6est, filename);
  SC_CHECK_ABORT (!retval, "p6est_vtk: Error writing footer");

  P4EST_FREE (values);
  P4EST_FREE (names);
}
static void
curved_bi_est_interface
(
 curved_element_data_t** e_m,
 int faces_m,
 int f_m,
 curved_element_data_t** e_p,
 int faces_p,
 int f_p,
 int* e_m_is_ghost,
 int orientation,
 dgmath_jit_dbase_t* dgmath_jit_dbase,
 p4est_geometry_t* geom,
 void* params
)
{ 
  int stride;
  int deg_p [(P4EST_HALF)];
  int max_deg_p = -1;
  int face_nodes_p [(P4EST_HALF)];
  int deg_m [(P4EST_HALF)];
  int face_nodes_m [(P4EST_HALF)];
  int max_deg_m = -1;
  int nodes_mortar [(P4EST_HALF)];
  int deg_mortar [(P4EST_HALF)];
  int faces_mortar = (faces_m > faces_p) ? faces_m : faces_p;
  double Je1_prefactor_mortar [(P4EST_HALF)];
  double Je2_prefactor_mortar [(P4EST_HALF)];

  curved_element_data_t* e_p_oriented [(P4EST_HALF)];
  curved_element_data_reorient_f_p_elements_to_f_m_order(e_p, (P4EST_DIM)-1, f_m, f_p, orientation, faces_p, e_p_oriented);
  
  /* calculate degs and nodes of each face of (-) side */
  int total_side_nodes_m = 0;
  for (int i = 0; i < faces_m; i++){
    deg_m[i] = e_m[i]->deg;
    if (e_m[i]->deg > max_deg_m) max_deg_m = e_m[i]->deg;
    face_nodes_m[i] = dgmath_get_nodes( (P4EST_DIM) - 1, e_m[i]->deg );
    total_side_nodes_m += face_nodes_m[i];
  }

  /* calculate degs and nodes of each face of (+) side  */
  int total_side_nodes_p = 0;
  for (int i = 0; i < faces_p; i++){
    deg_p[i] = e_p_oriented[i]->deg;
    if (e_p_oriented[i]->deg > max_deg_p) max_deg_p = e_p_oriented[i]->deg;
    face_nodes_p[i] = dgmath_get_nodes( (P4EST_DIM) - 1, e_p_oriented[i]->deg );
    total_side_nodes_p += face_nodes_p[i];
  }    

  /* calculate degs and nodes of the mortar faces */
  int total_nodes_mortar = 0;
  for (int i = 0; i < faces_m; i++)
    for (int j = 0; j < faces_p; j++){
      /* find max degree for each face pair of the two sides*/
      deg_mortar[i+j] = util_max_int( e_m[i]->deg, e_p_oriented[j]->deg );
      nodes_mortar[i+j] = dgmath_get_nodes( (P4EST_DIM) - 1, deg_mortar[i+j] );     
      total_nodes_mortar += nodes_mortar[i+j];
      double h = util_min((e_m[i]->volume/e_m[i]->surface_area[f_m]), (e_p_oriented[j]->volume/e_p_oriented[j]->surface_area[f_p]));

      Je1_prefactor_mortar[i+j] =  curved_bi_est_gradu_prefactor_calculate_fcn
                                   (
                                    deg_mortar[i+j],
                                    h,
                                    deg_mortar[i+j],
                                    h,
                                    curved_bi_est_sipg_flux_penalty_prefactor
                                   );    
    
      Je2_prefactor_mortar[i+j] = curved_bi_est_u_prefactor_calculate_fcn
                                  (
                                   deg_mortar[i+j],
                                   h,
                                   deg_mortar[i+j],
                                   h,
                                   curved_bi_est_sipg_flux_penalty_prefactor
                                  );    
      
    }

  /* slices of scalar/vector fields of (-) onto f_m and (+) onto f_p */
  double* u_m_on_f_m = P4EST_ALLOC(double, total_side_nodes_m);
  double* u_p_on_f_p = P4EST_ALLOC(double, total_side_nodes_p);
  double* du_m_on_f_m [(P4EST_DIM)]; 
  double* du_p_on_f_p [(P4EST_DIM)]; 

  for (int d = 0; d < (P4EST_DIM); d++){
    du_m_on_f_m[d] = P4EST_ALLOC(double, total_side_nodes_m);
    du_p_on_f_p[d] = P4EST_ALLOC(double, total_side_nodes_p);
  }
  
  /* projections of f_m slices to max_deg space */
  double* u_m_on_f_m_mortar = P4EST_ALLOC(double, total_nodes_mortar);
  double* u_p_on_f_p_mortar = P4EST_ALLOC(double, total_nodes_mortar);
  double* du_m_on_f_m_mortar [(P4EST_DIM)];
  double* du_p_on_f_p_mortar [(P4EST_DIM)];
  
  for (int d = 0; d < (P4EST_DIM); d++){
    du_m_on_f_m_mortar[d] = P4EST_ALLOC(double, total_nodes_mortar);
    du_p_on_f_p_mortar[d] = P4EST_ALLOC(double, total_nodes_mortar);
  }
  
  double* Je1 = P4EST_ALLOC_ZERO(double, total_nodes_mortar);
  double* sje1 = P4EST_ALLOC_ZERO(double, total_nodes_mortar);
  double* MJe1 = P4EST_ALLOC(double, total_nodes_mortar);

  double* Je2 [(P4EST_DIM)]; /* = P4EST_ALLOC_ZERO(double, total_nodes_mortar); */
  double* sje2 [(P4EST_DIM)];
  
  for (int d = 0; d < (P4EST_DIM); d++) {
    Je2[d] = P4EST_ALLOC(double, total_nodes_mortar);
    sje2[d] = P4EST_ALLOC(double, total_nodes_mortar);
  }

  double* MJe2 = P4EST_ALLOC(double, total_nodes_mortar);
  
  double* tmp = P4EST_ALLOC(double, total_side_nodes_p);
  double* sj_on_f_m_mortar = P4EST_ALLOC(double, total_nodes_mortar);
  double* n_on_f_m_mortar [(P4EST_DIM)];
  
  for (int d = 0; d < (P4EST_DIM); d++){
    n_on_f_m_mortar[d] = P4EST_ALLOC(double, total_nodes_mortar);
  }

  stride = 0;
  for (int i = 0; i < faces_m; i++){   
    dgmath_apply_slicer
      (
       dgmath_jit_dbase,
       &(e_m[i]->u_elem[0]),
       (P4EST_DIM),
       f_m,
       e_m[i]->deg,
       &u_m_on_f_m[stride]
      );
    stride += face_nodes_m[i];
  }
 
  stride = 0;
  for (int i = 0; i < faces_p; i++){
    dgmath_apply_slicer
      (
       dgmath_jit_dbase,
       &(e_p_oriented[i]->u_elem[0]),
       (P4EST_DIM),
       f_p,
       e_p_oriented[i]->deg,
       tmp
      );
    
    dgmath_reorient_face_data
      (
       dgmath_jit_dbase,
       tmp,
       ((P4EST_DIM) - 1),
       e_p_oriented[i]->deg,
       orientation,
       f_m,
       f_p,
       &u_p_on_f_p[stride]
      );
    stride += face_nodes_p[i];
  }


  /* project (-)-side u trace vector onto mortar space */
  dgmath_project_side_onto_mortar_space
    (
     dgmath_jit_dbase,
     u_m_on_f_m,
     faces_m,
     deg_m,
     u_m_on_f_m_mortar,
     faces_mortar,
     deg_mortar
    );

  /* project (+)-side u trace vector onto mortar space */
  dgmath_project_side_onto_mortar_space
    (
     dgmath_jit_dbase,
     u_p_on_f_p,
     faces_p,
     deg_p,
     u_p_on_f_p_mortar,
     faces_mortar,
     deg_mortar
    );
  
  
  /* For each component of the vector */
  for (int d = 0; d < (P4EST_DIM); d++){

    /* project (-)-u-derivative on the (-)-side faces and project q onto the (-)-side faces */
    stride = 0;
    for (int i = 0; i < faces_m; i++){
      dgmath_apply_slicer
        (
         dgmath_jit_dbase,
         &e_m[i]->du_elem[d][0],
         (P4EST_DIM),
         f_m,
         e_m[i]->deg,
         &du_m_on_f_m[d][stride]
        );
    
      stride += face_nodes_m[i];
    }
    
    for (int i = 0; i < faces_p; i++){
      dgmath_apply_slicer
        (
         dgmath_jit_dbase,
         &e_p_oriented[i]->du_elem[d][0],
         (P4EST_DIM),
         f_p,
         e_p_oriented[i]->deg,
         tmp
        );

      dgmath_reorient_face_data
        (
         dgmath_jit_dbase,
         tmp,
         ((P4EST_DIM) - 1),
         e_p_oriented[i]->deg,
         orientation,
         f_m,
         f_p,
         &du_p_on_f_p[d][stride]
        );

      stride += face_nodes_p[i];
    }

    /* project the derivatives from (-) and (+) sides onto the mortar space */
    dgmath_project_side_onto_mortar_space
      (
       dgmath_jit_dbase,
       du_m_on_f_m[d],
       faces_m,
       deg_m,
       du_m_on_f_m_mortar[d],
       faces_mortar,
       deg_mortar
      );

    dgmath_project_side_onto_mortar_space
      (
       dgmath_jit_dbase,
       du_p_on_f_p[d],
       faces_p,
       deg_p,
       du_p_on_f_p_mortar[d],
       faces_mortar,
       deg_mortar
      );

  }
  
  curved_element_data_compute_mortar_normal_and_sj_using_face_data
    (
     e_m,
     faces_m,
     faces_mortar,
     &deg_mortar[0],
     f_m,
     n_on_f_m_mortar,
     sj_on_f_m_mortar,
     geom,
     dgmath_jit_dbase
    );

    /* calculate symmetric interior penalty flux */
    int k;
    int f;
    int ks;
    double n_ks;
    double sj_ks;
    stride = 0;
    for (f = 0; f < faces_mortar; f++){
      for (k = 0; k < nodes_mortar[f]; k++){
        ks = k + stride;
        sj_ks = sj_on_f_m_mortar[ks];
        Je1[ks] = 0.;
        sje1[ks] = 0.;
        for (int d = 0; d < (P4EST_DIM); d++){
          n_ks = n_on_f_m_mortar[d][ks];        
          Je1[ks] += Je1_prefactor_mortar[f]*n_ks*
                     (du_m_on_f_m_mortar[d][ks] - du_p_on_f_p_mortar[d][ks]);
          sje1[ks] += sj_ks*Je1_prefactor_mortar[f]*n_ks*
                      (du_m_on_f_m_mortar[d][ks] - du_p_on_f_p_mortar[d][ks]);

          Je2[d][ks] = n_ks*u_m_on_f_m_mortar[ks];
          Je2[d][ks] -= n_ks*u_p_on_f_p_mortar[ks];
          Je2[d][ks] *= Je2_prefactor_mortar[f];
          sje2[d][ks] = sj_ks*Je2[d][ks];
        }
      }
      stride += nodes_mortar[f];
    }

    /* the contribution in every direction must be added up due to it being a vector norm */
    stride = 0;
    for (f = 0; f < faces_mortar; f++){
      for (int d = 0; d < (P4EST_DIM); d++){
        dgmath_apply_Mij
          (
           dgmath_jit_dbase,
           &sje2[d][stride],
           (P4EST_DIM) - 1,
           deg_mortar[f],
           &MJe2[stride]
          );

        /* even if it's a ghost we can still add it to the ghosts estimator because we will not send it back! */
        double Je2MJe2 = linalg_vec_dot(&Je2[d][stride], &MJe2[stride], nodes_mortar[f]);
        if(faces_m == (P4EST_HALF)){
          e_m[f]->local_estimator += Je2MJe2;    
        }
        else{
          e_m[0]->local_estimator += Je2MJe2;
        }
      }
      stride += nodes_mortar[f];
    }

  stride = 0;
  for (f = 0; f < faces_mortar; f++){  
    dgmath_apply_Mij
      (
       dgmath_jit_dbase,
       &sje1[stride],
       (P4EST_DIM) - 1,
       deg_mortar[f],
       &MJe1[stride]
      );

    double Je1MJe1 = linalg_vec_dot(&Je1[stride], &MJe1[stride], nodes_mortar[f]);

    /* even if it's a ghost we can still add it to the ghosts estimator because we will not send it back! */
      if(faces_m == (P4EST_HALF)){
        e_m[f]->local_estimator += Je1MJe1;   
      }
      else{
        e_m[0]->local_estimator += Je1MJe1;   
      }
    stride += nodes_mortar[f];
  }

  P4EST_FREE(tmp);
  
  for (int i = 0; i < (P4EST_DIM); i++){
    P4EST_FREE(n_on_f_m_mortar[i]);
    P4EST_FREE(du_m_on_f_m_mortar[i]);
    P4EST_FREE(du_m_on_f_m[i]);
    P4EST_FREE(du_p_on_f_p[i]);
    P4EST_FREE(du_p_on_f_p_mortar[i]);
    P4EST_FREE(Je2[i]);
    P4EST_FREE(sje2[i]);
  }
  
  P4EST_FREE(sje1);
  P4EST_FREE(Je1);
  P4EST_FREE(MJe1);
  P4EST_FREE(MJe2);
  P4EST_FREE(u_p_on_f_p_mortar);
  P4EST_FREE(u_m_on_f_m_mortar);
  P4EST_FREE(u_p_on_f_p);
  P4EST_FREE(sj_on_f_m_mortar);
  P4EST_FREE(u_m_on_f_m);
}
예제 #29
0
int main(int argc, char *argv[])
{
  int mpiret;
  sc_MPI_Comm mpicomm;
  int proc_size;

  p4est_connectivity_t *conn;
  p4est_geometry_t *geom;
  p4est_t* p4est;
  
  int seed = time(NULL);
  srand(seed);
  
  /* MPI init */
  mpiret = sc_MPI_Init(&argc, &argv);
  SC_CHECK_MPI(mpiret);
  mpicomm = sc_MPI_COMM_WORLD;
  sc_init (mpicomm, 1, 1, NULL, SC_LP_ESSENTIAL);
  mpiret = MPI_Comm_size(mpicomm, &proc_size);
  SC_CHECK_MPI (mpiret);
  /* pXest init */
  p4est_init(NULL, SC_LP_PRODUCTION);


  conn = p4est_connectivity_new_disk();
  /* geom = p4est_geometry_new_connectivity(conn); */
  geom = p4est_geometry_new_disk(conn,1.,2.);

  p4est = p4est_new_ext (mpicomm, conn, -1, 0, 1,
                         sizeof(curved_element_data_t), NULL, NULL);

  int world_rank,world_size;
  sc_MPI_Comm_rank(sc_MPI_COMM_WORLD, &world_rank);
  sc_MPI_Comm_size(sc_MPI_COMM_WORLD, &world_size);
  
  /* start just-in-time dg-math */
  dgmath_jit_dbase_t* dgmath_jit_dbase = dgmath_jit_dbase_init();
  geometric_factors_t* geometric_factors = geometric_factors_init(p4est);
  
  curved_element_data_init(p4est, geometric_factors, dgmath_jit_dbase, geom, 4);
  /* int local_nodes = curved_element_data_get_local_nodes(p4est); */
  /* double* u = P4EST_ALLOC(double, local_nodes); */

  /* for (int i = 0; i < local_nodes; i++){ */
  /*   /\* u = x *\/ */
  /*   u[i] = geometric_factors->xyz[i]; */
  /* } */
  
  int num_of_refinements = 2;
  /* p4est_vtk_write_all */
  /*   (p4est, */
  /*    geom, */
  /*    0.99, */
  /*    1, */
  /*    1, */
  /*    1, */
  /*    0, */
  /*    0, */
  /*    0, */
  /*    "disk0" */
  /*   ); */
  for (int i = 0; i < num_of_refinements; i++){
    p4est_refine_ext (p4est, 0, -1, random_h_refine, NULL, refine_uniform_replace_callback);
    p4est_balance_ext(p4est, P4EST_CONNECT_FACE, NULL, refine_uniform_replace_callback);
    /* p4est_vtk_write_all */
    /*   (p4est, */
    /*    geom, */
    /*    0.99, */
    /*    1, */
    /*    1, */
    /*    1, */
    /*    0, */
    /*    0, */
    /*    0, */
    /*    "disk" */
    /*   ); */
  }

  curved_element_data_init(p4est, geometric_factors, dgmath_jit_dbase, geom, -1);
  int local_nodes = curved_element_data_get_local_nodes(p4est);
  double* u = P4EST_ALLOC(double, local_nodes);

  for (int i = 0; i < local_nodes; i++){
    /* u = x */
    u[i] = geometric_factors->xyz[i];
  }
  
  

  /* curved_element_data_init(p4est, geometric_factors, dgmath_jit_dbase, geom, -1); */

  /* store vector */
  curved_element_data_copy_from_vec_to_storage
    (
     p4est,
     u
    );
  
  test_curved_data_t test_curved_data;
  test_curved_data.mortar_err = 0.;
  test_curved_data.hanging_proj_err = 0.;
  test_curved_data.full_proj_err = 0.;
  test_curved_data.print_data = 1;
  test_curved_data.no_reorient = 0;
  test_curved_data.geom = geom;

  p4est_ghost_t* ghost = p4est_ghost_new (p4est, P4EST_CONNECT_FACE);
  /* create space for storing the ghost data */
  curved_element_data_t* ghost_data = P4EST_ALLOC (curved_element_data_t,
                                                   ghost->ghosts.elem_count);
  
  p4est_ghost_exchange_data (p4est, ghost, ghost_data);
  curved_compute_flux_user_data_t curved_compute_flux_user_data;
  curved_compute_flux_user_data.dgmath_jit_dbase = dgmath_jit_dbase;  

  curved_flux_fcn_ptrs_t flux_fcns = (test_curved_data_fetch_fcns(&test_curved_data));

  curved_compute_flux_user_data.flux_fcn_ptrs = &flux_fcns;
  p4est->user_pointer = &curved_compute_flux_user_data;
  
  p4est_iterate (p4est,
  		 ghost,
  		 (void *) ghost_data,
  		 NULL,
                 curved_compute_flux_on_local_elements,
#if (P4EST_DIM)==3
                 NULL,
#endif
                 NULL);  

  test_curved_data.mortar_err = 0.;
  
  if (world_rank == 0)
    printf("mortar_err = %.20f\n",
           test_curved_data.mortar_err
          );
 
  p4est_ghost_destroy (ghost);
  P4EST_FREE (ghost_data);
  ghost = NULL;
  ghost_data = NULL;
  /* curved_hp_amr(p4est, */
  /*               &u, */
  /*               test_nonconform_random_hp, */
  /*               NULL, */
  /*               NULL, */
  /*               NULL, */
  /*               dgmath_jit_dbase */
  /*              ); */

  /*   curved_element_data_init(p4est, geometric_factors, dgmath_jit_dbase, geom, -1); */
    
  /* double* u_vertex = P4EST_ALLOC(double, p4est->local_num_quadrants*(P4EST_CHILDREN)); */

  /* element_data_store_nodal_vec_in_vertex_array */
  /*   ( */
  /*    p4est, */
  /*    u, */
  /*    u_vertex */
  /*   ); */

  /* char sol_save_as [500]; */
  /* sprintf(sol_save_as, "%s_test_nonconform_sym_level_%d_u", P4EST_STRING, i); */
    
  /* curved_hacked_p4est_vtk_write_all */
  /*   (p4est, */
  /*    NULL, */
  /*    0.99, */
  /*    0,    */
  /*    1,    */
  /*    1,    */
  /*    0, */
  /*    1, */
  /*    0, */
  /*    sol_save_as, */
  /*    "u", */
  /*    u_vertex */
  /*   ); */

  /* P4EST_FREE(u_vertex);    */

    
  /* ip_flux_params_t ip_flux_params; */
  /* ip_flux_params.ip_flux_penalty_prefactor = atoi(argv[6]); */
  /* ip_flux_params.ip_flux_penalty_calculate_fcn = sipg_flux_vector_calc_penalty_maxp2_over_minh; */


  /* problem_data_t vecs; */
  /* vecs.u = u; */
  /* vecs.local_nodes = element_data_get_local_nodes(p4est); */
  /* vecs.vector_flux_fcn_data = sipg_flux_vector_dirichlet_fetch_fcns */
  /* ( */
  /* zero_fcn, */
  /* &ip_flux_params */
  /* ); */
  /* vecs.scalar_flux_fcn_data = sipg_flux_scalar_dirichlet_fetch_fcns(zero_fcn); */

  /* weakeqn_ptrs_t fcns; */
  /* fcns.apply_lhs = poisson_apply_aij; */

  /* matrix_sym_tester */
  /*   ( */
  /*    p4est, */
  /*    &vecs, /\* only needed for # of nodes *\/ */
  /*    &fcns, */
  /*    .000000000000001, */
  /*    dgmath_jit_dbase, */
  /*    0, */
  /*    0 */
  /*   ); */

  /* } */
  
  P4EST_FREE(u);
  geometric_factors_destroy(geometric_factors);
  /* free pointers */
  dgmath_jit_dbase_destroy(dgmath_jit_dbase);
  
  /* free pXest */
  p4est_destroy(p4est);
  /* p4est_destroy(p4est); */
  if (geom != NULL) {
    p4est_geometry_destroy (geom);
  }
  p4est_connectivity_destroy(conn);

  /* finalize mpi stuff */  
  sc_finalize();
  mpiret = sc_MPI_Finalize ();
  SC_CHECK_MPI(mpiret);  
}
static void
curved_sipg_weak_flux_vector_dirichlet
(
 curved_element_data_t* e_m,
 int f_m,
 grid_fcn_t bndry_fcn,
 dgmath_jit_dbase_t* dgmath_jit_dbase,
 p4est_geometry_t* geom,
 void* params
)
{
  ip_flux_params_t* ip_params = (ip_flux_params_t*) params;
  double curved_sipg_weak_flux_penalty_prefactor = ip_params->ip_flux_penalty_prefactor;
  penalty_calc_t curved_sipg_weak_flux_penalty_calculate_fcn = ip_params->ip_flux_penalty_calculate_fcn;
  
  grid_fcn_t u_at_bndry = bndry_fcn;
  int face_nodes_m = dgmath_get_nodes ( (P4EST_DIM) - 1, e_m->deg );
  /* int vol_nodes_m = dgmath_get_nodes ( (P4EST_DIM) , e_m->deg ); */

  double* u_m_on_f_m = P4EST_ALLOC(double, face_nodes_m);
  double* du_m_on_f_m [(P4EST_DIM)];
  double* q_m_on_f_m [(P4EST_DIM)]; 
  double* xyz_on_f_m [(P4EST_DIM)];
  
  for (int i = 0; i < (P4EST_DIM); i++) {
    du_m_on_f_m[i] = P4EST_ALLOC(double, face_nodes_m);
    q_m_on_f_m[i] = P4EST_ALLOC(double, face_nodes_m);
    xyz_on_f_m[i] = P4EST_ALLOC(double, face_nodes_m);
  }

  double* sj_qstar_min_q_dot_n = P4EST_ALLOC_ZERO(double, face_nodes_m);
  double* u_on_f_m_min_u_at_bndry = P4EST_ALLOC(double, face_nodes_m);
  double* sj_on_f_m = P4EST_ALLOC(double, face_nodes_m);
  double* n_on_f_m [(P4EST_DIM)];

  for (int d = 0; d < (P4EST_DIM); d++){
    n_on_f_m[d] = P4EST_ALLOC(double, face_nodes_m);
  }

  /* get solution variable on this face */
  dgmath_apply_slicer(dgmath_jit_dbase, e_m->u_elem, (P4EST_DIM), f_m, e_m->deg, u_m_on_f_m);

  for (int d = 0; d < (P4EST_DIM); d++){
    dgmath_apply_slicer(dgmath_jit_dbase, e_m->xyz[d], (P4EST_DIM), f_m, e_m->deg, xyz_on_f_m[d]);
    dgmath_apply_slicer(dgmath_jit_dbase, e_m->du_elem[d], (P4EST_DIM), f_m, e_m->deg, du_m_on_f_m[d]);
    dgmath_apply_slicer(dgmath_jit_dbase, e_m->q_elem[d], (P4EST_DIM), f_m, e_m->deg, q_m_on_f_m[d]);
  }    


  curved_element_data_compute_mortar_normal_and_sj_using_face_data
    (
     &e_m,
     1,
     1,
     &e_m->deg,
     f_m,
     n_on_f_m,
     sj_on_f_m,
     geom,
     dgmath_jit_dbase
    );

  double h = (e_m->volume/e_m->surface_area[f_m]);  
  double penalty = curved_sipg_weak_flux_penalty_calculate_fcn
                   (
                    e_m->deg,
                    h,
                    e_m->deg,
                    h,
                    curved_sipg_weak_flux_penalty_prefactor
                   );

  
  /* get boundary values on this face */
  for (int i = 0; i < face_nodes_m; i++){
    u_on_f_m_min_u_at_bndry[i] = u_m_on_f_m[i] - u_at_bndry(
                                                            xyz_on_f_m[0][i],
                                                            xyz_on_f_m[1][i]
#if (P4EST_DIM)==3
                                                            ,
                                                            xyz_on_f_m[2][i]
#endif
    );
  }
  
  for(int i = 0; i < face_nodes_m; i++){
    double qstar_min_q [(P4EST_DIM)];
    for (int d = 0; d < (P4EST_DIM); d++){
      qstar_min_q[d] = du_m_on_f_m[d][i]
                       - penalty*n_on_f_m[d][i]*(u_on_f_m_min_u_at_bndry[i]);
    }
    sj_qstar_min_q_dot_n[i] = 0.;
    for (int d = 0; d < (P4EST_DIM); d++){
      sj_qstar_min_q_dot_n[i] += sj_on_f_m[i]*n_on_f_m[d][i]*qstar_min_q[d];
    }
  }
  
  dgmath_apply_Mij
    (
     dgmath_jit_dbase,
     sj_qstar_min_q_dot_n,
     (P4EST_DIM) - 1,
     e_m->deg,
     &e_m->M_qstar_min_q_dot_n[f_m*face_nodes_m]
    );


  P4EST_FREE(u_m_on_f_m);
  for (int i = 0; i < (P4EST_DIM); i++) {
    P4EST_FREE(du_m_on_f_m[i]);
    P4EST_FREE(q_m_on_f_m[i]);
    P4EST_FREE(xyz_on_f_m[i]);
  }

  P4EST_FREE(sj_on_f_m);
  P4EST_FREE(u_on_f_m_min_u_at_bndry);
  P4EST_FREE(sj_qstar_min_q_dot_n);
  
  for (int d = 0; d < (P4EST_DIM); d++){
    P4EST_FREE(n_on_f_m[d]);
  }


  
  

  
}