xref: /petsc/src/dm/impls/plex/plexexodusii.c (revision 28b400f66ebc7ae0049166a2294dfcd3df27e64b)
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 
91e50132fSMatthew G. Knepley #include <petsc/private/viewerimpl.h>
101e50132fSMatthew G. Knepley #include <petsc/private/viewerexodusiiimpl.h>
11e0266925SMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
1278569bb4SMatthew G. Knepley /*
131e50132fSMatthew G. Knepley   PETSC_VIEWER_EXODUSII_ - Creates an ExodusII PetscViewer shared by all processors in a communicator.
141e50132fSMatthew G. Knepley 
151e50132fSMatthew G. Knepley   Collective
161e50132fSMatthew G. Knepley 
171e50132fSMatthew G. Knepley   Input Parameter:
181e50132fSMatthew G. Knepley . comm - the MPI communicator to share the ExodusII PetscViewer
191e50132fSMatthew G. Knepley 
201e50132fSMatthew G. Knepley   Level: intermediate
211e50132fSMatthew G. Knepley 
221e50132fSMatthew G. Knepley   Notes:
231e50132fSMatthew G. Knepley     misses Fortran bindings
241e50132fSMatthew G. Knepley 
251e50132fSMatthew G. Knepley   Notes:
261e50132fSMatthew G. Knepley   Unlike almost all other PETSc routines, PETSC_VIEWER_EXODUSII_ does not return
271e50132fSMatthew G. Knepley   an error code.  The GLVIS PetscViewer is usually used in the form
281e50132fSMatthew G. Knepley $       XXXView(XXX object, PETSC_VIEWER_EXODUSII_(comm));
291e50132fSMatthew G. Knepley 
3000373969SVaclav Hapla .seealso: PetscViewerExodusIIOpen(), PetscViewerType, PetscViewerCreate(), PetscViewerDestroy()
311e50132fSMatthew G. Knepley */
321e50132fSMatthew G. Knepley PetscViewer PETSC_VIEWER_EXODUSII_(MPI_Comm comm)
331e50132fSMatthew G. Knepley {
341e50132fSMatthew G. Knepley   PetscViewer    viewer;
351e50132fSMatthew G. Knepley   PetscErrorCode ierr;
361e50132fSMatthew G. Knepley 
371e50132fSMatthew G. Knepley   PetscFunctionBegin;
381e50132fSMatthew G. Knepley   ierr = PetscViewerExodusIIOpen(comm, "mesh.exo", FILE_MODE_WRITE, &viewer);
3900373969SVaclav Hapla   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_EXODUSII_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
401e50132fSMatthew G. Knepley   ierr = PetscObjectRegisterDestroy((PetscObject) viewer);
4100373969SVaclav Hapla   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_EXODUSII_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
421e50132fSMatthew G. Knepley   PetscFunctionReturn(viewer);
431e50132fSMatthew G. Knepley }
441e50132fSMatthew G. Knepley 
451e50132fSMatthew G. Knepley static PetscErrorCode PetscViewerView_ExodusII(PetscViewer v, PetscViewer viewer)
461e50132fSMatthew G. Knepley {
476823f3c5SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *) v->data;
481e50132fSMatthew G. Knepley 
491e50132fSMatthew G. Knepley   PetscFunctionBegin;
505f80ce2aSJacob Faibussowitsch   if (exo->filename) CHKERRQ(PetscViewerASCIIPrintf(viewer, "Filename:    %s\n", exo->filename));
515f80ce2aSJacob Faibussowitsch   if (exo->exoid)    CHKERRQ(PetscViewerASCIIPrintf(viewer, "exoid:       %d\n", exo->exoid));
525f80ce2aSJacob Faibussowitsch   if (exo->btype)    CHKERRQ(PetscViewerASCIIPrintf(viewer, "IO Mode:     %d\n", exo->btype));
535f80ce2aSJacob Faibussowitsch   if (exo->order)    CHKERRQ(PetscViewerASCIIPrintf(viewer, "Mesh order:  %d\n", exo->order));
541e50132fSMatthew G. Knepley   PetscFunctionReturn(0);
551e50132fSMatthew G. Knepley }
561e50132fSMatthew G. Knepley 
571e50132fSMatthew G. Knepley static PetscErrorCode PetscViewerSetFromOptions_ExodusII(PetscOptionItems *PetscOptionsObject, PetscViewer v)
581e50132fSMatthew G. Knepley {
591e50132fSMatthew G. Knepley   PetscFunctionBegin;
605f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsHead(PetscOptionsObject, "ExodusII PetscViewer Options"));
615f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscOptionsTail());
621e50132fSMatthew G. Knepley   PetscFunctionReturn(0);
631e50132fSMatthew G. Knepley }
641e50132fSMatthew G. Knepley 
651e50132fSMatthew G. Knepley static PetscErrorCode PetscViewerSetUp_ExodusII(PetscViewer viewer)
661e50132fSMatthew G. Knepley {
671e50132fSMatthew G. Knepley   PetscFunctionBegin;
681e50132fSMatthew G. Knepley   PetscFunctionReturn(0);
691e50132fSMatthew G. Knepley }
701e50132fSMatthew G. Knepley 
711e50132fSMatthew G. Knepley static PetscErrorCode PetscViewerDestroy_ExodusII(PetscViewer viewer)
721e50132fSMatthew G. Knepley {
731e50132fSMatthew G. Knepley   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *) viewer->data;
741e50132fSMatthew G. Knepley 
751e50132fSMatthew G. Knepley   PetscFunctionBegin;
76a74df02fSJacob Faibussowitsch   if (exo->exoid >= 0) {PetscStackCallStandard(ex_close,exo->exoid);}
775f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(exo->filename));
785f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree(exo));
795f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetName_C",NULL));
805f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileGetName_C",NULL));
815f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetMode_C",NULL));
825f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerGetId_C",NULL));
835f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerGetOrder_C",NULL));
845f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerSetOrder_C",NULL));
851e50132fSMatthew G. Knepley   PetscFunctionReturn(0);
861e50132fSMatthew G. Knepley }
871e50132fSMatthew G. Knepley 
881e50132fSMatthew G. Knepley static PetscErrorCode PetscViewerFileSetName_ExodusII(PetscViewer viewer, const char name[])
891e50132fSMatthew G. Knepley {
901e50132fSMatthew G. Knepley   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *) viewer->data;
911e50132fSMatthew G. Knepley   PetscMPIInt           rank;
921e50132fSMatthew G. Knepley   int                   CPU_word_size, IO_word_size, EXO_mode;
936823f3c5SBlaise Bourdin   MPI_Info              mpi_info = MPI_INFO_NULL;
946823f3c5SBlaise Bourdin   float                 EXO_version;
951e50132fSMatthew G. Knepley 
965f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) viewer), &rank));
971e50132fSMatthew G. Knepley   CPU_word_size = sizeof(PetscReal);
981e50132fSMatthew G. Knepley   IO_word_size  = sizeof(PetscReal);
991e50132fSMatthew G. Knepley 
1001e50132fSMatthew G. Knepley   PetscFunctionBegin;
1016823f3c5SBlaise Bourdin   if (exo->exoid >= 0) {
102a74df02fSJacob Faibussowitsch     PetscStackCallStandard(ex_close,exo->exoid);
1036823f3c5SBlaise Bourdin     exo->exoid = -1;
1046823f3c5SBlaise Bourdin   }
1055f80ce2aSJacob Faibussowitsch   if (exo->filename) CHKERRQ(PetscFree(exo->filename));
1065f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrallocpy(name, &exo->filename));
1071e50132fSMatthew G. Knepley   switch (exo->btype) {
1081e50132fSMatthew G. Knepley   case FILE_MODE_READ:
1096823f3c5SBlaise Bourdin     EXO_mode = EX_READ;
1101e50132fSMatthew G. Knepley     break;
1111e50132fSMatthew G. Knepley   case FILE_MODE_APPEND:
1126823f3c5SBlaise Bourdin   case FILE_MODE_UPDATE:
1136823f3c5SBlaise Bourdin   case FILE_MODE_APPEND_UPDATE:
1146823f3c5SBlaise Bourdin     /* Will fail if the file does not already exist */
1156823f3c5SBlaise Bourdin     EXO_mode = EX_WRITE;
1161e50132fSMatthew G. Knepley     break;
1171e50132fSMatthew G. Knepley   case FILE_MODE_WRITE:
1186823f3c5SBlaise Bourdin     /*
1196823f3c5SBlaise Bourdin       exodus only allows writing geometry upon file creation, so we will let DMView create the file.
1206823f3c5SBlaise Bourdin     */
1216823f3c5SBlaise Bourdin     PetscFunctionReturn(0);
1221e50132fSMatthew G. Knepley     break;
1231e50132fSMatthew G. Knepley   default:
1241e50132fSMatthew G. Knepley     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
1251e50132fSMatthew G. Knepley   }
1261e50132fSMatthew G. Knepley   #if defined(PETSC_USE_64BIT_INDICES)
1271e50132fSMatthew G. Knepley   EXO_mode += EX_ALL_INT64_API;
1281e50132fSMatthew G. Knepley   #endif
1296823f3c5SBlaise Bourdin   exo->exoid = ex_open_par(name,EXO_mode,&CPU_word_size,&IO_word_size,&EXO_version,PETSC_COMM_WORLD,mpi_info);
1302c71b3e2SJacob Faibussowitsch   PetscCheckFalse(exo->exoid < 0,PETSC_COMM_SELF, PETSC_ERR_LIB, "ex_open_par failed for %s", name);
1311e50132fSMatthew G. Knepley   PetscFunctionReturn(0);
1321e50132fSMatthew G. Knepley }
1331e50132fSMatthew G. Knepley 
1341e50132fSMatthew G. Knepley static PetscErrorCode PetscViewerFileGetName_ExodusII(PetscViewer viewer, const char **name)
1351e50132fSMatthew G. Knepley {
1361e50132fSMatthew G. Knepley   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *) viewer->data;
1371e50132fSMatthew G. Knepley 
1381e50132fSMatthew G. Knepley   PetscFunctionBegin;
1391e50132fSMatthew G. Knepley   *name = exo->filename;
1401e50132fSMatthew G. Knepley   PetscFunctionReturn(0);
1411e50132fSMatthew G. Knepley }
1421e50132fSMatthew G. Knepley 
1431e50132fSMatthew G. Knepley static PetscErrorCode PetscViewerFileSetMode_ExodusII(PetscViewer viewer, PetscFileMode type)
1441e50132fSMatthew G. Knepley {
1451e50132fSMatthew G. Knepley   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *) viewer->data;
1461e50132fSMatthew G. Knepley 
1471e50132fSMatthew G. Knepley   PetscFunctionBegin;
1481e50132fSMatthew G. Knepley   exo->btype = type;
1491e50132fSMatthew G. Knepley   PetscFunctionReturn(0);
1501e50132fSMatthew G. Knepley }
1511e50132fSMatthew G. Knepley 
1521e50132fSMatthew G. Knepley static PetscErrorCode PetscViewerFileGetMode_ExodusII(PetscViewer viewer, PetscFileMode *type)
1531e50132fSMatthew G. Knepley {
1541e50132fSMatthew G. Knepley   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *) viewer->data;
1551e50132fSMatthew G. Knepley 
1561e50132fSMatthew G. Knepley   PetscFunctionBegin;
1571e50132fSMatthew G. Knepley   *type = exo->btype;
1581e50132fSMatthew G. Knepley   PetscFunctionReturn(0);
1591e50132fSMatthew G. Knepley }
1601e50132fSMatthew G. Knepley 
1611e50132fSMatthew G. Knepley static PetscErrorCode PetscViewerExodusIIGetId_ExodusII(PetscViewer viewer, int *exoid)
1621e50132fSMatthew G. Knepley {
1631e50132fSMatthew G. Knepley   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *) viewer->data;
1641e50132fSMatthew G. Knepley 
1651e50132fSMatthew G. Knepley   PetscFunctionBegin;
1661e50132fSMatthew G. Knepley   *exoid = exo->exoid;
1671e50132fSMatthew G. Knepley   PetscFunctionReturn(0);
1681e50132fSMatthew G. Knepley }
1691e50132fSMatthew G. Knepley 
1706823f3c5SBlaise Bourdin static PetscErrorCode PetscViewerExodusIIGetOrder_ExodusII(PetscViewer viewer, PetscInt *order)
1711e50132fSMatthew G. Knepley {
1726823f3c5SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *) viewer->data;
1731e50132fSMatthew G. Knepley 
1741e50132fSMatthew G. Knepley   PetscFunctionBegin;
1756823f3c5SBlaise Bourdin   *order = exo->order;
1766823f3c5SBlaise Bourdin   PetscFunctionReturn(0);
1776823f3c5SBlaise Bourdin }
1786823f3c5SBlaise Bourdin 
1796823f3c5SBlaise Bourdin static PetscErrorCode PetscViewerExodusIISetOrder_ExodusII(PetscViewer viewer, PetscInt order)
1806823f3c5SBlaise Bourdin {
1816823f3c5SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *) viewer->data;
1826823f3c5SBlaise Bourdin 
1836823f3c5SBlaise Bourdin   PetscFunctionBegin;
1846823f3c5SBlaise Bourdin   exo->order = order;
1851e50132fSMatthew G. Knepley   PetscFunctionReturn(0);
1861e50132fSMatthew G. Knepley }
1871e50132fSMatthew G. Knepley 
1881e50132fSMatthew G. Knepley /*MC
18900373969SVaclav Hapla    PETSCVIEWEREXODUSII - A viewer that writes to an Exodus II file
1901e50132fSMatthew G. Knepley 
19100373969SVaclav Hapla .seealso:  PetscViewerExodusIIOpen(), PetscViewerCreate(), PETSCVIEWERBINARY, PETSCVIEWERHDF5, DMView(),
1921e50132fSMatthew G. Knepley            PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType()
1931e50132fSMatthew G. Knepley 
1941e50132fSMatthew G. Knepley   Level: beginner
1951e50132fSMatthew G. Knepley M*/
1961e50132fSMatthew G. Knepley 
1971e50132fSMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscViewerCreate_ExodusII(PetscViewer v)
1981e50132fSMatthew G. Knepley {
1991e50132fSMatthew G. Knepley   PetscViewer_ExodusII *exo;
2001e50132fSMatthew G. Knepley 
2011e50132fSMatthew G. Knepley   PetscFunctionBegin;
2025f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscNewLog(v,&exo));
2031e50132fSMatthew G. Knepley 
2041e50132fSMatthew G. Knepley   v->data                = (void*) exo;
2051e50132fSMatthew G. Knepley   v->ops->destroy        = PetscViewerDestroy_ExodusII;
2061e50132fSMatthew G. Knepley   v->ops->setfromoptions = PetscViewerSetFromOptions_ExodusII;
2071e50132fSMatthew G. Knepley   v->ops->setup          = PetscViewerSetUp_ExodusII;
2081e50132fSMatthew G. Knepley   v->ops->view           = PetscViewerView_ExodusII;
2091e50132fSMatthew G. Knepley   v->ops->flush          = 0;
2101e50132fSMatthew G. Knepley   exo->btype             = (PetscFileMode) -1;
2111e50132fSMatthew G. Knepley   exo->filename          = 0;
2121e50132fSMatthew G. Knepley   exo->exoid             = -1;
2131e50132fSMatthew G. Knepley 
2145f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",PetscViewerFileSetName_ExodusII));
2155f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",PetscViewerFileGetName_ExodusII));
2165f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_ExodusII));
2175f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetMode_C",PetscViewerFileGetMode_ExodusII));
2185f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)v,"PetscViewerGetId_C",PetscViewerExodusIIGetId_ExodusII));
2195f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)v,"PetscViewerSetOrder_C",PetscViewerExodusIISetOrder_ExodusII));
2205f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectComposeFunction((PetscObject)v,"PetscViewerGetOrder_C",PetscViewerExodusIIGetOrder_ExodusII));
2211e50132fSMatthew G. Knepley   PetscFunctionReturn(0);
2221e50132fSMatthew G. Knepley }
2231e50132fSMatthew G. Knepley 
2241e50132fSMatthew G. Knepley /*
22578569bb4SMatthew G. Knepley   EXOGetVarIndex - Locate a result in an exodus file based on its name
22678569bb4SMatthew G. Knepley 
2276823f3c5SBlaise Bourdin   Collective
22878569bb4SMatthew G. Knepley 
22978569bb4SMatthew G. Knepley   Input Parameters:
23078569bb4SMatthew G. Knepley + exoid    - the exodus id of a file (obtained from ex_open or ex_create for instance)
23178569bb4SMatthew G. Knepley . obj_type - the type of entity for instance EX_NODAL, EX_ELEM_BLOCK
23278569bb4SMatthew G. Knepley - name     - the name of the result
23378569bb4SMatthew G. Knepley 
23478569bb4SMatthew G. Knepley   Output Parameters:
23578569bb4SMatthew G. Knepley . varIndex - the location in the exodus file of the result
23678569bb4SMatthew G. Knepley 
23778569bb4SMatthew G. Knepley   Notes:
23878569bb4SMatthew G. Knepley   The exodus variable index is obtained by comparing name and the
23978569bb4SMatthew G. Knepley   names of zonal variables declared in the exodus file. For instance if name is "V"
24078569bb4SMatthew G. Knepley   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
24178569bb4SMatthew G. Knepley   amongst all variables of type obj_type.
24278569bb4SMatthew G. Knepley 
24378569bb4SMatthew G. Knepley   Level: beginner
24478569bb4SMatthew G. Knepley 
245cd921712SStefano Zampini .seealso: EXOGetVarIndex(),DMPlexView_ExodusII_Internal(),VecViewPlex_ExodusII_Nodal_Internal(),VecLoadNodal_PlexEXO(),VecLoadZonal_PlexEXO()
24678569bb4SMatthew G. Knepley */
2476823f3c5SBlaise Bourdin PetscErrorCode EXOGetVarIndex_Internal(int exoid, ex_entity_type obj_type, const char name[], int *varIndex)
24878569bb4SMatthew G. Knepley {
2496de834b4SMatthew G. Knepley   int            num_vars, i, j;
25078569bb4SMatthew G. Knepley   char           ext_name[MAX_STR_LENGTH+1], var_name[MAX_STR_LENGTH+1];
25178569bb4SMatthew G. Knepley   const int      num_suffix = 5;
25278569bb4SMatthew G. Knepley   char          *suffix[5];
25378569bb4SMatthew G. Knepley   PetscBool      flg;
25478569bb4SMatthew G. Knepley 
25578569bb4SMatthew G. Knepley   PetscFunctionBegin;
25678569bb4SMatthew G. Knepley   suffix[0] = (char *) "";
25778569bb4SMatthew G. Knepley   suffix[1] = (char *) "_X";
25878569bb4SMatthew G. Knepley   suffix[2] = (char *) "_XX";
25978569bb4SMatthew G. Knepley   suffix[3] = (char *) "_1";
26078569bb4SMatthew G. Knepley   suffix[4] = (char *) "_11";
26178569bb4SMatthew G. Knepley 
2626823f3c5SBlaise Bourdin   *varIndex = -1;
263a74df02fSJacob Faibussowitsch   PetscStackCallStandard(ex_get_variable_param,exoid, obj_type, &num_vars);
26478569bb4SMatthew G. Knepley   for (i = 0; i < num_vars; ++i) {
265a74df02fSJacob Faibussowitsch     PetscStackCallStandard(ex_get_variable_name,exoid, obj_type, i+1, var_name);
26678569bb4SMatthew G. Knepley     for (j = 0; j < num_suffix; ++j) {
2675f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscStrncpy(ext_name, name, MAX_STR_LENGTH));
2685f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscStrlcat(ext_name, suffix[j], MAX_STR_LENGTH));
2695f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscStrcasecmp(ext_name, var_name, &flg));
27078569bb4SMatthew G. Knepley       if (flg) {
27178569bb4SMatthew G. Knepley         *varIndex = i+1;
2726823f3c5SBlaise Bourdin       }
2736823f3c5SBlaise Bourdin     }
2746823f3c5SBlaise Bourdin   }
27578569bb4SMatthew G. Knepley   PetscFunctionReturn(0);
27678569bb4SMatthew G. Knepley }
27778569bb4SMatthew G. Knepley 
27878569bb4SMatthew G. Knepley /*
2796823f3c5SBlaise Bourdin   DMView_PlexExodusII - Write a DM to disk in exodus format
28078569bb4SMatthew G. Knepley 
28178569bb4SMatthew G. Knepley   Collective on dm
28278569bb4SMatthew G. Knepley 
28378569bb4SMatthew G. Knepley   Input Parameters:
28478569bb4SMatthew G. Knepley + dm  - The dm to be written
2856823f3c5SBlaise Bourdin . viewer - an exodusII viewer
28678569bb4SMatthew G. Knepley 
28778569bb4SMatthew G. Knepley   Notes:
28878569bb4SMatthew G. Knepley   Not all DM can be written to disk this way. For instance, exodus assume that element blocks (mapped to "Cell sets" labels)
28978569bb4SMatthew G. Knepley   consists of sequentially numbered cells. If this is not the case, the exodus file will be corrupted.
29078569bb4SMatthew G. Knepley 
2916823f3c5SBlaise Bourdin   If the dm has been distributed, only the part of the DM on MPI rank 0 (including "ghost" cells and vertices)
2926823f3c5SBlaise Bourdin   will be written.
29378569bb4SMatthew G. Knepley 
29478569bb4SMatthew G. Knepley   DMPlex only represents geometry while most post-processing software expect that a mesh also provides information
29578569bb4SMatthew G. Knepley   on the discretization space. This function assumes that the file represents Lagrange finite elements of order 1 or 2.
2966823f3c5SBlaise Bourdin   The order of the mesh shall be set using PetscViewerExodusIISetOrder
29778569bb4SMatthew G. Knepley   It should be extended to use PetscFE objects.
29878569bb4SMatthew G. Knepley 
2996823f3c5SBlaise Bourdin   This function will only handle TRI, TET, QUAD, and HEX cells.
30078569bb4SMatthew G. Knepley   Level: beginner
30178569bb4SMatthew G. Knepley 
3026823f3c5SBlaise Bourdin .seealso:
30378569bb4SMatthew G. Knepley */
3046823f3c5SBlaise Bourdin PetscErrorCode DMView_PlexExodusII(DM dm, PetscViewer viewer)
30578569bb4SMatthew G. Knepley {
30678569bb4SMatthew G. Knepley   enum ElemType {TRI, QUAD, TET, HEX};
30778569bb4SMatthew G. Knepley   MPI_Comm        comm;
3086823f3c5SBlaise Bourdin   PetscInt        degree; /* the order of the mesh */
30978569bb4SMatthew G. Knepley   /* Connectivity Variables */
31078569bb4SMatthew G. Knepley   PetscInt        cellsNotInConnectivity;
31178569bb4SMatthew G. Knepley   /* Cell Sets */
31278569bb4SMatthew G. Knepley   DMLabel         csLabel;
31378569bb4SMatthew G. Knepley   IS              csIS;
31478569bb4SMatthew G. Knepley   const PetscInt *csIdx;
31578569bb4SMatthew G. Knepley   PetscInt        num_cs, cs;
31678569bb4SMatthew G. Knepley   enum ElemType  *type;
317fe209ef9SBlaise Bourdin   PetscBool       hasLabel;
31878569bb4SMatthew G. Knepley   /* Coordinate Variables */
31978569bb4SMatthew G. Knepley   DM              cdm;
3206823f3c5SBlaise Bourdin   PetscSection    coordSection;
32178569bb4SMatthew G. Knepley   Vec             coord;
32278569bb4SMatthew G. Knepley   PetscInt      **nodes;
323eae8a387SMatthew G. Knepley   PetscInt        depth, d, dim, skipCells = 0;
32478569bb4SMatthew G. Knepley   PetscInt        pStart, pEnd, p, cStart, cEnd, numCells, vStart, vEnd, numVertices, eStart, eEnd, numEdges, fStart, fEnd, numFaces, numNodes;
32578569bb4SMatthew G. Knepley   PetscInt        num_vs, num_fs;
32678569bb4SMatthew G. Knepley   PetscMPIInt     rank, size;
32778569bb4SMatthew G. Knepley   const char     *dmName;
328fe209ef9SBlaise Bourdin   PetscInt        nodesTriP1[4]  = {3,0,0,0};
329fe209ef9SBlaise Bourdin   PetscInt        nodesTriP2[4]  = {3,3,0,0};
330fe209ef9SBlaise Bourdin   PetscInt        nodesQuadP1[4] = {4,0,0,0};
331fe209ef9SBlaise Bourdin   PetscInt        nodesQuadP2[4] = {4,4,0,1};
332fe209ef9SBlaise Bourdin   PetscInt        nodesTetP1[4]  = {4,0,0,0};
333fe209ef9SBlaise Bourdin   PetscInt        nodesTetP2[4]  = {4,6,0,0};
334fe209ef9SBlaise Bourdin   PetscInt        nodesHexP1[4]  = {8,0,0,0};
335fe209ef9SBlaise Bourdin   PetscInt        nodesHexP2[4]  = {8,12,6,1};
33678569bb4SMatthew G. Knepley   PetscErrorCode  ierr;
33778569bb4SMatthew G. Knepley 
3386823f3c5SBlaise Bourdin   int             CPU_word_size, IO_word_size, EXO_mode;
3396823f3c5SBlaise Bourdin   float           EXO_version;
3406823f3c5SBlaise Bourdin 
3416823f3c5SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *) viewer->data;
3426823f3c5SBlaise Bourdin 
34378569bb4SMatthew G. Knepley   PetscFunctionBegin;
3445f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)dm, &comm));
3455f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm, &rank));
3465f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(comm, &size));
3476823f3c5SBlaise Bourdin 
3486823f3c5SBlaise Bourdin   /*
3496823f3c5SBlaise Bourdin     Creating coordSection is a collective operation so we do it somewhat out of sequence
3506823f3c5SBlaise Bourdin   */
3515f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionCreate(comm, &coordSection));
3525f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinatesLocalSetUp(dm));
3536823f3c5SBlaise Bourdin   if (!rank) {
3546823f3c5SBlaise Bourdin     switch (exo->btype) {
3556823f3c5SBlaise Bourdin     case FILE_MODE_READ:
3566823f3c5SBlaise Bourdin     case FILE_MODE_APPEND:
3576823f3c5SBlaise Bourdin     case FILE_MODE_UPDATE:
3586823f3c5SBlaise Bourdin     case FILE_MODE_APPEND_UPDATE:
3596823f3c5SBlaise Bourdin       /* exodusII does not allow writing geometry to an existing file */
36098921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "cannot add geometry to existing file %s", exo->filename);
3616823f3c5SBlaise Bourdin     case FILE_MODE_WRITE:
3626823f3c5SBlaise Bourdin       /* Create an empty file if one already exists*/
3636823f3c5SBlaise Bourdin       EXO_mode = EX_CLOBBER;
3646823f3c5SBlaise Bourdin #if defined(PETSC_USE_64BIT_INDICES)
3656823f3c5SBlaise Bourdin       EXO_mode += EX_ALL_INT64_API;
3666823f3c5SBlaise Bourdin #endif
3676823f3c5SBlaise Bourdin         CPU_word_size = sizeof(PetscReal);
3686823f3c5SBlaise Bourdin         IO_word_size  = sizeof(PetscReal);
3696823f3c5SBlaise Bourdin         exo->exoid = ex_create(exo->filename, EXO_mode, &CPU_word_size, &IO_word_size);
3702c71b3e2SJacob Faibussowitsch         PetscCheckFalse(exo->exoid < 0,PETSC_COMM_SELF, PETSC_ERR_LIB, "ex_create failed for %s", exo->filename);
3716823f3c5SBlaise Bourdin 
3726823f3c5SBlaise Bourdin       break;
3736823f3c5SBlaise Bourdin     default:
3746823f3c5SBlaise Bourdin       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
3756823f3c5SBlaise Bourdin     }
3766823f3c5SBlaise Bourdin 
37778569bb4SMatthew G. Knepley     /* --- Get DM info --- */
3785f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscObjectGetName((PetscObject) dm, &dmName));
3795f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetDepth(dm, &depth));
3805f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetDimension(dm, &dim));
3815f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd));
3825f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
3835f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd));
3845f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd));
3855f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
38678569bb4SMatthew G. Knepley     numCells    = cEnd - cStart;
38778569bb4SMatthew G. Knepley     numEdges    = eEnd - eStart;
38878569bb4SMatthew G. Knepley     numVertices = vEnd - vStart;
38978569bb4SMatthew G. Knepley     if (depth == 3) {numFaces = fEnd - fStart;}
39078569bb4SMatthew G. Knepley     else            {numFaces = 0;}
3915f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetLabelSize(dm, "Cell Sets", &num_cs));
3925f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetLabelSize(dm, "Vertex Sets", &num_vs));
3935f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetLabelSize(dm, "Face Sets", &num_fs));
3945f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinatesLocal(dm, &coord));
3955f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetCoordinateDM(dm, &cdm));
39678569bb4SMatthew G. Knepley     if (num_cs > 0) {
3975f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetLabel(dm, "Cell Sets", &csLabel));
3985f80ce2aSJacob Faibussowitsch       CHKERRQ(DMLabelGetValueIS(csLabel, &csIS));
3995f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetIndices(csIS, &csIdx));
40078569bb4SMatthew G. Knepley     }
4015f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(num_cs, &nodes));
40278569bb4SMatthew G. Knepley     /* Set element type for each block and compute total number of nodes */
4035f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(num_cs, &type));
40478569bb4SMatthew G. Knepley     numNodes = numVertices;
4056823f3c5SBlaise Bourdin 
4065f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscViewerExodusIIGetOrder(viewer, &degree));
40778569bb4SMatthew G. Knepley     if (degree == 2) {numNodes += numEdges;}
40878569bb4SMatthew G. Knepley     cellsNotInConnectivity = numCells;
40978569bb4SMatthew G. Knepley     for (cs = 0; cs < num_cs; ++cs) {
41078569bb4SMatthew G. Knepley       IS              stratumIS;
41178569bb4SMatthew G. Knepley       const PetscInt *cells;
41278569bb4SMatthew G. Knepley       PetscScalar    *xyz = NULL;
41378569bb4SMatthew G. Knepley       PetscInt        csSize, closureSize;
41478569bb4SMatthew G. Knepley 
4155f80ce2aSJacob Faibussowitsch       CHKERRQ(DMLabelGetStratumIS(csLabel, csIdx[cs], &stratumIS));
4165f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetIndices(stratumIS, &cells));
4175f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetSize(stratumIS, &csSize));
4185f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexVecGetClosure(cdm, NULL, coord, cells[0], &closureSize, &xyz));
41978569bb4SMatthew G. Knepley       switch (dim) {
42078569bb4SMatthew G. Knepley         case 2:
42178569bb4SMatthew G. Knepley           if      (closureSize == 3*dim) {type[cs] = TRI;}
42278569bb4SMatthew G. Knepley           else if (closureSize == 4*dim) {type[cs] = QUAD;}
42398921bdaSJacob Faibussowitsch           else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices %D in dimension %D has no ExodusII type", closureSize/dim, dim);
42478569bb4SMatthew G. Knepley           break;
42578569bb4SMatthew G. Knepley         case 3:
42678569bb4SMatthew G. Knepley           if      (closureSize == 4*dim) {type[cs] = TET;}
42778569bb4SMatthew G. Knepley           else if (closureSize == 8*dim) {type[cs] = HEX;}
42898921bdaSJacob Faibussowitsch           else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices %D in dimension %D has no ExodusII type", closureSize/dim, dim);
42978569bb4SMatthew G. Knepley           break;
43098921bdaSJacob Faibussowitsch         default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %D not handled by ExodusII viewer", dim);
43178569bb4SMatthew G. Knepley       }
43278569bb4SMatthew G. Knepley       if ((degree == 2) && (type[cs] == QUAD)) {numNodes += csSize;}
43378569bb4SMatthew G. Knepley       if ((degree == 2) && (type[cs] == HEX))  {numNodes += csSize; numNodes += numFaces;}
4345f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexVecRestoreClosure(cdm, NULL, coord, cells[0], &closureSize, &xyz));
43578569bb4SMatthew G. Knepley       /* Set nodes and Element type */
43678569bb4SMatthew G. Knepley       if (type[cs] == TRI) {
43778569bb4SMatthew G. Knepley         if      (degree == 1) nodes[cs] = nodesTriP1;
43878569bb4SMatthew G. Knepley         else if (degree == 2) nodes[cs] = nodesTriP2;
43978569bb4SMatthew G. Knepley       } else if (type[cs] == QUAD) {
44078569bb4SMatthew G. Knepley         if      (degree == 1) nodes[cs] = nodesQuadP1;
44178569bb4SMatthew G. Knepley         else if (degree == 2) nodes[cs] = nodesQuadP2;
44278569bb4SMatthew G. Knepley       } else if (type[cs] == TET) {
44378569bb4SMatthew G. Knepley         if      (degree == 1) nodes[cs] = nodesTetP1;
44478569bb4SMatthew G. Knepley         else if (degree == 2) nodes[cs] = nodesTetP2;
44578569bb4SMatthew G. Knepley       } else if (type[cs] == HEX) {
44678569bb4SMatthew G. Knepley         if      (degree == 1) nodes[cs] = nodesHexP1;
44778569bb4SMatthew G. Knepley         else if (degree == 2) nodes[cs] = nodesHexP2;
44878569bb4SMatthew G. Knepley       }
44978569bb4SMatthew G. Knepley       /* Compute the number of cells not in the connectivity table */
45078569bb4SMatthew G. Knepley       cellsNotInConnectivity -= nodes[cs][3]*csSize;
45178569bb4SMatthew G. Knepley 
4525f80ce2aSJacob Faibussowitsch       CHKERRQ(ISRestoreIndices(stratumIS, &cells));
4535f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&stratumIS));
45478569bb4SMatthew G. Knepley     }
455a74df02fSJacob Faibussowitsch     if (num_cs > 0) {PetscStackCallStandard(ex_put_init,exo->exoid, dmName, dim, numNodes, numCells, num_cs, num_vs, num_fs);}
45678569bb4SMatthew G. Knepley     /* --- Connectivity --- */
45778569bb4SMatthew G. Knepley     for (cs = 0; cs < num_cs; ++cs) {
45878569bb4SMatthew G. Knepley       IS              stratumIS;
45978569bb4SMatthew G. Knepley       const PetscInt *cells;
460fe209ef9SBlaise Bourdin       PetscInt       *connect, off = 0;
461eae8a387SMatthew G. Knepley       PetscInt        edgesInClosure = 0, facesInClosure = 0, verticesInClosure = 0;
46278569bb4SMatthew G. Knepley       PetscInt        csSize, c, connectSize, closureSize;
46378569bb4SMatthew G. Knepley       char           *elem_type = NULL;
46478569bb4SMatthew G. Knepley       char            elem_type_tri3[]  = "TRI3",  elem_type_quad4[] = "QUAD4";
46578569bb4SMatthew G. Knepley       char            elem_type_tri6[]  = "TRI6",  elem_type_quad9[] = "QUAD9";
46678569bb4SMatthew G. Knepley       char            elem_type_tet4[]  = "TET4",  elem_type_hex8[]  = "HEX8";
46778569bb4SMatthew G. Knepley       char            elem_type_tet10[] = "TET10", elem_type_hex27[] = "HEX27";
46878569bb4SMatthew G. Knepley 
4695f80ce2aSJacob Faibussowitsch       CHKERRQ(DMLabelGetStratumIS(csLabel, csIdx[cs], &stratumIS));
4705f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetIndices(stratumIS, &cells));
4715f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetSize(stratumIS, &csSize));
47278569bb4SMatthew G. Knepley       /* Set Element type */
47378569bb4SMatthew G. Knepley       if (type[cs] == TRI) {
47478569bb4SMatthew G. Knepley         if      (degree == 1) elem_type = elem_type_tri3;
47578569bb4SMatthew G. Knepley         else if (degree == 2) elem_type = elem_type_tri6;
47678569bb4SMatthew G. Knepley       } else if (type[cs] == QUAD) {
47778569bb4SMatthew G. Knepley         if      (degree == 1) elem_type = elem_type_quad4;
47878569bb4SMatthew G. Knepley         else if (degree == 2) elem_type = elem_type_quad9;
47978569bb4SMatthew G. Knepley       } else if (type[cs] == TET) {
48078569bb4SMatthew G. Knepley         if      (degree == 1) elem_type = elem_type_tet4;
48178569bb4SMatthew G. Knepley         else if (degree == 2) elem_type = elem_type_tet10;
48278569bb4SMatthew G. Knepley       } else if (type[cs] == HEX) {
48378569bb4SMatthew G. Knepley         if      (degree == 1) elem_type = elem_type_hex8;
48478569bb4SMatthew G. Knepley         else if (degree == 2) elem_type = elem_type_hex27;
48578569bb4SMatthew G. Knepley       }
48678569bb4SMatthew G. Knepley       connectSize = nodes[cs][0] + nodes[cs][1] + nodes[cs][2] + nodes[cs][3];
4875f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(PetscMax(27,connectSize)*csSize, &connect));
488a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_put_block,exo->exoid, EX_ELEM_BLOCK, csIdx[cs], elem_type, csSize, connectSize, 0, 0, 1);
48978569bb4SMatthew G. Knepley       /* Find number of vertices, edges, and faces in the closure */
49078569bb4SMatthew G. Knepley       verticesInClosure = nodes[cs][0];
49178569bb4SMatthew G. Knepley       if (depth > 1) {
49278569bb4SMatthew G. Knepley         if (dim == 2) {
4935f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexGetConeSize(dm, cells[0], &edgesInClosure));
49478569bb4SMatthew G. Knepley         } else if (dim == 3) {
49578569bb4SMatthew G. Knepley           PetscInt *closure = NULL;
49678569bb4SMatthew G. Knepley 
4975f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexGetConeSize(dm, cells[0], &facesInClosure));
4985f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexGetTransitiveClosure(dm, cells[0], PETSC_TRUE, &closureSize, &closure));
49978569bb4SMatthew G. Knepley           edgesInClosure = closureSize - facesInClosure - 1 - verticesInClosure;
5005f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexRestoreTransitiveClosure(dm, cells[0], PETSC_TRUE, &closureSize, &closure));
50178569bb4SMatthew G. Knepley         }
50278569bb4SMatthew G. Knepley       }
50378569bb4SMatthew G. Knepley       /* Get connectivity for each cell */
50478569bb4SMatthew G. Knepley       for (c = 0; c < csSize; ++c) {
50578569bb4SMatthew G. Knepley         PetscInt *closure = NULL;
50678569bb4SMatthew G. Knepley         PetscInt  temp, i;
50778569bb4SMatthew G. Knepley 
5085f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetTransitiveClosure(dm, cells[c], PETSC_TRUE, &closureSize, &closure));
50978569bb4SMatthew G. Knepley         for (i = 0; i < connectSize; ++i) {
51078569bb4SMatthew G. Knepley           if (i < nodes[cs][0]) {/* Vertices */
511fe209ef9SBlaise Bourdin             connect[i+off] = closure[(i+edgesInClosure+facesInClosure+1)*2] + 1;
512fe209ef9SBlaise Bourdin             connect[i+off] -= cellsNotInConnectivity;
51378569bb4SMatthew G. Knepley           } else if (i < nodes[cs][0]+nodes[cs][1]) { /* Edges */
514fe209ef9SBlaise Bourdin             connect[i+off] = closure[(i-verticesInClosure+facesInClosure+1)*2] + 1;
515fe209ef9SBlaise Bourdin             if (nodes[cs][2] == 0) connect[i+off] -= numFaces;
516fe209ef9SBlaise Bourdin             connect[i+off] -= cellsNotInConnectivity;
51778569bb4SMatthew G. Knepley           } else if (i < nodes[cs][0]+nodes[cs][1]+nodes[cs][3]) { /* Cells */
518fe209ef9SBlaise Bourdin             connect[i+off] = closure[0] + 1;
519fe209ef9SBlaise Bourdin             connect[i+off] -= skipCells;
52078569bb4SMatthew G. Knepley           } else if (i < nodes[cs][0]+nodes[cs][1]+nodes[cs][3]+nodes[cs][2]) { /* Faces */
521fe209ef9SBlaise Bourdin             connect[i+off] = closure[(i-edgesInClosure-verticesInClosure)*2] + 1;
522fe209ef9SBlaise Bourdin             connect[i+off] -= cellsNotInConnectivity;
52378569bb4SMatthew G. Knepley           } else {
524fe209ef9SBlaise Bourdin             connect[i+off] = -1;
52578569bb4SMatthew G. Knepley           }
52678569bb4SMatthew G. Knepley         }
52778569bb4SMatthew G. Knepley         /* Tetrahedra are inverted */
52878569bb4SMatthew G. Knepley         if (type[cs] == TET) {
529fe209ef9SBlaise Bourdin           temp = connect[0+off]; connect[0+off] = connect[1+off]; connect[1+off] = temp;
53078569bb4SMatthew G. Knepley           if (degree == 2) {
531e2c9586dSBlaise Bourdin             temp = connect[5+off]; connect[5+off] = connect[6+off]; connect[6+off] = temp;
532e2c9586dSBlaise Bourdin             temp = connect[7+off]; connect[7+off] = connect[8+off]; connect[8+off] = temp;
53378569bb4SMatthew G. Knepley           }
53478569bb4SMatthew G. Knepley         }
53578569bb4SMatthew G. Knepley         /* Hexahedra are inverted */
53678569bb4SMatthew G. Knepley         if (type[cs] == HEX) {
537fe209ef9SBlaise Bourdin           temp = connect[1+off]; connect[1+off] = connect[3+off]; connect[3+off] = temp;
53878569bb4SMatthew G. Knepley           if (degree == 2) {
539fe209ef9SBlaise Bourdin             temp = connect[8+off];  connect[8+off]  = connect[11+off]; connect[11+off] = temp;
540fe209ef9SBlaise Bourdin             temp = connect[9+off];  connect[9+off]  = connect[10+off]; connect[10+off] = temp;
541fe209ef9SBlaise Bourdin             temp = connect[16+off]; connect[16+off] = connect[17+off]; connect[17+off] = temp;
542fe209ef9SBlaise Bourdin             temp = connect[18+off]; connect[18+off] = connect[19+off]; connect[19+off] = temp;
54378569bb4SMatthew G. Knepley 
544fe209ef9SBlaise Bourdin             temp = connect[12+off]; connect[12+off] = connect[16+off]; connect[16+off] = temp;
545fe209ef9SBlaise Bourdin             temp = connect[13+off]; connect[13+off] = connect[17+off]; connect[17+off] = temp;
546fe209ef9SBlaise Bourdin             temp = connect[14+off]; connect[14+off] = connect[18+off]; connect[18+off] = temp;
547fe209ef9SBlaise Bourdin             temp = connect[15+off]; connect[15+off] = connect[19+off]; connect[19+off] = temp;
54878569bb4SMatthew G. Knepley 
549fe209ef9SBlaise Bourdin             temp = connect[23+off]; connect[23+off] = connect[26+off]; connect[26+off] = temp;
550fe209ef9SBlaise Bourdin             temp = connect[24+off]; connect[24+off] = connect[25+off]; connect[25+off] = temp;
551fe209ef9SBlaise Bourdin             temp = connect[25+off]; connect[25+off] = connect[26+off]; connect[26+off] = temp;
55278569bb4SMatthew G. Knepley           }
55378569bb4SMatthew G. Knepley         }
554fe209ef9SBlaise Bourdin         off += connectSize;
5555f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexRestoreTransitiveClosure(dm, cells[c], PETSC_TRUE, &closureSize, &closure));
55678569bb4SMatthew G. Knepley       }
557a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_put_conn,exo->exoid, EX_ELEM_BLOCK, csIdx[cs], connect, 0, 0);
55878569bb4SMatthew G. Knepley       skipCells += (nodes[cs][3] == 0)*csSize;
5595f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree(connect));
5605f80ce2aSJacob Faibussowitsch       CHKERRQ(ISRestoreIndices(stratumIS, &cells));
5615f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&stratumIS));
56278569bb4SMatthew G. Knepley     }
5635f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(type));
56478569bb4SMatthew G. Knepley     /* --- Coordinates --- */
5655f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetChart(coordSection, pStart, pEnd));
5661e50132fSMatthew G. Knepley     if (num_cs) {
56778569bb4SMatthew G. Knepley       for (d = 0; d < depth; ++d) {
5685f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
56978569bb4SMatthew G. Knepley         for (p = pStart; p < pEnd; ++p) {
5705f80ce2aSJacob Faibussowitsch           CHKERRQ(PetscSectionSetDof(coordSection, p, nodes[0][d] > 0));
57178569bb4SMatthew G. Knepley         }
57278569bb4SMatthew G. Knepley       }
5731e50132fSMatthew G. Knepley     }
57478569bb4SMatthew G. Knepley     for (cs = 0; cs < num_cs; ++cs) {
57578569bb4SMatthew G. Knepley       IS              stratumIS;
57678569bb4SMatthew G. Knepley       const PetscInt *cells;
57778569bb4SMatthew G. Knepley       PetscInt        csSize, c;
57878569bb4SMatthew G. Knepley 
5795f80ce2aSJacob Faibussowitsch       CHKERRQ(DMLabelGetStratumIS(csLabel, csIdx[cs], &stratumIS));
5805f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetIndices(stratumIS, &cells));
5815f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetSize(stratumIS, &csSize));
58278569bb4SMatthew G. Knepley       for (c = 0; c < csSize; ++c) {
5835f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionSetDof(coordSection, cells[c], nodes[cs][3] > 0));
58478569bb4SMatthew G. Knepley       }
5855f80ce2aSJacob Faibussowitsch       CHKERRQ(ISRestoreIndices(stratumIS, &cells));
5865f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&stratumIS));
58778569bb4SMatthew G. Knepley     }
58878569bb4SMatthew G. Knepley     if (num_cs > 0) {
5895f80ce2aSJacob Faibussowitsch       CHKERRQ(ISRestoreIndices(csIS, &csIdx));
5905f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&csIS));
59178569bb4SMatthew G. Knepley     }
5925f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(nodes));
5935f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetUp(coordSection));
59478569bb4SMatthew G. Knepley     if (numNodes > 0) {
59578569bb4SMatthew G. Knepley       const char  *coordNames[3] = {"x", "y", "z"};
596233c95e0SFrancesco Ballarin       PetscScalar *closure, *cval;
597233c95e0SFrancesco Ballarin       PetscReal   *coords;
59878569bb4SMatthew G. Knepley       PetscInt     hasDof, n = 0;
59978569bb4SMatthew G. Knepley 
6006823f3c5SBlaise Bourdin       /* There can't be more than 24 values in the closure of a point for the coord coordSection */
6015f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscCalloc3(numNodes*3, &coords, dim, &cval, 24, &closure));
6025f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetCoordinatesLocalNoncollective(dm, &coord));
6035f80ce2aSJacob Faibussowitsch       CHKERRQ(DMPlexGetChart(dm, &pStart, &pEnd));
60478569bb4SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
6055f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscSectionGetDof(coordSection, p, &hasDof));
60678569bb4SMatthew G. Knepley         if (hasDof) {
60778569bb4SMatthew G. Knepley           PetscInt closureSize = 24, j;
60878569bb4SMatthew G. Knepley 
6095f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexVecGetClosure(cdm, NULL, coord, p, &closureSize, &closure));
61078569bb4SMatthew G. Knepley           for (d = 0; d < dim; ++d) {
61178569bb4SMatthew G. Knepley             cval[d] = 0.0;
61278569bb4SMatthew G. Knepley             for (j = 0; j < closureSize/dim; j++) cval[d] += closure[j*dim+d];
613233c95e0SFrancesco Ballarin             coords[d*numNodes+n] = PetscRealPart(cval[d]) * dim / closureSize;
61478569bb4SMatthew G. Knepley           }
61578569bb4SMatthew G. Knepley           ++n;
61678569bb4SMatthew G. Knepley         }
61778569bb4SMatthew G. Knepley       }
618a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_put_coord,exo->exoid, &coords[0*numNodes], &coords[1*numNodes], &coords[2*numNodes]);
6195f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree3(coords, cval, closure));
620a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_put_coord_names,exo->exoid, (char **) coordNames);
62178569bb4SMatthew G. Knepley     }
6226823f3c5SBlaise Bourdin 
623fe209ef9SBlaise Bourdin     /* --- Node Sets/Vertex Sets --- */
624fe209ef9SBlaise Bourdin     DMHasLabel(dm, "Vertex Sets", &hasLabel);
625fe209ef9SBlaise Bourdin     if (hasLabel) {
626fe209ef9SBlaise Bourdin       PetscInt        i, vs, vsSize;
627fe209ef9SBlaise Bourdin       const PetscInt *vsIdx, *vertices;
628fe209ef9SBlaise Bourdin       PetscInt       *nodeList;
629fe209ef9SBlaise Bourdin       IS              vsIS, stratumIS;
630fe209ef9SBlaise Bourdin       DMLabel         vsLabel;
6315f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetLabel(dm, "Vertex Sets", &vsLabel));
6325f80ce2aSJacob Faibussowitsch       CHKERRQ(DMLabelGetValueIS(vsLabel, &vsIS));
6335f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetIndices(vsIS, &vsIdx));
634fe209ef9SBlaise Bourdin       for (vs=0; vs<num_vs; ++vs) {
6355f80ce2aSJacob Faibussowitsch         CHKERRQ(DMLabelGetStratumIS(vsLabel, vsIdx[vs], &stratumIS));
6365f80ce2aSJacob Faibussowitsch         CHKERRQ(ISGetIndices(stratumIS, &vertices));
6375f80ce2aSJacob Faibussowitsch         CHKERRQ(ISGetSize(stratumIS, &vsSize));
6385f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscMalloc1(vsSize, &nodeList));
639fe209ef9SBlaise Bourdin         for (i=0; i<vsSize; ++i) {
640fe209ef9SBlaise Bourdin           nodeList[i] = vertices[i] - skipCells + 1;
641fe209ef9SBlaise Bourdin         }
642a74df02fSJacob Faibussowitsch         PetscStackCallStandard(ex_put_set_param,exo->exoid, EX_NODE_SET, vsIdx[vs], vsSize, 0);
643a74df02fSJacob Faibussowitsch         PetscStackCallStandard(ex_put_set,exo->exoid, EX_NODE_SET, vsIdx[vs], nodeList, NULL);
6445f80ce2aSJacob Faibussowitsch         CHKERRQ(ISRestoreIndices(stratumIS, &vertices));
6455f80ce2aSJacob Faibussowitsch         CHKERRQ(ISDestroy(&stratumIS));
6465f80ce2aSJacob Faibussowitsch         CHKERRQ(PetscFree(nodeList));
647fe209ef9SBlaise Bourdin       }
6485f80ce2aSJacob Faibussowitsch       CHKERRQ(ISRestoreIndices(vsIS, &vsIdx));
6495f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&vsIS));
650fe209ef9SBlaise Bourdin     }
651fe209ef9SBlaise Bourdin     /* --- Side Sets/Face Sets --- */
6525f80ce2aSJacob Faibussowitsch     CHKERRQ(DMHasLabel(dm, "Face Sets", &hasLabel));
653fe209ef9SBlaise Bourdin     if (hasLabel) {
654fe209ef9SBlaise Bourdin       PetscInt        i, j, fs, fsSize;
655fe209ef9SBlaise Bourdin       const PetscInt *fsIdx, *faces;
656fe209ef9SBlaise Bourdin       IS              fsIS, stratumIS;
657fe209ef9SBlaise Bourdin       DMLabel         fsLabel;
658fe209ef9SBlaise Bourdin       PetscInt        numPoints, *points;
659fe209ef9SBlaise Bourdin       PetscInt        elem_list_size = 0;
660fe209ef9SBlaise Bourdin       PetscInt       *elem_list, *elem_ind, *side_list;
661fe209ef9SBlaise Bourdin 
6625f80ce2aSJacob Faibussowitsch       CHKERRQ(DMGetLabel(dm, "Face Sets", &fsLabel));
663fe209ef9SBlaise Bourdin       /* Compute size of Node List and Element List */
6645f80ce2aSJacob Faibussowitsch       CHKERRQ(DMLabelGetValueIS(fsLabel, &fsIS));
6655f80ce2aSJacob Faibussowitsch       CHKERRQ(ISGetIndices(fsIS, &fsIdx));
666fe209ef9SBlaise Bourdin       for (fs=0; fs<num_fs; ++fs) {
6675f80ce2aSJacob Faibussowitsch         CHKERRQ(DMLabelGetStratumIS(fsLabel, fsIdx[fs], &stratumIS));
6685f80ce2aSJacob Faibussowitsch         CHKERRQ(ISGetSize(stratumIS, &fsSize));
669fe209ef9SBlaise Bourdin         elem_list_size += fsSize;
6705f80ce2aSJacob Faibussowitsch         CHKERRQ(ISDestroy(&stratumIS));
671fe209ef9SBlaise Bourdin       }
672fe209ef9SBlaise Bourdin       ierr = PetscMalloc3(num_fs, &elem_ind,
673fe209ef9SBlaise Bourdin                           elem_list_size, &elem_list,
674fe209ef9SBlaise Bourdin                           elem_list_size, &side_list);CHKERRQ(ierr);
675fe209ef9SBlaise Bourdin       elem_ind[0] = 0;
676fe209ef9SBlaise Bourdin       for (fs=0; fs<num_fs; ++fs) {
6775f80ce2aSJacob Faibussowitsch         CHKERRQ(DMLabelGetStratumIS(fsLabel, fsIdx[fs], &stratumIS));
6785f80ce2aSJacob Faibussowitsch         CHKERRQ(ISGetIndices(stratumIS, &faces));
6795f80ce2aSJacob Faibussowitsch         CHKERRQ(ISGetSize(stratumIS, &fsSize));
680fe209ef9SBlaise Bourdin         /* Set Parameters */
681a74df02fSJacob Faibussowitsch         PetscStackCallStandard(ex_put_set_param,exo->exoid, EX_SIDE_SET, fsIdx[fs], fsSize, 0);
682fe209ef9SBlaise Bourdin         /* Indices */
683fe209ef9SBlaise Bourdin         if (fs<num_fs-1) {
684fe209ef9SBlaise Bourdin           elem_ind[fs+1] = elem_ind[fs] + fsSize;
685fe209ef9SBlaise Bourdin         }
686fe209ef9SBlaise Bourdin 
687fe209ef9SBlaise Bourdin         for (i=0; i<fsSize; ++i) {
688fe209ef9SBlaise Bourdin           /* Element List */
689fe209ef9SBlaise Bourdin           points = NULL;
6905f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexGetTransitiveClosure(dm, faces[i], PETSC_FALSE, &numPoints, &points));
691fe209ef9SBlaise Bourdin           elem_list[elem_ind[fs] + i] = points[2] +1;
6925f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexRestoreTransitiveClosure(dm, faces[i], PETSC_FALSE, &numPoints, &points));
693fe209ef9SBlaise Bourdin 
694fe209ef9SBlaise Bourdin           /* Side List */
695fe209ef9SBlaise Bourdin           points = NULL;
6965f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexGetTransitiveClosure(dm, elem_list[elem_ind[fs] + i]-1, PETSC_TRUE, &numPoints, &points));
697fe209ef9SBlaise Bourdin           for (j=1; j<numPoints; ++j) {
698fe209ef9SBlaise Bourdin             if (points[j*2]==faces[i]) {break;}
699fe209ef9SBlaise Bourdin           }
700fe209ef9SBlaise Bourdin           /* Convert HEX sides */
701fe209ef9SBlaise Bourdin           if (numPoints == 27) {
702fe209ef9SBlaise Bourdin             if      (j == 1) {j = 5;}
703fe209ef9SBlaise Bourdin             else if (j == 2) {j = 6;}
704fe209ef9SBlaise Bourdin             else if (j == 3) {j = 1;}
705fe209ef9SBlaise Bourdin             else if (j == 4) {j = 3;}
706fe209ef9SBlaise Bourdin             else if (j == 5) {j = 2;}
707fe209ef9SBlaise Bourdin             else if (j == 6) {j = 4;}
708fe209ef9SBlaise Bourdin           }
709fe209ef9SBlaise Bourdin           /* Convert TET sides */
710fe209ef9SBlaise Bourdin           if (numPoints == 15) {
711fe209ef9SBlaise Bourdin             --j;
712fe209ef9SBlaise Bourdin             if (j == 0) {j = 4;}
713fe209ef9SBlaise Bourdin           }
714fe209ef9SBlaise Bourdin           side_list[elem_ind[fs] + i] = j;
7155f80ce2aSJacob Faibussowitsch           CHKERRQ(DMPlexRestoreTransitiveClosure(dm, elem_list[elem_ind[fs] + i]-1, PETSC_TRUE, &numPoints, &points));
716fe209ef9SBlaise Bourdin 
717fe209ef9SBlaise Bourdin         }
7185f80ce2aSJacob Faibussowitsch         CHKERRQ(ISRestoreIndices(stratumIS, &faces));
7195f80ce2aSJacob Faibussowitsch         CHKERRQ(ISDestroy(&stratumIS));
720fe209ef9SBlaise Bourdin       }
7215f80ce2aSJacob Faibussowitsch       CHKERRQ(ISRestoreIndices(fsIS, &fsIdx));
7225f80ce2aSJacob Faibussowitsch       CHKERRQ(ISDestroy(&fsIS));
723fe209ef9SBlaise Bourdin 
724fe209ef9SBlaise Bourdin       /* Put side sets */
725fe209ef9SBlaise Bourdin       for (fs=0; fs<num_fs; ++fs) {
726a74df02fSJacob Faibussowitsch         PetscStackCallStandard(ex_put_set,exo->exoid, EX_SIDE_SET, fsIdx[fs], &elem_list[elem_ind[fs]], &side_list[elem_ind[fs]]);
727fe209ef9SBlaise Bourdin       }
7285f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree3(elem_ind,elem_list,side_list));
729fe209ef9SBlaise Bourdin     }
7306823f3c5SBlaise Bourdin     /*
7316823f3c5SBlaise Bourdin       close the exodus file
7326823f3c5SBlaise Bourdin     */
7336823f3c5SBlaise Bourdin     ex_close(exo->exoid);
7346823f3c5SBlaise Bourdin     exo->exoid = -1;
7356823f3c5SBlaise Bourdin   }
7365f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionDestroy(&coordSection));
7376823f3c5SBlaise Bourdin 
7386823f3c5SBlaise Bourdin   /*
7396823f3c5SBlaise Bourdin     reopen the file in parallel
7406823f3c5SBlaise Bourdin   */
7416823f3c5SBlaise Bourdin   EXO_mode = EX_WRITE;
7426823f3c5SBlaise Bourdin #if defined(PETSC_USE_64BIT_INDICES)
7436823f3c5SBlaise Bourdin   EXO_mode += EX_ALL_INT64_API;
7446823f3c5SBlaise Bourdin #endif
7456823f3c5SBlaise Bourdin   CPU_word_size = sizeof(PetscReal);
7466823f3c5SBlaise Bourdin   IO_word_size  = sizeof(PetscReal);
7476823f3c5SBlaise Bourdin   exo->exoid = ex_open_par(exo->filename,EXO_mode,&CPU_word_size,&IO_word_size,&EXO_version,comm,MPI_INFO_NULL);
7482c71b3e2SJacob Faibussowitsch   PetscCheckFalse(exo->exoid < 0,PETSC_COMM_SELF, PETSC_ERR_LIB, "ex_open_par failed for %s", exo->filename);
7496823f3c5SBlaise Bourdin   PetscFunctionReturn(0);
7506823f3c5SBlaise Bourdin }
7516823f3c5SBlaise Bourdin 
7526823f3c5SBlaise Bourdin /*
7536823f3c5SBlaise Bourdin   VecView_PlexExodusII_Internal - Write a Vec corresponding in an exodus file
7546823f3c5SBlaise Bourdin 
7556823f3c5SBlaise Bourdin   Collective on v
7566823f3c5SBlaise Bourdin 
7576823f3c5SBlaise Bourdin   Input Parameters:
7586823f3c5SBlaise Bourdin + v  - The vector to be written
7596823f3c5SBlaise Bourdin - viewer - The PetscViewerExodusII viewer associate to an exodus file
7606823f3c5SBlaise Bourdin 
7616823f3c5SBlaise Bourdin   Notes:
7626823f3c5SBlaise Bourdin   The exodus result variable index is obtained by comparing the Vec name and the
7636823f3c5SBlaise Bourdin   names of variables declared in the exodus file. For instance for a Vec named "V"
7646823f3c5SBlaise Bourdin   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
7656823f3c5SBlaise Bourdin   amongst all variables.
7666823f3c5SBlaise Bourdin   In the event where a nodal and zonal variable both match, the function will return an error instead of
7676823f3c5SBlaise Bourdin   possibly corrupting the file
7686823f3c5SBlaise Bourdin 
7696823f3c5SBlaise Bourdin   Level: beginner
7706823f3c5SBlaise Bourdin 
7716823f3c5SBlaise Bourdin .seealso: EXOGetVarIndex_Internal(),DMPlexView_ExodusII(),VecView_PlexExodusII()
7726823f3c5SBlaise Bourdin @*/
7736823f3c5SBlaise Bourdin PetscErrorCode VecView_PlexExodusII_Internal(Vec v, PetscViewer viewer)
7746823f3c5SBlaise Bourdin {
7756823f3c5SBlaise Bourdin   DM                 dm;
7766823f3c5SBlaise Bourdin   MPI_Comm           comm;
7776823f3c5SBlaise Bourdin   PetscMPIInt        rank;
7786823f3c5SBlaise Bourdin 
7796823f3c5SBlaise Bourdin   int                exoid,offsetN = 0, offsetZ = 0;
7806823f3c5SBlaise Bourdin   const char        *vecname;
7816823f3c5SBlaise Bourdin   PetscInt           step;
7826823f3c5SBlaise Bourdin 
7836823f3c5SBlaise Bourdin   PetscFunctionBegin;
7845f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject) v, &comm));
7855f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm, &rank));
7865f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerExodusIIGetId(viewer,&exoid));
7875f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetDM(v, &dm));
7885f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetName((PetscObject) v, &vecname));
7896823f3c5SBlaise Bourdin 
7905f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetOutputSequenceNumber(dm,&step,NULL));
7915f80ce2aSJacob Faibussowitsch   CHKERRQ(EXOGetVarIndex_Internal(exoid,EX_NODAL,vecname,&offsetN));
7925f80ce2aSJacob Faibussowitsch   CHKERRQ(EXOGetVarIndex_Internal(exoid,EX_ELEM_BLOCK,vecname,&offsetZ));
7932c71b3e2SJacob Faibussowitsch   PetscCheckFalse(offsetN <= 0 && offsetZ <= 0,comm, PETSC_ERR_FILE_UNEXPECTED, "Found both nodal and zonal variable %s in exodus file. ", vecname);
7946823f3c5SBlaise Bourdin   if (offsetN > 0) {
7955f80ce2aSJacob Faibussowitsch     CHKERRQ(VecViewPlex_ExodusII_Nodal_Internal(v,exoid,(int) step+1,offsetN));
7966823f3c5SBlaise Bourdin   } else if (offsetZ > 0) {
7975f80ce2aSJacob Faibussowitsch     CHKERRQ(VecViewPlex_ExodusII_Zonal_Internal(v,exoid,(int) step+1,offsetZ));
79898921bdaSJacob Faibussowitsch   } else SETERRQ(comm, PETSC_ERR_FILE_UNEXPECTED, "Could not find nodal or zonal variable %s in exodus file. ", vecname);
7996823f3c5SBlaise Bourdin   PetscFunctionReturn(0);
8006823f3c5SBlaise Bourdin }
8016823f3c5SBlaise Bourdin 
8026823f3c5SBlaise Bourdin /*
8036823f3c5SBlaise Bourdin   VecLoad_PlexExodusII_Internal - Write a Vec corresponding in an exodus file
8046823f3c5SBlaise Bourdin 
8056823f3c5SBlaise Bourdin   Collective on v
8066823f3c5SBlaise Bourdin 
8076823f3c5SBlaise Bourdin   Input Parameters:
8086823f3c5SBlaise Bourdin + v  - The vector to be written
8096823f3c5SBlaise Bourdin - viewer - The PetscViewerExodusII viewer associate to an exodus file
8106823f3c5SBlaise Bourdin 
8116823f3c5SBlaise Bourdin   Notes:
8126823f3c5SBlaise Bourdin   The exodus result variable index is obtained by comparing the Vec name and the
8136823f3c5SBlaise Bourdin   names of variables declared in the exodus file. For instance for a Vec named "V"
8146823f3c5SBlaise Bourdin   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
8156823f3c5SBlaise Bourdin   amongst all variables.
8166823f3c5SBlaise Bourdin   In the event where a nodal and zonal variable both match, the function will return an error instead of
8176823f3c5SBlaise Bourdin   possibly corrupting the file
8186823f3c5SBlaise Bourdin 
8196823f3c5SBlaise Bourdin   Level: beginner
8206823f3c5SBlaise Bourdin 
8216823f3c5SBlaise Bourdin .seealso: EXOGetVarIndex_Internal(),DMPlexView_ExodusII(),VecView_PlexExodusII()
8226823f3c5SBlaise Bourdin @*/
8236823f3c5SBlaise Bourdin PetscErrorCode VecLoad_PlexExodusII_Internal(Vec v, PetscViewer viewer)
8246823f3c5SBlaise Bourdin {
8256823f3c5SBlaise Bourdin   DM                 dm;
8266823f3c5SBlaise Bourdin   MPI_Comm           comm;
8276823f3c5SBlaise Bourdin   PetscMPIInt        rank;
8286823f3c5SBlaise Bourdin 
8296823f3c5SBlaise Bourdin   int                exoid,offsetN = 0, offsetZ = 0;
8306823f3c5SBlaise Bourdin   const char        *vecname;
8316823f3c5SBlaise Bourdin   PetscInt           step;
8326823f3c5SBlaise Bourdin 
8336823f3c5SBlaise Bourdin   PetscFunctionBegin;
8345f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject) v, &comm));
8355f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm, &rank));
8365f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerExodusIIGetId(viewer,&exoid));
8375f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetDM(v, &dm));
8385f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetName((PetscObject) v, &vecname));
8396823f3c5SBlaise Bourdin 
8405f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetOutputSequenceNumber(dm,&step,NULL));
8415f80ce2aSJacob Faibussowitsch   CHKERRQ(EXOGetVarIndex_Internal(exoid,EX_NODAL,vecname,&offsetN));
8425f80ce2aSJacob Faibussowitsch   CHKERRQ(EXOGetVarIndex_Internal(exoid,EX_ELEM_BLOCK,vecname,&offsetZ));
8432c71b3e2SJacob Faibussowitsch   PetscCheckFalse(offsetN <= 0 && offsetZ <= 0,comm, PETSC_ERR_FILE_UNEXPECTED, "Found both nodal and zonal variable %s in exodus file. ", vecname);
8446823f3c5SBlaise Bourdin   if (offsetN > 0) {
8455f80ce2aSJacob Faibussowitsch     CHKERRQ(VecLoadPlex_ExodusII_Nodal_Internal(v,exoid,(int) step+1,offsetN));
8466823f3c5SBlaise Bourdin   } else if (offsetZ > 0) {
8475f80ce2aSJacob Faibussowitsch     CHKERRQ(VecLoadPlex_ExodusII_Zonal_Internal(v,exoid,(int) step+1,offsetZ));
84898921bdaSJacob Faibussowitsch   } else SETERRQ(comm, PETSC_ERR_FILE_UNEXPECTED, "Could not find nodal or zonal variable %s in exodus file. ", vecname);
84978569bb4SMatthew G. Knepley   PetscFunctionReturn(0);
85078569bb4SMatthew G. Knepley }
85178569bb4SMatthew G. Knepley 
85278569bb4SMatthew G. Knepley /*
85378569bb4SMatthew G. Knepley   VecViewPlex_ExodusII_Nodal_Internal - Write a Vec corresponding to a nodal field to an exodus file
85478569bb4SMatthew G. Knepley 
85578569bb4SMatthew G. Knepley   Collective on v
85678569bb4SMatthew G. Knepley 
85778569bb4SMatthew G. Knepley   Input Parameters:
85878569bb4SMatthew G. Knepley + v  - The vector to be written
85978569bb4SMatthew G. Knepley . exoid - the exodus id of a file (obtained from ex_open or ex_create for instance)
8606823f3c5SBlaise Bourdin . step - the time step to write at (exodus steps are numbered starting from 1)
8616823f3c5SBlaise Bourdin - offset - the location of the variable in the file
86278569bb4SMatthew G. Knepley 
86378569bb4SMatthew G. Knepley   Notes:
86478569bb4SMatthew G. Knepley   The exodus result nodal variable index is obtained by comparing the Vec name and the
86578569bb4SMatthew G. Knepley   names of nodal variables declared in the exodus file. For instance for a Vec named "V"
86678569bb4SMatthew G. Knepley   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
86778569bb4SMatthew G. Knepley   amongst all nodal variables.
86878569bb4SMatthew G. Knepley 
86978569bb4SMatthew G. Knepley   Level: beginner
87078569bb4SMatthew G. Knepley 
8716823f3c5SBlaise Bourdin .seealso: EXOGetVarIndex_Internal(),DMPlexView_ExodusII_Internal(),VecLoadNodal_PlexEXO(),VecViewZonal_PlexEXO(),VecLoadZonal_PlexEXO()
87278569bb4SMatthew G. Knepley @*/
8736823f3c5SBlaise Bourdin PetscErrorCode VecViewPlex_ExodusII_Nodal_Internal(Vec v, int exoid, int step, int offset)
87478569bb4SMatthew G. Knepley {
87578569bb4SMatthew G. Knepley   MPI_Comm           comm;
87678569bb4SMatthew G. Knepley   PetscMPIInt        size;
87778569bb4SMatthew G. Knepley   DM                 dm;
87878569bb4SMatthew G. Knepley   Vec                vNatural, vComp;
87922a7544eSVaclav Hapla   const PetscScalar *varray;
88078569bb4SMatthew G. Knepley   PetscInt           xs, xe, bs;
88178569bb4SMatthew G. Knepley   PetscBool          useNatural;
88278569bb4SMatthew G. Knepley 
88378569bb4SMatthew G. Knepley   PetscFunctionBegin;
8845f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject) v, &comm));
8855f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(comm, &size));
8865f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetDM(v, &dm));
8875f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetUseNatural(dm, &useNatural));
88878569bb4SMatthew G. Knepley   useNatural = useNatural && size > 1 ? PETSC_TRUE : PETSC_FALSE;
88978569bb4SMatthew G. Knepley   if (useNatural) {
8905f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetGlobalVector(dm, &vNatural));
8915f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGlobalToNaturalBegin(dm, v, vNatural));
8925f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGlobalToNaturalEnd(dm, v, vNatural));
89378569bb4SMatthew G. Knepley   } else {
89478569bb4SMatthew G. Knepley     vNatural = v;
89578569bb4SMatthew G. Knepley   }
8966823f3c5SBlaise Bourdin 
89778569bb4SMatthew G. Knepley   /* Write local chunk of the result in the exodus file
89878569bb4SMatthew G. Knepley      exodus stores each component of a vector-valued field as a separate variable.
89978569bb4SMatthew G. Knepley      We assume that they are stored sequentially */
9005f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetOwnershipRange(vNatural, &xs, &xe));
9015f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetBlockSize(vNatural, &bs));
90278569bb4SMatthew G. Knepley   if (bs == 1) {
9035f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArrayRead(vNatural, &varray));
904a74df02fSJacob Faibussowitsch     PetscStackCallStandard(ex_put_partial_var,exoid, step, EX_NODAL, offset, 1, xs+1, xe-xs, varray);
9055f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArrayRead(vNatural, &varray));
90678569bb4SMatthew G. Knepley   } else {
90778569bb4SMatthew G. Knepley     IS       compIS;
90878569bb4SMatthew G. Knepley     PetscInt c;
90978569bb4SMatthew G. Knepley 
9105f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateStride(comm, (xe-xs)/bs, xs, bs, &compIS));
91178569bb4SMatthew G. Knepley     for (c = 0; c < bs; ++c) {
9125f80ce2aSJacob Faibussowitsch       CHKERRQ(ISStrideSetStride(compIS, (xe-xs)/bs, xs+c, bs));
9135f80ce2aSJacob Faibussowitsch       CHKERRQ(VecGetSubVector(vNatural, compIS, &vComp));
9145f80ce2aSJacob Faibussowitsch       CHKERRQ(VecGetArrayRead(vComp, &varray));
915a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_put_partial_var,exoid, step, EX_NODAL, offset+c, 1, xs/bs+1, (xe-xs)/bs, varray);
9165f80ce2aSJacob Faibussowitsch       CHKERRQ(VecRestoreArrayRead(vComp, &varray));
9175f80ce2aSJacob Faibussowitsch       CHKERRQ(VecRestoreSubVector(vNatural, compIS, &vComp));
91878569bb4SMatthew G. Knepley     }
9195f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&compIS));
92078569bb4SMatthew G. Knepley   }
9215f80ce2aSJacob Faibussowitsch   if (useNatural) CHKERRQ(DMRestoreGlobalVector(dm, &vNatural));
92278569bb4SMatthew G. Knepley   PetscFunctionReturn(0);
92378569bb4SMatthew G. Knepley }
92478569bb4SMatthew G. Knepley 
92578569bb4SMatthew G. Knepley /*
92678569bb4SMatthew G. Knepley   VecLoadPlex_ExodusII_Nodal_Internal - Read a Vec corresponding to a nodal field from an exodus file
92778569bb4SMatthew G. Knepley 
92878569bb4SMatthew G. Knepley   Collective on v
92978569bb4SMatthew G. Knepley 
93078569bb4SMatthew G. Knepley   Input Parameters:
93178569bb4SMatthew G. Knepley + v  - The vector to be written
93278569bb4SMatthew G. Knepley . exoid - the exodus id of a file (obtained from ex_open or ex_create for instance)
9336823f3c5SBlaise Bourdin . step - the time step to read at (exodus steps are numbered starting from 1)
9346823f3c5SBlaise Bourdin - offset - the location of the variable in the file
93578569bb4SMatthew G. Knepley 
93678569bb4SMatthew G. Knepley   Notes:
93778569bb4SMatthew G. Knepley   The exodus result nodal variable index is obtained by comparing the Vec name and the
93878569bb4SMatthew G. Knepley   names of nodal variables declared in the exodus file. For instance for a Vec named "V"
93978569bb4SMatthew G. Knepley   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
94078569bb4SMatthew G. Knepley   amongst all nodal variables.
94178569bb4SMatthew G. Knepley 
94278569bb4SMatthew G. Knepley   Level: beginner
94378569bb4SMatthew G. Knepley 
9446823f3c5SBlaise Bourdin .seealso: EXOGetVarIndex_Internal(), DMPlexView_ExodusII_Internal(), VecViewPlex_ExodusII_Nodal_Internal(), VecViewZonal_PlexEXO(), VecLoadZonal_PlexEXO()
94578569bb4SMatthew G. Knepley */
9466823f3c5SBlaise Bourdin PetscErrorCode VecLoadPlex_ExodusII_Nodal_Internal(Vec v, int exoid, int step, int offset)
94778569bb4SMatthew G. Knepley {
94878569bb4SMatthew G. Knepley   MPI_Comm       comm;
94978569bb4SMatthew G. Knepley   PetscMPIInt    size;
95078569bb4SMatthew G. Knepley   DM             dm;
95178569bb4SMatthew G. Knepley   Vec            vNatural, vComp;
95222a7544eSVaclav Hapla   PetscScalar   *varray;
95378569bb4SMatthew G. Knepley   PetscInt       xs, xe, bs;
95478569bb4SMatthew G. Knepley   PetscBool      useNatural;
95578569bb4SMatthew G. Knepley 
95678569bb4SMatthew G. Knepley   PetscFunctionBegin;
9575f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject) v, &comm));
9585f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(comm, &size));
9595f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetDM(v,&dm));
9605f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetUseNatural(dm, &useNatural));
96178569bb4SMatthew G. Knepley   useNatural = useNatural && size > 1 ? PETSC_TRUE : PETSC_FALSE;
9625f80ce2aSJacob Faibussowitsch   if (useNatural) CHKERRQ(DMGetGlobalVector(dm,&vNatural));
96378569bb4SMatthew G. Knepley   else            {vNatural = v;}
9646823f3c5SBlaise Bourdin 
96578569bb4SMatthew G. Knepley   /* Read local chunk from the file */
9665f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetOwnershipRange(vNatural, &xs, &xe));
9675f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetBlockSize(vNatural, &bs));
96878569bb4SMatthew G. Knepley   if (bs == 1) {
9695f80ce2aSJacob Faibussowitsch     CHKERRQ(VecGetArray(vNatural, &varray));
970a74df02fSJacob Faibussowitsch     PetscStackCallStandard(ex_get_partial_var,exoid, step, EX_NODAL, offset, 1, xs+1, xe-xs, varray);
9715f80ce2aSJacob Faibussowitsch     CHKERRQ(VecRestoreArray(vNatural, &varray));
97278569bb4SMatthew G. Knepley   } else {
97378569bb4SMatthew G. Knepley     IS       compIS;
97478569bb4SMatthew G. Knepley     PetscInt c;
97578569bb4SMatthew G. Knepley 
9765f80ce2aSJacob Faibussowitsch     CHKERRQ(ISCreateStride(comm, (xe-xs)/bs, xs, bs, &compIS));
97778569bb4SMatthew G. Knepley     for (c = 0; c < bs; ++c) {
9785f80ce2aSJacob Faibussowitsch       CHKERRQ(ISStrideSetStride(compIS, (xe-xs)/bs, xs+c, bs));
9795f80ce2aSJacob Faibussowitsch       CHKERRQ(VecGetSubVector(vNatural, compIS, &vComp));
9805f80ce2aSJacob Faibussowitsch       CHKERRQ(VecGetArray(vComp, &varray));
981a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_get_partial_var,exoid, step, EX_NODAL, offset+c, 1, xs/bs+1, (xe-xs)/bs, varray);
9825f80ce2aSJacob Faibussowitsch       CHKERRQ(VecRestoreArray(vComp, &varray));
9835f80ce2aSJacob Faibussowitsch       CHKERRQ(VecRestoreSubVector(vNatural, compIS, &vComp));
98478569bb4SMatthew G. Knepley     }
9855f80ce2aSJacob Faibussowitsch     CHKERRQ(ISDestroy(&compIS));
98678569bb4SMatthew G. Knepley   }
98778569bb4SMatthew G. Knepley   if (useNatural) {
9885f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexNaturalToGlobalBegin(dm, vNatural, v));
9895f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexNaturalToGlobalEnd(dm, vNatural, v));
9905f80ce2aSJacob Faibussowitsch     CHKERRQ(DMRestoreGlobalVector(dm, &vNatural));
99178569bb4SMatthew G. Knepley   }
99278569bb4SMatthew G. Knepley   PetscFunctionReturn(0);
99378569bb4SMatthew G. Knepley }
99478569bb4SMatthew G. Knepley 
99578569bb4SMatthew G. Knepley /*
99678569bb4SMatthew G. Knepley   VecViewPlex_ExodusII_Zonal_Internal - Write a Vec corresponding to a zonal (cell based) field to an exodus file
99778569bb4SMatthew G. Knepley 
99878569bb4SMatthew G. Knepley   Collective on v
99978569bb4SMatthew G. Knepley 
100078569bb4SMatthew G. Knepley   Input Parameters:
100178569bb4SMatthew G. Knepley + v  - The vector to be written
100278569bb4SMatthew G. Knepley . exoid - the exodus id of a file (obtained from ex_open or ex_create for instance)
10036823f3c5SBlaise Bourdin . step - the time step to write at (exodus steps are numbered starting from 1)
10046823f3c5SBlaise Bourdin - offset - the location of the variable in the file
100578569bb4SMatthew G. Knepley 
100678569bb4SMatthew G. Knepley   Notes:
100778569bb4SMatthew G. Knepley   The exodus result zonal variable index is obtained by comparing the Vec name and the
100878569bb4SMatthew G. Knepley   names of zonal variables declared in the exodus file. For instance for a Vec named "V"
100978569bb4SMatthew G. Knepley   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
101078569bb4SMatthew G. Knepley   amongst all zonal variables.
101178569bb4SMatthew G. Knepley 
101278569bb4SMatthew G. Knepley   Level: beginner
101378569bb4SMatthew G. Knepley 
10146823f3c5SBlaise Bourdin .seealso: EXOGetVarIndex_Internal(),DMPlexView_ExodusII_Internal(),VecViewPlex_ExodusII_Nodal_Internal(),VecLoadPlex_ExodusII_Nodal_Internal(),VecLoadPlex_ExodusII_Zonal_Internal()
101578569bb4SMatthew G. Knepley */
10166823f3c5SBlaise Bourdin PetscErrorCode VecViewPlex_ExodusII_Zonal_Internal(Vec v, int exoid, int step, int offset)
101778569bb4SMatthew G. Knepley {
101878569bb4SMatthew G. Knepley   MPI_Comm          comm;
101978569bb4SMatthew G. Knepley   PetscMPIInt       size;
102078569bb4SMatthew G. Knepley   DM                dm;
102178569bb4SMatthew G. Knepley   Vec               vNatural, vComp;
102222a7544eSVaclav Hapla   const PetscScalar *varray;
102378569bb4SMatthew G. Knepley   PetscInt          xs, xe, bs;
102478569bb4SMatthew G. Knepley   PetscBool         useNatural;
102578569bb4SMatthew G. Knepley   IS                compIS;
102678569bb4SMatthew G. Knepley   PetscInt         *csSize, *csID;
102778569bb4SMatthew G. Knepley   PetscInt          numCS, set, csxs = 0;
102878569bb4SMatthew G. Knepley 
102978569bb4SMatthew G. Knepley   PetscFunctionBegin;
10305f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)v, &comm));
10315f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(comm, &size));
10325f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetDM(v, &dm));
10335f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetUseNatural(dm, &useNatural));
103478569bb4SMatthew G. Knepley   useNatural = useNatural && size > 1 ? PETSC_TRUE : PETSC_FALSE;
103578569bb4SMatthew G. Knepley   if (useNatural) {
10365f80ce2aSJacob Faibussowitsch     CHKERRQ(DMGetGlobalVector(dm, &vNatural));
10375f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGlobalToNaturalBegin(dm, v, vNatural));
10385f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexGlobalToNaturalEnd(dm, v, vNatural));
103978569bb4SMatthew G. Knepley   } else {
104078569bb4SMatthew G. Knepley     vNatural = v;
104178569bb4SMatthew G. Knepley   }
10426823f3c5SBlaise Bourdin 
104378569bb4SMatthew G. Knepley   /* Write local chunk of the result in the exodus file
104478569bb4SMatthew G. Knepley      exodus stores each component of a vector-valued field as a separate variable.
104578569bb4SMatthew G. Knepley      We assume that they are stored sequentially
104678569bb4SMatthew G. Knepley      Zonal variables are accessed one element block at a time, so we loop through the cell sets,
1047a5b23f4aSJose E. Roman      but once the vector has been reordered to natural size, we cannot use the label information
104878569bb4SMatthew G. Knepley      to figure out what to save where. */
104978569bb4SMatthew G. Knepley   numCS = ex_inquire_int(exoid, EX_INQ_ELEM_BLK);
10505f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc2(numCS, &csID, numCS, &csSize));
1051a74df02fSJacob Faibussowitsch   PetscStackCallStandard(ex_get_ids,exoid, EX_ELEM_BLOCK, csID);
105278569bb4SMatthew G. Knepley   for (set = 0; set < numCS; ++set) {
105378569bb4SMatthew G. Knepley     ex_block block;
105478569bb4SMatthew G. Knepley 
105578569bb4SMatthew G. Knepley     block.id   = csID[set];
105678569bb4SMatthew G. Knepley     block.type = EX_ELEM_BLOCK;
1057a74df02fSJacob Faibussowitsch     PetscStackCallStandard(ex_get_block_param,exoid, &block);
105878569bb4SMatthew G. Knepley     csSize[set] = block.num_entry;
105978569bb4SMatthew G. Knepley   }
10605f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetOwnershipRange(vNatural, &xs, &xe));
10615f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetBlockSize(vNatural, &bs));
10625f80ce2aSJacob Faibussowitsch   if (bs > 1) CHKERRQ(ISCreateStride(comm, (xe-xs)/bs, xs, bs, &compIS));
106378569bb4SMatthew G. Knepley   for (set = 0; set < numCS; set++) {
106478569bb4SMatthew G. Knepley     PetscInt csLocalSize, c;
106578569bb4SMatthew G. Knepley 
106678569bb4SMatthew G. Knepley     /* range of indices for set setID[set]: csxs:csxs + csSize[set]-1
106778569bb4SMatthew G. Knepley        local slice of zonal values:         xs/bs,xm/bs-1
106878569bb4SMatthew G. Knepley        intersection:                        max(xs/bs,csxs),min(xm/bs-1,csxs + csSize[set]-1) */
106978569bb4SMatthew G. Knepley     csLocalSize = PetscMax(0, PetscMin(xe/bs, csxs+csSize[set]) - PetscMax(xs/bs, csxs));
107078569bb4SMatthew G. Knepley     if (bs == 1) {
10715f80ce2aSJacob Faibussowitsch       CHKERRQ(VecGetArrayRead(vNatural, &varray));
1072a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_put_partial_var,exoid, step, EX_ELEM_BLOCK, offset, csID[set], PetscMax(xs-csxs, 0)+1, csLocalSize, &varray[PetscMax(0, csxs-xs)]);
10735f80ce2aSJacob Faibussowitsch       CHKERRQ(VecRestoreArrayRead(vNatural, &varray));
107478569bb4SMatthew G. Knepley     } else {
107578569bb4SMatthew G. Knepley       for (c = 0; c < bs; ++c) {
10765f80ce2aSJacob Faibussowitsch         CHKERRQ(ISStrideSetStride(compIS, (xe-xs)/bs, xs+c, bs));
10775f80ce2aSJacob Faibussowitsch         CHKERRQ(VecGetSubVector(vNatural, compIS, &vComp));
10785f80ce2aSJacob Faibussowitsch         CHKERRQ(VecGetArrayRead(vComp, &varray));
1079a74df02fSJacob Faibussowitsch         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)]);
10805f80ce2aSJacob Faibussowitsch         CHKERRQ(VecRestoreArrayRead(vComp, &varray));
10815f80ce2aSJacob Faibussowitsch         CHKERRQ(VecRestoreSubVector(vNatural, compIS, &vComp));
108278569bb4SMatthew G. Knepley       }
108378569bb4SMatthew G. Knepley     }
108478569bb4SMatthew G. Knepley     csxs += csSize[set];
108578569bb4SMatthew G. Knepley   }
10865f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree2(csID, csSize));
10875f80ce2aSJacob Faibussowitsch   if (bs > 1) CHKERRQ(ISDestroy(&compIS));
10885f80ce2aSJacob Faibussowitsch   if (useNatural) CHKERRQ(DMRestoreGlobalVector(dm,&vNatural));
108978569bb4SMatthew G. Knepley   PetscFunctionReturn(0);
109078569bb4SMatthew G. Knepley }
109178569bb4SMatthew G. Knepley 
109278569bb4SMatthew G. Knepley /*
109378569bb4SMatthew G. Knepley   VecLoadPlex_ExodusII_Zonal_Internal - Read a Vec corresponding to a zonal (cell based) field from an exodus file
109478569bb4SMatthew G. Knepley 
109578569bb4SMatthew G. Knepley   Collective on v
109678569bb4SMatthew G. Knepley 
109778569bb4SMatthew G. Knepley   Input Parameters:
109878569bb4SMatthew G. Knepley + v  - The vector to be written
109978569bb4SMatthew G. Knepley . exoid - the exodus id of a file (obtained from ex_open or ex_create for instance)
11006823f3c5SBlaise Bourdin . step - the time step to read at (exodus steps are numbered starting from 1)
11016823f3c5SBlaise Bourdin - offset - the location of the variable in the file
110278569bb4SMatthew G. Knepley 
110378569bb4SMatthew G. Knepley   Notes:
110478569bb4SMatthew G. Knepley   The exodus result zonal variable index is obtained by comparing the Vec name and the
110578569bb4SMatthew G. Knepley   names of zonal variables declared in the exodus file. For instance for a Vec named "V"
110678569bb4SMatthew G. Knepley   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
110778569bb4SMatthew G. Knepley   amongst all zonal variables.
110878569bb4SMatthew G. Knepley 
110978569bb4SMatthew G. Knepley   Level: beginner
111078569bb4SMatthew G. Knepley 
11116823f3c5SBlaise Bourdin .seealso: EXOGetVarIndex_Internal(), DMPlexView_ExodusII_Internal(), VecViewPlex_ExodusII_Nodal_Internal(), VecLoadPlex_ExodusII_Nodal_Internal(), VecLoadPlex_ExodusII_Zonal_Internal()
111278569bb4SMatthew G. Knepley */
11136823f3c5SBlaise Bourdin PetscErrorCode VecLoadPlex_ExodusII_Zonal_Internal(Vec v, int exoid, int step, int offset)
111478569bb4SMatthew G. Knepley {
111578569bb4SMatthew G. Knepley   MPI_Comm          comm;
111678569bb4SMatthew G. Knepley   PetscMPIInt       size;
111778569bb4SMatthew G. Knepley   DM                dm;
111878569bb4SMatthew G. Knepley   Vec               vNatural, vComp;
111922a7544eSVaclav Hapla   PetscScalar      *varray;
112078569bb4SMatthew G. Knepley   PetscInt          xs, xe, bs;
112178569bb4SMatthew G. Knepley   PetscBool         useNatural;
112278569bb4SMatthew G. Knepley   IS                compIS;
112378569bb4SMatthew G. Knepley   PetscInt         *csSize, *csID;
112478569bb4SMatthew G. Knepley   PetscInt          numCS, set, csxs = 0;
112578569bb4SMatthew G. Knepley 
112678569bb4SMatthew G. Knepley   PetscFunctionBegin;
11275f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectGetComm((PetscObject)v,&comm));
11285f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(comm, &size));
11295f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetDM(v, &dm));
11305f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetUseNatural(dm, &useNatural));
113178569bb4SMatthew G. Knepley   useNatural = useNatural && size > 1 ? PETSC_TRUE : PETSC_FALSE;
11325f80ce2aSJacob Faibussowitsch   if (useNatural) CHKERRQ(DMGetGlobalVector(dm,&vNatural));
113378569bb4SMatthew G. Knepley   else            {vNatural = v;}
11346823f3c5SBlaise Bourdin 
113578569bb4SMatthew G. Knepley   /* Read local chunk of the result in the exodus file
113678569bb4SMatthew G. Knepley      exodus stores each component of a vector-valued field as a separate variable.
113778569bb4SMatthew G. Knepley      We assume that they are stored sequentially
113878569bb4SMatthew G. Knepley      Zonal variables are accessed one element block at a time, so we loop through the cell sets,
1139a5b23f4aSJose E. Roman      but once the vector has been reordered to natural size, we cannot use the label information
114078569bb4SMatthew G. Knepley      to figure out what to save where. */
114178569bb4SMatthew G. Knepley   numCS = ex_inquire_int(exoid, EX_INQ_ELEM_BLK);
11425f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscMalloc2(numCS, &csID, numCS, &csSize));
1143a74df02fSJacob Faibussowitsch   PetscStackCallStandard(ex_get_ids,exoid, EX_ELEM_BLOCK, csID);
114478569bb4SMatthew G. Knepley   for (set = 0; set < numCS; ++set) {
114578569bb4SMatthew G. Knepley     ex_block block;
114678569bb4SMatthew G. Knepley 
114778569bb4SMatthew G. Knepley     block.id   = csID[set];
114878569bb4SMatthew G. Knepley     block.type = EX_ELEM_BLOCK;
1149a74df02fSJacob Faibussowitsch     PetscStackCallStandard(ex_get_block_param,exoid, &block);
115078569bb4SMatthew G. Knepley     csSize[set] = block.num_entry;
115178569bb4SMatthew G. Knepley   }
11525f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetOwnershipRange(vNatural, &xs, &xe));
11535f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetBlockSize(vNatural, &bs));
11545f80ce2aSJacob Faibussowitsch   if (bs > 1) CHKERRQ(ISCreateStride(comm, (xe-xs)/bs, xs, bs, &compIS));
115578569bb4SMatthew G. Knepley   for (set = 0; set < numCS; ++set) {
115678569bb4SMatthew G. Knepley     PetscInt csLocalSize, c;
115778569bb4SMatthew G. Knepley 
115878569bb4SMatthew G. Knepley     /* range of indices for set setID[set]: csxs:csxs + csSize[set]-1
115978569bb4SMatthew G. Knepley        local slice of zonal values:         xs/bs,xm/bs-1
116078569bb4SMatthew G. Knepley        intersection:                        max(xs/bs,csxs),min(xm/bs-1,csxs + csSize[set]-1) */
116178569bb4SMatthew G. Knepley     csLocalSize = PetscMax(0, PetscMin(xe/bs, csxs+csSize[set]) - PetscMax(xs/bs, csxs));
116278569bb4SMatthew G. Knepley     if (bs == 1) {
11635f80ce2aSJacob Faibussowitsch       CHKERRQ(VecGetArray(vNatural, &varray));
1164a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_get_partial_var,exoid, step, EX_ELEM_BLOCK, offset, csID[set], PetscMax(xs-csxs, 0)+1, csLocalSize, &varray[PetscMax(0, csxs-xs)]);
11655f80ce2aSJacob Faibussowitsch       CHKERRQ(VecRestoreArray(vNatural, &varray));
116678569bb4SMatthew G. Knepley     } else {
116778569bb4SMatthew G. Knepley       for (c = 0; c < bs; ++c) {
11685f80ce2aSJacob Faibussowitsch         CHKERRQ(ISStrideSetStride(compIS, (xe-xs)/bs, xs+c, bs));
11695f80ce2aSJacob Faibussowitsch         CHKERRQ(VecGetSubVector(vNatural, compIS, &vComp));
11705f80ce2aSJacob Faibussowitsch         CHKERRQ(VecGetArray(vComp, &varray));
1171a74df02fSJacob Faibussowitsch         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)]);
11725f80ce2aSJacob Faibussowitsch         CHKERRQ(VecRestoreArray(vComp, &varray));
11735f80ce2aSJacob Faibussowitsch         CHKERRQ(VecRestoreSubVector(vNatural, compIS, &vComp));
117478569bb4SMatthew G. Knepley       }
117578569bb4SMatthew G. Knepley     }
117678569bb4SMatthew G. Knepley     csxs += csSize[set];
117778569bb4SMatthew G. Knepley   }
11785f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscFree2(csID, csSize));
11795f80ce2aSJacob Faibussowitsch   if (bs > 1) CHKERRQ(ISDestroy(&compIS));
118078569bb4SMatthew G. Knepley   if (useNatural) {
11815f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexNaturalToGlobalBegin(dm, vNatural, v));
11825f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexNaturalToGlobalEnd(dm, vNatural, v));
11835f80ce2aSJacob Faibussowitsch     CHKERRQ(DMRestoreGlobalVector(dm, &vNatural));
118478569bb4SMatthew G. Knepley   }
118578569bb4SMatthew G. Knepley   PetscFunctionReturn(0);
118678569bb4SMatthew G. Knepley }
1187b53c8456SSatish Balay #endif
118878569bb4SMatthew G. Knepley 
11891e50132fSMatthew G. Knepley /*@
11901e50132fSMatthew G. Knepley   PetscViewerExodusIIGetId - Get the file id of the ExodusII file
11911e50132fSMatthew G. Knepley 
11921e50132fSMatthew G. Knepley   Logically Collective on PetscViewer
11931e50132fSMatthew G. Knepley 
11941e50132fSMatthew G. Knepley   Input Parameter:
11951e50132fSMatthew G. Knepley .  viewer - the PetscViewer
11961e50132fSMatthew G. Knepley 
11971e50132fSMatthew G. Knepley   Output Parameter:
1198d8d19677SJose E. Roman .  exoid - The ExodusII file id
11991e50132fSMatthew G. Knepley 
12001e50132fSMatthew G. Knepley   Level: intermediate
12011e50132fSMatthew G. Knepley 
12021e50132fSMatthew G. Knepley .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()
12031e50132fSMatthew G. Knepley @*/
12041e50132fSMatthew G. Knepley PetscErrorCode PetscViewerExodusIIGetId(PetscViewer viewer, int *exoid)
12051e50132fSMatthew G. Knepley {
12061e50132fSMatthew G. Knepley   PetscFunctionBegin;
12071e50132fSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
12085f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTryMethod(viewer, "PetscViewerGetId_C",(PetscViewer,int*),(viewer,exoid)));
12096823f3c5SBlaise Bourdin   PetscFunctionReturn(0);
12106823f3c5SBlaise Bourdin }
12116823f3c5SBlaise Bourdin 
12126823f3c5SBlaise Bourdin /*@
12136823f3c5SBlaise Bourdin    PetscViewerExodusIISetOrder - Set the elements order in the exodusII file.
12146823f3c5SBlaise Bourdin 
12156823f3c5SBlaise Bourdin    Collective
12166823f3c5SBlaise Bourdin 
12176823f3c5SBlaise Bourdin    Input Parameters:
12186823f3c5SBlaise Bourdin +  viewer - the viewer
121998a6a78aSPierre Jolivet -  order - elements order
12206823f3c5SBlaise Bourdin 
12216823f3c5SBlaise Bourdin    Output Parameter:
12226823f3c5SBlaise Bourdin 
12236823f3c5SBlaise Bourdin    Level: beginner
12246823f3c5SBlaise Bourdin 
12256823f3c5SBlaise Bourdin    Note:
12266823f3c5SBlaise Bourdin 
12276823f3c5SBlaise Bourdin .seealso: PetscViewerExodusIIGetId(), PetscViewerExodusIIGetOrder(), PetscViewerExodusIISetOrder()
12286823f3c5SBlaise Bourdin @*/
12296823f3c5SBlaise Bourdin PetscErrorCode PetscViewerExodusIISetOrder(PetscViewer viewer, PetscInt order)
12306823f3c5SBlaise Bourdin {
12316823f3c5SBlaise Bourdin   PetscFunctionBegin;
12326823f3c5SBlaise Bourdin   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
12335f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTryMethod(viewer, "PetscViewerSetOrder_C",(PetscViewer,PetscInt),(viewer,order)));
12346823f3c5SBlaise Bourdin   PetscFunctionReturn(0);
12356823f3c5SBlaise Bourdin }
12366823f3c5SBlaise Bourdin 
12376823f3c5SBlaise Bourdin /*@
12386823f3c5SBlaise Bourdin    PetscViewerExodusIIGetOrder - Get the elements order in the exodusII file.
12396823f3c5SBlaise Bourdin 
12406823f3c5SBlaise Bourdin    Collective
12416823f3c5SBlaise Bourdin 
12426823f3c5SBlaise Bourdin    Input Parameters:
12436823f3c5SBlaise Bourdin +  viewer - the viewer
124498a6a78aSPierre Jolivet -  order - elements order
12456823f3c5SBlaise Bourdin 
12466823f3c5SBlaise Bourdin    Output Parameter:
12476823f3c5SBlaise Bourdin 
12486823f3c5SBlaise Bourdin    Level: beginner
12496823f3c5SBlaise Bourdin 
12506823f3c5SBlaise Bourdin    Note:
12516823f3c5SBlaise Bourdin 
12526823f3c5SBlaise Bourdin .seealso: PetscViewerExodusIIGetId(), PetscViewerExodusIIGetOrder(), PetscViewerExodusIISetOrder()
12536823f3c5SBlaise Bourdin @*/
12546823f3c5SBlaise Bourdin PetscErrorCode PetscViewerExodusIIGetOrder(PetscViewer viewer, PetscInt *order)
12556823f3c5SBlaise Bourdin {
12566823f3c5SBlaise Bourdin   PetscFunctionBegin;
12576823f3c5SBlaise Bourdin   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
12585f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscTryMethod(viewer, "PetscViewerGetOrder_C",(PetscViewer,PetscInt*),(viewer,order)));
12596823f3c5SBlaise Bourdin   PetscFunctionReturn(0);
12606823f3c5SBlaise Bourdin }
12616823f3c5SBlaise Bourdin 
12626823f3c5SBlaise Bourdin /*@C
12636823f3c5SBlaise Bourdin    PetscViewerExodusIIOpen - Opens a file for ExodusII input/output.
12646823f3c5SBlaise Bourdin 
12656823f3c5SBlaise Bourdin    Collective
12666823f3c5SBlaise Bourdin 
12676823f3c5SBlaise Bourdin    Input Parameters:
12686823f3c5SBlaise Bourdin +  comm - MPI communicator
12696823f3c5SBlaise Bourdin .  name - name of file
12706823f3c5SBlaise Bourdin -  type - type of file
12716823f3c5SBlaise Bourdin $    FILE_MODE_WRITE - create new file for binary output
12726823f3c5SBlaise Bourdin $    FILE_MODE_READ - open existing file for binary input
12736823f3c5SBlaise Bourdin $    FILE_MODE_APPEND - open existing file for binary output
12746823f3c5SBlaise Bourdin 
12756823f3c5SBlaise Bourdin    Output Parameter:
12766823f3c5SBlaise Bourdin .  exo - PetscViewer for Exodus II input/output to use with the specified file
12776823f3c5SBlaise Bourdin 
12786823f3c5SBlaise Bourdin    Level: beginner
12796823f3c5SBlaise Bourdin 
12806823f3c5SBlaise Bourdin    Note:
12816823f3c5SBlaise Bourdin    This PetscViewer should be destroyed with PetscViewerDestroy().
12826823f3c5SBlaise Bourdin 
12836823f3c5SBlaise Bourdin .seealso: PetscViewerPushFormat(), PetscViewerDestroy(),
12846823f3c5SBlaise Bourdin           DMLoad(), PetscFileMode, PetscViewer, PetscViewerSetType(), PetscViewerFileSetMode(), PetscViewerFileSetName()
12856823f3c5SBlaise Bourdin @*/
12866823f3c5SBlaise Bourdin PetscErrorCode PetscViewerExodusIIOpen(MPI_Comm comm, const char name[], PetscFileMode type, PetscViewer *exo)
12876823f3c5SBlaise Bourdin {
12886823f3c5SBlaise Bourdin   PetscFunctionBegin;
12895f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerCreate(comm, exo));
12905f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerSetType(*exo, PETSCVIEWEREXODUSII));
12915f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerFileSetMode(*exo, type));
12925f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerFileSetName(*exo, name));
12935f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscViewerSetFromOptions(*exo));
12941e50132fSMatthew G. Knepley   PetscFunctionReturn(0);
12951e50132fSMatthew G. Knepley }
12961e50132fSMatthew G. Knepley 
129733751fbdSMichael Lange /*@C
1298eaf898f9SPatrick Sanan   DMPlexCreateExodusFromFile - Create a DMPlex mesh from an ExodusII file.
129933751fbdSMichael Lange 
1300d083f849SBarry Smith   Collective
130133751fbdSMichael Lange 
130233751fbdSMichael Lange   Input Parameters:
130333751fbdSMichael Lange + comm  - The MPI communicator
130433751fbdSMichael Lange . filename - The name of the ExodusII file
130533751fbdSMichael Lange - interpolate - Create faces and edges in the mesh
130633751fbdSMichael Lange 
130733751fbdSMichael Lange   Output Parameter:
130833751fbdSMichael Lange . dm  - The DM object representing the mesh
130933751fbdSMichael Lange 
131033751fbdSMichael Lange   Level: beginner
131133751fbdSMichael Lange 
131233751fbdSMichael Lange .seealso: DMPLEX, DMCreate(), DMPlexCreateExodus()
131333751fbdSMichael Lange @*/
131433751fbdSMichael Lange PetscErrorCode DMPlexCreateExodusFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm)
131533751fbdSMichael Lange {
131633751fbdSMichael Lange   PetscMPIInt    rank;
131733751fbdSMichael Lange #if defined(PETSC_HAVE_EXODUSII)
1318e84f7031SBlaise Bourdin   int   CPU_word_size = sizeof(PetscReal), IO_word_size = 0, exoid = -1;
131933751fbdSMichael Lange   float version;
132033751fbdSMichael Lange #endif
132133751fbdSMichael Lange 
132233751fbdSMichael Lange   PetscFunctionBegin;
132333751fbdSMichael Lange   PetscValidCharPointer(filename, 2);
13245f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm, &rank));
132533751fbdSMichael Lange #if defined(PETSC_HAVE_EXODUSII)
1326dd400576SPatrick Sanan   if (rank == 0) {
132733751fbdSMichael Lange     exoid = ex_open(filename, EX_READ, &CPU_word_size, &IO_word_size, &version);
13282c71b3e2SJacob Faibussowitsch     PetscCheckFalse(exoid <= 0,PETSC_COMM_SELF, PETSC_ERR_LIB, "ex_open(\"%s\",...) did not return a valid file ID", filename);
132933751fbdSMichael Lange   }
13305f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexCreateExodus(comm, exoid, interpolate, dm));
1331a74df02fSJacob Faibussowitsch   if (rank == 0) {PetscStackCallStandard(ex_close,exoid);}
1332b458e8f1SJose E. Roman   PetscFunctionReturn(0);
133333751fbdSMichael Lange #else
133433751fbdSMichael Lange   SETERRQ(comm, PETSC_ERR_SUP, "This method requires ExodusII support. Reconfigure using --download-exodusii");
133533751fbdSMichael Lange #endif
133633751fbdSMichael Lange }
133733751fbdSMichael Lange 
13388f861fbcSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
13396823f3c5SBlaise Bourdin static PetscErrorCode ExodusGetCellType_Internal(const char *elem_type, DMPolytopeType *ct)
13408f861fbcSMatthew G. Knepley {
13418f861fbcSMatthew G. Knepley   PetscBool      flg;
13428f861fbcSMatthew G. Knepley 
13438f861fbcSMatthew G. Knepley   PetscFunctionBegin;
13448f861fbcSMatthew G. Knepley   *ct = DM_POLYTOPE_UNKNOWN;
13455f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(elem_type, "TRI", &flg));
13468f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_TRIANGLE; goto done;}
13475f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(elem_type, "TRI3", &flg));
13488f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_TRIANGLE; goto done;}
13495f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(elem_type, "QUAD", &flg));
13508f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_QUADRILATERAL; goto done;}
13515f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(elem_type, "QUAD4", &flg));
13528f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_QUADRILATERAL; goto done;}
13535f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(elem_type, "SHELL4", &flg));
13548f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_QUADRILATERAL; goto done;}
13555f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(elem_type, "TETRA", &flg));
13568f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_TETRAHEDRON; goto done;}
13575f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(elem_type, "TET4", &flg));
13588f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_TETRAHEDRON; goto done;}
13595f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(elem_type, "WEDGE", &flg));
13608f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_TRI_PRISM; goto done;}
13615f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(elem_type, "HEX", &flg));
13628f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_HEXAHEDRON; goto done;}
13635f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(elem_type, "HEX8", &flg));
13648f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_HEXAHEDRON; goto done;}
13655f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscStrcmp(elem_type, "HEXAHEDRON", &flg));
13668f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_HEXAHEDRON; goto done;}
136798921bdaSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unrecognized element type %s", elem_type);
13688f861fbcSMatthew G. Knepley   done:
13698f861fbcSMatthew G. Knepley   PetscFunctionReturn(0);
13708f861fbcSMatthew G. Knepley }
13718f861fbcSMatthew G. Knepley #endif
13728f861fbcSMatthew G. Knepley 
1373552f7358SJed Brown /*@
137433751fbdSMichael Lange   DMPlexCreateExodus - Create a DMPlex mesh from an ExodusII file ID.
1375552f7358SJed Brown 
1376d083f849SBarry Smith   Collective
1377552f7358SJed Brown 
1378552f7358SJed Brown   Input Parameters:
1379552f7358SJed Brown + comm  - The MPI communicator
1380552f7358SJed Brown . exoid - The ExodusII id associated with a exodus file and obtained using ex_open
1381552f7358SJed Brown - interpolate - Create faces and edges in the mesh
1382552f7358SJed Brown 
1383552f7358SJed Brown   Output Parameter:
1384552f7358SJed Brown . dm  - The DM object representing the mesh
1385552f7358SJed Brown 
1386552f7358SJed Brown   Level: beginner
1387552f7358SJed Brown 
1388e84e7769SJed Brown .seealso: DMPLEX, DMCreate()
1389552f7358SJed Brown @*/
1390552f7358SJed Brown PetscErrorCode DMPlexCreateExodus(MPI_Comm comm, PetscInt exoid, PetscBool interpolate, DM *dm)
1391552f7358SJed Brown {
1392552f7358SJed Brown #if defined(PETSC_HAVE_EXODUSII)
1393552f7358SJed Brown   PetscMPIInt    num_proc, rank;
1394ae9eebabSLisandro Dalcin   DMLabel        cellSets = NULL, faceSets = NULL, vertSets = NULL;
1395552f7358SJed Brown   PetscSection   coordSection;
1396552f7358SJed Brown   Vec            coordinates;
1397552f7358SJed Brown   PetscScalar    *coords;
1398552f7358SJed Brown   PetscInt       coordSize, v;
1399552f7358SJed Brown   /* Read from ex_get_init() */
1400552f7358SJed Brown   char title[PETSC_MAX_PATH_LEN+1];
14015f80ce2aSJacob Faibussowitsch   int  dim    = 0, dimEmbed = 0, numVertices = 0, numCells = 0;
1402552f7358SJed Brown   int  num_cs = 0, num_vs = 0, num_fs = 0;
1403552f7358SJed Brown #endif
1404552f7358SJed Brown 
1405552f7358SJed Brown   PetscFunctionBegin;
1406552f7358SJed Brown #if defined(PETSC_HAVE_EXODUSII)
14075f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_rank(comm, &rank));
14085f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Comm_size(comm, &num_proc));
14095f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreate(comm, dm));
14105f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetType(*dm, DMPLEX));
1411a5b23f4aSJose E. Roman   /* Open EXODUS II file and read basic information on rank 0, then broadcast to all processors */
1412dd400576SPatrick Sanan   if (rank == 0) {
14135f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMemzero(title,PETSC_MAX_PATH_LEN+1));
1414a74df02fSJacob Faibussowitsch     PetscStackCallStandard(ex_get_init,exoid, title, &dimEmbed, &numVertices, &numCells, &num_cs, &num_vs, &num_fs);
1415*28b400f6SJacob Faibussowitsch     PetscCheck(num_cs,PETSC_COMM_SELF,PETSC_ERR_SUP,"Exodus file does not contain any cell set");
1416552f7358SJed Brown   }
14175f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Bcast(title, PETSC_MAX_PATH_LEN+1, MPI_CHAR, 0, comm));
14185f80ce2aSJacob Faibussowitsch   CHKERRMPI(MPI_Bcast(&dim, 1, MPI_INT, 0, comm));
14195f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) *dm, title));
14205f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSetChart(*dm, 0, numCells+numVertices));
1421412e9a14SMatthew G. Knepley   /*   We do not want this label automatically computed, instead we compute it here */
14225f80ce2aSJacob Faibussowitsch   CHKERRQ(DMCreateLabel(*dm, "celltype"));
1423552f7358SJed Brown 
1424552f7358SJed Brown   /* Read cell sets information */
1425dd400576SPatrick Sanan   if (rank == 0) {
1426552f7358SJed Brown     PetscInt *cone;
1427e8f6893fSMatthew G. Knepley     int      c, cs, ncs, c_loc, v, v_loc;
1428552f7358SJed Brown     /* Read from ex_get_elem_blk_ids() */
1429e8f6893fSMatthew G. Knepley     int *cs_id, *cs_order;
1430552f7358SJed Brown     /* Read from ex_get_elem_block() */
1431552f7358SJed Brown     char buffer[PETSC_MAX_PATH_LEN+1];
1432e8f6893fSMatthew G. Knepley     int  num_cell_in_set, num_vertex_per_cell, num_hybrid, num_attr;
1433552f7358SJed Brown     /* Read from ex_get_elem_conn() */
1434552f7358SJed Brown     int *cs_connect;
1435552f7358SJed Brown 
1436552f7358SJed Brown     /* Get cell sets IDs */
14375f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc2(num_cs, &cs_id, num_cs, &cs_order));
1438a74df02fSJacob Faibussowitsch     PetscStackCallStandard(ex_get_ids,exoid, EX_ELEM_BLOCK, cs_id);
1439552f7358SJed Brown     /* Read the cell set connectivity table and build mesh topology
1440552f7358SJed Brown        EXO standard requires that cells in cell sets be numbered sequentially and be pairwise disjoint. */
1441e8f6893fSMatthew G. Knepley     /* Check for a hybrid mesh */
1442e8f6893fSMatthew G. Knepley     for (cs = 0, num_hybrid = 0; cs < num_cs; ++cs) {
14438f861fbcSMatthew G. Knepley       DMPolytopeType ct;
14448f861fbcSMatthew G. Knepley       char           elem_type[PETSC_MAX_PATH_LEN];
14458f861fbcSMatthew G. Knepley 
14465f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscArrayzero(elem_type, sizeof(elem_type)));
1447a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_get_elem_type,exoid, cs_id[cs], elem_type);
14485f80ce2aSJacob Faibussowitsch       CHKERRQ(ExodusGetCellType_Internal(elem_type, &ct));
14498f861fbcSMatthew G. Knepley       dim  = PetscMax(dim, DMPolytopeTypeGetDim(ct));
1450a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_get_block,exoid, EX_ELEM_BLOCK, cs_id[cs], buffer, &num_cell_in_set,&num_vertex_per_cell, 0, 0, &num_attr);
14518f861fbcSMatthew G. Knepley       switch (ct) {
14528f861fbcSMatthew G. Knepley         case DM_POLYTOPE_TRI_PRISM:
1453e8f6893fSMatthew G. Knepley           cs_order[cs] = cs;
1454e8f6893fSMatthew G. Knepley           ++num_hybrid;
1455e8f6893fSMatthew G. Knepley           break;
1456e8f6893fSMatthew G. Knepley         default:
1457e8f6893fSMatthew G. Knepley           for (c = cs; c > cs-num_hybrid; --c) cs_order[c] = cs_order[c-1];
1458e8f6893fSMatthew G. Knepley           cs_order[cs-num_hybrid] = cs;
1459e8f6893fSMatthew G. Knepley       }
1460e8f6893fSMatthew G. Knepley     }
1461552f7358SJed Brown     /* First set sizes */
1462e8f6893fSMatthew G. Knepley     for (ncs = 0, c = 0; ncs < num_cs; ++ncs) {
14638f861fbcSMatthew G. Knepley       DMPolytopeType ct;
14648f861fbcSMatthew G. Knepley       char           elem_type[PETSC_MAX_PATH_LEN];
1465e8f6893fSMatthew G. Knepley       const PetscInt cs = cs_order[ncs];
14668f861fbcSMatthew G. Knepley 
14675f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscArrayzero(elem_type, sizeof(elem_type)));
1468a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_get_elem_type,exoid, cs_id[cs], elem_type);
14695f80ce2aSJacob Faibussowitsch       CHKERRQ(ExodusGetCellType_Internal(elem_type, &ct));
1470a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_get_block,exoid, EX_ELEM_BLOCK, cs_id[cs], buffer, &num_cell_in_set,&num_vertex_per_cell, 0, 0, &num_attr);
1471552f7358SJed Brown       for (c_loc = 0; c_loc < num_cell_in_set; ++c_loc, ++c) {
14725f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetConeSize(*dm, c, num_vertex_per_cell));
14735f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCellType(*dm, c, ct));
1474552f7358SJed Brown       }
1475552f7358SJed Brown     }
14765f80ce2aSJacob Faibussowitsch     for (v = numCells; v < numCells+numVertices; ++v) CHKERRQ(DMPlexSetCellType(*dm, v, DM_POLYTOPE_POINT));
14775f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetUp(*dm));
1478e8f6893fSMatthew G. Knepley     for (ncs = 0, c = 0; ncs < num_cs; ++ncs) {
1479e8f6893fSMatthew G. Knepley       const PetscInt cs = cs_order[ncs];
1480a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_get_block,exoid, EX_ELEM_BLOCK, cs_id[cs], buffer, &num_cell_in_set, &num_vertex_per_cell, 0, 0, &num_attr);
14815f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc2(num_vertex_per_cell*num_cell_in_set,&cs_connect,num_vertex_per_cell,&cone));
1482a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_get_conn,exoid, EX_ELEM_BLOCK, cs_id[cs], cs_connect,NULL,NULL);
1483eaf898f9SPatrick Sanan       /* EXO uses Fortran-based indexing, DMPlex uses C-style and numbers cell first then vertices. */
1484552f7358SJed Brown       for (c_loc = 0, v = 0; c_loc < num_cell_in_set; ++c_loc, ++c) {
1485636e64ffSStefano Zampini         DMPolytopeType ct;
1486636e64ffSStefano Zampini 
1487552f7358SJed Brown         for (v_loc = 0; v_loc < num_vertex_per_cell; ++v_loc, ++v) {
1488552f7358SJed Brown           cone[v_loc] = cs_connect[v]+numCells-1;
1489552f7358SJed Brown         }
14905f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetCellType(*dm, c, &ct));
14915f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexInvertCell(ct, cone));
14925f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexSetCone(*dm, c, cone));
14935f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue_Fast(*dm, &cellSets, "Cell Sets", c, cs_id[cs]));
1494552f7358SJed Brown       }
14955f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree2(cs_connect,cone));
1496552f7358SJed Brown     }
14975f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree2(cs_id, cs_order));
1498552f7358SJed Brown   }
14998f861fbcSMatthew G. Knepley   {
15008f861fbcSMatthew G. Knepley     PetscInt ints[] = {dim, dimEmbed};
15018f861fbcSMatthew G. Knepley 
15025f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Bcast(ints, 2, MPIU_INT, 0, comm));
15035f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetDimension(*dm, ints[0]));
15045f80ce2aSJacob Faibussowitsch     CHKERRQ(DMSetCoordinateDim(*dm, ints[1]));
15058f861fbcSMatthew G. Knepley     dim      = ints[0];
15068f861fbcSMatthew G. Knepley     dimEmbed = ints[1];
15078f861fbcSMatthew G. Knepley   }
15085f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexSymmetrize(*dm));
15095f80ce2aSJacob Faibussowitsch   CHKERRQ(DMPlexStratify(*dm));
1510552f7358SJed Brown   if (interpolate) {
15115fd9971aSMatthew G. Knepley     DM idm;
1512552f7358SJed Brown 
15135f80ce2aSJacob Faibussowitsch     CHKERRQ(DMPlexInterpolate(*dm, &idm));
15145f80ce2aSJacob Faibussowitsch     CHKERRQ(DMDestroy(dm));
1515552f7358SJed Brown     *dm  = idm;
1516552f7358SJed Brown   }
1517552f7358SJed Brown 
1518552f7358SJed Brown   /* Create vertex set label */
1519dd400576SPatrick Sanan   if (rank == 0 && (num_vs > 0)) {
1520552f7358SJed Brown     int vs, v;
1521552f7358SJed Brown     /* Read from ex_get_node_set_ids() */
1522552f7358SJed Brown     int *vs_id;
1523552f7358SJed Brown     /* Read from ex_get_node_set_param() */
1524f958083aSBlaise Bourdin     int num_vertex_in_set;
1525552f7358SJed Brown     /* Read from ex_get_node_set() */
1526552f7358SJed Brown     int *vs_vertex_list;
1527552f7358SJed Brown 
1528552f7358SJed Brown     /* Get vertex set ids */
15295f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(num_vs, &vs_id));
1530a74df02fSJacob Faibussowitsch     PetscStackCallStandard(ex_get_ids,exoid, EX_NODE_SET, vs_id);
1531552f7358SJed Brown     for (vs = 0; vs < num_vs; ++vs) {
1532a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_get_set_param,exoid, EX_NODE_SET, vs_id[vs], &num_vertex_in_set, NULL);
15335f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc1(num_vertex_in_set, &vs_vertex_list));
1534a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_get_set,exoid, EX_NODE_SET, vs_id[vs], vs_vertex_list, NULL);
1535552f7358SJed Brown       for (v = 0; v < num_vertex_in_set; ++v) {
15365f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vs_vertex_list[v]+numCells-1, vs_id[vs]));
1537552f7358SJed Brown       }
15385f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree(vs_vertex_list));
1539552f7358SJed Brown     }
15405f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(vs_id));
1541552f7358SJed Brown   }
1542552f7358SJed Brown   /* Read coordinates */
15435f80ce2aSJacob Faibussowitsch   CHKERRQ(DMGetCoordinateSection(*dm, &coordSection));
15445f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetNumFields(coordSection, 1));
15455f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed));
15465f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
1547552f7358SJed Brown   for (v = numCells; v < numCells+numVertices; ++v) {
15485f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetDof(coordSection, v, dimEmbed));
15495f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed));
1550552f7358SJed Brown   }
15515f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionSetUp(coordSection));
15525f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscSectionGetStorageSize(coordSection, &coordSize));
15535f80ce2aSJacob Faibussowitsch   CHKERRQ(VecCreate(PETSC_COMM_SELF, &coordinates));
15545f80ce2aSJacob Faibussowitsch   CHKERRQ(PetscObjectSetName((PetscObject) coordinates, "coordinates"));
15555f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
15565f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetBlockSize(coordinates, dimEmbed));
15575f80ce2aSJacob Faibussowitsch   CHKERRQ(VecSetType(coordinates,VECSTANDARD));
15585f80ce2aSJacob Faibussowitsch   CHKERRQ(VecGetArray(coordinates, &coords));
1559dd400576SPatrick Sanan   if (rank == 0) {
1560e84f7031SBlaise Bourdin     PetscReal *x, *y, *z;
1561552f7358SJed Brown 
15625f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc3(numVertices,&x,numVertices,&y,numVertices,&z));
1563a74df02fSJacob Faibussowitsch     PetscStackCallStandard(ex_get_coord,exoid, x, y, z);
15648f861fbcSMatthew G. Knepley     if (dimEmbed > 0) {
15658f861fbcSMatthew G. Knepley       for (v = 0; v < numVertices; ++v) coords[v*dimEmbed+0] = x[v];
15660d644c17SKarl Rupp     }
15678f861fbcSMatthew G. Knepley     if (dimEmbed > 1) {
15688f861fbcSMatthew G. Knepley       for (v = 0; v < numVertices; ++v) coords[v*dimEmbed+1] = y[v];
15690d644c17SKarl Rupp     }
15708f861fbcSMatthew G. Knepley     if (dimEmbed > 2) {
15718f861fbcSMatthew G. Knepley       for (v = 0; v < numVertices; ++v) coords[v*dimEmbed+2] = z[v];
15720d644c17SKarl Rupp     }
15735f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree3(x,y,z));
1574552f7358SJed Brown   }
15755f80ce2aSJacob Faibussowitsch   CHKERRQ(VecRestoreArray(coordinates, &coords));
15765f80ce2aSJacob Faibussowitsch   CHKERRQ(DMSetCoordinatesLocal(*dm, coordinates));
15775f80ce2aSJacob Faibussowitsch   CHKERRQ(VecDestroy(&coordinates));
1578552f7358SJed Brown 
1579552f7358SJed Brown   /* Create side set label */
1580dd400576SPatrick Sanan   if (rank == 0 && interpolate && (num_fs > 0)) {
1581552f7358SJed Brown     int fs, f, voff;
1582552f7358SJed Brown     /* Read from ex_get_side_set_ids() */
1583552f7358SJed Brown     int *fs_id;
1584552f7358SJed Brown     /* Read from ex_get_side_set_param() */
1585f958083aSBlaise Bourdin     int num_side_in_set;
1586552f7358SJed Brown     /* Read from ex_get_side_set_node_list() */
1587552f7358SJed Brown     int *fs_vertex_count_list, *fs_vertex_list;
1588ef073283Smichael_afanasiev     /* Read side set labels */
1589ef073283Smichael_afanasiev     char fs_name[MAX_STR_LENGTH+1];
1590552f7358SJed Brown 
1591552f7358SJed Brown     /* Get side set ids */
15925f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscMalloc1(num_fs, &fs_id));
1593a74df02fSJacob Faibussowitsch     PetscStackCallStandard(ex_get_ids,exoid, EX_SIDE_SET, fs_id);
1594552f7358SJed Brown     for (fs = 0; fs < num_fs; ++fs) {
1595a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_get_set_param,exoid, EX_SIDE_SET, fs_id[fs], &num_side_in_set, NULL);
15965f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscMalloc2(num_side_in_set,&fs_vertex_count_list,num_side_in_set*4,&fs_vertex_list));
1597a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_get_side_set_node_list,exoid, fs_id[fs], fs_vertex_count_list, fs_vertex_list);
1598ef073283Smichael_afanasiev       /* Get the specific name associated with this side set ID. */
1599ef073283Smichael_afanasiev       int fs_name_err = ex_get_name(exoid, EX_SIDE_SET, fs_id[fs], fs_name);
1600552f7358SJed Brown       for (f = 0, voff = 0; f < num_side_in_set; ++f) {
16010298fd71SBarry Smith         const PetscInt *faces   = NULL;
1602552f7358SJed Brown         PetscInt       faceSize = fs_vertex_count_list[f], numFaces;
1603552f7358SJed Brown         PetscInt       faceVertices[4], v;
1604552f7358SJed Brown 
16052c71b3e2SJacob Faibussowitsch         PetscCheckFalse(faceSize > 4,comm, PETSC_ERR_ARG_WRONG, "ExodusII side cannot have %d > 4 vertices", faceSize);
1606552f7358SJed Brown         for (v = 0; v < faceSize; ++v, ++voff) {
1607552f7358SJed Brown           faceVertices[v] = fs_vertex_list[voff]+numCells-1;
1608552f7358SJed Brown         }
16095f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexGetFullJoin(*dm, faceSize, faceVertices, &numFaces, &faces));
16102c71b3e2SJacob Faibussowitsch         PetscCheckFalse(numFaces != 1,comm, PETSC_ERR_ARG_WRONG, "Invalid ExodusII side %d in set %d maps to %d faces", f, fs, numFaces);
16115f80ce2aSJacob Faibussowitsch         CHKERRQ(DMSetLabelValue_Fast(*dm, &faceSets, "Face Sets", faces[0], fs_id[fs]));
1612ef073283Smichael_afanasiev         /* Only add the label if one has been detected for this side set. */
1613ef073283Smichael_afanasiev         if (!fs_name_err) {
16145f80ce2aSJacob Faibussowitsch           CHKERRQ(DMSetLabelValue(*dm, fs_name, faces[0], fs_id[fs]));
1615ef073283Smichael_afanasiev         }
16165f80ce2aSJacob Faibussowitsch         CHKERRQ(DMPlexRestoreJoin(*dm, faceSize, faceVertices, &numFaces, &faces));
1617552f7358SJed Brown       }
16185f80ce2aSJacob Faibussowitsch       CHKERRQ(PetscFree2(fs_vertex_count_list,fs_vertex_list));
1619552f7358SJed Brown     }
16205f80ce2aSJacob Faibussowitsch     CHKERRQ(PetscFree(fs_id));
1621552f7358SJed Brown   }
1622ae9eebabSLisandro Dalcin 
1623ae9eebabSLisandro Dalcin   { /* Create Cell/Face/Vertex Sets labels at all processes */
1624ae9eebabSLisandro Dalcin     enum {n = 3};
1625ae9eebabSLisandro Dalcin     PetscBool flag[n];
1626ae9eebabSLisandro Dalcin 
1627ae9eebabSLisandro Dalcin     flag[0] = cellSets ? PETSC_TRUE : PETSC_FALSE;
1628ae9eebabSLisandro Dalcin     flag[1] = faceSets ? PETSC_TRUE : PETSC_FALSE;
1629ae9eebabSLisandro Dalcin     flag[2] = vertSets ? PETSC_TRUE : PETSC_FALSE;
16305f80ce2aSJacob Faibussowitsch     CHKERRMPI(MPI_Bcast(flag, n, MPIU_BOOL, 0, comm));
16315f80ce2aSJacob Faibussowitsch     if (flag[0]) CHKERRQ(DMCreateLabel(*dm, "Cell Sets"));
16325f80ce2aSJacob Faibussowitsch     if (flag[1]) CHKERRQ(DMCreateLabel(*dm, "Face Sets"));
16335f80ce2aSJacob Faibussowitsch     if (flag[2]) CHKERRQ(DMCreateLabel(*dm, "Vertex Sets"));
1634ae9eebabSLisandro Dalcin   }
1635b458e8f1SJose E. Roman   PetscFunctionReturn(0);
1636552f7358SJed Brown #else
1637552f7358SJed Brown   SETERRQ(comm, PETSC_ERR_SUP, "This method requires ExodusII support. Reconfigure using --download-exodusii");
1638552f7358SJed Brown #endif
1639552f7358SJed Brown }
1640