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