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; 10878569bb4SMatthew G. Knepley /* Coordinate Variables */ 10978569bb4SMatthew G. Knepley DM cdm; 11078569bb4SMatthew G. Knepley PetscSection section; 11178569bb4SMatthew G. Knepley Vec coord; 11278569bb4SMatthew G. Knepley PetscInt **nodes; 113eae8a387SMatthew G. Knepley PetscInt depth, d, dim, skipCells = 0; 11478569bb4SMatthew G. Knepley PetscInt pStart, pEnd, p, cStart, cEnd, numCells, vStart, vEnd, numVertices, eStart, eEnd, numEdges, fStart, fEnd, numFaces, numNodes; 11578569bb4SMatthew G. Knepley PetscInt num_vs, num_fs; 11678569bb4SMatthew G. Knepley PetscMPIInt rank, size; 11778569bb4SMatthew G. Knepley const char *dmName; 11878569bb4SMatthew G. Knepley PetscErrorCode ierr; 11978569bb4SMatthew G. Knepley 12078569bb4SMatthew G. Knepley PetscFunctionBegin; 12178569bb4SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr); 12278569bb4SMatthew G. Knepley ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 12378569bb4SMatthew G. Knepley ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 12478569bb4SMatthew G. Knepley /* --- Get DM info --- */ 12578569bb4SMatthew G. Knepley ierr = PetscObjectGetName((PetscObject) dm, &dmName);CHKERRQ(ierr); 12678569bb4SMatthew G. Knepley ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 12778569bb4SMatthew G. Knepley ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 12878569bb4SMatthew G. Knepley ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 12978569bb4SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 13078569bb4SMatthew G. Knepley ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); 13178569bb4SMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr); 13278569bb4SMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 13378569bb4SMatthew G. Knepley numCells = cEnd - cStart; 13478569bb4SMatthew G. Knepley numEdges = eEnd - eStart; 13578569bb4SMatthew G. Knepley numVertices = vEnd - vStart; 13678569bb4SMatthew G. Knepley if (depth == 3) {numFaces = fEnd - fStart;} 13778569bb4SMatthew G. Knepley else {numFaces = 0;} 13878569bb4SMatthew G. Knepley ierr = DMGetLabelSize(dm, "Cell Sets", &num_cs);CHKERRQ(ierr); 13978569bb4SMatthew G. Knepley ierr = DMGetLabelSize(dm, "Vertex Sets", &num_vs);CHKERRQ(ierr); 14078569bb4SMatthew G. Knepley ierr = DMGetLabelSize(dm, "Face Sets", &num_fs);CHKERRQ(ierr); 14178569bb4SMatthew G. Knepley ierr = DMGetCoordinatesLocal(dm, &coord);CHKERRQ(ierr); 14278569bb4SMatthew G. Knepley ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 14378569bb4SMatthew G. Knepley if (num_cs > 0) { 14478569bb4SMatthew G. Knepley ierr = DMGetLabel(dm, "Cell Sets", &csLabel);CHKERRQ(ierr); 14578569bb4SMatthew G. Knepley ierr = DMLabelGetValueIS(csLabel, &csIS);CHKERRQ(ierr); 14678569bb4SMatthew G. Knepley ierr = ISGetIndices(csIS, &csIdx);CHKERRQ(ierr); 14778569bb4SMatthew G. Knepley } 14878569bb4SMatthew G. Knepley ierr = PetscMalloc1(num_cs, &nodes);CHKERRQ(ierr); 14978569bb4SMatthew G. Knepley /* Set element type for each block and compute total number of nodes */ 15078569bb4SMatthew G. Knepley ierr = PetscMalloc1(num_cs, &type);CHKERRQ(ierr); 15178569bb4SMatthew G. Knepley numNodes = numVertices; 15278569bb4SMatthew G. Knepley if (degree == 2) {numNodes += numEdges;} 15378569bb4SMatthew G. Knepley cellsNotInConnectivity = numCells; 15478569bb4SMatthew G. Knepley for (cs = 0; cs < num_cs; ++cs) { 15578569bb4SMatthew G. Knepley IS stratumIS; 15678569bb4SMatthew G. Knepley const PetscInt *cells; 15778569bb4SMatthew G. Knepley PetscScalar *xyz = NULL; 15878569bb4SMatthew G. Knepley PetscInt csSize, closureSize; 15978569bb4SMatthew G. Knepley PetscInt nodesTriP1[4] = {3,0,0,0}; 16078569bb4SMatthew G. Knepley PetscInt nodesTriP2[4] = {3,3,0,0}; 16178569bb4SMatthew G. Knepley PetscInt nodesQuadP1[4] = {4,0,0,0}; 16278569bb4SMatthew G. Knepley PetscInt nodesQuadP2[4] = {4,4,0,1}; 16378569bb4SMatthew G. Knepley PetscInt nodesTetP1[4] = {4,0,0,0}; 16478569bb4SMatthew G. Knepley PetscInt nodesTetP2[4] = {4,6,0,0}; 16578569bb4SMatthew G. Knepley PetscInt nodesHexP1[4] = {8,0,0,0}; 16678569bb4SMatthew G. Knepley PetscInt nodesHexP2[4] = {8,12,6,1}; 16778569bb4SMatthew G. Knepley 16878569bb4SMatthew G. Knepley ierr = DMLabelGetStratumIS(csLabel, csIdx[cs], &stratumIS);CHKERRQ(ierr); 16978569bb4SMatthew G. Knepley ierr = ISGetIndices(stratumIS, &cells);CHKERRQ(ierr); 17078569bb4SMatthew G. Knepley ierr = ISGetSize(stratumIS, &csSize);CHKERRQ(ierr); 17178569bb4SMatthew G. Knepley ierr = DMPlexVecGetClosure(cdm, NULL, coord, cells[0], &closureSize, &xyz);CHKERRQ(ierr); 17278569bb4SMatthew G. Knepley switch (dim) { 17378569bb4SMatthew G. Knepley case 2: 17478569bb4SMatthew G. Knepley if (closureSize == 3*dim) {type[cs] = TRI;} 17578569bb4SMatthew G. Knepley else if (closureSize == 4*dim) {type[cs] = QUAD;} 17678569bb4SMatthew 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); 17778569bb4SMatthew G. Knepley break; 17878569bb4SMatthew G. Knepley case 3: 17978569bb4SMatthew G. Knepley if (closureSize == 4*dim) {type[cs] = TET;} 18078569bb4SMatthew G. Knepley else if (closureSize == 8*dim) {type[cs] = HEX;} 18178569bb4SMatthew 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); 18278569bb4SMatthew G. Knepley break; 18378569bb4SMatthew G. Knepley default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %D not handled by ExodusII viewer", dim); 18478569bb4SMatthew G. Knepley } 18578569bb4SMatthew G. Knepley if ((degree == 2) && (type[cs] == QUAD)) {numNodes += csSize;} 18678569bb4SMatthew G. Knepley if ((degree == 2) && (type[cs] == HEX)) {numNodes += csSize; numNodes += numFaces;} 18778569bb4SMatthew G. Knepley ierr = DMPlexVecRestoreClosure(cdm, NULL, coord, cells[0], &closureSize, &xyz);CHKERRQ(ierr); 18878569bb4SMatthew G. Knepley /* Set nodes and Element type */ 18978569bb4SMatthew G. Knepley if (type[cs] == TRI) { 19078569bb4SMatthew G. Knepley if (degree == 1) nodes[cs] = nodesTriP1; 19178569bb4SMatthew G. Knepley else if (degree == 2) nodes[cs] = nodesTriP2; 19278569bb4SMatthew G. Knepley } else if (type[cs] == QUAD) { 19378569bb4SMatthew G. Knepley if (degree == 1) nodes[cs] = nodesQuadP1; 19478569bb4SMatthew G. Knepley else if (degree == 2) nodes[cs] = nodesQuadP2; 19578569bb4SMatthew G. Knepley } else if (type[cs] == TET) { 19678569bb4SMatthew G. Knepley if (degree == 1) nodes[cs] = nodesTetP1; 19778569bb4SMatthew G. Knepley else if (degree == 2) nodes[cs] = nodesTetP2; 19878569bb4SMatthew G. Knepley } else if (type[cs] == HEX) { 19978569bb4SMatthew G. Knepley if (degree == 1) nodes[cs] = nodesHexP1; 20078569bb4SMatthew G. Knepley else if (degree == 2) nodes[cs] = nodesHexP2; 20178569bb4SMatthew G. Knepley } 20278569bb4SMatthew G. Knepley /* Compute the number of cells not in the connectivity table */ 20378569bb4SMatthew G. Knepley cellsNotInConnectivity -= nodes[cs][3]*csSize; 20478569bb4SMatthew G. Knepley 20578569bb4SMatthew G. Knepley ierr = ISRestoreIndices(stratumIS, &cells);CHKERRQ(ierr); 20678569bb4SMatthew G. Knepley ierr = ISDestroy(&stratumIS);CHKERRQ(ierr); 20778569bb4SMatthew G. Knepley } 2086de834b4SMatthew G. Knepley if (num_cs > 0) {PetscStackCallStandard(ex_put_init,(exoid, dmName, dim, numNodes, numCells, num_cs, num_vs, num_fs));} 20978569bb4SMatthew G. Knepley /* --- Connectivity --- */ 21078569bb4SMatthew G. Knepley for (cs = 0; cs < num_cs; ++cs) { 21178569bb4SMatthew G. Knepley IS stratumIS; 21278569bb4SMatthew G. Knepley const PetscInt *cells; 213*e2c9586dSBlaise Bourdin PetscInt *connect, off = 0; 214eae8a387SMatthew G. Knepley PetscInt edgesInClosure = 0, facesInClosure = 0, verticesInClosure = 0; 21578569bb4SMatthew G. Knepley PetscInt csSize, c, connectSize, closureSize; 21678569bb4SMatthew G. Knepley char *elem_type = NULL; 21778569bb4SMatthew G. Knepley char elem_type_tri3[] = "TRI3", elem_type_quad4[] = "QUAD4"; 21878569bb4SMatthew G. Knepley char elem_type_tri6[] = "TRI6", elem_type_quad9[] = "QUAD9"; 21978569bb4SMatthew G. Knepley char elem_type_tet4[] = "TET4", elem_type_hex8[] = "HEX8"; 22078569bb4SMatthew G. Knepley char elem_type_tet10[] = "TET10", elem_type_hex27[] = "HEX27"; 22178569bb4SMatthew G. Knepley 22278569bb4SMatthew G. Knepley ierr = DMLabelGetStratumIS(csLabel, csIdx[cs], &stratumIS);CHKERRQ(ierr); 22378569bb4SMatthew G. Knepley ierr = ISGetIndices(stratumIS, &cells);CHKERRQ(ierr); 22478569bb4SMatthew G. Knepley ierr = ISGetSize(stratumIS, &csSize);CHKERRQ(ierr); 22578569bb4SMatthew G. Knepley /* Set Element type */ 22678569bb4SMatthew G. Knepley if (type[cs] == TRI) { 22778569bb4SMatthew G. Knepley if (degree == 1) elem_type = elem_type_tri3; 22878569bb4SMatthew G. Knepley else if (degree == 2) elem_type = elem_type_tri6; 22978569bb4SMatthew G. Knepley } else if (type[cs] == QUAD) { 23078569bb4SMatthew G. Knepley if (degree == 1) elem_type = elem_type_quad4; 23178569bb4SMatthew G. Knepley else if (degree == 2) elem_type = elem_type_quad9; 23278569bb4SMatthew G. Knepley } else if (type[cs] == TET) { 23378569bb4SMatthew G. Knepley if (degree == 1) elem_type = elem_type_tet4; 23478569bb4SMatthew G. Knepley else if (degree == 2) elem_type = elem_type_tet10; 23578569bb4SMatthew G. Knepley } else if (type[cs] == HEX) { 23678569bb4SMatthew G. Knepley if (degree == 1) elem_type = elem_type_hex8; 23778569bb4SMatthew G. Knepley else if (degree == 2) elem_type = elem_type_hex27; 23878569bb4SMatthew G. Knepley } 23978569bb4SMatthew G. Knepley connectSize = nodes[cs][0] + nodes[cs][1] + nodes[cs][2] + nodes[cs][3]; 240*e2c9586dSBlaise Bourdin ierr = PetscMalloc1(PetscMax(27,connectSize)*csSize, &connect);CHKERRQ(ierr); 241822047bbSBlaise Bourdin PetscStackCallStandard(ex_put_block,(exoid, EX_ELEM_BLOCK, csIdx[cs], elem_type, csSize, connectSize, 0, 0, 1)); 24278569bb4SMatthew G. Knepley /* Find number of vertices, edges, and faces in the closure */ 24378569bb4SMatthew G. Knepley verticesInClosure = nodes[cs][0]; 24478569bb4SMatthew G. Knepley if (depth > 1) { 24578569bb4SMatthew G. Knepley if (dim == 2) { 24678569bb4SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, cells[0], &edgesInClosure);CHKERRQ(ierr); 24778569bb4SMatthew G. Knepley } else if (dim == 3) { 24878569bb4SMatthew G. Knepley PetscInt *closure = NULL; 24978569bb4SMatthew G. Knepley 25078569bb4SMatthew G. Knepley ierr = DMPlexGetConeSize(dm, cells[0], &facesInClosure);CHKERRQ(ierr); 25178569bb4SMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, cells[0], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 25278569bb4SMatthew G. Knepley edgesInClosure = closureSize - facesInClosure - 1 - verticesInClosure; 25378569bb4SMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, cells[0], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 25478569bb4SMatthew G. Knepley } 25578569bb4SMatthew G. Knepley } 25678569bb4SMatthew G. Knepley /* Get connectivity for each cell */ 25778569bb4SMatthew G. Knepley for (c = 0; c < csSize; ++c) { 25878569bb4SMatthew G. Knepley PetscInt *closure = NULL; 25978569bb4SMatthew G. Knepley PetscInt temp, i; 26078569bb4SMatthew G. Knepley 26178569bb4SMatthew G. Knepley ierr = DMPlexGetTransitiveClosure(dm, cells[c], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 26278569bb4SMatthew G. Knepley for (i = 0; i < connectSize; ++i) { 26378569bb4SMatthew G. Knepley if (i < nodes[cs][0]) {/* Vertices */ 264*e2c9586dSBlaise Bourdin connect[i+off] = closure[(i+edgesInClosure+facesInClosure+1)*2] + 1; 265*e2c9586dSBlaise Bourdin connect[i+off] -= cellsNotInConnectivity; 26678569bb4SMatthew G. Knepley } else if (i < nodes[cs][0]+nodes[cs][1]) { /* Edges */ 267*e2c9586dSBlaise Bourdin connect[i+off] = closure[(i-verticesInClosure+facesInClosure+1)*2] + 1; 268*e2c9586dSBlaise Bourdin if (nodes[cs][2] == 0) connect[i+off] -= numFaces; 269*e2c9586dSBlaise Bourdin connect[i+off] -= cellsNotInConnectivity; 27078569bb4SMatthew G. Knepley } else if (i < nodes[cs][0]+nodes[cs][1]+nodes[cs][3]){ /* Cells */ 271*e2c9586dSBlaise Bourdin connect[i+off] = closure[0] + 1; 272*e2c9586dSBlaise Bourdin connect[i+off] -= skipCells; 27378569bb4SMatthew G. Knepley } else if (i < nodes[cs][0]+nodes[cs][1]+nodes[cs][3]+nodes[cs][2]){ /* Faces */ 274*e2c9586dSBlaise Bourdin connect[i+off] = closure[(i-edgesInClosure-verticesInClosure)*2] + 1; 275*e2c9586dSBlaise Bourdin connect[i+off] -= cellsNotInConnectivity; 27678569bb4SMatthew G. Knepley } else { 277*e2c9586dSBlaise Bourdin connect[i+off] = -1; 27878569bb4SMatthew G. Knepley } 27978569bb4SMatthew G. Knepley } 28078569bb4SMatthew G. Knepley /* Tetrahedra are inverted */ 28178569bb4SMatthew G. Knepley if (type[cs] == TET) { 282*e2c9586dSBlaise Bourdin temp = connect[0+off]; connect[0+off] = connect[1+off]; connect[1+off] = temp; 28378569bb4SMatthew G. Knepley if (degree == 2) { 284*e2c9586dSBlaise Bourdin temp = connect[5+off]; connect[5+off] = connect[6+off]; connect[6+off] = temp; 285*e2c9586dSBlaise Bourdin temp = connect[7+off]; connect[7+off] = connect[8+off]; connect[8+off] = temp; 28678569bb4SMatthew G. Knepley } 28778569bb4SMatthew G. Knepley } 28878569bb4SMatthew G. Knepley /* Hexahedra are inverted */ 28978569bb4SMatthew G. Knepley if (type[cs] == HEX) { 290*e2c9586dSBlaise Bourdin temp = connect[1+off]; connect[1+off] = connect[3+off]; connect[3+off] = temp; 29178569bb4SMatthew G. Knepley if (degree == 2) { 292*e2c9586dSBlaise Bourdin temp = connect[8+off]; connect[8+off] = connect[11+off]; connect[11+off] = temp; 293*e2c9586dSBlaise Bourdin temp = connect[9+off]; connect[9+off] = connect[10+off]; connect[10+off] = temp; 294*e2c9586dSBlaise Bourdin temp = connect[16+off]; connect[16+off] = connect[17+off]; connect[17+off] = temp; 295*e2c9586dSBlaise Bourdin temp = connect[18+off]; connect[18+off] = connect[19+off]; connect[19+off] = temp; 29678569bb4SMatthew G. Knepley 297*e2c9586dSBlaise Bourdin temp = connect[12+off]; connect[12+off] = connect[16+off]; connect[16+off] = temp; 298*e2c9586dSBlaise Bourdin temp = connect[13+off]; connect[13+off] = connect[17+off]; connect[17+off] = temp; 299*e2c9586dSBlaise Bourdin temp = connect[14+off]; connect[14+off] = connect[18+off]; connect[18+off] = temp; 300*e2c9586dSBlaise Bourdin temp = connect[15+off]; connect[15+off] = connect[19+off]; connect[19+off] = temp; 30178569bb4SMatthew G. Knepley 302*e2c9586dSBlaise Bourdin temp = connect[23+off]; connect[23+off] = connect[26+off]; connect[26+off] = temp; 303*e2c9586dSBlaise Bourdin temp = connect[24+off]; connect[24+off] = connect[25+off]; connect[25+off] = temp; 304*e2c9586dSBlaise Bourdin temp = connect[25+off]; connect[25+off] = connect[26+off]; connect[26+off] = temp; 30578569bb4SMatthew G. Knepley } 30678569bb4SMatthew G. Knepley } 307*e2c9586dSBlaise Bourdin off += connectSize; 30878569bb4SMatthew G. Knepley ierr = DMPlexRestoreTransitiveClosure(dm, cells[c], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 30978569bb4SMatthew G. Knepley } 310*e2c9586dSBlaise Bourdin PetscStackCallStandard(ex_put_conn,(exoid, EX_ELEM_BLOCK, csIdx[cs], connect, 0, 0)); 31178569bb4SMatthew G. Knepley skipCells += (nodes[cs][3] == 0)*csSize; 31278569bb4SMatthew G. Knepley ierr = PetscFree(connect);CHKERRQ(ierr); 31378569bb4SMatthew G. Knepley ierr = ISRestoreIndices(stratumIS, &cells);CHKERRQ(ierr); 31478569bb4SMatthew G. Knepley ierr = ISDestroy(&stratumIS);CHKERRQ(ierr); 31578569bb4SMatthew G. Knepley } 31678569bb4SMatthew G. Knepley ierr = PetscFree(type);CHKERRQ(ierr); 31778569bb4SMatthew G. Knepley /* --- Coordinates --- */ 31878569bb4SMatthew G. Knepley ierr = PetscSectionCreate(comm, §ion);CHKERRQ(ierr); 31978569bb4SMatthew G. Knepley ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 32078569bb4SMatthew G. Knepley for (d = 0; d < depth; ++d) { 32178569bb4SMatthew G. Knepley ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 32278569bb4SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 32378569bb4SMatthew G. Knepley ierr = PetscSectionSetDof(section, p, nodes[0][d] > 0);CHKERRQ(ierr); 32478569bb4SMatthew G. Knepley } 32578569bb4SMatthew G. Knepley } 32678569bb4SMatthew G. Knepley for (cs = 0; cs < num_cs; ++cs) { 32778569bb4SMatthew G. Knepley IS stratumIS; 32878569bb4SMatthew G. Knepley const PetscInt *cells; 32978569bb4SMatthew G. Knepley PetscInt csSize, c; 33078569bb4SMatthew G. Knepley 33178569bb4SMatthew G. Knepley ierr = DMLabelGetStratumIS(csLabel, csIdx[cs], &stratumIS);CHKERRQ(ierr); 33278569bb4SMatthew G. Knepley ierr = ISGetIndices(stratumIS, &cells);CHKERRQ(ierr); 33378569bb4SMatthew G. Knepley ierr = ISGetSize(stratumIS, &csSize);CHKERRQ(ierr); 33478569bb4SMatthew G. Knepley for (c = 0; c < csSize; ++c) { 33578569bb4SMatthew G. Knepley ierr = PetscSectionSetDof(section, cells[c], nodes[cs][3] > 0);CHKERRQ(ierr); 33678569bb4SMatthew G. Knepley } 33778569bb4SMatthew G. Knepley ierr = ISRestoreIndices(stratumIS, &cells);CHKERRQ(ierr); 33878569bb4SMatthew G. Knepley ierr = ISDestroy(&stratumIS);CHKERRQ(ierr); 33978569bb4SMatthew G. Knepley } 34078569bb4SMatthew G. Knepley if (num_cs > 0) { 34178569bb4SMatthew G. Knepley ierr = ISRestoreIndices(csIS, &csIdx);CHKERRQ(ierr); 34278569bb4SMatthew G. Knepley ierr = ISDestroy(&csIS);CHKERRQ(ierr); 34378569bb4SMatthew G. Knepley } 34478569bb4SMatthew G. Knepley ierr = PetscFree(nodes);CHKERRQ(ierr); 34578569bb4SMatthew G. Knepley ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 34678569bb4SMatthew G. Knepley if (numNodes > 0) { 34778569bb4SMatthew G. Knepley const char *coordNames[3] = {"x", "y", "z"}; 34878569bb4SMatthew G. Knepley PetscScalar *coords, *closure; 34978569bb4SMatthew G. Knepley PetscReal *cval; 35078569bb4SMatthew G. Knepley PetscInt hasDof, n = 0; 35178569bb4SMatthew G. Knepley 35278569bb4SMatthew G. Knepley /* There can't be more than 24 values in the closure of a point for the coord section */ 3536de834b4SMatthew G. Knepley ierr = PetscCalloc3(numNodes*3, &coords, dim, &cval, 24, &closure);CHKERRQ(ierr); 35478569bb4SMatthew G. Knepley ierr = DMGetCoordinatesLocal(dm, &coord);CHKERRQ(ierr); 35578569bb4SMatthew G. Knepley ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 35678569bb4SMatthew G. Knepley for (p = pStart; p < pEnd; ++p) { 35778569bb4SMatthew G. Knepley ierr = PetscSectionGetDof(section, p, &hasDof); 35878569bb4SMatthew G. Knepley if (hasDof) { 35978569bb4SMatthew G. Knepley PetscInt closureSize = 24, j; 36078569bb4SMatthew G. Knepley 36178569bb4SMatthew G. Knepley ierr = DMPlexVecGetClosure(cdm, NULL, coord, p, &closureSize, &closure);CHKERRQ(ierr); 36278569bb4SMatthew G. Knepley for (d = 0; d < dim; ++d) { 36378569bb4SMatthew G. Knepley cval[d] = 0.0; 36478569bb4SMatthew G. Knepley for (j = 0; j < closureSize/dim; j++) cval[d] += closure[j*dim+d]; 36578569bb4SMatthew G. Knepley coords[d*numNodes+n] = cval[d] * dim / closureSize; 36678569bb4SMatthew G. Knepley } 36778569bb4SMatthew G. Knepley ++n; 36878569bb4SMatthew G. Knepley } 36978569bb4SMatthew G. Knepley } 3706de834b4SMatthew G. Knepley PetscStackCallStandard(ex_put_coord,(exoid, &coords[0*numNodes], &coords[1*numNodes], &coords[2*numNodes])); 37178569bb4SMatthew G. Knepley ierr = PetscFree3(coords, cval, closure);CHKERRQ(ierr); 3726de834b4SMatthew G. Knepley PetscStackCallStandard(ex_put_coord_names,(exoid, (char **) coordNames)); 37378569bb4SMatthew G. Knepley } 37478569bb4SMatthew G. Knepley ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 37578569bb4SMatthew G. Knepley PetscFunctionReturn(0); 37678569bb4SMatthew G. Knepley } 37778569bb4SMatthew G. Knepley 37878569bb4SMatthew G. Knepley /* 37978569bb4SMatthew G. Knepley VecViewPlex_ExodusII_Nodal_Internal - Write a Vec corresponding to a nodal field to an exodus file 38078569bb4SMatthew G. Knepley 38178569bb4SMatthew G. Knepley Collective on v 38278569bb4SMatthew G. Knepley 38378569bb4SMatthew G. Knepley Input Parameters: 38478569bb4SMatthew G. Knepley + v - The vector to be written 38578569bb4SMatthew G. Knepley . exoid - the exodus id of a file (obtained from ex_open or ex_create for instance) 38678569bb4SMatthew G. Knepley - step - the time step to write at (exodus steps are numbered starting from 1) 38778569bb4SMatthew G. Knepley 38878569bb4SMatthew G. Knepley Notes: 38978569bb4SMatthew G. Knepley The exodus result nodal variable index is obtained by comparing the Vec name and the 39078569bb4SMatthew G. Knepley names of nodal variables declared in the exodus file. For instance for a Vec named "V" 39178569bb4SMatthew G. Knepley the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11" 39278569bb4SMatthew G. Knepley amongst all nodal variables. 39378569bb4SMatthew G. Knepley 39478569bb4SMatthew G. Knepley Level: beginner 39578569bb4SMatthew G. Knepley 39678569bb4SMatthew G. Knepley .keywords: mesh,ExodusII 39778569bb4SMatthew G. Knepley .seealso: EXOGetVarIndex_Private(),DMPlexView_ExodusII_Internal(),VecLoadNodal_PlexEXO(),VecViewZonal_PlexEXO(),VecLoadZonal_PlexEXO() 39878569bb4SMatthew G. Knepley @*/ 39978569bb4SMatthew G. Knepley PetscErrorCode VecViewPlex_ExodusII_Nodal_Internal(Vec v, int exoid, int step) 40078569bb4SMatthew G. Knepley { 40178569bb4SMatthew G. Knepley MPI_Comm comm; 40278569bb4SMatthew G. Knepley PetscMPIInt size; 40378569bb4SMatthew G. Knepley DM dm; 40478569bb4SMatthew G. Knepley Vec vNatural, vComp; 40578569bb4SMatthew G. Knepley const PetscReal *varray; 40678569bb4SMatthew G. Knepley const char *vecname; 40778569bb4SMatthew G. Knepley PetscInt xs, xe, bs; 40878569bb4SMatthew G. Knepley PetscBool useNatural; 40978569bb4SMatthew G. Knepley int offset; 41078569bb4SMatthew G. Knepley PetscErrorCode ierr; 41178569bb4SMatthew G. Knepley 41278569bb4SMatthew G. Knepley PetscFunctionBegin; 41378569bb4SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) v, &comm);CHKERRQ(ierr); 41478569bb4SMatthew G. Knepley ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 41578569bb4SMatthew G. Knepley ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 41678569bb4SMatthew G. Knepley ierr = DMGetUseNatural(dm, &useNatural);CHKERRQ(ierr); 41778569bb4SMatthew G. Knepley useNatural = useNatural && size > 1 ? PETSC_TRUE : PETSC_FALSE; 41878569bb4SMatthew G. Knepley if (useNatural) { 41978569bb4SMatthew G. Knepley ierr = DMGetGlobalVector(dm, &vNatural);CHKERRQ(ierr); 42078569bb4SMatthew G. Knepley ierr = DMPlexGlobalToNaturalBegin(dm, v, vNatural);CHKERRQ(ierr); 42178569bb4SMatthew G. Knepley ierr = DMPlexGlobalToNaturalEnd(dm, v, vNatural);CHKERRQ(ierr); 42278569bb4SMatthew G. Knepley } else { 42378569bb4SMatthew G. Knepley vNatural = v; 42478569bb4SMatthew G. Knepley } 42578569bb4SMatthew G. Knepley /* Get the location of the variable in the exodus file */ 42678569bb4SMatthew G. Knepley ierr = PetscObjectGetName((PetscObject) v, &vecname);CHKERRQ(ierr); 42778569bb4SMatthew G. Knepley ierr = EXOGetVarIndex_Private(exoid, EX_NODAL, vecname, &offset);CHKERRQ(ierr); 42878569bb4SMatthew G. Knepley if (!offset) SETERRQ1(comm, PETSC_ERR_FILE_UNEXPECTED, "Cannot locate nodal variable %s in exodus file\n", vecname); 42978569bb4SMatthew G. Knepley /* Write local chunk of the result in the exodus file 43078569bb4SMatthew G. Knepley exodus stores each component of a vector-valued field as a separate variable. 43178569bb4SMatthew G. Knepley We assume that they are stored sequentially */ 43278569bb4SMatthew G. Knepley ierr = VecGetOwnershipRange(vNatural, &xs, &xe);CHKERRQ(ierr); 43378569bb4SMatthew G. Knepley ierr = VecGetBlockSize(vNatural, &bs);CHKERRQ(ierr); 43478569bb4SMatthew G. Knepley if (bs == 1) { 43578569bb4SMatthew G. Knepley ierr = VecGetArrayRead(vNatural, &varray);CHKERRQ(ierr); 4366de834b4SMatthew G. Knepley PetscStackCallStandard(ex_put_partial_var,(exoid, step, EX_NODAL, offset, 1, xs+1, xe-xs, varray)); 43778569bb4SMatthew G. Knepley ierr = VecRestoreArrayRead(vNatural, &varray);CHKERRQ(ierr); 43878569bb4SMatthew G. Knepley } else { 43978569bb4SMatthew G. Knepley IS compIS; 44078569bb4SMatthew G. Knepley PetscInt c; 44178569bb4SMatthew G. Knepley 44278569bb4SMatthew G. Knepley ierr = ISCreateStride(PETSC_COMM_SELF, (xe-xs)/bs, xs, bs, &compIS);CHKERRQ(ierr); 44378569bb4SMatthew G. Knepley for (c = 0; c < bs; ++c) { 44478569bb4SMatthew G. Knepley ierr = ISStrideSetStride(compIS, (xe-xs)/bs, xs+c, bs);CHKERRQ(ierr); 44578569bb4SMatthew G. Knepley ierr = VecGetSubVector(vNatural, compIS, &vComp);CHKERRQ(ierr); 44678569bb4SMatthew G. Knepley ierr = VecGetArrayRead(vComp, &varray);CHKERRQ(ierr); 4476de834b4SMatthew G. Knepley PetscStackCallStandard(ex_put_partial_var,(exoid, step, EX_NODAL, offset+c, 1, xs/bs+1, (xe-xs)/bs, varray)); 44878569bb4SMatthew G. Knepley ierr = VecRestoreArrayRead(vComp, &varray);CHKERRQ(ierr); 44978569bb4SMatthew G. Knepley ierr = VecRestoreSubVector(vNatural, compIS, &vComp);CHKERRQ(ierr); 45078569bb4SMatthew G. Knepley } 45178569bb4SMatthew G. Knepley ierr = ISDestroy(&compIS);CHKERRQ(ierr); 45278569bb4SMatthew G. Knepley } 45378569bb4SMatthew G. Knepley if (useNatural) {ierr = DMRestoreGlobalVector(dm, &vNatural);CHKERRQ(ierr);} 45478569bb4SMatthew G. Knepley PetscFunctionReturn(0); 45578569bb4SMatthew G. Knepley } 45678569bb4SMatthew G. Knepley 45778569bb4SMatthew G. Knepley /* 45878569bb4SMatthew G. Knepley VecLoadPlex_ExodusII_Nodal_Internal - Read a Vec corresponding to a nodal field from an exodus file 45978569bb4SMatthew G. Knepley 46078569bb4SMatthew G. Knepley Collective on v 46178569bb4SMatthew G. Knepley 46278569bb4SMatthew G. Knepley Input Parameters: 46378569bb4SMatthew G. Knepley + v - The vector to be written 46478569bb4SMatthew G. Knepley . exoid - the exodus id of a file (obtained from ex_open or ex_create for instance) 46578569bb4SMatthew G. Knepley - step - the time step to read at (exodus steps are numbered starting from 1) 46678569bb4SMatthew G. Knepley 46778569bb4SMatthew G. Knepley Notes: 46878569bb4SMatthew G. Knepley The exodus result nodal variable index is obtained by comparing the Vec name and the 46978569bb4SMatthew G. Knepley names of nodal variables declared in the exodus file. For instance for a Vec named "V" 47078569bb4SMatthew G. Knepley the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11" 47178569bb4SMatthew G. Knepley amongst all nodal variables. 47278569bb4SMatthew G. Knepley 47378569bb4SMatthew G. Knepley Level: beginner 47478569bb4SMatthew G. Knepley 47578569bb4SMatthew G. Knepley .keywords: mesh, ExodusII 47678569bb4SMatthew G. Knepley .seealso: EXOGetVarIndex_Private(), DMPlexView_ExodusII_Internal(), VecViewPlex_ExodusII_Nodal_Internal(), VecViewZonal_PlexEXO(), VecLoadZonal_PlexEXO() 47778569bb4SMatthew G. Knepley */ 47878569bb4SMatthew G. Knepley PetscErrorCode VecLoadPlex_ExodusII_Nodal_Internal(Vec v, int exoid, int step) 47978569bb4SMatthew G. Knepley { 48078569bb4SMatthew G. Knepley MPI_Comm comm; 48178569bb4SMatthew G. Knepley PetscMPIInt size; 48278569bb4SMatthew G. Knepley DM dm; 48378569bb4SMatthew G. Knepley Vec vNatural, vComp; 48478569bb4SMatthew G. Knepley PetscReal *varray; 48578569bb4SMatthew G. Knepley const char *vecname; 48678569bb4SMatthew G. Knepley PetscInt xs, xe, bs; 48778569bb4SMatthew G. Knepley PetscBool useNatural; 48878569bb4SMatthew G. Knepley int offset; 48978569bb4SMatthew G. Knepley PetscErrorCode ierr; 49078569bb4SMatthew G. Knepley 49178569bb4SMatthew G. Knepley PetscFunctionBegin; 49278569bb4SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject) v, &comm);CHKERRQ(ierr); 49378569bb4SMatthew G. Knepley ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 49478569bb4SMatthew G. Knepley ierr = VecGetDM(v,&dm);CHKERRQ(ierr); 49578569bb4SMatthew G. Knepley ierr = DMGetUseNatural(dm, &useNatural);CHKERRQ(ierr); 49678569bb4SMatthew G. Knepley useNatural = useNatural && size > 1 ? PETSC_TRUE : PETSC_FALSE; 49778569bb4SMatthew G. Knepley if (useNatural) {ierr = DMGetGlobalVector(dm,&vNatural);CHKERRQ(ierr);} 49878569bb4SMatthew G. Knepley else {vNatural = v;} 49978569bb4SMatthew G. Knepley /* Get the location of the variable in the exodus file */ 50078569bb4SMatthew G. Knepley ierr = PetscObjectGetName((PetscObject) v, &vecname);CHKERRQ(ierr); 50178569bb4SMatthew G. Knepley ierr = EXOGetVarIndex_Private(exoid, EX_NODAL, vecname, &offset);CHKERRQ(ierr); 50278569bb4SMatthew G. Knepley if (!offset) SETERRQ1(comm, PETSC_ERR_FILE_UNEXPECTED, "Cannot locate nodal variable %s in exodus file", vecname); 50378569bb4SMatthew G. Knepley /* Read local chunk from the file */ 50478569bb4SMatthew G. Knepley ierr = VecGetOwnershipRange(vNatural, &xs, &xe);CHKERRQ(ierr); 50578569bb4SMatthew G. Knepley ierr = VecGetBlockSize(vNatural, &bs);CHKERRQ(ierr); 50678569bb4SMatthew G. Knepley if (bs == 1) { 50778569bb4SMatthew G. Knepley ierr = VecGetArray(vNatural, &varray);CHKERRQ(ierr); 5086de834b4SMatthew G. Knepley PetscStackCallStandard(ex_get_partial_var,(exoid, step, EX_NODAL, offset, 1, xs+1, xe-xs, varray)); 50978569bb4SMatthew G. Knepley ierr = VecRestoreArray(vNatural, &varray);CHKERRQ(ierr); 51078569bb4SMatthew G. Knepley } else { 51178569bb4SMatthew G. Knepley IS compIS; 51278569bb4SMatthew G. Knepley PetscInt c; 51378569bb4SMatthew G. Knepley 51478569bb4SMatthew G. Knepley ierr = ISCreateStride(PETSC_COMM_SELF, (xe-xs)/bs, xs, bs, &compIS);CHKERRQ(ierr); 51578569bb4SMatthew G. Knepley for (c = 0; c < bs; ++c) { 51678569bb4SMatthew G. Knepley ierr = ISStrideSetStride(compIS, (xe-xs)/bs, xs+c, bs);CHKERRQ(ierr); 51778569bb4SMatthew G. Knepley ierr = VecGetSubVector(vNatural, compIS, &vComp);CHKERRQ(ierr); 51878569bb4SMatthew G. Knepley ierr = VecGetArray(vComp, &varray);CHKERRQ(ierr); 5196de834b4SMatthew G. Knepley PetscStackCallStandard(ex_get_partial_var,(exoid, step, EX_NODAL, offset+c, 1, xs/bs+1, (xe-xs)/bs, varray)); 52078569bb4SMatthew G. Knepley ierr = VecRestoreArray(vComp, &varray);CHKERRQ(ierr); 52178569bb4SMatthew G. Knepley ierr = VecRestoreSubVector(vNatural, compIS, &vComp);CHKERRQ(ierr); 52278569bb4SMatthew G. Knepley } 52378569bb4SMatthew G. Knepley ierr = ISDestroy(&compIS);CHKERRQ(ierr); 52478569bb4SMatthew G. Knepley } 52578569bb4SMatthew G. Knepley if (useNatural) { 52678569bb4SMatthew G. Knepley ierr = DMPlexNaturalToGlobalBegin(dm, vNatural, v);CHKERRQ(ierr); 52778569bb4SMatthew G. Knepley ierr = DMPlexNaturalToGlobalEnd(dm, vNatural, v);CHKERRQ(ierr); 52878569bb4SMatthew G. Knepley ierr = DMRestoreGlobalVector(dm, &vNatural);CHKERRQ(ierr); 52978569bb4SMatthew G. Knepley } 53078569bb4SMatthew G. Knepley PetscFunctionReturn(0); 53178569bb4SMatthew G. Knepley } 53278569bb4SMatthew G. Knepley 53378569bb4SMatthew G. Knepley /* 53478569bb4SMatthew G. Knepley VecViewPlex_ExodusII_Zonal_Internal - Write a Vec corresponding to a zonal (cell based) field to an exodus file 53578569bb4SMatthew G. Knepley 53678569bb4SMatthew G. Knepley Collective on v 53778569bb4SMatthew G. Knepley 53878569bb4SMatthew G. Knepley Input Parameters: 53978569bb4SMatthew G. Knepley + v - The vector to be written 54078569bb4SMatthew G. Knepley . exoid - the exodus id of a file (obtained from ex_open or ex_create for instance) 54178569bb4SMatthew G. Knepley - step - the time step to write at (exodus steps are numbered starting from 1) 54278569bb4SMatthew G. Knepley 54378569bb4SMatthew G. Knepley Notes: 54478569bb4SMatthew G. Knepley The exodus result zonal variable index is obtained by comparing the Vec name and the 54578569bb4SMatthew G. Knepley names of zonal variables declared in the exodus file. For instance for a Vec named "V" 54678569bb4SMatthew G. Knepley the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11" 54778569bb4SMatthew G. Knepley amongst all zonal variables. 54878569bb4SMatthew G. Knepley 54978569bb4SMatthew G. Knepley Level: beginner 55078569bb4SMatthew G. Knepley 55178569bb4SMatthew G. Knepley .keywords: mesh,ExodusII 55278569bb4SMatthew G. Knepley .seealso: EXOGetVarIndex_Private(),DMPlexView_ExodusII_Internal(),VecViewPlex_ExodusII_Nodal_Internal(),VecLoadPlex_ExodusII_Nodal_Internal(),VecLoadPlex_ExodusII_Zonal_Internal() 55378569bb4SMatthew G. Knepley */ 55478569bb4SMatthew G. Knepley PetscErrorCode VecViewPlex_ExodusII_Zonal_Internal(Vec v, int exoid, int step) 55578569bb4SMatthew G. Knepley { 55678569bb4SMatthew G. Knepley MPI_Comm comm; 55778569bb4SMatthew G. Knepley PetscMPIInt size; 55878569bb4SMatthew G. Knepley DM dm; 55978569bb4SMatthew G. Knepley Vec vNatural, vComp; 56078569bb4SMatthew G. Knepley const PetscReal *varray; 56178569bb4SMatthew G. Knepley const char *vecname; 56278569bb4SMatthew G. Knepley PetscInt xs, xe, bs; 56378569bb4SMatthew G. Knepley PetscBool useNatural; 56478569bb4SMatthew G. Knepley int offset; 56578569bb4SMatthew G. Knepley IS compIS; 56678569bb4SMatthew G. Knepley PetscInt *csSize, *csID; 56778569bb4SMatthew G. Knepley PetscInt numCS, set, csxs = 0; 56878569bb4SMatthew G. Knepley PetscErrorCode ierr; 56978569bb4SMatthew G. Knepley 57078569bb4SMatthew G. Knepley PetscFunctionBegin; 57178569bb4SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject)v, &comm);CHKERRQ(ierr); 57278569bb4SMatthew G. Knepley ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 57378569bb4SMatthew G. Knepley ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 57478569bb4SMatthew G. Knepley ierr = DMGetUseNatural(dm, &useNatural);CHKERRQ(ierr); 57578569bb4SMatthew G. Knepley useNatural = useNatural && size > 1 ? PETSC_TRUE : PETSC_FALSE; 57678569bb4SMatthew G. Knepley if (useNatural) { 57778569bb4SMatthew G. Knepley ierr = DMGetGlobalVector(dm, &vNatural);CHKERRQ(ierr); 57878569bb4SMatthew G. Knepley ierr = DMPlexGlobalToNaturalBegin(dm, v, vNatural);CHKERRQ(ierr); 57978569bb4SMatthew G. Knepley ierr = DMPlexGlobalToNaturalEnd(dm, v, vNatural);CHKERRQ(ierr); 58078569bb4SMatthew G. Knepley } else { 58178569bb4SMatthew G. Knepley vNatural = v; 58278569bb4SMatthew G. Knepley } 58378569bb4SMatthew G. Knepley /* Get the location of the variable in the exodus file */ 58478569bb4SMatthew G. Knepley ierr = PetscObjectGetName((PetscObject) v, &vecname);CHKERRQ(ierr); 58578569bb4SMatthew G. Knepley ierr = EXOGetVarIndex_Private(exoid, EX_ELEM_BLOCK, vecname, &offset);CHKERRQ(ierr); 58678569bb4SMatthew G. Knepley if (!offset) SETERRQ1(comm, PETSC_ERR_FILE_UNEXPECTED, "Cannot locate zonal variable %s in exodus file\n", vecname); 58778569bb4SMatthew G. Knepley /* Write local chunk of the result in the exodus file 58878569bb4SMatthew G. Knepley exodus stores each component of a vector-valued field as a separate variable. 58978569bb4SMatthew G. Knepley We assume that they are stored sequentially 59078569bb4SMatthew G. Knepley Zonal variables are accessed one element block at a time, so we loop through the cell sets, 59178569bb4SMatthew G. Knepley but once the vector has been reordered to natural size, we cannot use the label informations 59278569bb4SMatthew G. Knepley to figure out what to save where. */ 59378569bb4SMatthew G. Knepley numCS = ex_inquire_int(exoid, EX_INQ_ELEM_BLK); 59478569bb4SMatthew G. Knepley ierr = PetscMalloc2(numCS, &csID, numCS, &csSize);CHKERRQ(ierr); 5956de834b4SMatthew G. Knepley PetscStackCallStandard(ex_get_ids,(exoid, EX_ELEM_BLOCK, csID)); 59678569bb4SMatthew G. Knepley for (set = 0; set < numCS; ++set) { 59778569bb4SMatthew G. Knepley ex_block block; 59878569bb4SMatthew G. Knepley 59978569bb4SMatthew G. Knepley block.id = csID[set]; 60078569bb4SMatthew G. Knepley block.type = EX_ELEM_BLOCK; 6016de834b4SMatthew G. Knepley PetscStackCallStandard(ex_get_block_param,(exoid, &block)); 60278569bb4SMatthew G. Knepley csSize[set] = block.num_entry; 60378569bb4SMatthew G. Knepley } 60478569bb4SMatthew G. Knepley ierr = VecGetOwnershipRange(vNatural, &xs, &xe);CHKERRQ(ierr); 60578569bb4SMatthew G. Knepley ierr = VecGetBlockSize(vNatural, &bs);CHKERRQ(ierr); 60678569bb4SMatthew G. Knepley if (bs > 1) {ierr = ISCreateStride(comm, (xe-xs)/bs, xs, bs, &compIS);CHKERRQ(ierr);} 60778569bb4SMatthew G. Knepley for (set = 0; set < numCS; set++) { 60878569bb4SMatthew G. Knepley PetscInt csLocalSize, c; 60978569bb4SMatthew G. Knepley 61078569bb4SMatthew G. Knepley /* range of indices for set setID[set]: csxs:csxs + csSize[set]-1 61178569bb4SMatthew G. Knepley local slice of zonal values: xs/bs,xm/bs-1 61278569bb4SMatthew G. Knepley intersection: max(xs/bs,csxs),min(xm/bs-1,csxs + csSize[set]-1) */ 61378569bb4SMatthew G. Knepley csLocalSize = PetscMax(0, PetscMin(xe/bs, csxs+csSize[set]) - PetscMax(xs/bs, csxs)); 61478569bb4SMatthew G. Knepley if (bs == 1) { 61578569bb4SMatthew G. Knepley ierr = VecGetArrayRead(vNatural, &varray);CHKERRQ(ierr); 6166de834b4SMatthew 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)])); 61778569bb4SMatthew G. Knepley ierr = VecRestoreArrayRead(vNatural, &varray);CHKERRQ(ierr); 61878569bb4SMatthew G. Knepley } else { 61978569bb4SMatthew G. Knepley for (c = 0; c < bs; ++c) { 62078569bb4SMatthew G. Knepley ierr = ISStrideSetStride(compIS, (xe-xs)/bs, xs+c, bs);CHKERRQ(ierr); 62178569bb4SMatthew G. Knepley ierr = VecGetSubVector(vNatural, compIS, &vComp);CHKERRQ(ierr); 62278569bb4SMatthew G. Knepley ierr = VecGetArrayRead(vComp, &varray);CHKERRQ(ierr); 6236de834b4SMatthew 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)])); 62478569bb4SMatthew G. Knepley ierr = VecRestoreArrayRead(vComp, &varray);CHKERRQ(ierr); 62578569bb4SMatthew G. Knepley ierr = VecRestoreSubVector(vNatural, compIS, &vComp);CHKERRQ(ierr); 62678569bb4SMatthew G. Knepley } 62778569bb4SMatthew G. Knepley } 62878569bb4SMatthew G. Knepley csxs += csSize[set]; 62978569bb4SMatthew G. Knepley } 63078569bb4SMatthew G. Knepley ierr = PetscFree2(csID, csSize);CHKERRQ(ierr); 63178569bb4SMatthew G. Knepley if (bs > 1) {ierr = ISDestroy(&compIS);CHKERRQ(ierr);} 63278569bb4SMatthew G. Knepley if (useNatural) {ierr = DMRestoreGlobalVector(dm,&vNatural);CHKERRQ(ierr);} 63378569bb4SMatthew G. Knepley PetscFunctionReturn(0); 63478569bb4SMatthew G. Knepley } 63578569bb4SMatthew G. Knepley 63678569bb4SMatthew G. Knepley /* 63778569bb4SMatthew G. Knepley VecLoadPlex_ExodusII_Zonal_Internal - Read a Vec corresponding to a zonal (cell based) field from an exodus file 63878569bb4SMatthew G. Knepley 63978569bb4SMatthew G. Knepley Collective on v 64078569bb4SMatthew G. Knepley 64178569bb4SMatthew G. Knepley Input Parameters: 64278569bb4SMatthew G. Knepley + v - The vector to be written 64378569bb4SMatthew G. Knepley . exoid - the exodus id of a file (obtained from ex_open or ex_create for instance) 64478569bb4SMatthew G. Knepley - step - the time step to read at (exodus steps are numbered starting from 1) 64578569bb4SMatthew G. Knepley 64678569bb4SMatthew G. Knepley Notes: 64778569bb4SMatthew G. Knepley The exodus result zonal variable index is obtained by comparing the Vec name and the 64878569bb4SMatthew G. Knepley names of zonal variables declared in the exodus file. For instance for a Vec named "V" 64978569bb4SMatthew G. Knepley the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11" 65078569bb4SMatthew G. Knepley amongst all zonal variables. 65178569bb4SMatthew G. Knepley 65278569bb4SMatthew G. Knepley Level: beginner 65378569bb4SMatthew G. Knepley 65478569bb4SMatthew G. Knepley .keywords: mesh,ExodusII 65578569bb4SMatthew G. Knepley .seealso: EXOGetVarIndex_Private(), DMPlexView_ExodusII_Internal(), VecViewPlex_ExodusII_Nodal_Internal(), VecLoadPlex_ExodusII_Nodal_Internal(), VecLoadPlex_ExodusII_Zonal_Internal() 65678569bb4SMatthew G. Knepley */ 65778569bb4SMatthew G. Knepley PetscErrorCode VecLoadPlex_ExodusII_Zonal_Internal(Vec v, int exoid, int step) 65878569bb4SMatthew G. Knepley { 65978569bb4SMatthew G. Knepley MPI_Comm comm; 66078569bb4SMatthew G. Knepley PetscMPIInt size; 66178569bb4SMatthew G. Knepley DM dm; 66278569bb4SMatthew G. Knepley Vec vNatural, vComp; 66378569bb4SMatthew G. Knepley PetscReal *varray; 66478569bb4SMatthew G. Knepley const char *vecname; 66578569bb4SMatthew G. Knepley PetscInt xs, xe, bs; 66678569bb4SMatthew G. Knepley PetscBool useNatural; 66778569bb4SMatthew G. Knepley int offset; 66878569bb4SMatthew G. Knepley IS compIS; 66978569bb4SMatthew G. Knepley PetscInt *csSize, *csID; 67078569bb4SMatthew G. Knepley PetscInt numCS, set, csxs = 0; 67178569bb4SMatthew G. Knepley PetscErrorCode ierr; 67278569bb4SMatthew G. Knepley 67378569bb4SMatthew G. Knepley PetscFunctionBegin; 67478569bb4SMatthew G. Knepley ierr = PetscObjectGetComm((PetscObject)v,&comm);CHKERRQ(ierr); 67578569bb4SMatthew G. Knepley ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 67678569bb4SMatthew G. Knepley ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 67778569bb4SMatthew G. Knepley ierr = DMGetUseNatural(dm, &useNatural);CHKERRQ(ierr); 67878569bb4SMatthew G. Knepley useNatural = useNatural && size > 1 ? PETSC_TRUE : PETSC_FALSE; 67978569bb4SMatthew G. Knepley if (useNatural) {ierr = DMGetGlobalVector(dm,&vNatural);CHKERRQ(ierr);} 68078569bb4SMatthew G. Knepley else {vNatural = v;} 68178569bb4SMatthew G. Knepley /* Get the location of the variable in the exodus file */ 68278569bb4SMatthew G. Knepley ierr = PetscObjectGetName((PetscObject) v, &vecname);CHKERRQ(ierr); 68378569bb4SMatthew G. Knepley ierr = EXOGetVarIndex_Private(exoid, EX_ELEM_BLOCK, vecname, &offset);CHKERRQ(ierr); 68478569bb4SMatthew G. Knepley if (!offset) SETERRQ1(comm, PETSC_ERR_FILE_UNEXPECTED, "Cannot locate zonal variable %s in exodus file\n", vecname); 68578569bb4SMatthew G. Knepley /* Read local chunk of the result in the exodus file 68678569bb4SMatthew G. Knepley exodus stores each component of a vector-valued field as a separate variable. 68778569bb4SMatthew G. Knepley We assume that they are stored sequentially 68878569bb4SMatthew G. Knepley Zonal variables are accessed one element block at a time, so we loop through the cell sets, 68978569bb4SMatthew G. Knepley but once the vector has been reordered to natural size, we cannot use the label informations 69078569bb4SMatthew G. Knepley to figure out what to save where. */ 69178569bb4SMatthew G. Knepley numCS = ex_inquire_int(exoid, EX_INQ_ELEM_BLK); 69278569bb4SMatthew G. Knepley ierr = PetscMalloc2(numCS, &csID, numCS, &csSize);CHKERRQ(ierr); 6936de834b4SMatthew G. Knepley PetscStackCallStandard(ex_get_ids,(exoid, EX_ELEM_BLOCK, csID)); 69478569bb4SMatthew G. Knepley for (set = 0; set < numCS; ++set) { 69578569bb4SMatthew G. Knepley ex_block block; 69678569bb4SMatthew G. Knepley 69778569bb4SMatthew G. Knepley block.id = csID[set]; 69878569bb4SMatthew G. Knepley block.type = EX_ELEM_BLOCK; 6996de834b4SMatthew G. Knepley PetscStackCallStandard(ex_get_block_param,(exoid, &block)); 70078569bb4SMatthew G. Knepley csSize[set] = block.num_entry; 70178569bb4SMatthew G. Knepley } 70278569bb4SMatthew G. Knepley ierr = VecGetOwnershipRange(vNatural, &xs, &xe);CHKERRQ(ierr); 70378569bb4SMatthew G. Knepley ierr = VecGetBlockSize(vNatural, &bs);CHKERRQ(ierr); 70478569bb4SMatthew G. Knepley if (bs > 1) {ierr = ISCreateStride(comm, (xe-xs)/bs, xs, bs, &compIS);CHKERRQ(ierr);} 70578569bb4SMatthew G. Knepley for (set = 0; set < numCS; ++set) { 70678569bb4SMatthew G. Knepley PetscInt csLocalSize, c; 70778569bb4SMatthew G. Knepley 70878569bb4SMatthew G. Knepley /* range of indices for set setID[set]: csxs:csxs + csSize[set]-1 70978569bb4SMatthew G. Knepley local slice of zonal values: xs/bs,xm/bs-1 71078569bb4SMatthew G. Knepley intersection: max(xs/bs,csxs),min(xm/bs-1,csxs + csSize[set]-1) */ 71178569bb4SMatthew G. Knepley csLocalSize = PetscMax(0, PetscMin(xe/bs, csxs+csSize[set]) - PetscMax(xs/bs, csxs)); 71278569bb4SMatthew G. Knepley if (bs == 1) { 71378569bb4SMatthew G. Knepley ierr = VecGetArray(vNatural, &varray);CHKERRQ(ierr); 7146de834b4SMatthew 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)])); 71578569bb4SMatthew G. Knepley ierr = VecRestoreArray(vNatural, &varray);CHKERRQ(ierr); 71678569bb4SMatthew G. Knepley } else { 71778569bb4SMatthew G. Knepley for (c = 0; c < bs; ++c) { 71878569bb4SMatthew G. Knepley ierr = ISStrideSetStride(compIS, (xe-xs)/bs, xs+c, bs);CHKERRQ(ierr); 71978569bb4SMatthew G. Knepley ierr = VecGetSubVector(vNatural, compIS, &vComp);CHKERRQ(ierr); 72078569bb4SMatthew G. Knepley ierr = VecGetArray(vComp, &varray);CHKERRQ(ierr); 7216de834b4SMatthew 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)])); 72278569bb4SMatthew G. Knepley ierr = VecRestoreArray(vComp, &varray);CHKERRQ(ierr); 72378569bb4SMatthew G. Knepley ierr = VecRestoreSubVector(vNatural, compIS, &vComp);CHKERRQ(ierr); 72478569bb4SMatthew G. Knepley } 72578569bb4SMatthew G. Knepley } 72678569bb4SMatthew G. Knepley csxs += csSize[set]; 72778569bb4SMatthew G. Knepley } 72878569bb4SMatthew G. Knepley ierr = PetscFree2(csID, csSize);CHKERRQ(ierr); 72978569bb4SMatthew G. Knepley if (bs > 1) {ierr = ISDestroy(&compIS);CHKERRQ(ierr);} 73078569bb4SMatthew G. Knepley if (useNatural) { 73178569bb4SMatthew G. Knepley ierr = DMPlexNaturalToGlobalBegin(dm, vNatural, v);CHKERRQ(ierr); 73278569bb4SMatthew G. Knepley ierr = DMPlexNaturalToGlobalEnd(dm, vNatural, v);CHKERRQ(ierr); 73378569bb4SMatthew G. Knepley ierr = DMRestoreGlobalVector(dm, &vNatural);CHKERRQ(ierr); 73478569bb4SMatthew G. Knepley } 73578569bb4SMatthew G. Knepley PetscFunctionReturn(0); 73678569bb4SMatthew G. Knepley } 737b53c8456SSatish Balay #endif 73878569bb4SMatthew G. Knepley 73933751fbdSMichael Lange /*@C 740eaf898f9SPatrick Sanan DMPlexCreateExodusFromFile - Create a DMPlex mesh from an ExodusII file. 74133751fbdSMichael Lange 74233751fbdSMichael Lange Collective on comm 74333751fbdSMichael Lange 74433751fbdSMichael Lange Input Parameters: 74533751fbdSMichael Lange + comm - The MPI communicator 74633751fbdSMichael Lange . filename - The name of the ExodusII file 74733751fbdSMichael Lange - interpolate - Create faces and edges in the mesh 74833751fbdSMichael Lange 74933751fbdSMichael Lange Output Parameter: 75033751fbdSMichael Lange . dm - The DM object representing the mesh 75133751fbdSMichael Lange 75233751fbdSMichael Lange Level: beginner 75333751fbdSMichael Lange 75433751fbdSMichael Lange .keywords: mesh,ExodusII 75533751fbdSMichael Lange .seealso: DMPLEX, DMCreate(), DMPlexCreateExodus() 75633751fbdSMichael Lange @*/ 75733751fbdSMichael Lange PetscErrorCode DMPlexCreateExodusFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm) 75833751fbdSMichael Lange { 75933751fbdSMichael Lange PetscMPIInt rank; 76033751fbdSMichael Lange PetscErrorCode ierr; 76133751fbdSMichael Lange #if defined(PETSC_HAVE_EXODUSII) 762e84f7031SBlaise Bourdin int CPU_word_size = sizeof(PetscReal), IO_word_size = 0, exoid = -1; 76333751fbdSMichael Lange float version; 76433751fbdSMichael Lange #endif 76533751fbdSMichael Lange 76633751fbdSMichael Lange PetscFunctionBegin; 76733751fbdSMichael Lange PetscValidCharPointer(filename, 2); 76833751fbdSMichael Lange ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 76933751fbdSMichael Lange #if defined(PETSC_HAVE_EXODUSII) 77033751fbdSMichael Lange if (!rank) { 77133751fbdSMichael Lange exoid = ex_open(filename, EX_READ, &CPU_word_size, &IO_word_size, &version); 77233751fbdSMichael Lange if (exoid <= 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, "ex_open(\"%s\",...) did not return a valid file ID", filename); 77333751fbdSMichael Lange } 77433751fbdSMichael Lange ierr = DMPlexCreateExodus(comm, exoid, interpolate, dm);CHKERRQ(ierr); 7756de834b4SMatthew G. Knepley if (!rank) {PetscStackCallStandard(ex_close,(exoid));} 77633751fbdSMichael Lange #else 77733751fbdSMichael Lange SETERRQ(comm, PETSC_ERR_SUP, "This method requires ExodusII support. Reconfigure using --download-exodusii"); 77833751fbdSMichael Lange #endif 77933751fbdSMichael Lange PetscFunctionReturn(0); 78033751fbdSMichael Lange } 78133751fbdSMichael Lange 782552f7358SJed Brown /*@ 78333751fbdSMichael Lange DMPlexCreateExodus - Create a DMPlex mesh from an ExodusII file ID. 784552f7358SJed Brown 785552f7358SJed Brown Collective on comm 786552f7358SJed Brown 787552f7358SJed Brown Input Parameters: 788552f7358SJed Brown + comm - The MPI communicator 789552f7358SJed Brown . exoid - The ExodusII id associated with a exodus file and obtained using ex_open 790552f7358SJed Brown - interpolate - Create faces and edges in the mesh 791552f7358SJed Brown 792552f7358SJed Brown Output Parameter: 793552f7358SJed Brown . dm - The DM object representing the mesh 794552f7358SJed Brown 795552f7358SJed Brown Level: beginner 796552f7358SJed Brown 797552f7358SJed Brown .keywords: mesh,ExodusII 798e84e7769SJed Brown .seealso: DMPLEX, DMCreate() 799552f7358SJed Brown @*/ 800552f7358SJed Brown PetscErrorCode DMPlexCreateExodus(MPI_Comm comm, PetscInt exoid, PetscBool interpolate, DM *dm) 801552f7358SJed Brown { 802552f7358SJed Brown #if defined(PETSC_HAVE_EXODUSII) 803552f7358SJed Brown PetscMPIInt num_proc, rank; 804552f7358SJed Brown PetscSection coordSection; 805552f7358SJed Brown Vec coordinates; 806552f7358SJed Brown PetscScalar *coords; 807552f7358SJed Brown PetscInt coordSize, v; 808552f7358SJed Brown PetscErrorCode ierr; 809552f7358SJed Brown /* Read from ex_get_init() */ 810552f7358SJed Brown char title[PETSC_MAX_PATH_LEN+1]; 811552f7358SJed Brown int dim = 0, numVertices = 0, numCells = 0; 812552f7358SJed Brown int num_cs = 0, num_vs = 0, num_fs = 0; 813552f7358SJed Brown #endif 814552f7358SJed Brown 815552f7358SJed Brown PetscFunctionBegin; 816552f7358SJed Brown #if defined(PETSC_HAVE_EXODUSII) 817552f7358SJed Brown ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 818552f7358SJed Brown ierr = MPI_Comm_size(comm, &num_proc);CHKERRQ(ierr); 819552f7358SJed Brown ierr = DMCreate(comm, dm);CHKERRQ(ierr); 820552f7358SJed Brown ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr); 821552f7358SJed Brown /* Open EXODUS II file and read basic informations on rank 0, then broadcast to all processors */ 822552f7358SJed Brown if (!rank) { 82339bba695SBarry Smith ierr = PetscMemzero(title,(PETSC_MAX_PATH_LEN+1)*sizeof(char));CHKERRQ(ierr); 8246de834b4SMatthew G. Knepley PetscStackCallStandard(ex_get_init,(exoid, title, &dim, &numVertices, &numCells, &num_cs, &num_vs, &num_fs)); 825552f7358SJed Brown if (!num_cs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Exodus file does not contain any cell set\n"); 826552f7358SJed Brown } 827552f7358SJed Brown ierr = MPI_Bcast(title, PETSC_MAX_PATH_LEN+1, MPI_CHAR, 0, comm);CHKERRQ(ierr); 828552f7358SJed Brown ierr = MPI_Bcast(&dim, 1, MPI_INT, 0, comm);CHKERRQ(ierr); 829552f7358SJed Brown ierr = PetscObjectSetName((PetscObject) *dm, title);CHKERRQ(ierr); 830c73cfb54SMatthew G. Knepley ierr = DMSetDimension(*dm, dim);CHKERRQ(ierr); 831552f7358SJed Brown ierr = DMPlexSetChart(*dm, 0, numCells+numVertices);CHKERRQ(ierr); 832552f7358SJed Brown 833552f7358SJed Brown /* Read cell sets information */ 834552f7358SJed Brown if (!rank) { 835552f7358SJed Brown PetscInt *cone; 836552f7358SJed Brown int c, cs, c_loc, v, v_loc; 837552f7358SJed Brown /* Read from ex_get_elem_blk_ids() */ 838552f7358SJed Brown int *cs_id; 839552f7358SJed Brown /* Read from ex_get_elem_block() */ 840552f7358SJed Brown char buffer[PETSC_MAX_PATH_LEN+1]; 841552f7358SJed Brown int num_cell_in_set, num_vertex_per_cell, num_attr; 842552f7358SJed Brown /* Read from ex_get_elem_conn() */ 843552f7358SJed Brown int *cs_connect; 844552f7358SJed Brown 845552f7358SJed Brown /* Get cell sets IDs */ 846785e854fSJed Brown ierr = PetscMalloc1(num_cs, &cs_id);CHKERRQ(ierr); 8476de834b4SMatthew G. Knepley PetscStackCallStandard(ex_get_ids,(exoid, EX_ELEM_BLOCK, cs_id)); 848552f7358SJed Brown /* Read the cell set connectivity table and build mesh topology 849552f7358SJed Brown EXO standard requires that cells in cell sets be numbered sequentially and be pairwise disjoint. */ 850552f7358SJed Brown /* First set sizes */ 851552f7358SJed Brown for (cs = 0, c = 0; cs < num_cs; cs++) { 8526de834b4SMatthew 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)); 853552f7358SJed Brown for (c_loc = 0; c_loc < num_cell_in_set; ++c_loc, ++c) { 854552f7358SJed Brown ierr = DMPlexSetConeSize(*dm, c, num_vertex_per_cell);CHKERRQ(ierr); 855552f7358SJed Brown } 856552f7358SJed Brown } 857552f7358SJed Brown ierr = DMSetUp(*dm);CHKERRQ(ierr); 858552f7358SJed Brown for (cs = 0, c = 0; cs < num_cs; cs++) { 8596de834b4SMatthew 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)); 860dcca6d9dSJed Brown ierr = PetscMalloc2(num_vertex_per_cell*num_cell_in_set,&cs_connect,num_vertex_per_cell,&cone);CHKERRQ(ierr); 8616de834b4SMatthew G. Knepley PetscStackCallStandard(ex_get_conn,(exoid, EX_ELEM_BLOCK, cs_id[cs], cs_connect,NULL,NULL)); 862eaf898f9SPatrick Sanan /* EXO uses Fortran-based indexing, DMPlex uses C-style and numbers cell first then vertices. */ 863552f7358SJed Brown for (c_loc = 0, v = 0; c_loc < num_cell_in_set; ++c_loc, ++c) { 864552f7358SJed Brown for (v_loc = 0; v_loc < num_vertex_per_cell; ++v_loc, ++v) { 865552f7358SJed Brown cone[v_loc] = cs_connect[v]+numCells-1; 866552f7358SJed Brown } 867731dcdf4SMatthew G. Knepley if (dim == 3) { 8682e1b13c2SMatthew G. Knepley /* Tetrahedra are inverted */ 8692e1b13c2SMatthew G. Knepley if (num_vertex_per_cell == 4) { 8702e1b13c2SMatthew G. Knepley PetscInt tmp = cone[0]; 8712e1b13c2SMatthew G. Knepley cone[0] = cone[1]; 8722e1b13c2SMatthew G. Knepley cone[1] = tmp; 8732e1b13c2SMatthew G. Knepley } 8742e1b13c2SMatthew G. Knepley /* Hexahedra are inverted */ 8752e1b13c2SMatthew G. Knepley if (num_vertex_per_cell == 8) { 8762e1b13c2SMatthew G. Knepley PetscInt tmp = cone[1]; 8772e1b13c2SMatthew G. Knepley cone[1] = cone[3]; 8782e1b13c2SMatthew G. Knepley cone[3] = tmp; 8792e1b13c2SMatthew G. Knepley } 880731dcdf4SMatthew G. Knepley } 881552f7358SJed Brown ierr = DMPlexSetCone(*dm, c, cone);CHKERRQ(ierr); 882c58f1c22SToby Isaac ierr = DMSetLabelValue(*dm, "Cell Sets", c, cs_id[cs]);CHKERRQ(ierr); 883552f7358SJed Brown } 884552f7358SJed Brown ierr = PetscFree2(cs_connect,cone);CHKERRQ(ierr); 885552f7358SJed Brown } 886552f7358SJed Brown ierr = PetscFree(cs_id);CHKERRQ(ierr); 887552f7358SJed Brown } 888552f7358SJed Brown ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr); 889552f7358SJed Brown ierr = DMPlexStratify(*dm);CHKERRQ(ierr); 890552f7358SJed Brown if (interpolate) { 8915fd9971aSMatthew G. Knepley DM idm; 892552f7358SJed Brown 8939f074e33SMatthew G Knepley ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); 894552f7358SJed Brown ierr = DMDestroy(dm);CHKERRQ(ierr); 895552f7358SJed Brown *dm = idm; 896552f7358SJed Brown } 897552f7358SJed Brown 898552f7358SJed Brown /* Create vertex set label */ 899552f7358SJed Brown if (!rank && (num_vs > 0)) { 900552f7358SJed Brown int vs, v; 901552f7358SJed Brown /* Read from ex_get_node_set_ids() */ 902552f7358SJed Brown int *vs_id; 903552f7358SJed Brown /* Read from ex_get_node_set_param() */ 904f958083aSBlaise Bourdin int num_vertex_in_set; 905552f7358SJed Brown /* Read from ex_get_node_set() */ 906552f7358SJed Brown int *vs_vertex_list; 907552f7358SJed Brown 908552f7358SJed Brown /* Get vertex set ids */ 909785e854fSJed Brown ierr = PetscMalloc1(num_vs, &vs_id);CHKERRQ(ierr); 9106de834b4SMatthew G. Knepley PetscStackCallStandard(ex_get_ids,(exoid, EX_NODE_SET, vs_id)); 911552f7358SJed Brown for (vs = 0; vs < num_vs; ++vs) { 9126de834b4SMatthew G. Knepley PetscStackCallStandard(ex_get_set_param,(exoid, EX_NODE_SET, vs_id[vs], &num_vertex_in_set, NULL)); 913785e854fSJed Brown ierr = PetscMalloc1(num_vertex_in_set, &vs_vertex_list);CHKERRQ(ierr); 9146de834b4SMatthew G. Knepley PetscStackCallStandard(ex_get_set,(exoid, EX_NODE_SET, vs_id[vs], vs_vertex_list, NULL)); 915552f7358SJed Brown for (v = 0; v < num_vertex_in_set; ++v) { 916c58f1c22SToby Isaac ierr = DMSetLabelValue(*dm, "Vertex Sets", vs_vertex_list[v]+numCells-1, vs_id[vs]);CHKERRQ(ierr); 917552f7358SJed Brown } 918552f7358SJed Brown ierr = PetscFree(vs_vertex_list);CHKERRQ(ierr); 919552f7358SJed Brown } 920552f7358SJed Brown ierr = PetscFree(vs_id);CHKERRQ(ierr); 921552f7358SJed Brown } 922552f7358SJed Brown /* Read coordinates */ 92369d8a9ceSMatthew G. Knepley ierr = DMGetCoordinateSection(*dm, &coordSection);CHKERRQ(ierr); 924552f7358SJed Brown ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr); 925552f7358SJed Brown ierr = PetscSectionSetFieldComponents(coordSection, 0, dim);CHKERRQ(ierr); 926552f7358SJed Brown ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr); 927552f7358SJed Brown for (v = numCells; v < numCells+numVertices; ++v) { 928552f7358SJed Brown ierr = PetscSectionSetDof(coordSection, v, dim);CHKERRQ(ierr); 929552f7358SJed Brown ierr = PetscSectionSetFieldDof(coordSection, v, 0, dim);CHKERRQ(ierr); 930552f7358SJed Brown } 931552f7358SJed Brown ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr); 932552f7358SJed Brown ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr); 9338b9ced59SLisandro Dalcin ierr = VecCreate(PETSC_COMM_SELF, &coordinates);CHKERRQ(ierr); 934552f7358SJed Brown ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr); 935552f7358SJed Brown ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 9364e90ef8eSMatthew G. Knepley ierr = VecSetBlockSize(coordinates, dim);CHKERRQ(ierr); 9372eb5907fSJed Brown ierr = VecSetType(coordinates,VECSTANDARD);CHKERRQ(ierr); 938552f7358SJed Brown ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 9390aba08f6SKarl Rupp if (!rank) { 940e84f7031SBlaise Bourdin PetscReal *x, *y, *z; 941552f7358SJed Brown 942dcca6d9dSJed Brown ierr = PetscMalloc3(numVertices,&x,numVertices,&y,numVertices,&z);CHKERRQ(ierr); 9436de834b4SMatthew G. Knepley PetscStackCallStandard(ex_get_coord,(exoid, x, y, z)); 9440d644c17SKarl Rupp if (dim > 0) { 9450d644c17SKarl Rupp for (v = 0; v < numVertices; ++v) coords[v*dim+0] = x[v]; 9460d644c17SKarl Rupp } 9470d644c17SKarl Rupp if (dim > 1) { 9480d644c17SKarl Rupp for (v = 0; v < numVertices; ++v) coords[v*dim+1] = y[v]; 9490d644c17SKarl Rupp } 9500d644c17SKarl Rupp if (dim > 2) { 9510d644c17SKarl Rupp for (v = 0; v < numVertices; ++v) coords[v*dim+2] = z[v]; 9520d644c17SKarl Rupp } 953552f7358SJed Brown ierr = PetscFree3(x,y,z);CHKERRQ(ierr); 954552f7358SJed Brown } 955552f7358SJed Brown ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 956552f7358SJed Brown ierr = DMSetCoordinatesLocal(*dm, coordinates);CHKERRQ(ierr); 957552f7358SJed Brown ierr = VecDestroy(&coordinates);CHKERRQ(ierr); 958552f7358SJed Brown 959552f7358SJed Brown /* Create side set label */ 960552f7358SJed Brown if (!rank && interpolate && (num_fs > 0)) { 961552f7358SJed Brown int fs, f, voff; 962552f7358SJed Brown /* Read from ex_get_side_set_ids() */ 963552f7358SJed Brown int *fs_id; 964552f7358SJed Brown /* Read from ex_get_side_set_param() */ 965f958083aSBlaise Bourdin int num_side_in_set; 966552f7358SJed Brown /* Read from ex_get_side_set_node_list() */ 967552f7358SJed Brown int *fs_vertex_count_list, *fs_vertex_list; 968ef073283Smichael_afanasiev /* Read side set labels */ 969ef073283Smichael_afanasiev char fs_name[MAX_STR_LENGTH+1]; 970552f7358SJed Brown 971552f7358SJed Brown /* Get side set ids */ 972785e854fSJed Brown ierr = PetscMalloc1(num_fs, &fs_id);CHKERRQ(ierr); 9736de834b4SMatthew G. Knepley PetscStackCallStandard(ex_get_ids,(exoid, EX_SIDE_SET, fs_id)); 974552f7358SJed Brown for (fs = 0; fs < num_fs; ++fs) { 9756de834b4SMatthew G. Knepley PetscStackCallStandard(ex_get_set_param,(exoid, EX_SIDE_SET, fs_id[fs], &num_side_in_set, NULL)); 976dcca6d9dSJed Brown ierr = PetscMalloc2(num_side_in_set,&fs_vertex_count_list,num_side_in_set*4,&fs_vertex_list);CHKERRQ(ierr); 9776de834b4SMatthew G. Knepley PetscStackCallStandard(ex_get_side_set_node_list,(exoid, fs_id[fs], fs_vertex_count_list, fs_vertex_list)); 978ef073283Smichael_afanasiev /* Get the specific name associated with this side set ID. */ 979ef073283Smichael_afanasiev int fs_name_err = ex_get_name(exoid, EX_SIDE_SET, fs_id[fs], fs_name); 980552f7358SJed Brown for (f = 0, voff = 0; f < num_side_in_set; ++f) { 9810298fd71SBarry Smith const PetscInt *faces = NULL; 982552f7358SJed Brown PetscInt faceSize = fs_vertex_count_list[f], numFaces; 983552f7358SJed Brown PetscInt faceVertices[4], v; 984552f7358SJed Brown 985552f7358SJed Brown if (faceSize > 4) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "ExodusII side cannot have %d > 4 vertices", faceSize); 986552f7358SJed Brown for (v = 0; v < faceSize; ++v, ++voff) { 987552f7358SJed Brown faceVertices[v] = fs_vertex_list[voff]+numCells-1; 988552f7358SJed Brown } 989552f7358SJed Brown ierr = DMPlexGetFullJoin(*dm, faceSize, faceVertices, &numFaces, &faces);CHKERRQ(ierr); 990552f7358SJed Brown if (numFaces != 1) SETERRQ3(comm, PETSC_ERR_ARG_WRONG, "Invalid ExodusII side %d in set %d maps to %d faces", f, fs, numFaces); 991c58f1c22SToby Isaac ierr = DMSetLabelValue(*dm, "Face Sets", faces[0], fs_id[fs]);CHKERRQ(ierr); 992ef073283Smichael_afanasiev /* Only add the label if one has been detected for this side set. */ 993ef073283Smichael_afanasiev if (!fs_name_err) { 994ef073283Smichael_afanasiev ierr = DMSetLabelValue(*dm, fs_name, faces[0], fs_id[fs]);CHKERRQ(ierr); 995ef073283Smichael_afanasiev } 996552f7358SJed Brown ierr = DMPlexRestoreJoin(*dm, faceSize, faceVertices, &numFaces, &faces);CHKERRQ(ierr); 997552f7358SJed Brown } 998552f7358SJed Brown ierr = PetscFree2(fs_vertex_count_list,fs_vertex_list);CHKERRQ(ierr); 999552f7358SJed Brown } 1000552f7358SJed Brown ierr = PetscFree(fs_id);CHKERRQ(ierr); 1001552f7358SJed Brown } 1002552f7358SJed Brown #else 1003552f7358SJed Brown SETERRQ(comm, PETSC_ERR_SUP, "This method requires ExodusII support. Reconfigure using --download-exodusii"); 1004552f7358SJed Brown #endif 1005552f7358SJed Brown PetscFunctionReturn(0); 1006552f7358SJed Brown } 1007