void p6est_profile_element_to_node (p6est_t * p6est, p6est_profile_t * profile, p4est_locidx_t * offsets, p4est_locidx_t * elem_to_node, p6est_lnodes_code_t * fc) { p4est_topidx_t jt; p4est_t *columns = p6est->columns; p4est_tree_t *tree; p4est_quadrant_t *col; sc_array_t *tquadrants; p4est_locidx_t (*lr)[2] = (p4est_locidx_t (*)[2]) profile->lnode_ranges; p4est_locidx_t cid; size_t zz; p6est_lnodes_code_t mask = 0x1fe0; p6est_lnodes_code_t hbit = 0x0010; int degree = profile->lnodes->degree; int Nrp = (degree + 1); int Nfp = (degree + 1) * (degree + 1); sc_array_t *layers = p6est->layers; for (cid = 0, jt = columns->first_local_tree; jt <= columns->last_local_tree; ++jt) { tree = p4est_tree_array_index (columns->trees, jt); tquadrants = &tree->quadrants; for (zz = 0; zz < tquadrants->elem_count; ++zz, cid++) { p4est_locidx_t nlayers; p4est_locidx_t nid = profile->lnodes->element_nodes[Nfp * cid + Nrp * (Nrp / 2) + (Nrp / 2)]; size_t first, last, zw, zy; col = p4est_quadrant_array_index (tquadrants, zz); P6EST_COLUMN_GET_RANGE (col, &first, &last); nlayers = lr[nid][1]; p6est_profile_element_to_node_col (profile, cid, offsets, elem_to_node, fc); elem_to_node += nlayers * (degree + 1) * (degree + 1) * (degree + 1); for (zy = 0, zw = first; zw < last; zw++, zy++) { if (fc[zy] & mask) { /* this layer has vertical half faces, we need to set the bit that * says whether this is the upper half or the lower half */ p2est_quadrant_t *layer; layer = p2est_quadrant_array_index (layers, zw); if (layer->z & P4EST_QUADRANT_LEN (layer->level)) { /* upper half of a pair of layers */ fc[zy] |= hbit; } } } fc += nlayers; } } }
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; }
p6est_profile_t * p6est_profile_new_local (p6est_t * p6est, p6est_ghost_t * ghost, p6est_profile_type_t ptype, p8est_connect_type_t btype, int degree) { p6est_profile_t *profile = P4EST_ALLOC (p6est_profile_t, 1); p4est_lnodes_t *lnodes; p4est_locidx_t nln, nle; p4est_topidx_t jt; p4est_t *columns = p6est->columns; p4est_tree_t *tree; sc_array_t *tquadrants; p4est_quadrant_t *col; p4est_qcoord_t diff = P4EST_ROOT_LEN - p6est->root_len; size_t first, last, count, zz, zy; p4est_locidx_t *en, (*lr)[2]; sc_array_t *lc; int i, j; p2est_quadrant_t *layer; sc_array_t *layers = p6est->layers; p4est_locidx_t nidx, enidx; p4est_connect_type_t hbtype; int8_t *c; sc_array_t *thisprof; sc_array_t *selfprof; sc_array_t *faceprof; sc_array_t *cornerprof; sc_array_t *work; sc_array_t oldprof; const int Nrp = degree + 1; P4EST_ASSERT (degree > 1); profile->ptype = ptype; profile->btype = btype; profile->lnode_changed[0] = NULL; profile->lnode_changed[1] = NULL; profile->enode_counts = NULL; profile->diff = diff; if (btype == P8EST_CONNECT_FACE) { hbtype = P4EST_CONNECT_FACE; } else { hbtype = P4EST_CONNECT_FULL; } if (ghost == NULL) { profile->cghost = p4est_ghost_new (p6est->columns, P4EST_CONNECT_FULL); profile->ghost_owned = 1; } else { P4EST_ASSERT (ghost->column_ghost->btype == P4EST_CONNECT_FULL); profile->cghost = ghost->column_ghost; profile->ghost_owned = 0; } if (ptype == P6EST_PROFILE_UNION) { P4EST_ASSERT (degree == 2); } profile->lnodes = lnodes = p4est_lnodes_new (p6est->columns, profile->cghost, degree); en = lnodes->element_nodes; nln = lnodes->num_local_nodes; nle = lnodes->num_local_elements; profile->lnode_ranges = P4EST_ALLOC_ZERO (p4est_locidx_t, 2 * nln); lr = (p4est_locidx_t (*)[2]) profile->lnode_ranges; profile->lnode_columns = lc = sc_array_new (sizeof (int8_t)); selfprof = sc_array_new (sizeof (int8_t)); work = sc_array_new (sizeof (int8_t)); faceprof = sc_array_new (sizeof (int8_t)); cornerprof = sc_array_new (sizeof (int8_t)); if (ptype == P6EST_PROFILE_UNION) { profile->lnode_changed[0] = P4EST_ALLOC (p4est_locidx_t, nln); profile->lnode_changed[1] = P4EST_ALLOC (p4est_locidx_t, nln); profile->enode_counts = P4EST_ALLOC (p4est_locidx_t, P4EST_INSUL * nle); profile->evenodd = 0; memset (profile->lnode_changed[0], -1, nln * sizeof (int)); } /* create the profiles for each node: layers are reduced to just their level * */ for (enidx = 0, jt = columns->first_local_tree; jt <= columns->last_local_tree; ++jt) { tree = p4est_tree_array_index (columns->trees, jt); tquadrants = &tree->quadrants; for (zz = 0; zz < tquadrants->elem_count; ++zz) { col = p4est_quadrant_array_index (tquadrants, zz); P6EST_COLUMN_GET_RANGE (col, &first, &last); count = last - first; sc_array_truncate (selfprof); c = (int8_t *) sc_array_push_count (selfprof, count); for (zy = first; zy < last; zy++) { layer = p2est_quadrant_array_index (layers, zy); *(c++) = layer->level; } if (ptype == P6EST_PROFILE_UNION) { p6est_profile_balance_self (selfprof, work); if (btype == P8EST_CONNECT_FACE) { p6est_profile_balance_face (selfprof, faceprof, work, diff); } else { p6est_profile_balance_full (selfprof, faceprof, work, diff); } if (btype == P8EST_CONNECT_EDGE) { p6est_profile_balance_face (selfprof, cornerprof, work, diff); } else if (btype == P8EST_CONNECT_FULL) { p6est_profile_balance_full (selfprof, cornerprof, work, diff); } } for (j = 0; j < Nrp; j++) { for (i = 0; i < Nrp; i++, enidx++) { nidx = en[enidx]; if (ptype == P6EST_PROFILE_UNION) { thisprof = NULL; if (!(i % degree) && !(j % degree)) { if (hbtype == P4EST_CONNECT_FACE) { /* skip corners if we don't need to balance them */ P4EST_ASSERT (!lr[nidx][0]); P4EST_ASSERT (!lr[nidx][1]); continue; } else { thisprof = cornerprof; } } else if ((i % degree) && (j % degree)) { thisprof = selfprof; } else { thisprof = faceprof; } count = thisprof->elem_count; profile->enode_counts[enidx] = count; if (!lr[nidx][1]) { /* if this node has not yet been initialized, initialize it */ lr[nidx][0] = lc->elem_count; lr[nidx][1] = count; c = (int8_t *) sc_array_push_count (lc, count); memcpy (c, thisprof->array, count * sizeof (int8_t)); } else { /* if this node has been initialized, combine the two profiles, * taking the finer layers from each */ sc_array_init_view (&oldprof, lc, lr[nidx][0], lr[nidx][1]); p6est_profile_union (thisprof, &oldprof, work); if (work->elem_count > oldprof.elem_count) { lr[nidx][0] = lc->elem_count; lr[nidx][1] = work->elem_count; c = (int8_t *) sc_array_push_count (lc, work->elem_count); memcpy (c, work->array, work->elem_count * work->elem_size); } } } else { count = selfprof->elem_count; if (!lr[nidx][1]) { /* if this node has not yet been initialized, initialize it */ lr[nidx][0] = lc->elem_count; lr[nidx][1] = count; c = (int8_t *) sc_array_push_count (lc, count); memcpy (c, selfprof->array, count * sizeof (int8_t)); } else { /* if this node has been initialized, combine the two profiles, * taking the coarser layers from each */ sc_array_init_view (&oldprof, lc, lr[nidx][0], lr[nidx][1]); p6est_profile_intersection (selfprof, &oldprof, work); P4EST_ASSERT (work->elem_count <= oldprof.elem_count); if (work->elem_count < oldprof.elem_count) { lr[nidx][1] = work->elem_count; memcpy (oldprof.array, work->array, work->elem_count * work->elem_size); } } } } } } } p6est_profile_compress (profile); sc_array_destroy (selfprof); sc_array_destroy (faceprof); sc_array_destroy (cornerprof); sc_array_destroy (work); return profile; }
void p6est_refine_to_profile (p6est_t * p6est, p6est_profile_t * profile, p6est_init_t init_fn, p6est_replace_t replace_fn) { size_t zz, zy, first, last; p4est_topidx_t jt; p4est_quadrant_t *col; p4est_tree_t *tree; sc_array_t *tquadrants; p4est_locidx_t eidx; p4est_locidx_t *en = profile->lnodes->element_nodes; p4est_locidx_t (*lr)[2]; p4est_locidx_t nidx, pidx, pfirst, plast; sc_array_t *layers = p6est->layers; sc_array_t *lc = profile->lnode_columns; sc_array_t *work; P4EST_ASSERT (profile->lnodes->degree == 2); lr = (p4est_locidx_t (*)[2]) profile->lnode_ranges; work = sc_array_new (sizeof (p2est_quadrant_t)); for (eidx = 0, jt = p6est->columns->first_local_tree; jt <= p6est->columns->last_local_tree; ++jt) { tree = p4est_tree_array_index (p6est->columns->trees, jt); tquadrants = &tree->quadrants; for (zz = 0; zz < tquadrants->elem_count; ++zz, eidx++) { col = p4est_quadrant_array_index (tquadrants, zz); P6EST_COLUMN_GET_RANGE (col, &first, &last); nidx = en[P4EST_INSUL * eidx + P4EST_INSUL / 2]; P4EST_ASSERT ((size_t) lr[nidx][1] >= last - first); pfirst = lr[nidx][0]; plast = pfirst + lr[nidx][1]; if ((size_t) lr[nidx][1] > last - first) { p2est_quadrant_t stack[P4EST_QMAXLEVEL]; p2est_quadrant_t *q, *r, s, t; int stackcount; sc_array_truncate (work); stackcount = 0; zy = first; for (pidx = pfirst; pidx < plast; pidx++) { int8_t p; P4EST_ASSERT (stackcount || zy < last); p = *((int8_t *) sc_array_index (lc, pidx)); if (stackcount) { q = &(stack[--stackcount]); } else { q = p2est_quadrant_array_index (layers, zy++); } P4EST_ASSERT (q->level <= p); while (q->level < p) { p2est_quadrant_t *child[2]; t = *q; s = *q; s.level++; stack[stackcount] = s; stack[stackcount].z += P4EST_QUADRANT_LEN (s.level); child[0] = &s; child[1] = &stack[stackcount++]; p6est_layer_init_data (p6est, jt, col, child[0], init_fn); p6est_layer_init_data (p6est, jt, col, child[1], init_fn); q = &t; if (replace_fn) { replace_fn (p6est, jt, 1, 1, &col, &q, 1, 2, &col, child); } p6est_layer_free_data (p6est, &t); q = &s; } r = p2est_quadrant_array_push (work); *r = *q; } P4EST_ASSERT (work->elem_count == (size_t) lr[nidx][1]); first = layers->elem_count; last = first + work->elem_count; P6EST_COLUMN_SET_RANGE (col, first, last); q = (p2est_quadrant_t *) sc_array_push_count (layers, work->elem_count); memcpy (q, work->array, work->elem_count * work->elem_size); } } } sc_array_destroy (work); p6est_compress_columns (p6est); p6est_update_offsets (p6est); }
p4est_gloidx_t * p6est_lnodes_get_column_labels (p6est_t * p6est, p8est_lnodes_t * lnodes) { p4est_gloidx_t *labels; p4est_gloidx_t num_cols = 0; p4est_gloidx_t global_num_cols = 0; p4est_topidx_t jt; p4est_tree_t *tree; sc_array_t *tquadrants; p4est_quadrant_t *col; size_t zz, first, last; p4est_locidx_t lfirst, llast, lk; int stride = lnodes->degree + 1; int vnodes = lnodes->vnodes; int mpiret, i; labels = P4EST_ALLOC (p4est_gloidx_t, lnodes->owned_count); memset (labels, -1, lnodes->owned_count * sizeof (*labels)); for (jt = p6est->columns->first_local_tree; jt <= p6est->columns->last_local_tree; ++jt) { tree = p4est_tree_array_index (p6est->columns->trees, jt); tquadrants = &tree->quadrants; for (zz = 0; zz < tquadrants->elem_count; ++zz) { col = p4est_quadrant_array_index (tquadrants, zz); P6EST_COLUMN_GET_RANGE (col, &first, &last); lfirst = (p4est_locidx_t) first; llast = (p4est_locidx_t) last; for (i = 0; i < vnodes; i += stride) { p4est_locidx_t fnid = lnodes->element_nodes[vnodes * lfirst + i]; p4est_locidx_t lnid = lnodes->element_nodes[vnodes * (llast - 1) + i + (stride - 1)]; P4EST_ASSERT (lnid >= 0); P4EST_ASSERT (lnid >= fnid); P4EST_ASSERT (fnid < lnodes->num_local_nodes); if (lnid < lnodes->owned_count) { P4EST_ASSERT (fnid < lnodes->owned_count); if (labels[fnid] < 0) { for (lk = fnid; lk <= lnid; lk++) { labels[lk] = num_cols; } num_cols++; } } } } } mpiret = sc_MPI_Exscan (&num_cols, &global_num_cols, 1, P4EST_MPI_GLOIDX, sc_MPI_SUM, lnodes->mpicomm); SC_CHECK_MPI (mpiret); if (!p6est->mpirank) { global_num_cols = 0; } for (lk = 0; lk < lnodes->owned_count; lk++) { labels[lk] += global_num_cols; } #if 0 { sc_array_t view; sc_array_init_data (&view, labels, sizeof (*labels), (size_t) lnodes->num_local_nodes); p6est_lnodes_share_owned (&view, lnodes); } #endif for (lk = 0; lk < lnodes->owned_count; lk++) { P4EST_ASSERT (labels[lk] >= 0); } return labels; }