xref: /petsc/src/dm/impls/plex/plexexodusii.c (revision fe209ef936d65819f68557b29764e49ab84a2d32)
1552f7358SJed Brown #define PETSCDM_DLL
2af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h>    /*I   "petscdmplex.h"   I*/
3552f7358SJed Brown 
4519f805aSKarl Rupp #if defined(PETSC_HAVE_EXODUSII)
5552f7358SJed Brown #include <netcdf.h>
6552f7358SJed Brown #include <exodusII.h>
7552f7358SJed Brown #endif
8552f7358SJed Brown 
9e0266925SMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
1078569bb4SMatthew G. Knepley /*
1178569bb4SMatthew G. Knepley   EXOGetVarIndex - Locate a result in an exodus file based on its name
1278569bb4SMatthew G. Knepley 
1378569bb4SMatthew G. Knepley   Not collective
1478569bb4SMatthew G. Knepley 
1578569bb4SMatthew G. Knepley   Input Parameters:
1678569bb4SMatthew G. Knepley + exoid    - the exodus id of a file (obtained from ex_open or ex_create for instance)
1778569bb4SMatthew G. Knepley . obj_type - the type of entity for instance EX_NODAL, EX_ELEM_BLOCK
1878569bb4SMatthew G. Knepley - name     - the name of the result
1978569bb4SMatthew G. Knepley 
2078569bb4SMatthew G. Knepley   Output Parameters:
2178569bb4SMatthew G. Knepley . varIndex - the location in the exodus file of the result
2278569bb4SMatthew G. Knepley 
2378569bb4SMatthew G. Knepley   Notes:
2478569bb4SMatthew G. Knepley   The exodus variable index is obtained by comparing name and the
2578569bb4SMatthew G. Knepley   names of zonal variables declared in the exodus file. For instance if name is "V"
2678569bb4SMatthew G. Knepley   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
2778569bb4SMatthew G. Knepley   amongst all variables of type obj_type.
2878569bb4SMatthew G. Knepley 
2978569bb4SMatthew G. Knepley   Level: beginner
3078569bb4SMatthew G. Knepley 
3178569bb4SMatthew G. Knepley .keywords: mesh,ExodusII
3278569bb4SMatthew G. Knepley .seealso: EXOGetVarIndex(),DMView_Exodus(),VecViewPlex_ExodusII_Nodal_Internal(),VecLoadNodal_PlexEXO(),VecLoadZonal_PlexEXO()
3378569bb4SMatthew G. Knepley */
3478569bb4SMatthew G. Knepley static PetscErrorCode EXOGetVarIndex_Private(int exoid, ex_entity_type obj_type, const char name[], int *varIndex)
3578569bb4SMatthew G. Knepley {
366de834b4SMatthew G. Knepley   int            num_vars, i, j;
3778569bb4SMatthew G. Knepley   char           ext_name[MAX_STR_LENGTH+1], var_name[MAX_STR_LENGTH+1];
3878569bb4SMatthew G. Knepley   const int      num_suffix = 5;
3978569bb4SMatthew G. Knepley   char          *suffix[5];
4078569bb4SMatthew G. Knepley   PetscBool      flg;
4178569bb4SMatthew G. Knepley   PetscErrorCode ierr;
4278569bb4SMatthew G. Knepley 
4378569bb4SMatthew G. Knepley   PetscFunctionBegin;
4478569bb4SMatthew G. Knepley   suffix[0] = (char *) "";
4578569bb4SMatthew G. Knepley   suffix[1] = (char *) "_X";
4678569bb4SMatthew G. Knepley   suffix[2] = (char *) "_XX";
4778569bb4SMatthew G. Knepley   suffix[3] = (char *) "_1";
4878569bb4SMatthew G. Knepley   suffix[4] = (char *) "_11";
4978569bb4SMatthew G. Knepley 
5078569bb4SMatthew G. Knepley   *varIndex = 0;
516de834b4SMatthew G. Knepley   PetscStackCallStandard(ex_get_variable_param,(exoid, obj_type, &num_vars));
5278569bb4SMatthew G. Knepley   for (i = 0; i < num_vars; ++i) {
536de834b4SMatthew G. Knepley     PetscStackCallStandard(ex_get_variable_name,(exoid, obj_type, i+1, var_name));
5478569bb4SMatthew G. Knepley     for (j = 0; j < num_suffix; ++j){
5578569bb4SMatthew G. Knepley       ierr = PetscStrncpy(ext_name, name, MAX_STR_LENGTH);CHKERRQ(ierr);
5678569bb4SMatthew G. Knepley       ierr = PetscStrncat(ext_name, suffix[j], MAX_STR_LENGTH);CHKERRQ(ierr);
5778569bb4SMatthew G. Knepley       ierr = PetscStrcasecmp(ext_name, var_name, &flg);
5878569bb4SMatthew G. Knepley       if (flg) {
5978569bb4SMatthew G. Knepley         *varIndex = i+1;
6078569bb4SMatthew G. Knepley         PetscFunctionReturn(0);
6178569bb4SMatthew G. Knepley       }
6278569bb4SMatthew G. Knepley     }
6378569bb4SMatthew G. Knepley   }
6478569bb4SMatthew G. Knepley   SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unable to locate variable %s in ExodusII file.", name);
6578569bb4SMatthew G. Knepley  PetscFunctionReturn(-1);
6678569bb4SMatthew G. Knepley }
6778569bb4SMatthew G. Knepley 
6878569bb4SMatthew G. Knepley /*
6978569bb4SMatthew G. Knepley   DMPlexView_ExodusII_Internal - Write a DM to disk in exodus format
7078569bb4SMatthew G. Knepley 
7178569bb4SMatthew G. Knepley   Collective on dm
7278569bb4SMatthew G. Knepley 
7378569bb4SMatthew G. Knepley   Input Parameters:
7478569bb4SMatthew G. Knepley + dm  - The dm to be written
7578569bb4SMatthew G. Knepley . exoid - the exodus id of a file (obtained from ex_open or ex_create for instance)
7678569bb4SMatthew G. Knepley - degree - the degree of the interpolation space
7778569bb4SMatthew G. Knepley 
7878569bb4SMatthew G. Knepley   Notes:
7978569bb4SMatthew G. Knepley   Not all DM can be written to disk this way. For instance, exodus assume that element blocks (mapped to "Cell sets" labels)
8078569bb4SMatthew G. Knepley   consists of sequentially numbered cells. If this is not the case, the exodus file will be corrupted.
8178569bb4SMatthew G. Knepley 
8278569bb4SMatthew G. Knepley   If the dm has been distributed and exoid points to different files on each MPI rank, only the "local" part of the DM
8378569bb4SMatthew G. Knepley   (including "ghost" cells and vertices) will be written. If all exoid points to the same file, the resulting file will
8478569bb4SMatthew G. Knepley   probably be corrupted.
8578569bb4SMatthew G. Knepley 
8678569bb4SMatthew G. Knepley   DMPlex only represents geometry while most post-processing software expect that a mesh also provides information
8778569bb4SMatthew G. Knepley   on the discretization space. This function assumes that the file represents Lagrange finite elements of order 1 or 2.
8878569bb4SMatthew G. Knepley   It should be extended to use PetscFE objects.
8978569bb4SMatthew G. Knepley 
9078569bb4SMatthew G. Knepley   This function will only handle TRI, TET, QUAD and HEX cells.
9178569bb4SMatthew G. Knepley   Level: beginner
9278569bb4SMatthew G. Knepley 
9378569bb4SMatthew G. Knepley .keywords: mesh, ExodusII
9478569bb4SMatthew G. Knepley .seealso: EXOGetVarIndex_Private(), VecViewPlex_ExodusII_Nodal_Internal(), VecLoadNodal_PlexEXO(), VecViewZonal_PlexEXO(), VecLoadZonal_PlexEXO()
9578569bb4SMatthew G. Knepley */
9678569bb4SMatthew G. Knepley PetscErrorCode DMPlexView_ExodusII_Internal(DM dm, int exoid, PetscInt degree)
9778569bb4SMatthew G. Knepley {
9878569bb4SMatthew G. Knepley   enum ElemType {TRI, QUAD, TET, HEX};
9978569bb4SMatthew G. Knepley   MPI_Comm        comm;
10078569bb4SMatthew G. Knepley   /* Connectivity Variables */
10178569bb4SMatthew G. Knepley   PetscInt        cellsNotInConnectivity;
10278569bb4SMatthew G. Knepley   /* Cell Sets */
10378569bb4SMatthew G. Knepley   DMLabel         csLabel;
10478569bb4SMatthew G. Knepley   IS              csIS;
10578569bb4SMatthew G. Knepley   const PetscInt *csIdx;
10678569bb4SMatthew G. Knepley   PetscInt        num_cs, cs;
10778569bb4SMatthew G. Knepley   enum ElemType  *type;
108*fe209ef9SBlaise Bourdin   PetscBool       hasLabel;
10978569bb4SMatthew G. Knepley   /* Coordinate Variables */
11078569bb4SMatthew G. Knepley   DM              cdm;
11178569bb4SMatthew G. Knepley   PetscSection    section;
11278569bb4SMatthew G. Knepley   Vec             coord;
11378569bb4SMatthew G. Knepley   PetscInt      **nodes;
114eae8a387SMatthew G. Knepley   PetscInt        depth, d, dim, skipCells = 0;
11578569bb4SMatthew G. Knepley   PetscInt        pStart, pEnd, p, cStart, cEnd, numCells, vStart, vEnd, numVertices, eStart, eEnd, numEdges, fStart, fEnd, numFaces, numNodes;
11678569bb4SMatthew G. Knepley   PetscInt        num_vs, num_fs;
11778569bb4SMatthew G. Knepley   PetscMPIInt     rank, size;
11878569bb4SMatthew G. Knepley   const char     *dmName;
119*fe209ef9SBlaise Bourdin   PetscInt        nodesTriP1[4]  = {3,0,0,0};
120*fe209ef9SBlaise Bourdin   PetscInt        nodesTriP2[4]  = {3,3,0,0};
121*fe209ef9SBlaise Bourdin   PetscInt        nodesQuadP1[4] = {4,0,0,0};
122*fe209ef9SBlaise Bourdin   PetscInt        nodesQuadP2[4] = {4,4,0,1};
123*fe209ef9SBlaise Bourdin   PetscInt        nodesTetP1[4]  = {4,0,0,0};
124*fe209ef9SBlaise Bourdin   PetscInt        nodesTetP2[4]  = {4,6,0,0};
125*fe209ef9SBlaise Bourdin   PetscInt        nodesHexP1[4]  = {8,0,0,0};
126*fe209ef9SBlaise Bourdin   PetscInt        nodesHexP2[4]  = {8,12,6,1};
12778569bb4SMatthew G. Knepley   PetscErrorCode  ierr;
12878569bb4SMatthew G. Knepley 
12978569bb4SMatthew G. Knepley   PetscFunctionBegin;
13078569bb4SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr);
13178569bb4SMatthew G. Knepley   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
13278569bb4SMatthew G. Knepley   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
13378569bb4SMatthew G. Knepley   /* --- Get DM info --- */
13478569bb4SMatthew G. Knepley   ierr = PetscObjectGetName((PetscObject) dm, &dmName);CHKERRQ(ierr);
13578569bb4SMatthew G. Knepley   ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
13678569bb4SMatthew G. Knepley   ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
13778569bb4SMatthew G. Knepley   ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
13878569bb4SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
13978569bb4SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
14078569bb4SMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
14178569bb4SMatthew G. Knepley   ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
14278569bb4SMatthew G. Knepley   numCells    = cEnd - cStart;
14378569bb4SMatthew G. Knepley   numEdges    = eEnd - eStart;
14478569bb4SMatthew G. Knepley   numVertices = vEnd - vStart;
14578569bb4SMatthew G. Knepley   if (depth == 3) {numFaces = fEnd - fStart;}
14678569bb4SMatthew G. Knepley   else            {numFaces = 0;}
14778569bb4SMatthew G. Knepley   ierr = DMGetLabelSize(dm, "Cell Sets", &num_cs);CHKERRQ(ierr);
14878569bb4SMatthew G. Knepley   ierr = DMGetLabelSize(dm, "Vertex Sets", &num_vs);CHKERRQ(ierr);
14978569bb4SMatthew G. Knepley   ierr = DMGetLabelSize(dm, "Face Sets", &num_fs);CHKERRQ(ierr);
15078569bb4SMatthew G. Knepley   ierr = DMGetCoordinatesLocal(dm, &coord);CHKERRQ(ierr);
15178569bb4SMatthew G. Knepley   ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
15278569bb4SMatthew G. Knepley   if (num_cs > 0) {
15378569bb4SMatthew G. Knepley     ierr = DMGetLabel(dm, "Cell Sets", &csLabel);CHKERRQ(ierr);
15478569bb4SMatthew G. Knepley     ierr = DMLabelGetValueIS(csLabel, &csIS);CHKERRQ(ierr);
15578569bb4SMatthew G. Knepley     ierr = ISGetIndices(csIS, &csIdx);CHKERRQ(ierr);
15678569bb4SMatthew G. Knepley   }
15778569bb4SMatthew G. Knepley   ierr = PetscMalloc1(num_cs, &nodes);CHKERRQ(ierr);
15878569bb4SMatthew G. Knepley   /* Set element type for each block and compute total number of nodes */
15978569bb4SMatthew G. Knepley   ierr = PetscMalloc1(num_cs, &type);CHKERRQ(ierr);
16078569bb4SMatthew G. Knepley   numNodes = numVertices;
16178569bb4SMatthew G. Knepley   if (degree == 2) {numNodes += numEdges;}
16278569bb4SMatthew G. Knepley   cellsNotInConnectivity = numCells;
16378569bb4SMatthew G. Knepley   for (cs = 0; cs < num_cs; ++cs) {
16478569bb4SMatthew G. Knepley     IS              stratumIS;
16578569bb4SMatthew G. Knepley     const PetscInt *cells;
16678569bb4SMatthew G. Knepley     PetscScalar    *xyz = NULL;
16778569bb4SMatthew G. Knepley     PetscInt        csSize, closureSize;
16878569bb4SMatthew G. Knepley 
16978569bb4SMatthew G. Knepley     ierr = DMLabelGetStratumIS(csLabel, csIdx[cs], &stratumIS);CHKERRQ(ierr);
17078569bb4SMatthew G. Knepley     ierr = ISGetIndices(stratumIS, &cells);CHKERRQ(ierr);
17178569bb4SMatthew G. Knepley     ierr = ISGetSize(stratumIS, &csSize);CHKERRQ(ierr);
17278569bb4SMatthew G. Knepley     ierr = DMPlexVecGetClosure(cdm, NULL, coord, cells[0], &closureSize, &xyz);CHKERRQ(ierr);
17378569bb4SMatthew G. Knepley     switch (dim) {
17478569bb4SMatthew G. Knepley       case 2:
17578569bb4SMatthew G. Knepley         if      (closureSize == 3*dim) {type[cs] = TRI;}
17678569bb4SMatthew G. Knepley         else if (closureSize == 4*dim) {type[cs] = QUAD;}
17778569bb4SMatthew G. Knepley         else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices %D in dimension %D has no ExodusII type", closureSize/dim, dim);
17878569bb4SMatthew G. Knepley         break;
17978569bb4SMatthew G. Knepley       case 3:
18078569bb4SMatthew G. Knepley         if      (closureSize == 4*dim) {type[cs] = TET;}
18178569bb4SMatthew G. Knepley         else if (closureSize == 8*dim) {type[cs] = HEX;}
18278569bb4SMatthew G. Knepley         else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices %D in dimension %D has no ExodusII type", closureSize/dim, dim);
18378569bb4SMatthew G. Knepley         break;
18478569bb4SMatthew G. Knepley       default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %D not handled by ExodusII viewer", dim);
18578569bb4SMatthew G. Knepley     }
18678569bb4SMatthew G. Knepley     if ((degree == 2) && (type[cs] == QUAD)) {numNodes += csSize;}
18778569bb4SMatthew G. Knepley     if ((degree == 2) && (type[cs] == HEX))  {numNodes += csSize; numNodes += numFaces;}
18878569bb4SMatthew G. Knepley     ierr = DMPlexVecRestoreClosure(cdm, NULL, coord, cells[0], &closureSize, &xyz);CHKERRQ(ierr);
18978569bb4SMatthew G. Knepley     /* Set nodes and Element type */
19078569bb4SMatthew G. Knepley     if (type[cs] == TRI) {
19178569bb4SMatthew G. Knepley       if      (degree == 1) nodes[cs] = nodesTriP1;
19278569bb4SMatthew G. Knepley       else if (degree == 2) nodes[cs] = nodesTriP2;
19378569bb4SMatthew G. Knepley     } else if (type[cs] == QUAD) {
19478569bb4SMatthew G. Knepley       if      (degree == 1) nodes[cs] = nodesQuadP1;
19578569bb4SMatthew G. Knepley       else if (degree == 2) nodes[cs] = nodesQuadP2;
19678569bb4SMatthew G. Knepley     } else if (type[cs] == TET) {
19778569bb4SMatthew G. Knepley       if      (degree == 1) nodes[cs] = nodesTetP1;
19878569bb4SMatthew G. Knepley       else if (degree == 2) nodes[cs] = nodesTetP2;
19978569bb4SMatthew G. Knepley     } else if (type[cs] == HEX) {
20078569bb4SMatthew G. Knepley       if      (degree == 1) nodes[cs] = nodesHexP1;
20178569bb4SMatthew G. Knepley       else if (degree == 2) nodes[cs] = nodesHexP2;
20278569bb4SMatthew G. Knepley     }
20378569bb4SMatthew G. Knepley     /* Compute the number of cells not in the connectivity table */
20478569bb4SMatthew G. Knepley     cellsNotInConnectivity -= nodes[cs][3]*csSize;
20578569bb4SMatthew G. Knepley 
20678569bb4SMatthew G. Knepley     ierr = ISRestoreIndices(stratumIS, &cells);CHKERRQ(ierr);
20778569bb4SMatthew G. Knepley     ierr = ISDestroy(&stratumIS);CHKERRQ(ierr);
20878569bb4SMatthew G. Knepley   }
2096de834b4SMatthew G. Knepley   if (num_cs > 0) {PetscStackCallStandard(ex_put_init,(exoid, dmName, dim, numNodes, numCells, num_cs, num_vs, num_fs));}
21078569bb4SMatthew G. Knepley   /* --- Connectivity --- */
21178569bb4SMatthew G. Knepley   for (cs = 0; cs < num_cs; ++cs) {
21278569bb4SMatthew G. Knepley     IS              stratumIS;
21378569bb4SMatthew G. Knepley     const PetscInt *cells;
214*fe209ef9SBlaise Bourdin     PetscInt       *connect, off = 0;
215eae8a387SMatthew G. Knepley     PetscInt        edgesInClosure = 0, facesInClosure = 0, verticesInClosure = 0;
21678569bb4SMatthew G. Knepley     PetscInt        csSize, c, connectSize, closureSize;
21778569bb4SMatthew G. Knepley     char           *elem_type = NULL;
21878569bb4SMatthew G. Knepley     char            elem_type_tri3[]  = "TRI3",  elem_type_quad4[] = "QUAD4";
21978569bb4SMatthew G. Knepley     char            elem_type_tri6[]  = "TRI6",  elem_type_quad9[] = "QUAD9";
22078569bb4SMatthew G. Knepley     char            elem_type_tet4[]  = "TET4",  elem_type_hex8[]  = "HEX8";
22178569bb4SMatthew G. Knepley     char            elem_type_tet10[] = "TET10", elem_type_hex27[] = "HEX27";
22278569bb4SMatthew G. Knepley 
22378569bb4SMatthew G. Knepley     ierr = DMLabelGetStratumIS(csLabel, csIdx[cs], &stratumIS);CHKERRQ(ierr);
22478569bb4SMatthew G. Knepley     ierr = ISGetIndices(stratumIS, &cells);CHKERRQ(ierr);
22578569bb4SMatthew G. Knepley     ierr = ISGetSize(stratumIS, &csSize);CHKERRQ(ierr);
22678569bb4SMatthew G. Knepley     /* Set Element type */
22778569bb4SMatthew G. Knepley     if (type[cs] == TRI) {
22878569bb4SMatthew G. Knepley       if      (degree == 1) elem_type = elem_type_tri3;
22978569bb4SMatthew G. Knepley       else if (degree == 2) elem_type = elem_type_tri6;
23078569bb4SMatthew G. Knepley     } else if (type[cs] == QUAD) {
23178569bb4SMatthew G. Knepley       if      (degree == 1) elem_type = elem_type_quad4;
23278569bb4SMatthew G. Knepley       else if (degree == 2) elem_type = elem_type_quad9;
23378569bb4SMatthew G. Knepley     } else if (type[cs] == TET) {
23478569bb4SMatthew G. Knepley       if      (degree == 1) elem_type = elem_type_tet4;
23578569bb4SMatthew G. Knepley       else if (degree == 2) elem_type = elem_type_tet10;
23678569bb4SMatthew G. Knepley     } else if (type[cs] == HEX) {
23778569bb4SMatthew G. Knepley       if      (degree == 1) elem_type = elem_type_hex8;
23878569bb4SMatthew G. Knepley       else if (degree == 2) elem_type = elem_type_hex27;
23978569bb4SMatthew G. Knepley     }
24078569bb4SMatthew G. Knepley     connectSize = nodes[cs][0] + nodes[cs][1] + nodes[cs][2] + nodes[cs][3];
241*fe209ef9SBlaise Bourdin     ierr = PetscMalloc1(PetscMax(27,connectSize)*csSize, &connect);CHKERRQ(ierr);
242*fe209ef9SBlaise Bourdin     PetscStackCallStandard(ex_put_block,(exoid, EX_ELEM_BLOCK, csIdx[cs], elem_type, csSize, connectSize, 0, 0, 1));
24378569bb4SMatthew G. Knepley     /* Find number of vertices, edges, and faces in the closure */
24478569bb4SMatthew G. Knepley     verticesInClosure = nodes[cs][0];
24578569bb4SMatthew G. Knepley     if (depth > 1) {
24678569bb4SMatthew G. Knepley       if (dim == 2) {
24778569bb4SMatthew G. Knepley         ierr = DMPlexGetConeSize(dm, cells[0], &edgesInClosure);CHKERRQ(ierr);
24878569bb4SMatthew G. Knepley       } else if (dim == 3) {
24978569bb4SMatthew G. Knepley         PetscInt *closure = NULL;
25078569bb4SMatthew G. Knepley 
25178569bb4SMatthew G. Knepley         ierr = DMPlexGetConeSize(dm, cells[0], &facesInClosure);CHKERRQ(ierr);
25278569bb4SMatthew G. Knepley         ierr = DMPlexGetTransitiveClosure(dm, cells[0], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
25378569bb4SMatthew G. Knepley         edgesInClosure = closureSize - facesInClosure - 1 - verticesInClosure;
25478569bb4SMatthew G. Knepley         ierr = DMPlexRestoreTransitiveClosure(dm, cells[0], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
25578569bb4SMatthew G. Knepley       }
25678569bb4SMatthew G. Knepley     }
25778569bb4SMatthew G. Knepley     /* Get connectivity for each cell */
25878569bb4SMatthew G. Knepley     for (c = 0; c < csSize; ++c) {
25978569bb4SMatthew G. Knepley       PetscInt *closure = NULL;
26078569bb4SMatthew G. Knepley       PetscInt  temp, i;
26178569bb4SMatthew G. Knepley 
26278569bb4SMatthew G. Knepley       ierr = DMPlexGetTransitiveClosure(dm, cells[c], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
26378569bb4SMatthew G. Knepley       for (i = 0; i < connectSize; ++i) {
26478569bb4SMatthew G. Knepley         if (i < nodes[cs][0]) {/* Vertices */
265*fe209ef9SBlaise Bourdin           connect[i+off] = closure[(i+edgesInClosure+facesInClosure+1)*2] + 1;
266*fe209ef9SBlaise Bourdin           connect[i+off] -= cellsNotInConnectivity;
26778569bb4SMatthew G. Knepley         } else if (i < nodes[cs][0]+nodes[cs][1]) { /* Edges */
268*fe209ef9SBlaise Bourdin           connect[i+off] = closure[(i-verticesInClosure+facesInClosure+1)*2] + 1;
269*fe209ef9SBlaise Bourdin           if (nodes[cs][2] == 0) connect[i+off] -= numFaces;
270*fe209ef9SBlaise Bourdin           connect[i+off] -= cellsNotInConnectivity;
27178569bb4SMatthew G. Knepley         } else if (i < nodes[cs][0]+nodes[cs][1]+nodes[cs][3]){ /* Cells */
272*fe209ef9SBlaise Bourdin           connect[i+off] = closure[0] + 1;
273*fe209ef9SBlaise Bourdin           connect[i+off] -= skipCells;
27478569bb4SMatthew G. Knepley         } else if (i < nodes[cs][0]+nodes[cs][1]+nodes[cs][3]+nodes[cs][2]){ /* Faces */
275*fe209ef9SBlaise Bourdin           connect[i+off] = closure[(i-edgesInClosure-verticesInClosure)*2] + 1;
276*fe209ef9SBlaise Bourdin           connect[i+off] -= cellsNotInConnectivity;
27778569bb4SMatthew G. Knepley         } else {
278*fe209ef9SBlaise Bourdin           connect[i+off] = -1;
27978569bb4SMatthew G. Knepley         }
28078569bb4SMatthew G. Knepley       }
28178569bb4SMatthew G. Knepley       /* Tetrahedra are inverted */
28278569bb4SMatthew G. Knepley       if (type[cs] == TET) {
283*fe209ef9SBlaise Bourdin         temp = connect[0+off]; connect[0+off] = connect[1+off]; connect[1+off] = temp;
28478569bb4SMatthew G. Knepley         if (degree == 2) {
285*fe209ef9SBlaise Bourdin           temp = connect[5+off]; connect[5] = connect[6+off]; connect[6] = temp;
286*fe209ef9SBlaise Bourdin           temp = connect[7+off]; connect[7] = connect[8+off]; connect[8] = temp;
28778569bb4SMatthew G. Knepley         }
28878569bb4SMatthew G. Knepley       }
28978569bb4SMatthew G. Knepley       /* Hexahedra are inverted */
29078569bb4SMatthew G. Knepley       if (type[cs] == HEX) {
291*fe209ef9SBlaise Bourdin         temp = connect[1+off]; connect[1+off] = connect[3+off]; connect[3+off] = temp;
29278569bb4SMatthew G. Knepley         if (degree == 2) {
293*fe209ef9SBlaise Bourdin           temp = connect[8+off];  connect[8+off]  = connect[11+off]; connect[11+off] = temp;
294*fe209ef9SBlaise Bourdin           temp = connect[9+off];  connect[9+off]  = connect[10+off]; connect[10+off] = temp;
295*fe209ef9SBlaise Bourdin           temp = connect[16+off]; connect[16+off] = connect[17+off]; connect[17+off] = temp;
296*fe209ef9SBlaise Bourdin           temp = connect[18+off]; connect[18+off] = connect[19+off]; connect[19+off] = temp;
29778569bb4SMatthew G. Knepley 
298*fe209ef9SBlaise Bourdin           temp = connect[12+off]; connect[12+off] = connect[16+off]; connect[16+off] = temp;
299*fe209ef9SBlaise Bourdin           temp = connect[13+off]; connect[13+off] = connect[17+off]; connect[17+off] = temp;
300*fe209ef9SBlaise Bourdin           temp = connect[14+off]; connect[14+off] = connect[18+off]; connect[18+off] = temp;
301*fe209ef9SBlaise Bourdin           temp = connect[15+off]; connect[15+off] = connect[19+off]; connect[19+off] = temp;
30278569bb4SMatthew G. Knepley 
303*fe209ef9SBlaise Bourdin           temp = connect[23+off]; connect[23+off] = connect[26+off]; connect[26+off] = temp;
304*fe209ef9SBlaise Bourdin           temp = connect[24+off]; connect[24+off] = connect[25+off]; connect[25+off] = temp;
305*fe209ef9SBlaise Bourdin           temp = connect[25+off]; connect[25+off] = connect[26+off]; connect[26+off] = temp;
30678569bb4SMatthew G. Knepley         }
30778569bb4SMatthew G. Knepley       }
308*fe209ef9SBlaise Bourdin       off += connectSize;
30978569bb4SMatthew G. Knepley       ierr = DMPlexRestoreTransitiveClosure(dm, cells[c], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
31078569bb4SMatthew G. Knepley     }
311*fe209ef9SBlaise Bourdin     PetscStackCallStandard(ex_put_conn,(exoid, EX_ELEM_BLOCK, csIdx[cs], connect, 0, 0));
31278569bb4SMatthew G. Knepley     skipCells += (nodes[cs][3] == 0)*csSize;
31378569bb4SMatthew G. Knepley     ierr = PetscFree(connect);CHKERRQ(ierr);
31478569bb4SMatthew G. Knepley     ierr = ISRestoreIndices(stratumIS, &cells);CHKERRQ(ierr);
31578569bb4SMatthew G. Knepley     ierr = ISDestroy(&stratumIS);CHKERRQ(ierr);
31678569bb4SMatthew G. Knepley   }
31778569bb4SMatthew G. Knepley   ierr = PetscFree(type);CHKERRQ(ierr);
31878569bb4SMatthew G. Knepley   /* --- Coordinates --- */
31978569bb4SMatthew G. Knepley   ierr = PetscSectionCreate(comm, &section);CHKERRQ(ierr);
32078569bb4SMatthew G. Knepley   ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr);
32178569bb4SMatthew G. Knepley   for (d = 0; d < depth; ++d) {
32278569bb4SMatthew G. Knepley     ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr);
32378569bb4SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
32478569bb4SMatthew G. Knepley       ierr = PetscSectionSetDof(section, p, nodes[0][d] > 0);CHKERRQ(ierr);
32578569bb4SMatthew G. Knepley     }
32678569bb4SMatthew G. Knepley   }
32778569bb4SMatthew G. Knepley   for (cs = 0; cs < num_cs; ++cs) {
32878569bb4SMatthew G. Knepley     IS              stratumIS;
32978569bb4SMatthew G. Knepley     const PetscInt *cells;
33078569bb4SMatthew G. Knepley     PetscInt        csSize, c;
33178569bb4SMatthew G. Knepley 
33278569bb4SMatthew G. Knepley     ierr = DMLabelGetStratumIS(csLabel, csIdx[cs], &stratumIS);CHKERRQ(ierr);
33378569bb4SMatthew G. Knepley     ierr = ISGetIndices(stratumIS, &cells);CHKERRQ(ierr);
33478569bb4SMatthew G. Knepley     ierr = ISGetSize(stratumIS, &csSize);CHKERRQ(ierr);
33578569bb4SMatthew G. Knepley     for (c = 0; c < csSize; ++c) {
33678569bb4SMatthew G. Knepley       ierr = PetscSectionSetDof(section, cells[c], nodes[cs][3] > 0);CHKERRQ(ierr);
33778569bb4SMatthew G. Knepley     }
33878569bb4SMatthew G. Knepley     ierr = ISRestoreIndices(stratumIS, &cells);CHKERRQ(ierr);
33978569bb4SMatthew G. Knepley     ierr = ISDestroy(&stratumIS);CHKERRQ(ierr);
34078569bb4SMatthew G. Knepley   }
34178569bb4SMatthew G. Knepley   if (num_cs > 0) {
34278569bb4SMatthew G. Knepley     ierr = ISRestoreIndices(csIS, &csIdx);CHKERRQ(ierr);
34378569bb4SMatthew G. Knepley     ierr = ISDestroy(&csIS);CHKERRQ(ierr);
34478569bb4SMatthew G. Knepley   }
34578569bb4SMatthew G. Knepley   ierr = PetscFree(nodes);CHKERRQ(ierr);
34678569bb4SMatthew G. Knepley   ierr = PetscSectionSetUp(section);CHKERRQ(ierr);
34778569bb4SMatthew G. Knepley   if (numNodes > 0) {
34878569bb4SMatthew G. Knepley     const char  *coordNames[3] = {"x", "y", "z"};
34978569bb4SMatthew G. Knepley     PetscScalar *coords, *closure;
35078569bb4SMatthew G. Knepley     PetscReal   *cval;
35178569bb4SMatthew G. Knepley     PetscInt     hasDof, n = 0;
35278569bb4SMatthew G. Knepley 
35378569bb4SMatthew G. Knepley     /* There can't be more than 24 values in the closure of a point for the coord section */
3546de834b4SMatthew G. Knepley     ierr = PetscCalloc3(numNodes*3, &coords, dim, &cval, 24, &closure);CHKERRQ(ierr);
35578569bb4SMatthew G. Knepley     ierr = DMGetCoordinatesLocal(dm, &coord);CHKERRQ(ierr);
35678569bb4SMatthew G. Knepley     ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
35778569bb4SMatthew G. Knepley     for (p = pStart; p < pEnd; ++p) {
35878569bb4SMatthew G. Knepley       ierr = PetscSectionGetDof(section, p, &hasDof);
35978569bb4SMatthew G. Knepley       if (hasDof) {
36078569bb4SMatthew G. Knepley         PetscInt closureSize = 24, j;
36178569bb4SMatthew G. Knepley 
36278569bb4SMatthew G. Knepley         ierr = DMPlexVecGetClosure(cdm, NULL, coord, p, &closureSize, &closure);CHKERRQ(ierr);
36378569bb4SMatthew G. Knepley         for (d = 0; d < dim; ++d) {
36478569bb4SMatthew G. Knepley           cval[d] = 0.0;
36578569bb4SMatthew G. Knepley           for (j = 0; j < closureSize/dim; j++) cval[d] += closure[j*dim+d];
36678569bb4SMatthew G. Knepley           coords[d*numNodes+n] = cval[d] * dim / closureSize;
36778569bb4SMatthew G. Knepley         }
36878569bb4SMatthew G. Knepley         ++n;
36978569bb4SMatthew G. Knepley       }
37078569bb4SMatthew G. Knepley     }
3716de834b4SMatthew G. Knepley     PetscStackCallStandard(ex_put_coord,(exoid, &coords[0*numNodes], &coords[1*numNodes], &coords[2*numNodes]));
37278569bb4SMatthew G. Knepley     ierr = PetscFree3(coords, cval, closure);CHKERRQ(ierr);
3736de834b4SMatthew G. Knepley     PetscStackCallStandard(ex_put_coord_names,(exoid, (char **) coordNames));
37478569bb4SMatthew G. Knepley   }
37578569bb4SMatthew G. Knepley   ierr = PetscSectionDestroy(&section);CHKERRQ(ierr);
376*fe209ef9SBlaise Bourdin   /* --- Node Sets/Vertex Sets --- */
377*fe209ef9SBlaise Bourdin   DMHasLabel(dm, "Vertex Sets", &hasLabel);
378*fe209ef9SBlaise Bourdin   if (hasLabel) {
379*fe209ef9SBlaise Bourdin     PetscInt        i, vs, vsSize;
380*fe209ef9SBlaise Bourdin     const PetscInt *vsIdx, *vertices;
381*fe209ef9SBlaise Bourdin     PetscInt       *nodeList;
382*fe209ef9SBlaise Bourdin     IS              vsIS, stratumIS;
383*fe209ef9SBlaise Bourdin     DMLabel         vsLabel;
384*fe209ef9SBlaise Bourdin     ierr = DMGetLabel(dm, "Vertex Sets", &vsLabel);CHKERRQ(ierr);
385*fe209ef9SBlaise Bourdin     ierr = DMLabelGetValueIS(vsLabel, &vsIS);CHKERRQ(ierr);
386*fe209ef9SBlaise Bourdin     ierr = ISGetIndices(vsIS, &vsIdx);CHKERRQ(ierr);
387*fe209ef9SBlaise Bourdin     for (vs=0; vs<num_vs; ++vs) {
388*fe209ef9SBlaise Bourdin       ierr = DMLabelGetStratumIS(vsLabel, vsIdx[vs], &stratumIS);CHKERRQ(ierr);
389*fe209ef9SBlaise Bourdin       ierr = ISGetIndices(stratumIS, &vertices);CHKERRQ(ierr);
390*fe209ef9SBlaise Bourdin       ierr = ISGetSize(stratumIS, &vsSize);CHKERRQ(ierr);
391*fe209ef9SBlaise Bourdin       ierr = PetscMalloc1(vsSize, &nodeList);
392*fe209ef9SBlaise Bourdin       for (i=0; i<vsSize; ++i) {
393*fe209ef9SBlaise Bourdin         nodeList[i] = vertices[i] - skipCells + 1;
394*fe209ef9SBlaise Bourdin       }
395*fe209ef9SBlaise Bourdin       PetscStackCallStandard(ex_put_set_param,(exoid, EX_NODE_SET, vsIdx[vs], vsSize, 0));
396*fe209ef9SBlaise Bourdin       PetscStackCallStandard(ex_put_set,(exoid, EX_NODE_SET, vsIdx[vs], nodeList, NULL));
397*fe209ef9SBlaise Bourdin       ierr = ISRestoreIndices(stratumIS, &vertices);CHKERRQ(ierr);
398*fe209ef9SBlaise Bourdin       ierr = ISDestroy(&stratumIS);CHKERRQ(ierr);
399*fe209ef9SBlaise Bourdin       ierr = PetscFree(nodeList);CHKERRQ(ierr);
400*fe209ef9SBlaise Bourdin     }
401*fe209ef9SBlaise Bourdin     ierr = ISRestoreIndices(vsIS, &vsIdx);CHKERRQ(ierr);
402*fe209ef9SBlaise Bourdin     ierr = ISDestroy(&vsIS);CHKERRQ(ierr);
403*fe209ef9SBlaise Bourdin   }
404*fe209ef9SBlaise Bourdin   /* --- Side Sets/Face Sets --- */
405*fe209ef9SBlaise Bourdin   ierr = DMHasLabel(dm, "Face Sets", &hasLabel);CHKERRQ(ierr);
406*fe209ef9SBlaise Bourdin   if (hasLabel) {
407*fe209ef9SBlaise Bourdin     PetscInt        i, j, fs, fsSize;
408*fe209ef9SBlaise Bourdin     const PetscInt *fsIdx, *faces;
409*fe209ef9SBlaise Bourdin     IS              fsIS, stratumIS;
410*fe209ef9SBlaise Bourdin     DMLabel         fsLabel;
411*fe209ef9SBlaise Bourdin     PetscInt        numPoints, *points;
412*fe209ef9SBlaise Bourdin     PetscInt        elem_list_size = 0;
413*fe209ef9SBlaise Bourdin     PetscInt       *elem_list, *elem_ind, *side_list;
414*fe209ef9SBlaise Bourdin 
415*fe209ef9SBlaise Bourdin     ierr = DMGetLabel(dm, "Face Sets", &fsLabel);CHKERRQ(ierr);
416*fe209ef9SBlaise Bourdin     /* Compute size of Node List and Element List */
417*fe209ef9SBlaise Bourdin     ierr = DMLabelGetValueIS(fsLabel, &fsIS);CHKERRQ(ierr);
418*fe209ef9SBlaise Bourdin     ierr = ISGetIndices(fsIS, &fsIdx);CHKERRQ(ierr);
419*fe209ef9SBlaise Bourdin     for (fs=0; fs<num_fs; ++fs) {
420*fe209ef9SBlaise Bourdin       ierr = DMLabelGetStratumIS(fsLabel, fsIdx[fs], &stratumIS);CHKERRQ(ierr);;
421*fe209ef9SBlaise Bourdin       ierr = ISGetSize(stratumIS, &fsSize);CHKERRQ(ierr);
422*fe209ef9SBlaise Bourdin       elem_list_size += fsSize;
423*fe209ef9SBlaise Bourdin       ierr = ISDestroy(&stratumIS);CHKERRQ(ierr);
424*fe209ef9SBlaise Bourdin     }
425*fe209ef9SBlaise Bourdin     ierr = PetscMalloc3(num_fs, &elem_ind,
426*fe209ef9SBlaise Bourdin                         elem_list_size, &elem_list,
427*fe209ef9SBlaise Bourdin                         elem_list_size, &side_list);CHKERRQ(ierr);
428*fe209ef9SBlaise Bourdin     elem_ind[0] = 0;
429*fe209ef9SBlaise Bourdin     for (fs=0; fs<num_fs; ++fs) {
430*fe209ef9SBlaise Bourdin       ierr = DMLabelGetStratumIS(fsLabel, fsIdx[fs], &stratumIS);CHKERRQ(ierr);
431*fe209ef9SBlaise Bourdin       ierr = ISGetIndices(stratumIS, &faces);CHKERRQ(ierr);
432*fe209ef9SBlaise Bourdin       ierr = ISGetSize(stratumIS, &fsSize);CHKERRQ(ierr);
433*fe209ef9SBlaise Bourdin       /* Set Parameters */
434*fe209ef9SBlaise Bourdin       PetscStackCallStandard(ex_put_set_param,(exoid, EX_SIDE_SET, fsIdx[fs], fsSize, 0));
435*fe209ef9SBlaise Bourdin       /* Indices */
436*fe209ef9SBlaise Bourdin       if (fs<num_fs-1) {
437*fe209ef9SBlaise Bourdin         elem_ind[fs+1] = elem_ind[fs] + fsSize;
438*fe209ef9SBlaise Bourdin       }
439*fe209ef9SBlaise Bourdin 
440*fe209ef9SBlaise Bourdin       for (i=0; i<fsSize; ++i) {
441*fe209ef9SBlaise Bourdin         /* Element List */
442*fe209ef9SBlaise Bourdin         points = NULL;
443*fe209ef9SBlaise Bourdin         ierr = DMPlexGetTransitiveClosure(dm, faces[i], PETSC_FALSE, &numPoints, &points);CHKERRQ(ierr);
444*fe209ef9SBlaise Bourdin         elem_list[elem_ind[fs] + i] = points[2] +1;
445*fe209ef9SBlaise Bourdin         ierr = DMPlexRestoreTransitiveClosure(dm, faces[i], PETSC_FALSE, &numPoints, &points);CHKERRQ(ierr);
446*fe209ef9SBlaise Bourdin 
447*fe209ef9SBlaise Bourdin         /* Side List */
448*fe209ef9SBlaise Bourdin         points = NULL;
449*fe209ef9SBlaise Bourdin         ierr = DMPlexGetTransitiveClosure(dm, elem_list[elem_ind[fs] + i]-1, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);
450*fe209ef9SBlaise Bourdin         for (j=1; j<numPoints; ++j) {
451*fe209ef9SBlaise Bourdin           if (points[j*2]==faces[i]) {break;}
452*fe209ef9SBlaise Bourdin         }
453*fe209ef9SBlaise Bourdin         /* Convert HEX sides */
454*fe209ef9SBlaise Bourdin         if (numPoints == 27) {
455*fe209ef9SBlaise Bourdin           if      (j == 1) {j = 5;}
456*fe209ef9SBlaise Bourdin           else if (j == 2) {j = 6;}
457*fe209ef9SBlaise Bourdin           else if (j == 3) {j = 1;}
458*fe209ef9SBlaise Bourdin           else if (j == 4) {j = 3;}
459*fe209ef9SBlaise Bourdin           else if (j == 5) {j = 2;}
460*fe209ef9SBlaise Bourdin           else if (j == 6) {j = 4;}
461*fe209ef9SBlaise Bourdin         }
462*fe209ef9SBlaise Bourdin         /* Convert TET sides */
463*fe209ef9SBlaise Bourdin         if (numPoints == 15) {
464*fe209ef9SBlaise Bourdin           --j;
465*fe209ef9SBlaise Bourdin           if (j == 0) {j = 4;}
466*fe209ef9SBlaise Bourdin         }
467*fe209ef9SBlaise Bourdin         side_list[elem_ind[fs] + i] = j;
468*fe209ef9SBlaise Bourdin         ierr = DMPlexRestoreTransitiveClosure(dm, elem_list[elem_ind[fs] + i]-1, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);
469*fe209ef9SBlaise Bourdin 
470*fe209ef9SBlaise Bourdin       }
471*fe209ef9SBlaise Bourdin       ierr = ISRestoreIndices(stratumIS, &faces);CHKERRQ(ierr);
472*fe209ef9SBlaise Bourdin       ierr = ISDestroy(&stratumIS);CHKERRQ(ierr);
473*fe209ef9SBlaise Bourdin     }
474*fe209ef9SBlaise Bourdin     ierr = ISRestoreIndices(fsIS, &fsIdx);CHKERRQ(ierr);
475*fe209ef9SBlaise Bourdin     ierr = ISDestroy(&fsIS);CHKERRQ(ierr);
476*fe209ef9SBlaise Bourdin 
477*fe209ef9SBlaise Bourdin     /* Put side sets */
478*fe209ef9SBlaise Bourdin     for (fs=0; fs<num_fs; ++fs) {
479*fe209ef9SBlaise Bourdin       PetscStackCallStandard(ex_put_set,(exoid, EX_SIDE_SET, fsIdx[fs], &elem_list[elem_ind[fs]], &side_list[elem_ind[fs]]));
480*fe209ef9SBlaise Bourdin     }
481*fe209ef9SBlaise Bourdin     ierr = PetscFree3(elem_ind,elem_list,side_list);CHKERRQ(ierr);
482*fe209ef9SBlaise Bourdin   }
48378569bb4SMatthew G. Knepley   PetscFunctionReturn(0);
48478569bb4SMatthew G. Knepley }
48578569bb4SMatthew G. Knepley 
48678569bb4SMatthew G. Knepley /*
48778569bb4SMatthew G. Knepley   VecViewPlex_ExodusII_Nodal_Internal - Write a Vec corresponding to a nodal field to an exodus file
48878569bb4SMatthew G. Knepley 
48978569bb4SMatthew G. Knepley   Collective on v
49078569bb4SMatthew G. Knepley 
49178569bb4SMatthew G. Knepley   Input Parameters:
49278569bb4SMatthew G. Knepley + v  - The vector to be written
49378569bb4SMatthew G. Knepley . exoid - the exodus id of a file (obtained from ex_open or ex_create for instance)
49478569bb4SMatthew G. Knepley - step - the time step to write at (exodus steps are numbered starting from 1)
49578569bb4SMatthew G. Knepley 
49678569bb4SMatthew G. Knepley   Notes:
49778569bb4SMatthew G. Knepley   The exodus result nodal variable index is obtained by comparing the Vec name and the
49878569bb4SMatthew G. Knepley   names of nodal variables declared in the exodus file. For instance for a Vec named "V"
49978569bb4SMatthew G. Knepley   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
50078569bb4SMatthew G. Knepley   amongst all nodal variables.
50178569bb4SMatthew G. Knepley 
50278569bb4SMatthew G. Knepley   Level: beginner
50378569bb4SMatthew G. Knepley 
50478569bb4SMatthew G. Knepley .keywords: mesh,ExodusII
50578569bb4SMatthew G. Knepley .seealso: EXOGetVarIndex_Private(),DMPlexView_ExodusII_Internal(),VecLoadNodal_PlexEXO(),VecViewZonal_PlexEXO(),VecLoadZonal_PlexEXO()
50678569bb4SMatthew G. Knepley @*/
50778569bb4SMatthew G. Knepley PetscErrorCode VecViewPlex_ExodusII_Nodal_Internal(Vec v, int exoid, int step)
50878569bb4SMatthew G. Knepley {
50978569bb4SMatthew G. Knepley   MPI_Comm         comm;
51078569bb4SMatthew G. Knepley   PetscMPIInt      size;
51178569bb4SMatthew G. Knepley   DM               dm;
51278569bb4SMatthew G. Knepley   Vec              vNatural, vComp;
51378569bb4SMatthew G. Knepley   const PetscReal *varray;
51478569bb4SMatthew G. Knepley   const char      *vecname;
51578569bb4SMatthew G. Knepley   PetscInt         xs, xe, bs;
51678569bb4SMatthew G. Knepley   PetscBool        useNatural;
51778569bb4SMatthew G. Knepley   int              offset;
51878569bb4SMatthew G. Knepley   PetscErrorCode   ierr;
51978569bb4SMatthew G. Knepley 
52078569bb4SMatthew G. Knepley   PetscFunctionBegin;
52178569bb4SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) v, &comm);CHKERRQ(ierr);
52278569bb4SMatthew G. Knepley   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
52378569bb4SMatthew G. Knepley   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
52478569bb4SMatthew G. Knepley   ierr = DMGetUseNatural(dm, &useNatural);CHKERRQ(ierr);
52578569bb4SMatthew G. Knepley   useNatural = useNatural && size > 1 ? PETSC_TRUE : PETSC_FALSE;
52678569bb4SMatthew G. Knepley   if (useNatural) {
52778569bb4SMatthew G. Knepley     ierr = DMGetGlobalVector(dm, &vNatural);CHKERRQ(ierr);
52878569bb4SMatthew G. Knepley     ierr = DMPlexGlobalToNaturalBegin(dm, v, vNatural);CHKERRQ(ierr);
52978569bb4SMatthew G. Knepley     ierr = DMPlexGlobalToNaturalEnd(dm, v, vNatural);CHKERRQ(ierr);
53078569bb4SMatthew G. Knepley   } else {
53178569bb4SMatthew G. Knepley     vNatural = v;
53278569bb4SMatthew G. Knepley   }
53378569bb4SMatthew G. Knepley   /* Get the location of the variable in the exodus file */
53478569bb4SMatthew G. Knepley   ierr = PetscObjectGetName((PetscObject) v, &vecname);CHKERRQ(ierr);
53578569bb4SMatthew G. Knepley   ierr = EXOGetVarIndex_Private(exoid, EX_NODAL, vecname, &offset);CHKERRQ(ierr);
53678569bb4SMatthew G. Knepley   if (!offset) SETERRQ1(comm, PETSC_ERR_FILE_UNEXPECTED, "Cannot locate nodal variable %s in exodus file\n", vecname);
53778569bb4SMatthew G. Knepley   /* Write local chunk of the result in the exodus file
53878569bb4SMatthew G. Knepley      exodus stores each component of a vector-valued field as a separate variable.
53978569bb4SMatthew G. Knepley      We assume that they are stored sequentially */
54078569bb4SMatthew G. Knepley   ierr = VecGetOwnershipRange(vNatural, &xs, &xe);CHKERRQ(ierr);
54178569bb4SMatthew G. Knepley   ierr = VecGetBlockSize(vNatural, &bs);CHKERRQ(ierr);
54278569bb4SMatthew G. Knepley   if (bs == 1) {
54378569bb4SMatthew G. Knepley     ierr = VecGetArrayRead(vNatural, &varray);CHKERRQ(ierr);
5446de834b4SMatthew G. Knepley     PetscStackCallStandard(ex_put_partial_var,(exoid, step, EX_NODAL, offset, 1, xs+1, xe-xs, varray));
54578569bb4SMatthew G. Knepley     ierr = VecRestoreArrayRead(vNatural, &varray);CHKERRQ(ierr);
54678569bb4SMatthew G. Knepley   } else {
54778569bb4SMatthew G. Knepley     IS       compIS;
54878569bb4SMatthew G. Knepley     PetscInt c;
54978569bb4SMatthew G. Knepley 
55078569bb4SMatthew G. Knepley     ierr = ISCreateStride(PETSC_COMM_SELF, (xe-xs)/bs, xs, bs, &compIS);CHKERRQ(ierr);
55178569bb4SMatthew G. Knepley     for (c = 0; c < bs; ++c) {
55278569bb4SMatthew G. Knepley       ierr = ISStrideSetStride(compIS, (xe-xs)/bs, xs+c, bs);CHKERRQ(ierr);
55378569bb4SMatthew G. Knepley       ierr = VecGetSubVector(vNatural, compIS, &vComp);CHKERRQ(ierr);
55478569bb4SMatthew G. Knepley       ierr = VecGetArrayRead(vComp, &varray);CHKERRQ(ierr);
5556de834b4SMatthew G. Knepley       PetscStackCallStandard(ex_put_partial_var,(exoid, step, EX_NODAL, offset+c, 1, xs/bs+1, (xe-xs)/bs, varray));
55678569bb4SMatthew G. Knepley       ierr = VecRestoreArrayRead(vComp, &varray);CHKERRQ(ierr);
55778569bb4SMatthew G. Knepley       ierr = VecRestoreSubVector(vNatural, compIS, &vComp);CHKERRQ(ierr);
55878569bb4SMatthew G. Knepley     }
55978569bb4SMatthew G. Knepley     ierr = ISDestroy(&compIS);CHKERRQ(ierr);
56078569bb4SMatthew G. Knepley   }
56178569bb4SMatthew G. Knepley   if (useNatural) {ierr = DMRestoreGlobalVector(dm, &vNatural);CHKERRQ(ierr);}
56278569bb4SMatthew G. Knepley   PetscFunctionReturn(0);
56378569bb4SMatthew G. Knepley }
56478569bb4SMatthew G. Knepley 
56578569bb4SMatthew G. Knepley /*
56678569bb4SMatthew G. Knepley   VecLoadPlex_ExodusII_Nodal_Internal - Read a Vec corresponding to a nodal field from an exodus file
56778569bb4SMatthew G. Knepley 
56878569bb4SMatthew G. Knepley   Collective on v
56978569bb4SMatthew G. Knepley 
57078569bb4SMatthew G. Knepley   Input Parameters:
57178569bb4SMatthew G. Knepley + v  - The vector to be written
57278569bb4SMatthew G. Knepley . exoid - the exodus id of a file (obtained from ex_open or ex_create for instance)
57378569bb4SMatthew G. Knepley - step - the time step to read at (exodus steps are numbered starting from 1)
57478569bb4SMatthew G. Knepley 
57578569bb4SMatthew G. Knepley   Notes:
57678569bb4SMatthew G. Knepley   The exodus result nodal variable index is obtained by comparing the Vec name and the
57778569bb4SMatthew G. Knepley   names of nodal variables declared in the exodus file. For instance for a Vec named "V"
57878569bb4SMatthew G. Knepley   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
57978569bb4SMatthew G. Knepley   amongst all nodal variables.
58078569bb4SMatthew G. Knepley 
58178569bb4SMatthew G. Knepley   Level: beginner
58278569bb4SMatthew G. Knepley 
58378569bb4SMatthew G. Knepley .keywords: mesh, ExodusII
58478569bb4SMatthew G. Knepley .seealso: EXOGetVarIndex_Private(), DMPlexView_ExodusII_Internal(), VecViewPlex_ExodusII_Nodal_Internal(), VecViewZonal_PlexEXO(), VecLoadZonal_PlexEXO()
58578569bb4SMatthew G. Knepley */
58678569bb4SMatthew G. Knepley PetscErrorCode VecLoadPlex_ExodusII_Nodal_Internal(Vec v, int exoid, int step)
58778569bb4SMatthew G. Knepley {
58878569bb4SMatthew G. Knepley   MPI_Comm       comm;
58978569bb4SMatthew G. Knepley   PetscMPIInt    size;
59078569bb4SMatthew G. Knepley   DM             dm;
59178569bb4SMatthew G. Knepley   Vec            vNatural, vComp;
59278569bb4SMatthew G. Knepley   PetscReal     *varray;
59378569bb4SMatthew G. Knepley   const char    *vecname;
59478569bb4SMatthew G. Knepley   PetscInt       xs, xe, bs;
59578569bb4SMatthew G. Knepley   PetscBool      useNatural;
59678569bb4SMatthew G. Knepley   int            offset;
59778569bb4SMatthew G. Knepley   PetscErrorCode ierr;
59878569bb4SMatthew G. Knepley 
59978569bb4SMatthew G. Knepley   PetscFunctionBegin;
60078569bb4SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) v, &comm);CHKERRQ(ierr);
60178569bb4SMatthew G. Knepley   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
60278569bb4SMatthew G. Knepley   ierr = VecGetDM(v,&dm);CHKERRQ(ierr);
60378569bb4SMatthew G. Knepley   ierr = DMGetUseNatural(dm, &useNatural);CHKERRQ(ierr);
60478569bb4SMatthew G. Knepley   useNatural = useNatural && size > 1 ? PETSC_TRUE : PETSC_FALSE;
60578569bb4SMatthew G. Knepley   if (useNatural) {ierr = DMGetGlobalVector(dm,&vNatural);CHKERRQ(ierr);}
60678569bb4SMatthew G. Knepley   else            {vNatural = v;}
60778569bb4SMatthew G. Knepley   /* Get the location of the variable in the exodus file */
60878569bb4SMatthew G. Knepley   ierr = PetscObjectGetName((PetscObject) v, &vecname);CHKERRQ(ierr);
60978569bb4SMatthew G. Knepley   ierr = EXOGetVarIndex_Private(exoid, EX_NODAL, vecname, &offset);CHKERRQ(ierr);
61078569bb4SMatthew G. Knepley   if (!offset) SETERRQ1(comm, PETSC_ERR_FILE_UNEXPECTED, "Cannot locate nodal variable %s in exodus file", vecname);
61178569bb4SMatthew G. Knepley   /* Read local chunk from the file */
61278569bb4SMatthew G. Knepley   ierr = VecGetOwnershipRange(vNatural, &xs, &xe);CHKERRQ(ierr);
61378569bb4SMatthew G. Knepley   ierr = VecGetBlockSize(vNatural, &bs);CHKERRQ(ierr);
61478569bb4SMatthew G. Knepley   if (bs == 1) {
61578569bb4SMatthew G. Knepley     ierr = VecGetArray(vNatural, &varray);CHKERRQ(ierr);
6166de834b4SMatthew G. Knepley     PetscStackCallStandard(ex_get_partial_var,(exoid, step, EX_NODAL, offset, 1, xs+1, xe-xs, varray));
61778569bb4SMatthew G. Knepley     ierr = VecRestoreArray(vNatural, &varray);CHKERRQ(ierr);
61878569bb4SMatthew G. Knepley   } else {
61978569bb4SMatthew G. Knepley     IS       compIS;
62078569bb4SMatthew G. Knepley     PetscInt c;
62178569bb4SMatthew G. Knepley 
62278569bb4SMatthew G. Knepley     ierr = ISCreateStride(PETSC_COMM_SELF, (xe-xs)/bs, xs, bs, &compIS);CHKERRQ(ierr);
62378569bb4SMatthew G. Knepley     for (c = 0; c < bs; ++c) {
62478569bb4SMatthew G. Knepley       ierr = ISStrideSetStride(compIS, (xe-xs)/bs, xs+c, bs);CHKERRQ(ierr);
62578569bb4SMatthew G. Knepley       ierr = VecGetSubVector(vNatural, compIS, &vComp);CHKERRQ(ierr);
62678569bb4SMatthew G. Knepley       ierr = VecGetArray(vComp, &varray);CHKERRQ(ierr);
6276de834b4SMatthew G. Knepley       PetscStackCallStandard(ex_get_partial_var,(exoid, step, EX_NODAL, offset+c, 1, xs/bs+1, (xe-xs)/bs, varray));
62878569bb4SMatthew G. Knepley       ierr = VecRestoreArray(vComp, &varray);CHKERRQ(ierr);
62978569bb4SMatthew G. Knepley       ierr = VecRestoreSubVector(vNatural, compIS, &vComp);CHKERRQ(ierr);
63078569bb4SMatthew G. Knepley     }
63178569bb4SMatthew G. Knepley     ierr = ISDestroy(&compIS);CHKERRQ(ierr);
63278569bb4SMatthew G. Knepley   }
63378569bb4SMatthew G. Knepley   if (useNatural) {
63478569bb4SMatthew G. Knepley     ierr = DMPlexNaturalToGlobalBegin(dm, vNatural, v);CHKERRQ(ierr);
63578569bb4SMatthew G. Knepley     ierr = DMPlexNaturalToGlobalEnd(dm, vNatural, v);CHKERRQ(ierr);
63678569bb4SMatthew G. Knepley     ierr = DMRestoreGlobalVector(dm, &vNatural);CHKERRQ(ierr);
63778569bb4SMatthew G. Knepley   }
63878569bb4SMatthew G. Knepley   PetscFunctionReturn(0);
63978569bb4SMatthew G. Knepley }
64078569bb4SMatthew G. Knepley 
64178569bb4SMatthew G. Knepley /*
64278569bb4SMatthew G. Knepley   VecViewPlex_ExodusII_Zonal_Internal - Write a Vec corresponding to a zonal (cell based) field to an exodus file
64378569bb4SMatthew G. Knepley 
64478569bb4SMatthew G. Knepley   Collective on v
64578569bb4SMatthew G. Knepley 
64678569bb4SMatthew G. Knepley   Input Parameters:
64778569bb4SMatthew G. Knepley + v  - The vector to be written
64878569bb4SMatthew G. Knepley . exoid - the exodus id of a file (obtained from ex_open or ex_create for instance)
64978569bb4SMatthew G. Knepley - step - the time step to write at (exodus steps are numbered starting from 1)
65078569bb4SMatthew G. Knepley 
65178569bb4SMatthew G. Knepley   Notes:
65278569bb4SMatthew G. Knepley   The exodus result zonal variable index is obtained by comparing the Vec name and the
65378569bb4SMatthew G. Knepley   names of zonal variables declared in the exodus file. For instance for a Vec named "V"
65478569bb4SMatthew G. Knepley   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
65578569bb4SMatthew G. Knepley   amongst all zonal variables.
65678569bb4SMatthew G. Knepley 
65778569bb4SMatthew G. Knepley   Level: beginner
65878569bb4SMatthew G. Knepley 
65978569bb4SMatthew G. Knepley .keywords: mesh,ExodusII
66078569bb4SMatthew G. Knepley .seealso: EXOGetVarIndex_Private(),DMPlexView_ExodusII_Internal(),VecViewPlex_ExodusII_Nodal_Internal(),VecLoadPlex_ExodusII_Nodal_Internal(),VecLoadPlex_ExodusII_Zonal_Internal()
66178569bb4SMatthew G. Knepley */
66278569bb4SMatthew G. Knepley PetscErrorCode VecViewPlex_ExodusII_Zonal_Internal(Vec v, int exoid, int step)
66378569bb4SMatthew G. Knepley {
66478569bb4SMatthew G. Knepley   MPI_Comm          comm;
66578569bb4SMatthew G. Knepley   PetscMPIInt       size;
66678569bb4SMatthew G. Knepley   DM                dm;
66778569bb4SMatthew G. Knepley   Vec               vNatural, vComp;
66878569bb4SMatthew G. Knepley   const PetscReal  *varray;
66978569bb4SMatthew G. Knepley   const char       *vecname;
67078569bb4SMatthew G. Knepley   PetscInt          xs, xe, bs;
67178569bb4SMatthew G. Knepley   PetscBool         useNatural;
67278569bb4SMatthew G. Knepley   int               offset;
67378569bb4SMatthew G. Knepley   IS                compIS;
67478569bb4SMatthew G. Knepley   PetscInt         *csSize, *csID;
67578569bb4SMatthew G. Knepley   PetscInt          numCS, set, csxs = 0;
67678569bb4SMatthew G. Knepley   PetscErrorCode    ierr;
67778569bb4SMatthew G. Knepley 
67878569bb4SMatthew G. Knepley   PetscFunctionBegin;
67978569bb4SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject)v, &comm);CHKERRQ(ierr);
68078569bb4SMatthew G. Knepley   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
68178569bb4SMatthew G. Knepley   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
68278569bb4SMatthew G. Knepley   ierr = DMGetUseNatural(dm, &useNatural);CHKERRQ(ierr);
68378569bb4SMatthew G. Knepley   useNatural = useNatural && size > 1 ? PETSC_TRUE : PETSC_FALSE;
68478569bb4SMatthew G. Knepley   if (useNatural) {
68578569bb4SMatthew G. Knepley     ierr = DMGetGlobalVector(dm, &vNatural);CHKERRQ(ierr);
68678569bb4SMatthew G. Knepley     ierr = DMPlexGlobalToNaturalBegin(dm, v, vNatural);CHKERRQ(ierr);
68778569bb4SMatthew G. Knepley     ierr = DMPlexGlobalToNaturalEnd(dm, v, vNatural);CHKERRQ(ierr);
68878569bb4SMatthew G. Knepley   } else {
68978569bb4SMatthew G. Knepley     vNatural = v;
69078569bb4SMatthew G. Knepley   }
69178569bb4SMatthew G. Knepley   /* Get the location of the variable in the exodus file */
69278569bb4SMatthew G. Knepley   ierr = PetscObjectGetName((PetscObject) v, &vecname);CHKERRQ(ierr);
69378569bb4SMatthew G. Knepley   ierr = EXOGetVarIndex_Private(exoid, EX_ELEM_BLOCK, vecname, &offset);CHKERRQ(ierr);
69478569bb4SMatthew G. Knepley   if (!offset) SETERRQ1(comm, PETSC_ERR_FILE_UNEXPECTED, "Cannot locate zonal variable %s in exodus file\n", vecname);
69578569bb4SMatthew G. Knepley   /* Write local chunk of the result in the exodus file
69678569bb4SMatthew G. Knepley      exodus stores each component of a vector-valued field as a separate variable.
69778569bb4SMatthew G. Knepley      We assume that they are stored sequentially
69878569bb4SMatthew G. Knepley      Zonal variables are accessed one element block at a time, so we loop through the cell sets,
69978569bb4SMatthew G. Knepley      but once the vector has been reordered to natural size, we cannot use the label informations
70078569bb4SMatthew G. Knepley      to figure out what to save where. */
70178569bb4SMatthew G. Knepley   numCS = ex_inquire_int(exoid, EX_INQ_ELEM_BLK);
70278569bb4SMatthew G. Knepley   ierr = PetscMalloc2(numCS, &csID, numCS, &csSize);CHKERRQ(ierr);
7036de834b4SMatthew G. Knepley   PetscStackCallStandard(ex_get_ids,(exoid, EX_ELEM_BLOCK, csID));
70478569bb4SMatthew G. Knepley   for (set = 0; set < numCS; ++set) {
70578569bb4SMatthew G. Knepley     ex_block block;
70678569bb4SMatthew G. Knepley 
70778569bb4SMatthew G. Knepley     block.id   = csID[set];
70878569bb4SMatthew G. Knepley     block.type = EX_ELEM_BLOCK;
7096de834b4SMatthew G. Knepley     PetscStackCallStandard(ex_get_block_param,(exoid, &block));
71078569bb4SMatthew G. Knepley     csSize[set] = block.num_entry;
71178569bb4SMatthew G. Knepley   }
71278569bb4SMatthew G. Knepley   ierr = VecGetOwnershipRange(vNatural, &xs, &xe);CHKERRQ(ierr);
71378569bb4SMatthew G. Knepley   ierr = VecGetBlockSize(vNatural, &bs);CHKERRQ(ierr);
71478569bb4SMatthew G. Knepley   if (bs > 1) {ierr = ISCreateStride(comm, (xe-xs)/bs, xs, bs, &compIS);CHKERRQ(ierr);}
71578569bb4SMatthew G. Knepley   for (set = 0; set < numCS; set++) {
71678569bb4SMatthew G. Knepley     PetscInt csLocalSize, c;
71778569bb4SMatthew G. Knepley 
71878569bb4SMatthew G. Knepley     /* range of indices for set setID[set]: csxs:csxs + csSize[set]-1
71978569bb4SMatthew G. Knepley        local slice of zonal values:         xs/bs,xm/bs-1
72078569bb4SMatthew G. Knepley        intersection:                        max(xs/bs,csxs),min(xm/bs-1,csxs + csSize[set]-1) */
72178569bb4SMatthew G. Knepley     csLocalSize = PetscMax(0, PetscMin(xe/bs, csxs+csSize[set]) - PetscMax(xs/bs, csxs));
72278569bb4SMatthew G. Knepley     if (bs == 1) {
72378569bb4SMatthew G. Knepley       ierr = VecGetArrayRead(vNatural, &varray);CHKERRQ(ierr);
7246de834b4SMatthew G. Knepley       PetscStackCallStandard(ex_put_partial_var,(exoid, step, EX_ELEM_BLOCK, offset, csID[set], PetscMax(xs-csxs, 0)+1, csLocalSize, &varray[PetscMax(0, csxs-xs)]));
72578569bb4SMatthew G. Knepley       ierr = VecRestoreArrayRead(vNatural, &varray);CHKERRQ(ierr);
72678569bb4SMatthew G. Knepley     } else {
72778569bb4SMatthew G. Knepley       for (c = 0; c < bs; ++c) {
72878569bb4SMatthew G. Knepley         ierr = ISStrideSetStride(compIS, (xe-xs)/bs, xs+c, bs);CHKERRQ(ierr);
72978569bb4SMatthew G. Knepley         ierr = VecGetSubVector(vNatural, compIS, &vComp);CHKERRQ(ierr);
73078569bb4SMatthew G. Knepley         ierr = VecGetArrayRead(vComp, &varray);CHKERRQ(ierr);
7316de834b4SMatthew G. Knepley         PetscStackCallStandard(ex_put_partial_var,(exoid, step, EX_ELEM_BLOCK, offset+c, csID[set], PetscMax(xs/bs-csxs, 0)+1, csLocalSize, &varray[PetscMax(0, csxs-xs/bs)]));
73278569bb4SMatthew G. Knepley         ierr = VecRestoreArrayRead(vComp, &varray);CHKERRQ(ierr);
73378569bb4SMatthew G. Knepley         ierr = VecRestoreSubVector(vNatural, compIS, &vComp);CHKERRQ(ierr);
73478569bb4SMatthew G. Knepley       }
73578569bb4SMatthew G. Knepley     }
73678569bb4SMatthew G. Knepley     csxs += csSize[set];
73778569bb4SMatthew G. Knepley   }
73878569bb4SMatthew G. Knepley   ierr = PetscFree2(csID, csSize);CHKERRQ(ierr);
73978569bb4SMatthew G. Knepley   if (bs > 1) {ierr = ISDestroy(&compIS);CHKERRQ(ierr);}
74078569bb4SMatthew G. Knepley   if (useNatural) {ierr = DMRestoreGlobalVector(dm,&vNatural);CHKERRQ(ierr);}
74178569bb4SMatthew G. Knepley   PetscFunctionReturn(0);
74278569bb4SMatthew G. Knepley }
74378569bb4SMatthew G. Knepley 
74478569bb4SMatthew G. Knepley /*
74578569bb4SMatthew G. Knepley   VecLoadPlex_ExodusII_Zonal_Internal - Read a Vec corresponding to a zonal (cell based) field from an exodus file
74678569bb4SMatthew G. Knepley 
74778569bb4SMatthew G. Knepley   Collective on v
74878569bb4SMatthew G. Knepley 
74978569bb4SMatthew G. Knepley   Input Parameters:
75078569bb4SMatthew G. Knepley + v  - The vector to be written
75178569bb4SMatthew G. Knepley . exoid - the exodus id of a file (obtained from ex_open or ex_create for instance)
75278569bb4SMatthew G. Knepley - step - the time step to read at (exodus steps are numbered starting from 1)
75378569bb4SMatthew G. Knepley 
75478569bb4SMatthew G. Knepley   Notes:
75578569bb4SMatthew G. Knepley   The exodus result zonal variable index is obtained by comparing the Vec name and the
75678569bb4SMatthew G. Knepley   names of zonal variables declared in the exodus file. For instance for a Vec named "V"
75778569bb4SMatthew G. Knepley   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
75878569bb4SMatthew G. Knepley   amongst all zonal variables.
75978569bb4SMatthew G. Knepley 
76078569bb4SMatthew G. Knepley   Level: beginner
76178569bb4SMatthew G. Knepley 
76278569bb4SMatthew G. Knepley .keywords: mesh,ExodusII
76378569bb4SMatthew G. Knepley .seealso: EXOGetVarIndex_Private(), DMPlexView_ExodusII_Internal(), VecViewPlex_ExodusII_Nodal_Internal(), VecLoadPlex_ExodusII_Nodal_Internal(), VecLoadPlex_ExodusII_Zonal_Internal()
76478569bb4SMatthew G. Knepley */
76578569bb4SMatthew G. Knepley PetscErrorCode VecLoadPlex_ExodusII_Zonal_Internal(Vec v, int exoid, int step)
76678569bb4SMatthew G. Knepley {
76778569bb4SMatthew G. Knepley   MPI_Comm          comm;
76878569bb4SMatthew G. Knepley   PetscMPIInt       size;
76978569bb4SMatthew G. Knepley   DM                dm;
77078569bb4SMatthew G. Knepley   Vec               vNatural, vComp;
77178569bb4SMatthew G. Knepley   PetscReal        *varray;
77278569bb4SMatthew G. Knepley   const char       *vecname;
77378569bb4SMatthew G. Knepley   PetscInt          xs, xe, bs;
77478569bb4SMatthew G. Knepley   PetscBool         useNatural;
77578569bb4SMatthew G. Knepley   int               offset;
77678569bb4SMatthew G. Knepley   IS                compIS;
77778569bb4SMatthew G. Knepley   PetscInt         *csSize, *csID;
77878569bb4SMatthew G. Knepley   PetscInt          numCS, set, csxs = 0;
77978569bb4SMatthew G. Knepley   PetscErrorCode    ierr;
78078569bb4SMatthew G. Knepley 
78178569bb4SMatthew G. Knepley   PetscFunctionBegin;
78278569bb4SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject)v,&comm);CHKERRQ(ierr);
78378569bb4SMatthew G. Knepley   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
78478569bb4SMatthew G. Knepley   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
78578569bb4SMatthew G. Knepley   ierr = DMGetUseNatural(dm, &useNatural);CHKERRQ(ierr);
78678569bb4SMatthew G. Knepley   useNatural = useNatural && size > 1 ? PETSC_TRUE : PETSC_FALSE;
78778569bb4SMatthew G. Knepley   if (useNatural) {ierr = DMGetGlobalVector(dm,&vNatural);CHKERRQ(ierr);}
78878569bb4SMatthew G. Knepley   else            {vNatural = v;}
78978569bb4SMatthew G. Knepley   /* Get the location of the variable in the exodus file */
79078569bb4SMatthew G. Knepley   ierr = PetscObjectGetName((PetscObject) v, &vecname);CHKERRQ(ierr);
79178569bb4SMatthew G. Knepley   ierr = EXOGetVarIndex_Private(exoid, EX_ELEM_BLOCK, vecname, &offset);CHKERRQ(ierr);
79278569bb4SMatthew G. Knepley   if (!offset) SETERRQ1(comm, PETSC_ERR_FILE_UNEXPECTED, "Cannot locate zonal variable %s in exodus file\n", vecname);
79378569bb4SMatthew G. Knepley   /* Read local chunk of the result in the exodus file
79478569bb4SMatthew G. Knepley      exodus stores each component of a vector-valued field as a separate variable.
79578569bb4SMatthew G. Knepley      We assume that they are stored sequentially
79678569bb4SMatthew G. Knepley      Zonal variables are accessed one element block at a time, so we loop through the cell sets,
79778569bb4SMatthew G. Knepley      but once the vector has been reordered to natural size, we cannot use the label informations
79878569bb4SMatthew G. Knepley      to figure out what to save where. */
79978569bb4SMatthew G. Knepley   numCS = ex_inquire_int(exoid, EX_INQ_ELEM_BLK);
80078569bb4SMatthew G. Knepley   ierr = PetscMalloc2(numCS, &csID, numCS, &csSize);CHKERRQ(ierr);
8016de834b4SMatthew G. Knepley   PetscStackCallStandard(ex_get_ids,(exoid, EX_ELEM_BLOCK, csID));
80278569bb4SMatthew G. Knepley   for (set = 0; set < numCS; ++set) {
80378569bb4SMatthew G. Knepley     ex_block block;
80478569bb4SMatthew G. Knepley 
80578569bb4SMatthew G. Knepley     block.id   = csID[set];
80678569bb4SMatthew G. Knepley     block.type = EX_ELEM_BLOCK;
8076de834b4SMatthew G. Knepley     PetscStackCallStandard(ex_get_block_param,(exoid, &block));
80878569bb4SMatthew G. Knepley     csSize[set] = block.num_entry;
80978569bb4SMatthew G. Knepley   }
81078569bb4SMatthew G. Knepley   ierr = VecGetOwnershipRange(vNatural, &xs, &xe);CHKERRQ(ierr);
81178569bb4SMatthew G. Knepley   ierr = VecGetBlockSize(vNatural, &bs);CHKERRQ(ierr);
81278569bb4SMatthew G. Knepley   if (bs > 1) {ierr = ISCreateStride(comm, (xe-xs)/bs, xs, bs, &compIS);CHKERRQ(ierr);}
81378569bb4SMatthew G. Knepley   for (set = 0; set < numCS; ++set) {
81478569bb4SMatthew G. Knepley     PetscInt csLocalSize, c;
81578569bb4SMatthew G. Knepley 
81678569bb4SMatthew G. Knepley     /* range of indices for set setID[set]: csxs:csxs + csSize[set]-1
81778569bb4SMatthew G. Knepley        local slice of zonal values:         xs/bs,xm/bs-1
81878569bb4SMatthew G. Knepley        intersection:                        max(xs/bs,csxs),min(xm/bs-1,csxs + csSize[set]-1) */
81978569bb4SMatthew G. Knepley     csLocalSize = PetscMax(0, PetscMin(xe/bs, csxs+csSize[set]) - PetscMax(xs/bs, csxs));
82078569bb4SMatthew G. Knepley     if (bs == 1) {
82178569bb4SMatthew G. Knepley       ierr = VecGetArray(vNatural, &varray);CHKERRQ(ierr);
8226de834b4SMatthew G. Knepley       PetscStackCallStandard(ex_get_partial_var,(exoid, step, EX_ELEM_BLOCK, offset, csID[set], PetscMax(xs-csxs, 0)+1, csLocalSize, &varray[PetscMax(0, csxs-xs)]));
82378569bb4SMatthew G. Knepley       ierr = VecRestoreArray(vNatural, &varray);CHKERRQ(ierr);
82478569bb4SMatthew G. Knepley     } else {
82578569bb4SMatthew G. Knepley       for (c = 0; c < bs; ++c) {
82678569bb4SMatthew G. Knepley         ierr = ISStrideSetStride(compIS, (xe-xs)/bs, xs+c, bs);CHKERRQ(ierr);
82778569bb4SMatthew G. Knepley         ierr = VecGetSubVector(vNatural, compIS, &vComp);CHKERRQ(ierr);
82878569bb4SMatthew G. Knepley         ierr = VecGetArray(vComp, &varray);CHKERRQ(ierr);
8296de834b4SMatthew G. Knepley         PetscStackCallStandard(ex_get_partial_var,(exoid, step, EX_ELEM_BLOCK, offset+c, csID[set], PetscMax(xs/bs-csxs, 0)+1, csLocalSize, &varray[PetscMax(0, csxs-xs/bs)]));
83078569bb4SMatthew G. Knepley         ierr = VecRestoreArray(vComp, &varray);CHKERRQ(ierr);
83178569bb4SMatthew G. Knepley         ierr = VecRestoreSubVector(vNatural, compIS, &vComp);CHKERRQ(ierr);
83278569bb4SMatthew G. Knepley       }
83378569bb4SMatthew G. Knepley     }
83478569bb4SMatthew G. Knepley     csxs += csSize[set];
83578569bb4SMatthew G. Knepley   }
83678569bb4SMatthew G. Knepley   ierr = PetscFree2(csID, csSize);CHKERRQ(ierr);
83778569bb4SMatthew G. Knepley   if (bs > 1) {ierr = ISDestroy(&compIS);CHKERRQ(ierr);}
83878569bb4SMatthew G. Knepley   if (useNatural) {
83978569bb4SMatthew G. Knepley     ierr = DMPlexNaturalToGlobalBegin(dm, vNatural, v);CHKERRQ(ierr);
84078569bb4SMatthew G. Knepley     ierr = DMPlexNaturalToGlobalEnd(dm, vNatural, v);CHKERRQ(ierr);
84178569bb4SMatthew G. Knepley     ierr = DMRestoreGlobalVector(dm, &vNatural);CHKERRQ(ierr);
84278569bb4SMatthew G. Knepley   }
84378569bb4SMatthew G. Knepley   PetscFunctionReturn(0);
84478569bb4SMatthew G. Knepley }
845b53c8456SSatish Balay #endif
84678569bb4SMatthew G. Knepley 
84733751fbdSMichael Lange /*@C
848eaf898f9SPatrick Sanan   DMPlexCreateExodusFromFile - Create a DMPlex mesh from an ExodusII file.
84933751fbdSMichael Lange 
85033751fbdSMichael Lange   Collective on comm
85133751fbdSMichael Lange 
85233751fbdSMichael Lange   Input Parameters:
85333751fbdSMichael Lange + comm  - The MPI communicator
85433751fbdSMichael Lange . filename - The name of the ExodusII file
85533751fbdSMichael Lange - interpolate - Create faces and edges in the mesh
85633751fbdSMichael Lange 
85733751fbdSMichael Lange   Output Parameter:
85833751fbdSMichael Lange . dm  - The DM object representing the mesh
85933751fbdSMichael Lange 
86033751fbdSMichael Lange   Level: beginner
86133751fbdSMichael Lange 
86233751fbdSMichael Lange .keywords: mesh,ExodusII
86333751fbdSMichael Lange .seealso: DMPLEX, DMCreate(), DMPlexCreateExodus()
86433751fbdSMichael Lange @*/
86533751fbdSMichael Lange PetscErrorCode DMPlexCreateExodusFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm)
86633751fbdSMichael Lange {
86733751fbdSMichael Lange   PetscMPIInt    rank;
86833751fbdSMichael Lange   PetscErrorCode ierr;
86933751fbdSMichael Lange #if defined(PETSC_HAVE_EXODUSII)
870e84f7031SBlaise Bourdin   int   CPU_word_size = sizeof(PetscReal), IO_word_size = 0, exoid = -1;
87133751fbdSMichael Lange   float version;
87233751fbdSMichael Lange #endif
87333751fbdSMichael Lange 
87433751fbdSMichael Lange   PetscFunctionBegin;
87533751fbdSMichael Lange   PetscValidCharPointer(filename, 2);
87633751fbdSMichael Lange   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
87733751fbdSMichael Lange #if defined(PETSC_HAVE_EXODUSII)
87833751fbdSMichael Lange   if (!rank) {
87933751fbdSMichael Lange     exoid = ex_open(filename, EX_READ, &CPU_word_size, &IO_word_size, &version);
88033751fbdSMichael Lange     if (exoid <= 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, "ex_open(\"%s\",...) did not return a valid file ID", filename);
88133751fbdSMichael Lange   }
88233751fbdSMichael Lange   ierr = DMPlexCreateExodus(comm, exoid, interpolate, dm);CHKERRQ(ierr);
8836de834b4SMatthew G. Knepley   if (!rank) {PetscStackCallStandard(ex_close,(exoid));}
88433751fbdSMichael Lange #else
88533751fbdSMichael Lange   SETERRQ(comm, PETSC_ERR_SUP, "This method requires ExodusII support. Reconfigure using --download-exodusii");
88633751fbdSMichael Lange #endif
88733751fbdSMichael Lange   PetscFunctionReturn(0);
88833751fbdSMichael Lange }
88933751fbdSMichael Lange 
890552f7358SJed Brown /*@
89133751fbdSMichael Lange   DMPlexCreateExodus - Create a DMPlex mesh from an ExodusII file ID.
892552f7358SJed Brown 
893552f7358SJed Brown   Collective on comm
894552f7358SJed Brown 
895552f7358SJed Brown   Input Parameters:
896552f7358SJed Brown + comm  - The MPI communicator
897552f7358SJed Brown . exoid - The ExodusII id associated with a exodus file and obtained using ex_open
898552f7358SJed Brown - interpolate - Create faces and edges in the mesh
899552f7358SJed Brown 
900552f7358SJed Brown   Output Parameter:
901552f7358SJed Brown . dm  - The DM object representing the mesh
902552f7358SJed Brown 
903552f7358SJed Brown   Level: beginner
904552f7358SJed Brown 
905552f7358SJed Brown .keywords: mesh,ExodusII
906e84e7769SJed Brown .seealso: DMPLEX, DMCreate()
907552f7358SJed Brown @*/
908552f7358SJed Brown PetscErrorCode DMPlexCreateExodus(MPI_Comm comm, PetscInt exoid, PetscBool interpolate, DM *dm)
909552f7358SJed Brown {
910552f7358SJed Brown #if defined(PETSC_HAVE_EXODUSII)
911552f7358SJed Brown   PetscMPIInt    num_proc, rank;
912552f7358SJed Brown   PetscSection   coordSection;
913552f7358SJed Brown   Vec            coordinates;
914552f7358SJed Brown   PetscScalar    *coords;
915552f7358SJed Brown   PetscInt       coordSize, v;
916552f7358SJed Brown   PetscErrorCode ierr;
917552f7358SJed Brown   /* Read from ex_get_init() */
918552f7358SJed Brown   char title[PETSC_MAX_PATH_LEN+1];
919552f7358SJed Brown   int  dim    = 0, numVertices = 0, numCells = 0;
920552f7358SJed Brown   int  num_cs = 0, num_vs = 0, num_fs = 0;
921552f7358SJed Brown #endif
922552f7358SJed Brown 
923552f7358SJed Brown   PetscFunctionBegin;
924552f7358SJed Brown #if defined(PETSC_HAVE_EXODUSII)
925552f7358SJed Brown   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
926552f7358SJed Brown   ierr = MPI_Comm_size(comm, &num_proc);CHKERRQ(ierr);
927552f7358SJed Brown   ierr = DMCreate(comm, dm);CHKERRQ(ierr);
928552f7358SJed Brown   ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr);
929552f7358SJed Brown   /* Open EXODUS II file and read basic informations on rank 0, then broadcast to all processors */
930552f7358SJed Brown   if (!rank) {
93139bba695SBarry Smith     ierr = PetscMemzero(title,(PETSC_MAX_PATH_LEN+1)*sizeof(char));CHKERRQ(ierr);
9326de834b4SMatthew G. Knepley     PetscStackCallStandard(ex_get_init,(exoid, title, &dim, &numVertices, &numCells, &num_cs, &num_vs, &num_fs));
933552f7358SJed Brown     if (!num_cs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Exodus file does not contain any cell set\n");
934552f7358SJed Brown   }
935552f7358SJed Brown   ierr = MPI_Bcast(title, PETSC_MAX_PATH_LEN+1, MPI_CHAR, 0, comm);CHKERRQ(ierr);
936552f7358SJed Brown   ierr = MPI_Bcast(&dim, 1, MPI_INT, 0, comm);CHKERRQ(ierr);
937552f7358SJed Brown   ierr = PetscObjectSetName((PetscObject) *dm, title);CHKERRQ(ierr);
938c73cfb54SMatthew G. Knepley   ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr);
939552f7358SJed Brown   ierr = DMPlexSetChart(*dm, 0, numCells+numVertices);CHKERRQ(ierr);
940552f7358SJed Brown 
941552f7358SJed Brown   /* Read cell sets information */
942552f7358SJed Brown   if (!rank) {
943552f7358SJed Brown     PetscInt *cone;
944552f7358SJed Brown     int      c, cs, c_loc, v, v_loc;
945552f7358SJed Brown     /* Read from ex_get_elem_blk_ids() */
946552f7358SJed Brown     int *cs_id;
947552f7358SJed Brown     /* Read from ex_get_elem_block() */
948552f7358SJed Brown     char buffer[PETSC_MAX_PATH_LEN+1];
949552f7358SJed Brown     int  num_cell_in_set, num_vertex_per_cell, num_attr;
950552f7358SJed Brown     /* Read from ex_get_elem_conn() */
951552f7358SJed Brown     int *cs_connect;
952552f7358SJed Brown 
953552f7358SJed Brown     /* Get cell sets IDs */
954785e854fSJed Brown     ierr = PetscMalloc1(num_cs, &cs_id);CHKERRQ(ierr);
9556de834b4SMatthew G. Knepley     PetscStackCallStandard(ex_get_ids,(exoid, EX_ELEM_BLOCK, cs_id));
956552f7358SJed Brown     /* Read the cell set connectivity table and build mesh topology
957552f7358SJed Brown        EXO standard requires that cells in cell sets be numbered sequentially and be pairwise disjoint. */
958552f7358SJed Brown     /* First set sizes */
959552f7358SJed Brown     for (cs = 0, c = 0; cs < num_cs; cs++) {
9606de834b4SMatthew G. Knepley       PetscStackCallStandard(ex_get_block,(exoid, EX_ELEM_BLOCK, cs_id[cs], buffer, &num_cell_in_set,&num_vertex_per_cell, 0, 0, &num_attr));
961552f7358SJed Brown       for (c_loc = 0; c_loc < num_cell_in_set; ++c_loc, ++c) {
962552f7358SJed Brown         ierr = DMPlexSetConeSize(*dm, c, num_vertex_per_cell);CHKERRQ(ierr);
963552f7358SJed Brown       }
964552f7358SJed Brown     }
965552f7358SJed Brown     ierr = DMSetUp(*dm);CHKERRQ(ierr);
966552f7358SJed Brown     for (cs = 0, c = 0; cs < num_cs; cs++) {
9676de834b4SMatthew G. Knepley       PetscStackCallStandard(ex_get_block,(exoid, EX_ELEM_BLOCK, cs_id[cs], buffer, &num_cell_in_set, &num_vertex_per_cell, 0, 0, &num_attr));
968dcca6d9dSJed Brown       ierr = PetscMalloc2(num_vertex_per_cell*num_cell_in_set,&cs_connect,num_vertex_per_cell,&cone);CHKERRQ(ierr);
9696de834b4SMatthew G. Knepley       PetscStackCallStandard(ex_get_conn,(exoid, EX_ELEM_BLOCK, cs_id[cs], cs_connect,NULL,NULL));
970eaf898f9SPatrick Sanan       /* EXO uses Fortran-based indexing, DMPlex uses C-style and numbers cell first then vertices. */
971552f7358SJed Brown       for (c_loc = 0, v = 0; c_loc < num_cell_in_set; ++c_loc, ++c) {
972552f7358SJed Brown         for (v_loc = 0; v_loc < num_vertex_per_cell; ++v_loc, ++v) {
973552f7358SJed Brown           cone[v_loc] = cs_connect[v]+numCells-1;
974552f7358SJed Brown         }
975731dcdf4SMatthew G. Knepley         if (dim == 3) {
9762e1b13c2SMatthew G. Knepley           /* Tetrahedra are inverted */
9772e1b13c2SMatthew G. Knepley           if (num_vertex_per_cell == 4) {
9782e1b13c2SMatthew G. Knepley             PetscInt tmp = cone[0];
9792e1b13c2SMatthew G. Knepley             cone[0] = cone[1];
9802e1b13c2SMatthew G. Knepley             cone[1] = tmp;
9812e1b13c2SMatthew G. Knepley           }
9822e1b13c2SMatthew G. Knepley           /* Hexahedra are inverted */
9832e1b13c2SMatthew G. Knepley           if (num_vertex_per_cell == 8) {
9842e1b13c2SMatthew G. Knepley             PetscInt tmp = cone[1];
9852e1b13c2SMatthew G. Knepley             cone[1] = cone[3];
9862e1b13c2SMatthew G. Knepley             cone[3] = tmp;
9872e1b13c2SMatthew G. Knepley           }
988731dcdf4SMatthew G. Knepley         }
989552f7358SJed Brown         ierr = DMPlexSetCone(*dm, c, cone);CHKERRQ(ierr);
990c58f1c22SToby Isaac         ierr = DMSetLabelValue(*dm, "Cell Sets", c, cs_id[cs]);CHKERRQ(ierr);
991552f7358SJed Brown       }
992552f7358SJed Brown       ierr = PetscFree2(cs_connect,cone);CHKERRQ(ierr);
993552f7358SJed Brown     }
994552f7358SJed Brown     ierr = PetscFree(cs_id);CHKERRQ(ierr);
995552f7358SJed Brown   }
996552f7358SJed Brown   ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr);
997552f7358SJed Brown   ierr = DMPlexStratify(*dm);CHKERRQ(ierr);
998552f7358SJed Brown   if (interpolate) {
9995fd9971aSMatthew G. Knepley     DM idm;
1000552f7358SJed Brown 
10019f074e33SMatthew G Knepley     ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr);
1002552f7358SJed Brown     ierr = DMDestroy(dm);CHKERRQ(ierr);
1003552f7358SJed Brown     *dm  = idm;
1004552f7358SJed Brown   }
1005552f7358SJed Brown 
1006552f7358SJed Brown   /* Create vertex set label */
1007552f7358SJed Brown   if (!rank && (num_vs > 0)) {
1008552f7358SJed Brown     int vs, v;
1009552f7358SJed Brown     /* Read from ex_get_node_set_ids() */
1010552f7358SJed Brown     int *vs_id;
1011552f7358SJed Brown     /* Read from ex_get_node_set_param() */
1012f958083aSBlaise Bourdin     int num_vertex_in_set;
1013552f7358SJed Brown     /* Read from ex_get_node_set() */
1014552f7358SJed Brown     int *vs_vertex_list;
1015552f7358SJed Brown 
1016552f7358SJed Brown     /* Get vertex set ids */
1017785e854fSJed Brown     ierr = PetscMalloc1(num_vs, &vs_id);CHKERRQ(ierr);
10186de834b4SMatthew G. Knepley     PetscStackCallStandard(ex_get_ids,(exoid, EX_NODE_SET, vs_id));
1019552f7358SJed Brown     for (vs = 0; vs < num_vs; ++vs) {
10206de834b4SMatthew G. Knepley       PetscStackCallStandard(ex_get_set_param,(exoid, EX_NODE_SET, vs_id[vs], &num_vertex_in_set, NULL));
1021785e854fSJed Brown       ierr = PetscMalloc1(num_vertex_in_set, &vs_vertex_list);CHKERRQ(ierr);
10226de834b4SMatthew G. Knepley       PetscStackCallStandard(ex_get_set,(exoid, EX_NODE_SET, vs_id[vs], vs_vertex_list, NULL));
1023552f7358SJed Brown       for (v = 0; v < num_vertex_in_set; ++v) {
1024c58f1c22SToby Isaac         ierr = DMSetLabelValue(*dm, "Vertex Sets", vs_vertex_list[v]+numCells-1, vs_id[vs]);CHKERRQ(ierr);
1025552f7358SJed Brown       }
1026552f7358SJed Brown       ierr = PetscFree(vs_vertex_list);CHKERRQ(ierr);
1027552f7358SJed Brown     }
1028552f7358SJed Brown     ierr = PetscFree(vs_id);CHKERRQ(ierr);
1029552f7358SJed Brown   }
1030552f7358SJed Brown   /* Read coordinates */
103169d8a9ceSMatthew G. Knepley   ierr = DMGetCoordinateSection(*dm, &coordSection);CHKERRQ(ierr);
1032552f7358SJed Brown   ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr);
1033552f7358SJed Brown   ierr = PetscSectionSetFieldComponents(coordSection, 0, dim);CHKERRQ(ierr);
1034552f7358SJed Brown   ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr);
1035552f7358SJed Brown   for (v = numCells; v < numCells+numVertices; ++v) {
1036552f7358SJed Brown     ierr = PetscSectionSetDof(coordSection, v, dim);CHKERRQ(ierr);
1037552f7358SJed Brown     ierr = PetscSectionSetFieldDof(coordSection, v, 0, dim);CHKERRQ(ierr);
1038552f7358SJed Brown   }
1039552f7358SJed Brown   ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr);
1040552f7358SJed Brown   ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr);
10418b9ced59SLisandro Dalcin   ierr = VecCreate(PETSC_COMM_SELF, &coordinates);CHKERRQ(ierr);
1042552f7358SJed Brown   ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr);
1043552f7358SJed Brown   ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr);
10444e90ef8eSMatthew G. Knepley   ierr = VecSetBlockSize(coordinates, dim);CHKERRQ(ierr);
10452eb5907fSJed Brown   ierr = VecSetType(coordinates,VECSTANDARD);CHKERRQ(ierr);
1046552f7358SJed Brown   ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr);
10470aba08f6SKarl Rupp   if (!rank) {
1048e84f7031SBlaise Bourdin     PetscReal *x, *y, *z;
1049552f7358SJed Brown 
1050dcca6d9dSJed Brown     ierr = PetscMalloc3(numVertices,&x,numVertices,&y,numVertices,&z);CHKERRQ(ierr);
10516de834b4SMatthew G. Knepley     PetscStackCallStandard(ex_get_coord,(exoid, x, y, z));
10520d644c17SKarl Rupp     if (dim > 0) {
10530d644c17SKarl Rupp       for (v = 0; v < numVertices; ++v) coords[v*dim+0] = x[v];
10540d644c17SKarl Rupp     }
10550d644c17SKarl Rupp     if (dim > 1) {
10560d644c17SKarl Rupp       for (v = 0; v < numVertices; ++v) coords[v*dim+1] = y[v];
10570d644c17SKarl Rupp     }
10580d644c17SKarl Rupp     if (dim > 2) {
10590d644c17SKarl Rupp       for (v = 0; v < numVertices; ++v) coords[v*dim+2] = z[v];
10600d644c17SKarl Rupp     }
1061552f7358SJed Brown     ierr = PetscFree3(x,y,z);CHKERRQ(ierr);
1062552f7358SJed Brown   }
1063552f7358SJed Brown   ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr);
1064552f7358SJed Brown   ierr = DMSetCoordinatesLocal(*dm, coordinates);CHKERRQ(ierr);
1065552f7358SJed Brown   ierr = VecDestroy(&coordinates);CHKERRQ(ierr);
1066552f7358SJed Brown 
1067552f7358SJed Brown   /* Create side set label */
1068552f7358SJed Brown   if (!rank && interpolate && (num_fs > 0)) {
1069552f7358SJed Brown     int fs, f, voff;
1070552f7358SJed Brown     /* Read from ex_get_side_set_ids() */
1071552f7358SJed Brown     int *fs_id;
1072552f7358SJed Brown     /* Read from ex_get_side_set_param() */
1073f958083aSBlaise Bourdin     int num_side_in_set;
1074552f7358SJed Brown     /* Read from ex_get_side_set_node_list() */
1075552f7358SJed Brown     int *fs_vertex_count_list, *fs_vertex_list;
1076ef073283Smichael_afanasiev     /* Read side set labels */
1077ef073283Smichael_afanasiev     char fs_name[MAX_STR_LENGTH+1];
1078552f7358SJed Brown 
1079552f7358SJed Brown     /* Get side set ids */
1080785e854fSJed Brown     ierr = PetscMalloc1(num_fs, &fs_id);CHKERRQ(ierr);
10816de834b4SMatthew G. Knepley     PetscStackCallStandard(ex_get_ids,(exoid, EX_SIDE_SET, fs_id));
1082552f7358SJed Brown     for (fs = 0; fs < num_fs; ++fs) {
10836de834b4SMatthew G. Knepley       PetscStackCallStandard(ex_get_set_param,(exoid, EX_SIDE_SET, fs_id[fs], &num_side_in_set, NULL));
1084dcca6d9dSJed Brown       ierr = PetscMalloc2(num_side_in_set,&fs_vertex_count_list,num_side_in_set*4,&fs_vertex_list);CHKERRQ(ierr);
10856de834b4SMatthew G. Knepley       PetscStackCallStandard(ex_get_side_set_node_list,(exoid, fs_id[fs], fs_vertex_count_list, fs_vertex_list));
1086ef073283Smichael_afanasiev       /* Get the specific name associated with this side set ID. */
1087ef073283Smichael_afanasiev       int fs_name_err = ex_get_name(exoid, EX_SIDE_SET, fs_id[fs], fs_name);
1088552f7358SJed Brown       for (f = 0, voff = 0; f < num_side_in_set; ++f) {
10890298fd71SBarry Smith         const PetscInt *faces   = NULL;
1090552f7358SJed Brown         PetscInt       faceSize = fs_vertex_count_list[f], numFaces;
1091552f7358SJed Brown         PetscInt       faceVertices[4], v;
1092552f7358SJed Brown 
1093552f7358SJed Brown         if (faceSize > 4) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "ExodusII side cannot have %d > 4 vertices", faceSize);
1094552f7358SJed Brown         for (v = 0; v < faceSize; ++v, ++voff) {
1095552f7358SJed Brown           faceVertices[v] = fs_vertex_list[voff]+numCells-1;
1096552f7358SJed Brown         }
1097552f7358SJed Brown         ierr = DMPlexGetFullJoin(*dm, faceSize, faceVertices, &numFaces, &faces);CHKERRQ(ierr);
1098552f7358SJed Brown         if (numFaces != 1) SETERRQ3(comm, PETSC_ERR_ARG_WRONG, "Invalid ExodusII side %d in set %d maps to %d faces", f, fs, numFaces);
1099c58f1c22SToby Isaac         ierr = DMSetLabelValue(*dm, "Face Sets", faces[0], fs_id[fs]);CHKERRQ(ierr);
1100ef073283Smichael_afanasiev         /* Only add the label if one has been detected for this side set. */
1101ef073283Smichael_afanasiev         if (!fs_name_err) {
1102ef073283Smichael_afanasiev           ierr = DMSetLabelValue(*dm, fs_name, faces[0], fs_id[fs]);CHKERRQ(ierr);
1103ef073283Smichael_afanasiev         }
1104552f7358SJed Brown         ierr = DMPlexRestoreJoin(*dm, faceSize, faceVertices, &numFaces, &faces);CHKERRQ(ierr);
1105552f7358SJed Brown       }
1106552f7358SJed Brown       ierr = PetscFree2(fs_vertex_count_list,fs_vertex_list);CHKERRQ(ierr);
1107552f7358SJed Brown     }
1108552f7358SJed Brown     ierr = PetscFree(fs_id);CHKERRQ(ierr);
1109552f7358SJed Brown   }
1110552f7358SJed Brown #else
1111552f7358SJed Brown   SETERRQ(comm, PETSC_ERR_SUP, "This method requires ExodusII support. Reconfigure using --download-exodusii");
1112552f7358SJed Brown #endif
1113552f7358SJed Brown   PetscFunctionReturn(0);
1114552f7358SJed Brown }
1115