xref: /petsc/src/dm/impls/plex/plexexodusii.c (revision 6823f3c5150c1da349ca574ac70c38fd7a677edd)
1552f7358SJed Brown #define PETSCDM_DLL
2af0996ceSBarry Smith #include <petsc/private/dmpleximpl.h>    /*I   "petscdmplex.h"   I*/
3552f7358SJed Brown 
4519f805aSKarl Rupp #if defined(PETSC_HAVE_EXODUSII)
5552f7358SJed Brown #include <netcdf.h>
6552f7358SJed Brown #include <exodusII.h>
7552f7358SJed Brown #endif
8552f7358SJed Brown 
91e50132fSMatthew G. Knepley #include <petsc/private/viewerimpl.h>
101e50132fSMatthew G. Knepley #include <petsc/private/viewerexodusiiimpl.h>
11e0266925SMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
1278569bb4SMatthew G. Knepley /*
131e50132fSMatthew G. Knepley   PETSC_VIEWER_EXODUSII_ - Creates an ExodusII PetscViewer shared by all processors in a communicator.
141e50132fSMatthew G. Knepley 
151e50132fSMatthew G. Knepley   Collective
161e50132fSMatthew G. Knepley 
171e50132fSMatthew G. Knepley   Input Parameter:
181e50132fSMatthew G. Knepley . comm - the MPI communicator to share the ExodusII PetscViewer
191e50132fSMatthew G. Knepley 
201e50132fSMatthew G. Knepley   Level: intermediate
211e50132fSMatthew G. Knepley 
221e50132fSMatthew G. Knepley   Notes:
231e50132fSMatthew G. Knepley     misses Fortran bindings
241e50132fSMatthew G. Knepley 
251e50132fSMatthew G. Knepley   Notes:
261e50132fSMatthew G. Knepley   Unlike almost all other PETSc routines, PETSC_VIEWER_EXODUSII_ does not return
271e50132fSMatthew G. Knepley   an error code.  The GLVIS PetscViewer is usually used in the form
281e50132fSMatthew G. Knepley $       XXXView(XXX object, PETSC_VIEWER_EXODUSII_(comm));
291e50132fSMatthew G. Knepley 
3000373969SVaclav Hapla .seealso: PetscViewerExodusIIOpen(), PetscViewerType, PetscViewerCreate(), PetscViewerDestroy()
311e50132fSMatthew G. Knepley */
321e50132fSMatthew G. Knepley PetscViewer PETSC_VIEWER_EXODUSII_(MPI_Comm comm)
331e50132fSMatthew G. Knepley {
341e50132fSMatthew G. Knepley   PetscViewer    viewer;
351e50132fSMatthew G. Knepley   PetscErrorCode ierr;
361e50132fSMatthew G. Knepley 
371e50132fSMatthew G. Knepley   PetscFunctionBegin;
381e50132fSMatthew G. Knepley   ierr = PetscViewerExodusIIOpen(comm, "mesh.exo", FILE_MODE_WRITE, &viewer);
3900373969SVaclav Hapla   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_EXODUSII_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
401e50132fSMatthew G. Knepley   ierr = PetscObjectRegisterDestroy((PetscObject) viewer);
4100373969SVaclav Hapla   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_EXODUSII_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
421e50132fSMatthew G. Knepley   PetscFunctionReturn(viewer);
431e50132fSMatthew G. Knepley }
441e50132fSMatthew G. Knepley 
451e50132fSMatthew G. Knepley static PetscErrorCode PetscViewerView_ExodusII(PetscViewer v, PetscViewer viewer)
461e50132fSMatthew G. Knepley {
47*6823f3c5SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *) v->data;
481e50132fSMatthew G. Knepley   PetscErrorCode        ierr;
491e50132fSMatthew G. Knepley 
501e50132fSMatthew G. Knepley   PetscFunctionBegin;
511e50132fSMatthew G. Knepley   if (exo->filename) {ierr = PetscViewerASCIIPrintf(viewer, "Filename:    %s\n", exo->filename);CHKERRQ(ierr);}
52*6823f3c5SBlaise Bourdin   if (exo->exoid)    {ierr = PetscViewerASCIIPrintf(viewer, "exoid:       %d\n", exo->exoid)   ;CHKERRQ(ierr);}
53*6823f3c5SBlaise Bourdin   if (exo->btype)    {ierr = PetscViewerASCIIPrintf(viewer, "IO Mode:     %d\n", exo->btype)   ;CHKERRQ(ierr);}
54*6823f3c5SBlaise Bourdin   if (exo->order)    {ierr = PetscViewerASCIIPrintf(viewer, "Mesh order:  %d\n", exo->order)   ;CHKERRQ(ierr);}
551e50132fSMatthew G. Knepley   PetscFunctionReturn(0);
561e50132fSMatthew G. Knepley }
571e50132fSMatthew G. Knepley 
581e50132fSMatthew G. Knepley static PetscErrorCode PetscViewerSetFromOptions_ExodusII(PetscOptionItems *PetscOptionsObject, PetscViewer v)
591e50132fSMatthew G. Knepley {
601e50132fSMatthew G. Knepley   PetscErrorCode ierr;
611e50132fSMatthew G. Knepley 
621e50132fSMatthew G. Knepley   PetscFunctionBegin;
631e50132fSMatthew G. Knepley   ierr = PetscOptionsHead(PetscOptionsObject, "ExodusII PetscViewer Options");CHKERRQ(ierr);
641e50132fSMatthew G. Knepley   ierr = PetscOptionsTail();CHKERRQ(ierr);
651e50132fSMatthew G. Knepley   PetscFunctionReturn(0);
661e50132fSMatthew G. Knepley }
671e50132fSMatthew G. Knepley 
681e50132fSMatthew G. Knepley static PetscErrorCode PetscViewerSetUp_ExodusII(PetscViewer viewer)
691e50132fSMatthew G. Knepley {
701e50132fSMatthew G. Knepley   PetscFunctionBegin;
711e50132fSMatthew G. Knepley   PetscFunctionReturn(0);
721e50132fSMatthew G. Knepley }
731e50132fSMatthew G. Knepley 
741e50132fSMatthew G. Knepley static PetscErrorCode PetscViewerDestroy_ExodusII(PetscViewer viewer)
751e50132fSMatthew G. Knepley {
761e50132fSMatthew G. Knepley   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *) viewer->data;
771e50132fSMatthew G. Knepley   PetscErrorCode        ierr;
781e50132fSMatthew G. Knepley 
791e50132fSMatthew G. Knepley   PetscFunctionBegin;
80*6823f3c5SBlaise Bourdin   if (exo->exoid >= 0) {PetscStackCallStandard(ex_close,(exo->exoid));}
81*6823f3c5SBlaise Bourdin   ierr = PetscFree(exo->filename);CHKERRQ(ierr);
821e50132fSMatthew G. Knepley   ierr = PetscFree(exo);CHKERRQ(ierr);
831e50132fSMatthew G. Knepley   ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetName_C",NULL);CHKERRQ(ierr);
841e50132fSMatthew G. Knepley   ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileGetName_C",NULL);CHKERRQ(ierr);
851e50132fSMatthew G. Knepley   ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetMode_C",NULL);CHKERRQ(ierr);
86*6823f3c5SBlaise Bourdin   ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerGetId_C",NULL);CHKERRQ(ierr);
87*6823f3c5SBlaise Bourdin   ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerGetOrder_C",NULL);CHKERRQ(ierr);
88*6823f3c5SBlaise Bourdin   ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerSetOrder_C",NULL);CHKERRQ(ierr);
891e50132fSMatthew G. Knepley   PetscFunctionReturn(0);
901e50132fSMatthew G. Knepley }
911e50132fSMatthew G. Knepley 
921e50132fSMatthew G. Knepley static PetscErrorCode PetscViewerFileSetName_ExodusII(PetscViewer viewer, const char name[])
931e50132fSMatthew G. Knepley {
941e50132fSMatthew G. Knepley   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *) viewer->data;
951e50132fSMatthew G. Knepley   PetscMPIInt           rank;
961e50132fSMatthew G. Knepley   int                   CPU_word_size, IO_word_size, EXO_mode;
971e50132fSMatthew G. Knepley   PetscErrorCode        ierr;
98*6823f3c5SBlaise Bourdin   MPI_Info              mpi_info = MPI_INFO_NULL;
99*6823f3c5SBlaise Bourdin   float                 EXO_version;
1001e50132fSMatthew G. Knepley 
101ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject) viewer), &rank);CHKERRMPI(ierr);
1021e50132fSMatthew G. Knepley   CPU_word_size = sizeof(PetscReal);
1031e50132fSMatthew G. Knepley   IO_word_size  = sizeof(PetscReal);
1041e50132fSMatthew G. Knepley 
1051e50132fSMatthew G. Knepley   PetscFunctionBegin;
106*6823f3c5SBlaise Bourdin   if (exo->exoid >= 0) {
107*6823f3c5SBlaise Bourdin     PetscStackCallStandard(ex_close,(exo->exoid));
108*6823f3c5SBlaise Bourdin     exo->exoid = -1;
109*6823f3c5SBlaise Bourdin   }
1101e50132fSMatthew G. Knepley   if (exo->filename) {ierr = PetscFree(exo->filename);CHKERRQ(ierr);}
1111e50132fSMatthew G. Knepley   ierr = PetscStrallocpy(name, &exo->filename);CHKERRQ(ierr);
1121e50132fSMatthew G. Knepley   switch (exo->btype) {
1131e50132fSMatthew G. Knepley   case FILE_MODE_READ:
114*6823f3c5SBlaise Bourdin     EXO_mode = EX_READ;
1151e50132fSMatthew G. Knepley     break;
1161e50132fSMatthew G. Knepley   case FILE_MODE_APPEND:
117*6823f3c5SBlaise Bourdin   case FILE_MODE_UPDATE:
118*6823f3c5SBlaise Bourdin   case FILE_MODE_APPEND_UPDATE:
119*6823f3c5SBlaise Bourdin     /* Will fail if the file does not already exist */
120*6823f3c5SBlaise Bourdin     EXO_mode = EX_WRITE;
1211e50132fSMatthew G. Knepley     break;
1221e50132fSMatthew G. Knepley   case FILE_MODE_WRITE:
123*6823f3c5SBlaise Bourdin     /*
124*6823f3c5SBlaise Bourdin       exodus only allows writing geometry upon file creation, so we will let DMView create the file.
125*6823f3c5SBlaise Bourdin     */
126*6823f3c5SBlaise Bourdin     PetscFunctionReturn(0);
1271e50132fSMatthew G. Knepley     break;
1281e50132fSMatthew G. Knepley   default:
1291e50132fSMatthew G. Knepley     SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
1301e50132fSMatthew G. Knepley   }
1311e50132fSMatthew G. Knepley   #if defined(PETSC_USE_64BIT_INDICES)
1321e50132fSMatthew G. Knepley   EXO_mode += EX_ALL_INT64_API;
1331e50132fSMatthew G. Knepley   #endif
134*6823f3c5SBlaise Bourdin   exo->exoid = ex_open_par(name,EXO_mode,&CPU_word_size,&IO_word_size,&EXO_version,PETSC_COMM_WORLD,mpi_info);
135*6823f3c5SBlaise Bourdin   if (exo->exoid < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, "ex_open_par failed for %s", name);
1361e50132fSMatthew G. Knepley   PetscFunctionReturn(0);
1371e50132fSMatthew G. Knepley }
1381e50132fSMatthew G. Knepley 
1391e50132fSMatthew G. Knepley static PetscErrorCode PetscViewerFileGetName_ExodusII(PetscViewer viewer, const char **name)
1401e50132fSMatthew G. Knepley {
1411e50132fSMatthew G. Knepley   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *) viewer->data;
1421e50132fSMatthew G. Knepley 
1431e50132fSMatthew G. Knepley   PetscFunctionBegin;
1441e50132fSMatthew G. Knepley   *name = exo->filename;
1451e50132fSMatthew G. Knepley   PetscFunctionReturn(0);
1461e50132fSMatthew G. Knepley }
1471e50132fSMatthew G. Knepley 
1481e50132fSMatthew G. Knepley static PetscErrorCode PetscViewerFileSetMode_ExodusII(PetscViewer viewer, PetscFileMode type)
1491e50132fSMatthew G. Knepley {
1501e50132fSMatthew G. Knepley   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *) viewer->data;
1511e50132fSMatthew G. Knepley 
1521e50132fSMatthew G. Knepley   PetscFunctionBegin;
1531e50132fSMatthew G. Knepley   exo->btype = type;
1541e50132fSMatthew G. Knepley   PetscFunctionReturn(0);
1551e50132fSMatthew G. Knepley }
1561e50132fSMatthew G. Knepley 
1571e50132fSMatthew G. Knepley static PetscErrorCode PetscViewerFileGetMode_ExodusII(PetscViewer viewer, PetscFileMode *type)
1581e50132fSMatthew G. Knepley {
1591e50132fSMatthew G. Knepley   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *) viewer->data;
1601e50132fSMatthew G. Knepley 
1611e50132fSMatthew G. Knepley   PetscFunctionBegin;
1621e50132fSMatthew G. Knepley   *type = exo->btype;
1631e50132fSMatthew G. Knepley   PetscFunctionReturn(0);
1641e50132fSMatthew G. Knepley }
1651e50132fSMatthew G. Knepley 
1661e50132fSMatthew G. Knepley static PetscErrorCode PetscViewerExodusIIGetId_ExodusII(PetscViewer viewer, int *exoid)
1671e50132fSMatthew G. Knepley {
1681e50132fSMatthew G. Knepley   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *) viewer->data;
1691e50132fSMatthew G. Knepley 
1701e50132fSMatthew G. Knepley   PetscFunctionBegin;
1711e50132fSMatthew G. Knepley   *exoid = exo->exoid;
1721e50132fSMatthew G. Knepley   PetscFunctionReturn(0);
1731e50132fSMatthew G. Knepley }
1741e50132fSMatthew G. Knepley 
175*6823f3c5SBlaise Bourdin static PetscErrorCode PetscViewerExodusIIGetOrder_ExodusII(PetscViewer viewer, PetscInt *order)
1761e50132fSMatthew G. Knepley {
177*6823f3c5SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *) viewer->data;
1781e50132fSMatthew G. Knepley 
1791e50132fSMatthew G. Knepley   PetscFunctionBegin;
180*6823f3c5SBlaise Bourdin   *order = exo->order;
181*6823f3c5SBlaise Bourdin   PetscFunctionReturn(0);
182*6823f3c5SBlaise Bourdin }
183*6823f3c5SBlaise Bourdin 
184*6823f3c5SBlaise Bourdin static PetscErrorCode PetscViewerExodusIISetOrder_ExodusII(PetscViewer viewer, PetscInt order)
185*6823f3c5SBlaise Bourdin {
186*6823f3c5SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *) viewer->data;
187*6823f3c5SBlaise Bourdin 
188*6823f3c5SBlaise Bourdin   PetscFunctionBegin;
189*6823f3c5SBlaise Bourdin   exo->order = order;
1901e50132fSMatthew G. Knepley   PetscFunctionReturn(0);
1911e50132fSMatthew G. Knepley }
1921e50132fSMatthew G. Knepley 
1931e50132fSMatthew G. Knepley /*MC
19400373969SVaclav Hapla    PETSCVIEWEREXODUSII - A viewer that writes to an Exodus II file
1951e50132fSMatthew G. Knepley 
1961e50132fSMatthew G. Knepley 
19700373969SVaclav Hapla .seealso:  PetscViewerExodusIIOpen(), PetscViewerCreate(), PETSCVIEWERBINARY, PETSCVIEWERHDF5, DMView(),
1981e50132fSMatthew G. Knepley            PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType()
1991e50132fSMatthew G. Knepley 
2001e50132fSMatthew G. Knepley   Level: beginner
2011e50132fSMatthew G. Knepley M*/
2021e50132fSMatthew G. Knepley 
2031e50132fSMatthew G. Knepley PETSC_EXTERN PetscErrorCode PetscViewerCreate_ExodusII(PetscViewer v)
2041e50132fSMatthew G. Knepley {
2051e50132fSMatthew G. Knepley   PetscViewer_ExodusII *exo;
2061e50132fSMatthew G. Knepley   PetscErrorCode        ierr;
2071e50132fSMatthew G. Knepley 
2081e50132fSMatthew G. Knepley   PetscFunctionBegin;
2091e50132fSMatthew G. Knepley   ierr = PetscNewLog(v,&exo);CHKERRQ(ierr);
2101e50132fSMatthew G. Knepley 
2111e50132fSMatthew G. Knepley   v->data                = (void*) exo;
2121e50132fSMatthew G. Knepley   v->ops->destroy        = PetscViewerDestroy_ExodusII;
2131e50132fSMatthew G. Knepley   v->ops->setfromoptions = PetscViewerSetFromOptions_ExodusII;
2141e50132fSMatthew G. Knepley   v->ops->setup          = PetscViewerSetUp_ExodusII;
2151e50132fSMatthew G. Knepley   v->ops->view           = PetscViewerView_ExodusII;
2161e50132fSMatthew G. Knepley   v->ops->flush          = 0;
2171e50132fSMatthew G. Knepley   exo->btype             = (PetscFileMode) -1;
2181e50132fSMatthew G. Knepley   exo->filename          = 0;
2191e50132fSMatthew G. Knepley   exo->exoid             = -1;
2201e50132fSMatthew G. Knepley 
2211e50132fSMatthew G. Knepley   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetName_C",PetscViewerFileSetName_ExodusII);CHKERRQ(ierr);
2221e50132fSMatthew G. Knepley   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetName_C",PetscViewerFileGetName_ExodusII);CHKERRQ(ierr);
2231e50132fSMatthew G. Knepley   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_ExodusII);CHKERRQ(ierr);
2241e50132fSMatthew G. Knepley   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerFileGetMode_C",PetscViewerFileGetMode_ExodusII);CHKERRQ(ierr);
225*6823f3c5SBlaise Bourdin   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerGetId_C",PetscViewerExodusIIGetId_ExodusII);CHKERRQ(ierr);
226*6823f3c5SBlaise Bourdin   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerSetOrder_C",PetscViewerExodusIISetOrder_ExodusII);CHKERRQ(ierr);
227*6823f3c5SBlaise Bourdin   ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerGetOrder_C",PetscViewerExodusIIGetOrder_ExodusII);CHKERRQ(ierr);
2281e50132fSMatthew G. Knepley   PetscFunctionReturn(0);
2291e50132fSMatthew G. Knepley }
2301e50132fSMatthew G. Knepley 
2311e50132fSMatthew G. Knepley /*
23278569bb4SMatthew G. Knepley   EXOGetVarIndex - Locate a result in an exodus file based on its name
23378569bb4SMatthew G. Knepley 
234*6823f3c5SBlaise Bourdin   Collective
23578569bb4SMatthew G. Knepley 
23678569bb4SMatthew G. Knepley   Input Parameters:
23778569bb4SMatthew G. Knepley + exoid    - the exodus id of a file (obtained from ex_open or ex_create for instance)
23878569bb4SMatthew G. Knepley . obj_type - the type of entity for instance EX_NODAL, EX_ELEM_BLOCK
23978569bb4SMatthew G. Knepley - name     - the name of the result
24078569bb4SMatthew G. Knepley 
24178569bb4SMatthew G. Knepley   Output Parameters:
24278569bb4SMatthew G. Knepley . varIndex - the location in the exodus file of the result
24378569bb4SMatthew G. Knepley 
24478569bb4SMatthew G. Knepley   Notes:
24578569bb4SMatthew G. Knepley   The exodus variable index is obtained by comparing name and the
24678569bb4SMatthew G. Knepley   names of zonal variables declared in the exodus file. For instance if name is "V"
24778569bb4SMatthew G. Knepley   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
24878569bb4SMatthew G. Knepley   amongst all variables of type obj_type.
24978569bb4SMatthew G. Knepley 
25078569bb4SMatthew G. Knepley   Level: beginner
25178569bb4SMatthew G. Knepley 
252cd921712SStefano Zampini .seealso: EXOGetVarIndex(),DMPlexView_ExodusII_Internal(),VecViewPlex_ExodusII_Nodal_Internal(),VecLoadNodal_PlexEXO(),VecLoadZonal_PlexEXO()
25378569bb4SMatthew G. Knepley */
254*6823f3c5SBlaise Bourdin PetscErrorCode EXOGetVarIndex_Internal(int exoid, ex_entity_type obj_type, const char name[], int *varIndex)
25578569bb4SMatthew G. Knepley {
2566de834b4SMatthew G. Knepley   int            num_vars, i, j;
25778569bb4SMatthew G. Knepley   char           ext_name[MAX_STR_LENGTH+1], var_name[MAX_STR_LENGTH+1];
25878569bb4SMatthew G. Knepley   const int      num_suffix = 5;
25978569bb4SMatthew G. Knepley   char          *suffix[5];
26078569bb4SMatthew G. Knepley   PetscBool      flg;
26178569bb4SMatthew G. Knepley   PetscErrorCode ierr;
26278569bb4SMatthew G. Knepley 
26378569bb4SMatthew G. Knepley   PetscFunctionBegin;
26478569bb4SMatthew G. Knepley   suffix[0] = (char *) "";
26578569bb4SMatthew G. Knepley   suffix[1] = (char *) "_X";
26678569bb4SMatthew G. Knepley   suffix[2] = (char *) "_XX";
26778569bb4SMatthew G. Knepley   suffix[3] = (char *) "_1";
26878569bb4SMatthew G. Knepley   suffix[4] = (char *) "_11";
26978569bb4SMatthew G. Knepley 
270*6823f3c5SBlaise Bourdin   *varIndex = -1;
2716de834b4SMatthew G. Knepley   PetscStackCallStandard(ex_get_variable_param,(exoid, obj_type, &num_vars));
27278569bb4SMatthew G. Knepley   for (i = 0; i < num_vars; ++i) {
2736de834b4SMatthew G. Knepley     PetscStackCallStandard(ex_get_variable_name,(exoid, obj_type, i+1, var_name));
27478569bb4SMatthew G. Knepley     for (j = 0; j < num_suffix; ++j){
27578569bb4SMatthew G. Knepley       ierr = PetscStrncpy(ext_name, name, MAX_STR_LENGTH);CHKERRQ(ierr);
276a126751eSBarry Smith       ierr = PetscStrlcat(ext_name, suffix[j], MAX_STR_LENGTH);CHKERRQ(ierr);
27778569bb4SMatthew G. Knepley       ierr = PetscStrcasecmp(ext_name, var_name, &flg);
27878569bb4SMatthew G. Knepley       if (flg) {
27978569bb4SMatthew G. Knepley         *varIndex = i+1;
280*6823f3c5SBlaise Bourdin       }
281*6823f3c5SBlaise Bourdin     }
282*6823f3c5SBlaise Bourdin   }
28378569bb4SMatthew G. Knepley   PetscFunctionReturn(0);
28478569bb4SMatthew G. Knepley }
28578569bb4SMatthew G. Knepley 
28678569bb4SMatthew G. Knepley /*
287*6823f3c5SBlaise Bourdin   DMView_PlexExodusII - Write a DM to disk in exodus format
28878569bb4SMatthew G. Knepley 
28978569bb4SMatthew G. Knepley   Collective on dm
29078569bb4SMatthew G. Knepley 
29178569bb4SMatthew G. Knepley   Input Parameters:
29278569bb4SMatthew G. Knepley + dm  - The dm to be written
293*6823f3c5SBlaise Bourdin . viewer - an exodusII viewer
29478569bb4SMatthew G. Knepley 
29578569bb4SMatthew G. Knepley   Notes:
29678569bb4SMatthew G. Knepley   Not all DM can be written to disk this way. For instance, exodus assume that element blocks (mapped to "Cell sets" labels)
29778569bb4SMatthew G. Knepley   consists of sequentially numbered cells. If this is not the case, the exodus file will be corrupted.
29878569bb4SMatthew G. Knepley 
299*6823f3c5SBlaise Bourdin   If the dm has been distributed, only the part of the DM on MPI rank 0 (including "ghost" cells and vertices)
300*6823f3c5SBlaise Bourdin   will be written.
30178569bb4SMatthew G. Knepley 
30278569bb4SMatthew G. Knepley   DMPlex only represents geometry while most post-processing software expect that a mesh also provides information
30378569bb4SMatthew G. Knepley   on the discretization space. This function assumes that the file represents Lagrange finite elements of order 1 or 2.
304*6823f3c5SBlaise Bourdin   The order of the mesh shall be set using PetscViewerExodusIISetOrder
30578569bb4SMatthew G. Knepley   It should be extended to use PetscFE objects.
30678569bb4SMatthew G. Knepley 
307*6823f3c5SBlaise Bourdin   This function will only handle TRI, TET, QUAD, and HEX cells.
30878569bb4SMatthew G. Knepley   Level: beginner
30978569bb4SMatthew G. Knepley 
310*6823f3c5SBlaise Bourdin .seealso:
31178569bb4SMatthew G. Knepley */
312*6823f3c5SBlaise Bourdin PetscErrorCode DMView_PlexExodusII(DM dm, PetscViewer viewer)
31378569bb4SMatthew G. Knepley {
31478569bb4SMatthew G. Knepley   enum ElemType {TRI, QUAD, TET, HEX};
31578569bb4SMatthew G. Knepley   MPI_Comm        comm;
316*6823f3c5SBlaise Bourdin   PetscInt        degree; /* the order of the mesh */
31778569bb4SMatthew G. Knepley   /* Connectivity Variables */
31878569bb4SMatthew G. Knepley   PetscInt        cellsNotInConnectivity;
31978569bb4SMatthew G. Knepley   /* Cell Sets */
32078569bb4SMatthew G. Knepley   DMLabel         csLabel;
32178569bb4SMatthew G. Knepley   IS              csIS;
32278569bb4SMatthew G. Knepley   const PetscInt *csIdx;
32378569bb4SMatthew G. Knepley   PetscInt        num_cs, cs;
32478569bb4SMatthew G. Knepley   enum ElemType  *type;
325fe209ef9SBlaise Bourdin   PetscBool       hasLabel;
32678569bb4SMatthew G. Knepley   /* Coordinate Variables */
32778569bb4SMatthew G. Knepley   DM              cdm;
328*6823f3c5SBlaise Bourdin   PetscSection    coordSection;
32978569bb4SMatthew G. Knepley   Vec             coord;
33078569bb4SMatthew G. Knepley   PetscInt      **nodes;
331eae8a387SMatthew G. Knepley   PetscInt        depth, d, dim, skipCells = 0;
33278569bb4SMatthew G. Knepley   PetscInt        pStart, pEnd, p, cStart, cEnd, numCells, vStart, vEnd, numVertices, eStart, eEnd, numEdges, fStart, fEnd, numFaces, numNodes;
33378569bb4SMatthew G. Knepley   PetscInt        num_vs, num_fs;
33478569bb4SMatthew G. Knepley   PetscMPIInt     rank, size;
33578569bb4SMatthew G. Knepley   const char     *dmName;
336fe209ef9SBlaise Bourdin   PetscInt        nodesTriP1[4]  = {3,0,0,0};
337fe209ef9SBlaise Bourdin   PetscInt        nodesTriP2[4]  = {3,3,0,0};
338fe209ef9SBlaise Bourdin   PetscInt        nodesQuadP1[4] = {4,0,0,0};
339fe209ef9SBlaise Bourdin   PetscInt        nodesQuadP2[4] = {4,4,0,1};
340fe209ef9SBlaise Bourdin   PetscInt        nodesTetP1[4]  = {4,0,0,0};
341fe209ef9SBlaise Bourdin   PetscInt        nodesTetP2[4]  = {4,6,0,0};
342fe209ef9SBlaise Bourdin   PetscInt        nodesHexP1[4]  = {8,0,0,0};
343fe209ef9SBlaise Bourdin   PetscInt        nodesHexP2[4]  = {8,12,6,1};
34478569bb4SMatthew G. Knepley   PetscErrorCode  ierr;
34578569bb4SMatthew G. Knepley 
346*6823f3c5SBlaise Bourdin   int             CPU_word_size, IO_word_size, EXO_mode;
347*6823f3c5SBlaise Bourdin   float           EXO_version;
348*6823f3c5SBlaise Bourdin 
349*6823f3c5SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *) viewer->data;
350*6823f3c5SBlaise Bourdin 
35178569bb4SMatthew G. Knepley   PetscFunctionBegin;
35278569bb4SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr);
353ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
354ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
355*6823f3c5SBlaise Bourdin 
356*6823f3c5SBlaise Bourdin   /*
357*6823f3c5SBlaise Bourdin     Creating coordSection is a collective operation so we do it somewhat out of sequence
358*6823f3c5SBlaise Bourdin   */
359*6823f3c5SBlaise Bourdin   ierr = PetscSectionCreate(comm, &coordSection);CHKERRQ(ierr);
360*6823f3c5SBlaise Bourdin   ierr = DMGetCoordinatesLocalSetUp(dm);CHKERRQ(ierr);
361*6823f3c5SBlaise Bourdin   if (!rank) {
362*6823f3c5SBlaise Bourdin     switch (exo->btype) {
363*6823f3c5SBlaise Bourdin     case FILE_MODE_READ:
364*6823f3c5SBlaise Bourdin     case FILE_MODE_APPEND:
365*6823f3c5SBlaise Bourdin     case FILE_MODE_UPDATE:
366*6823f3c5SBlaise Bourdin     case FILE_MODE_APPEND_UPDATE:
367*6823f3c5SBlaise Bourdin       /* exodusII does not allow writing geometry to an existing file */
368*6823f3c5SBlaise Bourdin       SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, "cannot add geometry to existing file %s", exo->filename);
369*6823f3c5SBlaise Bourdin     case FILE_MODE_WRITE:
370*6823f3c5SBlaise Bourdin       /* Create an empty file if one already exists*/
371*6823f3c5SBlaise Bourdin       EXO_mode = EX_CLOBBER;
372*6823f3c5SBlaise Bourdin #if defined(PETSC_USE_64BIT_INDICES)
373*6823f3c5SBlaise Bourdin       EXO_mode += EX_ALL_INT64_API;
374*6823f3c5SBlaise Bourdin #endif
375*6823f3c5SBlaise Bourdin         CPU_word_size = sizeof(PetscReal);
376*6823f3c5SBlaise Bourdin         IO_word_size  = sizeof(PetscReal);
377*6823f3c5SBlaise Bourdin         exo->exoid = ex_create(exo->filename, EXO_mode, &CPU_word_size, &IO_word_size);
378*6823f3c5SBlaise Bourdin         if (exo->exoid < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, "ex_create failed for %s", exo->filename);
379*6823f3c5SBlaise Bourdin 
380*6823f3c5SBlaise Bourdin       break;
381*6823f3c5SBlaise Bourdin     default:
382*6823f3c5SBlaise Bourdin       SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
383*6823f3c5SBlaise Bourdin     }
384*6823f3c5SBlaise Bourdin 
38578569bb4SMatthew G. Knepley     /* --- Get DM info --- */
38678569bb4SMatthew G. Knepley     ierr = PetscObjectGetName((PetscObject) dm, &dmName);CHKERRQ(ierr);
38778569bb4SMatthew G. Knepley     ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr);
38878569bb4SMatthew G. Knepley     ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr);
38978569bb4SMatthew G. Knepley     ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
39078569bb4SMatthew G. Knepley     ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr);
39178569bb4SMatthew G. Knepley     ierr = DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr);
39278569bb4SMatthew G. Knepley     ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);
39378569bb4SMatthew G. Knepley     ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr);
39478569bb4SMatthew G. Knepley     numCells    = cEnd - cStart;
39578569bb4SMatthew G. Knepley     numEdges    = eEnd - eStart;
39678569bb4SMatthew G. Knepley     numVertices = vEnd - vStart;
39778569bb4SMatthew G. Knepley     if (depth == 3) {numFaces = fEnd - fStart;}
39878569bb4SMatthew G. Knepley     else            {numFaces = 0;}
39978569bb4SMatthew G. Knepley     ierr = DMGetLabelSize(dm, "Cell Sets", &num_cs);CHKERRQ(ierr);
40078569bb4SMatthew G. Knepley     ierr = DMGetLabelSize(dm, "Vertex Sets", &num_vs);CHKERRQ(ierr);
40178569bb4SMatthew G. Knepley     ierr = DMGetLabelSize(dm, "Face Sets", &num_fs);CHKERRQ(ierr);
40278569bb4SMatthew G. Knepley     ierr = DMGetCoordinatesLocal(dm, &coord);CHKERRQ(ierr);
40378569bb4SMatthew G. Knepley     ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr);
40478569bb4SMatthew G. Knepley     if (num_cs > 0) {
40578569bb4SMatthew G. Knepley       ierr = DMGetLabel(dm, "Cell Sets", &csLabel);CHKERRQ(ierr);
40678569bb4SMatthew G. Knepley       ierr = DMLabelGetValueIS(csLabel, &csIS);CHKERRQ(ierr);
40778569bb4SMatthew G. Knepley       ierr = ISGetIndices(csIS, &csIdx);CHKERRQ(ierr);
40878569bb4SMatthew G. Knepley     }
40978569bb4SMatthew G. Knepley     ierr = PetscMalloc1(num_cs, &nodes);CHKERRQ(ierr);
41078569bb4SMatthew G. Knepley     /* Set element type for each block and compute total number of nodes */
41178569bb4SMatthew G. Knepley     ierr = PetscMalloc1(num_cs, &type);CHKERRQ(ierr);
41278569bb4SMatthew G. Knepley     numNodes = numVertices;
413*6823f3c5SBlaise Bourdin 
414*6823f3c5SBlaise Bourdin     ierr = PetscViewerExodusIIGetOrder(viewer, &degree);CHKERRQ(ierr);
41578569bb4SMatthew G. Knepley     if (degree == 2) {numNodes += numEdges;}
41678569bb4SMatthew G. Knepley     cellsNotInConnectivity = numCells;
41778569bb4SMatthew G. Knepley     for (cs = 0; cs < num_cs; ++cs) {
41878569bb4SMatthew G. Knepley       IS              stratumIS;
41978569bb4SMatthew G. Knepley       const PetscInt *cells;
42078569bb4SMatthew G. Knepley       PetscScalar    *xyz = NULL;
42178569bb4SMatthew G. Knepley       PetscInt        csSize, closureSize;
42278569bb4SMatthew G. Knepley 
42378569bb4SMatthew G. Knepley       ierr = DMLabelGetStratumIS(csLabel, csIdx[cs], &stratumIS);CHKERRQ(ierr);
42478569bb4SMatthew G. Knepley       ierr = ISGetIndices(stratumIS, &cells);CHKERRQ(ierr);
42578569bb4SMatthew G. Knepley       ierr = ISGetSize(stratumIS, &csSize);CHKERRQ(ierr);
42678569bb4SMatthew G. Knepley       ierr = DMPlexVecGetClosure(cdm, NULL, coord, cells[0], &closureSize, &xyz);CHKERRQ(ierr);
42778569bb4SMatthew G. Knepley       switch (dim) {
42878569bb4SMatthew G. Knepley         case 2:
42978569bb4SMatthew G. Knepley           if      (closureSize == 3*dim) {type[cs] = TRI;}
43078569bb4SMatthew G. Knepley           else if (closureSize == 4*dim) {type[cs] = QUAD;}
43178569bb4SMatthew G. Knepley           else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices %D in dimension %D has no ExodusII type", closureSize/dim, dim);
43278569bb4SMatthew G. Knepley           break;
43378569bb4SMatthew G. Knepley         case 3:
43478569bb4SMatthew G. Knepley           if      (closureSize == 4*dim) {type[cs] = TET;}
43578569bb4SMatthew G. Knepley           else if (closureSize == 8*dim) {type[cs] = HEX;}
43678569bb4SMatthew G. Knepley           else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices %D in dimension %D has no ExodusII type", closureSize/dim, dim);
43778569bb4SMatthew G. Knepley           break;
43878569bb4SMatthew G. Knepley         default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %D not handled by ExodusII viewer", dim);
43978569bb4SMatthew G. Knepley       }
44078569bb4SMatthew G. Knepley       if ((degree == 2) && (type[cs] == QUAD)) {numNodes += csSize;}
44178569bb4SMatthew G. Knepley       if ((degree == 2) && (type[cs] == HEX))  {numNodes += csSize; numNodes += numFaces;}
44278569bb4SMatthew G. Knepley       ierr = DMPlexVecRestoreClosure(cdm, NULL, coord, cells[0], &closureSize, &xyz);CHKERRQ(ierr);
44378569bb4SMatthew G. Knepley       /* Set nodes and Element type */
44478569bb4SMatthew G. Knepley       if (type[cs] == TRI) {
44578569bb4SMatthew G. Knepley         if      (degree == 1) nodes[cs] = nodesTriP1;
44678569bb4SMatthew G. Knepley         else if (degree == 2) nodes[cs] = nodesTriP2;
44778569bb4SMatthew G. Knepley       } else if (type[cs] == QUAD) {
44878569bb4SMatthew G. Knepley         if      (degree == 1) nodes[cs] = nodesQuadP1;
44978569bb4SMatthew G. Knepley         else if (degree == 2) nodes[cs] = nodesQuadP2;
45078569bb4SMatthew G. Knepley       } else if (type[cs] == TET) {
45178569bb4SMatthew G. Knepley         if      (degree == 1) nodes[cs] = nodesTetP1;
45278569bb4SMatthew G. Knepley         else if (degree == 2) nodes[cs] = nodesTetP2;
45378569bb4SMatthew G. Knepley       } else if (type[cs] == HEX) {
45478569bb4SMatthew G. Knepley         if      (degree == 1) nodes[cs] = nodesHexP1;
45578569bb4SMatthew G. Knepley         else if (degree == 2) nodes[cs] = nodesHexP2;
45678569bb4SMatthew G. Knepley       }
45778569bb4SMatthew G. Knepley       /* Compute the number of cells not in the connectivity table */
45878569bb4SMatthew G. Knepley       cellsNotInConnectivity -= nodes[cs][3]*csSize;
45978569bb4SMatthew G. Knepley 
46078569bb4SMatthew G. Knepley       ierr = ISRestoreIndices(stratumIS, &cells);CHKERRQ(ierr);
46178569bb4SMatthew G. Knepley       ierr = ISDestroy(&stratumIS);CHKERRQ(ierr);
46278569bb4SMatthew G. Knepley     }
463*6823f3c5SBlaise Bourdin     if (num_cs > 0) {PetscStackCallStandard(ex_put_init,(exo->exoid, dmName, dim, numNodes, numCells, num_cs, num_vs, num_fs));}
46478569bb4SMatthew G. Knepley     /* --- Connectivity --- */
46578569bb4SMatthew G. Knepley     for (cs = 0; cs < num_cs; ++cs) {
46678569bb4SMatthew G. Knepley       IS              stratumIS;
46778569bb4SMatthew G. Knepley       const PetscInt *cells;
468fe209ef9SBlaise Bourdin       PetscInt       *connect, off = 0;
469eae8a387SMatthew G. Knepley       PetscInt        edgesInClosure = 0, facesInClosure = 0, verticesInClosure = 0;
47078569bb4SMatthew G. Knepley       PetscInt        csSize, c, connectSize, closureSize;
47178569bb4SMatthew G. Knepley       char           *elem_type = NULL;
47278569bb4SMatthew G. Knepley       char            elem_type_tri3[]  = "TRI3",  elem_type_quad4[] = "QUAD4";
47378569bb4SMatthew G. Knepley       char            elem_type_tri6[]  = "TRI6",  elem_type_quad9[] = "QUAD9";
47478569bb4SMatthew G. Knepley       char            elem_type_tet4[]  = "TET4",  elem_type_hex8[]  = "HEX8";
47578569bb4SMatthew G. Knepley       char            elem_type_tet10[] = "TET10", elem_type_hex27[] = "HEX27";
47678569bb4SMatthew G. Knepley 
47778569bb4SMatthew G. Knepley       ierr = DMLabelGetStratumIS(csLabel, csIdx[cs], &stratumIS);CHKERRQ(ierr);
47878569bb4SMatthew G. Knepley       ierr = ISGetIndices(stratumIS, &cells);CHKERRQ(ierr);
47978569bb4SMatthew G. Knepley       ierr = ISGetSize(stratumIS, &csSize);CHKERRQ(ierr);
48078569bb4SMatthew G. Knepley       /* Set Element type */
48178569bb4SMatthew G. Knepley       if (type[cs] == TRI) {
48278569bb4SMatthew G. Knepley         if      (degree == 1) elem_type = elem_type_tri3;
48378569bb4SMatthew G. Knepley         else if (degree == 2) elem_type = elem_type_tri6;
48478569bb4SMatthew G. Knepley       } else if (type[cs] == QUAD) {
48578569bb4SMatthew G. Knepley         if      (degree == 1) elem_type = elem_type_quad4;
48678569bb4SMatthew G. Knepley         else if (degree == 2) elem_type = elem_type_quad9;
48778569bb4SMatthew G. Knepley       } else if (type[cs] == TET) {
48878569bb4SMatthew G. Knepley         if      (degree == 1) elem_type = elem_type_tet4;
48978569bb4SMatthew G. Knepley         else if (degree == 2) elem_type = elem_type_tet10;
49078569bb4SMatthew G. Knepley       } else if (type[cs] == HEX) {
49178569bb4SMatthew G. Knepley         if      (degree == 1) elem_type = elem_type_hex8;
49278569bb4SMatthew G. Knepley         else if (degree == 2) elem_type = elem_type_hex27;
49378569bb4SMatthew G. Knepley       }
49478569bb4SMatthew G. Knepley       connectSize = nodes[cs][0] + nodes[cs][1] + nodes[cs][2] + nodes[cs][3];
495fe209ef9SBlaise Bourdin       ierr = PetscMalloc1(PetscMax(27,connectSize)*csSize, &connect);CHKERRQ(ierr);
496*6823f3c5SBlaise Bourdin       PetscStackCallStandard(ex_put_block,(exo->exoid, EX_ELEM_BLOCK, csIdx[cs], elem_type, csSize, connectSize, 0, 0, 1));
49778569bb4SMatthew G. Knepley       /* Find number of vertices, edges, and faces in the closure */
49878569bb4SMatthew G. Knepley       verticesInClosure = nodes[cs][0];
49978569bb4SMatthew G. Knepley       if (depth > 1) {
50078569bb4SMatthew G. Knepley         if (dim == 2) {
50178569bb4SMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, cells[0], &edgesInClosure);CHKERRQ(ierr);
50278569bb4SMatthew G. Knepley         } else if (dim == 3) {
50378569bb4SMatthew G. Knepley           PetscInt *closure = NULL;
50478569bb4SMatthew G. Knepley 
50578569bb4SMatthew G. Knepley           ierr = DMPlexGetConeSize(dm, cells[0], &facesInClosure);CHKERRQ(ierr);
50678569bb4SMatthew G. Knepley           ierr = DMPlexGetTransitiveClosure(dm, cells[0], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
50778569bb4SMatthew G. Knepley           edgesInClosure = closureSize - facesInClosure - 1 - verticesInClosure;
50878569bb4SMatthew G. Knepley           ierr = DMPlexRestoreTransitiveClosure(dm, cells[0], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
50978569bb4SMatthew G. Knepley         }
51078569bb4SMatthew G. Knepley       }
51178569bb4SMatthew G. Knepley       /* Get connectivity for each cell */
51278569bb4SMatthew G. Knepley       for (c = 0; c < csSize; ++c) {
51378569bb4SMatthew G. Knepley         PetscInt *closure = NULL;
51478569bb4SMatthew G. Knepley         PetscInt  temp, i;
51578569bb4SMatthew G. Knepley 
51678569bb4SMatthew G. Knepley         ierr = DMPlexGetTransitiveClosure(dm, cells[c], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
51778569bb4SMatthew G. Knepley         for (i = 0; i < connectSize; ++i) {
51878569bb4SMatthew G. Knepley           if (i < nodes[cs][0]) {/* Vertices */
519fe209ef9SBlaise Bourdin             connect[i+off] = closure[(i+edgesInClosure+facesInClosure+1)*2] + 1;
520fe209ef9SBlaise Bourdin             connect[i+off] -= cellsNotInConnectivity;
52178569bb4SMatthew G. Knepley           } else if (i < nodes[cs][0]+nodes[cs][1]) { /* Edges */
522fe209ef9SBlaise Bourdin             connect[i+off] = closure[(i-verticesInClosure+facesInClosure+1)*2] + 1;
523fe209ef9SBlaise Bourdin             if (nodes[cs][2] == 0) connect[i+off] -= numFaces;
524fe209ef9SBlaise Bourdin             connect[i+off] -= cellsNotInConnectivity;
52578569bb4SMatthew G. Knepley           } else if (i < nodes[cs][0]+nodes[cs][1]+nodes[cs][3]){ /* Cells */
526fe209ef9SBlaise Bourdin             connect[i+off] = closure[0] + 1;
527fe209ef9SBlaise Bourdin             connect[i+off] -= skipCells;
52878569bb4SMatthew G. Knepley           } else if (i < nodes[cs][0]+nodes[cs][1]+nodes[cs][3]+nodes[cs][2]){ /* Faces */
529fe209ef9SBlaise Bourdin             connect[i+off] = closure[(i-edgesInClosure-verticesInClosure)*2] + 1;
530fe209ef9SBlaise Bourdin             connect[i+off] -= cellsNotInConnectivity;
53178569bb4SMatthew G. Knepley           } else {
532fe209ef9SBlaise Bourdin             connect[i+off] = -1;
53378569bb4SMatthew G. Knepley           }
53478569bb4SMatthew G. Knepley         }
53578569bb4SMatthew G. Knepley         /* Tetrahedra are inverted */
53678569bb4SMatthew G. Knepley         if (type[cs] == TET) {
537fe209ef9SBlaise Bourdin           temp = connect[0+off]; connect[0+off] = connect[1+off]; connect[1+off] = temp;
53878569bb4SMatthew G. Knepley           if (degree == 2) {
539e2c9586dSBlaise Bourdin             temp = connect[5+off]; connect[5+off] = connect[6+off]; connect[6+off] = temp;
540e2c9586dSBlaise Bourdin             temp = connect[7+off]; connect[7+off] = connect[8+off]; connect[8+off] = temp;
54178569bb4SMatthew G. Knepley           }
54278569bb4SMatthew G. Knepley         }
54378569bb4SMatthew G. Knepley         /* Hexahedra are inverted */
54478569bb4SMatthew G. Knepley         if (type[cs] == HEX) {
545fe209ef9SBlaise Bourdin           temp = connect[1+off]; connect[1+off] = connect[3+off]; connect[3+off] = temp;
54678569bb4SMatthew G. Knepley           if (degree == 2) {
547fe209ef9SBlaise Bourdin             temp = connect[8+off];  connect[8+off]  = connect[11+off]; connect[11+off] = temp;
548fe209ef9SBlaise Bourdin             temp = connect[9+off];  connect[9+off]  = connect[10+off]; connect[10+off] = temp;
549fe209ef9SBlaise Bourdin             temp = connect[16+off]; connect[16+off] = connect[17+off]; connect[17+off] = temp;
550fe209ef9SBlaise Bourdin             temp = connect[18+off]; connect[18+off] = connect[19+off]; connect[19+off] = temp;
55178569bb4SMatthew G. Knepley 
552fe209ef9SBlaise Bourdin             temp = connect[12+off]; connect[12+off] = connect[16+off]; connect[16+off] = temp;
553fe209ef9SBlaise Bourdin             temp = connect[13+off]; connect[13+off] = connect[17+off]; connect[17+off] = temp;
554fe209ef9SBlaise Bourdin             temp = connect[14+off]; connect[14+off] = connect[18+off]; connect[18+off] = temp;
555fe209ef9SBlaise Bourdin             temp = connect[15+off]; connect[15+off] = connect[19+off]; connect[19+off] = temp;
55678569bb4SMatthew G. Knepley 
557fe209ef9SBlaise Bourdin             temp = connect[23+off]; connect[23+off] = connect[26+off]; connect[26+off] = temp;
558fe209ef9SBlaise Bourdin             temp = connect[24+off]; connect[24+off] = connect[25+off]; connect[25+off] = temp;
559fe209ef9SBlaise Bourdin             temp = connect[25+off]; connect[25+off] = connect[26+off]; connect[26+off] = temp;
56078569bb4SMatthew G. Knepley           }
56178569bb4SMatthew G. Knepley         }
562fe209ef9SBlaise Bourdin         off += connectSize;
56378569bb4SMatthew G. Knepley         ierr = DMPlexRestoreTransitiveClosure(dm, cells[c], PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr);
56478569bb4SMatthew G. Knepley       }
565*6823f3c5SBlaise Bourdin       PetscStackCallStandard(ex_put_conn,(exo->exoid, EX_ELEM_BLOCK, csIdx[cs], connect, 0, 0));
56678569bb4SMatthew G. Knepley       skipCells += (nodes[cs][3] == 0)*csSize;
56778569bb4SMatthew G. Knepley       ierr = PetscFree(connect);CHKERRQ(ierr);
56878569bb4SMatthew G. Knepley       ierr = ISRestoreIndices(stratumIS, &cells);CHKERRQ(ierr);
56978569bb4SMatthew G. Knepley       ierr = ISDestroy(&stratumIS);CHKERRQ(ierr);
57078569bb4SMatthew G. Knepley     }
57178569bb4SMatthew G. Knepley     ierr = PetscFree(type);CHKERRQ(ierr);
57278569bb4SMatthew G. Knepley     /* --- Coordinates --- */
573*6823f3c5SBlaise Bourdin     ierr = PetscSectionSetChart(coordSection, pStart, pEnd);CHKERRQ(ierr);
5741e50132fSMatthew G. Knepley     if (num_cs) {
57578569bb4SMatthew G. Knepley       for (d = 0; d < depth; ++d) {
57678569bb4SMatthew G. Knepley         ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr);
57778569bb4SMatthew G. Knepley         for (p = pStart; p < pEnd; ++p) {
578*6823f3c5SBlaise Bourdin           ierr = PetscSectionSetDof(coordSection, p, nodes[0][d] > 0);CHKERRQ(ierr);
57978569bb4SMatthew G. Knepley         }
58078569bb4SMatthew G. Knepley       }
5811e50132fSMatthew G. Knepley     }
58278569bb4SMatthew G. Knepley     for (cs = 0; cs < num_cs; ++cs) {
58378569bb4SMatthew G. Knepley       IS              stratumIS;
58478569bb4SMatthew G. Knepley       const PetscInt *cells;
58578569bb4SMatthew G. Knepley       PetscInt        csSize, c;
58678569bb4SMatthew G. Knepley 
58778569bb4SMatthew G. Knepley       ierr = DMLabelGetStratumIS(csLabel, csIdx[cs], &stratumIS);CHKERRQ(ierr);
58878569bb4SMatthew G. Knepley       ierr = ISGetIndices(stratumIS, &cells);CHKERRQ(ierr);
58978569bb4SMatthew G. Knepley       ierr = ISGetSize(stratumIS, &csSize);CHKERRQ(ierr);
59078569bb4SMatthew G. Knepley       for (c = 0; c < csSize; ++c) {
591*6823f3c5SBlaise Bourdin         ierr = PetscSectionSetDof(coordSection, cells[c], nodes[cs][3] > 0);CHKERRQ(ierr);
59278569bb4SMatthew G. Knepley       }
59378569bb4SMatthew G. Knepley       ierr = ISRestoreIndices(stratumIS, &cells);CHKERRQ(ierr);
59478569bb4SMatthew G. Knepley       ierr = ISDestroy(&stratumIS);CHKERRQ(ierr);
59578569bb4SMatthew G. Knepley     }
59678569bb4SMatthew G. Knepley     if (num_cs > 0) {
59778569bb4SMatthew G. Knepley       ierr = ISRestoreIndices(csIS, &csIdx);CHKERRQ(ierr);
59878569bb4SMatthew G. Knepley       ierr = ISDestroy(&csIS);CHKERRQ(ierr);
59978569bb4SMatthew G. Knepley     }
60078569bb4SMatthew G. Knepley     ierr = PetscFree(nodes);CHKERRQ(ierr);
601*6823f3c5SBlaise Bourdin     ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr);
60278569bb4SMatthew G. Knepley     if (numNodes > 0) {
60378569bb4SMatthew G. Knepley       const char  *coordNames[3] = {"x", "y", "z"};
60478569bb4SMatthew G. Knepley       PetscScalar *coords, *closure;
60578569bb4SMatthew G. Knepley       PetscReal   *cval;
60678569bb4SMatthew G. Knepley       PetscInt     hasDof, n = 0;
60778569bb4SMatthew G. Knepley 
608*6823f3c5SBlaise Bourdin       /* There can't be more than 24 values in the closure of a point for the coord coordSection */
6096de834b4SMatthew G. Knepley       ierr = PetscCalloc3(numNodes*3, &coords, dim, &cval, 24, &closure);CHKERRQ(ierr);
610*6823f3c5SBlaise Bourdin       ierr = DMGetCoordinatesLocalNoncollective(dm, &coord);CHKERRQ(ierr);
61178569bb4SMatthew G. Knepley       ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr);
61278569bb4SMatthew G. Knepley       for (p = pStart; p < pEnd; ++p) {
613*6823f3c5SBlaise Bourdin         ierr = PetscSectionGetDof(coordSection, p, &hasDof);
61478569bb4SMatthew G. Knepley         if (hasDof) {
61578569bb4SMatthew G. Knepley           PetscInt closureSize = 24, j;
61678569bb4SMatthew G. Knepley 
61778569bb4SMatthew G. Knepley           ierr = DMPlexVecGetClosure(cdm, NULL, coord, p, &closureSize, &closure);CHKERRQ(ierr);
61878569bb4SMatthew G. Knepley           for (d = 0; d < dim; ++d) {
61978569bb4SMatthew G. Knepley             cval[d] = 0.0;
62078569bb4SMatthew G. Knepley             for (j = 0; j < closureSize/dim; j++) cval[d] += closure[j*dim+d];
62178569bb4SMatthew G. Knepley             coords[d*numNodes+n] = cval[d] * dim / closureSize;
62278569bb4SMatthew G. Knepley           }
62378569bb4SMatthew G. Knepley           ++n;
62478569bb4SMatthew G. Knepley         }
62578569bb4SMatthew G. Knepley       }
626*6823f3c5SBlaise Bourdin       PetscStackCallStandard(ex_put_coord,(exo->exoid, &coords[0*numNodes], &coords[1*numNodes], &coords[2*numNodes]));
62778569bb4SMatthew G. Knepley       ierr = PetscFree3(coords, cval, closure);CHKERRQ(ierr);
628*6823f3c5SBlaise Bourdin       PetscStackCallStandard(ex_put_coord_names,(exo->exoid, (char **) coordNames));
62978569bb4SMatthew G. Knepley     }
630*6823f3c5SBlaise Bourdin 
631fe209ef9SBlaise Bourdin     /* --- Node Sets/Vertex Sets --- */
632fe209ef9SBlaise Bourdin     DMHasLabel(dm, "Vertex Sets", &hasLabel);
633fe209ef9SBlaise Bourdin     if (hasLabel) {
634fe209ef9SBlaise Bourdin       PetscInt        i, vs, vsSize;
635fe209ef9SBlaise Bourdin       const PetscInt *vsIdx, *vertices;
636fe209ef9SBlaise Bourdin       PetscInt       *nodeList;
637fe209ef9SBlaise Bourdin       IS              vsIS, stratumIS;
638fe209ef9SBlaise Bourdin       DMLabel         vsLabel;
639fe209ef9SBlaise Bourdin       ierr = DMGetLabel(dm, "Vertex Sets", &vsLabel);CHKERRQ(ierr);
640fe209ef9SBlaise Bourdin       ierr = DMLabelGetValueIS(vsLabel, &vsIS);CHKERRQ(ierr);
641fe209ef9SBlaise Bourdin       ierr = ISGetIndices(vsIS, &vsIdx);CHKERRQ(ierr);
642fe209ef9SBlaise Bourdin       for (vs=0; vs<num_vs; ++vs) {
643fe209ef9SBlaise Bourdin         ierr = DMLabelGetStratumIS(vsLabel, vsIdx[vs], &stratumIS);CHKERRQ(ierr);
644fe209ef9SBlaise Bourdin         ierr = ISGetIndices(stratumIS, &vertices);CHKERRQ(ierr);
645fe209ef9SBlaise Bourdin         ierr = ISGetSize(stratumIS, &vsSize);CHKERRQ(ierr);
646fe209ef9SBlaise Bourdin         ierr = PetscMalloc1(vsSize, &nodeList);
647fe209ef9SBlaise Bourdin         for (i=0; i<vsSize; ++i) {
648fe209ef9SBlaise Bourdin           nodeList[i] = vertices[i] - skipCells + 1;
649fe209ef9SBlaise Bourdin         }
650*6823f3c5SBlaise Bourdin         PetscStackCallStandard(ex_put_set_param,(exo->exoid, EX_NODE_SET, vsIdx[vs], vsSize, 0));
651*6823f3c5SBlaise Bourdin         PetscStackCallStandard(ex_put_set,(exo->exoid, EX_NODE_SET, vsIdx[vs], nodeList, NULL));
652fe209ef9SBlaise Bourdin         ierr = ISRestoreIndices(stratumIS, &vertices);CHKERRQ(ierr);
653fe209ef9SBlaise Bourdin         ierr = ISDestroy(&stratumIS);CHKERRQ(ierr);
654fe209ef9SBlaise Bourdin         ierr = PetscFree(nodeList);CHKERRQ(ierr);
655fe209ef9SBlaise Bourdin       }
656fe209ef9SBlaise Bourdin       ierr = ISRestoreIndices(vsIS, &vsIdx);CHKERRQ(ierr);
657fe209ef9SBlaise Bourdin       ierr = ISDestroy(&vsIS);CHKERRQ(ierr);
658fe209ef9SBlaise Bourdin     }
659fe209ef9SBlaise Bourdin     /* --- Side Sets/Face Sets --- */
660fe209ef9SBlaise Bourdin     ierr = DMHasLabel(dm, "Face Sets", &hasLabel);CHKERRQ(ierr);
661fe209ef9SBlaise Bourdin     if (hasLabel) {
662fe209ef9SBlaise Bourdin       PetscInt        i, j, fs, fsSize;
663fe209ef9SBlaise Bourdin       const PetscInt *fsIdx, *faces;
664fe209ef9SBlaise Bourdin       IS              fsIS, stratumIS;
665fe209ef9SBlaise Bourdin       DMLabel         fsLabel;
666fe209ef9SBlaise Bourdin       PetscInt        numPoints, *points;
667fe209ef9SBlaise Bourdin       PetscInt        elem_list_size = 0;
668fe209ef9SBlaise Bourdin       PetscInt       *elem_list, *elem_ind, *side_list;
669fe209ef9SBlaise Bourdin 
670fe209ef9SBlaise Bourdin       ierr = DMGetLabel(dm, "Face Sets", &fsLabel);CHKERRQ(ierr);
671fe209ef9SBlaise Bourdin       /* Compute size of Node List and Element List */
672fe209ef9SBlaise Bourdin       ierr = DMLabelGetValueIS(fsLabel, &fsIS);CHKERRQ(ierr);
673fe209ef9SBlaise Bourdin       ierr = ISGetIndices(fsIS, &fsIdx);CHKERRQ(ierr);
674fe209ef9SBlaise Bourdin       for (fs=0; fs<num_fs; ++fs) {
675feb237baSPierre Jolivet         ierr = DMLabelGetStratumIS(fsLabel, fsIdx[fs], &stratumIS);CHKERRQ(ierr);
676fe209ef9SBlaise Bourdin         ierr = ISGetSize(stratumIS, &fsSize);CHKERRQ(ierr);
677fe209ef9SBlaise Bourdin         elem_list_size += fsSize;
678fe209ef9SBlaise Bourdin         ierr = ISDestroy(&stratumIS);CHKERRQ(ierr);
679fe209ef9SBlaise Bourdin       }
680fe209ef9SBlaise Bourdin       ierr = PetscMalloc3(num_fs, &elem_ind,
681fe209ef9SBlaise Bourdin                           elem_list_size, &elem_list,
682fe209ef9SBlaise Bourdin                           elem_list_size, &side_list);CHKERRQ(ierr);
683fe209ef9SBlaise Bourdin       elem_ind[0] = 0;
684fe209ef9SBlaise Bourdin       for (fs=0; fs<num_fs; ++fs) {
685fe209ef9SBlaise Bourdin         ierr = DMLabelGetStratumIS(fsLabel, fsIdx[fs], &stratumIS);CHKERRQ(ierr);
686fe209ef9SBlaise Bourdin         ierr = ISGetIndices(stratumIS, &faces);CHKERRQ(ierr);
687fe209ef9SBlaise Bourdin         ierr = ISGetSize(stratumIS, &fsSize);CHKERRQ(ierr);
688fe209ef9SBlaise Bourdin         /* Set Parameters */
689*6823f3c5SBlaise Bourdin         PetscStackCallStandard(ex_put_set_param,(exo->exoid, EX_SIDE_SET, fsIdx[fs], fsSize, 0));
690fe209ef9SBlaise Bourdin         /* Indices */
691fe209ef9SBlaise Bourdin         if (fs<num_fs-1) {
692fe209ef9SBlaise Bourdin           elem_ind[fs+1] = elem_ind[fs] + fsSize;
693fe209ef9SBlaise Bourdin         }
694fe209ef9SBlaise Bourdin 
695fe209ef9SBlaise Bourdin         for (i=0; i<fsSize; ++i) {
696fe209ef9SBlaise Bourdin           /* Element List */
697fe209ef9SBlaise Bourdin           points = NULL;
698fe209ef9SBlaise Bourdin           ierr = DMPlexGetTransitiveClosure(dm, faces[i], PETSC_FALSE, &numPoints, &points);CHKERRQ(ierr);
699fe209ef9SBlaise Bourdin           elem_list[elem_ind[fs] + i] = points[2] +1;
700fe209ef9SBlaise Bourdin           ierr = DMPlexRestoreTransitiveClosure(dm, faces[i], PETSC_FALSE, &numPoints, &points);CHKERRQ(ierr);
701fe209ef9SBlaise Bourdin 
702fe209ef9SBlaise Bourdin           /* Side List */
703fe209ef9SBlaise Bourdin           points = NULL;
704fe209ef9SBlaise Bourdin           ierr = DMPlexGetTransitiveClosure(dm, elem_list[elem_ind[fs] + i]-1, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);
705fe209ef9SBlaise Bourdin           for (j=1; j<numPoints; ++j) {
706fe209ef9SBlaise Bourdin             if (points[j*2]==faces[i]) {break;}
707fe209ef9SBlaise Bourdin           }
708fe209ef9SBlaise Bourdin           /* Convert HEX sides */
709fe209ef9SBlaise Bourdin           if (numPoints == 27) {
710fe209ef9SBlaise Bourdin             if      (j == 1) {j = 5;}
711fe209ef9SBlaise Bourdin             else if (j == 2) {j = 6;}
712fe209ef9SBlaise Bourdin             else if (j == 3) {j = 1;}
713fe209ef9SBlaise Bourdin             else if (j == 4) {j = 3;}
714fe209ef9SBlaise Bourdin             else if (j == 5) {j = 2;}
715fe209ef9SBlaise Bourdin             else if (j == 6) {j = 4;}
716fe209ef9SBlaise Bourdin           }
717fe209ef9SBlaise Bourdin           /* Convert TET sides */
718fe209ef9SBlaise Bourdin           if (numPoints == 15) {
719fe209ef9SBlaise Bourdin             --j;
720fe209ef9SBlaise Bourdin             if (j == 0) {j = 4;}
721fe209ef9SBlaise Bourdin           }
722fe209ef9SBlaise Bourdin           side_list[elem_ind[fs] + i] = j;
723fe209ef9SBlaise Bourdin           ierr = DMPlexRestoreTransitiveClosure(dm, elem_list[elem_ind[fs] + i]-1, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);
724fe209ef9SBlaise Bourdin 
725fe209ef9SBlaise Bourdin         }
726fe209ef9SBlaise Bourdin         ierr = ISRestoreIndices(stratumIS, &faces);CHKERRQ(ierr);
727fe209ef9SBlaise Bourdin         ierr = ISDestroy(&stratumIS);CHKERRQ(ierr);
728fe209ef9SBlaise Bourdin       }
729fe209ef9SBlaise Bourdin       ierr = ISRestoreIndices(fsIS, &fsIdx);CHKERRQ(ierr);
730fe209ef9SBlaise Bourdin       ierr = ISDestroy(&fsIS);CHKERRQ(ierr);
731fe209ef9SBlaise Bourdin 
732fe209ef9SBlaise Bourdin       /* Put side sets */
733fe209ef9SBlaise Bourdin       for (fs=0; fs<num_fs; ++fs) {
734*6823f3c5SBlaise Bourdin         PetscStackCallStandard(ex_put_set,(exo->exoid, EX_SIDE_SET, fsIdx[fs], &elem_list[elem_ind[fs]], &side_list[elem_ind[fs]]));
735fe209ef9SBlaise Bourdin       }
736fe209ef9SBlaise Bourdin       ierr = PetscFree3(elem_ind,elem_list,side_list);CHKERRQ(ierr);
737fe209ef9SBlaise Bourdin     }
738*6823f3c5SBlaise Bourdin     /*
739*6823f3c5SBlaise Bourdin       close the exodus file
740*6823f3c5SBlaise Bourdin     */
741*6823f3c5SBlaise Bourdin     ex_close(exo->exoid);
742*6823f3c5SBlaise Bourdin     exo->exoid = -1;
743*6823f3c5SBlaise Bourdin   }
744*6823f3c5SBlaise Bourdin   ierr = PetscSectionDestroy(&coordSection);CHKERRQ(ierr);
745*6823f3c5SBlaise Bourdin 
746*6823f3c5SBlaise Bourdin   /*
747*6823f3c5SBlaise Bourdin     reopen the file in parallel
748*6823f3c5SBlaise Bourdin   */
749*6823f3c5SBlaise Bourdin   EXO_mode = EX_WRITE;
750*6823f3c5SBlaise Bourdin #if defined(PETSC_USE_64BIT_INDICES)
751*6823f3c5SBlaise Bourdin   EXO_mode += EX_ALL_INT64_API;
752*6823f3c5SBlaise Bourdin #endif
753*6823f3c5SBlaise Bourdin   CPU_word_size = sizeof(PetscReal);
754*6823f3c5SBlaise Bourdin   IO_word_size  = sizeof(PetscReal);
755*6823f3c5SBlaise Bourdin   exo->exoid = ex_open_par(exo->filename,EXO_mode,&CPU_word_size,&IO_word_size,&EXO_version,comm,MPI_INFO_NULL);
756*6823f3c5SBlaise Bourdin   if (exo->exoid < 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, "ex_open_par failed for %s", exo->filename);
757*6823f3c5SBlaise Bourdin   PetscFunctionReturn(0);
758*6823f3c5SBlaise Bourdin }
759*6823f3c5SBlaise Bourdin 
760*6823f3c5SBlaise Bourdin /*
761*6823f3c5SBlaise Bourdin   VecView_PlexExodusII_Internal - Write a Vec corresponding in an exodus file
762*6823f3c5SBlaise Bourdin 
763*6823f3c5SBlaise Bourdin   Collective on v
764*6823f3c5SBlaise Bourdin 
765*6823f3c5SBlaise Bourdin   Input Parameters:
766*6823f3c5SBlaise Bourdin + v  - The vector to be written
767*6823f3c5SBlaise Bourdin - viewer - The PetscViewerExodusII viewer associate to an exodus file
768*6823f3c5SBlaise Bourdin 
769*6823f3c5SBlaise Bourdin   Notes:
770*6823f3c5SBlaise Bourdin   The exodus result variable index is obtained by comparing the Vec name and the
771*6823f3c5SBlaise Bourdin   names of variables declared in the exodus file. For instance for a Vec named "V"
772*6823f3c5SBlaise Bourdin   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
773*6823f3c5SBlaise Bourdin   amongst all variables.
774*6823f3c5SBlaise Bourdin   In the event where a nodal and zonal variable both match, the function will return an error instead of
775*6823f3c5SBlaise Bourdin   possibly corrupting the file
776*6823f3c5SBlaise Bourdin 
777*6823f3c5SBlaise Bourdin   Level: beginner
778*6823f3c5SBlaise Bourdin 
779*6823f3c5SBlaise Bourdin .seealso: EXOGetVarIndex_Internal(),DMPlexView_ExodusII(),VecView_PlexExodusII()
780*6823f3c5SBlaise Bourdin @*/
781*6823f3c5SBlaise Bourdin PetscErrorCode VecView_PlexExodusII_Internal(Vec v, PetscViewer viewer)
782*6823f3c5SBlaise Bourdin {
783*6823f3c5SBlaise Bourdin   DM                 dm;
784*6823f3c5SBlaise Bourdin   MPI_Comm           comm;
785*6823f3c5SBlaise Bourdin   PetscMPIInt        rank;
786*6823f3c5SBlaise Bourdin 
787*6823f3c5SBlaise Bourdin 
788*6823f3c5SBlaise Bourdin   int                exoid,offsetN = 0, offsetZ = 0;
789*6823f3c5SBlaise Bourdin   const char        *vecname;
790*6823f3c5SBlaise Bourdin   PetscInt           step;
791*6823f3c5SBlaise Bourdin   PetscErrorCode     ierr;
792*6823f3c5SBlaise Bourdin 
793*6823f3c5SBlaise Bourdin   PetscFunctionBegin;
794*6823f3c5SBlaise Bourdin   ierr = PetscObjectGetComm((PetscObject) v, &comm);CHKERRQ(ierr);
795*6823f3c5SBlaise Bourdin   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
796*6823f3c5SBlaise Bourdin   ierr = PetscViewerExodusIIGetId(viewer,&exoid);CHKERRQ(ierr);
797*6823f3c5SBlaise Bourdin   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
798*6823f3c5SBlaise Bourdin   ierr = PetscObjectGetName((PetscObject) v, &vecname);CHKERRQ(ierr);
799*6823f3c5SBlaise Bourdin 
800*6823f3c5SBlaise Bourdin   ierr = DMGetOutputSequenceNumber(dm,&step,NULL);CHKERRQ(ierr);
801*6823f3c5SBlaise Bourdin   ierr = EXOGetVarIndex_Internal(exoid,EX_NODAL,vecname,&offsetN);CHKERRQ(ierr);
802*6823f3c5SBlaise Bourdin   ierr = EXOGetVarIndex_Internal(exoid,EX_ELEM_BLOCK,vecname,&offsetZ);CHKERRQ(ierr);
803*6823f3c5SBlaise Bourdin   if (offsetN <= 0 && offsetZ <= 0) SETERRQ1(comm, PETSC_ERR_FILE_UNEXPECTED, "Found both nodal and zonal variable %s in exodus file. \n", vecname);
804*6823f3c5SBlaise Bourdin   if (offsetN > 0) {
805*6823f3c5SBlaise Bourdin     ierr = VecViewPlex_ExodusII_Nodal_Internal(v,exoid,(int) step+1,offsetN);CHKERRQ(ierr);
806*6823f3c5SBlaise Bourdin   } else if (offsetZ > 0) {
807*6823f3c5SBlaise Bourdin     ierr = VecViewPlex_ExodusII_Zonal_Internal(v,exoid,(int) step+1,offsetZ);CHKERRQ(ierr);
808*6823f3c5SBlaise Bourdin   } else SETERRQ1(comm, PETSC_ERR_FILE_UNEXPECTED, "Could not find nodal or zonal variable %s in exodus file. \n", vecname);
809*6823f3c5SBlaise Bourdin   PetscFunctionReturn(0);
810*6823f3c5SBlaise Bourdin }
811*6823f3c5SBlaise Bourdin 
812*6823f3c5SBlaise Bourdin /*
813*6823f3c5SBlaise Bourdin   VecLoad_PlexExodusII_Internal - Write a Vec corresponding in an exodus file
814*6823f3c5SBlaise Bourdin 
815*6823f3c5SBlaise Bourdin   Collective on v
816*6823f3c5SBlaise Bourdin 
817*6823f3c5SBlaise Bourdin   Input Parameters:
818*6823f3c5SBlaise Bourdin + v  - The vector to be written
819*6823f3c5SBlaise Bourdin - viewer - The PetscViewerExodusII viewer associate to an exodus file
820*6823f3c5SBlaise Bourdin 
821*6823f3c5SBlaise Bourdin   Notes:
822*6823f3c5SBlaise Bourdin   The exodus result variable index is obtained by comparing the Vec name and the
823*6823f3c5SBlaise Bourdin   names of variables declared in the exodus file. For instance for a Vec named "V"
824*6823f3c5SBlaise Bourdin   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
825*6823f3c5SBlaise Bourdin   amongst all variables.
826*6823f3c5SBlaise Bourdin   In the event where a nodal and zonal variable both match, the function will return an error instead of
827*6823f3c5SBlaise Bourdin   possibly corrupting the file
828*6823f3c5SBlaise Bourdin 
829*6823f3c5SBlaise Bourdin   Level: beginner
830*6823f3c5SBlaise Bourdin 
831*6823f3c5SBlaise Bourdin .seealso: EXOGetVarIndex_Internal(),DMPlexView_ExodusII(),VecView_PlexExodusII()
832*6823f3c5SBlaise Bourdin @*/
833*6823f3c5SBlaise Bourdin PetscErrorCode VecLoad_PlexExodusII_Internal(Vec v, PetscViewer viewer)
834*6823f3c5SBlaise Bourdin {
835*6823f3c5SBlaise Bourdin   DM                 dm;
836*6823f3c5SBlaise Bourdin   MPI_Comm           comm;
837*6823f3c5SBlaise Bourdin   PetscMPIInt        rank;
838*6823f3c5SBlaise Bourdin 
839*6823f3c5SBlaise Bourdin 
840*6823f3c5SBlaise Bourdin   int                exoid,offsetN = 0, offsetZ = 0;
841*6823f3c5SBlaise Bourdin   const char        *vecname;
842*6823f3c5SBlaise Bourdin   PetscInt           step;
843*6823f3c5SBlaise Bourdin   PetscErrorCode     ierr;
844*6823f3c5SBlaise Bourdin 
845*6823f3c5SBlaise Bourdin   PetscFunctionBegin;
846*6823f3c5SBlaise Bourdin   ierr = PetscObjectGetComm((PetscObject) v, &comm);CHKERRQ(ierr);
847*6823f3c5SBlaise Bourdin   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
848*6823f3c5SBlaise Bourdin   ierr = PetscViewerExodusIIGetId(viewer,&exoid);CHKERRQ(ierr);
849*6823f3c5SBlaise Bourdin   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
850*6823f3c5SBlaise Bourdin   ierr = PetscObjectGetName((PetscObject) v, &vecname);CHKERRQ(ierr);
851*6823f3c5SBlaise Bourdin 
852*6823f3c5SBlaise Bourdin   ierr = DMGetOutputSequenceNumber(dm,&step,NULL);CHKERRQ(ierr);
853*6823f3c5SBlaise Bourdin   ierr = EXOGetVarIndex_Internal(exoid,EX_NODAL,vecname,&offsetN);CHKERRQ(ierr);
854*6823f3c5SBlaise Bourdin   ierr = EXOGetVarIndex_Internal(exoid,EX_ELEM_BLOCK,vecname,&offsetZ);CHKERRQ(ierr);
855*6823f3c5SBlaise Bourdin   if (offsetN <= 0 && offsetZ <= 0) SETERRQ1(comm, PETSC_ERR_FILE_UNEXPECTED, "Found both nodal and zonal variable %s in exodus file. \n", vecname);
856*6823f3c5SBlaise Bourdin   if (offsetN > 0) {
857*6823f3c5SBlaise Bourdin     ierr = VecLoadPlex_ExodusII_Nodal_Internal(v,exoid,(int) step+1,offsetN);CHKERRQ(ierr);
858*6823f3c5SBlaise Bourdin   } else if (offsetZ > 0) {
859*6823f3c5SBlaise Bourdin     ierr = VecLoadPlex_ExodusII_Zonal_Internal(v,exoid,(int) step+1,offsetZ);CHKERRQ(ierr);
860*6823f3c5SBlaise Bourdin   } else SETERRQ1(comm, PETSC_ERR_FILE_UNEXPECTED, "Could not find nodal or zonal variable %s in exodus file. \n", vecname);
86178569bb4SMatthew G. Knepley   PetscFunctionReturn(0);
86278569bb4SMatthew G. Knepley }
86378569bb4SMatthew G. Knepley 
86478569bb4SMatthew G. Knepley /*
86578569bb4SMatthew G. Knepley   VecViewPlex_ExodusII_Nodal_Internal - Write a Vec corresponding to a nodal field to an exodus file
86678569bb4SMatthew G. Knepley 
86778569bb4SMatthew G. Knepley   Collective on v
86878569bb4SMatthew G. Knepley 
86978569bb4SMatthew G. Knepley   Input Parameters:
87078569bb4SMatthew G. Knepley + v  - The vector to be written
87178569bb4SMatthew G. Knepley . exoid - the exodus id of a file (obtained from ex_open or ex_create for instance)
872*6823f3c5SBlaise Bourdin . step - the time step to write at (exodus steps are numbered starting from 1)
873*6823f3c5SBlaise Bourdin - offset - the location of the variable in the file
87478569bb4SMatthew G. Knepley 
87578569bb4SMatthew G. Knepley   Notes:
87678569bb4SMatthew G. Knepley   The exodus result nodal variable index is obtained by comparing the Vec name and the
87778569bb4SMatthew G. Knepley   names of nodal variables declared in the exodus file. For instance for a Vec named "V"
87878569bb4SMatthew G. Knepley   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
87978569bb4SMatthew G. Knepley   amongst all nodal variables.
88078569bb4SMatthew G. Knepley 
88178569bb4SMatthew G. Knepley   Level: beginner
88278569bb4SMatthew G. Knepley 
883*6823f3c5SBlaise Bourdin .seealso: EXOGetVarIndex_Internal(),DMPlexView_ExodusII_Internal(),VecLoadNodal_PlexEXO(),VecViewZonal_PlexEXO(),VecLoadZonal_PlexEXO()
88478569bb4SMatthew G. Knepley @*/
885*6823f3c5SBlaise Bourdin PetscErrorCode VecViewPlex_ExodusII_Nodal_Internal(Vec v, int exoid, int step, int offset)
88678569bb4SMatthew G. Knepley {
88778569bb4SMatthew G. Knepley   MPI_Comm           comm;
88878569bb4SMatthew G. Knepley   PetscMPIInt        size;
88978569bb4SMatthew G. Knepley   DM                 dm;
89078569bb4SMatthew G. Knepley   Vec                vNatural, vComp;
89122a7544eSVaclav Hapla   const PetscScalar *varray;
89278569bb4SMatthew G. Knepley   PetscInt           xs, xe, bs;
89378569bb4SMatthew G. Knepley   PetscBool          useNatural;
89478569bb4SMatthew G. Knepley   PetscErrorCode     ierr;
89578569bb4SMatthew G. Knepley 
89678569bb4SMatthew G. Knepley   PetscFunctionBegin;
89778569bb4SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) v, &comm);CHKERRQ(ierr);
898ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
89978569bb4SMatthew G. Knepley   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
90078569bb4SMatthew G. Knepley   ierr = DMGetUseNatural(dm, &useNatural);CHKERRQ(ierr);
90178569bb4SMatthew G. Knepley   useNatural = useNatural && size > 1 ? PETSC_TRUE : PETSC_FALSE;
90278569bb4SMatthew G. Knepley   if (useNatural) {
90378569bb4SMatthew G. Knepley     ierr = DMGetGlobalVector(dm, &vNatural);CHKERRQ(ierr);
90478569bb4SMatthew G. Knepley     ierr = DMPlexGlobalToNaturalBegin(dm, v, vNatural);CHKERRQ(ierr);
90578569bb4SMatthew G. Knepley     ierr = DMPlexGlobalToNaturalEnd(dm, v, vNatural);CHKERRQ(ierr);
90678569bb4SMatthew G. Knepley   } else {
90778569bb4SMatthew G. Knepley     vNatural = v;
90878569bb4SMatthew G. Knepley   }
909*6823f3c5SBlaise Bourdin 
91078569bb4SMatthew G. Knepley   /* Write local chunk of the result in the exodus file
91178569bb4SMatthew G. Knepley      exodus stores each component of a vector-valued field as a separate variable.
91278569bb4SMatthew G. Knepley      We assume that they are stored sequentially */
91378569bb4SMatthew G. Knepley   ierr = VecGetOwnershipRange(vNatural, &xs, &xe);CHKERRQ(ierr);
91478569bb4SMatthew G. Knepley   ierr = VecGetBlockSize(vNatural, &bs);CHKERRQ(ierr);
91578569bb4SMatthew G. Knepley   if (bs == 1) {
91678569bb4SMatthew G. Knepley     ierr = VecGetArrayRead(vNatural, &varray);CHKERRQ(ierr);
9176de834b4SMatthew G. Knepley     PetscStackCallStandard(ex_put_partial_var,(exoid, step, EX_NODAL, offset, 1, xs+1, xe-xs, varray));
91878569bb4SMatthew G. Knepley     ierr = VecRestoreArrayRead(vNatural, &varray);CHKERRQ(ierr);
91978569bb4SMatthew G. Knepley   } else {
92078569bb4SMatthew G. Knepley     IS       compIS;
92178569bb4SMatthew G. Knepley     PetscInt c;
92278569bb4SMatthew G. Knepley 
92394a2d30dSStefano Zampini     ierr = ISCreateStride(comm, (xe-xs)/bs, xs, bs, &compIS);CHKERRQ(ierr);
92478569bb4SMatthew G. Knepley     for (c = 0; c < bs; ++c) {
92578569bb4SMatthew G. Knepley       ierr = ISStrideSetStride(compIS, (xe-xs)/bs, xs+c, bs);CHKERRQ(ierr);
92678569bb4SMatthew G. Knepley       ierr = VecGetSubVector(vNatural, compIS, &vComp);CHKERRQ(ierr);
92778569bb4SMatthew G. Knepley       ierr = VecGetArrayRead(vComp, &varray);CHKERRQ(ierr);
9286de834b4SMatthew G. Knepley       PetscStackCallStandard(ex_put_partial_var,(exoid, step, EX_NODAL, offset+c, 1, xs/bs+1, (xe-xs)/bs, varray));
92978569bb4SMatthew G. Knepley       ierr = VecRestoreArrayRead(vComp, &varray);CHKERRQ(ierr);
93078569bb4SMatthew G. Knepley       ierr = VecRestoreSubVector(vNatural, compIS, &vComp);CHKERRQ(ierr);
93178569bb4SMatthew G. Knepley     }
93278569bb4SMatthew G. Knepley     ierr = ISDestroy(&compIS);CHKERRQ(ierr);
93378569bb4SMatthew G. Knepley   }
93478569bb4SMatthew G. Knepley   if (useNatural) {ierr = DMRestoreGlobalVector(dm, &vNatural);CHKERRQ(ierr);}
93578569bb4SMatthew G. Knepley   PetscFunctionReturn(0);
93678569bb4SMatthew G. Knepley }
93778569bb4SMatthew G. Knepley 
93878569bb4SMatthew G. Knepley /*
93978569bb4SMatthew G. Knepley   VecLoadPlex_ExodusII_Nodal_Internal - Read a Vec corresponding to a nodal field from an exodus file
94078569bb4SMatthew G. Knepley 
94178569bb4SMatthew G. Knepley   Collective on v
94278569bb4SMatthew G. Knepley 
94378569bb4SMatthew G. Knepley   Input Parameters:
94478569bb4SMatthew G. Knepley + v  - The vector to be written
94578569bb4SMatthew G. Knepley . exoid - the exodus id of a file (obtained from ex_open or ex_create for instance)
946*6823f3c5SBlaise Bourdin . step - the time step to read at (exodus steps are numbered starting from 1)
947*6823f3c5SBlaise Bourdin - offset - the location of the variable in the file
94878569bb4SMatthew G. Knepley 
94978569bb4SMatthew G. Knepley   Notes:
95078569bb4SMatthew G. Knepley   The exodus result nodal variable index is obtained by comparing the Vec name and the
95178569bb4SMatthew G. Knepley   names of nodal variables declared in the exodus file. For instance for a Vec named "V"
95278569bb4SMatthew G. Knepley   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
95378569bb4SMatthew G. Knepley   amongst all nodal variables.
95478569bb4SMatthew G. Knepley 
95578569bb4SMatthew G. Knepley   Level: beginner
95678569bb4SMatthew G. Knepley 
957*6823f3c5SBlaise Bourdin .seealso: EXOGetVarIndex_Internal(), DMPlexView_ExodusII_Internal(), VecViewPlex_ExodusII_Nodal_Internal(), VecViewZonal_PlexEXO(), VecLoadZonal_PlexEXO()
95878569bb4SMatthew G. Knepley */
959*6823f3c5SBlaise Bourdin PetscErrorCode VecLoadPlex_ExodusII_Nodal_Internal(Vec v, int exoid, int step, int offset)
96078569bb4SMatthew G. Knepley {
96178569bb4SMatthew G. Knepley   MPI_Comm       comm;
96278569bb4SMatthew G. Knepley   PetscMPIInt    size;
96378569bb4SMatthew G. Knepley   DM             dm;
96478569bb4SMatthew G. Knepley   Vec            vNatural, vComp;
96522a7544eSVaclav Hapla   PetscScalar   *varray;
96678569bb4SMatthew G. Knepley   PetscInt       xs, xe, bs;
96778569bb4SMatthew G. Knepley   PetscBool      useNatural;
96878569bb4SMatthew G. Knepley   PetscErrorCode ierr;
96978569bb4SMatthew G. Knepley 
97078569bb4SMatthew G. Knepley   PetscFunctionBegin;
97178569bb4SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) v, &comm);CHKERRQ(ierr);
972ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
97378569bb4SMatthew G. Knepley   ierr = VecGetDM(v,&dm);CHKERRQ(ierr);
97478569bb4SMatthew G. Knepley   ierr = DMGetUseNatural(dm, &useNatural);CHKERRQ(ierr);
97578569bb4SMatthew G. Knepley   useNatural = useNatural && size > 1 ? PETSC_TRUE : PETSC_FALSE;
97678569bb4SMatthew G. Knepley   if (useNatural) {ierr = DMGetGlobalVector(dm,&vNatural);CHKERRQ(ierr);}
97778569bb4SMatthew G. Knepley   else            {vNatural = v;}
978*6823f3c5SBlaise Bourdin 
97978569bb4SMatthew G. Knepley   /* Read local chunk from the file */
98078569bb4SMatthew G. Knepley   ierr = VecGetOwnershipRange(vNatural, &xs, &xe);CHKERRQ(ierr);
98178569bb4SMatthew G. Knepley   ierr = VecGetBlockSize(vNatural, &bs);CHKERRQ(ierr);
98278569bb4SMatthew G. Knepley   if (bs == 1) {
98378569bb4SMatthew G. Knepley     ierr = VecGetArray(vNatural, &varray);CHKERRQ(ierr);
9846de834b4SMatthew G. Knepley     PetscStackCallStandard(ex_get_partial_var,(exoid, step, EX_NODAL, offset, 1, xs+1, xe-xs, varray));
98578569bb4SMatthew G. Knepley     ierr = VecRestoreArray(vNatural, &varray);CHKERRQ(ierr);
98678569bb4SMatthew G. Knepley   } else {
98778569bb4SMatthew G. Knepley     IS       compIS;
98878569bb4SMatthew G. Knepley     PetscInt c;
98978569bb4SMatthew G. Knepley 
99094a2d30dSStefano Zampini     ierr = ISCreateStride(comm, (xe-xs)/bs, xs, bs, &compIS);CHKERRQ(ierr);
99178569bb4SMatthew G. Knepley     for (c = 0; c < bs; ++c) {
99278569bb4SMatthew G. Knepley       ierr = ISStrideSetStride(compIS, (xe-xs)/bs, xs+c, bs);CHKERRQ(ierr);
99378569bb4SMatthew G. Knepley       ierr = VecGetSubVector(vNatural, compIS, &vComp);CHKERRQ(ierr);
99478569bb4SMatthew G. Knepley       ierr = VecGetArray(vComp, &varray);CHKERRQ(ierr);
9956de834b4SMatthew G. Knepley       PetscStackCallStandard(ex_get_partial_var,(exoid, step, EX_NODAL, offset+c, 1, xs/bs+1, (xe-xs)/bs, varray));
99678569bb4SMatthew G. Knepley       ierr = VecRestoreArray(vComp, &varray);CHKERRQ(ierr);
99778569bb4SMatthew G. Knepley       ierr = VecRestoreSubVector(vNatural, compIS, &vComp);CHKERRQ(ierr);
99878569bb4SMatthew G. Knepley     }
99978569bb4SMatthew G. Knepley     ierr = ISDestroy(&compIS);CHKERRQ(ierr);
100078569bb4SMatthew G. Knepley   }
100178569bb4SMatthew G. Knepley   if (useNatural) {
100278569bb4SMatthew G. Knepley     ierr = DMPlexNaturalToGlobalBegin(dm, vNatural, v);CHKERRQ(ierr);
100378569bb4SMatthew G. Knepley     ierr = DMPlexNaturalToGlobalEnd(dm, vNatural, v);CHKERRQ(ierr);
100478569bb4SMatthew G. Knepley     ierr = DMRestoreGlobalVector(dm, &vNatural);CHKERRQ(ierr);
100578569bb4SMatthew G. Knepley   }
100678569bb4SMatthew G. Knepley   PetscFunctionReturn(0);
100778569bb4SMatthew G. Knepley }
100878569bb4SMatthew G. Knepley 
100978569bb4SMatthew G. Knepley /*
101078569bb4SMatthew G. Knepley   VecViewPlex_ExodusII_Zonal_Internal - Write a Vec corresponding to a zonal (cell based) field to an exodus file
101178569bb4SMatthew G. Knepley 
101278569bb4SMatthew G. Knepley   Collective on v
101378569bb4SMatthew G. Knepley 
101478569bb4SMatthew G. Knepley   Input Parameters:
101578569bb4SMatthew G. Knepley + v  - The vector to be written
101678569bb4SMatthew G. Knepley . exoid - the exodus id of a file (obtained from ex_open or ex_create for instance)
1017*6823f3c5SBlaise Bourdin . step - the time step to write at (exodus steps are numbered starting from 1)
1018*6823f3c5SBlaise Bourdin - offset - the location of the variable in the file
101978569bb4SMatthew G. Knepley 
102078569bb4SMatthew G. Knepley   Notes:
102178569bb4SMatthew G. Knepley   The exodus result zonal variable index is obtained by comparing the Vec name and the
102278569bb4SMatthew G. Knepley   names of zonal variables declared in the exodus file. For instance for a Vec named "V"
102378569bb4SMatthew G. Knepley   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
102478569bb4SMatthew G. Knepley   amongst all zonal variables.
102578569bb4SMatthew G. Knepley 
102678569bb4SMatthew G. Knepley   Level: beginner
102778569bb4SMatthew G. Knepley 
1028*6823f3c5SBlaise Bourdin .seealso: EXOGetVarIndex_Internal(),DMPlexView_ExodusII_Internal(),VecViewPlex_ExodusII_Nodal_Internal(),VecLoadPlex_ExodusII_Nodal_Internal(),VecLoadPlex_ExodusII_Zonal_Internal()
102978569bb4SMatthew G. Knepley */
1030*6823f3c5SBlaise Bourdin PetscErrorCode VecViewPlex_ExodusII_Zonal_Internal(Vec v, int exoid, int step, int offset)
103178569bb4SMatthew G. Knepley {
103278569bb4SMatthew G. Knepley   MPI_Comm          comm;
103378569bb4SMatthew G. Knepley   PetscMPIInt       size;
103478569bb4SMatthew G. Knepley   DM                dm;
103578569bb4SMatthew G. Knepley   Vec               vNatural, vComp;
103622a7544eSVaclav Hapla   const PetscScalar *varray;
103778569bb4SMatthew G. Knepley   PetscInt          xs, xe, bs;
103878569bb4SMatthew G. Knepley   PetscBool         useNatural;
103978569bb4SMatthew G. Knepley   IS                compIS;
104078569bb4SMatthew G. Knepley   PetscInt         *csSize, *csID;
104178569bb4SMatthew G. Knepley   PetscInt          numCS, set, csxs = 0;
104278569bb4SMatthew G. Knepley   PetscErrorCode    ierr;
104378569bb4SMatthew G. Knepley 
104478569bb4SMatthew G. Knepley   PetscFunctionBegin;
104578569bb4SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject)v, &comm);CHKERRQ(ierr);
1046ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
104778569bb4SMatthew G. Knepley   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
104878569bb4SMatthew G. Knepley   ierr = DMGetUseNatural(dm, &useNatural);CHKERRQ(ierr);
104978569bb4SMatthew G. Knepley   useNatural = useNatural && size > 1 ? PETSC_TRUE : PETSC_FALSE;
105078569bb4SMatthew G. Knepley   if (useNatural) {
105178569bb4SMatthew G. Knepley     ierr = DMGetGlobalVector(dm, &vNatural);CHKERRQ(ierr);
105278569bb4SMatthew G. Knepley     ierr = DMPlexGlobalToNaturalBegin(dm, v, vNatural);CHKERRQ(ierr);
105378569bb4SMatthew G. Knepley     ierr = DMPlexGlobalToNaturalEnd(dm, v, vNatural);CHKERRQ(ierr);
105478569bb4SMatthew G. Knepley   } else {
105578569bb4SMatthew G. Knepley     vNatural = v;
105678569bb4SMatthew G. Knepley   }
1057*6823f3c5SBlaise Bourdin 
105878569bb4SMatthew G. Knepley   /* Write local chunk of the result in the exodus file
105978569bb4SMatthew G. Knepley      exodus stores each component of a vector-valued field as a separate variable.
106078569bb4SMatthew G. Knepley      We assume that they are stored sequentially
106178569bb4SMatthew G. Knepley      Zonal variables are accessed one element block at a time, so we loop through the cell sets,
106278569bb4SMatthew G. Knepley      but once the vector has been reordered to natural size, we cannot use the label informations
106378569bb4SMatthew G. Knepley      to figure out what to save where. */
106478569bb4SMatthew G. Knepley   numCS = ex_inquire_int(exoid, EX_INQ_ELEM_BLK);
106578569bb4SMatthew G. Knepley   ierr = PetscMalloc2(numCS, &csID, numCS, &csSize);CHKERRQ(ierr);
10666de834b4SMatthew G. Knepley   PetscStackCallStandard(ex_get_ids,(exoid, EX_ELEM_BLOCK, csID));
106778569bb4SMatthew G. Knepley   for (set = 0; set < numCS; ++set) {
106878569bb4SMatthew G. Knepley     ex_block block;
106978569bb4SMatthew G. Knepley 
107078569bb4SMatthew G. Knepley     block.id   = csID[set];
107178569bb4SMatthew G. Knepley     block.type = EX_ELEM_BLOCK;
10726de834b4SMatthew G. Knepley     PetscStackCallStandard(ex_get_block_param,(exoid, &block));
107378569bb4SMatthew G. Knepley     csSize[set] = block.num_entry;
107478569bb4SMatthew G. Knepley   }
107578569bb4SMatthew G. Knepley   ierr = VecGetOwnershipRange(vNatural, &xs, &xe);CHKERRQ(ierr);
107678569bb4SMatthew G. Knepley   ierr = VecGetBlockSize(vNatural, &bs);CHKERRQ(ierr);
107778569bb4SMatthew G. Knepley   if (bs > 1) {ierr = ISCreateStride(comm, (xe-xs)/bs, xs, bs, &compIS);CHKERRQ(ierr);}
107878569bb4SMatthew G. Knepley   for (set = 0; set < numCS; set++) {
107978569bb4SMatthew G. Knepley     PetscInt csLocalSize, c;
108078569bb4SMatthew G. Knepley 
108178569bb4SMatthew G. Knepley     /* range of indices for set setID[set]: csxs:csxs + csSize[set]-1
108278569bb4SMatthew G. Knepley        local slice of zonal values:         xs/bs,xm/bs-1
108378569bb4SMatthew G. Knepley        intersection:                        max(xs/bs,csxs),min(xm/bs-1,csxs + csSize[set]-1) */
108478569bb4SMatthew G. Knepley     csLocalSize = PetscMax(0, PetscMin(xe/bs, csxs+csSize[set]) - PetscMax(xs/bs, csxs));
108578569bb4SMatthew G. Knepley     if (bs == 1) {
108678569bb4SMatthew G. Knepley       ierr = VecGetArrayRead(vNatural, &varray);CHKERRQ(ierr);
10876de834b4SMatthew G. Knepley       PetscStackCallStandard(ex_put_partial_var,(exoid, step, EX_ELEM_BLOCK, offset, csID[set], PetscMax(xs-csxs, 0)+1, csLocalSize, &varray[PetscMax(0, csxs-xs)]));
108878569bb4SMatthew G. Knepley       ierr = VecRestoreArrayRead(vNatural, &varray);CHKERRQ(ierr);
108978569bb4SMatthew G. Knepley     } else {
109078569bb4SMatthew G. Knepley       for (c = 0; c < bs; ++c) {
109178569bb4SMatthew G. Knepley         ierr = ISStrideSetStride(compIS, (xe-xs)/bs, xs+c, bs);CHKERRQ(ierr);
109278569bb4SMatthew G. Knepley         ierr = VecGetSubVector(vNatural, compIS, &vComp);CHKERRQ(ierr);
109378569bb4SMatthew G. Knepley         ierr = VecGetArrayRead(vComp, &varray);CHKERRQ(ierr);
10946de834b4SMatthew G. Knepley         PetscStackCallStandard(ex_put_partial_var,(exoid, step, EX_ELEM_BLOCK, offset+c, csID[set], PetscMax(xs/bs-csxs, 0)+1, csLocalSize, &varray[PetscMax(0, csxs-xs/bs)]));
109578569bb4SMatthew G. Knepley         ierr = VecRestoreArrayRead(vComp, &varray);CHKERRQ(ierr);
109678569bb4SMatthew G. Knepley         ierr = VecRestoreSubVector(vNatural, compIS, &vComp);CHKERRQ(ierr);
109778569bb4SMatthew G. Knepley       }
109878569bb4SMatthew G. Knepley     }
109978569bb4SMatthew G. Knepley     csxs += csSize[set];
110078569bb4SMatthew G. Knepley   }
110178569bb4SMatthew G. Knepley   ierr = PetscFree2(csID, csSize);CHKERRQ(ierr);
110278569bb4SMatthew G. Knepley   if (bs > 1) {ierr = ISDestroy(&compIS);CHKERRQ(ierr);}
110378569bb4SMatthew G. Knepley   if (useNatural) {ierr = DMRestoreGlobalVector(dm,&vNatural);CHKERRQ(ierr);}
110478569bb4SMatthew G. Knepley   PetscFunctionReturn(0);
110578569bb4SMatthew G. Knepley }
110678569bb4SMatthew G. Knepley 
110778569bb4SMatthew G. Knepley /*
110878569bb4SMatthew G. Knepley   VecLoadPlex_ExodusII_Zonal_Internal - Read a Vec corresponding to a zonal (cell based) field from an exodus file
110978569bb4SMatthew G. Knepley 
111078569bb4SMatthew G. Knepley   Collective on v
111178569bb4SMatthew G. Knepley 
111278569bb4SMatthew G. Knepley   Input Parameters:
111378569bb4SMatthew G. Knepley + v  - The vector to be written
111478569bb4SMatthew G. Knepley . exoid - the exodus id of a file (obtained from ex_open or ex_create for instance)
1115*6823f3c5SBlaise Bourdin . step - the time step to read at (exodus steps are numbered starting from 1)
1116*6823f3c5SBlaise Bourdin - offset - the location of the variable in the file
111778569bb4SMatthew G. Knepley 
111878569bb4SMatthew G. Knepley   Notes:
111978569bb4SMatthew G. Knepley   The exodus result zonal variable index is obtained by comparing the Vec name and the
112078569bb4SMatthew G. Knepley   names of zonal variables declared in the exodus file. For instance for a Vec named "V"
112178569bb4SMatthew G. Knepley   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
112278569bb4SMatthew G. Knepley   amongst all zonal variables.
112378569bb4SMatthew G. Knepley 
112478569bb4SMatthew G. Knepley   Level: beginner
112578569bb4SMatthew G. Knepley 
1126*6823f3c5SBlaise Bourdin .seealso: EXOGetVarIndex_Internal(), DMPlexView_ExodusII_Internal(), VecViewPlex_ExodusII_Nodal_Internal(), VecLoadPlex_ExodusII_Nodal_Internal(), VecLoadPlex_ExodusII_Zonal_Internal()
112778569bb4SMatthew G. Knepley */
1128*6823f3c5SBlaise Bourdin PetscErrorCode VecLoadPlex_ExodusII_Zonal_Internal(Vec v, int exoid, int step, int offset)
112978569bb4SMatthew G. Knepley {
113078569bb4SMatthew G. Knepley   MPI_Comm          comm;
113178569bb4SMatthew G. Knepley   PetscMPIInt       size;
113278569bb4SMatthew G. Knepley   DM                dm;
113378569bb4SMatthew G. Knepley   Vec               vNatural, vComp;
113422a7544eSVaclav Hapla   PetscScalar      *varray;
113578569bb4SMatthew G. Knepley   PetscInt          xs, xe, bs;
113678569bb4SMatthew G. Knepley   PetscBool         useNatural;
113778569bb4SMatthew G. Knepley   IS                compIS;
113878569bb4SMatthew G. Knepley   PetscInt         *csSize, *csID;
113978569bb4SMatthew G. Knepley   PetscInt          numCS, set, csxs = 0;
114078569bb4SMatthew G. Knepley   PetscErrorCode    ierr;
114178569bb4SMatthew G. Knepley 
114278569bb4SMatthew G. Knepley   PetscFunctionBegin;
114378569bb4SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject)v,&comm);CHKERRQ(ierr);
1144ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
114578569bb4SMatthew G. Knepley   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
114678569bb4SMatthew G. Knepley   ierr = DMGetUseNatural(dm, &useNatural);CHKERRQ(ierr);
114778569bb4SMatthew G. Knepley   useNatural = useNatural && size > 1 ? PETSC_TRUE : PETSC_FALSE;
114878569bb4SMatthew G. Knepley   if (useNatural) {ierr = DMGetGlobalVector(dm,&vNatural);CHKERRQ(ierr);}
114978569bb4SMatthew G. Knepley   else            {vNatural = v;}
1150*6823f3c5SBlaise Bourdin 
115178569bb4SMatthew G. Knepley   /* Read local chunk of the result in the exodus file
115278569bb4SMatthew G. Knepley      exodus stores each component of a vector-valued field as a separate variable.
115378569bb4SMatthew G. Knepley      We assume that they are stored sequentially
115478569bb4SMatthew G. Knepley      Zonal variables are accessed one element block at a time, so we loop through the cell sets,
115578569bb4SMatthew G. Knepley      but once the vector has been reordered to natural size, we cannot use the label informations
115678569bb4SMatthew G. Knepley      to figure out what to save where. */
115778569bb4SMatthew G. Knepley   numCS = ex_inquire_int(exoid, EX_INQ_ELEM_BLK);
115878569bb4SMatthew G. Knepley   ierr = PetscMalloc2(numCS, &csID, numCS, &csSize);CHKERRQ(ierr);
11596de834b4SMatthew G. Knepley   PetscStackCallStandard(ex_get_ids,(exoid, EX_ELEM_BLOCK, csID));
116078569bb4SMatthew G. Knepley   for (set = 0; set < numCS; ++set) {
116178569bb4SMatthew G. Knepley     ex_block block;
116278569bb4SMatthew G. Knepley 
116378569bb4SMatthew G. Knepley     block.id   = csID[set];
116478569bb4SMatthew G. Knepley     block.type = EX_ELEM_BLOCK;
11656de834b4SMatthew G. Knepley     PetscStackCallStandard(ex_get_block_param,(exoid, &block));
116678569bb4SMatthew G. Knepley     csSize[set] = block.num_entry;
116778569bb4SMatthew G. Knepley   }
116878569bb4SMatthew G. Knepley   ierr = VecGetOwnershipRange(vNatural, &xs, &xe);CHKERRQ(ierr);
116978569bb4SMatthew G. Knepley   ierr = VecGetBlockSize(vNatural, &bs);CHKERRQ(ierr);
117078569bb4SMatthew G. Knepley   if (bs > 1) {ierr = ISCreateStride(comm, (xe-xs)/bs, xs, bs, &compIS);CHKERRQ(ierr);}
117178569bb4SMatthew G. Knepley   for (set = 0; set < numCS; ++set) {
117278569bb4SMatthew G. Knepley     PetscInt csLocalSize, c;
117378569bb4SMatthew G. Knepley 
117478569bb4SMatthew G. Knepley     /* range of indices for set setID[set]: csxs:csxs + csSize[set]-1
117578569bb4SMatthew G. Knepley        local slice of zonal values:         xs/bs,xm/bs-1
117678569bb4SMatthew G. Knepley        intersection:                        max(xs/bs,csxs),min(xm/bs-1,csxs + csSize[set]-1) */
117778569bb4SMatthew G. Knepley     csLocalSize = PetscMax(0, PetscMin(xe/bs, csxs+csSize[set]) - PetscMax(xs/bs, csxs));
117878569bb4SMatthew G. Knepley     if (bs == 1) {
117978569bb4SMatthew G. Knepley       ierr = VecGetArray(vNatural, &varray);CHKERRQ(ierr);
11806de834b4SMatthew G. Knepley       PetscStackCallStandard(ex_get_partial_var,(exoid, step, EX_ELEM_BLOCK, offset, csID[set], PetscMax(xs-csxs, 0)+1, csLocalSize, &varray[PetscMax(0, csxs-xs)]));
118178569bb4SMatthew G. Knepley       ierr = VecRestoreArray(vNatural, &varray);CHKERRQ(ierr);
118278569bb4SMatthew G. Knepley     } else {
118378569bb4SMatthew G. Knepley       for (c = 0; c < bs; ++c) {
118478569bb4SMatthew G. Knepley         ierr = ISStrideSetStride(compIS, (xe-xs)/bs, xs+c, bs);CHKERRQ(ierr);
118578569bb4SMatthew G. Knepley         ierr = VecGetSubVector(vNatural, compIS, &vComp);CHKERRQ(ierr);
118678569bb4SMatthew G. Knepley         ierr = VecGetArray(vComp, &varray);CHKERRQ(ierr);
11876de834b4SMatthew G. Knepley         PetscStackCallStandard(ex_get_partial_var,(exoid, step, EX_ELEM_BLOCK, offset+c, csID[set], PetscMax(xs/bs-csxs, 0)+1, csLocalSize, &varray[PetscMax(0, csxs-xs/bs)]));
118878569bb4SMatthew G. Knepley         ierr = VecRestoreArray(vComp, &varray);CHKERRQ(ierr);
118978569bb4SMatthew G. Knepley         ierr = VecRestoreSubVector(vNatural, compIS, &vComp);CHKERRQ(ierr);
119078569bb4SMatthew G. Knepley       }
119178569bb4SMatthew G. Knepley     }
119278569bb4SMatthew G. Knepley     csxs += csSize[set];
119378569bb4SMatthew G. Knepley   }
119478569bb4SMatthew G. Knepley   ierr = PetscFree2(csID, csSize);CHKERRQ(ierr);
119578569bb4SMatthew G. Knepley   if (bs > 1) {ierr = ISDestroy(&compIS);CHKERRQ(ierr);}
119678569bb4SMatthew G. Knepley   if (useNatural) {
119778569bb4SMatthew G. Knepley     ierr = DMPlexNaturalToGlobalBegin(dm, vNatural, v);CHKERRQ(ierr);
119878569bb4SMatthew G. Knepley     ierr = DMPlexNaturalToGlobalEnd(dm, vNatural, v);CHKERRQ(ierr);
119978569bb4SMatthew G. Knepley     ierr = DMRestoreGlobalVector(dm, &vNatural);CHKERRQ(ierr);
120078569bb4SMatthew G. Knepley   }
120178569bb4SMatthew G. Knepley   PetscFunctionReturn(0);
120278569bb4SMatthew G. Knepley }
1203b53c8456SSatish Balay #endif
120478569bb4SMatthew G. Knepley 
12051e50132fSMatthew G. Knepley /*@
12061e50132fSMatthew G. Knepley   PetscViewerExodusIIGetId - Get the file id of the ExodusII file
12071e50132fSMatthew G. Knepley 
12081e50132fSMatthew G. Knepley   Logically Collective on PetscViewer
12091e50132fSMatthew G. Knepley 
12101e50132fSMatthew G. Knepley   Input Parameter:
12111e50132fSMatthew G. Knepley .  viewer - the PetscViewer
12121e50132fSMatthew G. Knepley 
12131e50132fSMatthew G. Knepley   Output Parameter:
12141e50132fSMatthew G. Knepley -  exoid - The ExodusII file id
12151e50132fSMatthew G. Knepley 
12161e50132fSMatthew G. Knepley   Level: intermediate
12171e50132fSMatthew G. Knepley 
12181e50132fSMatthew G. Knepley .seealso: PetscViewerFileSetMode(), PetscViewerCreate(), PetscViewerSetType(), PetscViewerBinaryOpen()
12191e50132fSMatthew G. Knepley @*/
12201e50132fSMatthew G. Knepley PetscErrorCode PetscViewerExodusIIGetId(PetscViewer viewer, int *exoid)
12211e50132fSMatthew G. Knepley {
12221e50132fSMatthew G. Knepley   PetscErrorCode ierr;
12231e50132fSMatthew G. Knepley 
12241e50132fSMatthew G. Knepley   PetscFunctionBegin;
12251e50132fSMatthew G. Knepley   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
1226*6823f3c5SBlaise Bourdin   ierr = PetscTryMethod(viewer, "PetscViewerGetId_C",(PetscViewer,int*),(viewer,exoid));CHKERRQ(ierr);
1227*6823f3c5SBlaise Bourdin   PetscFunctionReturn(0);
1228*6823f3c5SBlaise Bourdin }
1229*6823f3c5SBlaise Bourdin 
1230*6823f3c5SBlaise Bourdin 
1231*6823f3c5SBlaise Bourdin 
1232*6823f3c5SBlaise Bourdin /*@
1233*6823f3c5SBlaise Bourdin    PetscViewerExodusIISetOrder - Set the elements order in the exodusII file.
1234*6823f3c5SBlaise Bourdin 
1235*6823f3c5SBlaise Bourdin    Collective
1236*6823f3c5SBlaise Bourdin 
1237*6823f3c5SBlaise Bourdin    Input Parameters:
1238*6823f3c5SBlaise Bourdin +  viewer - the viewer
1239*6823f3c5SBlaise Bourdin .  order - elements order
1240*6823f3c5SBlaise Bourdin 
1241*6823f3c5SBlaise Bourdin    Output Parameter:
1242*6823f3c5SBlaise Bourdin 
1243*6823f3c5SBlaise Bourdin    Level: beginner
1244*6823f3c5SBlaise Bourdin 
1245*6823f3c5SBlaise Bourdin    Note:
1246*6823f3c5SBlaise Bourdin 
1247*6823f3c5SBlaise Bourdin 
1248*6823f3c5SBlaise Bourdin .seealso: PetscViewerExodusIIGetId(), PetscViewerExodusIIGetOrder(), PetscViewerExodusIISetOrder()
1249*6823f3c5SBlaise Bourdin @*/
1250*6823f3c5SBlaise Bourdin PetscErrorCode PetscViewerExodusIISetOrder(PetscViewer viewer, PetscInt order)
1251*6823f3c5SBlaise Bourdin {
1252*6823f3c5SBlaise Bourdin   PetscErrorCode ierr;
1253*6823f3c5SBlaise Bourdin 
1254*6823f3c5SBlaise Bourdin   PetscFunctionBegin;
1255*6823f3c5SBlaise Bourdin   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
1256*6823f3c5SBlaise Bourdin   ierr = PetscTryMethod(viewer, "PetscViewerSetOrder_C",(PetscViewer,PetscInt),(viewer,order));CHKERRQ(ierr);
1257*6823f3c5SBlaise Bourdin   PetscFunctionReturn(0);
1258*6823f3c5SBlaise Bourdin }
1259*6823f3c5SBlaise Bourdin 
1260*6823f3c5SBlaise Bourdin /*@
1261*6823f3c5SBlaise Bourdin    PetscViewerExodusIIGetOrder - Get the elements order in the exodusII file.
1262*6823f3c5SBlaise Bourdin 
1263*6823f3c5SBlaise Bourdin    Collective
1264*6823f3c5SBlaise Bourdin 
1265*6823f3c5SBlaise Bourdin    Input Parameters:
1266*6823f3c5SBlaise Bourdin +  viewer - the viewer
1267*6823f3c5SBlaise Bourdin .  order - elements order
1268*6823f3c5SBlaise Bourdin 
1269*6823f3c5SBlaise Bourdin    Output Parameter:
1270*6823f3c5SBlaise Bourdin 
1271*6823f3c5SBlaise Bourdin    Level: beginner
1272*6823f3c5SBlaise Bourdin 
1273*6823f3c5SBlaise Bourdin    Note:
1274*6823f3c5SBlaise Bourdin 
1275*6823f3c5SBlaise Bourdin 
1276*6823f3c5SBlaise Bourdin .seealso: PetscViewerExodusIIGetId(), PetscViewerExodusIIGetOrder(), PetscViewerExodusIISetOrder()
1277*6823f3c5SBlaise Bourdin @*/
1278*6823f3c5SBlaise Bourdin PetscErrorCode PetscViewerExodusIIGetOrder(PetscViewer viewer, PetscInt *order)
1279*6823f3c5SBlaise Bourdin {
1280*6823f3c5SBlaise Bourdin   PetscErrorCode ierr;
1281*6823f3c5SBlaise Bourdin 
1282*6823f3c5SBlaise Bourdin   PetscFunctionBegin;
1283*6823f3c5SBlaise Bourdin   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
1284*6823f3c5SBlaise Bourdin   ierr = PetscTryMethod(viewer, "PetscViewerGetOrder_C",(PetscViewer,PetscInt*),(viewer,order));CHKERRQ(ierr);
1285*6823f3c5SBlaise Bourdin   PetscFunctionReturn(0);
1286*6823f3c5SBlaise Bourdin }
1287*6823f3c5SBlaise Bourdin 
1288*6823f3c5SBlaise Bourdin /*@C
1289*6823f3c5SBlaise Bourdin    PetscViewerExodusIIOpen - Opens a file for ExodusII input/output.
1290*6823f3c5SBlaise Bourdin 
1291*6823f3c5SBlaise Bourdin    Collective
1292*6823f3c5SBlaise Bourdin 
1293*6823f3c5SBlaise Bourdin    Input Parameters:
1294*6823f3c5SBlaise Bourdin +  comm - MPI communicator
1295*6823f3c5SBlaise Bourdin .  name - name of file
1296*6823f3c5SBlaise Bourdin -  type - type of file
1297*6823f3c5SBlaise Bourdin $    FILE_MODE_WRITE - create new file for binary output
1298*6823f3c5SBlaise Bourdin $    FILE_MODE_READ - open existing file for binary input
1299*6823f3c5SBlaise Bourdin $    FILE_MODE_APPEND - open existing file for binary output
1300*6823f3c5SBlaise Bourdin 
1301*6823f3c5SBlaise Bourdin    Output Parameter:
1302*6823f3c5SBlaise Bourdin .  exo - PetscViewer for Exodus II input/output to use with the specified file
1303*6823f3c5SBlaise Bourdin 
1304*6823f3c5SBlaise Bourdin    Level: beginner
1305*6823f3c5SBlaise Bourdin 
1306*6823f3c5SBlaise Bourdin    Note:
1307*6823f3c5SBlaise Bourdin    This PetscViewer should be destroyed with PetscViewerDestroy().
1308*6823f3c5SBlaise Bourdin 
1309*6823f3c5SBlaise Bourdin 
1310*6823f3c5SBlaise Bourdin .seealso: PetscViewerPushFormat(), PetscViewerDestroy(),
1311*6823f3c5SBlaise Bourdin           DMLoad(), PetscFileMode, PetscViewer, PetscViewerSetType(), PetscViewerFileSetMode(), PetscViewerFileSetName()
1312*6823f3c5SBlaise Bourdin @*/
1313*6823f3c5SBlaise Bourdin PetscErrorCode PetscViewerExodusIIOpen(MPI_Comm comm, const char name[], PetscFileMode type, PetscViewer *exo)
1314*6823f3c5SBlaise Bourdin {
1315*6823f3c5SBlaise Bourdin   PetscErrorCode ierr;
1316*6823f3c5SBlaise Bourdin 
1317*6823f3c5SBlaise Bourdin   PetscFunctionBegin;
1318*6823f3c5SBlaise Bourdin   ierr = PetscViewerCreate(comm, exo);CHKERRQ(ierr);
1319*6823f3c5SBlaise Bourdin   ierr = PetscViewerSetType(*exo, PETSCVIEWEREXODUSII);CHKERRQ(ierr);
1320*6823f3c5SBlaise Bourdin   ierr = PetscViewerFileSetMode(*exo, type);CHKERRQ(ierr);
1321*6823f3c5SBlaise Bourdin   ierr = PetscViewerFileSetName(*exo, name);CHKERRQ(ierr);
1322*6823f3c5SBlaise Bourdin   ierr = PetscViewerSetFromOptions(*exo);CHKERRQ(ierr);
13231e50132fSMatthew G. Knepley   PetscFunctionReturn(0);
13241e50132fSMatthew G. Knepley }
13251e50132fSMatthew G. Knepley 
132633751fbdSMichael Lange /*@C
1327eaf898f9SPatrick Sanan   DMPlexCreateExodusFromFile - Create a DMPlex mesh from an ExodusII file.
132833751fbdSMichael Lange 
1329d083f849SBarry Smith   Collective
133033751fbdSMichael Lange 
133133751fbdSMichael Lange   Input Parameters:
133233751fbdSMichael Lange + comm  - The MPI communicator
133333751fbdSMichael Lange . filename - The name of the ExodusII file
133433751fbdSMichael Lange - interpolate - Create faces and edges in the mesh
133533751fbdSMichael Lange 
133633751fbdSMichael Lange   Output Parameter:
133733751fbdSMichael Lange . dm  - The DM object representing the mesh
133833751fbdSMichael Lange 
133933751fbdSMichael Lange   Level: beginner
134033751fbdSMichael Lange 
134133751fbdSMichael Lange .seealso: DMPLEX, DMCreate(), DMPlexCreateExodus()
134233751fbdSMichael Lange @*/
134333751fbdSMichael Lange PetscErrorCode DMPlexCreateExodusFromFile(MPI_Comm comm, const char filename[], PetscBool interpolate, DM *dm)
134433751fbdSMichael Lange {
134533751fbdSMichael Lange   PetscMPIInt    rank;
134633751fbdSMichael Lange   PetscErrorCode ierr;
134733751fbdSMichael Lange #if defined(PETSC_HAVE_EXODUSII)
1348e84f7031SBlaise Bourdin   int   CPU_word_size = sizeof(PetscReal), IO_word_size = 0, exoid = -1;
134933751fbdSMichael Lange   float version;
135033751fbdSMichael Lange #endif
135133751fbdSMichael Lange 
135233751fbdSMichael Lange   PetscFunctionBegin;
135333751fbdSMichael Lange   PetscValidCharPointer(filename, 2);
1354ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
135533751fbdSMichael Lange #if defined(PETSC_HAVE_EXODUSII)
135633751fbdSMichael Lange   if (!rank) {
135733751fbdSMichael Lange     exoid = ex_open(filename, EX_READ, &CPU_word_size, &IO_word_size, &version);
135833751fbdSMichael Lange     if (exoid <= 0) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_LIB, "ex_open(\"%s\",...) did not return a valid file ID", filename);
135933751fbdSMichael Lange   }
136033751fbdSMichael Lange   ierr = DMPlexCreateExodus(comm, exoid, interpolate, dm);CHKERRQ(ierr);
13616de834b4SMatthew G. Knepley   if (!rank) {PetscStackCallStandard(ex_close,(exoid));}
1362b458e8f1SJose E. Roman   PetscFunctionReturn(0);
136333751fbdSMichael Lange #else
136433751fbdSMichael Lange   SETERRQ(comm, PETSC_ERR_SUP, "This method requires ExodusII support. Reconfigure using --download-exodusii");
136533751fbdSMichael Lange #endif
136633751fbdSMichael Lange }
136733751fbdSMichael Lange 
13688f861fbcSMatthew G. Knepley #if defined(PETSC_HAVE_EXODUSII)
1369*6823f3c5SBlaise Bourdin static PetscErrorCode ExodusGetCellType_Internal(const char *elem_type, DMPolytopeType *ct)
13708f861fbcSMatthew G. Knepley {
13718f861fbcSMatthew G. Knepley   PetscBool      flg;
13728f861fbcSMatthew G. Knepley   PetscErrorCode ierr;
13738f861fbcSMatthew G. Knepley 
13748f861fbcSMatthew G. Knepley   PetscFunctionBegin;
13758f861fbcSMatthew G. Knepley   *ct = DM_POLYTOPE_UNKNOWN;
13768f861fbcSMatthew G. Knepley   ierr = PetscStrcmp(elem_type, "TRI", &flg);CHKERRQ(ierr);
13778f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_TRIANGLE; goto done;}
13788f861fbcSMatthew G. Knepley   ierr = PetscStrcmp(elem_type, "TRI3", &flg);CHKERRQ(ierr);
13798f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_TRIANGLE; goto done;}
13808f861fbcSMatthew G. Knepley   ierr = PetscStrcmp(elem_type, "QUAD", &flg);CHKERRQ(ierr);
13818f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_QUADRILATERAL; goto done;}
13828f861fbcSMatthew G. Knepley   ierr = PetscStrcmp(elem_type, "QUAD4", &flg);CHKERRQ(ierr);
13838f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_QUADRILATERAL; goto done;}
13848f861fbcSMatthew G. Knepley   ierr = PetscStrcmp(elem_type, "SHELL4", &flg);CHKERRQ(ierr);
13858f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_QUADRILATERAL; goto done;}
13868f861fbcSMatthew G. Knepley   ierr = PetscStrcmp(elem_type, "TETRA", &flg);CHKERRQ(ierr);
13878f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_TETRAHEDRON; goto done;}
13888f861fbcSMatthew G. Knepley   ierr = PetscStrcmp(elem_type, "TET4", &flg);CHKERRQ(ierr);
13898f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_TETRAHEDRON; goto done;}
13908f861fbcSMatthew G. Knepley   ierr = PetscStrcmp(elem_type, "WEDGE", &flg);CHKERRQ(ierr);
13918f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_TRI_PRISM; goto done;}
13928f861fbcSMatthew G. Knepley   ierr = PetscStrcmp(elem_type, "HEX", &flg);CHKERRQ(ierr);
13938f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_HEXAHEDRON; goto done;}
13948f861fbcSMatthew G. Knepley   ierr = PetscStrcmp(elem_type, "HEX8", &flg);CHKERRQ(ierr);
13958f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_HEXAHEDRON; goto done;}
13968f861fbcSMatthew G. Knepley   ierr = PetscStrcmp(elem_type, "HEXAHEDRON", &flg);CHKERRQ(ierr);
13978f861fbcSMatthew G. Knepley   if (flg) {*ct = DM_POLYTOPE_HEXAHEDRON; goto done;}
13988f861fbcSMatthew G. Knepley   SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unrecognized element type %s", elem_type);
13998f861fbcSMatthew G. Knepley   done:
14008f861fbcSMatthew G. Knepley   PetscFunctionReturn(0);
14018f861fbcSMatthew G. Knepley }
14028f861fbcSMatthew G. Knepley #endif
14038f861fbcSMatthew G. Knepley 
1404552f7358SJed Brown /*@
140533751fbdSMichael Lange   DMPlexCreateExodus - Create a DMPlex mesh from an ExodusII file ID.
1406552f7358SJed Brown 
1407d083f849SBarry Smith   Collective
1408552f7358SJed Brown 
1409552f7358SJed Brown   Input Parameters:
1410552f7358SJed Brown + comm  - The MPI communicator
1411552f7358SJed Brown . exoid - The ExodusII id associated with a exodus file and obtained using ex_open
1412552f7358SJed Brown - interpolate - Create faces and edges in the mesh
1413552f7358SJed Brown 
1414552f7358SJed Brown   Output Parameter:
1415552f7358SJed Brown . dm  - The DM object representing the mesh
1416552f7358SJed Brown 
1417552f7358SJed Brown   Level: beginner
1418552f7358SJed Brown 
1419e84e7769SJed Brown .seealso: DMPLEX, DMCreate()
1420552f7358SJed Brown @*/
1421552f7358SJed Brown PetscErrorCode DMPlexCreateExodus(MPI_Comm comm, PetscInt exoid, PetscBool interpolate, DM *dm)
1422552f7358SJed Brown {
1423552f7358SJed Brown #if defined(PETSC_HAVE_EXODUSII)
1424552f7358SJed Brown   PetscMPIInt    num_proc, rank;
1425552f7358SJed Brown   PetscSection   coordSection;
1426552f7358SJed Brown   Vec            coordinates;
1427552f7358SJed Brown   PetscScalar    *coords;
1428552f7358SJed Brown   PetscInt       coordSize, v;
1429552f7358SJed Brown   PetscErrorCode ierr;
1430552f7358SJed Brown   /* Read from ex_get_init() */
1431552f7358SJed Brown   char title[PETSC_MAX_PATH_LEN+1];
14328f861fbcSMatthew G. Knepley   int  dim    = 0, dimEmbed = 0, numVertices = 0, numCells = 0, numHybridCells = 0;
1433552f7358SJed Brown   int  num_cs = 0, num_vs = 0, num_fs = 0;
1434552f7358SJed Brown #endif
1435552f7358SJed Brown 
1436552f7358SJed Brown   PetscFunctionBegin;
1437552f7358SJed Brown #if defined(PETSC_HAVE_EXODUSII)
1438ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
1439ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &num_proc);CHKERRMPI(ierr);
1440552f7358SJed Brown   ierr = DMCreate(comm, dm);CHKERRQ(ierr);
1441552f7358SJed Brown   ierr = DMSetType(*dm, DMPLEX);CHKERRQ(ierr);
1442552f7358SJed Brown   /* Open EXODUS II file and read basic informations on rank 0, then broadcast to all processors */
1443552f7358SJed Brown   if (!rank) {
1444580bdb30SBarry Smith     ierr = PetscMemzero(title,PETSC_MAX_PATH_LEN+1);CHKERRQ(ierr);
14458f861fbcSMatthew G. Knepley     PetscStackCallStandard(ex_get_init,(exoid, title, &dimEmbed, &numVertices, &numCells, &num_cs, &num_vs, &num_fs));
1446552f7358SJed Brown     if (!num_cs) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Exodus file does not contain any cell set\n");
1447552f7358SJed Brown   }
1448ffc4695bSBarry Smith   ierr = MPI_Bcast(title, PETSC_MAX_PATH_LEN+1, MPI_CHAR, 0, comm);CHKERRMPI(ierr);
1449ffc4695bSBarry Smith   ierr = MPI_Bcast(&dim, 1, MPI_INT, 0, comm);CHKERRMPI(ierr);
1450552f7358SJed Brown   ierr = PetscObjectSetName((PetscObject) *dm, title);CHKERRQ(ierr);
1451552f7358SJed Brown   ierr = DMPlexSetChart(*dm, 0, numCells+numVertices);CHKERRQ(ierr);
1452412e9a14SMatthew G. Knepley   /*   We do not want this label automatically computed, instead we compute it here */
1453412e9a14SMatthew G. Knepley   ierr = DMCreateLabel(*dm, "celltype");CHKERRQ(ierr);
1454552f7358SJed Brown 
1455552f7358SJed Brown   /* Read cell sets information */
1456552f7358SJed Brown   if (!rank) {
1457552f7358SJed Brown     PetscInt *cone;
1458e8f6893fSMatthew G. Knepley     int      c, cs, ncs, c_loc, v, v_loc;
1459552f7358SJed Brown     /* Read from ex_get_elem_blk_ids() */
1460e8f6893fSMatthew G. Knepley     int *cs_id, *cs_order;
1461552f7358SJed Brown     /* Read from ex_get_elem_block() */
1462552f7358SJed Brown     char buffer[PETSC_MAX_PATH_LEN+1];
1463e8f6893fSMatthew G. Knepley     int  num_cell_in_set, num_vertex_per_cell, num_hybrid, num_attr;
1464552f7358SJed Brown     /* Read from ex_get_elem_conn() */
1465552f7358SJed Brown     int *cs_connect;
1466552f7358SJed Brown 
1467552f7358SJed Brown     /* Get cell sets IDs */
1468e8f6893fSMatthew G. Knepley     ierr = PetscMalloc2(num_cs, &cs_id, num_cs, &cs_order);CHKERRQ(ierr);
14696de834b4SMatthew G. Knepley     PetscStackCallStandard(ex_get_ids,(exoid, EX_ELEM_BLOCK, cs_id));
1470552f7358SJed Brown     /* Read the cell set connectivity table and build mesh topology
1471552f7358SJed Brown        EXO standard requires that cells in cell sets be numbered sequentially and be pairwise disjoint. */
1472e8f6893fSMatthew G. Knepley     /* Check for a hybrid mesh */
1473e8f6893fSMatthew G. Knepley     for (cs = 0, num_hybrid = 0; cs < num_cs; ++cs) {
14748f861fbcSMatthew G. Knepley       DMPolytopeType ct;
14758f861fbcSMatthew G. Knepley       char           elem_type[PETSC_MAX_PATH_LEN];
14768f861fbcSMatthew G. Knepley 
14778f861fbcSMatthew G. Knepley       ierr = PetscArrayzero(elem_type, sizeof(elem_type));CHKERRQ(ierr);
14788f861fbcSMatthew G. Knepley       PetscStackCallStandard(ex_get_elem_type,(exoid, cs_id[cs], elem_type));
1479*6823f3c5SBlaise Bourdin       ierr = ExodusGetCellType_Internal(elem_type, &ct);CHKERRQ(ierr);
14808f861fbcSMatthew G. Knepley       dim  = PetscMax(dim, DMPolytopeTypeGetDim(ct));
1481e8f6893fSMatthew G. Knepley       PetscStackCallStandard(ex_get_block,(exoid, EX_ELEM_BLOCK, cs_id[cs], buffer, &num_cell_in_set,&num_vertex_per_cell, 0, 0, &num_attr));
14828f861fbcSMatthew G. Knepley       switch (ct) {
14838f861fbcSMatthew G. Knepley         case DM_POLYTOPE_TRI_PRISM:
1484e8f6893fSMatthew G. Knepley           cs_order[cs] = cs;
1485e8f6893fSMatthew G. Knepley           numHybridCells += num_cell_in_set;
1486e8f6893fSMatthew G. Knepley           ++num_hybrid;
1487e8f6893fSMatthew G. Knepley           break;
1488e8f6893fSMatthew G. Knepley         default:
1489e8f6893fSMatthew G. Knepley           for (c = cs; c > cs-num_hybrid; --c) cs_order[c] = cs_order[c-1];
1490e8f6893fSMatthew G. Knepley           cs_order[cs-num_hybrid] = cs;
1491e8f6893fSMatthew G. Knepley       }
1492e8f6893fSMatthew G. Knepley     }
1493552f7358SJed Brown     /* First set sizes */
1494e8f6893fSMatthew G. Knepley     for (ncs = 0, c = 0; ncs < num_cs; ++ncs) {
14958f861fbcSMatthew G. Knepley       DMPolytopeType ct;
14968f861fbcSMatthew G. Knepley       char           elem_type[PETSC_MAX_PATH_LEN];
1497e8f6893fSMatthew G. Knepley       const PetscInt cs = cs_order[ncs];
14988f861fbcSMatthew G. Knepley 
14998f861fbcSMatthew G. Knepley       ierr = PetscArrayzero(elem_type, sizeof(elem_type));CHKERRQ(ierr);
15008f861fbcSMatthew G. Knepley       PetscStackCallStandard(ex_get_elem_type,(exoid, cs_id[cs], elem_type));
1501*6823f3c5SBlaise Bourdin       ierr = ExodusGetCellType_Internal(elem_type, &ct);CHKERRQ(ierr);
15026de834b4SMatthew G. Knepley       PetscStackCallStandard(ex_get_block,(exoid, EX_ELEM_BLOCK, cs_id[cs], buffer, &num_cell_in_set,&num_vertex_per_cell, 0, 0, &num_attr));
1503552f7358SJed Brown       for (c_loc = 0; c_loc < num_cell_in_set; ++c_loc, ++c) {
1504552f7358SJed Brown         ierr = DMPlexSetConeSize(*dm, c, num_vertex_per_cell);CHKERRQ(ierr);
1505412e9a14SMatthew G. Knepley         ierr = DMPlexSetCellType(*dm, c, ct);CHKERRQ(ierr);
1506552f7358SJed Brown       }
1507552f7358SJed Brown     }
1508412e9a14SMatthew G. Knepley     for (v = numCells; v < numCells+numVertices; ++v) {ierr = DMPlexSetCellType(*dm, v, DM_POLYTOPE_POINT);CHKERRQ(ierr);}
1509552f7358SJed Brown     ierr = DMSetUp(*dm);CHKERRQ(ierr);
1510e8f6893fSMatthew G. Knepley     for (ncs = 0, c = 0; ncs < num_cs; ++ncs) {
1511e8f6893fSMatthew G. Knepley       const PetscInt cs = cs_order[ncs];
15126de834b4SMatthew G. Knepley       PetscStackCallStandard(ex_get_block,(exoid, EX_ELEM_BLOCK, cs_id[cs], buffer, &num_cell_in_set, &num_vertex_per_cell, 0, 0, &num_attr));
1513dcca6d9dSJed Brown       ierr = PetscMalloc2(num_vertex_per_cell*num_cell_in_set,&cs_connect,num_vertex_per_cell,&cone);CHKERRQ(ierr);
15146de834b4SMatthew G. Knepley       PetscStackCallStandard(ex_get_conn,(exoid, EX_ELEM_BLOCK, cs_id[cs], cs_connect,NULL,NULL));
1515eaf898f9SPatrick Sanan       /* EXO uses Fortran-based indexing, DMPlex uses C-style and numbers cell first then vertices. */
1516552f7358SJed Brown       for (c_loc = 0, v = 0; c_loc < num_cell_in_set; ++c_loc, ++c) {
1517636e64ffSStefano Zampini         DMPolytopeType ct;
1518636e64ffSStefano Zampini 
1519552f7358SJed Brown         for (v_loc = 0; v_loc < num_vertex_per_cell; ++v_loc, ++v) {
1520552f7358SJed Brown           cone[v_loc] = cs_connect[v]+numCells-1;
1521552f7358SJed Brown         }
1522636e64ffSStefano Zampini         ierr = DMPlexGetCellType(*dm, c, &ct);CHKERRQ(ierr);
1523636e64ffSStefano Zampini         ierr = DMPlexInvertCell(ct, cone);CHKERRQ(ierr);
1524552f7358SJed Brown         ierr = DMPlexSetCone(*dm, c, cone);CHKERRQ(ierr);
1525c58f1c22SToby Isaac         ierr = DMSetLabelValue(*dm, "Cell Sets", c, cs_id[cs]);CHKERRQ(ierr);
1526552f7358SJed Brown       }
1527552f7358SJed Brown       ierr = PetscFree2(cs_connect,cone);CHKERRQ(ierr);
1528552f7358SJed Brown     }
1529e8f6893fSMatthew G. Knepley     ierr = PetscFree2(cs_id, cs_order);CHKERRQ(ierr);
1530552f7358SJed Brown   }
15318f861fbcSMatthew G. Knepley   {
15328f861fbcSMatthew G. Knepley     PetscInt ints[] = {dim, dimEmbed};
15338f861fbcSMatthew G. Knepley 
1534ffc4695bSBarry Smith     ierr = MPI_Bcast(ints, 2, MPIU_INT, 0, comm);CHKERRMPI(ierr);
15358f861fbcSMatthew G. Knepley     ierr = DMSetDimension(*dm, ints[0]);CHKERRQ(ierr);
15368f861fbcSMatthew G. Knepley     ierr = DMSetCoordinateDim(*dm, ints[1]);CHKERRQ(ierr);
15378f861fbcSMatthew G. Knepley     dim      = ints[0];
15388f861fbcSMatthew G. Knepley     dimEmbed = ints[1];
15398f861fbcSMatthew G. Knepley   }
1540552f7358SJed Brown   ierr = DMPlexSymmetrize(*dm);CHKERRQ(ierr);
1541552f7358SJed Brown   ierr = DMPlexStratify(*dm);CHKERRQ(ierr);
1542552f7358SJed Brown   if (interpolate) {
15435fd9971aSMatthew G. Knepley     DM idm;
1544552f7358SJed Brown 
15459f074e33SMatthew G Knepley     ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr);
1546552f7358SJed Brown     ierr = DMDestroy(dm);CHKERRQ(ierr);
1547552f7358SJed Brown     *dm  = idm;
1548552f7358SJed Brown   }
1549552f7358SJed Brown 
1550552f7358SJed Brown   /* Create vertex set label */
1551552f7358SJed Brown   if (!rank && (num_vs > 0)) {
1552552f7358SJed Brown     int vs, v;
1553552f7358SJed Brown     /* Read from ex_get_node_set_ids() */
1554552f7358SJed Brown     int *vs_id;
1555552f7358SJed Brown     /* Read from ex_get_node_set_param() */
1556f958083aSBlaise Bourdin     int num_vertex_in_set;
1557552f7358SJed Brown     /* Read from ex_get_node_set() */
1558552f7358SJed Brown     int *vs_vertex_list;
1559552f7358SJed Brown 
1560552f7358SJed Brown     /* Get vertex set ids */
1561785e854fSJed Brown     ierr = PetscMalloc1(num_vs, &vs_id);CHKERRQ(ierr);
15626de834b4SMatthew G. Knepley     PetscStackCallStandard(ex_get_ids,(exoid, EX_NODE_SET, vs_id));
1563552f7358SJed Brown     for (vs = 0; vs < num_vs; ++vs) {
15646de834b4SMatthew G. Knepley       PetscStackCallStandard(ex_get_set_param,(exoid, EX_NODE_SET, vs_id[vs], &num_vertex_in_set, NULL));
1565785e854fSJed Brown       ierr = PetscMalloc1(num_vertex_in_set, &vs_vertex_list);CHKERRQ(ierr);
15666de834b4SMatthew G. Knepley       PetscStackCallStandard(ex_get_set,(exoid, EX_NODE_SET, vs_id[vs], vs_vertex_list, NULL));
1567552f7358SJed Brown       for (v = 0; v < num_vertex_in_set; ++v) {
1568c58f1c22SToby Isaac         ierr = DMSetLabelValue(*dm, "Vertex Sets", vs_vertex_list[v]+numCells-1, vs_id[vs]);CHKERRQ(ierr);
1569552f7358SJed Brown       }
1570552f7358SJed Brown       ierr = PetscFree(vs_vertex_list);CHKERRQ(ierr);
1571552f7358SJed Brown     }
1572552f7358SJed Brown     ierr = PetscFree(vs_id);CHKERRQ(ierr);
1573552f7358SJed Brown   }
1574552f7358SJed Brown   /* Read coordinates */
157569d8a9ceSMatthew G. Knepley   ierr = DMGetCoordinateSection(*dm, &coordSection);CHKERRQ(ierr);
1576552f7358SJed Brown   ierr = PetscSectionSetNumFields(coordSection, 1);CHKERRQ(ierr);
15778f861fbcSMatthew G. Knepley   ierr = PetscSectionSetFieldComponents(coordSection, 0, dimEmbed);CHKERRQ(ierr);
1578552f7358SJed Brown   ierr = PetscSectionSetChart(coordSection, numCells, numCells + numVertices);CHKERRQ(ierr);
1579552f7358SJed Brown   for (v = numCells; v < numCells+numVertices; ++v) {
15808f861fbcSMatthew G. Knepley     ierr = PetscSectionSetDof(coordSection, v, dimEmbed);CHKERRQ(ierr);
15818f861fbcSMatthew G. Knepley     ierr = PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed);CHKERRQ(ierr);
1582552f7358SJed Brown   }
1583552f7358SJed Brown   ierr = PetscSectionSetUp(coordSection);CHKERRQ(ierr);
1584552f7358SJed Brown   ierr = PetscSectionGetStorageSize(coordSection, &coordSize);CHKERRQ(ierr);
15858b9ced59SLisandro Dalcin   ierr = VecCreate(PETSC_COMM_SELF, &coordinates);CHKERRQ(ierr);
1586552f7358SJed Brown   ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr);
1587552f7358SJed Brown   ierr = VecSetSizes(coordinates, coordSize, PETSC_DETERMINE);CHKERRQ(ierr);
15888f861fbcSMatthew G. Knepley   ierr = VecSetBlockSize(coordinates, dimEmbed);CHKERRQ(ierr);
15892eb5907fSJed Brown   ierr = VecSetType(coordinates,VECSTANDARD);CHKERRQ(ierr);
1590552f7358SJed Brown   ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr);
15910aba08f6SKarl Rupp   if (!rank) {
1592e84f7031SBlaise Bourdin     PetscReal *x, *y, *z;
1593552f7358SJed Brown 
1594dcca6d9dSJed Brown     ierr = PetscMalloc3(numVertices,&x,numVertices,&y,numVertices,&z);CHKERRQ(ierr);
15956de834b4SMatthew G. Knepley     PetscStackCallStandard(ex_get_coord,(exoid, x, y, z));
15968f861fbcSMatthew G. Knepley     if (dimEmbed > 0) {
15978f861fbcSMatthew G. Knepley       for (v = 0; v < numVertices; ++v) coords[v*dimEmbed+0] = x[v];
15980d644c17SKarl Rupp     }
15998f861fbcSMatthew G. Knepley     if (dimEmbed > 1) {
16008f861fbcSMatthew G. Knepley       for (v = 0; v < numVertices; ++v) coords[v*dimEmbed+1] = y[v];
16010d644c17SKarl Rupp     }
16028f861fbcSMatthew G. Knepley     if (dimEmbed > 2) {
16038f861fbcSMatthew G. Knepley       for (v = 0; v < numVertices; ++v) coords[v*dimEmbed+2] = z[v];
16040d644c17SKarl Rupp     }
1605552f7358SJed Brown     ierr = PetscFree3(x,y,z);CHKERRQ(ierr);
1606552f7358SJed Brown   }
1607552f7358SJed Brown   ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr);
1608552f7358SJed Brown   ierr = DMSetCoordinatesLocal(*dm, coordinates);CHKERRQ(ierr);
1609552f7358SJed Brown   ierr = VecDestroy(&coordinates);CHKERRQ(ierr);
1610552f7358SJed Brown 
1611552f7358SJed Brown   /* Create side set label */
1612552f7358SJed Brown   if (!rank && interpolate && (num_fs > 0)) {
1613552f7358SJed Brown     int fs, f, voff;
1614552f7358SJed Brown     /* Read from ex_get_side_set_ids() */
1615552f7358SJed Brown     int *fs_id;
1616552f7358SJed Brown     /* Read from ex_get_side_set_param() */
1617f958083aSBlaise Bourdin     int num_side_in_set;
1618552f7358SJed Brown     /* Read from ex_get_side_set_node_list() */
1619552f7358SJed Brown     int *fs_vertex_count_list, *fs_vertex_list;
1620ef073283Smichael_afanasiev     /* Read side set labels */
1621ef073283Smichael_afanasiev     char fs_name[MAX_STR_LENGTH+1];
1622552f7358SJed Brown 
1623552f7358SJed Brown     /* Get side set ids */
1624785e854fSJed Brown     ierr = PetscMalloc1(num_fs, &fs_id);CHKERRQ(ierr);
16256de834b4SMatthew G. Knepley     PetscStackCallStandard(ex_get_ids,(exoid, EX_SIDE_SET, fs_id));
1626552f7358SJed Brown     for (fs = 0; fs < num_fs; ++fs) {
16276de834b4SMatthew G. Knepley       PetscStackCallStandard(ex_get_set_param,(exoid, EX_SIDE_SET, fs_id[fs], &num_side_in_set, NULL));
1628dcca6d9dSJed Brown       ierr = PetscMalloc2(num_side_in_set,&fs_vertex_count_list,num_side_in_set*4,&fs_vertex_list);CHKERRQ(ierr);
16296de834b4SMatthew G. Knepley       PetscStackCallStandard(ex_get_side_set_node_list,(exoid, fs_id[fs], fs_vertex_count_list, fs_vertex_list));
1630ef073283Smichael_afanasiev       /* Get the specific name associated with this side set ID. */
1631ef073283Smichael_afanasiev       int fs_name_err = ex_get_name(exoid, EX_SIDE_SET, fs_id[fs], fs_name);
1632552f7358SJed Brown       for (f = 0, voff = 0; f < num_side_in_set; ++f) {
16330298fd71SBarry Smith         const PetscInt *faces   = NULL;
1634552f7358SJed Brown         PetscInt       faceSize = fs_vertex_count_list[f], numFaces;
1635552f7358SJed Brown         PetscInt       faceVertices[4], v;
1636552f7358SJed Brown 
1637552f7358SJed Brown         if (faceSize > 4) SETERRQ1(comm, PETSC_ERR_ARG_WRONG, "ExodusII side cannot have %d > 4 vertices", faceSize);
1638552f7358SJed Brown         for (v = 0; v < faceSize; ++v, ++voff) {
1639552f7358SJed Brown           faceVertices[v] = fs_vertex_list[voff]+numCells-1;
1640552f7358SJed Brown         }
1641552f7358SJed Brown         ierr = DMPlexGetFullJoin(*dm, faceSize, faceVertices, &numFaces, &faces);CHKERRQ(ierr);
1642552f7358SJed Brown         if (numFaces != 1) SETERRQ3(comm, PETSC_ERR_ARG_WRONG, "Invalid ExodusII side %d in set %d maps to %d faces", f, fs, numFaces);
1643c58f1c22SToby Isaac         ierr = DMSetLabelValue(*dm, "Face Sets", faces[0], fs_id[fs]);CHKERRQ(ierr);
1644ef073283Smichael_afanasiev         /* Only add the label if one has been detected for this side set. */
1645ef073283Smichael_afanasiev         if (!fs_name_err) {
1646ef073283Smichael_afanasiev           ierr = DMSetLabelValue(*dm, fs_name, faces[0], fs_id[fs]);CHKERRQ(ierr);
1647ef073283Smichael_afanasiev         }
1648552f7358SJed Brown         ierr = DMPlexRestoreJoin(*dm, faceSize, faceVertices, &numFaces, &faces);CHKERRQ(ierr);
1649552f7358SJed Brown       }
1650552f7358SJed Brown       ierr = PetscFree2(fs_vertex_count_list,fs_vertex_list);CHKERRQ(ierr);
1651552f7358SJed Brown     }
1652552f7358SJed Brown     ierr = PetscFree(fs_id);CHKERRQ(ierr);
1653552f7358SJed Brown   }
1654b458e8f1SJose E. Roman   PetscFunctionReturn(0);
1655552f7358SJed Brown #else
1656552f7358SJed Brown   SETERRQ(comm, PETSC_ERR_SUP, "This method requires ExodusII support. Reconfigure using --download-exodusii");
1657552f7358SJed Brown #endif
1658552f7358SJed Brown }
1659