xref: /petsc/src/dm/impls/plex/plexexodusii.c (revision c2e3fba1fe1cda7e6350bbca19c4ed35ce95940a)
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 
30db781477SPatrick Sanan .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;
509566063dSJacob Faibussowitsch   if (exo->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename:    %s\n", exo->filename));
519566063dSJacob Faibussowitsch   if (exo->exoid)    PetscCall(PetscViewerASCIIPrintf(viewer, "exoid:       %d\n", exo->exoid));
529566063dSJacob Faibussowitsch   if (exo->btype)    PetscCall(PetscViewerASCIIPrintf(viewer, "IO Mode:     %d\n", exo->btype));
539566063dSJacob Faibussowitsch   if (exo->order)    PetscCall(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;
60d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "ExodusII PetscViewer Options");
61d0609cedSBarry Smith   PetscOptionsHeadEnd();
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);}
779566063dSJacob Faibussowitsch   PetscCall(PetscFree(exo->filename));
789566063dSJacob Faibussowitsch   PetscCall(PetscFree(exo));
799566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetName_C",NULL));
809566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileGetName_C",NULL));
819566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetMode_C",NULL));
829566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerGetId_C",NULL));
839566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerGetOrder_C",NULL));
849566063dSJacob Faibussowitsch   PetscCall(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 
969566063dSJacob Faibussowitsch   PetscCallMPI(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   }
1059566063dSJacob Faibussowitsch   if (exo->filename) PetscCall(PetscFree(exo->filename));
1069566063dSJacob Faibussowitsch   PetscCall(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);
13008401ef6SPierre Jolivet   PetscCheck(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 
191db781477SPatrick Sanan .seealso: `PetscViewerExodusIIOpen()`, `PetscViewerCreate()`, `PETSCVIEWERBINARY`, `PETSCVIEWERHDF5`, `DMView()`,
192db781477SPatrick Sanan           `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;
2029566063dSJacob Faibussowitsch   PetscCall(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 
2149566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",PetscViewerFileSetName_ExodusII));
2159566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",PetscViewerFileGetName_ExodusII));
2169566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_ExodusII));
2179566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetMode_C",PetscViewerFileGetMode_ExodusII));
2189566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerGetId_C",PetscViewerExodusIIGetId_ExodusII));
2199566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)v,"PetscViewerSetOrder_C",PetscViewerExodusIISetOrder_ExodusII));
2209566063dSJacob Faibussowitsch   PetscCall(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 
245*c2e3fba1SPatrick Sanan .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) {
2679566063dSJacob Faibussowitsch       PetscCall(PetscStrncpy(ext_name, name, MAX_STR_LENGTH));
2689566063dSJacob Faibussowitsch       PetscCall(PetscStrlcat(ext_name, suffix[j], MAX_STR_LENGTH));
2699566063dSJacob Faibussowitsch       PetscCall(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};
3366823f3c5SBlaise Bourdin   int             CPU_word_size, IO_word_size, EXO_mode;
3376823f3c5SBlaise Bourdin   float           EXO_version;
3386823f3c5SBlaise Bourdin 
3396823f3c5SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *) viewer->data;
3406823f3c5SBlaise Bourdin 
34178569bb4SMatthew G. Knepley   PetscFunctionBegin;
3429566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
3439566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
3449566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
3456823f3c5SBlaise Bourdin 
3466823f3c5SBlaise Bourdin   /*
3476823f3c5SBlaise Bourdin     Creating coordSection is a collective operation so we do it somewhat out of sequence
3486823f3c5SBlaise Bourdin   */
3499566063dSJacob Faibussowitsch   PetscCall(PetscSectionCreate(comm, &coordSection));
3509566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinatesLocalSetUp(dm));
3516823f3c5SBlaise Bourdin   if (!rank) {
3526823f3c5SBlaise Bourdin     switch (exo->btype) {
3536823f3c5SBlaise Bourdin     case FILE_MODE_READ:
3546823f3c5SBlaise Bourdin     case FILE_MODE_APPEND:
3556823f3c5SBlaise Bourdin     case FILE_MODE_UPDATE:
3566823f3c5SBlaise Bourdin     case FILE_MODE_APPEND_UPDATE:
3576823f3c5SBlaise Bourdin       /* exodusII does not allow writing geometry to an existing file */
35898921bdaSJacob Faibussowitsch       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "cannot add geometry to existing file %s", exo->filename);
3596823f3c5SBlaise Bourdin     case FILE_MODE_WRITE:
3606823f3c5SBlaise Bourdin       /* Create an empty file if one already exists*/
3616823f3c5SBlaise Bourdin       EXO_mode = EX_CLOBBER;
3626823f3c5SBlaise Bourdin #if defined(PETSC_USE_64BIT_INDICES)
3636823f3c5SBlaise Bourdin       EXO_mode += EX_ALL_INT64_API;
3646823f3c5SBlaise Bourdin #endif
3656823f3c5SBlaise Bourdin         CPU_word_size = sizeof(PetscReal);
3666823f3c5SBlaise Bourdin         IO_word_size  = sizeof(PetscReal);
3676823f3c5SBlaise Bourdin         exo->exoid = ex_create(exo->filename, EXO_mode, &CPU_word_size, &IO_word_size);
36808401ef6SPierre Jolivet         PetscCheck(exo->exoid >= 0,PETSC_COMM_SELF, PETSC_ERR_LIB, "ex_create failed for %s", exo->filename);
3696823f3c5SBlaise Bourdin 
3706823f3c5SBlaise Bourdin       break;
3716823f3c5SBlaise Bourdin     default:
3726823f3c5SBlaise Bourdin       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
3736823f3c5SBlaise Bourdin     }
3746823f3c5SBlaise Bourdin 
37578569bb4SMatthew G. Knepley     /* --- Get DM info --- */
3769566063dSJacob Faibussowitsch     PetscCall(PetscObjectGetName((PetscObject) dm, &dmName));
3779566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepth(dm, &depth));
3789566063dSJacob Faibussowitsch     PetscCall(DMGetDimension(dm, &dim));
3799566063dSJacob Faibussowitsch     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
3809566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
3819566063dSJacob Faibussowitsch     PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd));
3829566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd));
3839566063dSJacob Faibussowitsch     PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
38478569bb4SMatthew G. Knepley     numCells    = cEnd - cStart;
38578569bb4SMatthew G. Knepley     numEdges    = eEnd - eStart;
38678569bb4SMatthew G. Knepley     numVertices = vEnd - vStart;
38778569bb4SMatthew G. Knepley     if (depth == 3) {numFaces = fEnd - fStart;}
38878569bb4SMatthew G. Knepley     else            {numFaces = 0;}
3899566063dSJacob Faibussowitsch     PetscCall(DMGetLabelSize(dm, "Cell Sets", &num_cs));
3909566063dSJacob Faibussowitsch     PetscCall(DMGetLabelSize(dm, "Vertex Sets", &num_vs));
3919566063dSJacob Faibussowitsch     PetscCall(DMGetLabelSize(dm, "Face Sets", &num_fs));
3929566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinatesLocal(dm, &coord));
3939566063dSJacob Faibussowitsch     PetscCall(DMGetCoordinateDM(dm, &cdm));
39478569bb4SMatthew G. Knepley     if (num_cs > 0) {
3959566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, "Cell Sets", &csLabel));
3969566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValueIS(csLabel, &csIS));
3979566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(csIS, &csIdx));
39878569bb4SMatthew G. Knepley     }
3999566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(num_cs, &nodes));
40078569bb4SMatthew G. Knepley     /* Set element type for each block and compute total number of nodes */
4019566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(num_cs, &type));
40278569bb4SMatthew G. Knepley     numNodes = numVertices;
4036823f3c5SBlaise Bourdin 
4049566063dSJacob Faibussowitsch     PetscCall(PetscViewerExodusIIGetOrder(viewer, &degree));
40578569bb4SMatthew G. Knepley     if (degree == 2) {numNodes += numEdges;}
40678569bb4SMatthew G. Knepley     cellsNotInConnectivity = numCells;
40778569bb4SMatthew G. Knepley     for (cs = 0; cs < num_cs; ++cs) {
40878569bb4SMatthew G. Knepley       IS              stratumIS;
40978569bb4SMatthew G. Knepley       const PetscInt *cells;
41078569bb4SMatthew G. Knepley       PetscScalar    *xyz = NULL;
41178569bb4SMatthew G. Knepley       PetscInt        csSize, closureSize;
41278569bb4SMatthew G. Knepley 
4139566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(csLabel, csIdx[cs], &stratumIS));
4149566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(stratumIS, &cells));
4159566063dSJacob Faibussowitsch       PetscCall(ISGetSize(stratumIS, &csSize));
4169566063dSJacob Faibussowitsch       PetscCall(DMPlexVecGetClosure(cdm, NULL, coord, cells[0], &closureSize, &xyz));
41778569bb4SMatthew G. Knepley       switch (dim) {
41878569bb4SMatthew G. Knepley         case 2:
41978569bb4SMatthew G. Knepley           if      (closureSize == 3*dim) {type[cs] = TRI;}
42078569bb4SMatthew G. Knepley           else if (closureSize == 4*dim) {type[cs] = QUAD;}
42163a3b9bcSJacob Faibussowitsch           else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices %" PetscInt_FMT " in dimension %" PetscInt_FMT " has no ExodusII type", closureSize/dim, dim);
42278569bb4SMatthew G. Knepley           break;
42378569bb4SMatthew G. Knepley         case 3:
42478569bb4SMatthew G. Knepley           if      (closureSize == 4*dim) {type[cs] = TET;}
42578569bb4SMatthew G. Knepley           else if (closureSize == 8*dim) {type[cs] = HEX;}
42663a3b9bcSJacob Faibussowitsch           else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices %" PetscInt_FMT " in dimension %" PetscInt_FMT " has no ExodusII type", closureSize/dim, dim);
42778569bb4SMatthew G. Knepley           break;
42863a3b9bcSJacob Faibussowitsch         default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %" PetscInt_FMT " not handled by ExodusII viewer", dim);
42978569bb4SMatthew G. Knepley       }
43078569bb4SMatthew G. Knepley       if ((degree == 2) && (type[cs] == QUAD)) {numNodes += csSize;}
43178569bb4SMatthew G. Knepley       if ((degree == 2) && (type[cs] == HEX))  {numNodes += csSize; numNodes += numFaces;}
4329566063dSJacob Faibussowitsch       PetscCall(DMPlexVecRestoreClosure(cdm, NULL, coord, cells[0], &closureSize, &xyz));
43378569bb4SMatthew G. Knepley       /* Set nodes and Element type */
43478569bb4SMatthew G. Knepley       if (type[cs] == TRI) {
43578569bb4SMatthew G. Knepley         if      (degree == 1) nodes[cs] = nodesTriP1;
43678569bb4SMatthew G. Knepley         else if (degree == 2) nodes[cs] = nodesTriP2;
43778569bb4SMatthew G. Knepley       } else if (type[cs] == QUAD) {
43878569bb4SMatthew G. Knepley         if      (degree == 1) nodes[cs] = nodesQuadP1;
43978569bb4SMatthew G. Knepley         else if (degree == 2) nodes[cs] = nodesQuadP2;
44078569bb4SMatthew G. Knepley       } else if (type[cs] == TET) {
44178569bb4SMatthew G. Knepley         if      (degree == 1) nodes[cs] = nodesTetP1;
44278569bb4SMatthew G. Knepley         else if (degree == 2) nodes[cs] = nodesTetP2;
44378569bb4SMatthew G. Knepley       } else if (type[cs] == HEX) {
44478569bb4SMatthew G. Knepley         if      (degree == 1) nodes[cs] = nodesHexP1;
44578569bb4SMatthew G. Knepley         else if (degree == 2) nodes[cs] = nodesHexP2;
44678569bb4SMatthew G. Knepley       }
44778569bb4SMatthew G. Knepley       /* Compute the number of cells not in the connectivity table */
44878569bb4SMatthew G. Knepley       cellsNotInConnectivity -= nodes[cs][3]*csSize;
44978569bb4SMatthew G. Knepley 
4509566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(stratumIS, &cells));
4519566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&stratumIS));
45278569bb4SMatthew G. Knepley     }
453a74df02fSJacob Faibussowitsch     if (num_cs > 0) {PetscStackCallStandard(ex_put_init,exo->exoid, dmName, dim, numNodes, numCells, num_cs, num_vs, num_fs);}
45478569bb4SMatthew G. Knepley     /* --- Connectivity --- */
45578569bb4SMatthew G. Knepley     for (cs = 0; cs < num_cs; ++cs) {
45678569bb4SMatthew G. Knepley       IS              stratumIS;
45778569bb4SMatthew G. Knepley       const PetscInt *cells;
458fe209ef9SBlaise Bourdin       PetscInt       *connect, off = 0;
459eae8a387SMatthew G. Knepley       PetscInt        edgesInClosure = 0, facesInClosure = 0, verticesInClosure = 0;
46078569bb4SMatthew G. Knepley       PetscInt        csSize, c, connectSize, closureSize;
46178569bb4SMatthew G. Knepley       char           *elem_type = NULL;
46278569bb4SMatthew G. Knepley       char            elem_type_tri3[]  = "TRI3",  elem_type_quad4[] = "QUAD4";
46378569bb4SMatthew G. Knepley       char            elem_type_tri6[]  = "TRI6",  elem_type_quad9[] = "QUAD9";
46478569bb4SMatthew G. Knepley       char            elem_type_tet4[]  = "TET4",  elem_type_hex8[]  = "HEX8";
46578569bb4SMatthew G. Knepley       char            elem_type_tet10[] = "TET10", elem_type_hex27[] = "HEX27";
46678569bb4SMatthew G. Knepley 
4679566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(csLabel, csIdx[cs], &stratumIS));
4689566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(stratumIS, &cells));
4699566063dSJacob Faibussowitsch       PetscCall(ISGetSize(stratumIS, &csSize));
47078569bb4SMatthew G. Knepley       /* Set Element type */
47178569bb4SMatthew G. Knepley       if (type[cs] == TRI) {
47278569bb4SMatthew G. Knepley         if      (degree == 1) elem_type = elem_type_tri3;
47378569bb4SMatthew G. Knepley         else if (degree == 2) elem_type = elem_type_tri6;
47478569bb4SMatthew G. Knepley       } else if (type[cs] == QUAD) {
47578569bb4SMatthew G. Knepley         if      (degree == 1) elem_type = elem_type_quad4;
47678569bb4SMatthew G. Knepley         else if (degree == 2) elem_type = elem_type_quad9;
47778569bb4SMatthew G. Knepley       } else if (type[cs] == TET) {
47878569bb4SMatthew G. Knepley         if      (degree == 1) elem_type = elem_type_tet4;
47978569bb4SMatthew G. Knepley         else if (degree == 2) elem_type = elem_type_tet10;
48078569bb4SMatthew G. Knepley       } else if (type[cs] == HEX) {
48178569bb4SMatthew G. Knepley         if      (degree == 1) elem_type = elem_type_hex8;
48278569bb4SMatthew G. Knepley         else if (degree == 2) elem_type = elem_type_hex27;
48378569bb4SMatthew G. Knepley       }
48478569bb4SMatthew G. Knepley       connectSize = nodes[cs][0] + nodes[cs][1] + nodes[cs][2] + nodes[cs][3];
4859566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(PetscMax(27,connectSize)*csSize, &connect));
486a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_put_block,exo->exoid, EX_ELEM_BLOCK, csIdx[cs], elem_type, csSize, connectSize, 0, 0, 1);
48778569bb4SMatthew G. Knepley       /* Find number of vertices, edges, and faces in the closure */
48878569bb4SMatthew G. Knepley       verticesInClosure = nodes[cs][0];
48978569bb4SMatthew G. Knepley       if (depth > 1) {
49078569bb4SMatthew G. Knepley         if (dim == 2) {
4919566063dSJacob Faibussowitsch           PetscCall(DMPlexGetConeSize(dm, cells[0], &edgesInClosure));
49278569bb4SMatthew G. Knepley         } else if (dim == 3) {
49378569bb4SMatthew G. Knepley           PetscInt *closure = NULL;
49478569bb4SMatthew G. Knepley 
4959566063dSJacob Faibussowitsch           PetscCall(DMPlexGetConeSize(dm, cells[0], &facesInClosure));
4969566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, cells[0], PETSC_TRUE, &closureSize, &closure));
49778569bb4SMatthew G. Knepley           edgesInClosure = closureSize - facesInClosure - 1 - verticesInClosure;
4989566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, cells[0], PETSC_TRUE, &closureSize, &closure));
49978569bb4SMatthew G. Knepley         }
50078569bb4SMatthew G. Knepley       }
50178569bb4SMatthew G. Knepley       /* Get connectivity for each cell */
50278569bb4SMatthew G. Knepley       for (c = 0; c < csSize; ++c) {
50378569bb4SMatthew G. Knepley         PetscInt *closure = NULL;
50478569bb4SMatthew G. Knepley         PetscInt  temp, i;
50578569bb4SMatthew G. Knepley 
5069566063dSJacob Faibussowitsch         PetscCall(DMPlexGetTransitiveClosure(dm, cells[c], PETSC_TRUE, &closureSize, &closure));
50778569bb4SMatthew G. Knepley         for (i = 0; i < connectSize; ++i) {
50878569bb4SMatthew G. Knepley           if (i < nodes[cs][0]) {/* Vertices */
509fe209ef9SBlaise Bourdin             connect[i+off] = closure[(i+edgesInClosure+facesInClosure+1)*2] + 1;
510fe209ef9SBlaise Bourdin             connect[i+off] -= cellsNotInConnectivity;
51178569bb4SMatthew G. Knepley           } else if (i < nodes[cs][0]+nodes[cs][1]) { /* Edges */
512fe209ef9SBlaise Bourdin             connect[i+off] = closure[(i-verticesInClosure+facesInClosure+1)*2] + 1;
513fe209ef9SBlaise Bourdin             if (nodes[cs][2] == 0) connect[i+off] -= numFaces;
514fe209ef9SBlaise Bourdin             connect[i+off] -= cellsNotInConnectivity;
51578569bb4SMatthew G. Knepley           } else if (i < nodes[cs][0]+nodes[cs][1]+nodes[cs][3]) { /* Cells */
516fe209ef9SBlaise Bourdin             connect[i+off] = closure[0] + 1;
517fe209ef9SBlaise Bourdin             connect[i+off] -= skipCells;
51878569bb4SMatthew G. Knepley           } else if (i < nodes[cs][0]+nodes[cs][1]+nodes[cs][3]+nodes[cs][2]) { /* Faces */
519fe209ef9SBlaise Bourdin             connect[i+off] = closure[(i-edgesInClosure-verticesInClosure)*2] + 1;
520fe209ef9SBlaise Bourdin             connect[i+off] -= cellsNotInConnectivity;
52178569bb4SMatthew G. Knepley           } else {
522fe209ef9SBlaise Bourdin             connect[i+off] = -1;
52378569bb4SMatthew G. Knepley           }
52478569bb4SMatthew G. Knepley         }
52578569bb4SMatthew G. Knepley         /* Tetrahedra are inverted */
52678569bb4SMatthew G. Knepley         if (type[cs] == TET) {
527fe209ef9SBlaise Bourdin           temp = connect[0+off]; connect[0+off] = connect[1+off]; connect[1+off] = temp;
52878569bb4SMatthew G. Knepley           if (degree == 2) {
529e2c9586dSBlaise Bourdin             temp = connect[5+off]; connect[5+off] = connect[6+off]; connect[6+off] = temp;
530e2c9586dSBlaise Bourdin             temp = connect[7+off]; connect[7+off] = connect[8+off]; connect[8+off] = temp;
53178569bb4SMatthew G. Knepley           }
53278569bb4SMatthew G. Knepley         }
53378569bb4SMatthew G. Knepley         /* Hexahedra are inverted */
53478569bb4SMatthew G. Knepley         if (type[cs] == HEX) {
535fe209ef9SBlaise Bourdin           temp = connect[1+off]; connect[1+off] = connect[3+off]; connect[3+off] = temp;
53678569bb4SMatthew G. Knepley           if (degree == 2) {
537fe209ef9SBlaise Bourdin             temp = connect[8+off];  connect[8+off]  = connect[11+off]; connect[11+off] = temp;
538fe209ef9SBlaise Bourdin             temp = connect[9+off];  connect[9+off]  = connect[10+off]; connect[10+off] = temp;
539fe209ef9SBlaise Bourdin             temp = connect[16+off]; connect[16+off] = connect[17+off]; connect[17+off] = temp;
540fe209ef9SBlaise Bourdin             temp = connect[18+off]; connect[18+off] = connect[19+off]; connect[19+off] = temp;
54178569bb4SMatthew G. Knepley 
542fe209ef9SBlaise Bourdin             temp = connect[12+off]; connect[12+off] = connect[16+off]; connect[16+off] = temp;
543fe209ef9SBlaise Bourdin             temp = connect[13+off]; connect[13+off] = connect[17+off]; connect[17+off] = temp;
544fe209ef9SBlaise Bourdin             temp = connect[14+off]; connect[14+off] = connect[18+off]; connect[18+off] = temp;
545fe209ef9SBlaise Bourdin             temp = connect[15+off]; connect[15+off] = connect[19+off]; connect[19+off] = temp;
54678569bb4SMatthew G. Knepley 
547fe209ef9SBlaise Bourdin             temp = connect[23+off]; connect[23+off] = connect[26+off]; connect[26+off] = temp;
548fe209ef9SBlaise Bourdin             temp = connect[24+off]; connect[24+off] = connect[25+off]; connect[25+off] = temp;
549fe209ef9SBlaise Bourdin             temp = connect[25+off]; connect[25+off] = connect[26+off]; connect[26+off] = temp;
55078569bb4SMatthew G. Knepley           }
55178569bb4SMatthew G. Knepley         }
552fe209ef9SBlaise Bourdin         off += connectSize;
5539566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreTransitiveClosure(dm, cells[c], PETSC_TRUE, &closureSize, &closure));
55478569bb4SMatthew G. Knepley       }
555a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_put_conn,exo->exoid, EX_ELEM_BLOCK, csIdx[cs], connect, 0, 0);
55678569bb4SMatthew G. Knepley       skipCells += (nodes[cs][3] == 0)*csSize;
5579566063dSJacob Faibussowitsch       PetscCall(PetscFree(connect));
5589566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(stratumIS, &cells));
5599566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&stratumIS));
56078569bb4SMatthew G. Knepley     }
5619566063dSJacob Faibussowitsch     PetscCall(PetscFree(type));
56278569bb4SMatthew G. Knepley     /* --- Coordinates --- */
5639566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetChart(coordSection, pStart, pEnd));
5641e50132fSMatthew G. Knepley     if (num_cs) {
56578569bb4SMatthew G. Knepley       for (d = 0; d < depth; ++d) {
5669566063dSJacob Faibussowitsch         PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
56778569bb4SMatthew G. Knepley         for (p = pStart; p < pEnd; ++p) {
5689566063dSJacob Faibussowitsch           PetscCall(PetscSectionSetDof(coordSection, p, nodes[0][d] > 0));
56978569bb4SMatthew G. Knepley         }
57078569bb4SMatthew G. Knepley       }
5711e50132fSMatthew G. Knepley     }
57278569bb4SMatthew G. Knepley     for (cs = 0; cs < num_cs; ++cs) {
57378569bb4SMatthew G. Knepley       IS              stratumIS;
57478569bb4SMatthew G. Knepley       const PetscInt *cells;
57578569bb4SMatthew G. Knepley       PetscInt        csSize, c;
57678569bb4SMatthew G. Knepley 
5779566063dSJacob Faibussowitsch       PetscCall(DMLabelGetStratumIS(csLabel, csIdx[cs], &stratumIS));
5789566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(stratumIS, &cells));
5799566063dSJacob Faibussowitsch       PetscCall(ISGetSize(stratumIS, &csSize));
58078569bb4SMatthew G. Knepley       for (c = 0; c < csSize; ++c) {
5819566063dSJacob Faibussowitsch         PetscCall(PetscSectionSetDof(coordSection, cells[c], nodes[cs][3] > 0));
58278569bb4SMatthew G. Knepley       }
5839566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(stratumIS, &cells));
5849566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&stratumIS));
58578569bb4SMatthew G. Knepley     }
58678569bb4SMatthew G. Knepley     if (num_cs > 0) {
5879566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(csIS, &csIdx));
5889566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&csIS));
58978569bb4SMatthew G. Knepley     }
5909566063dSJacob Faibussowitsch     PetscCall(PetscFree(nodes));
5919566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetUp(coordSection));
59278569bb4SMatthew G. Knepley     if (numNodes > 0) {
59378569bb4SMatthew G. Knepley       const char  *coordNames[3] = {"x", "y", "z"};
594233c95e0SFrancesco Ballarin       PetscScalar *closure, *cval;
595233c95e0SFrancesco Ballarin       PetscReal   *coords;
59678569bb4SMatthew G. Knepley       PetscInt     hasDof, n = 0;
59778569bb4SMatthew G. Knepley 
5986823f3c5SBlaise Bourdin       /* There can't be more than 24 values in the closure of a point for the coord coordSection */
5999566063dSJacob Faibussowitsch       PetscCall(PetscCalloc3(numNodes*3, &coords, dim, &cval, 24, &closure));
6009566063dSJacob Faibussowitsch       PetscCall(DMGetCoordinatesLocalNoncollective(dm, &coord));
6019566063dSJacob Faibussowitsch       PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
60278569bb4SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
6039566063dSJacob Faibussowitsch         PetscCall(PetscSectionGetDof(coordSection, p, &hasDof));
60478569bb4SMatthew G. Knepley         if (hasDof) {
60578569bb4SMatthew G. Knepley           PetscInt closureSize = 24, j;
60678569bb4SMatthew G. Knepley 
6079566063dSJacob Faibussowitsch           PetscCall(DMPlexVecGetClosure(cdm, NULL, coord, p, &closureSize, &closure));
60878569bb4SMatthew G. Knepley           for (d = 0; d < dim; ++d) {
60978569bb4SMatthew G. Knepley             cval[d] = 0.0;
61078569bb4SMatthew G. Knepley             for (j = 0; j < closureSize/dim; j++) cval[d] += closure[j*dim+d];
611233c95e0SFrancesco Ballarin             coords[d*numNodes+n] = PetscRealPart(cval[d]) * dim / closureSize;
61278569bb4SMatthew G. Knepley           }
61378569bb4SMatthew G. Knepley           ++n;
61478569bb4SMatthew G. Knepley         }
61578569bb4SMatthew G. Knepley       }
616a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_put_coord,exo->exoid, &coords[0*numNodes], &coords[1*numNodes], &coords[2*numNodes]);
6179566063dSJacob Faibussowitsch       PetscCall(PetscFree3(coords, cval, closure));
618a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_put_coord_names,exo->exoid, (char **) coordNames);
61978569bb4SMatthew G. Knepley     }
6206823f3c5SBlaise Bourdin 
621fe209ef9SBlaise Bourdin     /* --- Node Sets/Vertex Sets --- */
622fe209ef9SBlaise Bourdin     DMHasLabel(dm, "Vertex Sets", &hasLabel);
623fe209ef9SBlaise Bourdin     if (hasLabel) {
624fe209ef9SBlaise Bourdin       PetscInt        i, vs, vsSize;
625fe209ef9SBlaise Bourdin       const PetscInt *vsIdx, *vertices;
626fe209ef9SBlaise Bourdin       PetscInt       *nodeList;
627fe209ef9SBlaise Bourdin       IS              vsIS, stratumIS;
628fe209ef9SBlaise Bourdin       DMLabel         vsLabel;
6299566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, "Vertex Sets", &vsLabel));
6309566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValueIS(vsLabel, &vsIS));
6319566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(vsIS, &vsIdx));
632fe209ef9SBlaise Bourdin       for (vs=0; vs<num_vs; ++vs) {
6339566063dSJacob Faibussowitsch         PetscCall(DMLabelGetStratumIS(vsLabel, vsIdx[vs], &stratumIS));
6349566063dSJacob Faibussowitsch         PetscCall(ISGetIndices(stratumIS, &vertices));
6359566063dSJacob Faibussowitsch         PetscCall(ISGetSize(stratumIS, &vsSize));
6369566063dSJacob Faibussowitsch         PetscCall(PetscMalloc1(vsSize, &nodeList));
637fe209ef9SBlaise Bourdin         for (i=0; i<vsSize; ++i) {
638fe209ef9SBlaise Bourdin           nodeList[i] = vertices[i] - skipCells + 1;
639fe209ef9SBlaise Bourdin         }
640a74df02fSJacob Faibussowitsch         PetscStackCallStandard(ex_put_set_param,exo->exoid, EX_NODE_SET, vsIdx[vs], vsSize, 0);
641a74df02fSJacob Faibussowitsch         PetscStackCallStandard(ex_put_set,exo->exoid, EX_NODE_SET, vsIdx[vs], nodeList, NULL);
6429566063dSJacob Faibussowitsch         PetscCall(ISRestoreIndices(stratumIS, &vertices));
6439566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&stratumIS));
6449566063dSJacob Faibussowitsch         PetscCall(PetscFree(nodeList));
645fe209ef9SBlaise Bourdin       }
6469566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(vsIS, &vsIdx));
6479566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&vsIS));
648fe209ef9SBlaise Bourdin     }
649fe209ef9SBlaise Bourdin     /* --- Side Sets/Face Sets --- */
6509566063dSJacob Faibussowitsch     PetscCall(DMHasLabel(dm, "Face Sets", &hasLabel));
651fe209ef9SBlaise Bourdin     if (hasLabel) {
652fe209ef9SBlaise Bourdin       PetscInt        i, j, fs, fsSize;
653fe209ef9SBlaise Bourdin       const PetscInt *fsIdx, *faces;
654fe209ef9SBlaise Bourdin       IS              fsIS, stratumIS;
655fe209ef9SBlaise Bourdin       DMLabel         fsLabel;
656fe209ef9SBlaise Bourdin       PetscInt        numPoints, *points;
657fe209ef9SBlaise Bourdin       PetscInt        elem_list_size = 0;
658fe209ef9SBlaise Bourdin       PetscInt       *elem_list, *elem_ind, *side_list;
659fe209ef9SBlaise Bourdin 
6609566063dSJacob Faibussowitsch       PetscCall(DMGetLabel(dm, "Face Sets", &fsLabel));
661fe209ef9SBlaise Bourdin       /* Compute size of Node List and Element List */
6629566063dSJacob Faibussowitsch       PetscCall(DMLabelGetValueIS(fsLabel, &fsIS));
6639566063dSJacob Faibussowitsch       PetscCall(ISGetIndices(fsIS, &fsIdx));
664fe209ef9SBlaise Bourdin       for (fs=0; fs<num_fs; ++fs) {
6659566063dSJacob Faibussowitsch         PetscCall(DMLabelGetStratumIS(fsLabel, fsIdx[fs], &stratumIS));
6669566063dSJacob Faibussowitsch         PetscCall(ISGetSize(stratumIS, &fsSize));
667fe209ef9SBlaise Bourdin         elem_list_size += fsSize;
6689566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&stratumIS));
669fe209ef9SBlaise Bourdin       }
670d0609cedSBarry Smith       PetscCall(PetscMalloc3(num_fs, &elem_ind,elem_list_size, &elem_list,elem_list_size, &side_list));
671fe209ef9SBlaise Bourdin       elem_ind[0] = 0;
672fe209ef9SBlaise Bourdin       for (fs=0; fs<num_fs; ++fs) {
6739566063dSJacob Faibussowitsch         PetscCall(DMLabelGetStratumIS(fsLabel, fsIdx[fs], &stratumIS));
6749566063dSJacob Faibussowitsch         PetscCall(ISGetIndices(stratumIS, &faces));
6759566063dSJacob Faibussowitsch         PetscCall(ISGetSize(stratumIS, &fsSize));
676fe209ef9SBlaise Bourdin         /* Set Parameters */
677a74df02fSJacob Faibussowitsch         PetscStackCallStandard(ex_put_set_param,exo->exoid, EX_SIDE_SET, fsIdx[fs], fsSize, 0);
678fe209ef9SBlaise Bourdin         /* Indices */
679fe209ef9SBlaise Bourdin         if (fs<num_fs-1) {
680fe209ef9SBlaise Bourdin           elem_ind[fs+1] = elem_ind[fs] + fsSize;
681fe209ef9SBlaise Bourdin         }
682fe209ef9SBlaise Bourdin 
683fe209ef9SBlaise Bourdin         for (i=0; i<fsSize; ++i) {
684fe209ef9SBlaise Bourdin           /* Element List */
685fe209ef9SBlaise Bourdin           points = NULL;
6869566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, faces[i], PETSC_FALSE, &numPoints, &points));
687fe209ef9SBlaise Bourdin           elem_list[elem_ind[fs] + i] = points[2] +1;
6889566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, faces[i], PETSC_FALSE, &numPoints, &points));
689fe209ef9SBlaise Bourdin 
690fe209ef9SBlaise Bourdin           /* Side List */
691fe209ef9SBlaise Bourdin           points = NULL;
6929566063dSJacob Faibussowitsch           PetscCall(DMPlexGetTransitiveClosure(dm, elem_list[elem_ind[fs] + i]-1, PETSC_TRUE, &numPoints, &points));
693fe209ef9SBlaise Bourdin           for (j=1; j<numPoints; ++j) {
694fe209ef9SBlaise Bourdin             if (points[j*2]==faces[i]) {break;}
695fe209ef9SBlaise Bourdin           }
696fe209ef9SBlaise Bourdin           /* Convert HEX sides */
697fe209ef9SBlaise Bourdin           if (numPoints == 27) {
698fe209ef9SBlaise Bourdin             if      (j == 1) {j = 5;}
699fe209ef9SBlaise Bourdin             else if (j == 2) {j = 6;}
700fe209ef9SBlaise Bourdin             else if (j == 3) {j = 1;}
701fe209ef9SBlaise Bourdin             else if (j == 4) {j = 3;}
702fe209ef9SBlaise Bourdin             else if (j == 5) {j = 2;}
703fe209ef9SBlaise Bourdin             else if (j == 6) {j = 4;}
704fe209ef9SBlaise Bourdin           }
705fe209ef9SBlaise Bourdin           /* Convert TET sides */
706fe209ef9SBlaise Bourdin           if (numPoints == 15) {
707fe209ef9SBlaise Bourdin             --j;
708fe209ef9SBlaise Bourdin             if (j == 0) {j = 4;}
709fe209ef9SBlaise Bourdin           }
710fe209ef9SBlaise Bourdin           side_list[elem_ind[fs] + i] = j;
7119566063dSJacob Faibussowitsch           PetscCall(DMPlexRestoreTransitiveClosure(dm, elem_list[elem_ind[fs] + i]-1, PETSC_TRUE, &numPoints, &points));
712fe209ef9SBlaise Bourdin 
713fe209ef9SBlaise Bourdin         }
7149566063dSJacob Faibussowitsch         PetscCall(ISRestoreIndices(stratumIS, &faces));
7159566063dSJacob Faibussowitsch         PetscCall(ISDestroy(&stratumIS));
716fe209ef9SBlaise Bourdin       }
7179566063dSJacob Faibussowitsch       PetscCall(ISRestoreIndices(fsIS, &fsIdx));
7189566063dSJacob Faibussowitsch       PetscCall(ISDestroy(&fsIS));
719fe209ef9SBlaise Bourdin 
720fe209ef9SBlaise Bourdin       /* Put side sets */
721fe209ef9SBlaise Bourdin       for (fs=0; fs<num_fs; ++fs) {
722a74df02fSJacob Faibussowitsch         PetscStackCallStandard(ex_put_set,exo->exoid, EX_SIDE_SET, fsIdx[fs], &elem_list[elem_ind[fs]], &side_list[elem_ind[fs]]);
723fe209ef9SBlaise Bourdin       }
7249566063dSJacob Faibussowitsch       PetscCall(PetscFree3(elem_ind,elem_list,side_list));
725fe209ef9SBlaise Bourdin     }
7266823f3c5SBlaise Bourdin     /*
7276823f3c5SBlaise Bourdin       close the exodus file
7286823f3c5SBlaise Bourdin     */
7296823f3c5SBlaise Bourdin     ex_close(exo->exoid);
7306823f3c5SBlaise Bourdin     exo->exoid = -1;
7316823f3c5SBlaise Bourdin   }
7329566063dSJacob Faibussowitsch   PetscCall(PetscSectionDestroy(&coordSection));
7336823f3c5SBlaise Bourdin 
7346823f3c5SBlaise Bourdin   /*
7356823f3c5SBlaise Bourdin     reopen the file in parallel
7366823f3c5SBlaise Bourdin   */
7376823f3c5SBlaise Bourdin   EXO_mode = EX_WRITE;
7386823f3c5SBlaise Bourdin #if defined(PETSC_USE_64BIT_INDICES)
7396823f3c5SBlaise Bourdin   EXO_mode += EX_ALL_INT64_API;
7406823f3c5SBlaise Bourdin #endif
7416823f3c5SBlaise Bourdin   CPU_word_size = sizeof(PetscReal);
7426823f3c5SBlaise Bourdin   IO_word_size  = sizeof(PetscReal);
7436823f3c5SBlaise Bourdin   exo->exoid = ex_open_par(exo->filename,EXO_mode,&CPU_word_size,&IO_word_size,&EXO_version,comm,MPI_INFO_NULL);
74408401ef6SPierre Jolivet   PetscCheck(exo->exoid >= 0,PETSC_COMM_SELF, PETSC_ERR_LIB, "ex_open_par failed for %s", exo->filename);
7456823f3c5SBlaise Bourdin   PetscFunctionReturn(0);
7466823f3c5SBlaise Bourdin }
7476823f3c5SBlaise Bourdin 
7486823f3c5SBlaise Bourdin /*
7496823f3c5SBlaise Bourdin   VecView_PlexExodusII_Internal - Write a Vec corresponding in an exodus file
7506823f3c5SBlaise Bourdin 
7516823f3c5SBlaise Bourdin   Collective on v
7526823f3c5SBlaise Bourdin 
7536823f3c5SBlaise Bourdin   Input Parameters:
7546823f3c5SBlaise Bourdin + v  - The vector to be written
7556823f3c5SBlaise Bourdin - viewer - The PetscViewerExodusII viewer associate to an exodus file
7566823f3c5SBlaise Bourdin 
7576823f3c5SBlaise Bourdin   Notes:
7586823f3c5SBlaise Bourdin   The exodus result variable index is obtained by comparing the Vec name and the
7596823f3c5SBlaise Bourdin   names of variables declared in the exodus file. For instance for a Vec named "V"
7606823f3c5SBlaise Bourdin   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
7616823f3c5SBlaise Bourdin   amongst all variables.
7626823f3c5SBlaise Bourdin   In the event where a nodal and zonal variable both match, the function will return an error instead of
7636823f3c5SBlaise Bourdin   possibly corrupting the file
7646823f3c5SBlaise Bourdin 
7656823f3c5SBlaise Bourdin   Level: beginner
7666823f3c5SBlaise Bourdin 
767*c2e3fba1SPatrick Sanan .seealso: `EXOGetVarIndex_Internal()`, `DMPlexView_ExodusII()`, `VecView_PlexExodusII()`
7686823f3c5SBlaise Bourdin @*/
7696823f3c5SBlaise Bourdin PetscErrorCode VecView_PlexExodusII_Internal(Vec v, PetscViewer viewer)
7706823f3c5SBlaise Bourdin {
7716823f3c5SBlaise Bourdin   DM                 dm;
7726823f3c5SBlaise Bourdin   MPI_Comm           comm;
7736823f3c5SBlaise Bourdin   PetscMPIInt        rank;
7746823f3c5SBlaise Bourdin 
7756823f3c5SBlaise Bourdin   int                exoid,offsetN = 0, offsetZ = 0;
7766823f3c5SBlaise Bourdin   const char        *vecname;
7776823f3c5SBlaise Bourdin   PetscInt           step;
7786823f3c5SBlaise Bourdin 
7796823f3c5SBlaise Bourdin   PetscFunctionBegin;
7809566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject) v, &comm));
7819566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7829566063dSJacob Faibussowitsch   PetscCall(PetscViewerExodusIIGetId(viewer,&exoid));
7839566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
7849566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject) v, &vecname));
7856823f3c5SBlaise Bourdin 
7869566063dSJacob Faibussowitsch   PetscCall(DMGetOutputSequenceNumber(dm,&step,NULL));
7879566063dSJacob Faibussowitsch   PetscCall(EXOGetVarIndex_Internal(exoid,EX_NODAL,vecname,&offsetN));
7889566063dSJacob Faibussowitsch   PetscCall(EXOGetVarIndex_Internal(exoid,EX_ELEM_BLOCK,vecname,&offsetZ));
7891dca8a05SBarry Smith   PetscCheck(offsetN > 0 || offsetZ > 0,comm, PETSC_ERR_FILE_UNEXPECTED, "Found both nodal and zonal variable %s in exodus file. ", vecname);
7906823f3c5SBlaise Bourdin   if (offsetN > 0) {
7919566063dSJacob Faibussowitsch     PetscCall(VecViewPlex_ExodusII_Nodal_Internal(v,exoid,(int) step+1,offsetN));
7926823f3c5SBlaise Bourdin   } else if (offsetZ > 0) {
7939566063dSJacob Faibussowitsch     PetscCall(VecViewPlex_ExodusII_Zonal_Internal(v,exoid,(int) step+1,offsetZ));
79498921bdaSJacob Faibussowitsch   } else SETERRQ(comm, PETSC_ERR_FILE_UNEXPECTED, "Could not find nodal or zonal variable %s in exodus file. ", vecname);
7956823f3c5SBlaise Bourdin   PetscFunctionReturn(0);
7966823f3c5SBlaise Bourdin }
7976823f3c5SBlaise Bourdin 
7986823f3c5SBlaise Bourdin /*
7996823f3c5SBlaise Bourdin   VecLoad_PlexExodusII_Internal - Write a Vec corresponding in an exodus file
8006823f3c5SBlaise Bourdin 
8016823f3c5SBlaise Bourdin   Collective on v
8026823f3c5SBlaise Bourdin 
8036823f3c5SBlaise Bourdin   Input Parameters:
8046823f3c5SBlaise Bourdin + v  - The vector to be written
8056823f3c5SBlaise Bourdin - viewer - The PetscViewerExodusII viewer associate to an exodus file
8066823f3c5SBlaise Bourdin 
8076823f3c5SBlaise Bourdin   Notes:
8086823f3c5SBlaise Bourdin   The exodus result variable index is obtained by comparing the Vec name and the
8096823f3c5SBlaise Bourdin   names of variables declared in the exodus file. For instance for a Vec named "V"
8106823f3c5SBlaise Bourdin   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
8116823f3c5SBlaise Bourdin   amongst all variables.
8126823f3c5SBlaise Bourdin   In the event where a nodal and zonal variable both match, the function will return an error instead of
8136823f3c5SBlaise Bourdin   possibly corrupting the file
8146823f3c5SBlaise Bourdin 
8156823f3c5SBlaise Bourdin   Level: beginner
8166823f3c5SBlaise Bourdin 
817*c2e3fba1SPatrick Sanan .seealso: `EXOGetVarIndex_Internal()`, `DMPlexView_ExodusII()`, `VecView_PlexExodusII()`
8186823f3c5SBlaise Bourdin @*/
8196823f3c5SBlaise Bourdin PetscErrorCode VecLoad_PlexExodusII_Internal(Vec v, PetscViewer viewer)
8206823f3c5SBlaise Bourdin {
8216823f3c5SBlaise Bourdin   DM                 dm;
8226823f3c5SBlaise Bourdin   MPI_Comm           comm;
8236823f3c5SBlaise Bourdin   PetscMPIInt        rank;
8246823f3c5SBlaise Bourdin 
8256823f3c5SBlaise Bourdin   int                exoid,offsetN = 0, offsetZ = 0;
8266823f3c5SBlaise Bourdin   const char        *vecname;
8276823f3c5SBlaise Bourdin   PetscInt           step;
8286823f3c5SBlaise Bourdin 
8296823f3c5SBlaise Bourdin   PetscFunctionBegin;
8309566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject) v, &comm));
8319566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
8329566063dSJacob Faibussowitsch   PetscCall(PetscViewerExodusIIGetId(viewer,&exoid));
8339566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
8349566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetName((PetscObject) v, &vecname));
8356823f3c5SBlaise Bourdin 
8369566063dSJacob Faibussowitsch   PetscCall(DMGetOutputSequenceNumber(dm,&step,NULL));
8379566063dSJacob Faibussowitsch   PetscCall(EXOGetVarIndex_Internal(exoid,EX_NODAL,vecname,&offsetN));
8389566063dSJacob Faibussowitsch   PetscCall(EXOGetVarIndex_Internal(exoid,EX_ELEM_BLOCK,vecname,&offsetZ));
8391dca8a05SBarry Smith   PetscCheck(offsetN > 0 || offsetZ > 0,comm, PETSC_ERR_FILE_UNEXPECTED, "Found both nodal and zonal variable %s in exodus file. ", vecname);
8401dca8a05SBarry Smith   if (offsetN > 0) PetscCall(VecLoadPlex_ExodusII_Nodal_Internal(v,exoid,(int) step+1,offsetN));
8411dca8a05SBarry Smith   else if (offsetZ > 0) PetscCall(VecLoadPlex_ExodusII_Zonal_Internal(v,exoid,(int) step+1,offsetZ));
8421dca8a05SBarry Smith   else SETERRQ(comm, PETSC_ERR_FILE_UNEXPECTED, "Could not find nodal or zonal variable %s in exodus file. ", vecname);
84378569bb4SMatthew G. Knepley   PetscFunctionReturn(0);
84478569bb4SMatthew G. Knepley }
84578569bb4SMatthew G. Knepley 
84678569bb4SMatthew G. Knepley /*
84778569bb4SMatthew G. Knepley   VecViewPlex_ExodusII_Nodal_Internal - Write a Vec corresponding to a nodal field to an exodus file
84878569bb4SMatthew G. Knepley 
84978569bb4SMatthew G. Knepley   Collective on v
85078569bb4SMatthew G. Knepley 
85178569bb4SMatthew G. Knepley   Input Parameters:
85278569bb4SMatthew G. Knepley + v  - The vector to be written
85378569bb4SMatthew G. Knepley . exoid - the exodus id of a file (obtained from ex_open or ex_create for instance)
8546823f3c5SBlaise Bourdin . step - the time step to write at (exodus steps are numbered starting from 1)
8556823f3c5SBlaise Bourdin - offset - the location of the variable in the file
85678569bb4SMatthew G. Knepley 
85778569bb4SMatthew G. Knepley   Notes:
85878569bb4SMatthew G. Knepley   The exodus result nodal variable index is obtained by comparing the Vec name and the
85978569bb4SMatthew G. Knepley   names of nodal variables declared in the exodus file. For instance for a Vec named "V"
86078569bb4SMatthew G. Knepley   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
86178569bb4SMatthew G. Knepley   amongst all nodal variables.
86278569bb4SMatthew G. Knepley 
86378569bb4SMatthew G. Knepley   Level: beginner
86478569bb4SMatthew G. Knepley 
865*c2e3fba1SPatrick Sanan .seealso: `EXOGetVarIndex_Internal()`, `DMPlexView_ExodusII_Internal()`, `VecLoadNodal_PlexEXO()`, `VecViewZonal_PlexEXO()`, `VecLoadZonal_PlexEXO()`
86678569bb4SMatthew G. Knepley @*/
8676823f3c5SBlaise Bourdin PetscErrorCode VecViewPlex_ExodusII_Nodal_Internal(Vec v, int exoid, int step, int offset)
86878569bb4SMatthew G. Knepley {
86978569bb4SMatthew G. Knepley   MPI_Comm           comm;
87078569bb4SMatthew G. Knepley   PetscMPIInt        size;
87178569bb4SMatthew G. Knepley   DM                 dm;
87278569bb4SMatthew G. Knepley   Vec                vNatural, vComp;
87322a7544eSVaclav Hapla   const PetscScalar *varray;
87478569bb4SMatthew G. Knepley   PetscInt           xs, xe, bs;
87578569bb4SMatthew G. Knepley   PetscBool          useNatural;
87678569bb4SMatthew G. Knepley 
87778569bb4SMatthew G. Knepley   PetscFunctionBegin;
8789566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject) v, &comm));
8799566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
8809566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
8819566063dSJacob Faibussowitsch   PetscCall(DMGetUseNatural(dm, &useNatural));
88278569bb4SMatthew G. Knepley   useNatural = useNatural && size > 1 ? PETSC_TRUE : PETSC_FALSE;
88378569bb4SMatthew G. Knepley   if (useNatural) {
8849566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalVector(dm, &vNatural));
8859566063dSJacob Faibussowitsch     PetscCall(DMPlexGlobalToNaturalBegin(dm, v, vNatural));
8869566063dSJacob Faibussowitsch     PetscCall(DMPlexGlobalToNaturalEnd(dm, v, vNatural));
88778569bb4SMatthew G. Knepley   } else {
88878569bb4SMatthew G. Knepley     vNatural = v;
88978569bb4SMatthew G. Knepley   }
8906823f3c5SBlaise Bourdin 
89178569bb4SMatthew G. Knepley   /* Write local chunk of the result in the exodus file
89278569bb4SMatthew G. Knepley      exodus stores each component of a vector-valued field as a separate variable.
89378569bb4SMatthew G. Knepley      We assume that they are stored sequentially */
8949566063dSJacob Faibussowitsch   PetscCall(VecGetOwnershipRange(vNatural, &xs, &xe));
8959566063dSJacob Faibussowitsch   PetscCall(VecGetBlockSize(vNatural, &bs));
89678569bb4SMatthew G. Knepley   if (bs == 1) {
8979566063dSJacob Faibussowitsch     PetscCall(VecGetArrayRead(vNatural, &varray));
898a74df02fSJacob Faibussowitsch     PetscStackCallStandard(ex_put_partial_var,exoid, step, EX_NODAL, offset, 1, xs+1, xe-xs, varray);
8999566063dSJacob Faibussowitsch     PetscCall(VecRestoreArrayRead(vNatural, &varray));
90078569bb4SMatthew G. Knepley   } else {
90178569bb4SMatthew G. Knepley     IS       compIS;
90278569bb4SMatthew G. Knepley     PetscInt c;
90378569bb4SMatthew G. Knepley 
9049566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(comm, (xe-xs)/bs, xs, bs, &compIS));
90578569bb4SMatthew G. Knepley     for (c = 0; c < bs; ++c) {
9069566063dSJacob Faibussowitsch       PetscCall(ISStrideSetStride(compIS, (xe-xs)/bs, xs+c, bs));
9079566063dSJacob Faibussowitsch       PetscCall(VecGetSubVector(vNatural, compIS, &vComp));
9089566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(vComp, &varray));
909a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_put_partial_var,exoid, step, EX_NODAL, offset+c, 1, xs/bs+1, (xe-xs)/bs, varray);
9109566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(vComp, &varray));
9119566063dSJacob Faibussowitsch       PetscCall(VecRestoreSubVector(vNatural, compIS, &vComp));
91278569bb4SMatthew G. Knepley     }
9139566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&compIS));
91478569bb4SMatthew G. Knepley   }
9159566063dSJacob Faibussowitsch   if (useNatural) PetscCall(DMRestoreGlobalVector(dm, &vNatural));
91678569bb4SMatthew G. Knepley   PetscFunctionReturn(0);
91778569bb4SMatthew G. Knepley }
91878569bb4SMatthew G. Knepley 
91978569bb4SMatthew G. Knepley /*
92078569bb4SMatthew G. Knepley   VecLoadPlex_ExodusII_Nodal_Internal - Read a Vec corresponding to a nodal field from an exodus file
92178569bb4SMatthew G. Knepley 
92278569bb4SMatthew G. Knepley   Collective on v
92378569bb4SMatthew G. Knepley 
92478569bb4SMatthew G. Knepley   Input Parameters:
92578569bb4SMatthew G. Knepley + v  - The vector to be written
92678569bb4SMatthew G. Knepley . exoid - the exodus id of a file (obtained from ex_open or ex_create for instance)
9276823f3c5SBlaise Bourdin . step - the time step to read at (exodus steps are numbered starting from 1)
9286823f3c5SBlaise Bourdin - offset - the location of the variable in the file
92978569bb4SMatthew G. Knepley 
93078569bb4SMatthew G. Knepley   Notes:
93178569bb4SMatthew G. Knepley   The exodus result nodal variable index is obtained by comparing the Vec name and the
93278569bb4SMatthew G. Knepley   names of nodal variables declared in the exodus file. For instance for a Vec named "V"
93378569bb4SMatthew G. Knepley   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
93478569bb4SMatthew G. Knepley   amongst all nodal variables.
93578569bb4SMatthew G. Knepley 
93678569bb4SMatthew G. Knepley   Level: beginner
93778569bb4SMatthew G. Knepley 
938db781477SPatrick Sanan .seealso: `EXOGetVarIndex_Internal()`, `DMPlexView_ExodusII_Internal()`, `VecViewPlex_ExodusII_Nodal_Internal()`, `VecViewZonal_PlexEXO()`, `VecLoadZonal_PlexEXO()`
93978569bb4SMatthew G. Knepley */
9406823f3c5SBlaise Bourdin PetscErrorCode VecLoadPlex_ExodusII_Nodal_Internal(Vec v, int exoid, int step, int offset)
94178569bb4SMatthew G. Knepley {
94278569bb4SMatthew G. Knepley   MPI_Comm       comm;
94378569bb4SMatthew G. Knepley   PetscMPIInt    size;
94478569bb4SMatthew G. Knepley   DM             dm;
94578569bb4SMatthew G. Knepley   Vec            vNatural, vComp;
94622a7544eSVaclav Hapla   PetscScalar   *varray;
94778569bb4SMatthew G. Knepley   PetscInt       xs, xe, bs;
94878569bb4SMatthew G. Knepley   PetscBool      useNatural;
94978569bb4SMatthew G. Knepley 
95078569bb4SMatthew G. Knepley   PetscFunctionBegin;
9519566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject) v, &comm));
9529566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
9539566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v,&dm));
9549566063dSJacob Faibussowitsch   PetscCall(DMGetUseNatural(dm, &useNatural));
95578569bb4SMatthew G. Knepley   useNatural = useNatural && size > 1 ? PETSC_TRUE : PETSC_FALSE;
9569566063dSJacob Faibussowitsch   if (useNatural) PetscCall(DMGetGlobalVector(dm,&vNatural));
95778569bb4SMatthew G. Knepley   else            {vNatural = v;}
9586823f3c5SBlaise Bourdin 
95978569bb4SMatthew G. Knepley   /* Read local chunk from the file */
9609566063dSJacob Faibussowitsch   PetscCall(VecGetOwnershipRange(vNatural, &xs, &xe));
9619566063dSJacob Faibussowitsch   PetscCall(VecGetBlockSize(vNatural, &bs));
96278569bb4SMatthew G. Knepley   if (bs == 1) {
9639566063dSJacob Faibussowitsch     PetscCall(VecGetArray(vNatural, &varray));
964a74df02fSJacob Faibussowitsch     PetscStackCallStandard(ex_get_partial_var,exoid, step, EX_NODAL, offset, 1, xs+1, xe-xs, varray);
9659566063dSJacob Faibussowitsch     PetscCall(VecRestoreArray(vNatural, &varray));
96678569bb4SMatthew G. Knepley   } else {
96778569bb4SMatthew G. Knepley     IS       compIS;
96878569bb4SMatthew G. Knepley     PetscInt c;
96978569bb4SMatthew G. Knepley 
9709566063dSJacob Faibussowitsch     PetscCall(ISCreateStride(comm, (xe-xs)/bs, xs, bs, &compIS));
97178569bb4SMatthew G. Knepley     for (c = 0; c < bs; ++c) {
9729566063dSJacob Faibussowitsch       PetscCall(ISStrideSetStride(compIS, (xe-xs)/bs, xs+c, bs));
9739566063dSJacob Faibussowitsch       PetscCall(VecGetSubVector(vNatural, compIS, &vComp));
9749566063dSJacob Faibussowitsch       PetscCall(VecGetArray(vComp, &varray));
975a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_get_partial_var,exoid, step, EX_NODAL, offset+c, 1, xs/bs+1, (xe-xs)/bs, varray);
9769566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(vComp, &varray));
9779566063dSJacob Faibussowitsch       PetscCall(VecRestoreSubVector(vNatural, compIS, &vComp));
97878569bb4SMatthew G. Knepley     }
9799566063dSJacob Faibussowitsch     PetscCall(ISDestroy(&compIS));
98078569bb4SMatthew G. Knepley   }
98178569bb4SMatthew G. Knepley   if (useNatural) {
9829566063dSJacob Faibussowitsch     PetscCall(DMPlexNaturalToGlobalBegin(dm, vNatural, v));
9839566063dSJacob Faibussowitsch     PetscCall(DMPlexNaturalToGlobalEnd(dm, vNatural, v));
9849566063dSJacob Faibussowitsch     PetscCall(DMRestoreGlobalVector(dm, &vNatural));
98578569bb4SMatthew G. Knepley   }
98678569bb4SMatthew G. Knepley   PetscFunctionReturn(0);
98778569bb4SMatthew G. Knepley }
98878569bb4SMatthew G. Knepley 
98978569bb4SMatthew G. Knepley /*
99078569bb4SMatthew G. Knepley   VecViewPlex_ExodusII_Zonal_Internal - Write a Vec corresponding to a zonal (cell based) field to an exodus file
99178569bb4SMatthew G. Knepley 
99278569bb4SMatthew G. Knepley   Collective on v
99378569bb4SMatthew G. Knepley 
99478569bb4SMatthew G. Knepley   Input Parameters:
99578569bb4SMatthew G. Knepley + v  - The vector to be written
99678569bb4SMatthew G. Knepley . exoid - the exodus id of a file (obtained from ex_open or ex_create for instance)
9976823f3c5SBlaise Bourdin . step - the time step to write at (exodus steps are numbered starting from 1)
9986823f3c5SBlaise Bourdin - offset - the location of the variable in the file
99978569bb4SMatthew G. Knepley 
100078569bb4SMatthew G. Knepley   Notes:
100178569bb4SMatthew G. Knepley   The exodus result zonal variable index is obtained by comparing the Vec name and the
100278569bb4SMatthew G. Knepley   names of zonal variables declared in the exodus file. For instance for a Vec named "V"
100378569bb4SMatthew G. Knepley   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
100478569bb4SMatthew G. Knepley   amongst all zonal variables.
100578569bb4SMatthew G. Knepley 
100678569bb4SMatthew G. Knepley   Level: beginner
100778569bb4SMatthew G. Knepley 
1008*c2e3fba1SPatrick Sanan .seealso: `EXOGetVarIndex_Internal()`, `DMPlexView_ExodusII_Internal()`, `VecViewPlex_ExodusII_Nodal_Internal()`, `VecLoadPlex_ExodusII_Nodal_Internal()`, `VecLoadPlex_ExodusII_Zonal_Internal()`
100978569bb4SMatthew G. Knepley */
10106823f3c5SBlaise Bourdin PetscErrorCode VecViewPlex_ExodusII_Zonal_Internal(Vec v, int exoid, int step, int offset)
101178569bb4SMatthew G. Knepley {
101278569bb4SMatthew G. Knepley   MPI_Comm          comm;
101378569bb4SMatthew G. Knepley   PetscMPIInt       size;
101478569bb4SMatthew G. Knepley   DM                dm;
101578569bb4SMatthew G. Knepley   Vec               vNatural, vComp;
101622a7544eSVaclav Hapla   const PetscScalar *varray;
101778569bb4SMatthew G. Knepley   PetscInt          xs, xe, bs;
101878569bb4SMatthew G. Knepley   PetscBool         useNatural;
101978569bb4SMatthew G. Knepley   IS                compIS;
102078569bb4SMatthew G. Knepley   PetscInt         *csSize, *csID;
102178569bb4SMatthew G. Knepley   PetscInt          numCS, set, csxs = 0;
102278569bb4SMatthew G. Knepley 
102378569bb4SMatthew G. Knepley   PetscFunctionBegin;
10249566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)v, &comm));
10259566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
10269566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
10279566063dSJacob Faibussowitsch   PetscCall(DMGetUseNatural(dm, &useNatural));
102878569bb4SMatthew G. Knepley   useNatural = useNatural && size > 1 ? PETSC_TRUE : PETSC_FALSE;
102978569bb4SMatthew G. Knepley   if (useNatural) {
10309566063dSJacob Faibussowitsch     PetscCall(DMGetGlobalVector(dm, &vNatural));
10319566063dSJacob Faibussowitsch     PetscCall(DMPlexGlobalToNaturalBegin(dm, v, vNatural));
10329566063dSJacob Faibussowitsch     PetscCall(DMPlexGlobalToNaturalEnd(dm, v, vNatural));
103378569bb4SMatthew G. Knepley   } else {
103478569bb4SMatthew G. Knepley     vNatural = v;
103578569bb4SMatthew G. Knepley   }
10366823f3c5SBlaise Bourdin 
103778569bb4SMatthew G. Knepley   /* Write local chunk of the result in the exodus file
103878569bb4SMatthew G. Knepley      exodus stores each component of a vector-valued field as a separate variable.
103978569bb4SMatthew G. Knepley      We assume that they are stored sequentially
104078569bb4SMatthew G. Knepley      Zonal variables are accessed one element block at a time, so we loop through the cell sets,
1041a5b23f4aSJose E. Roman      but once the vector has been reordered to natural size, we cannot use the label information
104278569bb4SMatthew G. Knepley      to figure out what to save where. */
104378569bb4SMatthew G. Knepley   numCS = ex_inquire_int(exoid, EX_INQ_ELEM_BLK);
10449566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(numCS, &csID, numCS, &csSize));
1045a74df02fSJacob Faibussowitsch   PetscStackCallStandard(ex_get_ids,exoid, EX_ELEM_BLOCK, csID);
104678569bb4SMatthew G. Knepley   for (set = 0; set < numCS; ++set) {
104778569bb4SMatthew G. Knepley     ex_block block;
104878569bb4SMatthew G. Knepley 
104978569bb4SMatthew G. Knepley     block.id   = csID[set];
105078569bb4SMatthew G. Knepley     block.type = EX_ELEM_BLOCK;
1051a74df02fSJacob Faibussowitsch     PetscStackCallStandard(ex_get_block_param,exoid, &block);
105278569bb4SMatthew G. Knepley     csSize[set] = block.num_entry;
105378569bb4SMatthew G. Knepley   }
10549566063dSJacob Faibussowitsch   PetscCall(VecGetOwnershipRange(vNatural, &xs, &xe));
10559566063dSJacob Faibussowitsch   PetscCall(VecGetBlockSize(vNatural, &bs));
10569566063dSJacob Faibussowitsch   if (bs > 1) PetscCall(ISCreateStride(comm, (xe-xs)/bs, xs, bs, &compIS));
105778569bb4SMatthew G. Knepley   for (set = 0; set < numCS; set++) {
105878569bb4SMatthew G. Knepley     PetscInt csLocalSize, c;
105978569bb4SMatthew G. Knepley 
106078569bb4SMatthew G. Knepley     /* range of indices for set setID[set]: csxs:csxs + csSize[set]-1
106178569bb4SMatthew G. Knepley        local slice of zonal values:         xs/bs,xm/bs-1
106278569bb4SMatthew G. Knepley        intersection:                        max(xs/bs,csxs),min(xm/bs-1,csxs + csSize[set]-1) */
106378569bb4SMatthew G. Knepley     csLocalSize = PetscMax(0, PetscMin(xe/bs, csxs+csSize[set]) - PetscMax(xs/bs, csxs));
106478569bb4SMatthew G. Knepley     if (bs == 1) {
10659566063dSJacob Faibussowitsch       PetscCall(VecGetArrayRead(vNatural, &varray));
1066a74df02fSJacob 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)]);
10679566063dSJacob Faibussowitsch       PetscCall(VecRestoreArrayRead(vNatural, &varray));
106878569bb4SMatthew G. Knepley     } else {
106978569bb4SMatthew G. Knepley       for (c = 0; c < bs; ++c) {
10709566063dSJacob Faibussowitsch         PetscCall(ISStrideSetStride(compIS, (xe-xs)/bs, xs+c, bs));
10719566063dSJacob Faibussowitsch         PetscCall(VecGetSubVector(vNatural, compIS, &vComp));
10729566063dSJacob Faibussowitsch         PetscCall(VecGetArrayRead(vComp, &varray));
1073a74df02fSJacob 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)]);
10749566063dSJacob Faibussowitsch         PetscCall(VecRestoreArrayRead(vComp, &varray));
10759566063dSJacob Faibussowitsch         PetscCall(VecRestoreSubVector(vNatural, compIS, &vComp));
107678569bb4SMatthew G. Knepley       }
107778569bb4SMatthew G. Knepley     }
107878569bb4SMatthew G. Knepley     csxs += csSize[set];
107978569bb4SMatthew G. Knepley   }
10809566063dSJacob Faibussowitsch   PetscCall(PetscFree2(csID, csSize));
10819566063dSJacob Faibussowitsch   if (bs > 1) PetscCall(ISDestroy(&compIS));
10829566063dSJacob Faibussowitsch   if (useNatural) PetscCall(DMRestoreGlobalVector(dm,&vNatural));
108378569bb4SMatthew G. Knepley   PetscFunctionReturn(0);
108478569bb4SMatthew G. Knepley }
108578569bb4SMatthew G. Knepley 
108678569bb4SMatthew G. Knepley /*
108778569bb4SMatthew G. Knepley   VecLoadPlex_ExodusII_Zonal_Internal - Read a Vec corresponding to a zonal (cell based) field from an exodus file
108878569bb4SMatthew G. Knepley 
108978569bb4SMatthew G. Knepley   Collective on v
109078569bb4SMatthew G. Knepley 
109178569bb4SMatthew G. Knepley   Input Parameters:
109278569bb4SMatthew G. Knepley + v  - The vector to be written
109378569bb4SMatthew G. Knepley . exoid - the exodus id of a file (obtained from ex_open or ex_create for instance)
10946823f3c5SBlaise Bourdin . step - the time step to read at (exodus steps are numbered starting from 1)
10956823f3c5SBlaise Bourdin - offset - the location of the variable in the file
109678569bb4SMatthew G. Knepley 
109778569bb4SMatthew G. Knepley   Notes:
109878569bb4SMatthew G. Knepley   The exodus result zonal variable index is obtained by comparing the Vec name and the
109978569bb4SMatthew G. Knepley   names of zonal variables declared in the exodus file. For instance for a Vec named "V"
110078569bb4SMatthew G. Knepley   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
110178569bb4SMatthew G. Knepley   amongst all zonal variables.
110278569bb4SMatthew G. Knepley 
110378569bb4SMatthew G. Knepley   Level: beginner
110478569bb4SMatthew G. Knepley 
1105db781477SPatrick Sanan .seealso: `EXOGetVarIndex_Internal()`, `DMPlexView_ExodusII_Internal()`, `VecViewPlex_ExodusII_Nodal_Internal()`, `VecLoadPlex_ExodusII_Nodal_Internal()`, `VecLoadPlex_ExodusII_Zonal_Internal()`
110678569bb4SMatthew G. Knepley */
11076823f3c5SBlaise Bourdin PetscErrorCode VecLoadPlex_ExodusII_Zonal_Internal(Vec v, int exoid, int step, int offset)
110878569bb4SMatthew G. Knepley {
110978569bb4SMatthew G. Knepley   MPI_Comm          comm;
111078569bb4SMatthew G. Knepley   PetscMPIInt       size;
111178569bb4SMatthew G. Knepley   DM                dm;
111278569bb4SMatthew G. Knepley   Vec               vNatural, vComp;
111322a7544eSVaclav Hapla   PetscScalar      *varray;
111478569bb4SMatthew G. Knepley   PetscInt          xs, xe, bs;
111578569bb4SMatthew G. Knepley   PetscBool         useNatural;
111678569bb4SMatthew G. Knepley   IS                compIS;
111778569bb4SMatthew G. Knepley   PetscInt         *csSize, *csID;
111878569bb4SMatthew G. Knepley   PetscInt          numCS, set, csxs = 0;
111978569bb4SMatthew G. Knepley 
112078569bb4SMatthew G. Knepley   PetscFunctionBegin;
11219566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject)v,&comm));
11229566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &size));
11239566063dSJacob Faibussowitsch   PetscCall(VecGetDM(v, &dm));
11249566063dSJacob Faibussowitsch   PetscCall(DMGetUseNatural(dm, &useNatural));
112578569bb4SMatthew G. Knepley   useNatural = useNatural && size > 1 ? PETSC_TRUE : PETSC_FALSE;
11269566063dSJacob Faibussowitsch   if (useNatural) PetscCall(DMGetGlobalVector(dm,&vNatural));
112778569bb4SMatthew G. Knepley   else            {vNatural = v;}
11286823f3c5SBlaise Bourdin 
112978569bb4SMatthew G. Knepley   /* Read local chunk of the result in the exodus file
113078569bb4SMatthew G. Knepley      exodus stores each component of a vector-valued field as a separate variable.
113178569bb4SMatthew G. Knepley      We assume that they are stored sequentially
113278569bb4SMatthew G. Knepley      Zonal variables are accessed one element block at a time, so we loop through the cell sets,
1133a5b23f4aSJose E. Roman      but once the vector has been reordered to natural size, we cannot use the label information
113478569bb4SMatthew G. Knepley      to figure out what to save where. */
113578569bb4SMatthew G. Knepley   numCS = ex_inquire_int(exoid, EX_INQ_ELEM_BLK);
11369566063dSJacob Faibussowitsch   PetscCall(PetscMalloc2(numCS, &csID, numCS, &csSize));
1137a74df02fSJacob Faibussowitsch   PetscStackCallStandard(ex_get_ids,exoid, EX_ELEM_BLOCK, csID);
113878569bb4SMatthew G. Knepley   for (set = 0; set < numCS; ++set) {
113978569bb4SMatthew G. Knepley     ex_block block;
114078569bb4SMatthew G. Knepley 
114178569bb4SMatthew G. Knepley     block.id   = csID[set];
114278569bb4SMatthew G. Knepley     block.type = EX_ELEM_BLOCK;
1143a74df02fSJacob Faibussowitsch     PetscStackCallStandard(ex_get_block_param,exoid, &block);
114478569bb4SMatthew G. Knepley     csSize[set] = block.num_entry;
114578569bb4SMatthew G. Knepley   }
11469566063dSJacob Faibussowitsch   PetscCall(VecGetOwnershipRange(vNatural, &xs, &xe));
11479566063dSJacob Faibussowitsch   PetscCall(VecGetBlockSize(vNatural, &bs));
11489566063dSJacob Faibussowitsch   if (bs > 1) PetscCall(ISCreateStride(comm, (xe-xs)/bs, xs, bs, &compIS));
114978569bb4SMatthew G. Knepley   for (set = 0; set < numCS; ++set) {
115078569bb4SMatthew G. Knepley     PetscInt csLocalSize, c;
115178569bb4SMatthew G. Knepley 
115278569bb4SMatthew G. Knepley     /* range of indices for set setID[set]: csxs:csxs + csSize[set]-1
115378569bb4SMatthew G. Knepley        local slice of zonal values:         xs/bs,xm/bs-1
115478569bb4SMatthew G. Knepley        intersection:                        max(xs/bs,csxs),min(xm/bs-1,csxs + csSize[set]-1) */
115578569bb4SMatthew G. Knepley     csLocalSize = PetscMax(0, PetscMin(xe/bs, csxs+csSize[set]) - PetscMax(xs/bs, csxs));
115678569bb4SMatthew G. Knepley     if (bs == 1) {
11579566063dSJacob Faibussowitsch       PetscCall(VecGetArray(vNatural, &varray));
1158a74df02fSJacob 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)]);
11599566063dSJacob Faibussowitsch       PetscCall(VecRestoreArray(vNatural, &varray));
116078569bb4SMatthew G. Knepley     } else {
116178569bb4SMatthew G. Knepley       for (c = 0; c < bs; ++c) {
11629566063dSJacob Faibussowitsch         PetscCall(ISStrideSetStride(compIS, (xe-xs)/bs, xs+c, bs));
11639566063dSJacob Faibussowitsch         PetscCall(VecGetSubVector(vNatural, compIS, &vComp));
11649566063dSJacob Faibussowitsch         PetscCall(VecGetArray(vComp, &varray));
1165a74df02fSJacob 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)]);
11669566063dSJacob Faibussowitsch         PetscCall(VecRestoreArray(vComp, &varray));
11679566063dSJacob Faibussowitsch         PetscCall(VecRestoreSubVector(vNatural, compIS, &vComp));
116878569bb4SMatthew G. Knepley       }
116978569bb4SMatthew G. Knepley     }
117078569bb4SMatthew G. Knepley     csxs += csSize[set];
117178569bb4SMatthew G. Knepley   }
11729566063dSJacob Faibussowitsch   PetscCall(PetscFree2(csID, csSize));
11739566063dSJacob Faibussowitsch   if (bs > 1) PetscCall(ISDestroy(&compIS));
117478569bb4SMatthew G. Knepley   if (useNatural) {
11759566063dSJacob Faibussowitsch     PetscCall(DMPlexNaturalToGlobalBegin(dm, vNatural, v));
11769566063dSJacob Faibussowitsch     PetscCall(DMPlexNaturalToGlobalEnd(dm, vNatural, v));
11779566063dSJacob Faibussowitsch     PetscCall(DMRestoreGlobalVector(dm, &vNatural));
117878569bb4SMatthew G. Knepley   }
117978569bb4SMatthew G. Knepley   PetscFunctionReturn(0);
118078569bb4SMatthew G. Knepley }
1181b53c8456SSatish Balay #endif
118278569bb4SMatthew G. Knepley 
11831e50132fSMatthew G. Knepley /*@
11841e50132fSMatthew G. Knepley   PetscViewerExodusIIGetId - Get the file id of the ExodusII file
11851e50132fSMatthew G. Knepley 
11861e50132fSMatthew G. Knepley   Logically Collective on PetscViewer
11871e50132fSMatthew G. Knepley 
11881e50132fSMatthew G. Knepley   Input Parameter:
11891e50132fSMatthew G. Knepley .  viewer - the PetscViewer
11901e50132fSMatthew G. Knepley 
11911e50132fSMatthew G. Knepley   Output Parameter:
1192d8d19677SJose E. Roman .  exoid - The ExodusII file id
11931e50132fSMatthew G. Knepley 
11941e50132fSMatthew G. Knepley   Level: intermediate
11951e50132fSMatthew G. Knepley 
1196db781477SPatrick Sanan .seealso: `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`
11971e50132fSMatthew G. Knepley @*/
11981e50132fSMatthew G. Knepley PetscErrorCode PetscViewerExodusIIGetId(PetscViewer viewer, int *exoid)
11991e50132fSMatthew G. Knepley {
12001e50132fSMatthew G. Knepley   PetscFunctionBegin;
12011e50132fSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
1202cac4c232SBarry Smith   PetscTryMethod(viewer, "PetscViewerGetId_C",(PetscViewer,int*),(viewer,exoid));
12036823f3c5SBlaise Bourdin   PetscFunctionReturn(0);
12046823f3c5SBlaise Bourdin }
12056823f3c5SBlaise Bourdin 
12066823f3c5SBlaise Bourdin /*@
12076823f3c5SBlaise Bourdin    PetscViewerExodusIISetOrder - Set the elements order in the exodusII file.
12086823f3c5SBlaise Bourdin 
12096823f3c5SBlaise Bourdin    Collective
12106823f3c5SBlaise Bourdin 
12116823f3c5SBlaise Bourdin    Input Parameters:
12126823f3c5SBlaise Bourdin +  viewer - the viewer
121398a6a78aSPierre Jolivet -  order - elements order
12146823f3c5SBlaise Bourdin 
12156823f3c5SBlaise Bourdin    Output Parameter:
12166823f3c5SBlaise Bourdin 
12176823f3c5SBlaise Bourdin    Level: beginner
12186823f3c5SBlaise Bourdin 
12196823f3c5SBlaise Bourdin    Note:
12206823f3c5SBlaise Bourdin 
1221db781477SPatrick Sanan .seealso: `PetscViewerExodusIIGetId()`, `PetscViewerExodusIIGetOrder()`, `PetscViewerExodusIISetOrder()`
12226823f3c5SBlaise Bourdin @*/
12236823f3c5SBlaise Bourdin PetscErrorCode PetscViewerExodusIISetOrder(PetscViewer viewer, PetscInt order)
12246823f3c5SBlaise Bourdin {
12256823f3c5SBlaise Bourdin   PetscFunctionBegin;
12266823f3c5SBlaise Bourdin   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
1227cac4c232SBarry Smith   PetscTryMethod(viewer, "PetscViewerSetOrder_C",(PetscViewer,PetscInt),(viewer,order));
12286823f3c5SBlaise Bourdin   PetscFunctionReturn(0);
12296823f3c5SBlaise Bourdin }
12306823f3c5SBlaise Bourdin 
12316823f3c5SBlaise Bourdin /*@
12326823f3c5SBlaise Bourdin    PetscViewerExodusIIGetOrder - Get the elements order in the exodusII file.
12336823f3c5SBlaise Bourdin 
12346823f3c5SBlaise Bourdin    Collective
12356823f3c5SBlaise Bourdin 
12366823f3c5SBlaise Bourdin    Input Parameters:
12376823f3c5SBlaise Bourdin +  viewer - the viewer
123898a6a78aSPierre Jolivet -  order - elements order
12396823f3c5SBlaise Bourdin 
12406823f3c5SBlaise Bourdin    Output Parameter:
12416823f3c5SBlaise Bourdin 
12426823f3c5SBlaise Bourdin    Level: beginner
12436823f3c5SBlaise Bourdin 
12446823f3c5SBlaise Bourdin    Note:
12456823f3c5SBlaise Bourdin 
1246db781477SPatrick Sanan .seealso: `PetscViewerExodusIIGetId()`, `PetscViewerExodusIIGetOrder()`, `PetscViewerExodusIISetOrder()`
12476823f3c5SBlaise Bourdin @*/
12486823f3c5SBlaise Bourdin PetscErrorCode PetscViewerExodusIIGetOrder(PetscViewer viewer, PetscInt *order)
12496823f3c5SBlaise Bourdin {
12506823f3c5SBlaise Bourdin   PetscFunctionBegin;
12516823f3c5SBlaise Bourdin   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
1252cac4c232SBarry Smith   PetscTryMethod(viewer, "PetscViewerGetOrder_C",(PetscViewer,PetscInt*),(viewer,order));
12536823f3c5SBlaise Bourdin   PetscFunctionReturn(0);
12546823f3c5SBlaise Bourdin }
12556823f3c5SBlaise Bourdin 
12566823f3c5SBlaise Bourdin /*@C
12576823f3c5SBlaise Bourdin    PetscViewerExodusIIOpen - Opens a file for ExodusII input/output.
12586823f3c5SBlaise Bourdin 
12596823f3c5SBlaise Bourdin    Collective
12606823f3c5SBlaise Bourdin 
12616823f3c5SBlaise Bourdin    Input Parameters:
12626823f3c5SBlaise Bourdin +  comm - MPI communicator
12636823f3c5SBlaise Bourdin .  name - name of file
12646823f3c5SBlaise Bourdin -  type - type of file
12656823f3c5SBlaise Bourdin $    FILE_MODE_WRITE - create new file for binary output
12666823f3c5SBlaise Bourdin $    FILE_MODE_READ - open existing file for binary input
12676823f3c5SBlaise Bourdin $    FILE_MODE_APPEND - open existing file for binary output
12686823f3c5SBlaise Bourdin 
12696823f3c5SBlaise Bourdin    Output Parameter:
12706823f3c5SBlaise Bourdin .  exo - PetscViewer for Exodus II input/output to use with the specified file
12716823f3c5SBlaise Bourdin 
12726823f3c5SBlaise Bourdin    Level: beginner
12736823f3c5SBlaise Bourdin 
12746823f3c5SBlaise Bourdin    Note:
12756823f3c5SBlaise Bourdin    This PetscViewer should be destroyed with PetscViewerDestroy().
12766823f3c5SBlaise Bourdin 
1277db781477SPatrick Sanan .seealso: `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
1278db781477SPatrick Sanan           `DMLoad()`, `PetscFileMode`, `PetscViewer`, `PetscViewerSetType()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()`
12796823f3c5SBlaise Bourdin @*/
12806823f3c5SBlaise Bourdin PetscErrorCode PetscViewerExodusIIOpen(MPI_Comm comm, const char name[], PetscFileMode type, PetscViewer *exo)
12816823f3c5SBlaise Bourdin {
12826823f3c5SBlaise Bourdin   PetscFunctionBegin;
12839566063dSJacob Faibussowitsch   PetscCall(PetscViewerCreate(comm, exo));
12849566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetType(*exo, PETSCVIEWEREXODUSII));
12859566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetMode(*exo, type));
12869566063dSJacob Faibussowitsch   PetscCall(PetscViewerFileSetName(*exo, name));
12879566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetFromOptions(*exo));
12881e50132fSMatthew G. Knepley   PetscFunctionReturn(0);
12891e50132fSMatthew G. Knepley }
12901e50132fSMatthew G. Knepley 
129133751fbdSMichael Lange /*@C
1292eaf898f9SPatrick Sanan   DMPlexCreateExodusFromFile - Create a DMPlex mesh from an ExodusII file.
129333751fbdSMichael Lange 
1294d083f849SBarry Smith   Collective
129533751fbdSMichael Lange 
129633751fbdSMichael Lange   Input Parameters:
129733751fbdSMichael Lange + comm  - The MPI communicator
129833751fbdSMichael Lange . filename - The name of the ExodusII file
129933751fbdSMichael Lange - interpolate - Create faces and edges in the mesh
130033751fbdSMichael Lange 
130133751fbdSMichael Lange   Output Parameter:
130233751fbdSMichael Lange . dm  - The DM object representing the mesh
130333751fbdSMichael Lange 
130433751fbdSMichael Lange   Level: beginner
130533751fbdSMichael Lange 
1306db781477SPatrick Sanan .seealso: `DMPLEX`, `DMCreate()`, `DMPlexCreateExodus()`
130733751fbdSMichael Lange @*/
130833751fbdSMichael Lange PetscErrorCode DMPlexCreateExodusFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm)
130933751fbdSMichael Lange {
131033751fbdSMichael Lange   PetscMPIInt    rank;
131133751fbdSMichael Lange #if defined(PETSC_HAVE_EXODUSII)
1312e84f7031SBlaise Bourdin   int   CPU_word_size = sizeof(PetscReal), IO_word_size = 0, exoid = -1;
131333751fbdSMichael Lange   float version;
131433751fbdSMichael Lange #endif
131533751fbdSMichael Lange 
131633751fbdSMichael Lange   PetscFunctionBegin;
131733751fbdSMichael Lange   PetscValidCharPointer(filename, 2);
13189566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
131933751fbdSMichael Lange #if defined(PETSC_HAVE_EXODUSII)
1320dd400576SPatrick Sanan   if (rank == 0) {
132133751fbdSMichael Lange     exoid = ex_open(filename, EX_READ, &CPU_word_size, &IO_word_size, &version);
132208401ef6SPierre Jolivet     PetscCheck(exoid > 0,PETSC_COMM_SELF, PETSC_ERR_LIB, "ex_open(\"%s\",...) did not return a valid file ID", filename);
132333751fbdSMichael Lange   }
13249566063dSJacob Faibussowitsch   PetscCall(DMPlexCreateExodus(comm, exoid, interpolate, dm));
1325a74df02fSJacob Faibussowitsch   if (rank == 0) {PetscStackCallStandard(ex_close,exoid);}
1326b458e8f1SJose E. Roman   PetscFunctionReturn(0);
132733751fbdSMichael Lange #else
132833751fbdSMichael Lange   SETERRQ(comm, PETSC_ERR_SUP, "This method requires ExodusII support. Reconfigure using --download-exodusii");
132933751fbdSMichael Lange #endif
133033751fbdSMichael Lange }
133133751fbdSMichael Lange 
13328f861fbcSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
13336823f3c5SBlaise Bourdin static PetscErrorCode ExodusGetCellType_Internal(const char *elem_type, DMPolytopeType *ct)
13348f861fbcSMatthew G. Knepley {
13358f861fbcSMatthew G. Knepley   PetscBool      flg;
13368f861fbcSMatthew G. Knepley 
13378f861fbcSMatthew G. Knepley   PetscFunctionBegin;
13388f861fbcSMatthew G. Knepley   *ct = DM_POLYTOPE_UNKNOWN;
13399566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(elem_type, "TRI", &flg));
13408f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_TRIANGLE; goto done;}
13419566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(elem_type, "TRI3", &flg));
13428f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_TRIANGLE; goto done;}
13439566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(elem_type, "QUAD", &flg));
13448f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_QUADRILATERAL; goto done;}
13459566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(elem_type, "QUAD4", &flg));
13468f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_QUADRILATERAL; goto done;}
13479566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(elem_type, "SHELL4", &flg));
13488f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_QUADRILATERAL; goto done;}
13499566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(elem_type, "TETRA", &flg));
13508f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_TETRAHEDRON; goto done;}
13519566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(elem_type, "TET4", &flg));
13528f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_TETRAHEDRON; goto done;}
13539566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(elem_type, "WEDGE", &flg));
13548f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_TRI_PRISM; goto done;}
13559566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(elem_type, "HEX", &flg));
13568f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_HEXAHEDRON; goto done;}
13579566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(elem_type, "HEX8", &flg));
13588f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_HEXAHEDRON; goto done;}
13599566063dSJacob Faibussowitsch   PetscCall(PetscStrcmp(elem_type, "HEXAHEDRON", &flg));
13608f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_HEXAHEDRON; goto done;}
136198921bdaSJacob Faibussowitsch   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unrecognized element type %s", elem_type);
13628f861fbcSMatthew G. Knepley   done:
13638f861fbcSMatthew G. Knepley   PetscFunctionReturn(0);
13648f861fbcSMatthew G. Knepley }
13658f861fbcSMatthew G. Knepley #endif
13668f861fbcSMatthew G. Knepley 
1367552f7358SJed Brown /*@
136833751fbdSMichael Lange   DMPlexCreateExodus - Create a DMPlex mesh from an ExodusII file ID.
1369552f7358SJed Brown 
1370d083f849SBarry Smith   Collective
1371552f7358SJed Brown 
1372552f7358SJed Brown   Input Parameters:
1373552f7358SJed Brown + comm  - The MPI communicator
1374552f7358SJed Brown . exoid - The ExodusII id associated with a exodus file and obtained using ex_open
1375552f7358SJed Brown - interpolate - Create faces and edges in the mesh
1376552f7358SJed Brown 
1377552f7358SJed Brown   Output Parameter:
1378552f7358SJed Brown . dm  - The DM object representing the mesh
1379552f7358SJed Brown 
1380552f7358SJed Brown   Level: beginner
1381552f7358SJed Brown 
1382db781477SPatrick Sanan .seealso: `DMPLEX`, `DMCreate()`
1383552f7358SJed Brown @*/
1384552f7358SJed Brown PetscErrorCode DMPlexCreateExodus(MPI_Comm comm, PetscInt exoid, PetscBool interpolate, DM *dm)
1385552f7358SJed Brown {
1386552f7358SJed Brown #if defined(PETSC_HAVE_EXODUSII)
1387552f7358SJed Brown   PetscMPIInt    num_proc, rank;
1388ae9eebabSLisandro Dalcin   DMLabel        cellSets = NULL, faceSets = NULL, vertSets = NULL;
1389552f7358SJed Brown   PetscSection   coordSection;
1390552f7358SJed Brown   Vec            coordinates;
1391552f7358SJed Brown   PetscScalar    *coords;
1392552f7358SJed Brown   PetscInt       coordSize, v;
1393552f7358SJed Brown   /* Read from ex_get_init() */
1394552f7358SJed Brown   char title[PETSC_MAX_PATH_LEN+1];
13955f80ce2aSJacob Faibussowitsch   int  dim    = 0, dimEmbed = 0, numVertices = 0, numCells = 0;
1396552f7358SJed Brown   int  num_cs = 0, num_vs = 0, num_fs = 0;
1397552f7358SJed Brown #endif
1398552f7358SJed Brown 
1399552f7358SJed Brown   PetscFunctionBegin;
1400552f7358SJed Brown #if defined(PETSC_HAVE_EXODUSII)
14019566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
14029566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_size(comm, &num_proc));
14039566063dSJacob Faibussowitsch   PetscCall(DMCreate(comm, dm));
14049566063dSJacob Faibussowitsch   PetscCall(DMSetType(*dm, DMPLEX));
1405a5b23f4aSJose E. Roman   /* Open EXODUS II file and read basic information on rank 0, then broadcast to all processors */
1406dd400576SPatrick Sanan   if (rank == 0) {
14079566063dSJacob Faibussowitsch     PetscCall(PetscMemzero(title,PETSC_MAX_PATH_LEN+1));
1408a74df02fSJacob Faibussowitsch     PetscStackCallStandard(ex_get_init,exoid, title, &dimEmbed, &numVertices, &numCells, &num_cs, &num_vs, &num_fs);
140928b400f6SJacob Faibussowitsch     PetscCheck(num_cs,PETSC_COMM_SELF,PETSC_ERR_SUP,"Exodus file does not contain any cell set");
1410552f7358SJed Brown   }
14119566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(title, PETSC_MAX_PATH_LEN+1, MPI_CHAR, 0, comm));
14129566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Bcast(&dim, 1, MPI_INT, 0, comm));
14139566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) *dm, title));
14149566063dSJacob Faibussowitsch   PetscCall(DMPlexSetChart(*dm, 0, numCells+numVertices));
1415412e9a14SMatthew G. Knepley   /*   We do not want this label automatically computed, instead we compute it here */
14169566063dSJacob Faibussowitsch   PetscCall(DMCreateLabel(*dm, "celltype"));
1417552f7358SJed Brown 
1418552f7358SJed Brown   /* Read cell sets information */
1419dd400576SPatrick Sanan   if (rank == 0) {
1420552f7358SJed Brown     PetscInt *cone;
1421e8f6893fSMatthew G. Knepley     int      c, cs, ncs, c_loc, v, v_loc;
1422552f7358SJed Brown     /* Read from ex_get_elem_blk_ids() */
1423e8f6893fSMatthew G. Knepley     int *cs_id, *cs_order;
1424552f7358SJed Brown     /* Read from ex_get_elem_block() */
1425552f7358SJed Brown     char buffer[PETSC_MAX_PATH_LEN+1];
1426e8f6893fSMatthew G. Knepley     int  num_cell_in_set, num_vertex_per_cell, num_hybrid, num_attr;
1427552f7358SJed Brown     /* Read from ex_get_elem_conn() */
1428552f7358SJed Brown     int *cs_connect;
1429552f7358SJed Brown 
1430552f7358SJed Brown     /* Get cell sets IDs */
14319566063dSJacob Faibussowitsch     PetscCall(PetscMalloc2(num_cs, &cs_id, num_cs, &cs_order));
1432a74df02fSJacob Faibussowitsch     PetscStackCallStandard(ex_get_ids,exoid, EX_ELEM_BLOCK, cs_id);
1433552f7358SJed Brown     /* Read the cell set connectivity table and build mesh topology
1434552f7358SJed Brown        EXO standard requires that cells in cell sets be numbered sequentially and be pairwise disjoint. */
1435e8f6893fSMatthew G. Knepley     /* Check for a hybrid mesh */
1436e8f6893fSMatthew G. Knepley     for (cs = 0, num_hybrid = 0; cs < num_cs; ++cs) {
14378f861fbcSMatthew G. Knepley       DMPolytopeType ct;
14388f861fbcSMatthew G. Knepley       char           elem_type[PETSC_MAX_PATH_LEN];
14398f861fbcSMatthew G. Knepley 
14409566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(elem_type, sizeof(elem_type)));
1441a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_get_elem_type,exoid, cs_id[cs], elem_type);
14429566063dSJacob Faibussowitsch       PetscCall(ExodusGetCellType_Internal(elem_type, &ct));
14438f861fbcSMatthew G. Knepley       dim  = PetscMax(dim, DMPolytopeTypeGetDim(ct));
1444a74df02fSJacob 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);
14458f861fbcSMatthew G. Knepley       switch (ct) {
14468f861fbcSMatthew G. Knepley         case DM_POLYTOPE_TRI_PRISM:
1447e8f6893fSMatthew G. Knepley           cs_order[cs] = cs;
1448e8f6893fSMatthew G. Knepley           ++num_hybrid;
1449e8f6893fSMatthew G. Knepley           break;
1450e8f6893fSMatthew G. Knepley         default:
1451e8f6893fSMatthew G. Knepley           for (c = cs; c > cs-num_hybrid; --c) cs_order[c] = cs_order[c-1];
1452e8f6893fSMatthew G. Knepley           cs_order[cs-num_hybrid] = cs;
1453e8f6893fSMatthew G. Knepley       }
1454e8f6893fSMatthew G. Knepley     }
1455552f7358SJed Brown     /* First set sizes */
1456e8f6893fSMatthew G. Knepley     for (ncs = 0, c = 0; ncs < num_cs; ++ncs) {
14578f861fbcSMatthew G. Knepley       DMPolytopeType ct;
14588f861fbcSMatthew G. Knepley       char           elem_type[PETSC_MAX_PATH_LEN];
1459e8f6893fSMatthew G. Knepley       const PetscInt cs = cs_order[ncs];
14608f861fbcSMatthew G. Knepley 
14619566063dSJacob Faibussowitsch       PetscCall(PetscArrayzero(elem_type, sizeof(elem_type)));
1462a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_get_elem_type,exoid, cs_id[cs], elem_type);
14639566063dSJacob Faibussowitsch       PetscCall(ExodusGetCellType_Internal(elem_type, &ct));
1464a74df02fSJacob 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);
1465552f7358SJed Brown       for (c_loc = 0; c_loc < num_cell_in_set; ++c_loc, ++c) {
14669566063dSJacob Faibussowitsch         PetscCall(DMPlexSetConeSize(*dm, c, num_vertex_per_cell));
14679566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCellType(*dm, c, ct));
1468552f7358SJed Brown       }
1469552f7358SJed Brown     }
14709566063dSJacob Faibussowitsch     for (v = numCells; v < numCells+numVertices; ++v) PetscCall(DMPlexSetCellType(*dm, v, DM_POLYTOPE_POINT));
14719566063dSJacob Faibussowitsch     PetscCall(DMSetUp(*dm));
1472e8f6893fSMatthew G. Knepley     for (ncs = 0, c = 0; ncs < num_cs; ++ncs) {
1473e8f6893fSMatthew G. Knepley       const PetscInt cs = cs_order[ncs];
1474a74df02fSJacob 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);
14759566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(num_vertex_per_cell*num_cell_in_set,&cs_connect,num_vertex_per_cell,&cone));
1476a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_get_conn,exoid, EX_ELEM_BLOCK, cs_id[cs], cs_connect,NULL,NULL);
1477eaf898f9SPatrick Sanan       /* EXO uses Fortran-based indexing, DMPlex uses C-style and numbers cell first then vertices. */
1478552f7358SJed Brown       for (c_loc = 0, v = 0; c_loc < num_cell_in_set; ++c_loc, ++c) {
1479636e64ffSStefano Zampini         DMPolytopeType ct;
1480636e64ffSStefano Zampini 
1481552f7358SJed Brown         for (v_loc = 0; v_loc < num_vertex_per_cell; ++v_loc, ++v) {
1482552f7358SJed Brown           cone[v_loc] = cs_connect[v]+numCells-1;
1483552f7358SJed Brown         }
14849566063dSJacob Faibussowitsch         PetscCall(DMPlexGetCellType(*dm, c, &ct));
14859566063dSJacob Faibussowitsch         PetscCall(DMPlexInvertCell(ct, cone));
14869566063dSJacob Faibussowitsch         PetscCall(DMPlexSetCone(*dm, c, cone));
14879566063dSJacob Faibussowitsch         PetscCall(DMSetLabelValue_Fast(*dm, &cellSets, "Cell Sets", c, cs_id[cs]));
1488552f7358SJed Brown       }
14899566063dSJacob Faibussowitsch       PetscCall(PetscFree2(cs_connect,cone));
1490552f7358SJed Brown     }
14919566063dSJacob Faibussowitsch     PetscCall(PetscFree2(cs_id, cs_order));
1492552f7358SJed Brown   }
14938f861fbcSMatthew G. Knepley   {
14948f861fbcSMatthew G. Knepley     PetscInt ints[] = {dim, dimEmbed};
14958f861fbcSMatthew G. Knepley 
14969566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Bcast(ints, 2, MPIU_INT, 0, comm));
14979566063dSJacob Faibussowitsch     PetscCall(DMSetDimension(*dm, ints[0]));
14989566063dSJacob Faibussowitsch     PetscCall(DMSetCoordinateDim(*dm, ints[1]));
14998f861fbcSMatthew G. Knepley     dim      = ints[0];
15008f861fbcSMatthew G. Knepley     dimEmbed = ints[1];
15018f861fbcSMatthew G. Knepley   }
15029566063dSJacob Faibussowitsch   PetscCall(DMPlexSymmetrize(*dm));
15039566063dSJacob Faibussowitsch   PetscCall(DMPlexStratify(*dm));
1504552f7358SJed Brown   if (interpolate) {
15055fd9971aSMatthew G. Knepley     DM idm;
1506552f7358SJed Brown 
15079566063dSJacob Faibussowitsch     PetscCall(DMPlexInterpolate(*dm, &idm));
15089566063dSJacob Faibussowitsch     PetscCall(DMDestroy(dm));
1509552f7358SJed Brown     *dm  = idm;
1510552f7358SJed Brown   }
1511552f7358SJed Brown 
1512552f7358SJed Brown   /* Create vertex set label */
1513dd400576SPatrick Sanan   if (rank == 0 && (num_vs > 0)) {
1514552f7358SJed Brown     int vs, v;
1515552f7358SJed Brown     /* Read from ex_get_node_set_ids() */
1516552f7358SJed Brown     int *vs_id;
1517552f7358SJed Brown     /* Read from ex_get_node_set_param() */
1518f958083aSBlaise Bourdin     int num_vertex_in_set;
1519552f7358SJed Brown     /* Read from ex_get_node_set() */
1520552f7358SJed Brown     int *vs_vertex_list;
1521552f7358SJed Brown 
1522552f7358SJed Brown     /* Get vertex set ids */
15239566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(num_vs, &vs_id));
1524a74df02fSJacob Faibussowitsch     PetscStackCallStandard(ex_get_ids,exoid, EX_NODE_SET, vs_id);
1525552f7358SJed Brown     for (vs = 0; vs < num_vs; ++vs) {
1526a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_get_set_param,exoid, EX_NODE_SET, vs_id[vs], &num_vertex_in_set, NULL);
15279566063dSJacob Faibussowitsch       PetscCall(PetscMalloc1(num_vertex_in_set, &vs_vertex_list));
1528a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_get_set,exoid, EX_NODE_SET, vs_id[vs], vs_vertex_list, NULL);
1529552f7358SJed Brown       for (v = 0; v < num_vertex_in_set; ++v) {
15309566063dSJacob Faibussowitsch         PetscCall(DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vs_vertex_list[v]+numCells-1, vs_id[vs]));
1531552f7358SJed Brown       }
15329566063dSJacob Faibussowitsch       PetscCall(PetscFree(vs_vertex_list));
1533552f7358SJed Brown     }
15349566063dSJacob Faibussowitsch     PetscCall(PetscFree(vs_id));
1535552f7358SJed Brown   }
1536552f7358SJed Brown   /* Read coordinates */
15379566063dSJacob Faibussowitsch   PetscCall(DMGetCoordinateSection(*dm, &coordSection));
15389566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetNumFields(coordSection, 1));
15399566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed));
15409566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
1541552f7358SJed Brown   for (v = numCells; v < numCells+numVertices; ++v) {
15429566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed));
15439566063dSJacob Faibussowitsch     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed));
1544552f7358SJed Brown   }
15459566063dSJacob Faibussowitsch   PetscCall(PetscSectionSetUp(coordSection));
15469566063dSJacob Faibussowitsch   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
15479566063dSJacob Faibussowitsch   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
15489566063dSJacob Faibussowitsch   PetscCall(PetscObjectSetName((PetscObject) coordinates, "coordinates"));
15499566063dSJacob Faibussowitsch   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
15509566063dSJacob Faibussowitsch   PetscCall(VecSetBlockSize(coordinates, dimEmbed));
15519566063dSJacob Faibussowitsch   PetscCall(VecSetType(coordinates,VECSTANDARD));
15529566063dSJacob Faibussowitsch   PetscCall(VecGetArray(coordinates, &coords));
1553dd400576SPatrick Sanan   if (rank == 0) {
1554e84f7031SBlaise Bourdin     PetscReal *x, *y, *z;
1555552f7358SJed Brown 
15569566063dSJacob Faibussowitsch     PetscCall(PetscMalloc3(numVertices,&x,numVertices,&y,numVertices,&z));
1557a74df02fSJacob Faibussowitsch     PetscStackCallStandard(ex_get_coord,exoid, x, y, z);
15588f861fbcSMatthew G. Knepley     if (dimEmbed > 0) {
15598f861fbcSMatthew G. Knepley       for (v = 0; v < numVertices; ++v) coords[v*dimEmbed+0] = x[v];
15600d644c17SKarl Rupp     }
15618f861fbcSMatthew G. Knepley     if (dimEmbed > 1) {
15628f861fbcSMatthew G. Knepley       for (v = 0; v < numVertices; ++v) coords[v*dimEmbed+1] = y[v];
15630d644c17SKarl Rupp     }
15648f861fbcSMatthew G. Knepley     if (dimEmbed > 2) {
15658f861fbcSMatthew G. Knepley       for (v = 0; v < numVertices; ++v) coords[v*dimEmbed+2] = z[v];
15660d644c17SKarl Rupp     }
15679566063dSJacob Faibussowitsch     PetscCall(PetscFree3(x,y,z));
1568552f7358SJed Brown   }
15699566063dSJacob Faibussowitsch   PetscCall(VecRestoreArray(coordinates, &coords));
15709566063dSJacob Faibussowitsch   PetscCall(DMSetCoordinatesLocal(*dm, coordinates));
15719566063dSJacob Faibussowitsch   PetscCall(VecDestroy(&coordinates));
1572552f7358SJed Brown 
1573552f7358SJed Brown   /* Create side set label */
1574dd400576SPatrick Sanan   if (rank == 0 && interpolate && (num_fs > 0)) {
1575552f7358SJed Brown     int fs, f, voff;
1576552f7358SJed Brown     /* Read from ex_get_side_set_ids() */
1577552f7358SJed Brown     int *fs_id;
1578552f7358SJed Brown     /* Read from ex_get_side_set_param() */
1579f958083aSBlaise Bourdin     int num_side_in_set;
1580552f7358SJed Brown     /* Read from ex_get_side_set_node_list() */
1581552f7358SJed Brown     int *fs_vertex_count_list, *fs_vertex_list;
1582ef073283Smichael_afanasiev     /* Read side set labels */
1583ef073283Smichael_afanasiev     char fs_name[MAX_STR_LENGTH+1];
1584552f7358SJed Brown 
1585552f7358SJed Brown     /* Get side set ids */
15869566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(num_fs, &fs_id));
1587a74df02fSJacob Faibussowitsch     PetscStackCallStandard(ex_get_ids,exoid, EX_SIDE_SET, fs_id);
1588552f7358SJed Brown     for (fs = 0; fs < num_fs; ++fs) {
1589a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_get_set_param,exoid, EX_SIDE_SET, fs_id[fs], &num_side_in_set, NULL);
15909566063dSJacob Faibussowitsch       PetscCall(PetscMalloc2(num_side_in_set,&fs_vertex_count_list,num_side_in_set*4,&fs_vertex_list));
1591a74df02fSJacob Faibussowitsch       PetscStackCallStandard(ex_get_side_set_node_list,exoid, fs_id[fs], fs_vertex_count_list, fs_vertex_list);
1592ef073283Smichael_afanasiev       /* Get the specific name associated with this side set ID. */
1593ef073283Smichael_afanasiev       int fs_name_err = ex_get_name(exoid, EX_SIDE_SET, fs_id[fs], fs_name);
1594552f7358SJed Brown       for (f = 0, voff = 0; f < num_side_in_set; ++f) {
15950298fd71SBarry Smith         const PetscInt *faces   = NULL;
1596552f7358SJed Brown         PetscInt       faceSize = fs_vertex_count_list[f], numFaces;
1597552f7358SJed Brown         PetscInt       faceVertices[4], v;
1598552f7358SJed Brown 
159908401ef6SPierre Jolivet         PetscCheck(faceSize <= 4,comm, PETSC_ERR_ARG_WRONG, "ExodusII side cannot have %d > 4 vertices", faceSize);
1600552f7358SJed Brown         for (v = 0; v < faceSize; ++v, ++voff) {
1601552f7358SJed Brown           faceVertices[v] = fs_vertex_list[voff]+numCells-1;
1602552f7358SJed Brown         }
16039566063dSJacob Faibussowitsch         PetscCall(DMPlexGetFullJoin(*dm, faceSize, faceVertices, &numFaces, &faces));
160408401ef6SPierre Jolivet         PetscCheck(numFaces == 1,comm, PETSC_ERR_ARG_WRONG, "Invalid ExodusII side %d in set %d maps to %d faces", f, fs, numFaces);
16059566063dSJacob Faibussowitsch         PetscCall(DMSetLabelValue_Fast(*dm, &faceSets, "Face Sets", faces[0], fs_id[fs]));
1606ef073283Smichael_afanasiev         /* Only add the label if one has been detected for this side set. */
1607ef073283Smichael_afanasiev         if (!fs_name_err) {
16089566063dSJacob Faibussowitsch           PetscCall(DMSetLabelValue(*dm, fs_name, faces[0], fs_id[fs]));
1609ef073283Smichael_afanasiev         }
16109566063dSJacob Faibussowitsch         PetscCall(DMPlexRestoreJoin(*dm, faceSize, faceVertices, &numFaces, &faces));
1611552f7358SJed Brown       }
16129566063dSJacob Faibussowitsch       PetscCall(PetscFree2(fs_vertex_count_list,fs_vertex_list));
1613552f7358SJed Brown     }
16149566063dSJacob Faibussowitsch     PetscCall(PetscFree(fs_id));
1615552f7358SJed Brown   }
1616ae9eebabSLisandro Dalcin 
1617ae9eebabSLisandro Dalcin   { /* Create Cell/Face/Vertex Sets labels at all processes */
1618ae9eebabSLisandro Dalcin     enum {n = 3};
1619ae9eebabSLisandro Dalcin     PetscBool flag[n];
1620ae9eebabSLisandro Dalcin 
1621ae9eebabSLisandro Dalcin     flag[0] = cellSets ? PETSC_TRUE : PETSC_FALSE;
1622ae9eebabSLisandro Dalcin     flag[1] = faceSets ? PETSC_TRUE : PETSC_FALSE;
1623ae9eebabSLisandro Dalcin     flag[2] = vertSets ? PETSC_TRUE : PETSC_FALSE;
16249566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Bcast(flag, n, MPIU_BOOL, 0, comm));
16259566063dSJacob Faibussowitsch     if (flag[0]) PetscCall(DMCreateLabel(*dm, "Cell Sets"));
16269566063dSJacob Faibussowitsch     if (flag[1]) PetscCall(DMCreateLabel(*dm, "Face Sets"));
16279566063dSJacob Faibussowitsch     if (flag[2]) PetscCall(DMCreateLabel(*dm, "Vertex Sets"));
1628ae9eebabSLisandro Dalcin   }
1629b458e8f1SJose E. Roman   PetscFunctionReturn(0);
1630552f7358SJed Brown #else
1631552f7358SJed Brown   SETERRQ(comm, PETSC_ERR_SUP, "This method requires ExodusII support. Reconfigure using --download-exodusii");
1632552f7358SJed Brown #endif
1633552f7358SJed Brown }
1634