xref: /petsc/src/dm/impls/plex/exodusii/plexexodusii2.c (revision 8a1c49cde0f53efee39379478b6d12fe35f75039)
149c89c76SBlaise Bourdin #define PETSCDM_DLL
249c89c76SBlaise Bourdin #include <petsc/private/dmpleximpl.h> /*I   "petscdmplex.h"   I*/
349c89c76SBlaise Bourdin 
449c89c76SBlaise Bourdin #include <netcdf.h>
549c89c76SBlaise Bourdin #include <exodusII.h>
649c89c76SBlaise Bourdin 
749c89c76SBlaise Bourdin #include <petsc/private/viewerimpl.h>
849c89c76SBlaise Bourdin #include <petsc/private/viewerexodusiiimpl.h>
949c89c76SBlaise Bourdin /*@C
1049c89c76SBlaise Bourdin   PETSC_VIEWER_EXODUSII_ - Creates an `PETSCVIEWEREXODUSII` `PetscViewer` shared by all processors in a communicator.
1149c89c76SBlaise Bourdin 
1249c89c76SBlaise Bourdin   Collective; No Fortran Support
1349c89c76SBlaise Bourdin 
1449c89c76SBlaise Bourdin   Input Parameter:
1549c89c76SBlaise Bourdin . comm - the MPI communicator to share the `PETSCVIEWEREXODUSII` `PetscViewer`
1649c89c76SBlaise Bourdin 
1749c89c76SBlaise Bourdin   Level: intermediate
1849c89c76SBlaise Bourdin 
1949c89c76SBlaise Bourdin   Note:
2049c89c76SBlaise Bourdin   Unlike almost all other PETSc routines, `PETSC_VIEWER_EXODUSII_()` does not return
2149c89c76SBlaise Bourdin   an error code.  The GLVIS PetscViewer is usually used in the form
2249c89c76SBlaise Bourdin $       XXXView(XXX object, PETSC_VIEWER_EXODUSII_(comm));
2349c89c76SBlaise Bourdin 
2449c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewer`, `PetscViewerExodusIIOpen()`, `PetscViewerType`, `PetscViewerCreate()`, `PetscViewerDestroy()`
2549c89c76SBlaise Bourdin @*/
2649c89c76SBlaise Bourdin PetscViewer PETSC_VIEWER_EXODUSII_(MPI_Comm comm)
2749c89c76SBlaise Bourdin {
2849c89c76SBlaise Bourdin   PetscViewer viewer;
2949c89c76SBlaise Bourdin 
3049c89c76SBlaise Bourdin   PetscFunctionBegin;
3149c89c76SBlaise Bourdin   PetscCallNull(PetscViewerExodusIIOpen(comm, "mesh.exo", FILE_MODE_WRITE, &viewer));
3249c89c76SBlaise Bourdin   PetscCallNull(PetscObjectRegisterDestroy((PetscObject)viewer));
3349c89c76SBlaise Bourdin   PetscFunctionReturn(viewer);
3449c89c76SBlaise Bourdin }
3549c89c76SBlaise Bourdin 
3649c89c76SBlaise Bourdin static PetscErrorCode PetscViewerView_ExodusII(PetscViewer v, PetscViewer viewer)
3749c89c76SBlaise Bourdin {
3849c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)v->data;
3949c89c76SBlaise Bourdin 
4049c89c76SBlaise Bourdin   PetscFunctionBegin;
4149c89c76SBlaise Bourdin   if (exo->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename:    %s\n", exo->filename));
420a5cf5d8SBlaise Bourdin   if (exo->exoid) PetscCall(PetscViewerASCIIPrintf(viewer, "exoid:       %" PetscExodusIIInt_FMT "\n", exo->exoid));
4349c89c76SBlaise Bourdin   if (exo->btype) PetscCall(PetscViewerASCIIPrintf(viewer, "IO Mode:     %d\n", exo->btype));
440a5cf5d8SBlaise Bourdin   if (exo->order) PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh order:  %" PetscInt_FMT "\n", exo->order));
450a5cf5d8SBlaise Bourdin   PetscCall(PetscViewerASCIIPrintf(viewer, "Number of nodal variables:  %" PetscExodusIIInt_FMT "\n", exo->numNodalVariables));
4649c89c76SBlaise Bourdin   for (int i = 0; i < exo->numNodalVariables; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "   %d: %s\n", i, exo->nodalVariableNames[i]));
470a5cf5d8SBlaise Bourdin   PetscCall(PetscViewerASCIIPrintf(viewer, "Number of zonal variables:  %" PetscExodusIIInt_FMT "\n", exo->numZonalVariables));
4849c89c76SBlaise Bourdin   for (int i = 0; i < exo->numZonalVariables; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "   %d: %s\n", i, exo->zonalVariableNames[i]));
4949c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
5049c89c76SBlaise Bourdin }
5149c89c76SBlaise Bourdin 
5249c89c76SBlaise Bourdin static PetscErrorCode PetscViewerFlush_ExodusII(PetscViewer v)
5349c89c76SBlaise Bourdin {
5449c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)v->data;
5549c89c76SBlaise Bourdin 
5649c89c76SBlaise Bourdin   PetscFunctionBegin;
5749c89c76SBlaise Bourdin   if (exo->exoid >= 0) PetscCallExternal(ex_update, exo->exoid);
5849c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
5949c89c76SBlaise Bourdin }
6049c89c76SBlaise Bourdin 
6149c89c76SBlaise Bourdin static PetscErrorCode PetscViewerSetFromOptions_ExodusII(PetscViewer v, PetscOptionItems *PetscOptionsObject)
6249c89c76SBlaise Bourdin {
6349c89c76SBlaise Bourdin   PetscFunctionBegin;
6449c89c76SBlaise Bourdin   PetscOptionsHeadBegin(PetscOptionsObject, "ExodusII PetscViewer Options");
6549c89c76SBlaise Bourdin   PetscOptionsHeadEnd();
6649c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
6749c89c76SBlaise Bourdin }
6849c89c76SBlaise Bourdin 
6949c89c76SBlaise Bourdin static PetscErrorCode PetscViewerSetUp_ExodusII(PetscViewer viewer)
7049c89c76SBlaise Bourdin {
7149c89c76SBlaise Bourdin   PetscFunctionBegin;
7249c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
7349c89c76SBlaise Bourdin }
7449c89c76SBlaise Bourdin 
7549c89c76SBlaise Bourdin static PetscErrorCode PetscViewerDestroy_ExodusII(PetscViewer viewer)
7649c89c76SBlaise Bourdin {
7749c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
7849c89c76SBlaise Bourdin 
7949c89c76SBlaise Bourdin   PetscFunctionBegin;
8049c89c76SBlaise Bourdin   if (exo->exoid >= 0) PetscCallExternal(ex_close, exo->exoid);
815341eb2eSStefano Zampini   for (PetscInt i = 0; i < exo->numZonalVariables; i++) PetscCall(PetscFree(exo->zonalVariableNames[i]));
8249c89c76SBlaise Bourdin   PetscCall(PetscFree(exo->zonalVariableNames));
835341eb2eSStefano Zampini   for (PetscInt i = 0; i < exo->numNodalVariables; i++) PetscCall(PetscFree(exo->nodalVariableNames[i]));
8449c89c76SBlaise Bourdin   PetscCall(PetscFree(exo->nodalVariableNames));
8549c89c76SBlaise Bourdin   PetscCall(PetscFree(exo->filename));
8649c89c76SBlaise Bourdin   PetscCall(PetscFree(exo));
8749c89c76SBlaise Bourdin   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL));
8849c89c76SBlaise Bourdin   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", NULL));
8949c89c76SBlaise Bourdin   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", NULL));
9049c89c76SBlaise Bourdin   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", NULL));
9149c89c76SBlaise Bourdin   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerGetId_C", NULL));
9249c89c76SBlaise Bourdin   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerGetOrder_C", NULL));
9349c89c76SBlaise Bourdin   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerSetOrder_C", NULL));
9449c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
9549c89c76SBlaise Bourdin }
9649c89c76SBlaise Bourdin 
9749c89c76SBlaise Bourdin static PetscErrorCode PetscViewerFileSetName_ExodusII(PetscViewer viewer, const char name[])
9849c89c76SBlaise Bourdin {
9949c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
10049c89c76SBlaise Bourdin   PetscMPIInt           rank;
1010a5cf5d8SBlaise Bourdin   PetscExodusIIInt      CPU_word_size, IO_word_size, EXO_mode;
10249c89c76SBlaise Bourdin   MPI_Info              mpi_info = MPI_INFO_NULL;
1030a5cf5d8SBlaise Bourdin   PetscExodusIIFloat    EXO_version;
10449c89c76SBlaise Bourdin 
10549c89c76SBlaise Bourdin   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
10649c89c76SBlaise Bourdin   CPU_word_size = sizeof(PetscReal);
10749c89c76SBlaise Bourdin   IO_word_size  = sizeof(PetscReal);
10849c89c76SBlaise Bourdin 
10949c89c76SBlaise Bourdin   PetscFunctionBegin;
11049c89c76SBlaise Bourdin   if (exo->exoid >= 0) {
11149c89c76SBlaise Bourdin     PetscCallExternal(ex_close, exo->exoid);
11249c89c76SBlaise Bourdin     exo->exoid = -1;
11349c89c76SBlaise Bourdin   }
11449c89c76SBlaise Bourdin   if (exo->filename) PetscCall(PetscFree(exo->filename));
11549c89c76SBlaise Bourdin   PetscCall(PetscStrallocpy(name, &exo->filename));
11649c89c76SBlaise Bourdin   switch (exo->btype) {
11749c89c76SBlaise Bourdin   case FILE_MODE_READ:
11849c89c76SBlaise Bourdin     EXO_mode = EX_READ;
11949c89c76SBlaise Bourdin     break;
12049c89c76SBlaise Bourdin   case FILE_MODE_APPEND:
12149c89c76SBlaise Bourdin   case FILE_MODE_UPDATE:
12249c89c76SBlaise Bourdin   case FILE_MODE_APPEND_UPDATE:
12349c89c76SBlaise Bourdin     /* Will fail if the file does not already exist */
12449c89c76SBlaise Bourdin     EXO_mode = EX_WRITE;
12549c89c76SBlaise Bourdin     break;
12649c89c76SBlaise Bourdin   case FILE_MODE_WRITE:
12749c89c76SBlaise Bourdin     /*
12849c89c76SBlaise Bourdin       exodus only allows writing geometry upon file creation, so we will let DMView create the file.
12949c89c76SBlaise Bourdin     */
13049c89c76SBlaise Bourdin     PetscFunctionReturn(PETSC_SUCCESS);
13149c89c76SBlaise Bourdin     break;
13249c89c76SBlaise Bourdin   default:
13349c89c76SBlaise Bourdin     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
13449c89c76SBlaise Bourdin   }
13549c89c76SBlaise Bourdin #if defined(PETSC_USE_64BIT_INDICES)
13649c89c76SBlaise Bourdin   EXO_mode += EX_ALL_INT64_API;
13749c89c76SBlaise Bourdin #endif
13849c89c76SBlaise Bourdin   exo->exoid = ex_open_par(name, EXO_mode, &CPU_word_size, &IO_word_size, &EXO_version, PETSC_COMM_WORLD, mpi_info);
13949c89c76SBlaise Bourdin   PetscCheck(exo->exoid >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "ex_open_par failed for %s", name);
14049c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
14149c89c76SBlaise Bourdin }
14249c89c76SBlaise Bourdin 
14349c89c76SBlaise Bourdin static PetscErrorCode PetscViewerFileGetName_ExodusII(PetscViewer viewer, const char *name[])
14449c89c76SBlaise Bourdin {
14549c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
14649c89c76SBlaise Bourdin 
14749c89c76SBlaise Bourdin   PetscFunctionBegin;
14849c89c76SBlaise Bourdin   *name = exo->filename;
14949c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
15049c89c76SBlaise Bourdin }
15149c89c76SBlaise Bourdin 
15249c89c76SBlaise Bourdin static PetscErrorCode PetscViewerFileSetMode_ExodusII(PetscViewer viewer, PetscFileMode type)
15349c89c76SBlaise Bourdin {
15449c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
15549c89c76SBlaise Bourdin 
15649c89c76SBlaise Bourdin   PetscFunctionBegin;
15749c89c76SBlaise Bourdin   exo->btype = type;
15849c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
15949c89c76SBlaise Bourdin }
16049c89c76SBlaise Bourdin 
16149c89c76SBlaise Bourdin static PetscErrorCode PetscViewerFileGetMode_ExodusII(PetscViewer viewer, PetscFileMode *type)
16249c89c76SBlaise Bourdin {
16349c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
16449c89c76SBlaise Bourdin 
16549c89c76SBlaise Bourdin   PetscFunctionBegin;
16649c89c76SBlaise Bourdin   *type = exo->btype;
16749c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
16849c89c76SBlaise Bourdin }
16949c89c76SBlaise Bourdin 
1700a5cf5d8SBlaise Bourdin static PetscErrorCode PetscViewerExodusIIGetId_ExodusII(PetscViewer viewer, PetscExodusIIInt *exoid)
17149c89c76SBlaise Bourdin {
17249c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
17349c89c76SBlaise Bourdin 
17449c89c76SBlaise Bourdin   PetscFunctionBegin;
17549c89c76SBlaise Bourdin   *exoid = exo->exoid;
17649c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
17749c89c76SBlaise Bourdin }
17849c89c76SBlaise Bourdin 
1790a5cf5d8SBlaise Bourdin static PetscErrorCode PetscViewerExodusIIGetOrder_ExodusII(PetscViewer viewer, PetscInt *order)
18049c89c76SBlaise Bourdin {
18149c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
18249c89c76SBlaise Bourdin 
18349c89c76SBlaise Bourdin   PetscFunctionBegin;
18449c89c76SBlaise Bourdin   *order = exo->order;
18549c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
18649c89c76SBlaise Bourdin }
18749c89c76SBlaise Bourdin 
1880a5cf5d8SBlaise Bourdin static PetscErrorCode PetscViewerExodusIISetOrder_ExodusII(PetscViewer viewer, PetscInt order)
18949c89c76SBlaise Bourdin {
19049c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
19149c89c76SBlaise Bourdin 
19249c89c76SBlaise Bourdin   PetscFunctionBegin;
19349c89c76SBlaise Bourdin   exo->order = order;
19449c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
19549c89c76SBlaise Bourdin }
19649c89c76SBlaise Bourdin 
19749c89c76SBlaise Bourdin /*@
19849c89c76SBlaise Bourdin   PetscViewerExodusIISetZonalVariable - Sets the number of zonal variables in an exodusII file
19949c89c76SBlaise Bourdin 
20049c89c76SBlaise Bourdin   Collective;
20149c89c76SBlaise Bourdin 
20249c89c76SBlaise Bourdin   Input Parameters:
20349c89c76SBlaise Bourdin + viewer - a `PetscViewer` of type `PETSCVIEWEREXODUSII`
20449c89c76SBlaise Bourdin - num    - the number of zonal variables in the exodusII file
20549c89c76SBlaise Bourdin 
20649c89c76SBlaise Bourdin   Level: intermediate
20749c89c76SBlaise Bourdin 
20849c89c76SBlaise Bourdin   Notes:
20949c89c76SBlaise Bourdin   The exodusII API does not allow changing the number of variables in a file so this function will return an error
21049c89c76SBlaise Bourdin   if called twice, called on a read-only file, or called on file for which the number of variables has already been specified
21149c89c76SBlaise Bourdin 
21249c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerExodusIIOpen()`, `PetscViewerSetType()`, `PetscViewerType`, `PetscViewerExodusIIGetZonalVariable()`
21349c89c76SBlaise Bourdin @*/
2140a5cf5d8SBlaise Bourdin PetscErrorCode PetscViewerExodusIISetZonalVariable(PetscViewer viewer, PetscExodusIIInt num)
21549c89c76SBlaise Bourdin {
21649c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
21749c89c76SBlaise Bourdin   MPI_Comm              comm;
2180a5cf5d8SBlaise Bourdin   PetscExodusIIInt      exoid = -1;
21949c89c76SBlaise Bourdin 
22049c89c76SBlaise Bourdin   PetscFunctionBegin;
22149c89c76SBlaise Bourdin   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
22249c89c76SBlaise Bourdin   PetscCheck(exo->numZonalVariables == -1, comm, PETSC_ERR_SUP, "The number of zonal variables has already been set to %d and cannot be overwritten", exo->numZonalVariables);
22349c89c76SBlaise Bourdin   PetscCheck((exo->btype != FILE_MODE_READ) && (exo->btype != FILE_MODE_UNDEFINED), comm, PETSC_ERR_FILE_WRITE, "Cannot set the number of variables because the file is not writable");
22449c89c76SBlaise Bourdin 
22549c89c76SBlaise Bourdin   exo->numZonalVariables = num;
22649c89c76SBlaise Bourdin   PetscCall(PetscMalloc1(num, &exo->zonalVariableNames));
22749c89c76SBlaise Bourdin   for (int i = 0; i < num; i++) { exo->zonalVariableNames[i] = NULL; }
22849c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetId(viewer, &exoid));
22949c89c76SBlaise Bourdin   PetscCallExternal(ex_put_variable_param, exoid, EX_ELEM_BLOCK, num);
23049c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
23149c89c76SBlaise Bourdin }
23249c89c76SBlaise Bourdin 
23349c89c76SBlaise Bourdin /*@
23449c89c76SBlaise Bourdin   PetscViewerExodusIISetNodalVariable - Sets the number of nodal variables in an exodusII file
23549c89c76SBlaise Bourdin 
23649c89c76SBlaise Bourdin   Collective;
23749c89c76SBlaise Bourdin 
23849c89c76SBlaise Bourdin   Input Parameters:
23949c89c76SBlaise Bourdin + viewer - a `PetscViewer` of type `PETSCVIEWEREXODUSII`
24049c89c76SBlaise Bourdin - num    - the number of nodal variables in the exodusII file
24149c89c76SBlaise Bourdin 
24249c89c76SBlaise Bourdin   Level: intermediate
24349c89c76SBlaise Bourdin 
24449c89c76SBlaise Bourdin   Notes:
24549c89c76SBlaise Bourdin   The exodusII API does not allow changing the number of variables in a file so this function will return an error
24649c89c76SBlaise Bourdin   if called twice, called on a read-only file, or called on file for which the number of variables has already been specified
24749c89c76SBlaise Bourdin 
24849c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerExodusIIOpen()`, `PetscViewerSetType()`, `PetscViewerType`, `PetscViewerExodusIIGetNodalVariable()`
24949c89c76SBlaise Bourdin @*/
2500a5cf5d8SBlaise Bourdin PetscErrorCode PetscViewerExodusIISetNodalVariable(PetscViewer viewer, PetscExodusIIInt num)
25149c89c76SBlaise Bourdin {
25249c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
25349c89c76SBlaise Bourdin   MPI_Comm              comm;
2540a5cf5d8SBlaise Bourdin   PetscExodusIIInt      exoid = -1;
25549c89c76SBlaise Bourdin 
25649c89c76SBlaise Bourdin   PetscFunctionBegin;
25749c89c76SBlaise Bourdin   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
25849c89c76SBlaise Bourdin   PetscCheck(exo->numNodalVariables == -1, comm, PETSC_ERR_SUP, "The number of nodal variables has already been set to %d and cannot be overwritten", exo->numNodalVariables);
25949c89c76SBlaise Bourdin   PetscCheck((exo->btype != FILE_MODE_READ) && (exo->btype != FILE_MODE_UNDEFINED), comm, PETSC_ERR_FILE_WRITE, "Cannot set the number of variables because the file is not writable");
26049c89c76SBlaise Bourdin 
26149c89c76SBlaise Bourdin   exo->numNodalVariables = num;
26249c89c76SBlaise Bourdin   PetscCall(PetscMalloc1(num, &exo->nodalVariableNames));
26349c89c76SBlaise Bourdin   for (int i = 0; i < num; i++) { exo->nodalVariableNames[i] = NULL; }
26449c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetId(viewer, &exoid));
26549c89c76SBlaise Bourdin   PetscCallExternal(ex_put_variable_param, exoid, EX_NODAL, num);
26649c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
26749c89c76SBlaise Bourdin }
26849c89c76SBlaise Bourdin 
26949c89c76SBlaise Bourdin /*@
27049c89c76SBlaise Bourdin   PetscViewerExodusIIGetZonalVariable - Gets the number of zonal variables in an exodusII file
27149c89c76SBlaise Bourdin 
27249c89c76SBlaise Bourdin   Collective
27349c89c76SBlaise Bourdin 
27449c89c76SBlaise Bourdin   Input Parameters:
27549c89c76SBlaise Bourdin . viewer - a `PetscViewer` of type `PETSCVIEWEREXODUSII`
27649c89c76SBlaise Bourdin 
27749c89c76SBlaise Bourdin   Output Parameters:
27849c89c76SBlaise Bourdin . num - the number variables in the exodusII file
27949c89c76SBlaise Bourdin 
28049c89c76SBlaise Bourdin   Level: intermediate
28149c89c76SBlaise Bourdin 
28249c89c76SBlaise Bourdin   Notes:
28349c89c76SBlaise Bourdin   The number of variables in the exodusII file is cached in the viewer
28449c89c76SBlaise Bourdin 
28549c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerExodusIIOpen()`, `PetscViewerSetType()`, `PetscViewerType`, `PetscViewerExodusIIsetZonalVariable()`
28649c89c76SBlaise Bourdin @*/
2870a5cf5d8SBlaise Bourdin PetscErrorCode PetscViewerExodusIIGetZonalVariable(PetscViewer viewer, PetscExodusIIInt *num)
28849c89c76SBlaise Bourdin {
28949c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
29049c89c76SBlaise Bourdin   MPI_Comm              comm;
2910a5cf5d8SBlaise Bourdin   PetscExodusIIInt      exoid = -1;
29249c89c76SBlaise Bourdin 
29349c89c76SBlaise Bourdin   PetscFunctionBegin;
29449c89c76SBlaise Bourdin   if (exo->numZonalVariables > -1) {
29549c89c76SBlaise Bourdin     *num = exo->numZonalVariables;
29649c89c76SBlaise Bourdin   } else {
29749c89c76SBlaise Bourdin     PetscCall(PetscViewerExodusIIGetId(viewer, &exoid));
29849c89c76SBlaise Bourdin     PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
29949c89c76SBlaise Bourdin     PetscCheck(exoid > 0, comm, PETSC_ERR_FILE_OPEN, "Exodus file is not open");
30049c89c76SBlaise Bourdin     PetscCallExternal(ex_get_variable_param, exoid, EX_ELEM_BLOCK, num);
30149c89c76SBlaise Bourdin     exo->numZonalVariables = *num;
30249c89c76SBlaise Bourdin     PetscCall(PetscMalloc1(*num, &exo->zonalVariableNames));
30349c89c76SBlaise Bourdin     for (int i = 0; i < *num; i++) { exo->zonalVariableNames[i] = NULL; }
30449c89c76SBlaise Bourdin   }
30549c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
30649c89c76SBlaise Bourdin }
30749c89c76SBlaise Bourdin 
30849c89c76SBlaise Bourdin /*@
30949c89c76SBlaise Bourdin   PetscViewerExodusIIGetNodalVariable - Gets the number of nodal variables in an exodusII file
31049c89c76SBlaise Bourdin 
31149c89c76SBlaise Bourdin   Collective
31249c89c76SBlaise Bourdin 
31349c89c76SBlaise Bourdin   Input Parameters:
31449c89c76SBlaise Bourdin . viewer - a `PetscViewer` of type `PETSCVIEWEREXODUSII`
31549c89c76SBlaise Bourdin 
31649c89c76SBlaise Bourdin   Output Parameters:
31749c89c76SBlaise Bourdin . num - the number variables in the exodusII file
31849c89c76SBlaise Bourdin 
31949c89c76SBlaise Bourdin   Level: intermediate
32049c89c76SBlaise Bourdin 
32149c89c76SBlaise Bourdin   Notes:
32249c89c76SBlaise Bourdin   This function gets the number of nodal variables and saves it in the address of num.
32349c89c76SBlaise Bourdin 
32449c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerExodusIIOpen()`, `PetscViewerSetType()`, `PetscViewerType`, `PetscViewerExodusIISetNodalVariable()`
32549c89c76SBlaise Bourdin @*/
3260a5cf5d8SBlaise Bourdin PetscErrorCode PetscViewerExodusIIGetNodalVariable(PetscViewer viewer, PetscExodusIIInt *num)
32749c89c76SBlaise Bourdin {
32849c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
32949c89c76SBlaise Bourdin   MPI_Comm              comm;
3300a5cf5d8SBlaise Bourdin   PetscExodusIIInt      exoid = -1;
33149c89c76SBlaise Bourdin 
33249c89c76SBlaise Bourdin   PetscFunctionBegin;
33349c89c76SBlaise Bourdin   if (exo->numNodalVariables > -1) {
33449c89c76SBlaise Bourdin     *num = exo->numNodalVariables;
33549c89c76SBlaise Bourdin   } else {
33649c89c76SBlaise Bourdin     PetscCall(PetscViewerExodusIIGetId(viewer, &exoid));
33749c89c76SBlaise Bourdin     PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
33849c89c76SBlaise Bourdin     PetscCheck(exoid > 0, comm, PETSC_ERR_FILE_OPEN, "Exodus file is not open");
33949c89c76SBlaise Bourdin     PetscCallExternal(ex_get_variable_param, exoid, EX_NODAL, num);
34049c89c76SBlaise Bourdin     exo->numNodalVariables = *num;
34149c89c76SBlaise Bourdin     PetscCall(PetscMalloc1(*num, &exo->nodalVariableNames));
34249c89c76SBlaise Bourdin     for (int i = 0; i < *num; i++) { exo->nodalVariableNames[i] = NULL; }
34349c89c76SBlaise Bourdin   }
34449c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
34549c89c76SBlaise Bourdin }
34649c89c76SBlaise Bourdin 
34749c89c76SBlaise Bourdin /*@
34849c89c76SBlaise Bourdin   PetscViewerExodusIISetZonalVariableName - Sets the name of a zonal variable.
34949c89c76SBlaise Bourdin 
35049c89c76SBlaise Bourdin   Collective;
35149c89c76SBlaise Bourdin 
35249c89c76SBlaise Bourdin   Input Parameters:
35349c89c76SBlaise Bourdin + viewer - a `PetscViewer` of type `PETSCVIEWEREXODUSII`
35449c89c76SBlaise Bourdin . idx    - the index for which you want to save the name
35549c89c76SBlaise Bourdin - name   - string containing the name characters
35649c89c76SBlaise Bourdin 
35749c89c76SBlaise Bourdin   Level: intermediate
35849c89c76SBlaise Bourdin 
35949c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerExodusIIOpen()`, `PetscViewerSetType()`, `PetscViewerType`, `PetscViewerExodusIIGetZonalVariableName()`
36049c89c76SBlaise Bourdin @*/
3610a5cf5d8SBlaise Bourdin PetscErrorCode PetscViewerExodusIISetZonalVariableName(PetscViewer viewer, PetscExodusIIInt idx, const char name[])
36249c89c76SBlaise Bourdin {
36349c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
36449c89c76SBlaise Bourdin 
36549c89c76SBlaise Bourdin   PetscFunctionBegin;
36649c89c76SBlaise Bourdin   PetscCheck((idx >= 0) && (idx < exo->numZonalVariables), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Variable index out of range. Was PetscViewerExodusIISetZonalVariable called?");
36749c89c76SBlaise Bourdin   PetscCall(PetscStrallocpy(name, (char **)&exo->zonalVariableNames[idx]));
36849c89c76SBlaise Bourdin   PetscCallExternal(ex_put_variable_name, exo->exoid, EX_ELEM_BLOCK, idx + 1, name);
36949c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
37049c89c76SBlaise Bourdin }
37149c89c76SBlaise Bourdin 
37249c89c76SBlaise Bourdin /*@
37349c89c76SBlaise Bourdin   PetscViewerExodusIISetNodalVariableName - Sets the name of a nodal variable.
37449c89c76SBlaise Bourdin 
37549c89c76SBlaise Bourdin   Collective;
37649c89c76SBlaise Bourdin 
37749c89c76SBlaise Bourdin   Input Parameters:
37849c89c76SBlaise Bourdin + viewer - a `PetscViewer` of type `PETSCVIEWEREXODUSII`
37949c89c76SBlaise Bourdin . idx    - the index for which you want to save the name
38049c89c76SBlaise Bourdin - name   - string containing the name characters
38149c89c76SBlaise Bourdin 
38249c89c76SBlaise Bourdin   Level: intermediate
38349c89c76SBlaise Bourdin 
38449c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerExodusIIOpen()`, `PetscViewerSetType()`, `PetscViewerType`, `PetscViewerExodusIIGetNodalVariableName()`
38549c89c76SBlaise Bourdin @*/
3860a5cf5d8SBlaise Bourdin PetscErrorCode PetscViewerExodusIISetNodalVariableName(PetscViewer viewer, PetscExodusIIInt idx, const char name[])
38749c89c76SBlaise Bourdin {
38849c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
38949c89c76SBlaise Bourdin 
39049c89c76SBlaise Bourdin   PetscFunctionBegin;
39149c89c76SBlaise Bourdin   PetscCheck((idx >= 0) && (idx < exo->numNodalVariables), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Variable index out of range. Was PetscViewerExodusIISetNodalVariable called?");
39249c89c76SBlaise Bourdin   PetscCall(PetscStrallocpy(name, (char **)&exo->nodalVariableNames[idx]));
39349c89c76SBlaise Bourdin   PetscCallExternal(ex_put_variable_name, exo->exoid, EX_NODAL, idx + 1, name);
39449c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
39549c89c76SBlaise Bourdin }
39649c89c76SBlaise Bourdin 
39749c89c76SBlaise Bourdin /*@
39849c89c76SBlaise Bourdin   PetscViewerExodusIIGetZonalVariableName - Gets the name of a zonal variable.
39949c89c76SBlaise Bourdin 
40049c89c76SBlaise Bourdin   Collective;
40149c89c76SBlaise Bourdin 
40249c89c76SBlaise Bourdin   Input Parameters:
40349c89c76SBlaise Bourdin + viewer - a `PetscViewer` of type `PETSCVIEWEREXODUSII`
40449c89c76SBlaise Bourdin - idx    - the index for which you want to get the name
40549c89c76SBlaise Bourdin 
40649c89c76SBlaise Bourdin   Output Parameter:
40749c89c76SBlaise Bourdin . name - pointer to the string containing the name characters
40849c89c76SBlaise Bourdin 
40949c89c76SBlaise Bourdin   Level: intermediate
41049c89c76SBlaise Bourdin 
41149c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerExodusIIOpen()`, `PetscViewerSetType()`, `PetscViewerType`, `PetscViewerExodusIISetZonalVariableName()`
41249c89c76SBlaise Bourdin @*/
4130a5cf5d8SBlaise Bourdin PetscErrorCode PetscViewerExodusIIGetZonalVariableName(PetscViewer viewer, PetscExodusIIInt idx, const char *name[])
41449c89c76SBlaise Bourdin {
41549c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo   = (PetscViewer_ExodusII *)viewer->data;
4160a5cf5d8SBlaise Bourdin   PetscExodusIIInt      exoid = -1;
41749c89c76SBlaise Bourdin   char                  tmpName[MAX_NAME_LENGTH + 1];
41849c89c76SBlaise Bourdin 
41949c89c76SBlaise Bourdin   PetscFunctionBegin;
42049c89c76SBlaise Bourdin   PetscCheck(idx >= 0 && idx < exo->numZonalVariables, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Variable index out of range. Was PetscViewerExodusIISetZonalVariable called?");
42149c89c76SBlaise Bourdin   if (!exo->zonalVariableNames[idx]) {
42249c89c76SBlaise Bourdin     PetscCall(PetscViewerExodusIIGetId(viewer, &exoid));
42349c89c76SBlaise Bourdin     PetscCallExternal(ex_get_variable_name, exoid, EX_ELEM_BLOCK, idx + 1, tmpName);
42449c89c76SBlaise Bourdin     PetscCall(PetscStrallocpy(tmpName, (char **)&exo->zonalVariableNames[idx]));
42549c89c76SBlaise Bourdin   }
42649c89c76SBlaise Bourdin   *name = exo->zonalVariableNames[idx];
42749c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
42849c89c76SBlaise Bourdin }
42949c89c76SBlaise Bourdin 
43049c89c76SBlaise Bourdin /*@
43149c89c76SBlaise Bourdin   PetscViewerExodusIIGetNodalVariableName - Gets the name of a nodal variable.
43249c89c76SBlaise Bourdin 
43349c89c76SBlaise Bourdin   Collective;
43449c89c76SBlaise Bourdin 
43549c89c76SBlaise Bourdin   Input Parameters:
43649c89c76SBlaise Bourdin + viewer - a `PetscViewer` of type `PETSCVIEWEREXODUSII`
43749c89c76SBlaise Bourdin - idx    - the index for which you want to save the name
43849c89c76SBlaise Bourdin 
43949c89c76SBlaise Bourdin   Output Parameter:
44049c89c76SBlaise Bourdin . name - string array containing name characters
44149c89c76SBlaise Bourdin 
44249c89c76SBlaise Bourdin   Level: intermediate
44349c89c76SBlaise Bourdin 
44449c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerExodusIIOpen()`, `PetscViewerSetType()`, `PetscViewerType`, `PetscViewerExodusIISetNodalVariableName()`
44549c89c76SBlaise Bourdin @*/
4460a5cf5d8SBlaise Bourdin PetscErrorCode PetscViewerExodusIIGetNodalVariableName(PetscViewer viewer, PetscExodusIIInt idx, const char *name[])
44749c89c76SBlaise Bourdin {
44849c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo   = (PetscViewer_ExodusII *)viewer->data;
4490a5cf5d8SBlaise Bourdin   PetscExodusIIInt      exoid = -1;
45049c89c76SBlaise Bourdin   char                  tmpName[MAX_NAME_LENGTH + 1];
45149c89c76SBlaise Bourdin 
45249c89c76SBlaise Bourdin   PetscFunctionBegin;
45349c89c76SBlaise Bourdin   PetscCheck((idx >= 0) && (idx < exo->numNodalVariables), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Variable index out of range. Was PetscViewerExodusIISetNodalVariable called?");
45449c89c76SBlaise Bourdin   if (!exo->nodalVariableNames[idx]) {
45549c89c76SBlaise Bourdin     PetscCall(PetscViewerExodusIIGetId(viewer, &exoid));
45649c89c76SBlaise Bourdin     PetscCallExternal(ex_get_variable_name, exoid, EX_NODAL, idx + 1, tmpName);
45749c89c76SBlaise Bourdin     PetscCall(PetscStrallocpy(tmpName, (char **)&exo->nodalVariableNames[idx]));
45849c89c76SBlaise Bourdin   }
45949c89c76SBlaise Bourdin   *name = exo->nodalVariableNames[idx];
46049c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
46149c89c76SBlaise Bourdin }
46249c89c76SBlaise Bourdin 
46349c89c76SBlaise Bourdin /*@C
46449c89c76SBlaise Bourdin   PetscViewerExodusIISetZonalVariableNames - Sets the names of all nodal variables
46549c89c76SBlaise Bourdin 
46649c89c76SBlaise Bourdin   Collective; No Fortran Support
46749c89c76SBlaise Bourdin 
46849c89c76SBlaise Bourdin   Input Parameters:
46949c89c76SBlaise Bourdin + viewer - a `PetscViewer` of type `PETSCVIEWEREXODUSII`
47049c89c76SBlaise Bourdin - names  - 2D array containing the array of string names to be set
47149c89c76SBlaise Bourdin 
47249c89c76SBlaise Bourdin   Level: intermediate
47349c89c76SBlaise Bourdin 
47449c89c76SBlaise Bourdin   Notes:
47549c89c76SBlaise Bourdin   This function allows users to set multiple zonal variable names at a time.
47649c89c76SBlaise Bourdin 
47749c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerExodusIIOpen()`, `PetscViewerSetType()`, `PetscViewerType`, `PetscViewerExodusIIGetZonalVariableNames()`
47849c89c76SBlaise Bourdin @*/
47949c89c76SBlaise Bourdin PetscErrorCode PetscViewerExodusIISetZonalVariableNames(PetscViewer viewer, const char *names[])
48049c89c76SBlaise Bourdin {
4810a5cf5d8SBlaise Bourdin   PetscExodusIIInt      numNames;
4820a5cf5d8SBlaise Bourdin   PetscExodusIIInt      exoid = -1;
48349c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo   = (PetscViewer_ExodusII *)viewer->data;
48449c89c76SBlaise Bourdin 
48549c89c76SBlaise Bourdin   PetscFunctionBegin;
48649c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetZonalVariable(viewer, &numNames));
48749c89c76SBlaise Bourdin   PetscCheck(numNames >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of zonal variables not set. Was PetscViewerExodusIISetZonalVariable called?");
48849c89c76SBlaise Bourdin 
48949c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetId(viewer, &exoid));
49049c89c76SBlaise Bourdin   for (int i = 0; i < numNames; i++) {
49149c89c76SBlaise Bourdin     PetscCall(PetscStrallocpy(names[i], &exo->zonalVariableNames[i]));
49249c89c76SBlaise Bourdin     PetscCallExternal(ex_put_variable_name, exoid, EX_ELEM_BLOCK, i + 1, names[i]);
49349c89c76SBlaise Bourdin   }
49449c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
49549c89c76SBlaise Bourdin }
49649c89c76SBlaise Bourdin 
49749c89c76SBlaise Bourdin /*@C
49849c89c76SBlaise Bourdin   PetscViewerExodusIISetNodalVariableNames - Sets the names of all nodal variables.
49949c89c76SBlaise Bourdin 
50049c89c76SBlaise Bourdin   Collective; No Fortran Support
50149c89c76SBlaise Bourdin 
50249c89c76SBlaise Bourdin   Input Parameters:
50349c89c76SBlaise Bourdin + viewer - a `PetscViewer` of type `PETSCVIEWEREXODUSII`
50449c89c76SBlaise Bourdin - names  - 2D array containing the array of string names to be set
50549c89c76SBlaise Bourdin 
50649c89c76SBlaise Bourdin   Level: intermediate
50749c89c76SBlaise Bourdin 
50849c89c76SBlaise Bourdin   Notes:
50949c89c76SBlaise Bourdin   This function allows users to set multiple nodal variable names at a time.
51049c89c76SBlaise Bourdin 
51149c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerExodusIIOpen()`, `PetscViewerSetType()`, `PetscViewerType`, `PetscViewerExodusIIGetNodalVariableNames()`
51249c89c76SBlaise Bourdin @*/
51349c89c76SBlaise Bourdin PetscErrorCode PetscViewerExodusIISetNodalVariableNames(PetscViewer viewer, const char *names[])
51449c89c76SBlaise Bourdin {
5150a5cf5d8SBlaise Bourdin   PetscExodusIIInt      numNames;
5160a5cf5d8SBlaise Bourdin   PetscExodusIIInt      exoid = -1;
51749c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo   = (PetscViewer_ExodusII *)viewer->data;
51849c89c76SBlaise Bourdin 
51949c89c76SBlaise Bourdin   PetscFunctionBegin;
52049c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetNodalVariable(viewer, &numNames));
52149c89c76SBlaise Bourdin   PetscCheck(numNames >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of nodal variables not set. Was PetscViewerExodusIISetNodalVariable called?");
52249c89c76SBlaise Bourdin 
52349c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetId(viewer, &exoid));
52449c89c76SBlaise Bourdin   for (int i = 0; i < numNames; i++) {
52549c89c76SBlaise Bourdin     PetscCall(PetscStrallocpy(names[i], &exo->nodalVariableNames[i]));
52649c89c76SBlaise Bourdin     PetscCallExternal(ex_put_variable_name, exoid, EX_NODAL, i + 1, names[i]);
52749c89c76SBlaise Bourdin   }
52849c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
52949c89c76SBlaise Bourdin }
53049c89c76SBlaise Bourdin 
53149c89c76SBlaise Bourdin /*@C
53249c89c76SBlaise Bourdin   PetscViewerExodusIIGetZonalVariableNames - Gets the names of all zonal variables.
53349c89c76SBlaise Bourdin 
53449c89c76SBlaise Bourdin   Collective; No Fortran Support
53549c89c76SBlaise Bourdin 
53649c89c76SBlaise Bourdin   Input Parameters:
53749c89c76SBlaise Bourdin + viewer  - a `PetscViewer` of type `PETSCVIEWEREXODUSII`
53849c89c76SBlaise Bourdin - numVars - the number of zonal variable names to retrieve
53949c89c76SBlaise Bourdin 
54049c89c76SBlaise Bourdin   Output Parameters:
54149c89c76SBlaise Bourdin . varNames - pointer to a 2D array where the zonal variable names will be saved
54249c89c76SBlaise Bourdin 
54349c89c76SBlaise Bourdin   Level: intermediate
54449c89c76SBlaise Bourdin 
54549c89c76SBlaise Bourdin   Notes:
54649c89c76SBlaise Bourdin   This function returns a borrowed pointer which should not be freed.
54749c89c76SBlaise Bourdin 
54849c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerExodusIIOpen()`, `PetscViewerSetType()`, `PetscViewerType`, `PetscViewerExodusIISetZonalVariableNames()`
54949c89c76SBlaise Bourdin @*/
5500a5cf5d8SBlaise Bourdin PetscErrorCode PetscViewerExodusIIGetZonalVariableNames(PetscViewer viewer, PetscExodusIIInt *numVars, char ***varNames)
55149c89c76SBlaise Bourdin {
55249c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
5530a5cf5d8SBlaise Bourdin   PetscExodusIIInt      idx;
55449c89c76SBlaise Bourdin   char                  tmpName[MAX_NAME_LENGTH + 1];
5550a5cf5d8SBlaise Bourdin   PetscExodusIIInt      exoid = -1;
55649c89c76SBlaise Bourdin 
55749c89c76SBlaise Bourdin   PetscFunctionBegin;
55849c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetZonalVariable(viewer, numVars));
55949c89c76SBlaise Bourdin   /*
56049c89c76SBlaise Bourdin     Cache variable names if necessary
56149c89c76SBlaise Bourdin   */
56249c89c76SBlaise Bourdin   for (idx = 0; idx < *numVars; idx++) {
56349c89c76SBlaise Bourdin     if (!exo->zonalVariableNames[idx]) {
56449c89c76SBlaise Bourdin       PetscCall(PetscViewerExodusIIGetId(viewer, &exoid));
56549c89c76SBlaise Bourdin       PetscCallExternal(ex_get_variable_name, exoid, EX_ELEM_BLOCK, idx + 1, tmpName);
56649c89c76SBlaise Bourdin       PetscCall(PetscStrallocpy(tmpName, (char **)&exo->zonalVariableNames[idx]));
56749c89c76SBlaise Bourdin     }
56849c89c76SBlaise Bourdin   }
56949c89c76SBlaise Bourdin   *varNames = (char **)exo->zonalVariableNames;
57049c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
57149c89c76SBlaise Bourdin }
57249c89c76SBlaise Bourdin 
57349c89c76SBlaise Bourdin /*@C
57449c89c76SBlaise Bourdin   PetscViewerExodusIIGetNodalVariableNames - Gets the names of all nodal variables.
57549c89c76SBlaise Bourdin 
57649c89c76SBlaise Bourdin   Collective; No Fortran Support
57749c89c76SBlaise Bourdin 
57849c89c76SBlaise Bourdin   Input Parameters:
57949c89c76SBlaise Bourdin + viewer  - a `PetscViewer` of type `PETSCVIEWEREXODUSII`
58049c89c76SBlaise Bourdin - numVars - the number of nodal variable names to retrieve
58149c89c76SBlaise Bourdin 
58249c89c76SBlaise Bourdin   Output Parameters:
58349c89c76SBlaise Bourdin . varNames - 2D array where the nodal variable names will be saved
58449c89c76SBlaise Bourdin 
58549c89c76SBlaise Bourdin   Level: intermediate
58649c89c76SBlaise Bourdin 
58749c89c76SBlaise Bourdin   Notes:
58849c89c76SBlaise Bourdin   This function returns a borrowed pointer which should not be freed.
58949c89c76SBlaise Bourdin 
59049c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerExodusIIOpen()`, `PetscViewerSetType()`, `PetscViewerType`, `PetscViewerExodusIISetNodalVariableNames()`
59149c89c76SBlaise Bourdin @*/
5920a5cf5d8SBlaise Bourdin PetscErrorCode PetscViewerExodusIIGetNodalVariableNames(PetscViewer viewer, PetscExodusIIInt *numVars, char ***varNames)
59349c89c76SBlaise Bourdin {
59449c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
5950a5cf5d8SBlaise Bourdin   PetscExodusIIInt      idx;
59649c89c76SBlaise Bourdin   char                  tmpName[MAX_NAME_LENGTH + 1];
5970a5cf5d8SBlaise Bourdin   PetscExodusIIInt      exoid = -1;
59849c89c76SBlaise Bourdin 
59949c89c76SBlaise Bourdin   PetscFunctionBegin;
60049c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetNodalVariable(viewer, numVars));
60149c89c76SBlaise Bourdin   /*
60249c89c76SBlaise Bourdin     Cache variable names if necessary
60349c89c76SBlaise Bourdin   */
60449c89c76SBlaise Bourdin   for (idx = 0; idx < *numVars; idx++) {
60549c89c76SBlaise Bourdin     if (!exo->nodalVariableNames[idx]) {
60649c89c76SBlaise Bourdin       PetscCall(PetscViewerExodusIIGetId(viewer, &exoid));
60749c89c76SBlaise Bourdin       PetscCallExternal(ex_get_variable_name, exoid, EX_NODAL, idx + 1, tmpName);
60849c89c76SBlaise Bourdin       PetscCall(PetscStrallocpy(tmpName, (char **)&exo->nodalVariableNames[idx]));
60949c89c76SBlaise Bourdin     }
61049c89c76SBlaise Bourdin   }
61149c89c76SBlaise Bourdin   *varNames = (char **)exo->nodalVariableNames;
61249c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
61349c89c76SBlaise Bourdin }
61449c89c76SBlaise Bourdin 
61549c89c76SBlaise Bourdin /*MC
61649c89c76SBlaise Bourdin    PETSCVIEWEREXODUSII - A viewer that writes to an Exodus II file
61749c89c76SBlaise Bourdin 
61849c89c76SBlaise Bourdin   Level: beginner
61949c89c76SBlaise Bourdin 
62049c89c76SBlaise Bourdin .seealso: `PetscViewerExodusIIOpen()`, `PetscViewerCreate()`, `PETSCVIEWERBINARY`, `PETSCVIEWERHDF5`, `DMView()`,
62149c89c76SBlaise Bourdin           `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
62249c89c76SBlaise Bourdin M*/
62349c89c76SBlaise Bourdin PETSC_EXTERN PetscErrorCode PetscViewerCreate_ExodusII(PetscViewer v)
62449c89c76SBlaise Bourdin {
62549c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo;
62649c89c76SBlaise Bourdin 
62749c89c76SBlaise Bourdin   PetscFunctionBegin;
62849c89c76SBlaise Bourdin   PetscCall(PetscNew(&exo));
62949c89c76SBlaise Bourdin 
63049c89c76SBlaise Bourdin   v->data                 = (void *)exo;
63149c89c76SBlaise Bourdin   v->ops->destroy         = PetscViewerDestroy_ExodusII;
63249c89c76SBlaise Bourdin   v->ops->setfromoptions  = PetscViewerSetFromOptions_ExodusII;
63349c89c76SBlaise Bourdin   v->ops->setup           = PetscViewerSetUp_ExodusII;
63449c89c76SBlaise Bourdin   v->ops->view            = PetscViewerView_ExodusII;
63549c89c76SBlaise Bourdin   v->ops->flush           = PetscViewerFlush_ExodusII;
63649c89c76SBlaise Bourdin   exo->btype              = FILE_MODE_UNDEFINED;
63749c89c76SBlaise Bourdin   exo->filename           = 0;
63849c89c76SBlaise Bourdin   exo->exoid              = -1;
63949c89c76SBlaise Bourdin   exo->numNodalVariables  = -1;
64049c89c76SBlaise Bourdin   exo->numZonalVariables  = -1;
64149c89c76SBlaise Bourdin   exo->nodalVariableNames = NULL;
64249c89c76SBlaise Bourdin   exo->zonalVariableNames = NULL;
64349c89c76SBlaise Bourdin 
64449c89c76SBlaise Bourdin   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetName_C", PetscViewerFileSetName_ExodusII));
64549c89c76SBlaise Bourdin   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetName_C", PetscViewerFileGetName_ExodusII));
64649c89c76SBlaise Bourdin   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ExodusII));
64749c89c76SBlaise Bourdin   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ExodusII));
64849c89c76SBlaise Bourdin   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerGetId_C", PetscViewerExodusIIGetId_ExodusII));
64949c89c76SBlaise Bourdin   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerSetOrder_C", PetscViewerExodusIISetOrder_ExodusII));
65049c89c76SBlaise Bourdin   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerGetOrder_C", PetscViewerExodusIIGetOrder_ExodusII));
65149c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
65249c89c76SBlaise Bourdin }
65349c89c76SBlaise Bourdin 
65449c89c76SBlaise Bourdin /*@
65549c89c76SBlaise Bourdin   PetscViewerExodusIIGetNodalVariableIndex - return the location of a nodal variable in an exodusII file given its name
65649c89c76SBlaise Bourdin 
65749c89c76SBlaise Bourdin   Collective
65849c89c76SBlaise Bourdin 
65949c89c76SBlaise Bourdin   Input Parameters:
66049c89c76SBlaise Bourdin + viewer - a `PetscViewer` of type `PETSCVIEWEREXODUSII`
66149c89c76SBlaise Bourdin - name   - the name of the result
66249c89c76SBlaise Bourdin 
66349c89c76SBlaise Bourdin   Output Parameter:
66449c89c76SBlaise Bourdin . varIndex - the location of the variable in the exodus file or -1 if the variable is not found
66549c89c76SBlaise Bourdin 
66649c89c76SBlaise Bourdin   Level: beginner
66749c89c76SBlaise Bourdin 
66849c89c76SBlaise Bourdin   Notes:
66949c89c76SBlaise Bourdin   The exodus variable index is obtained by comparing the name argument to the
67049c89c76SBlaise Bourdin   names of zonal variables declared in the exodus file. For instance if name is "V"
67149c89c76SBlaise Bourdin   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
67249c89c76SBlaise Bourdin   amongst all variables of type obj_type.
67349c89c76SBlaise Bourdin 
67449c89c76SBlaise Bourdin .seealso: `PetscViewerExodusIISetNodalVariable()`, `PetscViewerExodusIIGetNodalVariable()`, `PetscViewerExodusIISetNodalVariableName()`, `PetscViewerExodusIISetNodalVariableNames()`, `PetscViewerExodusIIGetNodalVariableName()`, `PetscViewerExodusIIGetNodalVariableNames()`
67549c89c76SBlaise Bourdin @*/
6760a5cf5d8SBlaise Bourdin PetscErrorCode PetscViewerExodusIIGetNodalVariableIndex(PetscViewer viewer, const char name[], PetscExodusIIInt *varIndex)
67749c89c76SBlaise Bourdin {
6780a5cf5d8SBlaise Bourdin   PetscExodusIIInt num_vars = 0, i, j;
67949c89c76SBlaise Bourdin   char             ext_name[MAX_STR_LENGTH + 1];
68049c89c76SBlaise Bourdin   char           **var_names;
68149c89c76SBlaise Bourdin   const int        num_suffix = 5;
68249c89c76SBlaise Bourdin   char            *suffix[5];
68349c89c76SBlaise Bourdin   PetscBool        flg;
68449c89c76SBlaise Bourdin 
68549c89c76SBlaise Bourdin   PetscFunctionBegin;
68649c89c76SBlaise Bourdin   suffix[0] = (char *)"";
68749c89c76SBlaise Bourdin   suffix[1] = (char *)"_X";
68849c89c76SBlaise Bourdin   suffix[2] = (char *)"_XX";
68949c89c76SBlaise Bourdin   suffix[3] = (char *)"_1";
69049c89c76SBlaise Bourdin   suffix[4] = (char *)"_11";
69149c89c76SBlaise Bourdin   *varIndex = -1;
69249c89c76SBlaise Bourdin 
69349c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetNodalVariableNames(viewer, &num_vars, &var_names));
69449c89c76SBlaise Bourdin   for (i = 0; i < num_vars; ++i) {
69549c89c76SBlaise Bourdin     for (j = 0; j < num_suffix; ++j) {
69649c89c76SBlaise Bourdin       PetscCall(PetscStrncpy(ext_name, name, MAX_STR_LENGTH));
69749c89c76SBlaise Bourdin       PetscCall(PetscStrlcat(ext_name, suffix[j], MAX_STR_LENGTH));
69849c89c76SBlaise Bourdin       PetscCall(PetscStrcasecmp(ext_name, var_names[i], &flg));
69949c89c76SBlaise Bourdin       if (flg) *varIndex = i;
70049c89c76SBlaise Bourdin     }
70149c89c76SBlaise Bourdin     if (flg) break;
70249c89c76SBlaise Bourdin   }
70349c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
70449c89c76SBlaise Bourdin }
70549c89c76SBlaise Bourdin 
70649c89c76SBlaise Bourdin /*@
70749c89c76SBlaise Bourdin   PetscViewerExodusIIGetZonalVariableIndex - return the location of a zonal variable in an exodusII file given its name
70849c89c76SBlaise Bourdin 
70949c89c76SBlaise Bourdin   Collective
71049c89c76SBlaise Bourdin 
71149c89c76SBlaise Bourdin   Input Parameters:
71249c89c76SBlaise Bourdin + viewer - a `PetscViewer` of type `PETSCVIEWEREXODUSII`
71349c89c76SBlaise Bourdin - name   - the name of the result
71449c89c76SBlaise Bourdin 
71549c89c76SBlaise Bourdin   Output Parameter:
71649c89c76SBlaise Bourdin . varIndex - the location of the variable in the exodus file or -1 if the variable is not found
71749c89c76SBlaise Bourdin 
71849c89c76SBlaise Bourdin   Level: beginner
71949c89c76SBlaise Bourdin 
72049c89c76SBlaise Bourdin   Notes:
72149c89c76SBlaise Bourdin   The exodus variable index is obtained by comparing the name argument to the
72249c89c76SBlaise Bourdin   names of zonal variables declared in the exodus file. For instance if name is "V"
72349c89c76SBlaise Bourdin   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
72449c89c76SBlaise Bourdin   amongst all variables of type obj_type.
72549c89c76SBlaise Bourdin 
72649c89c76SBlaise Bourdin .seealso: `PetscViewerExodusIISetNodalVariable()`, `PetscViewerExodusIIGetNodalVariable()`, `PetscViewerExodusIISetNodalVariableName()`, `PetscViewerExodusIISetNodalVariableNames()`, `PetscViewerExodusIIGetNodalVariableName()`, `PetscViewerExodusIIGetNodalVariableNames()`
72749c89c76SBlaise Bourdin @*/
72849c89c76SBlaise Bourdin PetscErrorCode PetscViewerExodusIIGetZonalVariableIndex(PetscViewer viewer, const char name[], int *varIndex)
72949c89c76SBlaise Bourdin {
7300a5cf5d8SBlaise Bourdin   PetscExodusIIInt num_vars = 0, i, j;
73149c89c76SBlaise Bourdin   char             ext_name[MAX_STR_LENGTH + 1];
73249c89c76SBlaise Bourdin   char           **var_names;
73349c89c76SBlaise Bourdin   const int        num_suffix = 5;
73449c89c76SBlaise Bourdin   char            *suffix[5];
73549c89c76SBlaise Bourdin   PetscBool        flg;
73649c89c76SBlaise Bourdin 
73749c89c76SBlaise Bourdin   PetscFunctionBegin;
73849c89c76SBlaise Bourdin   suffix[0] = (char *)"";
73949c89c76SBlaise Bourdin   suffix[1] = (char *)"_X";
74049c89c76SBlaise Bourdin   suffix[2] = (char *)"_XX";
74149c89c76SBlaise Bourdin   suffix[3] = (char *)"_1";
74249c89c76SBlaise Bourdin   suffix[4] = (char *)"_11";
74349c89c76SBlaise Bourdin   *varIndex = -1;
74449c89c76SBlaise Bourdin 
74549c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetZonalVariableNames(viewer, &num_vars, &var_names));
74649c89c76SBlaise Bourdin   for (i = 0; i < num_vars; ++i) {
74749c89c76SBlaise Bourdin     for (j = 0; j < num_suffix; ++j) {
74849c89c76SBlaise Bourdin       PetscCall(PetscStrncpy(ext_name, name, MAX_STR_LENGTH));
74949c89c76SBlaise Bourdin       PetscCall(PetscStrlcat(ext_name, suffix[j], MAX_STR_LENGTH));
75049c89c76SBlaise Bourdin       PetscCall(PetscStrcasecmp(ext_name, var_names[i], &flg));
75149c89c76SBlaise Bourdin       if (flg) *varIndex = i;
75249c89c76SBlaise Bourdin     }
75349c89c76SBlaise Bourdin     if (flg) break;
75449c89c76SBlaise Bourdin   }
75549c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
75649c89c76SBlaise Bourdin }
75749c89c76SBlaise Bourdin 
75849c89c76SBlaise Bourdin PetscErrorCode DMView_PlexExodusII(DM dm, PetscViewer viewer)
75949c89c76SBlaise Bourdin {
76049c89c76SBlaise Bourdin   enum ElemType {
76149c89c76SBlaise Bourdin     SEGMENT,
76249c89c76SBlaise Bourdin     TRI,
76349c89c76SBlaise Bourdin     QUAD,
76449c89c76SBlaise Bourdin     TET,
76549c89c76SBlaise Bourdin     HEX
76649c89c76SBlaise Bourdin   };
76749c89c76SBlaise Bourdin   MPI_Comm comm;
7680a5cf5d8SBlaise Bourdin   PetscInt degree; /* the order of the mesh */
76949c89c76SBlaise Bourdin   /* Connectivity Variables */
77049c89c76SBlaise Bourdin   PetscInt cellsNotInConnectivity;
77149c89c76SBlaise Bourdin   /* Cell Sets */
77249c89c76SBlaise Bourdin   DMLabel         csLabel;
77349c89c76SBlaise Bourdin   IS              csIS;
77449c89c76SBlaise Bourdin   const PetscInt *csIdx;
77549c89c76SBlaise Bourdin   PetscInt        num_cs, cs;
77649c89c76SBlaise Bourdin   enum ElemType  *type;
77749c89c76SBlaise Bourdin   PetscBool       hasLabel;
77849c89c76SBlaise Bourdin   /* Coordinate Variables */
77949c89c76SBlaise Bourdin   DM                 cdm;
78049c89c76SBlaise Bourdin   PetscSection       coordSection;
78149c89c76SBlaise Bourdin   Vec                coord;
78249c89c76SBlaise Bourdin   PetscInt         **nodes;
78349c89c76SBlaise Bourdin   PetscInt           depth, d, dim, skipCells = 0;
78449c89c76SBlaise Bourdin   PetscInt           pStart, pEnd, p, cStart, cEnd, numCells, vStart, vEnd, numVertices, eStart, eEnd, numEdges, fStart, fEnd, numFaces, numNodes;
78549c89c76SBlaise Bourdin   PetscInt           num_vs, num_fs;
78649c89c76SBlaise Bourdin   PetscMPIInt        rank, size;
78749c89c76SBlaise Bourdin   const char        *dmName;
78849c89c76SBlaise Bourdin   PetscInt           nodesLineP1[4] = {2, 0, 0, 0};
78949c89c76SBlaise Bourdin   PetscInt           nodesLineP2[4] = {2, 0, 0, 1};
79049c89c76SBlaise Bourdin   PetscInt           nodesTriP1[4]  = {3, 0, 0, 0};
79149c89c76SBlaise Bourdin   PetscInt           nodesTriP2[4]  = {3, 3, 0, 0};
79249c89c76SBlaise Bourdin   PetscInt           nodesQuadP1[4] = {4, 0, 0, 0};
79349c89c76SBlaise Bourdin   PetscInt           nodesQuadP2[4] = {4, 4, 0, 1};
79449c89c76SBlaise Bourdin   PetscInt           nodesTetP1[4]  = {4, 0, 0, 0};
79549c89c76SBlaise Bourdin   PetscInt           nodesTetP2[4]  = {4, 6, 0, 0};
79649c89c76SBlaise Bourdin   PetscInt           nodesHexP1[4]  = {8, 0, 0, 0};
79749c89c76SBlaise Bourdin   PetscInt           nodesHexP2[4]  = {8, 12, 6, 1};
7980a5cf5d8SBlaise Bourdin   PetscExodusIIInt   CPU_word_size, IO_word_size, EXO_mode;
7990a5cf5d8SBlaise Bourdin   PetscExodusIIFloat EXO_version;
80049c89c76SBlaise Bourdin 
80149c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
80249c89c76SBlaise Bourdin 
80349c89c76SBlaise Bourdin   PetscFunctionBegin;
80449c89c76SBlaise Bourdin   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
80549c89c76SBlaise Bourdin   PetscCallMPI(MPI_Comm_rank(comm, &rank));
80649c89c76SBlaise Bourdin   PetscCallMPI(MPI_Comm_size(comm, &size));
80749c89c76SBlaise Bourdin 
80849c89c76SBlaise Bourdin   /*
80949c89c76SBlaise Bourdin     Creating coordSection is a collective operation so we do it somewhat out of sequence
81049c89c76SBlaise Bourdin   */
81149c89c76SBlaise Bourdin   PetscCall(PetscSectionCreate(comm, &coordSection));
81249c89c76SBlaise Bourdin   PetscCall(DMGetCoordinatesLocalSetUp(dm));
81349c89c76SBlaise Bourdin   /*
81449c89c76SBlaise Bourdin     Check that all points are on rank 0 since we don't know how to save distributed DM in exodus format
81549c89c76SBlaise Bourdin   */
81649c89c76SBlaise Bourdin   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
81749c89c76SBlaise Bourdin   PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd));
81849c89c76SBlaise Bourdin   PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd));
81949c89c76SBlaise Bourdin   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
82049c89c76SBlaise Bourdin   numCells    = cEnd - cStart;
82149c89c76SBlaise Bourdin   numEdges    = eEnd - eStart;
82249c89c76SBlaise Bourdin   numVertices = vEnd - vStart;
82349c89c76SBlaise Bourdin   PetscCheck(!(rank && (numCells || numEdges || numVertices)), PETSC_COMM_SELF, PETSC_ERR_SUP, "Writing distributed DM in exodusII format not supported");
82449c89c76SBlaise Bourdin   if (rank == 0) {
82549c89c76SBlaise Bourdin     switch (exo->btype) {
82649c89c76SBlaise Bourdin     case FILE_MODE_READ:
82749c89c76SBlaise Bourdin     case FILE_MODE_APPEND:
82849c89c76SBlaise Bourdin     case FILE_MODE_UPDATE:
82949c89c76SBlaise Bourdin     case FILE_MODE_APPEND_UPDATE:
83049c89c76SBlaise Bourdin       /* exodusII does not allow writing geometry to an existing file */
83149c89c76SBlaise Bourdin       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "cannot add geometry to existing file %s", exo->filename);
83249c89c76SBlaise Bourdin     case FILE_MODE_WRITE:
83349c89c76SBlaise Bourdin       /* Create an empty file if one already exists*/
83449c89c76SBlaise Bourdin       EXO_mode = EX_CLOBBER;
83549c89c76SBlaise Bourdin #if defined(PETSC_USE_64BIT_INDICES)
83649c89c76SBlaise Bourdin       EXO_mode += EX_ALL_INT64_API;
83749c89c76SBlaise Bourdin #endif
83849c89c76SBlaise Bourdin       CPU_word_size = sizeof(PetscReal);
83949c89c76SBlaise Bourdin       IO_word_size  = sizeof(PetscReal);
84049c89c76SBlaise Bourdin       exo->exoid    = ex_create(exo->filename, EXO_mode, &CPU_word_size, &IO_word_size);
84149c89c76SBlaise Bourdin       PetscCheck(exo->exoid >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "ex_create failed for %s", exo->filename);
84249c89c76SBlaise Bourdin 
84349c89c76SBlaise Bourdin       break;
84449c89c76SBlaise Bourdin     default:
84549c89c76SBlaise Bourdin       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
84649c89c76SBlaise Bourdin     }
84749c89c76SBlaise Bourdin 
84849c89c76SBlaise Bourdin     /* --- Get DM info --- */
84949c89c76SBlaise Bourdin     PetscCall(PetscObjectGetName((PetscObject)dm, &dmName));
85049c89c76SBlaise Bourdin     PetscCall(DMPlexGetDepth(dm, &depth));
85149c89c76SBlaise Bourdin     PetscCall(DMGetDimension(dm, &dim));
85249c89c76SBlaise Bourdin     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
85349c89c76SBlaise Bourdin     if (depth == 3) {
85449c89c76SBlaise Bourdin       numFaces = fEnd - fStart;
85549c89c76SBlaise Bourdin     } else {
85649c89c76SBlaise Bourdin       numFaces = 0;
85749c89c76SBlaise Bourdin     }
85849c89c76SBlaise Bourdin     PetscCall(DMGetLabelSize(dm, "Cell Sets", &num_cs));
85949c89c76SBlaise Bourdin     PetscCall(DMGetLabelSize(dm, "Vertex Sets", &num_vs));
86049c89c76SBlaise Bourdin     PetscCall(DMGetLabelSize(dm, "Face Sets", &num_fs));
86149c89c76SBlaise Bourdin     PetscCall(DMGetCoordinatesLocal(dm, &coord));
86249c89c76SBlaise Bourdin     PetscCall(DMGetCoordinateDM(dm, &cdm));
86349c89c76SBlaise Bourdin     if (num_cs > 0) {
86449c89c76SBlaise Bourdin       PetscCall(DMGetLabel(dm, "Cell Sets", &csLabel));
86549c89c76SBlaise Bourdin       PetscCall(DMLabelGetValueIS(csLabel, &csIS));
86649c89c76SBlaise Bourdin       PetscCall(ISGetIndices(csIS, &csIdx));
86749c89c76SBlaise Bourdin     }
86849c89c76SBlaise Bourdin     PetscCall(PetscMalloc1(num_cs, &nodes));
86949c89c76SBlaise Bourdin     /* Set element type for each block and compute total number of nodes */
87049c89c76SBlaise Bourdin     PetscCall(PetscMalloc1(num_cs, &type));
87149c89c76SBlaise Bourdin     numNodes = numVertices;
87249c89c76SBlaise Bourdin 
87349c89c76SBlaise Bourdin     PetscCall(PetscViewerExodusIIGetOrder(viewer, &degree));
87449c89c76SBlaise Bourdin     if (degree == 2) numNodes += numEdges;
87549c89c76SBlaise Bourdin     cellsNotInConnectivity = numCells;
87649c89c76SBlaise Bourdin     for (cs = 0; cs < num_cs; ++cs) {
87749c89c76SBlaise Bourdin       IS              stratumIS;
87849c89c76SBlaise Bourdin       const PetscInt *cells;
87949c89c76SBlaise Bourdin       PetscScalar    *xyz = NULL;
88049c89c76SBlaise Bourdin       PetscInt        csSize, closureSize;
88149c89c76SBlaise Bourdin 
88249c89c76SBlaise Bourdin       PetscCall(DMLabelGetStratumIS(csLabel, csIdx[cs], &stratumIS));
88349c89c76SBlaise Bourdin       PetscCall(ISGetIndices(stratumIS, &cells));
88449c89c76SBlaise Bourdin       PetscCall(ISGetSize(stratumIS, &csSize));
88549c89c76SBlaise Bourdin       PetscCall(DMPlexVecGetClosure(cdm, NULL, coord, cells[0], &closureSize, &xyz));
88649c89c76SBlaise Bourdin       switch (dim) {
88749c89c76SBlaise Bourdin       case 1:
88849c89c76SBlaise Bourdin         if (closureSize == 2 * dim) {
88949c89c76SBlaise Bourdin           type[cs] = SEGMENT;
89049c89c76SBlaise Bourdin         } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices %" PetscInt_FMT " in dimension %" PetscInt_FMT " has no ExodusII type", closureSize / dim, dim);
891fac68d15SPierre Jolivet         break;
89249c89c76SBlaise Bourdin       case 2:
89349c89c76SBlaise Bourdin         if (closureSize == 3 * dim) {
89449c89c76SBlaise Bourdin           type[cs] = TRI;
89549c89c76SBlaise Bourdin         } else if (closureSize == 4 * dim) {
89649c89c76SBlaise Bourdin           type[cs] = QUAD;
89749c89c76SBlaise Bourdin         } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices %" PetscInt_FMT " in dimension %" PetscInt_FMT " has no ExodusII type", closureSize / dim, dim);
89849c89c76SBlaise Bourdin         break;
89949c89c76SBlaise Bourdin       case 3:
90049c89c76SBlaise Bourdin         if (closureSize == 4 * dim) {
90149c89c76SBlaise Bourdin           type[cs] = TET;
90249c89c76SBlaise Bourdin         } else if (closureSize == 8 * dim) {
90349c89c76SBlaise Bourdin           type[cs] = HEX;
90449c89c76SBlaise Bourdin         } else SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of vertices %" PetscInt_FMT " in dimension %" PetscInt_FMT " has no ExodusII type", closureSize / dim, dim);
90549c89c76SBlaise Bourdin         break;
90649c89c76SBlaise Bourdin       default:
90749c89c76SBlaise Bourdin         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %" PetscInt_FMT " not handled by ExodusII viewer", dim);
90849c89c76SBlaise Bourdin       }
90949c89c76SBlaise Bourdin       if ((degree == 2) && (type[cs] == SEGMENT)) numNodes += csSize;
91049c89c76SBlaise Bourdin       if ((degree == 2) && (type[cs] == QUAD)) numNodes += csSize;
91149c89c76SBlaise Bourdin       if ((degree == 2) && (type[cs] == HEX)) {
91249c89c76SBlaise Bourdin         numNodes += csSize;
91349c89c76SBlaise Bourdin         numNodes += numFaces;
91449c89c76SBlaise Bourdin       }
91549c89c76SBlaise Bourdin       PetscCall(DMPlexVecRestoreClosure(cdm, NULL, coord, cells[0], &closureSize, &xyz));
91649c89c76SBlaise Bourdin       /* Set nodes and Element type */
91749c89c76SBlaise Bourdin       if (type[cs] == SEGMENT) {
91849c89c76SBlaise Bourdin         if (degree == 1) nodes[cs] = nodesLineP1;
91949c89c76SBlaise Bourdin         else if (degree == 2) nodes[cs] = nodesLineP2;
92049c89c76SBlaise Bourdin       } else if (type[cs] == TRI) {
92149c89c76SBlaise Bourdin         if (degree == 1) nodes[cs] = nodesTriP1;
92249c89c76SBlaise Bourdin         else if (degree == 2) nodes[cs] = nodesTriP2;
92349c89c76SBlaise Bourdin       } else if (type[cs] == QUAD) {
92449c89c76SBlaise Bourdin         if (degree == 1) nodes[cs] = nodesQuadP1;
92549c89c76SBlaise Bourdin         else if (degree == 2) nodes[cs] = nodesQuadP2;
92649c89c76SBlaise Bourdin       } else if (type[cs] == TET) {
92749c89c76SBlaise Bourdin         if (degree == 1) nodes[cs] = nodesTetP1;
92849c89c76SBlaise Bourdin         else if (degree == 2) nodes[cs] = nodesTetP2;
92949c89c76SBlaise Bourdin       } else if (type[cs] == HEX) {
93049c89c76SBlaise Bourdin         if (degree == 1) nodes[cs] = nodesHexP1;
93149c89c76SBlaise Bourdin         else if (degree == 2) nodes[cs] = nodesHexP2;
93249c89c76SBlaise Bourdin       }
93349c89c76SBlaise Bourdin       /* Compute the number of cells not in the connectivity table */
93449c89c76SBlaise Bourdin       cellsNotInConnectivity -= nodes[cs][3] * csSize;
93549c89c76SBlaise Bourdin 
93649c89c76SBlaise Bourdin       PetscCall(ISRestoreIndices(stratumIS, &cells));
93749c89c76SBlaise Bourdin       PetscCall(ISDestroy(&stratumIS));
93849c89c76SBlaise Bourdin     }
93949c89c76SBlaise Bourdin     if (num_cs) PetscCallExternal(ex_put_init, exo->exoid, dmName, dim, numNodes, numCells, num_cs, num_vs, num_fs);
94049c89c76SBlaise Bourdin     /* --- Connectivity --- */
94149c89c76SBlaise Bourdin     for (cs = 0; cs < num_cs; ++cs) {
94249c89c76SBlaise Bourdin       IS              stratumIS;
94349c89c76SBlaise Bourdin       const PetscInt *cells;
94449c89c76SBlaise Bourdin       PetscInt       *connect, off = 0;
94549c89c76SBlaise Bourdin       PetscInt        edgesInClosure = 0, facesInClosure = 0, verticesInClosure = 0;
94649c89c76SBlaise Bourdin       PetscInt        csSize, c, connectSize, closureSize;
94749c89c76SBlaise Bourdin       char           *elem_type        = NULL;
94849c89c76SBlaise Bourdin       char            elem_type_bar2[] = "BAR2", elem_type_bar3[] = "BAR3";
94949c89c76SBlaise Bourdin       char            elem_type_tri3[] = "TRI3", elem_type_quad4[] = "QUAD4";
95049c89c76SBlaise Bourdin       char            elem_type_tri6[] = "TRI6", elem_type_quad9[] = "QUAD9";
95149c89c76SBlaise Bourdin       char            elem_type_tet4[] = "TET4", elem_type_hex8[] = "HEX8";
95249c89c76SBlaise Bourdin       char            elem_type_tet10[] = "TET10", elem_type_hex27[] = "HEX27";
95349c89c76SBlaise Bourdin 
95449c89c76SBlaise Bourdin       PetscCall(DMLabelGetStratumIS(csLabel, csIdx[cs], &stratumIS));
95549c89c76SBlaise Bourdin       PetscCall(ISGetIndices(stratumIS, &cells));
95649c89c76SBlaise Bourdin       PetscCall(ISGetSize(stratumIS, &csSize));
95749c89c76SBlaise Bourdin       /* Set Element type */
95849c89c76SBlaise Bourdin       if (type[cs] == SEGMENT) {
95949c89c76SBlaise Bourdin         if (degree == 1) elem_type = elem_type_bar2;
96049c89c76SBlaise Bourdin         else if (degree == 2) elem_type = elem_type_bar3;
96149c89c76SBlaise Bourdin       } else if (type[cs] == TRI) {
96249c89c76SBlaise Bourdin         if (degree == 1) elem_type = elem_type_tri3;
96349c89c76SBlaise Bourdin         else if (degree == 2) elem_type = elem_type_tri6;
96449c89c76SBlaise Bourdin       } else if (type[cs] == QUAD) {
96549c89c76SBlaise Bourdin         if (degree == 1) elem_type = elem_type_quad4;
96649c89c76SBlaise Bourdin         else if (degree == 2) elem_type = elem_type_quad9;
96749c89c76SBlaise Bourdin       } else if (type[cs] == TET) {
96849c89c76SBlaise Bourdin         if (degree == 1) elem_type = elem_type_tet4;
96949c89c76SBlaise Bourdin         else if (degree == 2) elem_type = elem_type_tet10;
97049c89c76SBlaise Bourdin       } else if (type[cs] == HEX) {
97149c89c76SBlaise Bourdin         if (degree == 1) elem_type = elem_type_hex8;
97249c89c76SBlaise Bourdin         else if (degree == 2) elem_type = elem_type_hex27;
97349c89c76SBlaise Bourdin       }
97449c89c76SBlaise Bourdin       connectSize = nodes[cs][0] + nodes[cs][1] + nodes[cs][2] + nodes[cs][3];
97549c89c76SBlaise Bourdin       PetscCall(PetscMalloc1(PetscMax(27, connectSize) * csSize, &connect));
97649c89c76SBlaise Bourdin       PetscCallExternal(ex_put_block, exo->exoid, EX_ELEM_BLOCK, csIdx[cs], elem_type, csSize, connectSize, 0, 0, 1);
97749c89c76SBlaise Bourdin       /* Find number of vertices, edges, and faces in the closure */
97849c89c76SBlaise Bourdin       verticesInClosure = nodes[cs][0];
97949c89c76SBlaise Bourdin       if (depth > 1) {
98049c89c76SBlaise Bourdin         if (dim == 2) {
98149c89c76SBlaise Bourdin           PetscCall(DMPlexGetConeSize(dm, cells[0], &edgesInClosure));
98249c89c76SBlaise Bourdin         } else if (dim == 3) {
98349c89c76SBlaise Bourdin           PetscInt *closure = NULL;
98449c89c76SBlaise Bourdin 
98549c89c76SBlaise Bourdin           PetscCall(DMPlexGetConeSize(dm, cells[0], &facesInClosure));
98649c89c76SBlaise Bourdin           PetscCall(DMPlexGetTransitiveClosure(dm, cells[0], PETSC_TRUE, &closureSize, &closure));
98749c89c76SBlaise Bourdin           edgesInClosure = closureSize - facesInClosure - 1 - verticesInClosure;
98849c89c76SBlaise Bourdin           PetscCall(DMPlexRestoreTransitiveClosure(dm, cells[0], PETSC_TRUE, &closureSize, &closure));
98949c89c76SBlaise Bourdin         }
99049c89c76SBlaise Bourdin       }
99149c89c76SBlaise Bourdin       /* Get connectivity for each cell */
99249c89c76SBlaise Bourdin       for (c = 0; c < csSize; ++c) {
99349c89c76SBlaise Bourdin         PetscInt *closure = NULL;
99449c89c76SBlaise Bourdin         PetscInt  temp, i;
99549c89c76SBlaise Bourdin 
99649c89c76SBlaise Bourdin         PetscCall(DMPlexGetTransitiveClosure(dm, cells[c], PETSC_TRUE, &closureSize, &closure));
99749c89c76SBlaise Bourdin         for (i = 0; i < connectSize; ++i) {
99849c89c76SBlaise Bourdin           if (i < nodes[cs][0]) { /* Vertices */
99949c89c76SBlaise Bourdin             connect[i + off] = closure[(i + edgesInClosure + facesInClosure + 1) * 2] + 1;
100049c89c76SBlaise Bourdin             connect[i + off] -= cellsNotInConnectivity;
100149c89c76SBlaise Bourdin           } else if (i < nodes[cs][0] + nodes[cs][1]) { /* Edges */
100249c89c76SBlaise Bourdin             connect[i + off] = closure[(i - verticesInClosure + facesInClosure + 1) * 2] + 1;
100349c89c76SBlaise Bourdin             if (nodes[cs][2] == 0) connect[i + off] -= numFaces;
100449c89c76SBlaise Bourdin             connect[i + off] -= cellsNotInConnectivity;
100549c89c76SBlaise Bourdin           } else if (i < nodes[cs][0] + nodes[cs][1] + nodes[cs][3]) { /* Cells */
100649c89c76SBlaise Bourdin             connect[i + off] = closure[0] + 1;
100749c89c76SBlaise Bourdin             connect[i + off] -= skipCells;
100849c89c76SBlaise Bourdin           } else if (i < nodes[cs][0] + nodes[cs][1] + nodes[cs][3] + nodes[cs][2]) { /* Faces */
100949c89c76SBlaise Bourdin             connect[i + off] = closure[(i - edgesInClosure - verticesInClosure) * 2] + 1;
101049c89c76SBlaise Bourdin             connect[i + off] -= cellsNotInConnectivity;
101149c89c76SBlaise Bourdin           } else {
101249c89c76SBlaise Bourdin             connect[i + off] = -1;
101349c89c76SBlaise Bourdin           }
101449c89c76SBlaise Bourdin         }
101549c89c76SBlaise Bourdin         /* Tetrahedra are inverted */
101649c89c76SBlaise Bourdin         if (type[cs] == TET) {
101749c89c76SBlaise Bourdin           temp             = connect[0 + off];
101849c89c76SBlaise Bourdin           connect[0 + off] = connect[1 + off];
101949c89c76SBlaise Bourdin           connect[1 + off] = temp;
102049c89c76SBlaise Bourdin           if (degree == 2) {
102149c89c76SBlaise Bourdin             temp             = connect[5 + off];
102249c89c76SBlaise Bourdin             connect[5 + off] = connect[6 + off];
102349c89c76SBlaise Bourdin             connect[6 + off] = temp;
102449c89c76SBlaise Bourdin             temp             = connect[7 + off];
102549c89c76SBlaise Bourdin             connect[7 + off] = connect[8 + off];
102649c89c76SBlaise Bourdin             connect[8 + off] = temp;
102749c89c76SBlaise Bourdin           }
102849c89c76SBlaise Bourdin         }
102949c89c76SBlaise Bourdin         /* Hexahedra are inverted */
103049c89c76SBlaise Bourdin         if (type[cs] == HEX) {
103149c89c76SBlaise Bourdin           temp             = connect[1 + off];
103249c89c76SBlaise Bourdin           connect[1 + off] = connect[3 + off];
103349c89c76SBlaise Bourdin           connect[3 + off] = temp;
103449c89c76SBlaise Bourdin           if (degree == 2) {
103549c89c76SBlaise Bourdin             temp              = connect[8 + off];
103649c89c76SBlaise Bourdin             connect[8 + off]  = connect[11 + off];
103749c89c76SBlaise Bourdin             connect[11 + off] = temp;
103849c89c76SBlaise Bourdin             temp              = connect[9 + off];
103949c89c76SBlaise Bourdin             connect[9 + off]  = connect[10 + off];
104049c89c76SBlaise Bourdin             connect[10 + off] = temp;
104149c89c76SBlaise Bourdin             temp              = connect[16 + off];
104249c89c76SBlaise Bourdin             connect[16 + off] = connect[17 + off];
104349c89c76SBlaise Bourdin             connect[17 + off] = temp;
104449c89c76SBlaise Bourdin             temp              = connect[18 + off];
104549c89c76SBlaise Bourdin             connect[18 + off] = connect[19 + off];
104649c89c76SBlaise Bourdin             connect[19 + off] = temp;
104749c89c76SBlaise Bourdin 
104849c89c76SBlaise Bourdin             temp              = connect[12 + off];
104949c89c76SBlaise Bourdin             connect[12 + off] = connect[16 + off];
105049c89c76SBlaise Bourdin             connect[16 + off] = temp;
105149c89c76SBlaise Bourdin             temp              = connect[13 + off];
105249c89c76SBlaise Bourdin             connect[13 + off] = connect[17 + off];
105349c89c76SBlaise Bourdin             connect[17 + off] = temp;
105449c89c76SBlaise Bourdin             temp              = connect[14 + off];
105549c89c76SBlaise Bourdin             connect[14 + off] = connect[18 + off];
105649c89c76SBlaise Bourdin             connect[18 + off] = temp;
105749c89c76SBlaise Bourdin             temp              = connect[15 + off];
105849c89c76SBlaise Bourdin             connect[15 + off] = connect[19 + off];
105949c89c76SBlaise Bourdin             connect[19 + off] = temp;
106049c89c76SBlaise Bourdin 
106149c89c76SBlaise Bourdin             temp              = connect[23 + off];
106249c89c76SBlaise Bourdin             connect[23 + off] = connect[26 + off];
106349c89c76SBlaise Bourdin             connect[26 + off] = temp;
106449c89c76SBlaise Bourdin             temp              = connect[24 + off];
106549c89c76SBlaise Bourdin             connect[24 + off] = connect[25 + off];
106649c89c76SBlaise Bourdin             connect[25 + off] = temp;
106749c89c76SBlaise Bourdin             temp              = connect[25 + off];
106849c89c76SBlaise Bourdin             connect[25 + off] = connect[26 + off];
106949c89c76SBlaise Bourdin             connect[26 + off] = temp;
107049c89c76SBlaise Bourdin           }
107149c89c76SBlaise Bourdin         }
107249c89c76SBlaise Bourdin         off += connectSize;
107349c89c76SBlaise Bourdin         PetscCall(DMPlexRestoreTransitiveClosure(dm, cells[c], PETSC_TRUE, &closureSize, &closure));
107449c89c76SBlaise Bourdin       }
107549c89c76SBlaise Bourdin       PetscCallExternal(ex_put_conn, exo->exoid, EX_ELEM_BLOCK, csIdx[cs], connect, 0, 0);
107649c89c76SBlaise Bourdin       skipCells += (nodes[cs][3] == 0) * csSize;
107749c89c76SBlaise Bourdin       PetscCall(PetscFree(connect));
107849c89c76SBlaise Bourdin       PetscCall(ISRestoreIndices(stratumIS, &cells));
107949c89c76SBlaise Bourdin       PetscCall(ISDestroy(&stratumIS));
108049c89c76SBlaise Bourdin     }
108149c89c76SBlaise Bourdin     PetscCall(PetscFree(type));
108249c89c76SBlaise Bourdin     /* --- Coordinates --- */
108349c89c76SBlaise Bourdin     PetscCall(PetscSectionSetChart(coordSection, pStart, pEnd));
108449c89c76SBlaise Bourdin     if (num_cs) {
108549c89c76SBlaise Bourdin       for (d = 0; d < depth; ++d) {
108649c89c76SBlaise Bourdin         PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
108749c89c76SBlaise Bourdin         for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(coordSection, p, nodes[0][d] > 0));
108849c89c76SBlaise Bourdin       }
108949c89c76SBlaise Bourdin     }
109049c89c76SBlaise Bourdin     for (cs = 0; cs < num_cs; ++cs) {
109149c89c76SBlaise Bourdin       IS              stratumIS;
109249c89c76SBlaise Bourdin       const PetscInt *cells;
109349c89c76SBlaise Bourdin       PetscInt        csSize, c;
109449c89c76SBlaise Bourdin 
109549c89c76SBlaise Bourdin       PetscCall(DMLabelGetStratumIS(csLabel, csIdx[cs], &stratumIS));
109649c89c76SBlaise Bourdin       PetscCall(ISGetIndices(stratumIS, &cells));
109749c89c76SBlaise Bourdin       PetscCall(ISGetSize(stratumIS, &csSize));
109849c89c76SBlaise Bourdin       for (c = 0; c < csSize; ++c) PetscCall(PetscSectionSetDof(coordSection, cells[c], nodes[cs][3] > 0));
109949c89c76SBlaise Bourdin       PetscCall(ISRestoreIndices(stratumIS, &cells));
110049c89c76SBlaise Bourdin       PetscCall(ISDestroy(&stratumIS));
110149c89c76SBlaise Bourdin     }
110249c89c76SBlaise Bourdin     if (num_cs) {
110349c89c76SBlaise Bourdin       PetscCall(ISRestoreIndices(csIS, &csIdx));
110449c89c76SBlaise Bourdin       PetscCall(ISDestroy(&csIS));
110549c89c76SBlaise Bourdin     }
110649c89c76SBlaise Bourdin     PetscCall(PetscFree(nodes));
110749c89c76SBlaise Bourdin     PetscCall(PetscSectionSetUp(coordSection));
110849c89c76SBlaise Bourdin     if (numNodes) {
110949c89c76SBlaise Bourdin       const char  *coordNames[3] = {"x", "y", "z"};
111049c89c76SBlaise Bourdin       PetscScalar *closure, *cval;
111149c89c76SBlaise Bourdin       PetscReal   *coords;
111249c89c76SBlaise Bourdin       PetscInt     hasDof, n = 0;
111349c89c76SBlaise Bourdin 
111449c89c76SBlaise Bourdin       /* There can't be more than 24 values in the closure of a point for the coord coordSection */
111549c89c76SBlaise Bourdin       PetscCall(PetscCalloc3(numNodes * 3, &coords, dim, &cval, 24, &closure));
111649c89c76SBlaise Bourdin       PetscCall(DMGetCoordinatesLocalNoncollective(dm, &coord));
111749c89c76SBlaise Bourdin       PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
111849c89c76SBlaise Bourdin       for (p = pStart; p < pEnd; ++p) {
111949c89c76SBlaise Bourdin         PetscCall(PetscSectionGetDof(coordSection, p, &hasDof));
112049c89c76SBlaise Bourdin         if (hasDof) {
112149c89c76SBlaise Bourdin           PetscInt closureSize = 24, j;
112249c89c76SBlaise Bourdin 
112349c89c76SBlaise Bourdin           PetscCall(DMPlexVecGetClosure(cdm, NULL, coord, p, &closureSize, &closure));
112449c89c76SBlaise Bourdin           for (d = 0; d < dim; ++d) {
112549c89c76SBlaise Bourdin             cval[d] = 0.0;
112649c89c76SBlaise Bourdin             for (j = 0; j < closureSize / dim; j++) cval[d] += closure[j * dim + d];
112749c89c76SBlaise Bourdin             coords[d * numNodes + n] = PetscRealPart(cval[d]) * dim / closureSize;
112849c89c76SBlaise Bourdin           }
112949c89c76SBlaise Bourdin           ++n;
113049c89c76SBlaise Bourdin         }
113149c89c76SBlaise Bourdin       }
113249c89c76SBlaise Bourdin       PetscCallExternal(ex_put_coord, exo->exoid, &coords[0 * numNodes], &coords[1 * numNodes], &coords[2 * numNodes]);
113349c89c76SBlaise Bourdin       PetscCall(PetscFree3(coords, cval, closure));
113449c89c76SBlaise Bourdin       PetscCallExternal(ex_put_coord_names, exo->exoid, (char **)coordNames);
113549c89c76SBlaise Bourdin     }
113649c89c76SBlaise Bourdin 
113749c89c76SBlaise Bourdin     /* --- Node Sets/Vertex Sets --- */
113849c89c76SBlaise Bourdin     PetscCall(DMHasLabel(dm, "Vertex Sets", &hasLabel));
113949c89c76SBlaise Bourdin     if (hasLabel) {
114049c89c76SBlaise Bourdin       PetscInt        i, vs, vsSize;
114149c89c76SBlaise Bourdin       const PetscInt *vsIdx, *vertices;
114249c89c76SBlaise Bourdin       PetscInt       *nodeList;
114349c89c76SBlaise Bourdin       IS              vsIS, stratumIS;
114449c89c76SBlaise Bourdin       DMLabel         vsLabel;
114549c89c76SBlaise Bourdin       PetscCall(DMGetLabel(dm, "Vertex Sets", &vsLabel));
114649c89c76SBlaise Bourdin       PetscCall(DMLabelGetValueIS(vsLabel, &vsIS));
114749c89c76SBlaise Bourdin       PetscCall(ISGetIndices(vsIS, &vsIdx));
114849c89c76SBlaise Bourdin       for (vs = 0; vs < num_vs; ++vs) {
114949c89c76SBlaise Bourdin         PetscCall(DMLabelGetStratumIS(vsLabel, vsIdx[vs], &stratumIS));
115049c89c76SBlaise Bourdin         PetscCall(ISGetIndices(stratumIS, &vertices));
115149c89c76SBlaise Bourdin         PetscCall(ISGetSize(stratumIS, &vsSize));
115249c89c76SBlaise Bourdin         PetscCall(PetscMalloc1(vsSize, &nodeList));
115349c89c76SBlaise Bourdin         for (i = 0; i < vsSize; ++i) nodeList[i] = vertices[i] - skipCells + 1;
115449c89c76SBlaise Bourdin         PetscCallExternal(ex_put_set_param, exo->exoid, EX_NODE_SET, vsIdx[vs], vsSize, 0);
115549c89c76SBlaise Bourdin         PetscCallExternal(ex_put_set, exo->exoid, EX_NODE_SET, vsIdx[vs], nodeList, NULL);
115649c89c76SBlaise Bourdin         PetscCall(ISRestoreIndices(stratumIS, &vertices));
115749c89c76SBlaise Bourdin         PetscCall(ISDestroy(&stratumIS));
115849c89c76SBlaise Bourdin         PetscCall(PetscFree(nodeList));
115949c89c76SBlaise Bourdin       }
116049c89c76SBlaise Bourdin       PetscCall(ISRestoreIndices(vsIS, &vsIdx));
116149c89c76SBlaise Bourdin       PetscCall(ISDestroy(&vsIS));
116249c89c76SBlaise Bourdin     }
116349c89c76SBlaise Bourdin     /* --- Side Sets/Face Sets --- */
116449c89c76SBlaise Bourdin     PetscCall(DMHasLabel(dm, "Face Sets", &hasLabel));
116549c89c76SBlaise Bourdin     if (hasLabel) {
116649c89c76SBlaise Bourdin       PetscInt        i, j, fs, fsSize;
116749c89c76SBlaise Bourdin       const PetscInt *fsIdx, *faces;
116849c89c76SBlaise Bourdin       IS              fsIS, stratumIS;
116949c89c76SBlaise Bourdin       DMLabel         fsLabel;
117049c89c76SBlaise Bourdin       PetscInt        numPoints, *points;
117149c89c76SBlaise Bourdin       PetscInt        elem_list_size = 0;
117249c89c76SBlaise Bourdin       PetscInt       *elem_list, *elem_ind, *side_list;
117349c89c76SBlaise Bourdin 
117449c89c76SBlaise Bourdin       PetscCall(DMGetLabel(dm, "Face Sets", &fsLabel));
117549c89c76SBlaise Bourdin       /* Compute size of Node List and Element List */
117649c89c76SBlaise Bourdin       PetscCall(DMLabelGetValueIS(fsLabel, &fsIS));
117749c89c76SBlaise Bourdin       PetscCall(ISGetIndices(fsIS, &fsIdx));
117849c89c76SBlaise Bourdin       for (fs = 0; fs < num_fs; ++fs) {
117949c89c76SBlaise Bourdin         PetscCall(DMLabelGetStratumIS(fsLabel, fsIdx[fs], &stratumIS));
118049c89c76SBlaise Bourdin         PetscCall(ISGetSize(stratumIS, &fsSize));
118149c89c76SBlaise Bourdin         elem_list_size += fsSize;
118249c89c76SBlaise Bourdin         PetscCall(ISDestroy(&stratumIS));
118349c89c76SBlaise Bourdin       }
118449c89c76SBlaise Bourdin       if (num_fs) {
118549c89c76SBlaise Bourdin         PetscCall(PetscMalloc3(num_fs, &elem_ind, elem_list_size, &elem_list, elem_list_size, &side_list));
118649c89c76SBlaise Bourdin         elem_ind[0] = 0;
118749c89c76SBlaise Bourdin         for (fs = 0; fs < num_fs; ++fs) {
118849c89c76SBlaise Bourdin           PetscCall(DMLabelGetStratumIS(fsLabel, fsIdx[fs], &stratumIS));
118949c89c76SBlaise Bourdin           PetscCall(ISGetIndices(stratumIS, &faces));
119049c89c76SBlaise Bourdin           PetscCall(ISGetSize(stratumIS, &fsSize));
119149c89c76SBlaise Bourdin           /* Set Parameters */
119249c89c76SBlaise Bourdin           PetscCallExternal(ex_put_set_param, exo->exoid, EX_SIDE_SET, fsIdx[fs], fsSize, 0);
119349c89c76SBlaise Bourdin           /* Indices */
119449c89c76SBlaise Bourdin           if (fs < num_fs - 1) elem_ind[fs + 1] = elem_ind[fs] + fsSize;
119549c89c76SBlaise Bourdin 
119649c89c76SBlaise Bourdin           for (i = 0; i < fsSize; ++i) {
119749c89c76SBlaise Bourdin             /* Element List */
119849c89c76SBlaise Bourdin             points = NULL;
119949c89c76SBlaise Bourdin             PetscCall(DMPlexGetTransitiveClosure(dm, faces[i], PETSC_FALSE, &numPoints, &points));
120049c89c76SBlaise Bourdin             elem_list[elem_ind[fs] + i] = points[2] + 1;
120149c89c76SBlaise Bourdin             PetscCall(DMPlexRestoreTransitiveClosure(dm, faces[i], PETSC_FALSE, &numPoints, &points));
120249c89c76SBlaise Bourdin 
120349c89c76SBlaise Bourdin             /* Side List */
120449c89c76SBlaise Bourdin             points = NULL;
120549c89c76SBlaise Bourdin             PetscCall(DMPlexGetTransitiveClosure(dm, elem_list[elem_ind[fs] + i] - 1, PETSC_TRUE, &numPoints, &points));
120649c89c76SBlaise Bourdin             for (j = 1; j < numPoints; ++j) {
120749c89c76SBlaise Bourdin               if (points[j * 2] == faces[i]) break;
120849c89c76SBlaise Bourdin             }
120949c89c76SBlaise Bourdin             /* Convert HEX sides */
121049c89c76SBlaise Bourdin             if (numPoints == 27) {
121149c89c76SBlaise Bourdin               if (j == 1) {
121249c89c76SBlaise Bourdin                 j = 5;
121349c89c76SBlaise Bourdin               } else if (j == 2) {
121449c89c76SBlaise Bourdin                 j = 6;
121549c89c76SBlaise Bourdin               } else if (j == 3) {
121649c89c76SBlaise Bourdin                 j = 1;
121749c89c76SBlaise Bourdin               } else if (j == 4) {
121849c89c76SBlaise Bourdin                 j = 3;
121949c89c76SBlaise Bourdin               } else if (j == 5) {
122049c89c76SBlaise Bourdin                 j = 2;
122149c89c76SBlaise Bourdin               } else if (j == 6) {
122249c89c76SBlaise Bourdin                 j = 4;
122349c89c76SBlaise Bourdin               }
122449c89c76SBlaise Bourdin             }
122549c89c76SBlaise Bourdin             /* Convert TET sides */
122649c89c76SBlaise Bourdin             if (numPoints == 15) {
122749c89c76SBlaise Bourdin               --j;
122849c89c76SBlaise Bourdin               if (j == 0) j = 4;
122949c89c76SBlaise Bourdin             }
123049c89c76SBlaise Bourdin             side_list[elem_ind[fs] + i] = j;
123149c89c76SBlaise Bourdin             PetscCall(DMPlexRestoreTransitiveClosure(dm, elem_list[elem_ind[fs] + i] - 1, PETSC_TRUE, &numPoints, &points));
123249c89c76SBlaise Bourdin           }
123349c89c76SBlaise Bourdin           PetscCall(ISRestoreIndices(stratumIS, &faces));
123449c89c76SBlaise Bourdin           PetscCall(ISDestroy(&stratumIS));
123549c89c76SBlaise Bourdin         }
123649c89c76SBlaise Bourdin         PetscCall(ISRestoreIndices(fsIS, &fsIdx));
123749c89c76SBlaise Bourdin         PetscCall(ISDestroy(&fsIS));
123849c89c76SBlaise Bourdin 
123949c89c76SBlaise Bourdin         /* Put side sets */
124049c89c76SBlaise Bourdin         for (fs = 0; fs < num_fs; ++fs) PetscCallExternal(ex_put_set, exo->exoid, EX_SIDE_SET, fsIdx[fs], &elem_list[elem_ind[fs]], &side_list[elem_ind[fs]]);
124149c89c76SBlaise Bourdin         PetscCall(PetscFree3(elem_ind, elem_list, side_list));
124249c89c76SBlaise Bourdin       }
124349c89c76SBlaise Bourdin     }
124449c89c76SBlaise Bourdin     /*
124549c89c76SBlaise Bourdin       close the exodus file
124649c89c76SBlaise Bourdin     */
124749c89c76SBlaise Bourdin     ex_close(exo->exoid);
124849c89c76SBlaise Bourdin     exo->exoid = -1;
124949c89c76SBlaise Bourdin   }
125049c89c76SBlaise Bourdin   PetscCall(PetscSectionDestroy(&coordSection));
125149c89c76SBlaise Bourdin 
125249c89c76SBlaise Bourdin   /*
125349c89c76SBlaise Bourdin     reopen the file in parallel
125449c89c76SBlaise Bourdin   */
125549c89c76SBlaise Bourdin   EXO_mode = EX_WRITE;
125649c89c76SBlaise Bourdin #if defined(PETSC_USE_64BIT_INDICES)
125749c89c76SBlaise Bourdin   EXO_mode += EX_ALL_INT64_API;
125849c89c76SBlaise Bourdin #endif
125949c89c76SBlaise Bourdin   CPU_word_size = sizeof(PetscReal);
126049c89c76SBlaise Bourdin   IO_word_size  = sizeof(PetscReal);
126149c89c76SBlaise Bourdin   exo->exoid    = ex_open_par(exo->filename, EXO_mode, &CPU_word_size, &IO_word_size, &EXO_version, comm, MPI_INFO_NULL);
126249c89c76SBlaise Bourdin   PetscCheck(exo->exoid >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "ex_open_par failed for %s", exo->filename);
126349c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
126449c89c76SBlaise Bourdin }
126549c89c76SBlaise Bourdin 
12660a5cf5d8SBlaise Bourdin static PetscErrorCode VecViewPlex_ExodusII_Nodal_Internal(Vec v, PetscExodusIIInt exoid, PetscExodusIIInt step, PetscExodusIIInt offset);
12670a5cf5d8SBlaise Bourdin static PetscErrorCode VecViewPlex_ExodusII_Zonal_Internal(Vec v, PetscExodusIIInt exoid, PetscExodusIIInt step, PetscExodusIIInt offset);
12680a5cf5d8SBlaise Bourdin static PetscErrorCode VecLoadPlex_ExodusII_Nodal_Internal(Vec v, PetscExodusIIInt exoid, PetscExodusIIInt step, PetscExodusIIInt offset);
12690a5cf5d8SBlaise Bourdin static PetscErrorCode VecLoadPlex_ExodusII_Zonal_Internal(Vec v, PetscExodusIIInt exoid, PetscExodusIIInt step, PetscExodusIIInt offset);
127049c89c76SBlaise Bourdin 
127149c89c76SBlaise Bourdin PetscErrorCode VecView_PlexExodusII_Internal(Vec v, PetscViewer viewer)
127249c89c76SBlaise Bourdin {
127349c89c76SBlaise Bourdin   DM          dm;
127449c89c76SBlaise Bourdin   MPI_Comm    comm;
127549c89c76SBlaise Bourdin   PetscMPIInt rank;
127649c89c76SBlaise Bourdin 
12770a5cf5d8SBlaise Bourdin   PetscExodusIIInt exoid, offsetN = -1, offsetZ = -1;
127849c89c76SBlaise Bourdin   const char      *vecname;
127949c89c76SBlaise Bourdin   PetscInt         step;
128049c89c76SBlaise Bourdin 
128149c89c76SBlaise Bourdin   PetscFunctionBegin;
128249c89c76SBlaise Bourdin   PetscCall(PetscObjectGetComm((PetscObject)v, &comm));
128349c89c76SBlaise Bourdin   PetscCallMPI(MPI_Comm_rank(comm, &rank));
128449c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetId(viewer, &exoid));
128549c89c76SBlaise Bourdin   PetscCall(VecGetDM(v, &dm));
128649c89c76SBlaise Bourdin   PetscCall(PetscObjectGetName((PetscObject)v, &vecname));
128749c89c76SBlaise Bourdin 
128849c89c76SBlaise Bourdin   PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL));
128949c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetNodalVariableIndex(viewer, vecname, &offsetN));
129049c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetZonalVariableIndex(viewer, vecname, &offsetZ));
129149c89c76SBlaise Bourdin   PetscCheck(!(offsetN >= 0 && offsetZ >= 0), comm, PETSC_ERR_FILE_UNEXPECTED, "Found both nodal and zonal variable %s in exodus file. ", vecname);
129249c89c76SBlaise Bourdin   if (offsetN >= 0) {
12930a5cf5d8SBlaise Bourdin     PetscCall(VecViewPlex_ExodusII_Nodal_Internal(v, exoid, (PetscExodusIIInt)step + 1, offsetN + 1));
129449c89c76SBlaise Bourdin   } else if (offsetZ >= 0) {
12950a5cf5d8SBlaise Bourdin     PetscCall(VecViewPlex_ExodusII_Zonal_Internal(v, exoid, (PetscExodusIIInt)step + 1, offsetZ + 1));
129649c89c76SBlaise Bourdin   } else SETERRQ(comm, PETSC_ERR_FILE_UNEXPECTED, "Could not find nodal or zonal variable %s in exodus file. ", vecname);
129749c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
129849c89c76SBlaise Bourdin }
129949c89c76SBlaise Bourdin 
130049c89c76SBlaise Bourdin PetscErrorCode VecLoad_PlexExodusII_Internal(Vec v, PetscViewer viewer)
130149c89c76SBlaise Bourdin {
130249c89c76SBlaise Bourdin   DM          dm;
130349c89c76SBlaise Bourdin   MPI_Comm    comm;
130449c89c76SBlaise Bourdin   PetscMPIInt rank;
130549c89c76SBlaise Bourdin 
13060a5cf5d8SBlaise Bourdin   PetscExodusIIInt exoid, offsetN = 0, offsetZ = 0;
130749c89c76SBlaise Bourdin   const char      *vecname;
130849c89c76SBlaise Bourdin   PetscInt         step;
130949c89c76SBlaise Bourdin 
131049c89c76SBlaise Bourdin   PetscFunctionBegin;
131149c89c76SBlaise Bourdin   PetscCall(PetscObjectGetComm((PetscObject)v, &comm));
131249c89c76SBlaise Bourdin   PetscCallMPI(MPI_Comm_rank(comm, &rank));
131349c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetId(viewer, &exoid));
131449c89c76SBlaise Bourdin   PetscCall(VecGetDM(v, &dm));
131549c89c76SBlaise Bourdin   PetscCall(PetscObjectGetName((PetscObject)v, &vecname));
131649c89c76SBlaise Bourdin 
131749c89c76SBlaise Bourdin   PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL));
131849c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetNodalVariableIndex(viewer, vecname, &offsetN));
131949c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetZonalVariableIndex(viewer, vecname, &offsetZ));
132049c89c76SBlaise Bourdin   PetscCheck(!(offsetN >= 0 && offsetZ >= 0), comm, PETSC_ERR_FILE_UNEXPECTED, "Found both nodal and zonal variable %s in exodus file. ", vecname);
13210a5cf5d8SBlaise Bourdin   if (offsetN >= 0) PetscCall(VecLoadPlex_ExodusII_Nodal_Internal(v, exoid, (PetscExodusIIInt)step + 1, offsetN + 1));
13220a5cf5d8SBlaise Bourdin   else if (offsetZ >= 0) PetscCall(VecLoadPlex_ExodusII_Zonal_Internal(v, exoid, (PetscExodusIIInt)step + 1, offsetZ + 1));
132349c89c76SBlaise Bourdin   else SETERRQ(comm, PETSC_ERR_FILE_UNEXPECTED, "Could not find nodal or zonal variable %s in exodus file. ", vecname);
132449c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
132549c89c76SBlaise Bourdin }
132649c89c76SBlaise Bourdin 
13270a5cf5d8SBlaise Bourdin static PetscErrorCode VecViewPlex_ExodusII_Nodal_Internal(Vec v, PetscExodusIIInt exoid, PetscExodusIIInt step, PetscExodusIIInt offset)
132849c89c76SBlaise Bourdin {
132949c89c76SBlaise Bourdin   MPI_Comm           comm;
133049c89c76SBlaise Bourdin   PetscMPIInt        size;
133149c89c76SBlaise Bourdin   DM                 dm;
133249c89c76SBlaise Bourdin   Vec                vNatural, vComp;
133349c89c76SBlaise Bourdin   const PetscScalar *varray;
133449c89c76SBlaise Bourdin   PetscInt           xs, xe, bs;
133549c89c76SBlaise Bourdin   PetscBool          useNatural;
133649c89c76SBlaise Bourdin 
133749c89c76SBlaise Bourdin   PetscFunctionBegin;
133849c89c76SBlaise Bourdin   PetscCall(PetscObjectGetComm((PetscObject)v, &comm));
133949c89c76SBlaise Bourdin   PetscCallMPI(MPI_Comm_size(comm, &size));
134049c89c76SBlaise Bourdin   PetscCall(VecGetDM(v, &dm));
134149c89c76SBlaise Bourdin   PetscCall(DMGetUseNatural(dm, &useNatural));
134249c89c76SBlaise Bourdin   useNatural = useNatural && size > 1 ? PETSC_TRUE : PETSC_FALSE;
134349c89c76SBlaise Bourdin   if (useNatural) {
134449c89c76SBlaise Bourdin     PetscCall(DMPlexCreateNaturalVector(dm, &vNatural));
134549c89c76SBlaise Bourdin     PetscCall(DMPlexGlobalToNaturalBegin(dm, v, vNatural));
134649c89c76SBlaise Bourdin     PetscCall(DMPlexGlobalToNaturalEnd(dm, v, vNatural));
134749c89c76SBlaise Bourdin   } else {
134849c89c76SBlaise Bourdin     vNatural = v;
134949c89c76SBlaise Bourdin   }
135049c89c76SBlaise Bourdin 
135149c89c76SBlaise Bourdin   /* Write local chunk of the result in the exodus file
135249c89c76SBlaise Bourdin      exodus stores each component of a vector-valued field as a separate variable.
135349c89c76SBlaise Bourdin      We assume that they are stored sequentially */
135449c89c76SBlaise Bourdin   PetscCall(VecGetOwnershipRange(vNatural, &xs, &xe));
135549c89c76SBlaise Bourdin   PetscCall(VecGetBlockSize(vNatural, &bs));
135649c89c76SBlaise Bourdin   if (bs == 1) {
135749c89c76SBlaise Bourdin     PetscCall(VecGetArrayRead(vNatural, &varray));
135849c89c76SBlaise Bourdin     PetscCallExternal(ex_put_partial_var, exoid, step, EX_NODAL, offset, 1, xs + 1, xe - xs, varray);
135949c89c76SBlaise Bourdin     PetscCall(VecRestoreArrayRead(vNatural, &varray));
136049c89c76SBlaise Bourdin   } else {
136149c89c76SBlaise Bourdin     IS       compIS;
136249c89c76SBlaise Bourdin     PetscInt c;
136349c89c76SBlaise Bourdin 
136449c89c76SBlaise Bourdin     PetscCall(ISCreateStride(comm, (xe - xs) / bs, xs, bs, &compIS));
136549c89c76SBlaise Bourdin     for (c = 0; c < bs; ++c) {
136649c89c76SBlaise Bourdin       PetscCall(ISStrideSetStride(compIS, (xe - xs) / bs, xs + c, bs));
136749c89c76SBlaise Bourdin       PetscCall(VecGetSubVector(vNatural, compIS, &vComp));
136849c89c76SBlaise Bourdin       PetscCall(VecGetArrayRead(vComp, &varray));
136949c89c76SBlaise Bourdin       PetscCallExternal(ex_put_partial_var, exoid, step, EX_NODAL, offset + c, 1, xs / bs + 1, (xe - xs) / bs, varray);
137049c89c76SBlaise Bourdin       PetscCall(VecRestoreArrayRead(vComp, &varray));
137149c89c76SBlaise Bourdin       PetscCall(VecRestoreSubVector(vNatural, compIS, &vComp));
137249c89c76SBlaise Bourdin     }
137349c89c76SBlaise Bourdin     PetscCall(ISDestroy(&compIS));
137449c89c76SBlaise Bourdin   }
137549c89c76SBlaise Bourdin   if (useNatural) PetscCall(VecDestroy(&vNatural));
137649c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
137749c89c76SBlaise Bourdin }
137849c89c76SBlaise Bourdin 
13790a5cf5d8SBlaise Bourdin static PetscErrorCode VecLoadPlex_ExodusII_Nodal_Internal(Vec v, PetscExodusIIInt exoid, PetscExodusIIInt step, PetscExodusIIInt offset)
138049c89c76SBlaise Bourdin {
138149c89c76SBlaise Bourdin   MPI_Comm     comm;
138249c89c76SBlaise Bourdin   PetscMPIInt  size;
138349c89c76SBlaise Bourdin   DM           dm;
138449c89c76SBlaise Bourdin   Vec          vNatural, vComp;
138549c89c76SBlaise Bourdin   PetscScalar *varray;
138649c89c76SBlaise Bourdin   PetscInt     xs, xe, bs;
138749c89c76SBlaise Bourdin   PetscBool    useNatural;
138849c89c76SBlaise Bourdin 
138949c89c76SBlaise Bourdin   PetscFunctionBegin;
139049c89c76SBlaise Bourdin   PetscCall(PetscObjectGetComm((PetscObject)v, &comm));
139149c89c76SBlaise Bourdin   PetscCallMPI(MPI_Comm_size(comm, &size));
139249c89c76SBlaise Bourdin   PetscCall(VecGetDM(v, &dm));
139349c89c76SBlaise Bourdin   PetscCall(DMGetUseNatural(dm, &useNatural));
139449c89c76SBlaise Bourdin   useNatural = useNatural && size > 1 ? PETSC_TRUE : PETSC_FALSE;
139549c89c76SBlaise Bourdin   if (useNatural) PetscCall(DMPlexCreateNaturalVector(dm, &vNatural));
139649c89c76SBlaise Bourdin   else vNatural = v;
139749c89c76SBlaise Bourdin 
139849c89c76SBlaise Bourdin   /* Read local chunk from the file */
139949c89c76SBlaise Bourdin   PetscCall(VecGetOwnershipRange(vNatural, &xs, &xe));
140049c89c76SBlaise Bourdin   PetscCall(VecGetBlockSize(vNatural, &bs));
140149c89c76SBlaise Bourdin   if (bs == 1) {
140249c89c76SBlaise Bourdin     PetscCall(VecGetArray(vNatural, &varray));
140349c89c76SBlaise Bourdin     PetscCallExternal(ex_get_partial_var, exoid, step, EX_NODAL, offset, 1, xs + 1, xe - xs, varray);
140449c89c76SBlaise Bourdin     PetscCall(VecRestoreArray(vNatural, &varray));
140549c89c76SBlaise Bourdin   } else {
140649c89c76SBlaise Bourdin     IS       compIS;
140749c89c76SBlaise Bourdin     PetscInt c;
140849c89c76SBlaise Bourdin 
140949c89c76SBlaise Bourdin     PetscCall(ISCreateStride(comm, (xe - xs) / bs, xs, bs, &compIS));
141049c89c76SBlaise Bourdin     for (c = 0; c < bs; ++c) {
141149c89c76SBlaise Bourdin       PetscCall(ISStrideSetStride(compIS, (xe - xs) / bs, xs + c, bs));
141249c89c76SBlaise Bourdin       PetscCall(VecGetSubVector(vNatural, compIS, &vComp));
141349c89c76SBlaise Bourdin       PetscCall(VecGetArray(vComp, &varray));
141449c89c76SBlaise Bourdin       PetscCallExternal(ex_get_partial_var, exoid, step, EX_NODAL, offset + c, 1, xs / bs + 1, (xe - xs) / bs, varray);
141549c89c76SBlaise Bourdin       PetscCall(VecRestoreArray(vComp, &varray));
141649c89c76SBlaise Bourdin       PetscCall(VecRestoreSubVector(vNatural, compIS, &vComp));
141749c89c76SBlaise Bourdin     }
141849c89c76SBlaise Bourdin     PetscCall(ISDestroy(&compIS));
141949c89c76SBlaise Bourdin   }
142049c89c76SBlaise Bourdin   if (useNatural) {
142149c89c76SBlaise Bourdin     PetscCall(DMPlexNaturalToGlobalBegin(dm, vNatural, v));
142249c89c76SBlaise Bourdin     PetscCall(DMPlexNaturalToGlobalEnd(dm, vNatural, v));
142349c89c76SBlaise Bourdin     PetscCall(VecDestroy(&vNatural));
142449c89c76SBlaise Bourdin   }
142549c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
142649c89c76SBlaise Bourdin }
142749c89c76SBlaise Bourdin 
14280a5cf5d8SBlaise Bourdin static PetscErrorCode VecViewPlex_ExodusII_Zonal_Internal(Vec v, PetscExodusIIInt exoid, PetscExodusIIInt step, PetscExodusIIInt offset)
142949c89c76SBlaise Bourdin {
143049c89c76SBlaise Bourdin   MPI_Comm           comm;
143149c89c76SBlaise Bourdin   PetscMPIInt        size;
143249c89c76SBlaise Bourdin   DM                 dm;
143349c89c76SBlaise Bourdin   Vec                vNatural, vComp;
143449c89c76SBlaise Bourdin   const PetscScalar *varray;
143549c89c76SBlaise Bourdin   PetscInt           xs, xe, bs;
143649c89c76SBlaise Bourdin   PetscBool          useNatural;
143749c89c76SBlaise Bourdin   IS                 compIS;
143849c89c76SBlaise Bourdin   PetscInt          *csSize, *csID;
14390a5cf5d8SBlaise Bourdin   PetscExodusIIInt   numCS, set, csxs = 0;
144049c89c76SBlaise Bourdin 
144149c89c76SBlaise Bourdin   PetscFunctionBegin;
144249c89c76SBlaise Bourdin   PetscCall(PetscObjectGetComm((PetscObject)v, &comm));
144349c89c76SBlaise Bourdin   PetscCallMPI(MPI_Comm_size(comm, &size));
144449c89c76SBlaise Bourdin   PetscCall(VecGetDM(v, &dm));
144549c89c76SBlaise Bourdin   PetscCall(DMGetUseNatural(dm, &useNatural));
144649c89c76SBlaise Bourdin   useNatural = useNatural && size > 1 ? PETSC_TRUE : PETSC_FALSE;
144749c89c76SBlaise Bourdin   if (useNatural) {
144849c89c76SBlaise Bourdin     PetscCall(DMPlexCreateNaturalVector(dm, &vNatural));
144949c89c76SBlaise Bourdin     PetscCall(DMPlexGlobalToNaturalBegin(dm, v, vNatural));
145049c89c76SBlaise Bourdin     PetscCall(DMPlexGlobalToNaturalEnd(dm, v, vNatural));
145149c89c76SBlaise Bourdin   } else {
145249c89c76SBlaise Bourdin     vNatural = v;
145349c89c76SBlaise Bourdin   }
145449c89c76SBlaise Bourdin 
145549c89c76SBlaise Bourdin   /* Write local chunk of the result in the exodus file
145649c89c76SBlaise Bourdin      exodus stores each component of a vector-valued field as a separate variable.
145749c89c76SBlaise Bourdin      We assume that they are stored sequentially
145849c89c76SBlaise Bourdin      Zonal variables are accessed one element block at a time, so we loop through the cell sets,
145949c89c76SBlaise Bourdin      but once the vector has been reordered to natural size, we cannot use the label information
146049c89c76SBlaise Bourdin      to figure out what to save where. */
1461*8a1c49cdSMatthew G. Knepley   numCS = (PetscExodusIIInt)ex_inquire_int(exoid, EX_INQ_ELEM_BLK); // This is an int64_t
146249c89c76SBlaise Bourdin   PetscCall(PetscMalloc2(numCS, &csID, numCS, &csSize));
146349c89c76SBlaise Bourdin   PetscCallExternal(ex_get_ids, exoid, EX_ELEM_BLOCK, csID);
146449c89c76SBlaise Bourdin   for (set = 0; set < numCS; ++set) {
146549c89c76SBlaise Bourdin     ex_block block;
146649c89c76SBlaise Bourdin 
146749c89c76SBlaise Bourdin     block.id   = csID[set];
146849c89c76SBlaise Bourdin     block.type = EX_ELEM_BLOCK;
146949c89c76SBlaise Bourdin     PetscCallExternal(ex_get_block_param, exoid, &block);
1470*8a1c49cdSMatthew G. Knepley     csSize[set] = (PetscInt)block.num_entry; // This is an int64_t
147149c89c76SBlaise Bourdin   }
147249c89c76SBlaise Bourdin   PetscCall(VecGetOwnershipRange(vNatural, &xs, &xe));
147349c89c76SBlaise Bourdin   PetscCall(VecGetBlockSize(vNatural, &bs));
147449c89c76SBlaise Bourdin   if (bs > 1) PetscCall(ISCreateStride(comm, (xe - xs) / bs, xs, bs, &compIS));
147549c89c76SBlaise Bourdin   for (set = 0; set < numCS; set++) {
147649c89c76SBlaise Bourdin     PetscInt csLocalSize, c;
147749c89c76SBlaise Bourdin 
147849c89c76SBlaise Bourdin     /* range of indices for set setID[set]: csxs:csxs + csSize[set]-1
147949c89c76SBlaise Bourdin        local slice of zonal values:         xs/bs,xm/bs-1
148049c89c76SBlaise Bourdin        intersection:                        max(xs/bs,csxs),min(xm/bs-1,csxs + csSize[set]-1) */
148149c89c76SBlaise Bourdin     csLocalSize = PetscMax(0, PetscMin(xe / bs, csxs + csSize[set]) - PetscMax(xs / bs, csxs));
148249c89c76SBlaise Bourdin     if (bs == 1) {
148349c89c76SBlaise Bourdin       PetscCall(VecGetArrayRead(vNatural, &varray));
148449c89c76SBlaise Bourdin       PetscCallExternal(ex_put_partial_var, exoid, step, EX_ELEM_BLOCK, offset, csID[set], PetscMax(xs - csxs, 0) + 1, csLocalSize, &varray[PetscMax(0, csxs - xs)]);
148549c89c76SBlaise Bourdin       PetscCall(VecRestoreArrayRead(vNatural, &varray));
148649c89c76SBlaise Bourdin     } else {
148749c89c76SBlaise Bourdin       for (c = 0; c < bs; ++c) {
148849c89c76SBlaise Bourdin         PetscCall(ISStrideSetStride(compIS, (xe - xs) / bs, xs + c, bs));
148949c89c76SBlaise Bourdin         PetscCall(VecGetSubVector(vNatural, compIS, &vComp));
149049c89c76SBlaise Bourdin         PetscCall(VecGetArrayRead(vComp, &varray));
149149c89c76SBlaise Bourdin         PetscCallExternal(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)]);
149249c89c76SBlaise Bourdin         PetscCall(VecRestoreArrayRead(vComp, &varray));
149349c89c76SBlaise Bourdin         PetscCall(VecRestoreSubVector(vNatural, compIS, &vComp));
149449c89c76SBlaise Bourdin       }
149549c89c76SBlaise Bourdin     }
149649c89c76SBlaise Bourdin     csxs += csSize[set];
149749c89c76SBlaise Bourdin   }
149849c89c76SBlaise Bourdin   PetscCall(PetscFree2(csID, csSize));
149949c89c76SBlaise Bourdin   if (bs > 1) PetscCall(ISDestroy(&compIS));
150049c89c76SBlaise Bourdin   if (useNatural) PetscCall(VecDestroy(&vNatural));
150149c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
150249c89c76SBlaise Bourdin }
150349c89c76SBlaise Bourdin 
15040a5cf5d8SBlaise Bourdin static PetscErrorCode VecLoadPlex_ExodusII_Zonal_Internal(Vec v, PetscExodusIIInt exoid, PetscExodusIIInt step, PetscExodusIIInt offset)
150549c89c76SBlaise Bourdin {
150649c89c76SBlaise Bourdin   MPI_Comm         comm;
150749c89c76SBlaise Bourdin   PetscMPIInt      size;
150849c89c76SBlaise Bourdin   DM               dm;
150949c89c76SBlaise Bourdin   Vec              vNatural, vComp;
151049c89c76SBlaise Bourdin   PetscScalar     *varray;
151149c89c76SBlaise Bourdin   PetscInt         xs, xe, bs;
151249c89c76SBlaise Bourdin   PetscBool        useNatural;
151349c89c76SBlaise Bourdin   IS               compIS;
151449c89c76SBlaise Bourdin   PetscInt        *csSize, *csID;
15150a5cf5d8SBlaise Bourdin   PetscExodusIIInt numCS, set, csxs = 0;
151649c89c76SBlaise Bourdin 
151749c89c76SBlaise Bourdin   PetscFunctionBegin;
151849c89c76SBlaise Bourdin   PetscCall(PetscObjectGetComm((PetscObject)v, &comm));
151949c89c76SBlaise Bourdin   PetscCallMPI(MPI_Comm_size(comm, &size));
152049c89c76SBlaise Bourdin   PetscCall(VecGetDM(v, &dm));
152149c89c76SBlaise Bourdin   PetscCall(DMGetUseNatural(dm, &useNatural));
152249c89c76SBlaise Bourdin   useNatural = useNatural && size > 1 ? PETSC_TRUE : PETSC_FALSE;
152349c89c76SBlaise Bourdin   if (useNatural) PetscCall(DMPlexCreateNaturalVector(dm, &vNatural));
152449c89c76SBlaise Bourdin   else vNatural = v;
152549c89c76SBlaise Bourdin 
152649c89c76SBlaise Bourdin   /* Read local chunk of the result in the exodus file
152749c89c76SBlaise Bourdin      exodus stores each component of a vector-valued field as a separate variable.
152849c89c76SBlaise Bourdin      We assume that they are stored sequentially
152949c89c76SBlaise Bourdin      Zonal variables are accessed one element block at a time, so we loop through the cell sets,
153049c89c76SBlaise Bourdin      but once the vector has been reordered to natural size, we cannot use the label information
153149c89c76SBlaise Bourdin      to figure out what to save where. */
1532*8a1c49cdSMatthew G. Knepley   numCS = (PetscExodusIIInt)ex_inquire_int(exoid, EX_INQ_ELEM_BLK); // This is an int64_t
153349c89c76SBlaise Bourdin   PetscCall(PetscMalloc2(numCS, &csID, numCS, &csSize));
153449c89c76SBlaise Bourdin   PetscCallExternal(ex_get_ids, exoid, EX_ELEM_BLOCK, csID);
153549c89c76SBlaise Bourdin   for (set = 0; set < numCS; ++set) {
153649c89c76SBlaise Bourdin     ex_block block;
153749c89c76SBlaise Bourdin 
153849c89c76SBlaise Bourdin     block.id   = csID[set];
153949c89c76SBlaise Bourdin     block.type = EX_ELEM_BLOCK;
154049c89c76SBlaise Bourdin     PetscCallExternal(ex_get_block_param, exoid, &block);
1541*8a1c49cdSMatthew G. Knepley     csSize[set] = (PetscInt)block.num_entry; // This is an int64_t
154249c89c76SBlaise Bourdin   }
154349c89c76SBlaise Bourdin   PetscCall(VecGetOwnershipRange(vNatural, &xs, &xe));
154449c89c76SBlaise Bourdin   PetscCall(VecGetBlockSize(vNatural, &bs));
154549c89c76SBlaise Bourdin   if (bs > 1) PetscCall(ISCreateStride(comm, (xe - xs) / bs, xs, bs, &compIS));
154649c89c76SBlaise Bourdin   for (set = 0; set < numCS; ++set) {
154749c89c76SBlaise Bourdin     PetscInt csLocalSize, c;
154849c89c76SBlaise Bourdin 
154949c89c76SBlaise Bourdin     /* range of indices for set setID[set]: csxs:csxs + csSize[set]-1
155049c89c76SBlaise Bourdin        local slice of zonal values:         xs/bs,xm/bs-1
155149c89c76SBlaise Bourdin        intersection:                        max(xs/bs,csxs),min(xm/bs-1,csxs + csSize[set]-1) */
155249c89c76SBlaise Bourdin     csLocalSize = PetscMax(0, PetscMin(xe / bs, csxs + csSize[set]) - PetscMax(xs / bs, csxs));
155349c89c76SBlaise Bourdin     if (bs == 1) {
155449c89c76SBlaise Bourdin       PetscCall(VecGetArray(vNatural, &varray));
155549c89c76SBlaise Bourdin       PetscCallExternal(ex_get_partial_var, exoid, step, EX_ELEM_BLOCK, offset, csID[set], PetscMax(xs - csxs, 0) + 1, csLocalSize, &varray[PetscMax(0, csxs - xs)]);
155649c89c76SBlaise Bourdin       PetscCall(VecRestoreArray(vNatural, &varray));
155749c89c76SBlaise Bourdin     } else {
155849c89c76SBlaise Bourdin       for (c = 0; c < bs; ++c) {
155949c89c76SBlaise Bourdin         PetscCall(ISStrideSetStride(compIS, (xe - xs) / bs, xs + c, bs));
156049c89c76SBlaise Bourdin         PetscCall(VecGetSubVector(vNatural, compIS, &vComp));
156149c89c76SBlaise Bourdin         PetscCall(VecGetArray(vComp, &varray));
156249c89c76SBlaise Bourdin         PetscCallExternal(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)]);
156349c89c76SBlaise Bourdin         PetscCall(VecRestoreArray(vComp, &varray));
156449c89c76SBlaise Bourdin         PetscCall(VecRestoreSubVector(vNatural, compIS, &vComp));
156549c89c76SBlaise Bourdin       }
156649c89c76SBlaise Bourdin     }
156749c89c76SBlaise Bourdin     csxs += csSize[set];
156849c89c76SBlaise Bourdin   }
156949c89c76SBlaise Bourdin   PetscCall(PetscFree2(csID, csSize));
157049c89c76SBlaise Bourdin   if (bs > 1) PetscCall(ISDestroy(&compIS));
157149c89c76SBlaise Bourdin   if (useNatural) {
157249c89c76SBlaise Bourdin     PetscCall(DMPlexNaturalToGlobalBegin(dm, vNatural, v));
157349c89c76SBlaise Bourdin     PetscCall(DMPlexNaturalToGlobalEnd(dm, vNatural, v));
157449c89c76SBlaise Bourdin     PetscCall(VecDestroy(&vNatural));
157549c89c76SBlaise Bourdin   }
157649c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
157749c89c76SBlaise Bourdin }
157849c89c76SBlaise Bourdin 
157949c89c76SBlaise Bourdin /*@
158049c89c76SBlaise Bourdin   PetscViewerExodusIIGetId - Get the file id of the `PETSCVIEWEREXODUSII` file
158149c89c76SBlaise Bourdin 
158249c89c76SBlaise Bourdin   Logically Collective
158349c89c76SBlaise Bourdin 
158449c89c76SBlaise Bourdin   Input Parameter:
158549c89c76SBlaise Bourdin . viewer - the `PetscViewer`
158649c89c76SBlaise Bourdin 
158749c89c76SBlaise Bourdin   Output Parameter:
158849c89c76SBlaise Bourdin . exoid - The ExodusII file id
158949c89c76SBlaise Bourdin 
159049c89c76SBlaise Bourdin   Level: intermediate
159149c89c76SBlaise Bourdin 
159249c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`
159349c89c76SBlaise Bourdin @*/
15940a5cf5d8SBlaise Bourdin PetscErrorCode PetscViewerExodusIIGetId(PetscViewer viewer, PetscExodusIIInt *exoid)
159549c89c76SBlaise Bourdin {
159649c89c76SBlaise Bourdin   PetscFunctionBegin;
159749c89c76SBlaise Bourdin   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
15980a5cf5d8SBlaise Bourdin   PetscTryMethod(viewer, "PetscViewerGetId_C", (PetscViewer, PetscExodusIIInt *), (viewer, exoid));
159949c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
160049c89c76SBlaise Bourdin }
160149c89c76SBlaise Bourdin 
160249c89c76SBlaise Bourdin /*@
160349c89c76SBlaise Bourdin   PetscViewerExodusIISetOrder - Set the elements order in the exodusII file.
160449c89c76SBlaise Bourdin 
160549c89c76SBlaise Bourdin   Collective
160649c89c76SBlaise Bourdin 
160749c89c76SBlaise Bourdin   Input Parameters:
160849c89c76SBlaise Bourdin + viewer - the `PETSCVIEWEREXODUSII` viewer
160949c89c76SBlaise Bourdin - order  - elements order
161049c89c76SBlaise Bourdin 
161149c89c76SBlaise Bourdin   Output Parameter:
161249c89c76SBlaise Bourdin 
161349c89c76SBlaise Bourdin   Level: beginner
161449c89c76SBlaise Bourdin 
161549c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerExodusIIGetId()`, `PetscViewerExodusIIGetOrder()`
161649c89c76SBlaise Bourdin @*/
16170a5cf5d8SBlaise Bourdin PetscErrorCode PetscViewerExodusIISetOrder(PetscViewer viewer, PetscInt order)
161849c89c76SBlaise Bourdin {
161949c89c76SBlaise Bourdin   PetscFunctionBegin;
162049c89c76SBlaise Bourdin   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
16210a5cf5d8SBlaise Bourdin   PetscTryMethod(viewer, "PetscViewerSetOrder_C", (PetscViewer, PetscInt), (viewer, order));
162249c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
162349c89c76SBlaise Bourdin }
162449c89c76SBlaise Bourdin 
162549c89c76SBlaise Bourdin /*@
162649c89c76SBlaise Bourdin   PetscViewerExodusIIGetOrder - Get the elements order in the exodusII file.
162749c89c76SBlaise Bourdin 
162849c89c76SBlaise Bourdin   Collective
162949c89c76SBlaise Bourdin 
163049c89c76SBlaise Bourdin   Input Parameters:
163149c89c76SBlaise Bourdin + viewer - the `PETSCVIEWEREXODUSII` viewer
163249c89c76SBlaise Bourdin - order  - elements order
163349c89c76SBlaise Bourdin 
163449c89c76SBlaise Bourdin   Output Parameter:
163549c89c76SBlaise Bourdin 
163649c89c76SBlaise Bourdin   Level: beginner
163749c89c76SBlaise Bourdin 
163849c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerExodusIIGetId()`, `PetscViewerExodusIISetOrder()`
163949c89c76SBlaise Bourdin @*/
16400a5cf5d8SBlaise Bourdin PetscErrorCode PetscViewerExodusIIGetOrder(PetscViewer viewer, PetscInt *order)
164149c89c76SBlaise Bourdin {
164249c89c76SBlaise Bourdin   PetscFunctionBegin;
164349c89c76SBlaise Bourdin   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
16440a5cf5d8SBlaise Bourdin   PetscTryMethod(viewer, "PetscViewerGetOrder_C", (PetscViewer, PetscInt *), (viewer, order));
164549c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
164649c89c76SBlaise Bourdin }
164749c89c76SBlaise Bourdin 
164849c89c76SBlaise Bourdin /*@
164949c89c76SBlaise Bourdin   PetscViewerExodusIIOpen - Opens a file for ExodusII input/output.
165049c89c76SBlaise Bourdin 
165149c89c76SBlaise Bourdin   Collective
165249c89c76SBlaise Bourdin 
165349c89c76SBlaise Bourdin   Input Parameters:
165449c89c76SBlaise Bourdin + comm - MPI communicator
165549c89c76SBlaise Bourdin . name - name of file
165649c89c76SBlaise Bourdin - mode - access mode
165749c89c76SBlaise Bourdin .vb
165849c89c76SBlaise Bourdin     FILE_MODE_WRITE - create new file for binary output
165949c89c76SBlaise Bourdin     FILE_MODE_READ - open existing file for binary input
166049c89c76SBlaise Bourdin     FILE_MODE_APPEND - open existing file for binary output
166149c89c76SBlaise Bourdin .ve
166249c89c76SBlaise Bourdin 
166349c89c76SBlaise Bourdin   Output Parameter:
166449c89c76SBlaise Bourdin . exo - `PETSCVIEWEREXODUSII` `PetscViewer` for Exodus II input/output to use with the specified file
166549c89c76SBlaise Bourdin 
166649c89c76SBlaise Bourdin   Level: beginner
166749c89c76SBlaise Bourdin 
166849c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
166949c89c76SBlaise Bourdin           `DMLoad()`, `PetscFileMode`, `PetscViewerSetType()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()`
167049c89c76SBlaise Bourdin @*/
167149c89c76SBlaise Bourdin PetscErrorCode PetscViewerExodusIIOpen(MPI_Comm comm, const char name[], PetscFileMode mode, PetscViewer *exo)
167249c89c76SBlaise Bourdin {
167349c89c76SBlaise Bourdin   PetscFunctionBegin;
167449c89c76SBlaise Bourdin   PetscCall(PetscViewerCreate(comm, exo));
167549c89c76SBlaise Bourdin   PetscCall(PetscViewerSetType(*exo, PETSCVIEWEREXODUSII));
167649c89c76SBlaise Bourdin   PetscCall(PetscViewerFileSetMode(*exo, mode));
167749c89c76SBlaise Bourdin   PetscCall(PetscViewerFileSetName(*exo, name));
167849c89c76SBlaise Bourdin   PetscCall(PetscViewerSetFromOptions(*exo));
167949c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
168049c89c76SBlaise Bourdin }
168149c89c76SBlaise Bourdin 
168249c89c76SBlaise Bourdin static PetscErrorCode ExodusGetCellType_Internal(const char *elem_type, DMPolytopeType *ct)
168349c89c76SBlaise Bourdin {
168449c89c76SBlaise Bourdin   PetscBool flg;
168549c89c76SBlaise Bourdin 
168649c89c76SBlaise Bourdin   PetscFunctionBegin;
168749c89c76SBlaise Bourdin   *ct = DM_POLYTOPE_UNKNOWN;
168849c89c76SBlaise Bourdin   PetscCall(PetscStrcmp(elem_type, "BAR2", &flg));
168949c89c76SBlaise Bourdin   if (flg) {
169049c89c76SBlaise Bourdin     *ct = DM_POLYTOPE_SEGMENT;
169149c89c76SBlaise Bourdin     goto done;
169249c89c76SBlaise Bourdin   }
169349c89c76SBlaise Bourdin   PetscCall(PetscStrcmp(elem_type, "BAR3", &flg));
169449c89c76SBlaise Bourdin   if (flg) {
169549c89c76SBlaise Bourdin     *ct = DM_POLYTOPE_SEGMENT;
169649c89c76SBlaise Bourdin     goto done;
169749c89c76SBlaise Bourdin   }
169849c89c76SBlaise Bourdin   PetscCall(PetscStrcmp(elem_type, "TRI", &flg));
169949c89c76SBlaise Bourdin   if (flg) {
170049c89c76SBlaise Bourdin     *ct = DM_POLYTOPE_TRIANGLE;
170149c89c76SBlaise Bourdin     goto done;
170249c89c76SBlaise Bourdin   }
170349c89c76SBlaise Bourdin   PetscCall(PetscStrcmp(elem_type, "TRI3", &flg));
170449c89c76SBlaise Bourdin   if (flg) {
170549c89c76SBlaise Bourdin     *ct = DM_POLYTOPE_TRIANGLE;
170649c89c76SBlaise Bourdin     goto done;
170749c89c76SBlaise Bourdin   }
170849c89c76SBlaise Bourdin   PetscCall(PetscStrcmp(elem_type, "QUAD", &flg));
170949c89c76SBlaise Bourdin   if (flg) {
171049c89c76SBlaise Bourdin     *ct = DM_POLYTOPE_QUADRILATERAL;
171149c89c76SBlaise Bourdin     goto done;
171249c89c76SBlaise Bourdin   }
171349c89c76SBlaise Bourdin   PetscCall(PetscStrcmp(elem_type, "QUAD4", &flg));
171449c89c76SBlaise Bourdin   if (flg) {
171549c89c76SBlaise Bourdin     *ct = DM_POLYTOPE_QUADRILATERAL;
171649c89c76SBlaise Bourdin     goto done;
171749c89c76SBlaise Bourdin   }
171849c89c76SBlaise Bourdin   PetscCall(PetscStrcmp(elem_type, "SHELL4", &flg));
171949c89c76SBlaise Bourdin   if (flg) {
172049c89c76SBlaise Bourdin     *ct = DM_POLYTOPE_QUADRILATERAL;
172149c89c76SBlaise Bourdin     goto done;
172249c89c76SBlaise Bourdin   }
172349c89c76SBlaise Bourdin   PetscCall(PetscStrcmp(elem_type, "TETRA", &flg));
172449c89c76SBlaise Bourdin   if (flg) {
172549c89c76SBlaise Bourdin     *ct = DM_POLYTOPE_TETRAHEDRON;
172649c89c76SBlaise Bourdin     goto done;
172749c89c76SBlaise Bourdin   }
172849c89c76SBlaise Bourdin   PetscCall(PetscStrcmp(elem_type, "TET4", &flg));
172949c89c76SBlaise Bourdin   if (flg) {
173049c89c76SBlaise Bourdin     *ct = DM_POLYTOPE_TETRAHEDRON;
173149c89c76SBlaise Bourdin     goto done;
173249c89c76SBlaise Bourdin   }
173349c89c76SBlaise Bourdin   PetscCall(PetscStrcmp(elem_type, "WEDGE", &flg));
173449c89c76SBlaise Bourdin   if (flg) {
173549c89c76SBlaise Bourdin     *ct = DM_POLYTOPE_TRI_PRISM;
173649c89c76SBlaise Bourdin     goto done;
173749c89c76SBlaise Bourdin   }
173849c89c76SBlaise Bourdin   PetscCall(PetscStrcmp(elem_type, "HEX", &flg));
173949c89c76SBlaise Bourdin   if (flg) {
174049c89c76SBlaise Bourdin     *ct = DM_POLYTOPE_HEXAHEDRON;
174149c89c76SBlaise Bourdin     goto done;
174249c89c76SBlaise Bourdin   }
174349c89c76SBlaise Bourdin   PetscCall(PetscStrcmp(elem_type, "HEX8", &flg));
174449c89c76SBlaise Bourdin   if (flg) {
174549c89c76SBlaise Bourdin     *ct = DM_POLYTOPE_HEXAHEDRON;
174649c89c76SBlaise Bourdin     goto done;
174749c89c76SBlaise Bourdin   }
174849c89c76SBlaise Bourdin   PetscCall(PetscStrcmp(elem_type, "HEXAHEDRON", &flg));
174949c89c76SBlaise Bourdin   if (flg) {
175049c89c76SBlaise Bourdin     *ct = DM_POLYTOPE_HEXAHEDRON;
175149c89c76SBlaise Bourdin     goto done;
175249c89c76SBlaise Bourdin   }
175349c89c76SBlaise Bourdin   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unrecognized element type %s", elem_type);
175449c89c76SBlaise Bourdin done:
175549c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
175649c89c76SBlaise Bourdin }
175749c89c76SBlaise Bourdin 
175849c89c76SBlaise Bourdin /*@
175949c89c76SBlaise Bourdin   DMPlexCreateExodus - Create a `DMPLEX` mesh from an ExodusII file ID.
176049c89c76SBlaise Bourdin 
176149c89c76SBlaise Bourdin   Collective
176249c89c76SBlaise Bourdin 
176349c89c76SBlaise Bourdin   Input Parameters:
176449c89c76SBlaise Bourdin + comm        - The MPI communicator
176549c89c76SBlaise Bourdin . exoid       - The ExodusII id associated with a exodus file and obtained using ex_open
176649c89c76SBlaise Bourdin - interpolate - Create faces and edges in the mesh
176749c89c76SBlaise Bourdin 
176849c89c76SBlaise Bourdin   Output Parameter:
176949c89c76SBlaise Bourdin . dm - The `DM` object representing the mesh
177049c89c76SBlaise Bourdin 
177149c89c76SBlaise Bourdin   Level: beginner
177249c89c76SBlaise Bourdin 
177349c89c76SBlaise Bourdin .seealso: [](ch_unstructured), `DM`, `PETSCVIEWEREXODUSII`, `DMPLEX`, `DMCreate()`
177449c89c76SBlaise Bourdin @*/
17750a5cf5d8SBlaise Bourdin PetscErrorCode DMPlexCreateExodus(MPI_Comm comm, PetscExodusIIInt exoid, PetscBool interpolate, DM *dm)
177649c89c76SBlaise Bourdin {
177749c89c76SBlaise Bourdin   PetscMPIInt  num_proc, rank;
177849c89c76SBlaise Bourdin   DMLabel      cellSets = NULL, faceSets = NULL, vertSets = NULL;
177949c89c76SBlaise Bourdin   PetscSection coordSection;
178049c89c76SBlaise Bourdin   Vec          coordinates;
178149c89c76SBlaise Bourdin   PetscScalar *coords;
178249c89c76SBlaise Bourdin   PetscInt     coordSize, v;
178349c89c76SBlaise Bourdin   /* Read from ex_get_init() */
178449c89c76SBlaise Bourdin   char title[PETSC_MAX_PATH_LEN + 1];
178549c89c76SBlaise Bourdin   int  dim = 0, dimEmbed = 0, numVertices = 0, numCells = 0;
178649c89c76SBlaise Bourdin   int  num_cs = 0, num_vs = 0, num_fs = 0;
178749c89c76SBlaise Bourdin 
178849c89c76SBlaise Bourdin   PetscFunctionBegin;
178949c89c76SBlaise Bourdin   PetscCallMPI(MPI_Comm_rank(comm, &rank));
179049c89c76SBlaise Bourdin   PetscCallMPI(MPI_Comm_size(comm, &num_proc));
179149c89c76SBlaise Bourdin   PetscCall(DMCreate(comm, dm));
179249c89c76SBlaise Bourdin   PetscCall(DMSetType(*dm, DMPLEX));
179349c89c76SBlaise Bourdin   /* Open EXODUS II file and read basic information on rank 0, then broadcast to all processors */
179449c89c76SBlaise Bourdin   if (rank == 0) {
179549c89c76SBlaise Bourdin     PetscCall(PetscMemzero(title, PETSC_MAX_PATH_LEN + 1));
179649c89c76SBlaise Bourdin     PetscCallExternal(ex_get_init, exoid, title, &dimEmbed, &numVertices, &numCells, &num_cs, &num_vs, &num_fs);
179749c89c76SBlaise Bourdin     PetscCheck(num_cs, PETSC_COMM_SELF, PETSC_ERR_SUP, "Exodus file does not contain any cell set");
179849c89c76SBlaise Bourdin   }
179949c89c76SBlaise Bourdin   PetscCallMPI(MPI_Bcast(title, PETSC_MAX_PATH_LEN + 1, MPI_CHAR, 0, comm));
180049c89c76SBlaise Bourdin   PetscCallMPI(MPI_Bcast(&dim, 1, MPI_INT, 0, comm));
180149c89c76SBlaise Bourdin   PetscCall(PetscObjectSetName((PetscObject)*dm, title));
180249c89c76SBlaise Bourdin   PetscCall(DMPlexSetChart(*dm, 0, numCells + numVertices));
180349c89c76SBlaise Bourdin   /*   We do not want this label automatically computed, instead we compute it here */
180449c89c76SBlaise Bourdin   PetscCall(DMCreateLabel(*dm, "celltype"));
180549c89c76SBlaise Bourdin 
180649c89c76SBlaise Bourdin   /* Read cell sets information */
180749c89c76SBlaise Bourdin   if (rank == 0) {
180849c89c76SBlaise Bourdin     PetscInt *cone;
180949c89c76SBlaise Bourdin     int       c, cs, ncs, c_loc, v, v_loc;
181049c89c76SBlaise Bourdin     /* Read from ex_get_elem_blk_ids() */
181149c89c76SBlaise Bourdin     int *cs_id, *cs_order;
181249c89c76SBlaise Bourdin     /* Read from ex_get_elem_block() */
181349c89c76SBlaise Bourdin     char buffer[PETSC_MAX_PATH_LEN + 1];
181449c89c76SBlaise Bourdin     int  num_cell_in_set, num_vertex_per_cell, num_hybrid, num_attr;
181549c89c76SBlaise Bourdin     /* Read from ex_get_elem_conn() */
181649c89c76SBlaise Bourdin     int *cs_connect;
181749c89c76SBlaise Bourdin 
181849c89c76SBlaise Bourdin     /* Get cell sets IDs */
181949c89c76SBlaise Bourdin     PetscCall(PetscMalloc2(num_cs, &cs_id, num_cs, &cs_order));
182049c89c76SBlaise Bourdin     PetscCallExternal(ex_get_ids, exoid, EX_ELEM_BLOCK, cs_id);
182149c89c76SBlaise Bourdin     /* Read the cell set connectivity table and build mesh topology
182249c89c76SBlaise Bourdin        EXO standard requires that cells in cell sets be numbered sequentially and be pairwise disjoint. */
182349c89c76SBlaise Bourdin     /* Check for a hybrid mesh */
182449c89c76SBlaise Bourdin     for (cs = 0, num_hybrid = 0; cs < num_cs; ++cs) {
182549c89c76SBlaise Bourdin       DMPolytopeType ct;
182649c89c76SBlaise Bourdin       char           elem_type[PETSC_MAX_PATH_LEN];
182749c89c76SBlaise Bourdin 
182849c89c76SBlaise Bourdin       PetscCall(PetscArrayzero(elem_type, sizeof(elem_type)));
182949c89c76SBlaise Bourdin       PetscCallExternal(ex_get_elem_type, exoid, cs_id[cs], elem_type);
183049c89c76SBlaise Bourdin       PetscCall(ExodusGetCellType_Internal(elem_type, &ct));
183149c89c76SBlaise Bourdin       dim = PetscMax(dim, DMPolytopeTypeGetDim(ct));
183249c89c76SBlaise Bourdin       PetscCallExternal(ex_get_block, exoid, EX_ELEM_BLOCK, cs_id[cs], buffer, &num_cell_in_set, &num_vertex_per_cell, 0, 0, &num_attr);
183349c89c76SBlaise Bourdin       switch (ct) {
183449c89c76SBlaise Bourdin       case DM_POLYTOPE_TRI_PRISM:
183549c89c76SBlaise Bourdin         cs_order[cs] = cs;
183649c89c76SBlaise Bourdin         ++num_hybrid;
183749c89c76SBlaise Bourdin         break;
183849c89c76SBlaise Bourdin       default:
183949c89c76SBlaise Bourdin         for (c = cs; c > cs - num_hybrid; --c) cs_order[c] = cs_order[c - 1];
184049c89c76SBlaise Bourdin         cs_order[cs - num_hybrid] = cs;
184149c89c76SBlaise Bourdin       }
184249c89c76SBlaise Bourdin     }
184349c89c76SBlaise Bourdin     /* First set sizes */
184449c89c76SBlaise Bourdin     for (ncs = 0, c = 0; ncs < num_cs; ++ncs) {
184549c89c76SBlaise Bourdin       DMPolytopeType ct;
184649c89c76SBlaise Bourdin       char           elem_type[PETSC_MAX_PATH_LEN];
184749c89c76SBlaise Bourdin       const PetscInt cs = cs_order[ncs];
184849c89c76SBlaise Bourdin 
184949c89c76SBlaise Bourdin       PetscCall(PetscArrayzero(elem_type, sizeof(elem_type)));
185049c89c76SBlaise Bourdin       PetscCallExternal(ex_get_elem_type, exoid, cs_id[cs], elem_type);
185149c89c76SBlaise Bourdin       PetscCall(ExodusGetCellType_Internal(elem_type, &ct));
185249c89c76SBlaise Bourdin       PetscCallExternal(ex_get_block, exoid, EX_ELEM_BLOCK, cs_id[cs], buffer, &num_cell_in_set, &num_vertex_per_cell, 0, 0, &num_attr);
185349c89c76SBlaise Bourdin       for (c_loc = 0; c_loc < num_cell_in_set; ++c_loc, ++c) {
185449c89c76SBlaise Bourdin         PetscCall(DMPlexSetConeSize(*dm, c, num_vertex_per_cell));
185549c89c76SBlaise Bourdin         PetscCall(DMPlexSetCellType(*dm, c, ct));
185649c89c76SBlaise Bourdin       }
185749c89c76SBlaise Bourdin     }
185849c89c76SBlaise Bourdin     for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetCellType(*dm, v, DM_POLYTOPE_POINT));
185949c89c76SBlaise Bourdin     PetscCall(DMSetUp(*dm));
186049c89c76SBlaise Bourdin     for (ncs = 0, c = 0; ncs < num_cs; ++ncs) {
186149c89c76SBlaise Bourdin       const PetscInt cs = cs_order[ncs];
186249c89c76SBlaise Bourdin       PetscCallExternal(ex_get_block, exoid, EX_ELEM_BLOCK, cs_id[cs], buffer, &num_cell_in_set, &num_vertex_per_cell, 0, 0, &num_attr);
186349c89c76SBlaise Bourdin       PetscCall(PetscMalloc2(num_vertex_per_cell * num_cell_in_set, &cs_connect, num_vertex_per_cell, &cone));
186449c89c76SBlaise Bourdin       PetscCallExternal(ex_get_conn, exoid, EX_ELEM_BLOCK, cs_id[cs], cs_connect, NULL, NULL);
186549c89c76SBlaise Bourdin       /* EXO uses Fortran-based indexing, DMPlex uses C-style and numbers cell first then vertices. */
186649c89c76SBlaise Bourdin       for (c_loc = 0, v = 0; c_loc < num_cell_in_set; ++c_loc, ++c) {
186749c89c76SBlaise Bourdin         DMPolytopeType ct;
186849c89c76SBlaise Bourdin 
186949c89c76SBlaise Bourdin         for (v_loc = 0; v_loc < num_vertex_per_cell; ++v_loc, ++v) cone[v_loc] = cs_connect[v] + numCells - 1;
187049c89c76SBlaise Bourdin         PetscCall(DMPlexGetCellType(*dm, c, &ct));
187149c89c76SBlaise Bourdin         PetscCall(DMPlexInvertCell(ct, cone));
187249c89c76SBlaise Bourdin         PetscCall(DMPlexSetCone(*dm, c, cone));
187349c89c76SBlaise Bourdin         PetscCall(DMSetLabelValue_Fast(*dm, &cellSets, "Cell Sets", c, cs_id[cs]));
187449c89c76SBlaise Bourdin       }
187549c89c76SBlaise Bourdin       PetscCall(PetscFree2(cs_connect, cone));
187649c89c76SBlaise Bourdin     }
187749c89c76SBlaise Bourdin     PetscCall(PetscFree2(cs_id, cs_order));
187849c89c76SBlaise Bourdin   }
187949c89c76SBlaise Bourdin   {
188049c89c76SBlaise Bourdin     PetscInt ints[] = {dim, dimEmbed};
188149c89c76SBlaise Bourdin 
188249c89c76SBlaise Bourdin     PetscCallMPI(MPI_Bcast(ints, 2, MPIU_INT, 0, comm));
188349c89c76SBlaise Bourdin     PetscCall(DMSetDimension(*dm, ints[0]));
188449c89c76SBlaise Bourdin     PetscCall(DMSetCoordinateDim(*dm, ints[1]));
188549c89c76SBlaise Bourdin     dim      = ints[0];
188649c89c76SBlaise Bourdin     dimEmbed = ints[1];
188749c89c76SBlaise Bourdin   }
188849c89c76SBlaise Bourdin   PetscCall(DMPlexSymmetrize(*dm));
188949c89c76SBlaise Bourdin   PetscCall(DMPlexStratify(*dm));
189049c89c76SBlaise Bourdin   if (interpolate) {
189149c89c76SBlaise Bourdin     DM idm;
189249c89c76SBlaise Bourdin 
189349c89c76SBlaise Bourdin     PetscCall(DMPlexInterpolate(*dm, &idm));
189449c89c76SBlaise Bourdin     PetscCall(DMDestroy(dm));
189549c89c76SBlaise Bourdin     *dm = idm;
189649c89c76SBlaise Bourdin   }
189749c89c76SBlaise Bourdin 
189849c89c76SBlaise Bourdin   /* Create vertex set label */
189949c89c76SBlaise Bourdin   if (rank == 0 && (num_vs > 0)) {
190049c89c76SBlaise Bourdin     int vs, v;
190149c89c76SBlaise Bourdin     /* Read from ex_get_node_set_ids() */
190249c89c76SBlaise Bourdin     int *vs_id;
190349c89c76SBlaise Bourdin     /* Read from ex_get_node_set_param() */
190449c89c76SBlaise Bourdin     int num_vertex_in_set;
190549c89c76SBlaise Bourdin     /* Read from ex_get_node_set() */
190649c89c76SBlaise Bourdin     int *vs_vertex_list;
190749c89c76SBlaise Bourdin 
190849c89c76SBlaise Bourdin     /* Get vertex set ids */
190949c89c76SBlaise Bourdin     PetscCall(PetscMalloc1(num_vs, &vs_id));
191049c89c76SBlaise Bourdin     PetscCallExternal(ex_get_ids, exoid, EX_NODE_SET, vs_id);
191149c89c76SBlaise Bourdin     for (vs = 0; vs < num_vs; ++vs) {
191249c89c76SBlaise Bourdin       PetscCallExternal(ex_get_set_param, exoid, EX_NODE_SET, vs_id[vs], &num_vertex_in_set, NULL);
191349c89c76SBlaise Bourdin       PetscCall(PetscMalloc1(num_vertex_in_set, &vs_vertex_list));
191449c89c76SBlaise Bourdin       PetscCallExternal(ex_get_set, exoid, EX_NODE_SET, vs_id[vs], vs_vertex_list, NULL);
191549c89c76SBlaise Bourdin       for (v = 0; v < num_vertex_in_set; ++v) PetscCall(DMSetLabelValue_Fast(*dm, &vertSets, "Vertex Sets", vs_vertex_list[v] + numCells - 1, vs_id[vs]));
191649c89c76SBlaise Bourdin       PetscCall(PetscFree(vs_vertex_list));
191749c89c76SBlaise Bourdin     }
191849c89c76SBlaise Bourdin     PetscCall(PetscFree(vs_id));
191949c89c76SBlaise Bourdin   }
192049c89c76SBlaise Bourdin   /* Read coordinates */
192149c89c76SBlaise Bourdin   PetscCall(DMGetCoordinateSection(*dm, &coordSection));
192249c89c76SBlaise Bourdin   PetscCall(PetscSectionSetNumFields(coordSection, 1));
192349c89c76SBlaise Bourdin   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed));
192449c89c76SBlaise Bourdin   PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
192549c89c76SBlaise Bourdin   for (v = numCells; v < numCells + numVertices; ++v) {
192649c89c76SBlaise Bourdin     PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed));
192749c89c76SBlaise Bourdin     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed));
192849c89c76SBlaise Bourdin   }
192949c89c76SBlaise Bourdin   PetscCall(PetscSectionSetUp(coordSection));
193049c89c76SBlaise Bourdin   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
193149c89c76SBlaise Bourdin   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
193249c89c76SBlaise Bourdin   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
193349c89c76SBlaise Bourdin   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
193449c89c76SBlaise Bourdin   PetscCall(VecSetBlockSize(coordinates, dimEmbed));
193549c89c76SBlaise Bourdin   PetscCall(VecSetType(coordinates, VECSTANDARD));
193649c89c76SBlaise Bourdin   PetscCall(VecGetArray(coordinates, &coords));
193749c89c76SBlaise Bourdin   if (rank == 0) {
193849c89c76SBlaise Bourdin     PetscReal *x, *y, *z;
193949c89c76SBlaise Bourdin 
194049c89c76SBlaise Bourdin     PetscCall(PetscMalloc3(numVertices, &x, numVertices, &y, numVertices, &z));
194149c89c76SBlaise Bourdin     PetscCallExternal(ex_get_coord, exoid, x, y, z);
194249c89c76SBlaise Bourdin     if (dimEmbed > 0) {
194349c89c76SBlaise Bourdin       for (v = 0; v < numVertices; ++v) coords[v * dimEmbed + 0] = x[v];
194449c89c76SBlaise Bourdin     }
194549c89c76SBlaise Bourdin     if (dimEmbed > 1) {
194649c89c76SBlaise Bourdin       for (v = 0; v < numVertices; ++v) coords[v * dimEmbed + 1] = y[v];
194749c89c76SBlaise Bourdin     }
194849c89c76SBlaise Bourdin     if (dimEmbed > 2) {
194949c89c76SBlaise Bourdin       for (v = 0; v < numVertices; ++v) coords[v * dimEmbed + 2] = z[v];
195049c89c76SBlaise Bourdin     }
195149c89c76SBlaise Bourdin     PetscCall(PetscFree3(x, y, z));
195249c89c76SBlaise Bourdin   }
195349c89c76SBlaise Bourdin   PetscCall(VecRestoreArray(coordinates, &coords));
195449c89c76SBlaise Bourdin   PetscCall(DMSetCoordinatesLocal(*dm, coordinates));
195549c89c76SBlaise Bourdin   PetscCall(VecDestroy(&coordinates));
195649c89c76SBlaise Bourdin 
195749c89c76SBlaise Bourdin   /* Create side set label */
195849c89c76SBlaise Bourdin   if (rank == 0 && interpolate && (num_fs > 0)) {
195949c89c76SBlaise Bourdin     int fs, f, voff;
196049c89c76SBlaise Bourdin     /* Read from ex_get_side_set_ids() */
196149c89c76SBlaise Bourdin     int *fs_id;
196249c89c76SBlaise Bourdin     /* Read from ex_get_side_set_param() */
196349c89c76SBlaise Bourdin     int num_side_in_set;
196449c89c76SBlaise Bourdin     /* Read from ex_get_side_set_node_list() */
196549c89c76SBlaise Bourdin     int *fs_vertex_count_list, *fs_vertex_list, *fs_side_list;
196649c89c76SBlaise Bourdin     /* Read side set labels */
196749c89c76SBlaise Bourdin     char   fs_name[MAX_STR_LENGTH + 1];
196849c89c76SBlaise Bourdin     size_t fs_name_len;
196949c89c76SBlaise Bourdin 
197049c89c76SBlaise Bourdin     /* Get side set ids */
197149c89c76SBlaise Bourdin     PetscCall(PetscMalloc1(num_fs, &fs_id));
197249c89c76SBlaise Bourdin     PetscCallExternal(ex_get_ids, exoid, EX_SIDE_SET, fs_id);
197349c89c76SBlaise Bourdin     // Ids 1 and 2 are reserved by ExodusII for indicating things in 3D
197449c89c76SBlaise Bourdin     for (fs = 0; fs < num_fs; ++fs) {
197549c89c76SBlaise Bourdin       PetscCallExternal(ex_get_set_param, exoid, EX_SIDE_SET, fs_id[fs], &num_side_in_set, NULL);
197649c89c76SBlaise Bourdin       PetscCall(PetscMalloc3(num_side_in_set, &fs_vertex_count_list, num_side_in_set * 4, &fs_vertex_list, num_side_in_set, &fs_side_list));
197749c89c76SBlaise Bourdin       PetscCallExternal(ex_get_side_set_node_list, exoid, fs_id[fs], fs_vertex_count_list, fs_vertex_list);
197849c89c76SBlaise Bourdin       PetscCallExternal(ex_get_set, exoid, EX_SIDE_SET, fs_id[fs], NULL, fs_side_list);
197949c89c76SBlaise Bourdin 
198049c89c76SBlaise Bourdin       /* Get the specific name associated with this side set ID. */
198149c89c76SBlaise Bourdin       int fs_name_err = ex_get_name(exoid, EX_SIDE_SET, fs_id[fs], fs_name);
198249c89c76SBlaise Bourdin       if (!fs_name_err) {
198349c89c76SBlaise Bourdin         PetscCall(PetscStrlen(fs_name, &fs_name_len));
198449c89c76SBlaise Bourdin         if (fs_name_len == 0) PetscCall(PetscStrncpy(fs_name, "Face Sets", MAX_STR_LENGTH));
198549c89c76SBlaise Bourdin       }
198649c89c76SBlaise Bourdin       for (f = 0, voff = 0; f < num_side_in_set; ++f) {
198749c89c76SBlaise Bourdin         const PetscInt *faces    = NULL;
198849c89c76SBlaise Bourdin         PetscInt        faceSize = fs_vertex_count_list[f], numFaces;
198949c89c76SBlaise Bourdin         PetscInt        faceVertices[4], v;
199049c89c76SBlaise Bourdin 
199149c89c76SBlaise Bourdin         PetscCheck(faceSize <= 4, comm, PETSC_ERR_ARG_WRONG, "ExodusII side cannot have %" PetscInt_FMT " > 4 vertices", faceSize);
199249c89c76SBlaise Bourdin         for (v = 0; v < faceSize; ++v, ++voff) faceVertices[v] = fs_vertex_list[voff] + numCells - 1;
199349c89c76SBlaise Bourdin         PetscCall(DMPlexGetFullJoin(*dm, faceSize, faceVertices, &numFaces, &faces));
199449c89c76SBlaise Bourdin         PetscCheck(numFaces == 1, comm, PETSC_ERR_ARG_WRONG, "Invalid ExodusII side %d in set %d maps to %" PetscInt_FMT " faces", f, fs, numFaces);
199549c89c76SBlaise Bourdin         PetscCheck(dim == 1 || faces[0] >= numCells + numVertices, comm, PETSC_ERR_ARG_WRONG, "Invalid ExodusII side %d in set %d maps to point %" PetscInt_FMT " which is not a face", f, fs, faces[0]);
199649c89c76SBlaise Bourdin         PetscCall(DMSetLabelValue_Fast(*dm, &faceSets, "Face Sets", faces[0], fs_id[fs]));
199749c89c76SBlaise Bourdin         /* Only add the label if one has been detected for this side set. */
199849c89c76SBlaise Bourdin         if (!fs_name_err) PetscCall(DMSetLabelValue(*dm, fs_name, faces[0], fs_id[fs]));
199949c89c76SBlaise Bourdin         PetscCall(DMPlexRestoreJoin(*dm, faceSize, faceVertices, &numFaces, &faces));
200049c89c76SBlaise Bourdin       }
200149c89c76SBlaise Bourdin       PetscCall(PetscFree3(fs_vertex_count_list, fs_vertex_list, fs_side_list));
200249c89c76SBlaise Bourdin     }
200349c89c76SBlaise Bourdin     PetscCall(PetscFree(fs_id));
200449c89c76SBlaise Bourdin   }
200549c89c76SBlaise Bourdin 
200649c89c76SBlaise Bourdin   { /* Create Cell/Face/Vertex Sets labels at all processes */
200749c89c76SBlaise Bourdin     enum {
200849c89c76SBlaise Bourdin       n = 3
200949c89c76SBlaise Bourdin     };
201049c89c76SBlaise Bourdin     PetscBool flag[n];
201149c89c76SBlaise Bourdin 
201249c89c76SBlaise Bourdin     flag[0] = cellSets ? PETSC_TRUE : PETSC_FALSE;
201349c89c76SBlaise Bourdin     flag[1] = faceSets ? PETSC_TRUE : PETSC_FALSE;
201449c89c76SBlaise Bourdin     flag[2] = vertSets ? PETSC_TRUE : PETSC_FALSE;
201549c89c76SBlaise Bourdin     PetscCallMPI(MPI_Bcast(flag, n, MPIU_BOOL, 0, comm));
201649c89c76SBlaise Bourdin     if (flag[0]) PetscCall(DMCreateLabel(*dm, "Cell Sets"));
201749c89c76SBlaise Bourdin     if (flag[1]) PetscCall(DMCreateLabel(*dm, "Face Sets"));
201849c89c76SBlaise Bourdin     if (flag[2]) PetscCall(DMCreateLabel(*dm, "Vertex Sets"));
201949c89c76SBlaise Bourdin   }
202049c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
202149c89c76SBlaise Bourdin }
2022