xref: /petsc/src/dm/impls/plex/exodusii/plexexodusii2.c (revision 49c89c767329b4815515fe9047927c4fa12c2a65)
1*49c89c76SBlaise Bourdin #define PETSCDM_DLL
2*49c89c76SBlaise Bourdin #include <petsc/private/dmpleximpl.h> /*I   "petscdmplex.h"   I*/
3*49c89c76SBlaise Bourdin 
4*49c89c76SBlaise Bourdin #include <netcdf.h>
5*49c89c76SBlaise Bourdin #include <exodusII.h>
6*49c89c76SBlaise Bourdin 
7*49c89c76SBlaise Bourdin #include <petsc/private/viewerimpl.h>
8*49c89c76SBlaise Bourdin #include <petsc/private/viewerexodusiiimpl.h>
9*49c89c76SBlaise Bourdin /*@C
10*49c89c76SBlaise Bourdin   PETSC_VIEWER_EXODUSII_ - Creates an `PETSCVIEWEREXODUSII` `PetscViewer` shared by all processors in a communicator.
11*49c89c76SBlaise Bourdin 
12*49c89c76SBlaise Bourdin   Collective; No Fortran Support
13*49c89c76SBlaise Bourdin 
14*49c89c76SBlaise Bourdin   Input Parameter:
15*49c89c76SBlaise Bourdin . comm - the MPI communicator to share the `PETSCVIEWEREXODUSII` `PetscViewer`
16*49c89c76SBlaise Bourdin 
17*49c89c76SBlaise Bourdin   Level: intermediate
18*49c89c76SBlaise Bourdin 
19*49c89c76SBlaise Bourdin   Note:
20*49c89c76SBlaise Bourdin   Unlike almost all other PETSc routines, `PETSC_VIEWER_EXODUSII_()` does not return
21*49c89c76SBlaise Bourdin   an error code.  The GLVIS PetscViewer is usually used in the form
22*49c89c76SBlaise Bourdin $       XXXView(XXX object, PETSC_VIEWER_EXODUSII_(comm));
23*49c89c76SBlaise Bourdin 
24*49c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewer`, `PetscViewerExodusIIOpen()`, `PetscViewerType`, `PetscViewerCreate()`, `PetscViewerDestroy()`
25*49c89c76SBlaise Bourdin @*/
26*49c89c76SBlaise Bourdin PetscViewer PETSC_VIEWER_EXODUSII_(MPI_Comm comm)
27*49c89c76SBlaise Bourdin {
28*49c89c76SBlaise Bourdin   PetscViewer viewer;
29*49c89c76SBlaise Bourdin 
30*49c89c76SBlaise Bourdin   PetscFunctionBegin;
31*49c89c76SBlaise Bourdin   PetscCallNull(PetscViewerExodusIIOpen(comm, "mesh.exo", FILE_MODE_WRITE, &viewer));
32*49c89c76SBlaise Bourdin   PetscCallNull(PetscObjectRegisterDestroy((PetscObject)viewer));
33*49c89c76SBlaise Bourdin   PetscFunctionReturn(viewer);
34*49c89c76SBlaise Bourdin }
35*49c89c76SBlaise Bourdin 
36*49c89c76SBlaise Bourdin static PetscErrorCode PetscViewerView_ExodusII(PetscViewer v, PetscViewer viewer)
37*49c89c76SBlaise Bourdin {
38*49c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)v->data;
39*49c89c76SBlaise Bourdin 
40*49c89c76SBlaise Bourdin   PetscFunctionBegin;
41*49c89c76SBlaise Bourdin   if (exo->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename:    %s\n", exo->filename));
42*49c89c76SBlaise Bourdin   if (exo->exoid) PetscCall(PetscViewerASCIIPrintf(viewer, "exoid:       %d\n", exo->exoid));
43*49c89c76SBlaise Bourdin   if (exo->btype) PetscCall(PetscViewerASCIIPrintf(viewer, "IO Mode:     %d\n", exo->btype));
44*49c89c76SBlaise Bourdin   if (exo->order) PetscCall(PetscViewerASCIIPrintf(viewer, "Mesh order:  %d\n", exo->order));
45*49c89c76SBlaise Bourdin   PetscCall(PetscViewerASCIIPrintf(viewer, "Number of nodal variables:  %d\n", exo->numNodalVariables));
46*49c89c76SBlaise Bourdin   for (int i = 0; i < exo->numNodalVariables; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "   %d: %s\n", i, exo->nodalVariableNames[i]));
47*49c89c76SBlaise Bourdin   PetscCall(PetscViewerASCIIPrintf(viewer, "Number of zonal variables:  %d\n", exo->numZonalVariables));
48*49c89c76SBlaise Bourdin   for (int i = 0; i < exo->numZonalVariables; i++) PetscCall(PetscViewerASCIIPrintf(viewer, "   %d: %s\n", i, exo->zonalVariableNames[i]));
49*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
50*49c89c76SBlaise Bourdin }
51*49c89c76SBlaise Bourdin 
52*49c89c76SBlaise Bourdin static PetscErrorCode PetscViewerFlush_ExodusII(PetscViewer v)
53*49c89c76SBlaise Bourdin {
54*49c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)v->data;
55*49c89c76SBlaise Bourdin 
56*49c89c76SBlaise Bourdin   PetscFunctionBegin;
57*49c89c76SBlaise Bourdin   if (exo->exoid >= 0) PetscCallExternal(ex_update, exo->exoid);
58*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
59*49c89c76SBlaise Bourdin }
60*49c89c76SBlaise Bourdin 
61*49c89c76SBlaise Bourdin static PetscErrorCode PetscViewerSetFromOptions_ExodusII(PetscViewer v, PetscOptionItems *PetscOptionsObject)
62*49c89c76SBlaise Bourdin {
63*49c89c76SBlaise Bourdin   PetscFunctionBegin;
64*49c89c76SBlaise Bourdin   PetscOptionsHeadBegin(PetscOptionsObject, "ExodusII PetscViewer Options");
65*49c89c76SBlaise Bourdin   PetscOptionsHeadEnd();
66*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
67*49c89c76SBlaise Bourdin }
68*49c89c76SBlaise Bourdin 
69*49c89c76SBlaise Bourdin static PetscErrorCode PetscViewerSetUp_ExodusII(PetscViewer viewer)
70*49c89c76SBlaise Bourdin {
71*49c89c76SBlaise Bourdin   PetscFunctionBegin;
72*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
73*49c89c76SBlaise Bourdin }
74*49c89c76SBlaise Bourdin 
75*49c89c76SBlaise Bourdin static PetscErrorCode PetscViewerDestroy_ExodusII(PetscViewer viewer)
76*49c89c76SBlaise Bourdin {
77*49c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
78*49c89c76SBlaise Bourdin 
79*49c89c76SBlaise Bourdin   PetscFunctionBegin;
80*49c89c76SBlaise Bourdin   if (exo->exoid >= 0) PetscCallExternal(ex_close, exo->exoid);
81*49c89c76SBlaise Bourdin   for (PetscInt i = 0; i < exo->numZonalVariables; i++) PetscFree(exo->zonalVariableNames[i]);
82*49c89c76SBlaise Bourdin   PetscCall(PetscFree(exo->zonalVariableNames));
83*49c89c76SBlaise Bourdin   for (PetscInt i = 0; i < exo->numNodalVariables; i++) PetscFree(exo->nodalVariableNames[i]);
84*49c89c76SBlaise Bourdin   PetscCall(PetscFree(exo->nodalVariableNames));
85*49c89c76SBlaise Bourdin   PetscCall(PetscFree(exo->filename));
86*49c89c76SBlaise Bourdin   PetscCall(PetscFree(exo));
87*49c89c76SBlaise Bourdin   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL));
88*49c89c76SBlaise Bourdin   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", NULL));
89*49c89c76SBlaise Bourdin   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", NULL));
90*49c89c76SBlaise Bourdin   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", NULL));
91*49c89c76SBlaise Bourdin   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerGetId_C", NULL));
92*49c89c76SBlaise Bourdin   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerGetOrder_C", NULL));
93*49c89c76SBlaise Bourdin   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerSetOrder_C", NULL));
94*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
95*49c89c76SBlaise Bourdin }
96*49c89c76SBlaise Bourdin 
97*49c89c76SBlaise Bourdin static PetscErrorCode PetscViewerFileSetName_ExodusII(PetscViewer viewer, const char name[])
98*49c89c76SBlaise Bourdin {
99*49c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
100*49c89c76SBlaise Bourdin   PetscMPIInt           rank;
101*49c89c76SBlaise Bourdin   int                   CPU_word_size, IO_word_size, EXO_mode;
102*49c89c76SBlaise Bourdin   MPI_Info              mpi_info = MPI_INFO_NULL;
103*49c89c76SBlaise Bourdin   float                 EXO_version;
104*49c89c76SBlaise Bourdin 
105*49c89c76SBlaise Bourdin   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
106*49c89c76SBlaise Bourdin   CPU_word_size = sizeof(PetscReal);
107*49c89c76SBlaise Bourdin   IO_word_size  = sizeof(PetscReal);
108*49c89c76SBlaise Bourdin 
109*49c89c76SBlaise Bourdin   PetscFunctionBegin;
110*49c89c76SBlaise Bourdin   if (exo->exoid >= 0) {
111*49c89c76SBlaise Bourdin     PetscCallExternal(ex_close, exo->exoid);
112*49c89c76SBlaise Bourdin     exo->exoid = -1;
113*49c89c76SBlaise Bourdin   }
114*49c89c76SBlaise Bourdin   if (exo->filename) PetscCall(PetscFree(exo->filename));
115*49c89c76SBlaise Bourdin   PetscCall(PetscStrallocpy(name, &exo->filename));
116*49c89c76SBlaise Bourdin   switch (exo->btype) {
117*49c89c76SBlaise Bourdin   case FILE_MODE_READ:
118*49c89c76SBlaise Bourdin     EXO_mode = EX_READ;
119*49c89c76SBlaise Bourdin     break;
120*49c89c76SBlaise Bourdin   case FILE_MODE_APPEND:
121*49c89c76SBlaise Bourdin   case FILE_MODE_UPDATE:
122*49c89c76SBlaise Bourdin   case FILE_MODE_APPEND_UPDATE:
123*49c89c76SBlaise Bourdin     /* Will fail if the file does not already exist */
124*49c89c76SBlaise Bourdin     EXO_mode = EX_WRITE;
125*49c89c76SBlaise Bourdin     break;
126*49c89c76SBlaise Bourdin   case FILE_MODE_WRITE:
127*49c89c76SBlaise Bourdin     /*
128*49c89c76SBlaise Bourdin       exodus only allows writing geometry upon file creation, so we will let DMView create the file.
129*49c89c76SBlaise Bourdin     */
130*49c89c76SBlaise Bourdin     PetscFunctionReturn(PETSC_SUCCESS);
131*49c89c76SBlaise Bourdin     break;
132*49c89c76SBlaise Bourdin   default:
133*49c89c76SBlaise Bourdin     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
134*49c89c76SBlaise Bourdin   }
135*49c89c76SBlaise Bourdin #if defined(PETSC_USE_64BIT_INDICES)
136*49c89c76SBlaise Bourdin   EXO_mode += EX_ALL_INT64_API;
137*49c89c76SBlaise Bourdin #endif
138*49c89c76SBlaise Bourdin   exo->exoid = ex_open_par(name, EXO_mode, &CPU_word_size, &IO_word_size, &EXO_version, PETSC_COMM_WORLD, mpi_info);
139*49c89c76SBlaise Bourdin   PetscCheck(exo->exoid >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "ex_open_par failed for %s", name);
140*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
141*49c89c76SBlaise Bourdin }
142*49c89c76SBlaise Bourdin 
143*49c89c76SBlaise Bourdin static PetscErrorCode PetscViewerFileGetName_ExodusII(PetscViewer viewer, const char *name[])
144*49c89c76SBlaise Bourdin {
145*49c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
146*49c89c76SBlaise Bourdin 
147*49c89c76SBlaise Bourdin   PetscFunctionBegin;
148*49c89c76SBlaise Bourdin   *name = exo->filename;
149*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
150*49c89c76SBlaise Bourdin }
151*49c89c76SBlaise Bourdin 
152*49c89c76SBlaise Bourdin static PetscErrorCode PetscViewerFileSetMode_ExodusII(PetscViewer viewer, PetscFileMode type)
153*49c89c76SBlaise Bourdin {
154*49c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
155*49c89c76SBlaise Bourdin 
156*49c89c76SBlaise Bourdin   PetscFunctionBegin;
157*49c89c76SBlaise Bourdin   exo->btype = type;
158*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
159*49c89c76SBlaise Bourdin }
160*49c89c76SBlaise Bourdin 
161*49c89c76SBlaise Bourdin static PetscErrorCode PetscViewerFileGetMode_ExodusII(PetscViewer viewer, PetscFileMode *type)
162*49c89c76SBlaise Bourdin {
163*49c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
164*49c89c76SBlaise Bourdin 
165*49c89c76SBlaise Bourdin   PetscFunctionBegin;
166*49c89c76SBlaise Bourdin   *type = exo->btype;
167*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
168*49c89c76SBlaise Bourdin }
169*49c89c76SBlaise Bourdin 
170*49c89c76SBlaise Bourdin static PetscErrorCode PetscViewerExodusIIGetId_ExodusII(PetscViewer viewer, int *exoid)
171*49c89c76SBlaise Bourdin {
172*49c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
173*49c89c76SBlaise Bourdin 
174*49c89c76SBlaise Bourdin   PetscFunctionBegin;
175*49c89c76SBlaise Bourdin   *exoid = exo->exoid;
176*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
177*49c89c76SBlaise Bourdin }
178*49c89c76SBlaise Bourdin 
179*49c89c76SBlaise Bourdin static PetscErrorCode PetscViewerExodusIIGetOrder_ExodusII(PetscViewer viewer, int *order)
180*49c89c76SBlaise Bourdin {
181*49c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
182*49c89c76SBlaise Bourdin 
183*49c89c76SBlaise Bourdin   PetscFunctionBegin;
184*49c89c76SBlaise Bourdin   *order = exo->order;
185*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
186*49c89c76SBlaise Bourdin }
187*49c89c76SBlaise Bourdin 
188*49c89c76SBlaise Bourdin static PetscErrorCode PetscViewerExodusIISetOrder_ExodusII(PetscViewer viewer, int order)
189*49c89c76SBlaise Bourdin {
190*49c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
191*49c89c76SBlaise Bourdin 
192*49c89c76SBlaise Bourdin   PetscFunctionBegin;
193*49c89c76SBlaise Bourdin   exo->order = order;
194*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
195*49c89c76SBlaise Bourdin }
196*49c89c76SBlaise Bourdin 
197*49c89c76SBlaise Bourdin /*@
198*49c89c76SBlaise Bourdin   PetscViewerExodusIISetZonalVariable - Sets the number of zonal variables in an exodusII file
199*49c89c76SBlaise Bourdin 
200*49c89c76SBlaise Bourdin   Collective;
201*49c89c76SBlaise Bourdin 
202*49c89c76SBlaise Bourdin   Input Parameters:
203*49c89c76SBlaise Bourdin + viewer - a `PetscViewer` of type `PETSCVIEWEREXODUSII`
204*49c89c76SBlaise Bourdin - num    - the number of zonal variables in the exodusII file
205*49c89c76SBlaise Bourdin 
206*49c89c76SBlaise Bourdin   Level: intermediate
207*49c89c76SBlaise Bourdin 
208*49c89c76SBlaise Bourdin   Notes:
209*49c89c76SBlaise Bourdin   The exodusII API does not allow changing the number of variables in a file so this function will return an error
210*49c89c76SBlaise Bourdin   if called twice, called on a read-only file, or called on file for which the number of variables has already been specified
211*49c89c76SBlaise Bourdin 
212*49c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerExodusIIOpen()`, `PetscViewerSetType()`, `PetscViewerType`, `PetscViewerExodusIIGetZonalVariable()`
213*49c89c76SBlaise Bourdin @*/
214*49c89c76SBlaise Bourdin PetscErrorCode PetscViewerExodusIISetZonalVariable(PetscViewer viewer, int num)
215*49c89c76SBlaise Bourdin {
216*49c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
217*49c89c76SBlaise Bourdin   MPI_Comm              comm;
218*49c89c76SBlaise Bourdin   int                   exoid = -1;
219*49c89c76SBlaise Bourdin 
220*49c89c76SBlaise Bourdin   PetscFunctionBegin;
221*49c89c76SBlaise Bourdin   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
222*49c89c76SBlaise 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);
223*49c89c76SBlaise 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");
224*49c89c76SBlaise Bourdin 
225*49c89c76SBlaise Bourdin   exo->numZonalVariables = num;
226*49c89c76SBlaise Bourdin   PetscCall(PetscMalloc1(num, &exo->zonalVariableNames));
227*49c89c76SBlaise Bourdin   for (int i = 0; i < num; i++) { exo->zonalVariableNames[i] = NULL; }
228*49c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetId(viewer, &exoid));
229*49c89c76SBlaise Bourdin   PetscCallExternal(ex_put_variable_param, exoid, EX_ELEM_BLOCK, num);
230*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
231*49c89c76SBlaise Bourdin }
232*49c89c76SBlaise Bourdin 
233*49c89c76SBlaise Bourdin /*@
234*49c89c76SBlaise Bourdin   PetscViewerExodusIISetNodalVariable - Sets the number of nodal variables in an exodusII file
235*49c89c76SBlaise Bourdin 
236*49c89c76SBlaise Bourdin   Collective;
237*49c89c76SBlaise Bourdin 
238*49c89c76SBlaise Bourdin   Input Parameters:
239*49c89c76SBlaise Bourdin + viewer - a `PetscViewer` of type `PETSCVIEWEREXODUSII`
240*49c89c76SBlaise Bourdin - num    - the number of nodal variables in the exodusII file
241*49c89c76SBlaise Bourdin 
242*49c89c76SBlaise Bourdin   Level: intermediate
243*49c89c76SBlaise Bourdin 
244*49c89c76SBlaise Bourdin   Notes:
245*49c89c76SBlaise Bourdin   The exodusII API does not allow changing the number of variables in a file so this function will return an error
246*49c89c76SBlaise Bourdin   if called twice, called on a read-only file, or called on file for which the number of variables has already been specified
247*49c89c76SBlaise Bourdin 
248*49c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerExodusIIOpen()`, `PetscViewerSetType()`, `PetscViewerType`, `PetscViewerExodusIIGetNodalVariable()`
249*49c89c76SBlaise Bourdin @*/
250*49c89c76SBlaise Bourdin PetscErrorCode PetscViewerExodusIISetNodalVariable(PetscViewer viewer, int num)
251*49c89c76SBlaise Bourdin {
252*49c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
253*49c89c76SBlaise Bourdin   MPI_Comm              comm;
254*49c89c76SBlaise Bourdin   int                   exoid = -1;
255*49c89c76SBlaise Bourdin 
256*49c89c76SBlaise Bourdin   PetscFunctionBegin;
257*49c89c76SBlaise Bourdin   PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
258*49c89c76SBlaise 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);
259*49c89c76SBlaise 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");
260*49c89c76SBlaise Bourdin 
261*49c89c76SBlaise Bourdin   exo->numNodalVariables = num;
262*49c89c76SBlaise Bourdin   PetscCall(PetscMalloc1(num, &exo->nodalVariableNames));
263*49c89c76SBlaise Bourdin   for (int i = 0; i < num; i++) { exo->nodalVariableNames[i] = NULL; }
264*49c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetId(viewer, &exoid));
265*49c89c76SBlaise Bourdin   PetscCallExternal(ex_put_variable_param, exoid, EX_NODAL, num);
266*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
267*49c89c76SBlaise Bourdin }
268*49c89c76SBlaise Bourdin 
269*49c89c76SBlaise Bourdin /*@
270*49c89c76SBlaise Bourdin   PetscViewerExodusIIGetZonalVariable - Gets the number of zonal variables in an exodusII file
271*49c89c76SBlaise Bourdin 
272*49c89c76SBlaise Bourdin   Collective
273*49c89c76SBlaise Bourdin 
274*49c89c76SBlaise Bourdin   Input Parameters:
275*49c89c76SBlaise Bourdin . viewer - a `PetscViewer` of type `PETSCVIEWEREXODUSII`
276*49c89c76SBlaise Bourdin 
277*49c89c76SBlaise Bourdin   Output Parameters:
278*49c89c76SBlaise Bourdin . num - the number variables in the exodusII file
279*49c89c76SBlaise Bourdin 
280*49c89c76SBlaise Bourdin   Level: intermediate
281*49c89c76SBlaise Bourdin 
282*49c89c76SBlaise Bourdin   Notes:
283*49c89c76SBlaise Bourdin   The number of variables in the exodusII file is cached in the viewer
284*49c89c76SBlaise Bourdin 
285*49c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerExodusIIOpen()`, `PetscViewerSetType()`, `PetscViewerType`, `PetscViewerExodusIIsetZonalVariable()`
286*49c89c76SBlaise Bourdin @*/
287*49c89c76SBlaise Bourdin PetscErrorCode PetscViewerExodusIIGetZonalVariable(PetscViewer viewer, int *num)
288*49c89c76SBlaise Bourdin {
289*49c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
290*49c89c76SBlaise Bourdin   MPI_Comm              comm;
291*49c89c76SBlaise Bourdin   int                   exoid = -1;
292*49c89c76SBlaise Bourdin 
293*49c89c76SBlaise Bourdin   PetscFunctionBegin;
294*49c89c76SBlaise Bourdin   if (exo->numZonalVariables > -1) {
295*49c89c76SBlaise Bourdin     *num = exo->numZonalVariables;
296*49c89c76SBlaise Bourdin   } else {
297*49c89c76SBlaise Bourdin     PetscCall(PetscViewerExodusIIGetId(viewer, &exoid));
298*49c89c76SBlaise Bourdin     PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
299*49c89c76SBlaise Bourdin     PetscCheck(exoid > 0, comm, PETSC_ERR_FILE_OPEN, "Exodus file is not open");
300*49c89c76SBlaise Bourdin     PetscCallExternal(ex_get_variable_param, exoid, EX_ELEM_BLOCK, num);
301*49c89c76SBlaise Bourdin     exo->numZonalVariables = *num;
302*49c89c76SBlaise Bourdin     PetscCall(PetscMalloc1(*num, &exo->zonalVariableNames));
303*49c89c76SBlaise Bourdin     for (int i = 0; i < *num; i++) { exo->zonalVariableNames[i] = NULL; }
304*49c89c76SBlaise Bourdin   }
305*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
306*49c89c76SBlaise Bourdin }
307*49c89c76SBlaise Bourdin 
308*49c89c76SBlaise Bourdin /*@
309*49c89c76SBlaise Bourdin   PetscViewerExodusIIGetNodalVariable - Gets the number of nodal variables in an exodusII file
310*49c89c76SBlaise Bourdin 
311*49c89c76SBlaise Bourdin   Collective
312*49c89c76SBlaise Bourdin 
313*49c89c76SBlaise Bourdin   Input Parameters:
314*49c89c76SBlaise Bourdin . viewer - a `PetscViewer` of type `PETSCVIEWEREXODUSII`
315*49c89c76SBlaise Bourdin 
316*49c89c76SBlaise Bourdin   Output Parameters:
317*49c89c76SBlaise Bourdin . num - the number variables in the exodusII file
318*49c89c76SBlaise Bourdin 
319*49c89c76SBlaise Bourdin   Level: intermediate
320*49c89c76SBlaise Bourdin 
321*49c89c76SBlaise Bourdin   Notes:
322*49c89c76SBlaise Bourdin   This function gets the number of nodal variables and saves it in the address of num.
323*49c89c76SBlaise Bourdin 
324*49c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerExodusIIOpen()`, `PetscViewerSetType()`, `PetscViewerType`, `PetscViewerExodusIISetNodalVariable()`
325*49c89c76SBlaise Bourdin @*/
326*49c89c76SBlaise Bourdin PetscErrorCode PetscViewerExodusIIGetNodalVariable(PetscViewer viewer, int *num)
327*49c89c76SBlaise Bourdin {
328*49c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
329*49c89c76SBlaise Bourdin   MPI_Comm              comm;
330*49c89c76SBlaise Bourdin   int                   exoid = -1;
331*49c89c76SBlaise Bourdin 
332*49c89c76SBlaise Bourdin   PetscFunctionBegin;
333*49c89c76SBlaise Bourdin   if (exo->numNodalVariables > -1) {
334*49c89c76SBlaise Bourdin     *num = exo->numNodalVariables;
335*49c89c76SBlaise Bourdin   } else {
336*49c89c76SBlaise Bourdin     PetscCall(PetscViewerExodusIIGetId(viewer, &exoid));
337*49c89c76SBlaise Bourdin     PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
338*49c89c76SBlaise Bourdin     PetscCheck(exoid > 0, comm, PETSC_ERR_FILE_OPEN, "Exodus file is not open");
339*49c89c76SBlaise Bourdin     PetscCallExternal(ex_get_variable_param, exoid, EX_NODAL, num);
340*49c89c76SBlaise Bourdin     exo->numNodalVariables = *num;
341*49c89c76SBlaise Bourdin     PetscCall(PetscMalloc1(*num, &exo->nodalVariableNames));
342*49c89c76SBlaise Bourdin     for (int i = 0; i < *num; i++) { exo->nodalVariableNames[i] = NULL; }
343*49c89c76SBlaise Bourdin   }
344*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
345*49c89c76SBlaise Bourdin }
346*49c89c76SBlaise Bourdin 
347*49c89c76SBlaise Bourdin /*@
348*49c89c76SBlaise Bourdin   PetscViewerExodusIISetZonalVariableName - Sets the name of a zonal variable.
349*49c89c76SBlaise Bourdin 
350*49c89c76SBlaise Bourdin   Collective;
351*49c89c76SBlaise Bourdin 
352*49c89c76SBlaise Bourdin   Input Parameters:
353*49c89c76SBlaise Bourdin + viewer - a `PetscViewer` of type `PETSCVIEWEREXODUSII`
354*49c89c76SBlaise Bourdin . idx    - the index for which you want to save the name
355*49c89c76SBlaise Bourdin - name   - string containing the name characters
356*49c89c76SBlaise Bourdin 
357*49c89c76SBlaise Bourdin   Level: intermediate
358*49c89c76SBlaise Bourdin 
359*49c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerExodusIIOpen()`, `PetscViewerSetType()`, `PetscViewerType`, `PetscViewerExodusIIGetZonalVariableName()`
360*49c89c76SBlaise Bourdin @*/
361*49c89c76SBlaise Bourdin PetscErrorCode PetscViewerExodusIISetZonalVariableName(PetscViewer viewer, int idx, const char name[])
362*49c89c76SBlaise Bourdin {
363*49c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
364*49c89c76SBlaise Bourdin 
365*49c89c76SBlaise Bourdin   PetscFunctionBegin;
366*49c89c76SBlaise Bourdin   PetscCheck((idx >= 0) && (idx < exo->numZonalVariables), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Variable index out of range. Was PetscViewerExodusIISetZonalVariable called?");
367*49c89c76SBlaise Bourdin   PetscCall(PetscStrallocpy(name, (char **)&exo->zonalVariableNames[idx]));
368*49c89c76SBlaise Bourdin   PetscCallExternal(ex_put_variable_name, exo->exoid, EX_ELEM_BLOCK, idx + 1, name);
369*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
370*49c89c76SBlaise Bourdin }
371*49c89c76SBlaise Bourdin 
372*49c89c76SBlaise Bourdin /*@
373*49c89c76SBlaise Bourdin   PetscViewerExodusIISetNodalVariableName - Sets the name of a nodal variable.
374*49c89c76SBlaise Bourdin 
375*49c89c76SBlaise Bourdin   Collective;
376*49c89c76SBlaise Bourdin 
377*49c89c76SBlaise Bourdin   Input Parameters:
378*49c89c76SBlaise Bourdin + viewer - a `PetscViewer` of type `PETSCVIEWEREXODUSII`
379*49c89c76SBlaise Bourdin . idx    - the index for which you want to save the name
380*49c89c76SBlaise Bourdin - name   - string containing the name characters
381*49c89c76SBlaise Bourdin 
382*49c89c76SBlaise Bourdin   Level: intermediate
383*49c89c76SBlaise Bourdin 
384*49c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerExodusIIOpen()`, `PetscViewerSetType()`, `PetscViewerType`, `PetscViewerExodusIIGetNodalVariableName()`
385*49c89c76SBlaise Bourdin @*/
386*49c89c76SBlaise Bourdin PetscErrorCode PetscViewerExodusIISetNodalVariableName(PetscViewer viewer, int idx, const char name[])
387*49c89c76SBlaise Bourdin {
388*49c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
389*49c89c76SBlaise Bourdin 
390*49c89c76SBlaise Bourdin   PetscFunctionBegin;
391*49c89c76SBlaise Bourdin   PetscCheck((idx >= 0) && (idx < exo->numNodalVariables), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Variable index out of range. Was PetscViewerExodusIISetNodalVariable called?");
392*49c89c76SBlaise Bourdin   PetscCall(PetscStrallocpy(name, (char **)&exo->nodalVariableNames[idx]));
393*49c89c76SBlaise Bourdin   PetscCallExternal(ex_put_variable_name, exo->exoid, EX_NODAL, idx + 1, name);
394*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
395*49c89c76SBlaise Bourdin }
396*49c89c76SBlaise Bourdin 
397*49c89c76SBlaise Bourdin /*@
398*49c89c76SBlaise Bourdin   PetscViewerExodusIIGetZonalVariableName - Gets the name of a zonal variable.
399*49c89c76SBlaise Bourdin 
400*49c89c76SBlaise Bourdin   Collective;
401*49c89c76SBlaise Bourdin 
402*49c89c76SBlaise Bourdin   Input Parameters:
403*49c89c76SBlaise Bourdin + viewer - a `PetscViewer` of type `PETSCVIEWEREXODUSII`
404*49c89c76SBlaise Bourdin - idx    - the index for which you want to get the name
405*49c89c76SBlaise Bourdin 
406*49c89c76SBlaise Bourdin   Output Parameter:
407*49c89c76SBlaise Bourdin . name - pointer to the string containing the name characters
408*49c89c76SBlaise Bourdin 
409*49c89c76SBlaise Bourdin   Level: intermediate
410*49c89c76SBlaise Bourdin 
411*49c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerExodusIIOpen()`, `PetscViewerSetType()`, `PetscViewerType`, `PetscViewerExodusIISetZonalVariableName()`
412*49c89c76SBlaise Bourdin @*/
413*49c89c76SBlaise Bourdin PetscErrorCode PetscViewerExodusIIGetZonalVariableName(PetscViewer viewer, int idx, const char *name[])
414*49c89c76SBlaise Bourdin {
415*49c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo   = (PetscViewer_ExodusII *)viewer->data;
416*49c89c76SBlaise Bourdin   int                   exoid = -1;
417*49c89c76SBlaise Bourdin   char                  tmpName[MAX_NAME_LENGTH + 1];
418*49c89c76SBlaise Bourdin 
419*49c89c76SBlaise Bourdin   PetscFunctionBegin;
420*49c89c76SBlaise Bourdin   PetscCheck(idx >= 0 && idx < exo->numZonalVariables, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Variable index out of range. Was PetscViewerExodusIISetZonalVariable called?");
421*49c89c76SBlaise Bourdin   if (!exo->zonalVariableNames[idx]) {
422*49c89c76SBlaise Bourdin     PetscCall(PetscViewerExodusIIGetId(viewer, &exoid));
423*49c89c76SBlaise Bourdin     PetscCallExternal(ex_get_variable_name, exoid, EX_ELEM_BLOCK, idx + 1, tmpName);
424*49c89c76SBlaise Bourdin     PetscCall(PetscStrallocpy(tmpName, (char **)&exo->zonalVariableNames[idx]));
425*49c89c76SBlaise Bourdin   }
426*49c89c76SBlaise Bourdin   *name = exo->zonalVariableNames[idx];
427*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
428*49c89c76SBlaise Bourdin }
429*49c89c76SBlaise Bourdin 
430*49c89c76SBlaise Bourdin /*@
431*49c89c76SBlaise Bourdin   PetscViewerExodusIIGetNodalVariableName - Gets the name of a nodal variable.
432*49c89c76SBlaise Bourdin 
433*49c89c76SBlaise Bourdin   Collective;
434*49c89c76SBlaise Bourdin 
435*49c89c76SBlaise Bourdin   Input Parameters:
436*49c89c76SBlaise Bourdin + viewer - a `PetscViewer` of type `PETSCVIEWEREXODUSII`
437*49c89c76SBlaise Bourdin - idx    - the index for which you want to save the name
438*49c89c76SBlaise Bourdin 
439*49c89c76SBlaise Bourdin   Output Parameter:
440*49c89c76SBlaise Bourdin . name - string array containing name characters
441*49c89c76SBlaise Bourdin 
442*49c89c76SBlaise Bourdin   Level: intermediate
443*49c89c76SBlaise Bourdin 
444*49c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerExodusIIOpen()`, `PetscViewerSetType()`, `PetscViewerType`, `PetscViewerExodusIISetNodalVariableName()`
445*49c89c76SBlaise Bourdin @*/
446*49c89c76SBlaise Bourdin PetscErrorCode PetscViewerExodusIIGetNodalVariableName(PetscViewer viewer, int idx, const char *name[])
447*49c89c76SBlaise Bourdin {
448*49c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo   = (PetscViewer_ExodusII *)viewer->data;
449*49c89c76SBlaise Bourdin   int                   exoid = -1;
450*49c89c76SBlaise Bourdin   char                  tmpName[MAX_NAME_LENGTH + 1];
451*49c89c76SBlaise Bourdin 
452*49c89c76SBlaise Bourdin   PetscFunctionBegin;
453*49c89c76SBlaise Bourdin   PetscCheck((idx >= 0) && (idx < exo->numNodalVariables), PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Variable index out of range. Was PetscViewerExodusIISetNodalVariable called?");
454*49c89c76SBlaise Bourdin   if (!exo->nodalVariableNames[idx]) {
455*49c89c76SBlaise Bourdin     PetscCall(PetscViewerExodusIIGetId(viewer, &exoid));
456*49c89c76SBlaise Bourdin     PetscCallExternal(ex_get_variable_name, exoid, EX_NODAL, idx + 1, tmpName);
457*49c89c76SBlaise Bourdin     PetscCall(PetscStrallocpy(tmpName, (char **)&exo->nodalVariableNames[idx]));
458*49c89c76SBlaise Bourdin   }
459*49c89c76SBlaise Bourdin   *name = exo->nodalVariableNames[idx];
460*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
461*49c89c76SBlaise Bourdin }
462*49c89c76SBlaise Bourdin 
463*49c89c76SBlaise Bourdin /*@C
464*49c89c76SBlaise Bourdin   PetscViewerExodusIISetZonalVariableNames - Sets the names of all nodal variables
465*49c89c76SBlaise Bourdin 
466*49c89c76SBlaise Bourdin   Collective; No Fortran Support
467*49c89c76SBlaise Bourdin 
468*49c89c76SBlaise Bourdin   Input Parameters:
469*49c89c76SBlaise Bourdin + viewer - a `PetscViewer` of type `PETSCVIEWEREXODUSII`
470*49c89c76SBlaise Bourdin - names  - 2D array containing the array of string names to be set
471*49c89c76SBlaise Bourdin 
472*49c89c76SBlaise Bourdin   Level: intermediate
473*49c89c76SBlaise Bourdin 
474*49c89c76SBlaise Bourdin   Notes:
475*49c89c76SBlaise Bourdin   This function allows users to set multiple zonal variable names at a time.
476*49c89c76SBlaise Bourdin 
477*49c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerExodusIIOpen()`, `PetscViewerSetType()`, `PetscViewerType`, `PetscViewerExodusIIGetZonalVariableNames()`
478*49c89c76SBlaise Bourdin @*/
479*49c89c76SBlaise Bourdin PetscErrorCode PetscViewerExodusIISetZonalVariableNames(PetscViewer viewer, const char *names[])
480*49c89c76SBlaise Bourdin {
481*49c89c76SBlaise Bourdin   int                   numNames;
482*49c89c76SBlaise Bourdin   int                   exoid = -1;
483*49c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo   = (PetscViewer_ExodusII *)viewer->data;
484*49c89c76SBlaise Bourdin 
485*49c89c76SBlaise Bourdin   PetscFunctionBegin;
486*49c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetZonalVariable(viewer, &numNames));
487*49c89c76SBlaise Bourdin   PetscCheck(numNames >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of zonal variables not set. Was PetscViewerExodusIISetZonalVariable called?");
488*49c89c76SBlaise Bourdin 
489*49c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetId(viewer, &exoid));
490*49c89c76SBlaise Bourdin   for (int i = 0; i < numNames; i++) {
491*49c89c76SBlaise Bourdin     PetscCall(PetscStrallocpy(names[i], &exo->zonalVariableNames[i]));
492*49c89c76SBlaise Bourdin     PetscCallExternal(ex_put_variable_name, exoid, EX_ELEM_BLOCK, i + 1, names[i]);
493*49c89c76SBlaise Bourdin   }
494*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
495*49c89c76SBlaise Bourdin }
496*49c89c76SBlaise Bourdin 
497*49c89c76SBlaise Bourdin /*@C
498*49c89c76SBlaise Bourdin   PetscViewerExodusIISetNodalVariableNames - Sets the names of all nodal variables.
499*49c89c76SBlaise Bourdin 
500*49c89c76SBlaise Bourdin   Collective; No Fortran Support
501*49c89c76SBlaise Bourdin 
502*49c89c76SBlaise Bourdin   Input Parameters:
503*49c89c76SBlaise Bourdin + viewer - a `PetscViewer` of type `PETSCVIEWEREXODUSII`
504*49c89c76SBlaise Bourdin - names  - 2D array containing the array of string names to be set
505*49c89c76SBlaise Bourdin 
506*49c89c76SBlaise Bourdin   Level: intermediate
507*49c89c76SBlaise Bourdin 
508*49c89c76SBlaise Bourdin   Notes:
509*49c89c76SBlaise Bourdin   This function allows users to set multiple nodal variable names at a time.
510*49c89c76SBlaise Bourdin 
511*49c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerExodusIIOpen()`, `PetscViewerSetType()`, `PetscViewerType`, `PetscViewerExodusIIGetNodalVariableNames()`
512*49c89c76SBlaise Bourdin @*/
513*49c89c76SBlaise Bourdin PetscErrorCode PetscViewerExodusIISetNodalVariableNames(PetscViewer viewer, const char *names[])
514*49c89c76SBlaise Bourdin {
515*49c89c76SBlaise Bourdin   int                   numNames;
516*49c89c76SBlaise Bourdin   int                   exoid = -1;
517*49c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo   = (PetscViewer_ExodusII *)viewer->data;
518*49c89c76SBlaise Bourdin 
519*49c89c76SBlaise Bourdin   PetscFunctionBegin;
520*49c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetNodalVariable(viewer, &numNames));
521*49c89c76SBlaise Bourdin   PetscCheck(numNames >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Number of nodal variables not set. Was PetscViewerExodusIISetNodalVariable called?");
522*49c89c76SBlaise Bourdin 
523*49c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetId(viewer, &exoid));
524*49c89c76SBlaise Bourdin   for (int i = 0; i < numNames; i++) {
525*49c89c76SBlaise Bourdin     PetscCall(PetscStrallocpy(names[i], &exo->nodalVariableNames[i]));
526*49c89c76SBlaise Bourdin     PetscCallExternal(ex_put_variable_name, exoid, EX_NODAL, i + 1, names[i]);
527*49c89c76SBlaise Bourdin   }
528*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
529*49c89c76SBlaise Bourdin }
530*49c89c76SBlaise Bourdin 
531*49c89c76SBlaise Bourdin /*@C
532*49c89c76SBlaise Bourdin   PetscViewerExodusIIGetZonalVariableNames - Gets the names of all zonal variables.
533*49c89c76SBlaise Bourdin 
534*49c89c76SBlaise Bourdin   Collective; No Fortran Support
535*49c89c76SBlaise Bourdin 
536*49c89c76SBlaise Bourdin   Input Parameters:
537*49c89c76SBlaise Bourdin + viewer  - a `PetscViewer` of type `PETSCVIEWEREXODUSII`
538*49c89c76SBlaise Bourdin - numVars - the number of zonal variable names to retrieve
539*49c89c76SBlaise Bourdin 
540*49c89c76SBlaise Bourdin   Output Parameters:
541*49c89c76SBlaise Bourdin . varNames - pointer to a 2D array where the zonal variable names will be saved
542*49c89c76SBlaise Bourdin 
543*49c89c76SBlaise Bourdin   Level: intermediate
544*49c89c76SBlaise Bourdin 
545*49c89c76SBlaise Bourdin   Notes:
546*49c89c76SBlaise Bourdin   This function returns a borrowed pointer which should not be freed.
547*49c89c76SBlaise Bourdin 
548*49c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerExodusIIOpen()`, `PetscViewerSetType()`, `PetscViewerType`, `PetscViewerExodusIISetZonalVariableNames()`
549*49c89c76SBlaise Bourdin @*/
550*49c89c76SBlaise Bourdin PetscErrorCode PetscViewerExodusIIGetZonalVariableNames(PetscViewer viewer, int *numVars, char ***varNames)
551*49c89c76SBlaise Bourdin {
552*49c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
553*49c89c76SBlaise Bourdin   int                   idx;
554*49c89c76SBlaise Bourdin   char                  tmpName[MAX_NAME_LENGTH + 1];
555*49c89c76SBlaise Bourdin   int                   exoid = -1;
556*49c89c76SBlaise Bourdin 
557*49c89c76SBlaise Bourdin   PetscFunctionBegin;
558*49c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetZonalVariable(viewer, numVars));
559*49c89c76SBlaise Bourdin   /*
560*49c89c76SBlaise Bourdin     Cache variable names if necessary
561*49c89c76SBlaise Bourdin   */
562*49c89c76SBlaise Bourdin   for (idx = 0; idx < *numVars; idx++) {
563*49c89c76SBlaise Bourdin     if (!exo->zonalVariableNames[idx]) {
564*49c89c76SBlaise Bourdin       PetscCall(PetscViewerExodusIIGetId(viewer, &exoid));
565*49c89c76SBlaise Bourdin       PetscCallExternal(ex_get_variable_name, exoid, EX_ELEM_BLOCK, idx + 1, tmpName);
566*49c89c76SBlaise Bourdin       PetscCall(PetscStrallocpy(tmpName, (char **)&exo->zonalVariableNames[idx]));
567*49c89c76SBlaise Bourdin     }
568*49c89c76SBlaise Bourdin   }
569*49c89c76SBlaise Bourdin   *varNames = (char **)exo->zonalVariableNames;
570*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
571*49c89c76SBlaise Bourdin }
572*49c89c76SBlaise Bourdin 
573*49c89c76SBlaise Bourdin /*@C
574*49c89c76SBlaise Bourdin   PetscViewerExodusIIGetNodalVariableNames - Gets the names of all nodal variables.
575*49c89c76SBlaise Bourdin 
576*49c89c76SBlaise Bourdin   Collective; No Fortran Support
577*49c89c76SBlaise Bourdin 
578*49c89c76SBlaise Bourdin   Input Parameters:
579*49c89c76SBlaise Bourdin + viewer  - a `PetscViewer` of type `PETSCVIEWEREXODUSII`
580*49c89c76SBlaise Bourdin - numVars - the number of nodal variable names to retrieve
581*49c89c76SBlaise Bourdin 
582*49c89c76SBlaise Bourdin   Output Parameters:
583*49c89c76SBlaise Bourdin . varNames - 2D array where the nodal variable names will be saved
584*49c89c76SBlaise Bourdin 
585*49c89c76SBlaise Bourdin   Level: intermediate
586*49c89c76SBlaise Bourdin 
587*49c89c76SBlaise Bourdin   Notes:
588*49c89c76SBlaise Bourdin   This function returns a borrowed pointer which should not be freed.
589*49c89c76SBlaise Bourdin 
590*49c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerExodusIIOpen()`, `PetscViewerSetType()`, `PetscViewerType`, `PetscViewerExodusIISetNodalVariableNames()`
591*49c89c76SBlaise Bourdin @*/
592*49c89c76SBlaise Bourdin PetscErrorCode PetscViewerExodusIIGetNodalVariableNames(PetscViewer viewer, int *numVars, char ***varNames)
593*49c89c76SBlaise Bourdin {
594*49c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
595*49c89c76SBlaise Bourdin   int                   idx;
596*49c89c76SBlaise Bourdin   char                  tmpName[MAX_NAME_LENGTH + 1];
597*49c89c76SBlaise Bourdin   int                   exoid = -1;
598*49c89c76SBlaise Bourdin 
599*49c89c76SBlaise Bourdin   PetscFunctionBegin;
600*49c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetNodalVariable(viewer, numVars));
601*49c89c76SBlaise Bourdin   /*
602*49c89c76SBlaise Bourdin     Cache variable names if necessary
603*49c89c76SBlaise Bourdin   */
604*49c89c76SBlaise Bourdin   for (idx = 0; idx < *numVars; idx++) {
605*49c89c76SBlaise Bourdin     if (!exo->nodalVariableNames[idx]) {
606*49c89c76SBlaise Bourdin       PetscCall(PetscViewerExodusIIGetId(viewer, &exoid));
607*49c89c76SBlaise Bourdin       PetscCallExternal(ex_get_variable_name, exoid, EX_NODAL, idx + 1, tmpName);
608*49c89c76SBlaise Bourdin       PetscCall(PetscStrallocpy(tmpName, (char **)&exo->nodalVariableNames[idx]));
609*49c89c76SBlaise Bourdin     }
610*49c89c76SBlaise Bourdin   }
611*49c89c76SBlaise Bourdin   *varNames = (char **)exo->nodalVariableNames;
612*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
613*49c89c76SBlaise Bourdin }
614*49c89c76SBlaise Bourdin 
615*49c89c76SBlaise Bourdin /*MC
616*49c89c76SBlaise Bourdin    PETSCVIEWEREXODUSII - A viewer that writes to an Exodus II file
617*49c89c76SBlaise Bourdin 
618*49c89c76SBlaise Bourdin   Level: beginner
619*49c89c76SBlaise Bourdin 
620*49c89c76SBlaise Bourdin .seealso: `PetscViewerExodusIIOpen()`, `PetscViewerCreate()`, `PETSCVIEWERBINARY`, `PETSCVIEWERHDF5`, `DMView()`,
621*49c89c76SBlaise Bourdin           `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
622*49c89c76SBlaise Bourdin M*/
623*49c89c76SBlaise Bourdin PETSC_EXTERN PetscErrorCode PetscViewerCreate_ExodusII(PetscViewer v)
624*49c89c76SBlaise Bourdin {
625*49c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo;
626*49c89c76SBlaise Bourdin 
627*49c89c76SBlaise Bourdin   PetscFunctionBegin;
628*49c89c76SBlaise Bourdin   PetscCall(PetscNew(&exo));
629*49c89c76SBlaise Bourdin 
630*49c89c76SBlaise Bourdin   v->data                 = (void *)exo;
631*49c89c76SBlaise Bourdin   v->ops->destroy         = PetscViewerDestroy_ExodusII;
632*49c89c76SBlaise Bourdin   v->ops->setfromoptions  = PetscViewerSetFromOptions_ExodusII;
633*49c89c76SBlaise Bourdin   v->ops->setup           = PetscViewerSetUp_ExodusII;
634*49c89c76SBlaise Bourdin   v->ops->view            = PetscViewerView_ExodusII;
635*49c89c76SBlaise Bourdin   v->ops->flush           = PetscViewerFlush_ExodusII;
636*49c89c76SBlaise Bourdin   exo->btype              = FILE_MODE_UNDEFINED;
637*49c89c76SBlaise Bourdin   exo->filename           = 0;
638*49c89c76SBlaise Bourdin   exo->exoid              = -1;
639*49c89c76SBlaise Bourdin   exo->numNodalVariables  = -1;
640*49c89c76SBlaise Bourdin   exo->numZonalVariables  = -1;
641*49c89c76SBlaise Bourdin   exo->nodalVariableNames = NULL;
642*49c89c76SBlaise Bourdin   exo->zonalVariableNames = NULL;
643*49c89c76SBlaise Bourdin 
644*49c89c76SBlaise Bourdin   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetName_C", PetscViewerFileSetName_ExodusII));
645*49c89c76SBlaise Bourdin   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetName_C", PetscViewerFileGetName_ExodusII));
646*49c89c76SBlaise Bourdin   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ExodusII));
647*49c89c76SBlaise Bourdin   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ExodusII));
648*49c89c76SBlaise Bourdin   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerGetId_C", PetscViewerExodusIIGetId_ExodusII));
649*49c89c76SBlaise Bourdin   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerSetOrder_C", PetscViewerExodusIISetOrder_ExodusII));
650*49c89c76SBlaise Bourdin   PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerGetOrder_C", PetscViewerExodusIIGetOrder_ExodusII));
651*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
652*49c89c76SBlaise Bourdin }
653*49c89c76SBlaise Bourdin 
654*49c89c76SBlaise Bourdin /*@
655*49c89c76SBlaise Bourdin   PetscViewerExodusIIGetNodalVariableIndex - return the location of a nodal variable in an exodusII file given its name
656*49c89c76SBlaise Bourdin 
657*49c89c76SBlaise Bourdin   Collective
658*49c89c76SBlaise Bourdin 
659*49c89c76SBlaise Bourdin   Input Parameters:
660*49c89c76SBlaise Bourdin + viewer - a `PetscViewer` of type `PETSCVIEWEREXODUSII`
661*49c89c76SBlaise Bourdin - name   - the name of the result
662*49c89c76SBlaise Bourdin 
663*49c89c76SBlaise Bourdin   Output Parameter:
664*49c89c76SBlaise Bourdin . varIndex - the location of the variable in the exodus file or -1 if the variable is not found
665*49c89c76SBlaise Bourdin 
666*49c89c76SBlaise Bourdin   Level: beginner
667*49c89c76SBlaise Bourdin 
668*49c89c76SBlaise Bourdin   Notes:
669*49c89c76SBlaise Bourdin   The exodus variable index is obtained by comparing the name argument to the
670*49c89c76SBlaise Bourdin   names of zonal variables declared in the exodus file. For instance if name is "V"
671*49c89c76SBlaise Bourdin   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
672*49c89c76SBlaise Bourdin   amongst all variables of type obj_type.
673*49c89c76SBlaise Bourdin 
674*49c89c76SBlaise Bourdin .seealso: `PetscViewerExodusIISetNodalVariable()`, `PetscViewerExodusIIGetNodalVariable()`, `PetscViewerExodusIISetNodalVariableName()`, `PetscViewerExodusIISetNodalVariableNames()`, `PetscViewerExodusIIGetNodalVariableName()`, `PetscViewerExodusIIGetNodalVariableNames()`
675*49c89c76SBlaise Bourdin @*/
676*49c89c76SBlaise Bourdin PetscErrorCode PetscViewerExodusIIGetNodalVariableIndex(PetscViewer viewer, const char name[], int *varIndex)
677*49c89c76SBlaise Bourdin {
678*49c89c76SBlaise Bourdin   int       num_vars = 0, i, j;
679*49c89c76SBlaise Bourdin   char      ext_name[MAX_STR_LENGTH + 1];
680*49c89c76SBlaise Bourdin   char    **var_names;
681*49c89c76SBlaise Bourdin   const int num_suffix = 5;
682*49c89c76SBlaise Bourdin   char     *suffix[5];
683*49c89c76SBlaise Bourdin   PetscBool flg;
684*49c89c76SBlaise Bourdin 
685*49c89c76SBlaise Bourdin   PetscFunctionBegin;
686*49c89c76SBlaise Bourdin   suffix[0] = (char *)"";
687*49c89c76SBlaise Bourdin   suffix[1] = (char *)"_X";
688*49c89c76SBlaise Bourdin   suffix[2] = (char *)"_XX";
689*49c89c76SBlaise Bourdin   suffix[3] = (char *)"_1";
690*49c89c76SBlaise Bourdin   suffix[4] = (char *)"_11";
691*49c89c76SBlaise Bourdin   *varIndex = -1;
692*49c89c76SBlaise Bourdin 
693*49c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetNodalVariableNames(viewer, &num_vars, &var_names));
694*49c89c76SBlaise Bourdin   for (i = 0; i < num_vars; ++i) {
695*49c89c76SBlaise Bourdin     for (j = 0; j < num_suffix; ++j) {
696*49c89c76SBlaise Bourdin       PetscCall(PetscStrncpy(ext_name, name, MAX_STR_LENGTH));
697*49c89c76SBlaise Bourdin       PetscCall(PetscStrlcat(ext_name, suffix[j], MAX_STR_LENGTH));
698*49c89c76SBlaise Bourdin       PetscCall(PetscStrcasecmp(ext_name, var_names[i], &flg));
699*49c89c76SBlaise Bourdin       if (flg) *varIndex = i;
700*49c89c76SBlaise Bourdin     }
701*49c89c76SBlaise Bourdin     if (flg) break;
702*49c89c76SBlaise Bourdin   }
703*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
704*49c89c76SBlaise Bourdin }
705*49c89c76SBlaise Bourdin 
706*49c89c76SBlaise Bourdin /*@
707*49c89c76SBlaise Bourdin   PetscViewerExodusIIGetZonalVariableIndex - return the location of a zonal variable in an exodusII file given its name
708*49c89c76SBlaise Bourdin 
709*49c89c76SBlaise Bourdin   Collective
710*49c89c76SBlaise Bourdin 
711*49c89c76SBlaise Bourdin   Input Parameters:
712*49c89c76SBlaise Bourdin + viewer - a `PetscViewer` of type `PETSCVIEWEREXODUSII`
713*49c89c76SBlaise Bourdin - name   - the name of the result
714*49c89c76SBlaise Bourdin 
715*49c89c76SBlaise Bourdin   Output Parameter:
716*49c89c76SBlaise Bourdin . varIndex - the location of the variable in the exodus file or -1 if the variable is not found
717*49c89c76SBlaise Bourdin 
718*49c89c76SBlaise Bourdin   Level: beginner
719*49c89c76SBlaise Bourdin 
720*49c89c76SBlaise Bourdin   Notes:
721*49c89c76SBlaise Bourdin   The exodus variable index is obtained by comparing the name argument to the
722*49c89c76SBlaise Bourdin   names of zonal variables declared in the exodus file. For instance if name is "V"
723*49c89c76SBlaise Bourdin   the location in the exodus file will be the first match of "V", "V_X", "V_XX", "V_1", or "V_11"
724*49c89c76SBlaise Bourdin   amongst all variables of type obj_type.
725*49c89c76SBlaise Bourdin 
726*49c89c76SBlaise Bourdin .seealso: `PetscViewerExodusIISetNodalVariable()`, `PetscViewerExodusIIGetNodalVariable()`, `PetscViewerExodusIISetNodalVariableName()`, `PetscViewerExodusIISetNodalVariableNames()`, `PetscViewerExodusIIGetNodalVariableName()`, `PetscViewerExodusIIGetNodalVariableNames()`
727*49c89c76SBlaise Bourdin @*/
728*49c89c76SBlaise Bourdin PetscErrorCode PetscViewerExodusIIGetZonalVariableIndex(PetscViewer viewer, const char name[], int *varIndex)
729*49c89c76SBlaise Bourdin {
730*49c89c76SBlaise Bourdin   int       num_vars = 0, i, j;
731*49c89c76SBlaise Bourdin   char      ext_name[MAX_STR_LENGTH + 1];
732*49c89c76SBlaise Bourdin   char    **var_names;
733*49c89c76SBlaise Bourdin   const int num_suffix = 5;
734*49c89c76SBlaise Bourdin   char     *suffix[5];
735*49c89c76SBlaise Bourdin   PetscBool flg;
736*49c89c76SBlaise Bourdin 
737*49c89c76SBlaise Bourdin   PetscFunctionBegin;
738*49c89c76SBlaise Bourdin   suffix[0] = (char *)"";
739*49c89c76SBlaise Bourdin   suffix[1] = (char *)"_X";
740*49c89c76SBlaise Bourdin   suffix[2] = (char *)"_XX";
741*49c89c76SBlaise Bourdin   suffix[3] = (char *)"_1";
742*49c89c76SBlaise Bourdin   suffix[4] = (char *)"_11";
743*49c89c76SBlaise Bourdin   *varIndex = -1;
744*49c89c76SBlaise Bourdin 
745*49c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetZonalVariableNames(viewer, &num_vars, &var_names));
746*49c89c76SBlaise Bourdin   for (i = 0; i < num_vars; ++i) {
747*49c89c76SBlaise Bourdin     for (j = 0; j < num_suffix; ++j) {
748*49c89c76SBlaise Bourdin       PetscCall(PetscStrncpy(ext_name, name, MAX_STR_LENGTH));
749*49c89c76SBlaise Bourdin       PetscCall(PetscStrlcat(ext_name, suffix[j], MAX_STR_LENGTH));
750*49c89c76SBlaise Bourdin       PetscCall(PetscStrcasecmp(ext_name, var_names[i], &flg));
751*49c89c76SBlaise Bourdin       if (flg) *varIndex = i;
752*49c89c76SBlaise Bourdin     }
753*49c89c76SBlaise Bourdin     if (flg) break;
754*49c89c76SBlaise Bourdin   }
755*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
756*49c89c76SBlaise Bourdin }
757*49c89c76SBlaise Bourdin 
758*49c89c76SBlaise Bourdin PetscErrorCode DMView_PlexExodusII(DM dm, PetscViewer viewer)
759*49c89c76SBlaise Bourdin {
760*49c89c76SBlaise Bourdin   enum ElemType {
761*49c89c76SBlaise Bourdin     SEGMENT,
762*49c89c76SBlaise Bourdin     TRI,
763*49c89c76SBlaise Bourdin     QUAD,
764*49c89c76SBlaise Bourdin     TET,
765*49c89c76SBlaise Bourdin     HEX
766*49c89c76SBlaise Bourdin   };
767*49c89c76SBlaise Bourdin   MPI_Comm comm;
768*49c89c76SBlaise Bourdin   int      degree; /* the order of the mesh */
769*49c89c76SBlaise Bourdin   /* Connectivity Variables */
770*49c89c76SBlaise Bourdin   PetscInt cellsNotInConnectivity;
771*49c89c76SBlaise Bourdin   /* Cell Sets */
772*49c89c76SBlaise Bourdin   DMLabel         csLabel;
773*49c89c76SBlaise Bourdin   IS              csIS;
774*49c89c76SBlaise Bourdin   const PetscInt *csIdx;
775*49c89c76SBlaise Bourdin   PetscInt        num_cs, cs;
776*49c89c76SBlaise Bourdin   enum ElemType  *type;
777*49c89c76SBlaise Bourdin   PetscBool       hasLabel;
778*49c89c76SBlaise Bourdin   /* Coordinate Variables */
779*49c89c76SBlaise Bourdin   DM           cdm;
780*49c89c76SBlaise Bourdin   PetscSection coordSection;
781*49c89c76SBlaise Bourdin   Vec          coord;
782*49c89c76SBlaise Bourdin   PetscInt   **nodes;
783*49c89c76SBlaise Bourdin   PetscInt     depth, d, dim, skipCells = 0;
784*49c89c76SBlaise Bourdin   PetscInt     pStart, pEnd, p, cStart, cEnd, numCells, vStart, vEnd, numVertices, eStart, eEnd, numEdges, fStart, fEnd, numFaces, numNodes;
785*49c89c76SBlaise Bourdin   PetscInt     num_vs, num_fs;
786*49c89c76SBlaise Bourdin   PetscMPIInt  rank, size;
787*49c89c76SBlaise Bourdin   const char  *dmName;
788*49c89c76SBlaise Bourdin   PetscInt     nodesLineP1[4] = {2, 0, 0, 0};
789*49c89c76SBlaise Bourdin   PetscInt     nodesLineP2[4] = {2, 0, 0, 1};
790*49c89c76SBlaise Bourdin   PetscInt     nodesTriP1[4]  = {3, 0, 0, 0};
791*49c89c76SBlaise Bourdin   PetscInt     nodesTriP2[4]  = {3, 3, 0, 0};
792*49c89c76SBlaise Bourdin   PetscInt     nodesQuadP1[4] = {4, 0, 0, 0};
793*49c89c76SBlaise Bourdin   PetscInt     nodesQuadP2[4] = {4, 4, 0, 1};
794*49c89c76SBlaise Bourdin   PetscInt     nodesTetP1[4]  = {4, 0, 0, 0};
795*49c89c76SBlaise Bourdin   PetscInt     nodesTetP2[4]  = {4, 6, 0, 0};
796*49c89c76SBlaise Bourdin   PetscInt     nodesHexP1[4]  = {8, 0, 0, 0};
797*49c89c76SBlaise Bourdin   PetscInt     nodesHexP2[4]  = {8, 12, 6, 1};
798*49c89c76SBlaise Bourdin   int          CPU_word_size, IO_word_size, EXO_mode;
799*49c89c76SBlaise Bourdin   float        EXO_version;
800*49c89c76SBlaise Bourdin 
801*49c89c76SBlaise Bourdin   PetscViewer_ExodusII *exo = (PetscViewer_ExodusII *)viewer->data;
802*49c89c76SBlaise Bourdin 
803*49c89c76SBlaise Bourdin   PetscFunctionBegin;
804*49c89c76SBlaise Bourdin   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
805*49c89c76SBlaise Bourdin   PetscCallMPI(MPI_Comm_rank(comm, &rank));
806*49c89c76SBlaise Bourdin   PetscCallMPI(MPI_Comm_size(comm, &size));
807*49c89c76SBlaise Bourdin 
808*49c89c76SBlaise Bourdin   /*
809*49c89c76SBlaise Bourdin     Creating coordSection is a collective operation so we do it somewhat out of sequence
810*49c89c76SBlaise Bourdin   */
811*49c89c76SBlaise Bourdin   PetscCall(PetscSectionCreate(comm, &coordSection));
812*49c89c76SBlaise Bourdin   PetscCall(DMGetCoordinatesLocalSetUp(dm));
813*49c89c76SBlaise Bourdin   /*
814*49c89c76SBlaise Bourdin     Check that all points are on rank 0 since we don't know how to save distributed DM in exodus format
815*49c89c76SBlaise Bourdin   */
816*49c89c76SBlaise Bourdin   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
817*49c89c76SBlaise Bourdin   PetscCall(DMPlexGetHeightStratum(dm, 1, &fStart, &fEnd));
818*49c89c76SBlaise Bourdin   PetscCall(DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd));
819*49c89c76SBlaise Bourdin   PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd));
820*49c89c76SBlaise Bourdin   numCells    = cEnd - cStart;
821*49c89c76SBlaise Bourdin   numEdges    = eEnd - eStart;
822*49c89c76SBlaise Bourdin   numVertices = vEnd - vStart;
823*49c89c76SBlaise Bourdin   PetscCheck(!(rank && (numCells || numEdges || numVertices)), PETSC_COMM_SELF, PETSC_ERR_SUP, "Writing distributed DM in exodusII format not supported");
824*49c89c76SBlaise Bourdin   if (rank == 0) {
825*49c89c76SBlaise Bourdin     switch (exo->btype) {
826*49c89c76SBlaise Bourdin     case FILE_MODE_READ:
827*49c89c76SBlaise Bourdin     case FILE_MODE_APPEND:
828*49c89c76SBlaise Bourdin     case FILE_MODE_UPDATE:
829*49c89c76SBlaise Bourdin     case FILE_MODE_APPEND_UPDATE:
830*49c89c76SBlaise Bourdin       /* exodusII does not allow writing geometry to an existing file */
831*49c89c76SBlaise Bourdin       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "cannot add geometry to existing file %s", exo->filename);
832*49c89c76SBlaise Bourdin     case FILE_MODE_WRITE:
833*49c89c76SBlaise Bourdin       /* Create an empty file if one already exists*/
834*49c89c76SBlaise Bourdin       EXO_mode = EX_CLOBBER;
835*49c89c76SBlaise Bourdin #if defined(PETSC_USE_64BIT_INDICES)
836*49c89c76SBlaise Bourdin       EXO_mode += EX_ALL_INT64_API;
837*49c89c76SBlaise Bourdin #endif
838*49c89c76SBlaise Bourdin       CPU_word_size = sizeof(PetscReal);
839*49c89c76SBlaise Bourdin       IO_word_size  = sizeof(PetscReal);
840*49c89c76SBlaise Bourdin       exo->exoid    = ex_create(exo->filename, EXO_mode, &CPU_word_size, &IO_word_size);
841*49c89c76SBlaise Bourdin       PetscCheck(exo->exoid >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "ex_create failed for %s", exo->filename);
842*49c89c76SBlaise Bourdin 
843*49c89c76SBlaise Bourdin       break;
844*49c89c76SBlaise Bourdin     default:
845*49c89c76SBlaise Bourdin       SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()");
846*49c89c76SBlaise Bourdin     }
847*49c89c76SBlaise Bourdin 
848*49c89c76SBlaise Bourdin     /* --- Get DM info --- */
849*49c89c76SBlaise Bourdin     PetscCall(PetscObjectGetName((PetscObject)dm, &dmName));
850*49c89c76SBlaise Bourdin     PetscCall(DMPlexGetDepth(dm, &depth));
851*49c89c76SBlaise Bourdin     PetscCall(DMGetDimension(dm, &dim));
852*49c89c76SBlaise Bourdin     PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
853*49c89c76SBlaise Bourdin     if (depth == 3) {
854*49c89c76SBlaise Bourdin       numFaces = fEnd - fStart;
855*49c89c76SBlaise Bourdin     } else {
856*49c89c76SBlaise Bourdin       numFaces = 0;
857*49c89c76SBlaise Bourdin     }
858*49c89c76SBlaise Bourdin     PetscCall(DMGetLabelSize(dm, "Cell Sets", &num_cs));
859*49c89c76SBlaise Bourdin     PetscCall(DMGetLabelSize(dm, "Vertex Sets", &num_vs));
860*49c89c76SBlaise Bourdin     PetscCall(DMGetLabelSize(dm, "Face Sets", &num_fs));
861*49c89c76SBlaise Bourdin     PetscCall(DMGetCoordinatesLocal(dm, &coord));
862*49c89c76SBlaise Bourdin     PetscCall(DMGetCoordinateDM(dm, &cdm));
863*49c89c76SBlaise Bourdin     if (num_cs > 0) {
864*49c89c76SBlaise Bourdin       PetscCall(DMGetLabel(dm, "Cell Sets", &csLabel));
865*49c89c76SBlaise Bourdin       PetscCall(DMLabelGetValueIS(csLabel, &csIS));
866*49c89c76SBlaise Bourdin       PetscCall(ISGetIndices(csIS, &csIdx));
867*49c89c76SBlaise Bourdin     }
868*49c89c76SBlaise Bourdin     PetscCall(PetscMalloc1(num_cs, &nodes));
869*49c89c76SBlaise Bourdin     /* Set element type for each block and compute total number of nodes */
870*49c89c76SBlaise Bourdin     PetscCall(PetscMalloc1(num_cs, &type));
871*49c89c76SBlaise Bourdin     numNodes = numVertices;
872*49c89c76SBlaise Bourdin 
873*49c89c76SBlaise Bourdin     PetscCall(PetscViewerExodusIIGetOrder(viewer, &degree));
874*49c89c76SBlaise Bourdin     if (degree == 2) numNodes += numEdges;
875*49c89c76SBlaise Bourdin     cellsNotInConnectivity = numCells;
876*49c89c76SBlaise Bourdin     for (cs = 0; cs < num_cs; ++cs) {
877*49c89c76SBlaise Bourdin       IS              stratumIS;
878*49c89c76SBlaise Bourdin       const PetscInt *cells;
879*49c89c76SBlaise Bourdin       PetscScalar    *xyz = NULL;
880*49c89c76SBlaise Bourdin       PetscInt        csSize, closureSize;
881*49c89c76SBlaise Bourdin 
882*49c89c76SBlaise Bourdin       PetscCall(DMLabelGetStratumIS(csLabel, csIdx[cs], &stratumIS));
883*49c89c76SBlaise Bourdin       PetscCall(ISGetIndices(stratumIS, &cells));
884*49c89c76SBlaise Bourdin       PetscCall(ISGetSize(stratumIS, &csSize));
885*49c89c76SBlaise Bourdin       PetscCall(DMPlexVecGetClosure(cdm, NULL, coord, cells[0], &closureSize, &xyz));
886*49c89c76SBlaise Bourdin       switch (dim) {
887*49c89c76SBlaise Bourdin       case 1:
888*49c89c76SBlaise Bourdin         if (closureSize == 2 * dim) {
889*49c89c76SBlaise Bourdin           type[cs] = SEGMENT;
890*49c89c76SBlaise 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);
891*49c89c76SBlaise Bourdin       case 2:
892*49c89c76SBlaise Bourdin         if (closureSize == 3 * dim) {
893*49c89c76SBlaise Bourdin           type[cs] = TRI;
894*49c89c76SBlaise Bourdin         } else if (closureSize == 4 * dim) {
895*49c89c76SBlaise Bourdin           type[cs] = QUAD;
896*49c89c76SBlaise 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);
897*49c89c76SBlaise Bourdin         break;
898*49c89c76SBlaise Bourdin       case 3:
899*49c89c76SBlaise Bourdin         if (closureSize == 4 * dim) {
900*49c89c76SBlaise Bourdin           type[cs] = TET;
901*49c89c76SBlaise Bourdin         } else if (closureSize == 8 * dim) {
902*49c89c76SBlaise Bourdin           type[cs] = HEX;
903*49c89c76SBlaise 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);
904*49c89c76SBlaise Bourdin         break;
905*49c89c76SBlaise Bourdin       default:
906*49c89c76SBlaise Bourdin         SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Dimension %" PetscInt_FMT " not handled by ExodusII viewer", dim);
907*49c89c76SBlaise Bourdin       }
908*49c89c76SBlaise Bourdin       if ((degree == 2) && (type[cs] == SEGMENT)) numNodes += csSize;
909*49c89c76SBlaise Bourdin       if ((degree == 2) && (type[cs] == QUAD)) numNodes += csSize;
910*49c89c76SBlaise Bourdin       if ((degree == 2) && (type[cs] == HEX)) {
911*49c89c76SBlaise Bourdin         numNodes += csSize;
912*49c89c76SBlaise Bourdin         numNodes += numFaces;
913*49c89c76SBlaise Bourdin       }
914*49c89c76SBlaise Bourdin       PetscCall(DMPlexVecRestoreClosure(cdm, NULL, coord, cells[0], &closureSize, &xyz));
915*49c89c76SBlaise Bourdin       /* Set nodes and Element type */
916*49c89c76SBlaise Bourdin       if (type[cs] == SEGMENT) {
917*49c89c76SBlaise Bourdin         if (degree == 1) nodes[cs] = nodesLineP1;
918*49c89c76SBlaise Bourdin         else if (degree == 2) nodes[cs] = nodesLineP2;
919*49c89c76SBlaise Bourdin       } else if (type[cs] == TRI) {
920*49c89c76SBlaise Bourdin         if (degree == 1) nodes[cs] = nodesTriP1;
921*49c89c76SBlaise Bourdin         else if (degree == 2) nodes[cs] = nodesTriP2;
922*49c89c76SBlaise Bourdin       } else if (type[cs] == QUAD) {
923*49c89c76SBlaise Bourdin         if (degree == 1) nodes[cs] = nodesQuadP1;
924*49c89c76SBlaise Bourdin         else if (degree == 2) nodes[cs] = nodesQuadP2;
925*49c89c76SBlaise Bourdin       } else if (type[cs] == TET) {
926*49c89c76SBlaise Bourdin         if (degree == 1) nodes[cs] = nodesTetP1;
927*49c89c76SBlaise Bourdin         else if (degree == 2) nodes[cs] = nodesTetP2;
928*49c89c76SBlaise Bourdin       } else if (type[cs] == HEX) {
929*49c89c76SBlaise Bourdin         if (degree == 1) nodes[cs] = nodesHexP1;
930*49c89c76SBlaise Bourdin         else if (degree == 2) nodes[cs] = nodesHexP2;
931*49c89c76SBlaise Bourdin       }
932*49c89c76SBlaise Bourdin       /* Compute the number of cells not in the connectivity table */
933*49c89c76SBlaise Bourdin       cellsNotInConnectivity -= nodes[cs][3] * csSize;
934*49c89c76SBlaise Bourdin 
935*49c89c76SBlaise Bourdin       PetscCall(ISRestoreIndices(stratumIS, &cells));
936*49c89c76SBlaise Bourdin       PetscCall(ISDestroy(&stratumIS));
937*49c89c76SBlaise Bourdin     }
938*49c89c76SBlaise Bourdin     if (num_cs) PetscCallExternal(ex_put_init, exo->exoid, dmName, dim, numNodes, numCells, num_cs, num_vs, num_fs);
939*49c89c76SBlaise Bourdin     /* --- Connectivity --- */
940*49c89c76SBlaise Bourdin     for (cs = 0; cs < num_cs; ++cs) {
941*49c89c76SBlaise Bourdin       IS              stratumIS;
942*49c89c76SBlaise Bourdin       const PetscInt *cells;
943*49c89c76SBlaise Bourdin       PetscInt       *connect, off = 0;
944*49c89c76SBlaise Bourdin       PetscInt        edgesInClosure = 0, facesInClosure = 0, verticesInClosure = 0;
945*49c89c76SBlaise Bourdin       PetscInt        csSize, c, connectSize, closureSize;
946*49c89c76SBlaise Bourdin       char           *elem_type        = NULL;
947*49c89c76SBlaise Bourdin       char            elem_type_bar2[] = "BAR2", elem_type_bar3[] = "BAR3";
948*49c89c76SBlaise Bourdin       char            elem_type_tri3[] = "TRI3", elem_type_quad4[] = "QUAD4";
949*49c89c76SBlaise Bourdin       char            elem_type_tri6[] = "TRI6", elem_type_quad9[] = "QUAD9";
950*49c89c76SBlaise Bourdin       char            elem_type_tet4[] = "TET4", elem_type_hex8[] = "HEX8";
951*49c89c76SBlaise Bourdin       char            elem_type_tet10[] = "TET10", elem_type_hex27[] = "HEX27";
952*49c89c76SBlaise Bourdin 
953*49c89c76SBlaise Bourdin       PetscCall(DMLabelGetStratumIS(csLabel, csIdx[cs], &stratumIS));
954*49c89c76SBlaise Bourdin       PetscCall(ISGetIndices(stratumIS, &cells));
955*49c89c76SBlaise Bourdin       PetscCall(ISGetSize(stratumIS, &csSize));
956*49c89c76SBlaise Bourdin       /* Set Element type */
957*49c89c76SBlaise Bourdin       if (type[cs] == SEGMENT) {
958*49c89c76SBlaise Bourdin         if (degree == 1) elem_type = elem_type_bar2;
959*49c89c76SBlaise Bourdin         else if (degree == 2) elem_type = elem_type_bar3;
960*49c89c76SBlaise Bourdin       } else if (type[cs] == TRI) {
961*49c89c76SBlaise Bourdin         if (degree == 1) elem_type = elem_type_tri3;
962*49c89c76SBlaise Bourdin         else if (degree == 2) elem_type = elem_type_tri6;
963*49c89c76SBlaise Bourdin       } else if (type[cs] == QUAD) {
964*49c89c76SBlaise Bourdin         if (degree == 1) elem_type = elem_type_quad4;
965*49c89c76SBlaise Bourdin         else if (degree == 2) elem_type = elem_type_quad9;
966*49c89c76SBlaise Bourdin       } else if (type[cs] == TET) {
967*49c89c76SBlaise Bourdin         if (degree == 1) elem_type = elem_type_tet4;
968*49c89c76SBlaise Bourdin         else if (degree == 2) elem_type = elem_type_tet10;
969*49c89c76SBlaise Bourdin       } else if (type[cs] == HEX) {
970*49c89c76SBlaise Bourdin         if (degree == 1) elem_type = elem_type_hex8;
971*49c89c76SBlaise Bourdin         else if (degree == 2) elem_type = elem_type_hex27;
972*49c89c76SBlaise Bourdin       }
973*49c89c76SBlaise Bourdin       connectSize = nodes[cs][0] + nodes[cs][1] + nodes[cs][2] + nodes[cs][3];
974*49c89c76SBlaise Bourdin       PetscCall(PetscMalloc1(PetscMax(27, connectSize) * csSize, &connect));
975*49c89c76SBlaise Bourdin       PetscCallExternal(ex_put_block, exo->exoid, EX_ELEM_BLOCK, csIdx[cs], elem_type, csSize, connectSize, 0, 0, 1);
976*49c89c76SBlaise Bourdin       /* Find number of vertices, edges, and faces in the closure */
977*49c89c76SBlaise Bourdin       verticesInClosure = nodes[cs][0];
978*49c89c76SBlaise Bourdin       if (depth > 1) {
979*49c89c76SBlaise Bourdin         if (dim == 2) {
980*49c89c76SBlaise Bourdin           PetscCall(DMPlexGetConeSize(dm, cells[0], &edgesInClosure));
981*49c89c76SBlaise Bourdin         } else if (dim == 3) {
982*49c89c76SBlaise Bourdin           PetscInt *closure = NULL;
983*49c89c76SBlaise Bourdin 
984*49c89c76SBlaise Bourdin           PetscCall(DMPlexGetConeSize(dm, cells[0], &facesInClosure));
985*49c89c76SBlaise Bourdin           PetscCall(DMPlexGetTransitiveClosure(dm, cells[0], PETSC_TRUE, &closureSize, &closure));
986*49c89c76SBlaise Bourdin           edgesInClosure = closureSize - facesInClosure - 1 - verticesInClosure;
987*49c89c76SBlaise Bourdin           PetscCall(DMPlexRestoreTransitiveClosure(dm, cells[0], PETSC_TRUE, &closureSize, &closure));
988*49c89c76SBlaise Bourdin         }
989*49c89c76SBlaise Bourdin       }
990*49c89c76SBlaise Bourdin       /* Get connectivity for each cell */
991*49c89c76SBlaise Bourdin       for (c = 0; c < csSize; ++c) {
992*49c89c76SBlaise Bourdin         PetscInt *closure = NULL;
993*49c89c76SBlaise Bourdin         PetscInt  temp, i;
994*49c89c76SBlaise Bourdin 
995*49c89c76SBlaise Bourdin         PetscCall(DMPlexGetTransitiveClosure(dm, cells[c], PETSC_TRUE, &closureSize, &closure));
996*49c89c76SBlaise Bourdin         for (i = 0; i < connectSize; ++i) {
997*49c89c76SBlaise Bourdin           if (i < nodes[cs][0]) { /* Vertices */
998*49c89c76SBlaise Bourdin             connect[i + off] = closure[(i + edgesInClosure + facesInClosure + 1) * 2] + 1;
999*49c89c76SBlaise Bourdin             connect[i + off] -= cellsNotInConnectivity;
1000*49c89c76SBlaise Bourdin           } else if (i < nodes[cs][0] + nodes[cs][1]) { /* Edges */
1001*49c89c76SBlaise Bourdin             connect[i + off] = closure[(i - verticesInClosure + facesInClosure + 1) * 2] + 1;
1002*49c89c76SBlaise Bourdin             if (nodes[cs][2] == 0) connect[i + off] -= numFaces;
1003*49c89c76SBlaise Bourdin             connect[i + off] -= cellsNotInConnectivity;
1004*49c89c76SBlaise Bourdin           } else if (i < nodes[cs][0] + nodes[cs][1] + nodes[cs][3]) { /* Cells */
1005*49c89c76SBlaise Bourdin             connect[i + off] = closure[0] + 1;
1006*49c89c76SBlaise Bourdin             connect[i + off] -= skipCells;
1007*49c89c76SBlaise Bourdin           } else if (i < nodes[cs][0] + nodes[cs][1] + nodes[cs][3] + nodes[cs][2]) { /* Faces */
1008*49c89c76SBlaise Bourdin             connect[i + off] = closure[(i - edgesInClosure - verticesInClosure) * 2] + 1;
1009*49c89c76SBlaise Bourdin             connect[i + off] -= cellsNotInConnectivity;
1010*49c89c76SBlaise Bourdin           } else {
1011*49c89c76SBlaise Bourdin             connect[i + off] = -1;
1012*49c89c76SBlaise Bourdin           }
1013*49c89c76SBlaise Bourdin         }
1014*49c89c76SBlaise Bourdin         /* Tetrahedra are inverted */
1015*49c89c76SBlaise Bourdin         if (type[cs] == TET) {
1016*49c89c76SBlaise Bourdin           temp             = connect[0 + off];
1017*49c89c76SBlaise Bourdin           connect[0 + off] = connect[1 + off];
1018*49c89c76SBlaise Bourdin           connect[1 + off] = temp;
1019*49c89c76SBlaise Bourdin           if (degree == 2) {
1020*49c89c76SBlaise Bourdin             temp             = connect[5 + off];
1021*49c89c76SBlaise Bourdin             connect[5 + off] = connect[6 + off];
1022*49c89c76SBlaise Bourdin             connect[6 + off] = temp;
1023*49c89c76SBlaise Bourdin             temp             = connect[7 + off];
1024*49c89c76SBlaise Bourdin             connect[7 + off] = connect[8 + off];
1025*49c89c76SBlaise Bourdin             connect[8 + off] = temp;
1026*49c89c76SBlaise Bourdin           }
1027*49c89c76SBlaise Bourdin         }
1028*49c89c76SBlaise Bourdin         /* Hexahedra are inverted */
1029*49c89c76SBlaise Bourdin         if (type[cs] == HEX) {
1030*49c89c76SBlaise Bourdin           temp             = connect[1 + off];
1031*49c89c76SBlaise Bourdin           connect[1 + off] = connect[3 + off];
1032*49c89c76SBlaise Bourdin           connect[3 + off] = temp;
1033*49c89c76SBlaise Bourdin           if (degree == 2) {
1034*49c89c76SBlaise Bourdin             temp              = connect[8 + off];
1035*49c89c76SBlaise Bourdin             connect[8 + off]  = connect[11 + off];
1036*49c89c76SBlaise Bourdin             connect[11 + off] = temp;
1037*49c89c76SBlaise Bourdin             temp              = connect[9 + off];
1038*49c89c76SBlaise Bourdin             connect[9 + off]  = connect[10 + off];
1039*49c89c76SBlaise Bourdin             connect[10 + off] = temp;
1040*49c89c76SBlaise Bourdin             temp              = connect[16 + off];
1041*49c89c76SBlaise Bourdin             connect[16 + off] = connect[17 + off];
1042*49c89c76SBlaise Bourdin             connect[17 + off] = temp;
1043*49c89c76SBlaise Bourdin             temp              = connect[18 + off];
1044*49c89c76SBlaise Bourdin             connect[18 + off] = connect[19 + off];
1045*49c89c76SBlaise Bourdin             connect[19 + off] = temp;
1046*49c89c76SBlaise Bourdin 
1047*49c89c76SBlaise Bourdin             temp              = connect[12 + off];
1048*49c89c76SBlaise Bourdin             connect[12 + off] = connect[16 + off];
1049*49c89c76SBlaise Bourdin             connect[16 + off] = temp;
1050*49c89c76SBlaise Bourdin             temp              = connect[13 + off];
1051*49c89c76SBlaise Bourdin             connect[13 + off] = connect[17 + off];
1052*49c89c76SBlaise Bourdin             connect[17 + off] = temp;
1053*49c89c76SBlaise Bourdin             temp              = connect[14 + off];
1054*49c89c76SBlaise Bourdin             connect[14 + off] = connect[18 + off];
1055*49c89c76SBlaise Bourdin             connect[18 + off] = temp;
1056*49c89c76SBlaise Bourdin             temp              = connect[15 + off];
1057*49c89c76SBlaise Bourdin             connect[15 + off] = connect[19 + off];
1058*49c89c76SBlaise Bourdin             connect[19 + off] = temp;
1059*49c89c76SBlaise Bourdin 
1060*49c89c76SBlaise Bourdin             temp              = connect[23 + off];
1061*49c89c76SBlaise Bourdin             connect[23 + off] = connect[26 + off];
1062*49c89c76SBlaise Bourdin             connect[26 + off] = temp;
1063*49c89c76SBlaise Bourdin             temp              = connect[24 + off];
1064*49c89c76SBlaise Bourdin             connect[24 + off] = connect[25 + off];
1065*49c89c76SBlaise Bourdin             connect[25 + off] = temp;
1066*49c89c76SBlaise Bourdin             temp              = connect[25 + off];
1067*49c89c76SBlaise Bourdin             connect[25 + off] = connect[26 + off];
1068*49c89c76SBlaise Bourdin             connect[26 + off] = temp;
1069*49c89c76SBlaise Bourdin           }
1070*49c89c76SBlaise Bourdin         }
1071*49c89c76SBlaise Bourdin         off += connectSize;
1072*49c89c76SBlaise Bourdin         PetscCall(DMPlexRestoreTransitiveClosure(dm, cells[c], PETSC_TRUE, &closureSize, &closure));
1073*49c89c76SBlaise Bourdin       }
1074*49c89c76SBlaise Bourdin       PetscCallExternal(ex_put_conn, exo->exoid, EX_ELEM_BLOCK, csIdx[cs], connect, 0, 0);
1075*49c89c76SBlaise Bourdin       skipCells += (nodes[cs][3] == 0) * csSize;
1076*49c89c76SBlaise Bourdin       PetscCall(PetscFree(connect));
1077*49c89c76SBlaise Bourdin       PetscCall(ISRestoreIndices(stratumIS, &cells));
1078*49c89c76SBlaise Bourdin       PetscCall(ISDestroy(&stratumIS));
1079*49c89c76SBlaise Bourdin     }
1080*49c89c76SBlaise Bourdin     PetscCall(PetscFree(type));
1081*49c89c76SBlaise Bourdin     /* --- Coordinates --- */
1082*49c89c76SBlaise Bourdin     PetscCall(PetscSectionSetChart(coordSection, pStart, pEnd));
1083*49c89c76SBlaise Bourdin     if (num_cs) {
1084*49c89c76SBlaise Bourdin       for (d = 0; d < depth; ++d) {
1085*49c89c76SBlaise Bourdin         PetscCall(DMPlexGetDepthStratum(dm, d, &pStart, &pEnd));
1086*49c89c76SBlaise Bourdin         for (p = pStart; p < pEnd; ++p) PetscCall(PetscSectionSetDof(coordSection, p, nodes[0][d] > 0));
1087*49c89c76SBlaise Bourdin       }
1088*49c89c76SBlaise Bourdin     }
1089*49c89c76SBlaise Bourdin     for (cs = 0; cs < num_cs; ++cs) {
1090*49c89c76SBlaise Bourdin       IS              stratumIS;
1091*49c89c76SBlaise Bourdin       const PetscInt *cells;
1092*49c89c76SBlaise Bourdin       PetscInt        csSize, c;
1093*49c89c76SBlaise Bourdin 
1094*49c89c76SBlaise Bourdin       PetscCall(DMLabelGetStratumIS(csLabel, csIdx[cs], &stratumIS));
1095*49c89c76SBlaise Bourdin       PetscCall(ISGetIndices(stratumIS, &cells));
1096*49c89c76SBlaise Bourdin       PetscCall(ISGetSize(stratumIS, &csSize));
1097*49c89c76SBlaise Bourdin       for (c = 0; c < csSize; ++c) PetscCall(PetscSectionSetDof(coordSection, cells[c], nodes[cs][3] > 0));
1098*49c89c76SBlaise Bourdin       PetscCall(ISRestoreIndices(stratumIS, &cells));
1099*49c89c76SBlaise Bourdin       PetscCall(ISDestroy(&stratumIS));
1100*49c89c76SBlaise Bourdin     }
1101*49c89c76SBlaise Bourdin     if (num_cs) {
1102*49c89c76SBlaise Bourdin       PetscCall(ISRestoreIndices(csIS, &csIdx));
1103*49c89c76SBlaise Bourdin       PetscCall(ISDestroy(&csIS));
1104*49c89c76SBlaise Bourdin     }
1105*49c89c76SBlaise Bourdin     PetscCall(PetscFree(nodes));
1106*49c89c76SBlaise Bourdin     PetscCall(PetscSectionSetUp(coordSection));
1107*49c89c76SBlaise Bourdin     if (numNodes) {
1108*49c89c76SBlaise Bourdin       const char  *coordNames[3] = {"x", "y", "z"};
1109*49c89c76SBlaise Bourdin       PetscScalar *closure, *cval;
1110*49c89c76SBlaise Bourdin       PetscReal   *coords;
1111*49c89c76SBlaise Bourdin       PetscInt     hasDof, n = 0;
1112*49c89c76SBlaise Bourdin 
1113*49c89c76SBlaise Bourdin       /* There can't be more than 24 values in the closure of a point for the coord coordSection */
1114*49c89c76SBlaise Bourdin       PetscCall(PetscCalloc3(numNodes * 3, &coords, dim, &cval, 24, &closure));
1115*49c89c76SBlaise Bourdin       PetscCall(DMGetCoordinatesLocalNoncollective(dm, &coord));
1116*49c89c76SBlaise Bourdin       PetscCall(DMPlexGetChart(dm, &pStart, &pEnd));
1117*49c89c76SBlaise Bourdin       for (p = pStart; p < pEnd; ++p) {
1118*49c89c76SBlaise Bourdin         PetscCall(PetscSectionGetDof(coordSection, p, &hasDof));
1119*49c89c76SBlaise Bourdin         if (hasDof) {
1120*49c89c76SBlaise Bourdin           PetscInt closureSize = 24, j;
1121*49c89c76SBlaise Bourdin 
1122*49c89c76SBlaise Bourdin           PetscCall(DMPlexVecGetClosure(cdm, NULL, coord, p, &closureSize, &closure));
1123*49c89c76SBlaise Bourdin           for (d = 0; d < dim; ++d) {
1124*49c89c76SBlaise Bourdin             cval[d] = 0.0;
1125*49c89c76SBlaise Bourdin             for (j = 0; j < closureSize / dim; j++) cval[d] += closure[j * dim + d];
1126*49c89c76SBlaise Bourdin             coords[d * numNodes + n] = PetscRealPart(cval[d]) * dim / closureSize;
1127*49c89c76SBlaise Bourdin           }
1128*49c89c76SBlaise Bourdin           ++n;
1129*49c89c76SBlaise Bourdin         }
1130*49c89c76SBlaise Bourdin       }
1131*49c89c76SBlaise Bourdin       PetscCallExternal(ex_put_coord, exo->exoid, &coords[0 * numNodes], &coords[1 * numNodes], &coords[2 * numNodes]);
1132*49c89c76SBlaise Bourdin       PetscCall(PetscFree3(coords, cval, closure));
1133*49c89c76SBlaise Bourdin       PetscCallExternal(ex_put_coord_names, exo->exoid, (char **)coordNames);
1134*49c89c76SBlaise Bourdin     }
1135*49c89c76SBlaise Bourdin 
1136*49c89c76SBlaise Bourdin     /* --- Node Sets/Vertex Sets --- */
1137*49c89c76SBlaise Bourdin     PetscCall(DMHasLabel(dm, "Vertex Sets", &hasLabel));
1138*49c89c76SBlaise Bourdin     if (hasLabel) {
1139*49c89c76SBlaise Bourdin       PetscInt        i, vs, vsSize;
1140*49c89c76SBlaise Bourdin       const PetscInt *vsIdx, *vertices;
1141*49c89c76SBlaise Bourdin       PetscInt       *nodeList;
1142*49c89c76SBlaise Bourdin       IS              vsIS, stratumIS;
1143*49c89c76SBlaise Bourdin       DMLabel         vsLabel;
1144*49c89c76SBlaise Bourdin       PetscCall(DMGetLabel(dm, "Vertex Sets", &vsLabel));
1145*49c89c76SBlaise Bourdin       PetscCall(DMLabelGetValueIS(vsLabel, &vsIS));
1146*49c89c76SBlaise Bourdin       PetscCall(ISGetIndices(vsIS, &vsIdx));
1147*49c89c76SBlaise Bourdin       for (vs = 0; vs < num_vs; ++vs) {
1148*49c89c76SBlaise Bourdin         PetscCall(DMLabelGetStratumIS(vsLabel, vsIdx[vs], &stratumIS));
1149*49c89c76SBlaise Bourdin         PetscCall(ISGetIndices(stratumIS, &vertices));
1150*49c89c76SBlaise Bourdin         PetscCall(ISGetSize(stratumIS, &vsSize));
1151*49c89c76SBlaise Bourdin         PetscCall(PetscMalloc1(vsSize, &nodeList));
1152*49c89c76SBlaise Bourdin         for (i = 0; i < vsSize; ++i) nodeList[i] = vertices[i] - skipCells + 1;
1153*49c89c76SBlaise Bourdin         PetscCallExternal(ex_put_set_param, exo->exoid, EX_NODE_SET, vsIdx[vs], vsSize, 0);
1154*49c89c76SBlaise Bourdin         PetscCallExternal(ex_put_set, exo->exoid, EX_NODE_SET, vsIdx[vs], nodeList, NULL);
1155*49c89c76SBlaise Bourdin         PetscCall(ISRestoreIndices(stratumIS, &vertices));
1156*49c89c76SBlaise Bourdin         PetscCall(ISDestroy(&stratumIS));
1157*49c89c76SBlaise Bourdin         PetscCall(PetscFree(nodeList));
1158*49c89c76SBlaise Bourdin       }
1159*49c89c76SBlaise Bourdin       PetscCall(ISRestoreIndices(vsIS, &vsIdx));
1160*49c89c76SBlaise Bourdin       PetscCall(ISDestroy(&vsIS));
1161*49c89c76SBlaise Bourdin     }
1162*49c89c76SBlaise Bourdin     /* --- Side Sets/Face Sets --- */
1163*49c89c76SBlaise Bourdin     PetscCall(DMHasLabel(dm, "Face Sets", &hasLabel));
1164*49c89c76SBlaise Bourdin     if (hasLabel) {
1165*49c89c76SBlaise Bourdin       PetscInt        i, j, fs, fsSize;
1166*49c89c76SBlaise Bourdin       const PetscInt *fsIdx, *faces;
1167*49c89c76SBlaise Bourdin       IS              fsIS, stratumIS;
1168*49c89c76SBlaise Bourdin       DMLabel         fsLabel;
1169*49c89c76SBlaise Bourdin       PetscInt        numPoints, *points;
1170*49c89c76SBlaise Bourdin       PetscInt        elem_list_size = 0;
1171*49c89c76SBlaise Bourdin       PetscInt       *elem_list, *elem_ind, *side_list;
1172*49c89c76SBlaise Bourdin 
1173*49c89c76SBlaise Bourdin       PetscCall(DMGetLabel(dm, "Face Sets", &fsLabel));
1174*49c89c76SBlaise Bourdin       /* Compute size of Node List and Element List */
1175*49c89c76SBlaise Bourdin       PetscCall(DMLabelGetValueIS(fsLabel, &fsIS));
1176*49c89c76SBlaise Bourdin       PetscCall(ISGetIndices(fsIS, &fsIdx));
1177*49c89c76SBlaise Bourdin       for (fs = 0; fs < num_fs; ++fs) {
1178*49c89c76SBlaise Bourdin         PetscCall(DMLabelGetStratumIS(fsLabel, fsIdx[fs], &stratumIS));
1179*49c89c76SBlaise Bourdin         PetscCall(ISGetSize(stratumIS, &fsSize));
1180*49c89c76SBlaise Bourdin         elem_list_size += fsSize;
1181*49c89c76SBlaise Bourdin         PetscCall(ISDestroy(&stratumIS));
1182*49c89c76SBlaise Bourdin       }
1183*49c89c76SBlaise Bourdin       if (num_fs) {
1184*49c89c76SBlaise Bourdin         PetscCall(PetscMalloc3(num_fs, &elem_ind, elem_list_size, &elem_list, elem_list_size, &side_list));
1185*49c89c76SBlaise Bourdin         elem_ind[0] = 0;
1186*49c89c76SBlaise Bourdin         for (fs = 0; fs < num_fs; ++fs) {
1187*49c89c76SBlaise Bourdin           PetscCall(DMLabelGetStratumIS(fsLabel, fsIdx[fs], &stratumIS));
1188*49c89c76SBlaise Bourdin           PetscCall(ISGetIndices(stratumIS, &faces));
1189*49c89c76SBlaise Bourdin           PetscCall(ISGetSize(stratumIS, &fsSize));
1190*49c89c76SBlaise Bourdin           /* Set Parameters */
1191*49c89c76SBlaise Bourdin           PetscCallExternal(ex_put_set_param, exo->exoid, EX_SIDE_SET, fsIdx[fs], fsSize, 0);
1192*49c89c76SBlaise Bourdin           /* Indices */
1193*49c89c76SBlaise Bourdin           if (fs < num_fs - 1) elem_ind[fs + 1] = elem_ind[fs] + fsSize;
1194*49c89c76SBlaise Bourdin 
1195*49c89c76SBlaise Bourdin           for (i = 0; i < fsSize; ++i) {
1196*49c89c76SBlaise Bourdin             /* Element List */
1197*49c89c76SBlaise Bourdin             points = NULL;
1198*49c89c76SBlaise Bourdin             PetscCall(DMPlexGetTransitiveClosure(dm, faces[i], PETSC_FALSE, &numPoints, &points));
1199*49c89c76SBlaise Bourdin             elem_list[elem_ind[fs] + i] = points[2] + 1;
1200*49c89c76SBlaise Bourdin             PetscCall(DMPlexRestoreTransitiveClosure(dm, faces[i], PETSC_FALSE, &numPoints, &points));
1201*49c89c76SBlaise Bourdin 
1202*49c89c76SBlaise Bourdin             /* Side List */
1203*49c89c76SBlaise Bourdin             points = NULL;
1204*49c89c76SBlaise Bourdin             PetscCall(DMPlexGetTransitiveClosure(dm, elem_list[elem_ind[fs] + i] - 1, PETSC_TRUE, &numPoints, &points));
1205*49c89c76SBlaise Bourdin             for (j = 1; j < numPoints; ++j) {
1206*49c89c76SBlaise Bourdin               if (points[j * 2] == faces[i]) break;
1207*49c89c76SBlaise Bourdin             }
1208*49c89c76SBlaise Bourdin             /* Convert HEX sides */
1209*49c89c76SBlaise Bourdin             if (numPoints == 27) {
1210*49c89c76SBlaise Bourdin               if (j == 1) {
1211*49c89c76SBlaise Bourdin                 j = 5;
1212*49c89c76SBlaise Bourdin               } else if (j == 2) {
1213*49c89c76SBlaise Bourdin                 j = 6;
1214*49c89c76SBlaise Bourdin               } else if (j == 3) {
1215*49c89c76SBlaise Bourdin                 j = 1;
1216*49c89c76SBlaise Bourdin               } else if (j == 4) {
1217*49c89c76SBlaise Bourdin                 j = 3;
1218*49c89c76SBlaise Bourdin               } else if (j == 5) {
1219*49c89c76SBlaise Bourdin                 j = 2;
1220*49c89c76SBlaise Bourdin               } else if (j == 6) {
1221*49c89c76SBlaise Bourdin                 j = 4;
1222*49c89c76SBlaise Bourdin               }
1223*49c89c76SBlaise Bourdin             }
1224*49c89c76SBlaise Bourdin             /* Convert TET sides */
1225*49c89c76SBlaise Bourdin             if (numPoints == 15) {
1226*49c89c76SBlaise Bourdin               --j;
1227*49c89c76SBlaise Bourdin               if (j == 0) j = 4;
1228*49c89c76SBlaise Bourdin             }
1229*49c89c76SBlaise Bourdin             side_list[elem_ind[fs] + i] = j;
1230*49c89c76SBlaise Bourdin             PetscCall(DMPlexRestoreTransitiveClosure(dm, elem_list[elem_ind[fs] + i] - 1, PETSC_TRUE, &numPoints, &points));
1231*49c89c76SBlaise Bourdin           }
1232*49c89c76SBlaise Bourdin           PetscCall(ISRestoreIndices(stratumIS, &faces));
1233*49c89c76SBlaise Bourdin           PetscCall(ISDestroy(&stratumIS));
1234*49c89c76SBlaise Bourdin         }
1235*49c89c76SBlaise Bourdin         PetscCall(ISRestoreIndices(fsIS, &fsIdx));
1236*49c89c76SBlaise Bourdin         PetscCall(ISDestroy(&fsIS));
1237*49c89c76SBlaise Bourdin 
1238*49c89c76SBlaise Bourdin         /* Put side sets */
1239*49c89c76SBlaise 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]]);
1240*49c89c76SBlaise Bourdin         PetscCall(PetscFree3(elem_ind, elem_list, side_list));
1241*49c89c76SBlaise Bourdin       }
1242*49c89c76SBlaise Bourdin     }
1243*49c89c76SBlaise Bourdin     /*
1244*49c89c76SBlaise Bourdin       close the exodus file
1245*49c89c76SBlaise Bourdin     */
1246*49c89c76SBlaise Bourdin     ex_close(exo->exoid);
1247*49c89c76SBlaise Bourdin     exo->exoid = -1;
1248*49c89c76SBlaise Bourdin   }
1249*49c89c76SBlaise Bourdin   PetscCall(PetscSectionDestroy(&coordSection));
1250*49c89c76SBlaise Bourdin 
1251*49c89c76SBlaise Bourdin   /*
1252*49c89c76SBlaise Bourdin     reopen the file in parallel
1253*49c89c76SBlaise Bourdin   */
1254*49c89c76SBlaise Bourdin   EXO_mode = EX_WRITE;
1255*49c89c76SBlaise Bourdin #if defined(PETSC_USE_64BIT_INDICES)
1256*49c89c76SBlaise Bourdin   EXO_mode += EX_ALL_INT64_API;
1257*49c89c76SBlaise Bourdin #endif
1258*49c89c76SBlaise Bourdin   CPU_word_size = sizeof(PetscReal);
1259*49c89c76SBlaise Bourdin   IO_word_size  = sizeof(PetscReal);
1260*49c89c76SBlaise Bourdin   exo->exoid    = ex_open_par(exo->filename, EXO_mode, &CPU_word_size, &IO_word_size, &EXO_version, comm, MPI_INFO_NULL);
1261*49c89c76SBlaise Bourdin   PetscCheck(exo->exoid >= 0, PETSC_COMM_SELF, PETSC_ERR_LIB, "ex_open_par failed for %s", exo->filename);
1262*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
1263*49c89c76SBlaise Bourdin }
1264*49c89c76SBlaise Bourdin 
1265*49c89c76SBlaise Bourdin static PetscErrorCode VecViewPlex_ExodusII_Nodal_Internal(Vec v, int exoid, int step, int offset);
1266*49c89c76SBlaise Bourdin static PetscErrorCode VecViewPlex_ExodusII_Zonal_Internal(Vec v, int exoid, int step, int offset);
1267*49c89c76SBlaise Bourdin static PetscErrorCode VecLoadPlex_ExodusII_Nodal_Internal(Vec v, int exoid, int step, int offset);
1268*49c89c76SBlaise Bourdin static PetscErrorCode VecLoadPlex_ExodusII_Zonal_Internal(Vec v, int exoid, int step, int offset);
1269*49c89c76SBlaise Bourdin 
1270*49c89c76SBlaise Bourdin PetscErrorCode VecView_PlexExodusII_Internal(Vec v, PetscViewer viewer)
1271*49c89c76SBlaise Bourdin {
1272*49c89c76SBlaise Bourdin   DM          dm;
1273*49c89c76SBlaise Bourdin   MPI_Comm    comm;
1274*49c89c76SBlaise Bourdin   PetscMPIInt rank;
1275*49c89c76SBlaise Bourdin 
1276*49c89c76SBlaise Bourdin   int         exoid, offsetN = -1, offsetZ = -1;
1277*49c89c76SBlaise Bourdin   const char *vecname;
1278*49c89c76SBlaise Bourdin   PetscInt    step;
1279*49c89c76SBlaise Bourdin 
1280*49c89c76SBlaise Bourdin   PetscFunctionBegin;
1281*49c89c76SBlaise Bourdin   PetscCall(PetscObjectGetComm((PetscObject)v, &comm));
1282*49c89c76SBlaise Bourdin   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1283*49c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetId(viewer, &exoid));
1284*49c89c76SBlaise Bourdin   PetscCall(VecGetDM(v, &dm));
1285*49c89c76SBlaise Bourdin   PetscCall(PetscObjectGetName((PetscObject)v, &vecname));
1286*49c89c76SBlaise Bourdin 
1287*49c89c76SBlaise Bourdin   PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL));
1288*49c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetNodalVariableIndex(viewer, vecname, &offsetN));
1289*49c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetZonalVariableIndex(viewer, vecname, &offsetZ));
1290*49c89c76SBlaise Bourdin   PetscCheck(!(offsetN >= 0 && offsetZ >= 0), comm, PETSC_ERR_FILE_UNEXPECTED, "Found both nodal and zonal variable %s in exodus file. ", vecname);
1291*49c89c76SBlaise Bourdin   if (offsetN >= 0) {
1292*49c89c76SBlaise Bourdin     PetscCall(VecViewPlex_ExodusII_Nodal_Internal(v, exoid, (int)step + 1, offsetN + 1));
1293*49c89c76SBlaise Bourdin   } else if (offsetZ >= 0) {
1294*49c89c76SBlaise Bourdin     PetscCall(VecViewPlex_ExodusII_Zonal_Internal(v, exoid, (int)step + 1, offsetZ + 1));
1295*49c89c76SBlaise Bourdin   } else SETERRQ(comm, PETSC_ERR_FILE_UNEXPECTED, "Could not find nodal or zonal variable %s in exodus file. ", vecname);
1296*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
1297*49c89c76SBlaise Bourdin }
1298*49c89c76SBlaise Bourdin 
1299*49c89c76SBlaise Bourdin PetscErrorCode VecLoad_PlexExodusII_Internal(Vec v, PetscViewer viewer)
1300*49c89c76SBlaise Bourdin {
1301*49c89c76SBlaise Bourdin   DM          dm;
1302*49c89c76SBlaise Bourdin   MPI_Comm    comm;
1303*49c89c76SBlaise Bourdin   PetscMPIInt rank;
1304*49c89c76SBlaise Bourdin 
1305*49c89c76SBlaise Bourdin   int         exoid, offsetN = 0, offsetZ = 0;
1306*49c89c76SBlaise Bourdin   const char *vecname;
1307*49c89c76SBlaise Bourdin   PetscInt    step;
1308*49c89c76SBlaise Bourdin 
1309*49c89c76SBlaise Bourdin   PetscFunctionBegin;
1310*49c89c76SBlaise Bourdin   PetscCall(PetscObjectGetComm((PetscObject)v, &comm));
1311*49c89c76SBlaise Bourdin   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1312*49c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetId(viewer, &exoid));
1313*49c89c76SBlaise Bourdin   PetscCall(VecGetDM(v, &dm));
1314*49c89c76SBlaise Bourdin   PetscCall(PetscObjectGetName((PetscObject)v, &vecname));
1315*49c89c76SBlaise Bourdin 
1316*49c89c76SBlaise Bourdin   PetscCall(DMGetOutputSequenceNumber(dm, &step, NULL));
1317*49c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetNodalVariableIndex(viewer, vecname, &offsetN));
1318*49c89c76SBlaise Bourdin   PetscCall(PetscViewerExodusIIGetZonalVariableIndex(viewer, vecname, &offsetZ));
1319*49c89c76SBlaise Bourdin   PetscCheck(!(offsetN >= 0 && offsetZ >= 0), comm, PETSC_ERR_FILE_UNEXPECTED, "Found both nodal and zonal variable %s in exodus file. ", vecname);
1320*49c89c76SBlaise Bourdin   if (offsetN >= 0) PetscCall(VecLoadPlex_ExodusII_Nodal_Internal(v, exoid, (int)step + 1, offsetN + 1));
1321*49c89c76SBlaise Bourdin   else if (offsetZ >= 0) PetscCall(VecLoadPlex_ExodusII_Zonal_Internal(v, exoid, (int)step + 1, offsetZ + 1));
1322*49c89c76SBlaise Bourdin   else SETERRQ(comm, PETSC_ERR_FILE_UNEXPECTED, "Could not find nodal or zonal variable %s in exodus file. ", vecname);
1323*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
1324*49c89c76SBlaise Bourdin }
1325*49c89c76SBlaise Bourdin 
1326*49c89c76SBlaise Bourdin static PetscErrorCode VecViewPlex_ExodusII_Nodal_Internal(Vec v, int exoid, int step, int offset)
1327*49c89c76SBlaise Bourdin {
1328*49c89c76SBlaise Bourdin   MPI_Comm           comm;
1329*49c89c76SBlaise Bourdin   PetscMPIInt        size;
1330*49c89c76SBlaise Bourdin   DM                 dm;
1331*49c89c76SBlaise Bourdin   Vec                vNatural, vComp;
1332*49c89c76SBlaise Bourdin   const PetscScalar *varray;
1333*49c89c76SBlaise Bourdin   PetscInt           xs, xe, bs;
1334*49c89c76SBlaise Bourdin   PetscBool          useNatural;
1335*49c89c76SBlaise Bourdin 
1336*49c89c76SBlaise Bourdin   PetscFunctionBegin;
1337*49c89c76SBlaise Bourdin   PetscCall(PetscObjectGetComm((PetscObject)v, &comm));
1338*49c89c76SBlaise Bourdin   PetscCallMPI(MPI_Comm_size(comm, &size));
1339*49c89c76SBlaise Bourdin   PetscCall(VecGetDM(v, &dm));
1340*49c89c76SBlaise Bourdin   PetscCall(DMGetUseNatural(dm, &useNatural));
1341*49c89c76SBlaise Bourdin   useNatural = useNatural && size > 1 ? PETSC_TRUE : PETSC_FALSE;
1342*49c89c76SBlaise Bourdin   if (useNatural) {
1343*49c89c76SBlaise Bourdin     PetscCall(DMPlexCreateNaturalVector(dm, &vNatural));
1344*49c89c76SBlaise Bourdin     PetscCall(DMPlexGlobalToNaturalBegin(dm, v, vNatural));
1345*49c89c76SBlaise Bourdin     PetscCall(DMPlexGlobalToNaturalEnd(dm, v, vNatural));
1346*49c89c76SBlaise Bourdin   } else {
1347*49c89c76SBlaise Bourdin     vNatural = v;
1348*49c89c76SBlaise Bourdin   }
1349*49c89c76SBlaise Bourdin 
1350*49c89c76SBlaise Bourdin   /* Write local chunk of the result in the exodus file
1351*49c89c76SBlaise Bourdin      exodus stores each component of a vector-valued field as a separate variable.
1352*49c89c76SBlaise Bourdin      We assume that they are stored sequentially */
1353*49c89c76SBlaise Bourdin   PetscCall(VecGetOwnershipRange(vNatural, &xs, &xe));
1354*49c89c76SBlaise Bourdin   PetscCall(VecGetBlockSize(vNatural, &bs));
1355*49c89c76SBlaise Bourdin   if (bs == 1) {
1356*49c89c76SBlaise Bourdin     PetscCall(VecGetArrayRead(vNatural, &varray));
1357*49c89c76SBlaise Bourdin     PetscCallExternal(ex_put_partial_var, exoid, step, EX_NODAL, offset, 1, xs + 1, xe - xs, varray);
1358*49c89c76SBlaise Bourdin     PetscCall(VecRestoreArrayRead(vNatural, &varray));
1359*49c89c76SBlaise Bourdin   } else {
1360*49c89c76SBlaise Bourdin     IS       compIS;
1361*49c89c76SBlaise Bourdin     PetscInt c;
1362*49c89c76SBlaise Bourdin 
1363*49c89c76SBlaise Bourdin     PetscCall(ISCreateStride(comm, (xe - xs) / bs, xs, bs, &compIS));
1364*49c89c76SBlaise Bourdin     for (c = 0; c < bs; ++c) {
1365*49c89c76SBlaise Bourdin       PetscCall(ISStrideSetStride(compIS, (xe - xs) / bs, xs + c, bs));
1366*49c89c76SBlaise Bourdin       PetscCall(VecGetSubVector(vNatural, compIS, &vComp));
1367*49c89c76SBlaise Bourdin       PetscCall(VecGetArrayRead(vComp, &varray));
1368*49c89c76SBlaise Bourdin       PetscCallExternal(ex_put_partial_var, exoid, step, EX_NODAL, offset + c, 1, xs / bs + 1, (xe - xs) / bs, varray);
1369*49c89c76SBlaise Bourdin       PetscCall(VecRestoreArrayRead(vComp, &varray));
1370*49c89c76SBlaise Bourdin       PetscCall(VecRestoreSubVector(vNatural, compIS, &vComp));
1371*49c89c76SBlaise Bourdin     }
1372*49c89c76SBlaise Bourdin     PetscCall(ISDestroy(&compIS));
1373*49c89c76SBlaise Bourdin   }
1374*49c89c76SBlaise Bourdin   if (useNatural) PetscCall(VecDestroy(&vNatural));
1375*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
1376*49c89c76SBlaise Bourdin }
1377*49c89c76SBlaise Bourdin 
1378*49c89c76SBlaise Bourdin static PetscErrorCode VecLoadPlex_ExodusII_Nodal_Internal(Vec v, int exoid, int step, int offset)
1379*49c89c76SBlaise Bourdin {
1380*49c89c76SBlaise Bourdin   MPI_Comm     comm;
1381*49c89c76SBlaise Bourdin   PetscMPIInt  size;
1382*49c89c76SBlaise Bourdin   DM           dm;
1383*49c89c76SBlaise Bourdin   Vec          vNatural, vComp;
1384*49c89c76SBlaise Bourdin   PetscScalar *varray;
1385*49c89c76SBlaise Bourdin   PetscInt     xs, xe, bs;
1386*49c89c76SBlaise Bourdin   PetscBool    useNatural;
1387*49c89c76SBlaise Bourdin 
1388*49c89c76SBlaise Bourdin   PetscFunctionBegin;
1389*49c89c76SBlaise Bourdin   PetscCall(PetscObjectGetComm((PetscObject)v, &comm));
1390*49c89c76SBlaise Bourdin   PetscCallMPI(MPI_Comm_size(comm, &size));
1391*49c89c76SBlaise Bourdin   PetscCall(VecGetDM(v, &dm));
1392*49c89c76SBlaise Bourdin   PetscCall(DMGetUseNatural(dm, &useNatural));
1393*49c89c76SBlaise Bourdin   useNatural = useNatural && size > 1 ? PETSC_TRUE : PETSC_FALSE;
1394*49c89c76SBlaise Bourdin   if (useNatural) PetscCall(DMPlexCreateNaturalVector(dm, &vNatural));
1395*49c89c76SBlaise Bourdin   else vNatural = v;
1396*49c89c76SBlaise Bourdin 
1397*49c89c76SBlaise Bourdin   /* Read local chunk from the file */
1398*49c89c76SBlaise Bourdin   PetscCall(VecGetOwnershipRange(vNatural, &xs, &xe));
1399*49c89c76SBlaise Bourdin   PetscCall(VecGetBlockSize(vNatural, &bs));
1400*49c89c76SBlaise Bourdin   if (bs == 1) {
1401*49c89c76SBlaise Bourdin     PetscCall(VecGetArray(vNatural, &varray));
1402*49c89c76SBlaise Bourdin     PetscCallExternal(ex_get_partial_var, exoid, step, EX_NODAL, offset, 1, xs + 1, xe - xs, varray);
1403*49c89c76SBlaise Bourdin     PetscCall(VecRestoreArray(vNatural, &varray));
1404*49c89c76SBlaise Bourdin   } else {
1405*49c89c76SBlaise Bourdin     IS       compIS;
1406*49c89c76SBlaise Bourdin     PetscInt c;
1407*49c89c76SBlaise Bourdin 
1408*49c89c76SBlaise Bourdin     PetscCall(ISCreateStride(comm, (xe - xs) / bs, xs, bs, &compIS));
1409*49c89c76SBlaise Bourdin     for (c = 0; c < bs; ++c) {
1410*49c89c76SBlaise Bourdin       PetscCall(ISStrideSetStride(compIS, (xe - xs) / bs, xs + c, bs));
1411*49c89c76SBlaise Bourdin       PetscCall(VecGetSubVector(vNatural, compIS, &vComp));
1412*49c89c76SBlaise Bourdin       PetscCall(VecGetArray(vComp, &varray));
1413*49c89c76SBlaise Bourdin       PetscCallExternal(ex_get_partial_var, exoid, step, EX_NODAL, offset + c, 1, xs / bs + 1, (xe - xs) / bs, varray);
1414*49c89c76SBlaise Bourdin       PetscCall(VecRestoreArray(vComp, &varray));
1415*49c89c76SBlaise Bourdin       PetscCall(VecRestoreSubVector(vNatural, compIS, &vComp));
1416*49c89c76SBlaise Bourdin     }
1417*49c89c76SBlaise Bourdin     PetscCall(ISDestroy(&compIS));
1418*49c89c76SBlaise Bourdin   }
1419*49c89c76SBlaise Bourdin   if (useNatural) {
1420*49c89c76SBlaise Bourdin     PetscCall(DMPlexNaturalToGlobalBegin(dm, vNatural, v));
1421*49c89c76SBlaise Bourdin     PetscCall(DMPlexNaturalToGlobalEnd(dm, vNatural, v));
1422*49c89c76SBlaise Bourdin     PetscCall(VecDestroy(&vNatural));
1423*49c89c76SBlaise Bourdin   }
1424*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
1425*49c89c76SBlaise Bourdin }
1426*49c89c76SBlaise Bourdin 
1427*49c89c76SBlaise Bourdin static PetscErrorCode VecViewPlex_ExodusII_Zonal_Internal(Vec v, int exoid, int step, int offset)
1428*49c89c76SBlaise Bourdin {
1429*49c89c76SBlaise Bourdin   MPI_Comm           comm;
1430*49c89c76SBlaise Bourdin   PetscMPIInt        size;
1431*49c89c76SBlaise Bourdin   DM                 dm;
1432*49c89c76SBlaise Bourdin   Vec                vNatural, vComp;
1433*49c89c76SBlaise Bourdin   const PetscScalar *varray;
1434*49c89c76SBlaise Bourdin   PetscInt           xs, xe, bs;
1435*49c89c76SBlaise Bourdin   PetscBool          useNatural;
1436*49c89c76SBlaise Bourdin   IS                 compIS;
1437*49c89c76SBlaise Bourdin   PetscInt          *csSize, *csID;
1438*49c89c76SBlaise Bourdin   PetscInt           numCS, set, csxs = 0;
1439*49c89c76SBlaise Bourdin 
1440*49c89c76SBlaise Bourdin   PetscFunctionBegin;
1441*49c89c76SBlaise Bourdin   PetscCall(PetscObjectGetComm((PetscObject)v, &comm));
1442*49c89c76SBlaise Bourdin   PetscCallMPI(MPI_Comm_size(comm, &size));
1443*49c89c76SBlaise Bourdin   PetscCall(VecGetDM(v, &dm));
1444*49c89c76SBlaise Bourdin   PetscCall(DMGetUseNatural(dm, &useNatural));
1445*49c89c76SBlaise Bourdin   useNatural = useNatural && size > 1 ? PETSC_TRUE : PETSC_FALSE;
1446*49c89c76SBlaise Bourdin   if (useNatural) {
1447*49c89c76SBlaise Bourdin     PetscCall(DMPlexCreateNaturalVector(dm, &vNatural));
1448*49c89c76SBlaise Bourdin     PetscCall(DMPlexGlobalToNaturalBegin(dm, v, vNatural));
1449*49c89c76SBlaise Bourdin     PetscCall(DMPlexGlobalToNaturalEnd(dm, v, vNatural));
1450*49c89c76SBlaise Bourdin   } else {
1451*49c89c76SBlaise Bourdin     vNatural = v;
1452*49c89c76SBlaise Bourdin   }
1453*49c89c76SBlaise Bourdin 
1454*49c89c76SBlaise Bourdin   /* Write local chunk of the result in the exodus file
1455*49c89c76SBlaise Bourdin      exodus stores each component of a vector-valued field as a separate variable.
1456*49c89c76SBlaise Bourdin      We assume that they are stored sequentially
1457*49c89c76SBlaise Bourdin      Zonal variables are accessed one element block at a time, so we loop through the cell sets,
1458*49c89c76SBlaise Bourdin      but once the vector has been reordered to natural size, we cannot use the label information
1459*49c89c76SBlaise Bourdin      to figure out what to save where. */
1460*49c89c76SBlaise Bourdin   numCS = ex_inquire_int(exoid, EX_INQ_ELEM_BLK);
1461*49c89c76SBlaise Bourdin   PetscCall(PetscMalloc2(numCS, &csID, numCS, &csSize));
1462*49c89c76SBlaise Bourdin   PetscCallExternal(ex_get_ids, exoid, EX_ELEM_BLOCK, csID);
1463*49c89c76SBlaise Bourdin   for (set = 0; set < numCS; ++set) {
1464*49c89c76SBlaise Bourdin     ex_block block;
1465*49c89c76SBlaise Bourdin 
1466*49c89c76SBlaise Bourdin     block.id   = csID[set];
1467*49c89c76SBlaise Bourdin     block.type = EX_ELEM_BLOCK;
1468*49c89c76SBlaise Bourdin     PetscCallExternal(ex_get_block_param, exoid, &block);
1469*49c89c76SBlaise Bourdin     csSize[set] = block.num_entry;
1470*49c89c76SBlaise Bourdin   }
1471*49c89c76SBlaise Bourdin   PetscCall(VecGetOwnershipRange(vNatural, &xs, &xe));
1472*49c89c76SBlaise Bourdin   PetscCall(VecGetBlockSize(vNatural, &bs));
1473*49c89c76SBlaise Bourdin   if (bs > 1) PetscCall(ISCreateStride(comm, (xe - xs) / bs, xs, bs, &compIS));
1474*49c89c76SBlaise Bourdin   for (set = 0; set < numCS; set++) {
1475*49c89c76SBlaise Bourdin     PetscInt csLocalSize, c;
1476*49c89c76SBlaise Bourdin 
1477*49c89c76SBlaise Bourdin     /* range of indices for set setID[set]: csxs:csxs + csSize[set]-1
1478*49c89c76SBlaise Bourdin        local slice of zonal values:         xs/bs,xm/bs-1
1479*49c89c76SBlaise Bourdin        intersection:                        max(xs/bs,csxs),min(xm/bs-1,csxs + csSize[set]-1) */
1480*49c89c76SBlaise Bourdin     csLocalSize = PetscMax(0, PetscMin(xe / bs, csxs + csSize[set]) - PetscMax(xs / bs, csxs));
1481*49c89c76SBlaise Bourdin     if (bs == 1) {
1482*49c89c76SBlaise Bourdin       PetscCall(VecGetArrayRead(vNatural, &varray));
1483*49c89c76SBlaise 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)]);
1484*49c89c76SBlaise Bourdin       PetscCall(VecRestoreArrayRead(vNatural, &varray));
1485*49c89c76SBlaise Bourdin     } else {
1486*49c89c76SBlaise Bourdin       for (c = 0; c < bs; ++c) {
1487*49c89c76SBlaise Bourdin         PetscCall(ISStrideSetStride(compIS, (xe - xs) / bs, xs + c, bs));
1488*49c89c76SBlaise Bourdin         PetscCall(VecGetSubVector(vNatural, compIS, &vComp));
1489*49c89c76SBlaise Bourdin         PetscCall(VecGetArrayRead(vComp, &varray));
1490*49c89c76SBlaise 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)]);
1491*49c89c76SBlaise Bourdin         PetscCall(VecRestoreArrayRead(vComp, &varray));
1492*49c89c76SBlaise Bourdin         PetscCall(VecRestoreSubVector(vNatural, compIS, &vComp));
1493*49c89c76SBlaise Bourdin       }
1494*49c89c76SBlaise Bourdin     }
1495*49c89c76SBlaise Bourdin     csxs += csSize[set];
1496*49c89c76SBlaise Bourdin   }
1497*49c89c76SBlaise Bourdin   PetscCall(PetscFree2(csID, csSize));
1498*49c89c76SBlaise Bourdin   if (bs > 1) PetscCall(ISDestroy(&compIS));
1499*49c89c76SBlaise Bourdin   if (useNatural) PetscCall(VecDestroy(&vNatural));
1500*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
1501*49c89c76SBlaise Bourdin }
1502*49c89c76SBlaise Bourdin 
1503*49c89c76SBlaise Bourdin static PetscErrorCode VecLoadPlex_ExodusII_Zonal_Internal(Vec v, int exoid, int step, int offset)
1504*49c89c76SBlaise Bourdin {
1505*49c89c76SBlaise Bourdin   MPI_Comm     comm;
1506*49c89c76SBlaise Bourdin   PetscMPIInt  size;
1507*49c89c76SBlaise Bourdin   DM           dm;
1508*49c89c76SBlaise Bourdin   Vec          vNatural, vComp;
1509*49c89c76SBlaise Bourdin   PetscScalar *varray;
1510*49c89c76SBlaise Bourdin   PetscInt     xs, xe, bs;
1511*49c89c76SBlaise Bourdin   PetscBool    useNatural;
1512*49c89c76SBlaise Bourdin   IS           compIS;
1513*49c89c76SBlaise Bourdin   PetscInt    *csSize, *csID;
1514*49c89c76SBlaise Bourdin   PetscInt     numCS, set, csxs = 0;
1515*49c89c76SBlaise Bourdin 
1516*49c89c76SBlaise Bourdin   PetscFunctionBegin;
1517*49c89c76SBlaise Bourdin   PetscCall(PetscObjectGetComm((PetscObject)v, &comm));
1518*49c89c76SBlaise Bourdin   PetscCallMPI(MPI_Comm_size(comm, &size));
1519*49c89c76SBlaise Bourdin   PetscCall(VecGetDM(v, &dm));
1520*49c89c76SBlaise Bourdin   PetscCall(DMGetUseNatural(dm, &useNatural));
1521*49c89c76SBlaise Bourdin   useNatural = useNatural && size > 1 ? PETSC_TRUE : PETSC_FALSE;
1522*49c89c76SBlaise Bourdin   if (useNatural) PetscCall(DMPlexCreateNaturalVector(dm, &vNatural));
1523*49c89c76SBlaise Bourdin   else vNatural = v;
1524*49c89c76SBlaise Bourdin 
1525*49c89c76SBlaise Bourdin   /* Read local chunk of the result in the exodus file
1526*49c89c76SBlaise Bourdin      exodus stores each component of a vector-valued field as a separate variable.
1527*49c89c76SBlaise Bourdin      We assume that they are stored sequentially
1528*49c89c76SBlaise Bourdin      Zonal variables are accessed one element block at a time, so we loop through the cell sets,
1529*49c89c76SBlaise Bourdin      but once the vector has been reordered to natural size, we cannot use the label information
1530*49c89c76SBlaise Bourdin      to figure out what to save where. */
1531*49c89c76SBlaise Bourdin   numCS = ex_inquire_int(exoid, EX_INQ_ELEM_BLK);
1532*49c89c76SBlaise Bourdin   PetscCall(PetscMalloc2(numCS, &csID, numCS, &csSize));
1533*49c89c76SBlaise Bourdin   PetscCallExternal(ex_get_ids, exoid, EX_ELEM_BLOCK, csID);
1534*49c89c76SBlaise Bourdin   for (set = 0; set < numCS; ++set) {
1535*49c89c76SBlaise Bourdin     ex_block block;
1536*49c89c76SBlaise Bourdin 
1537*49c89c76SBlaise Bourdin     block.id   = csID[set];
1538*49c89c76SBlaise Bourdin     block.type = EX_ELEM_BLOCK;
1539*49c89c76SBlaise Bourdin     PetscCallExternal(ex_get_block_param, exoid, &block);
1540*49c89c76SBlaise Bourdin     csSize[set] = block.num_entry;
1541*49c89c76SBlaise Bourdin   }
1542*49c89c76SBlaise Bourdin   PetscCall(VecGetOwnershipRange(vNatural, &xs, &xe));
1543*49c89c76SBlaise Bourdin   PetscCall(VecGetBlockSize(vNatural, &bs));
1544*49c89c76SBlaise Bourdin   if (bs > 1) PetscCall(ISCreateStride(comm, (xe - xs) / bs, xs, bs, &compIS));
1545*49c89c76SBlaise Bourdin   for (set = 0; set < numCS; ++set) {
1546*49c89c76SBlaise Bourdin     PetscInt csLocalSize, c;
1547*49c89c76SBlaise Bourdin 
1548*49c89c76SBlaise Bourdin     /* range of indices for set setID[set]: csxs:csxs + csSize[set]-1
1549*49c89c76SBlaise Bourdin        local slice of zonal values:         xs/bs,xm/bs-1
1550*49c89c76SBlaise Bourdin        intersection:                        max(xs/bs,csxs),min(xm/bs-1,csxs + csSize[set]-1) */
1551*49c89c76SBlaise Bourdin     csLocalSize = PetscMax(0, PetscMin(xe / bs, csxs + csSize[set]) - PetscMax(xs / bs, csxs));
1552*49c89c76SBlaise Bourdin     if (bs == 1) {
1553*49c89c76SBlaise Bourdin       PetscCall(VecGetArray(vNatural, &varray));
1554*49c89c76SBlaise 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)]);
1555*49c89c76SBlaise Bourdin       PetscCall(VecRestoreArray(vNatural, &varray));
1556*49c89c76SBlaise Bourdin     } else {
1557*49c89c76SBlaise Bourdin       for (c = 0; c < bs; ++c) {
1558*49c89c76SBlaise Bourdin         PetscCall(ISStrideSetStride(compIS, (xe - xs) / bs, xs + c, bs));
1559*49c89c76SBlaise Bourdin         PetscCall(VecGetSubVector(vNatural, compIS, &vComp));
1560*49c89c76SBlaise Bourdin         PetscCall(VecGetArray(vComp, &varray));
1561*49c89c76SBlaise 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)]);
1562*49c89c76SBlaise Bourdin         PetscCall(VecRestoreArray(vComp, &varray));
1563*49c89c76SBlaise Bourdin         PetscCall(VecRestoreSubVector(vNatural, compIS, &vComp));
1564*49c89c76SBlaise Bourdin       }
1565*49c89c76SBlaise Bourdin     }
1566*49c89c76SBlaise Bourdin     csxs += csSize[set];
1567*49c89c76SBlaise Bourdin   }
1568*49c89c76SBlaise Bourdin   PetscCall(PetscFree2(csID, csSize));
1569*49c89c76SBlaise Bourdin   if (bs > 1) PetscCall(ISDestroy(&compIS));
1570*49c89c76SBlaise Bourdin   if (useNatural) {
1571*49c89c76SBlaise Bourdin     PetscCall(DMPlexNaturalToGlobalBegin(dm, vNatural, v));
1572*49c89c76SBlaise Bourdin     PetscCall(DMPlexNaturalToGlobalEnd(dm, vNatural, v));
1573*49c89c76SBlaise Bourdin     PetscCall(VecDestroy(&vNatural));
1574*49c89c76SBlaise Bourdin   }
1575*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
1576*49c89c76SBlaise Bourdin }
1577*49c89c76SBlaise Bourdin 
1578*49c89c76SBlaise Bourdin /*@
1579*49c89c76SBlaise Bourdin   PetscViewerExodusIIGetId - Get the file id of the `PETSCVIEWEREXODUSII` file
1580*49c89c76SBlaise Bourdin 
1581*49c89c76SBlaise Bourdin   Logically Collective
1582*49c89c76SBlaise Bourdin 
1583*49c89c76SBlaise Bourdin   Input Parameter:
1584*49c89c76SBlaise Bourdin . viewer - the `PetscViewer`
1585*49c89c76SBlaise Bourdin 
1586*49c89c76SBlaise Bourdin   Output Parameter:
1587*49c89c76SBlaise Bourdin . exoid - The ExodusII file id
1588*49c89c76SBlaise Bourdin 
1589*49c89c76SBlaise Bourdin   Level: intermediate
1590*49c89c76SBlaise Bourdin 
1591*49c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerFileSetMode()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerBinaryOpen()`
1592*49c89c76SBlaise Bourdin @*/
1593*49c89c76SBlaise Bourdin PetscErrorCode PetscViewerExodusIIGetId(PetscViewer viewer, int *exoid)
1594*49c89c76SBlaise Bourdin {
1595*49c89c76SBlaise Bourdin   PetscFunctionBegin;
1596*49c89c76SBlaise Bourdin   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
1597*49c89c76SBlaise Bourdin   PetscTryMethod(viewer, "PetscViewerGetId_C", (PetscViewer, int *), (viewer, exoid));
1598*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
1599*49c89c76SBlaise Bourdin }
1600*49c89c76SBlaise Bourdin 
1601*49c89c76SBlaise Bourdin /*@
1602*49c89c76SBlaise Bourdin   PetscViewerExodusIISetOrder - Set the elements order in the exodusII file.
1603*49c89c76SBlaise Bourdin 
1604*49c89c76SBlaise Bourdin   Collective
1605*49c89c76SBlaise Bourdin 
1606*49c89c76SBlaise Bourdin   Input Parameters:
1607*49c89c76SBlaise Bourdin + viewer - the `PETSCVIEWEREXODUSII` viewer
1608*49c89c76SBlaise Bourdin - order  - elements order
1609*49c89c76SBlaise Bourdin 
1610*49c89c76SBlaise Bourdin   Output Parameter:
1611*49c89c76SBlaise Bourdin 
1612*49c89c76SBlaise Bourdin   Level: beginner
1613*49c89c76SBlaise Bourdin 
1614*49c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerExodusIIGetId()`, `PetscViewerExodusIIGetOrder()`
1615*49c89c76SBlaise Bourdin @*/
1616*49c89c76SBlaise Bourdin PetscErrorCode PetscViewerExodusIISetOrder(PetscViewer viewer, int order)
1617*49c89c76SBlaise Bourdin {
1618*49c89c76SBlaise Bourdin   PetscFunctionBegin;
1619*49c89c76SBlaise Bourdin   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
1620*49c89c76SBlaise Bourdin   PetscTryMethod(viewer, "PetscViewerSetOrder_C", (PetscViewer, int), (viewer, order));
1621*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
1622*49c89c76SBlaise Bourdin }
1623*49c89c76SBlaise Bourdin 
1624*49c89c76SBlaise Bourdin /*@
1625*49c89c76SBlaise Bourdin   PetscViewerExodusIIGetOrder - Get the elements order in the exodusII file.
1626*49c89c76SBlaise Bourdin 
1627*49c89c76SBlaise Bourdin   Collective
1628*49c89c76SBlaise Bourdin 
1629*49c89c76SBlaise Bourdin   Input Parameters:
1630*49c89c76SBlaise Bourdin + viewer - the `PETSCVIEWEREXODUSII` viewer
1631*49c89c76SBlaise Bourdin - order  - elements order
1632*49c89c76SBlaise Bourdin 
1633*49c89c76SBlaise Bourdin   Output Parameter:
1634*49c89c76SBlaise Bourdin 
1635*49c89c76SBlaise Bourdin   Level: beginner
1636*49c89c76SBlaise Bourdin 
1637*49c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerExodusIIGetId()`, `PetscViewerExodusIISetOrder()`
1638*49c89c76SBlaise Bourdin @*/
1639*49c89c76SBlaise Bourdin PetscErrorCode PetscViewerExodusIIGetOrder(PetscViewer viewer, int *order)
1640*49c89c76SBlaise Bourdin {
1641*49c89c76SBlaise Bourdin   PetscFunctionBegin;
1642*49c89c76SBlaise Bourdin   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
1643*49c89c76SBlaise Bourdin   PetscTryMethod(viewer, "PetscViewerGetOrder_C", (PetscViewer, int *), (viewer, order));
1644*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
1645*49c89c76SBlaise Bourdin }
1646*49c89c76SBlaise Bourdin 
1647*49c89c76SBlaise Bourdin /*@
1648*49c89c76SBlaise Bourdin   PetscViewerExodusIIOpen - Opens a file for ExodusII input/output.
1649*49c89c76SBlaise Bourdin 
1650*49c89c76SBlaise Bourdin   Collective
1651*49c89c76SBlaise Bourdin 
1652*49c89c76SBlaise Bourdin   Input Parameters:
1653*49c89c76SBlaise Bourdin + comm - MPI communicator
1654*49c89c76SBlaise Bourdin . name - name of file
1655*49c89c76SBlaise Bourdin - mode - access mode
1656*49c89c76SBlaise Bourdin .vb
1657*49c89c76SBlaise Bourdin     FILE_MODE_WRITE - create new file for binary output
1658*49c89c76SBlaise Bourdin     FILE_MODE_READ - open existing file for binary input
1659*49c89c76SBlaise Bourdin     FILE_MODE_APPEND - open existing file for binary output
1660*49c89c76SBlaise Bourdin .ve
1661*49c89c76SBlaise Bourdin 
1662*49c89c76SBlaise Bourdin   Output Parameter:
1663*49c89c76SBlaise Bourdin . exo - `PETSCVIEWEREXODUSII` `PetscViewer` for Exodus II input/output to use with the specified file
1664*49c89c76SBlaise Bourdin 
1665*49c89c76SBlaise Bourdin   Level: beginner
1666*49c89c76SBlaise Bourdin 
1667*49c89c76SBlaise Bourdin .seealso: `PETSCVIEWEREXODUSII`, `PetscViewer`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`,
1668*49c89c76SBlaise Bourdin           `DMLoad()`, `PetscFileMode`, `PetscViewerSetType()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()`
1669*49c89c76SBlaise Bourdin @*/
1670*49c89c76SBlaise Bourdin PetscErrorCode PetscViewerExodusIIOpen(MPI_Comm comm, const char name[], PetscFileMode mode, PetscViewer *exo)
1671*49c89c76SBlaise Bourdin {
1672*49c89c76SBlaise Bourdin   PetscFunctionBegin;
1673*49c89c76SBlaise Bourdin   PetscCall(PetscViewerCreate(comm, exo));
1674*49c89c76SBlaise Bourdin   PetscCall(PetscViewerSetType(*exo, PETSCVIEWEREXODUSII));
1675*49c89c76SBlaise Bourdin   PetscCall(PetscViewerFileSetMode(*exo, mode));
1676*49c89c76SBlaise Bourdin   PetscCall(PetscViewerFileSetName(*exo, name));
1677*49c89c76SBlaise Bourdin   PetscCall(PetscViewerSetFromOptions(*exo));
1678*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
1679*49c89c76SBlaise Bourdin }
1680*49c89c76SBlaise Bourdin 
1681*49c89c76SBlaise Bourdin static PetscErrorCode ExodusGetCellType_Internal(const char *elem_type, DMPolytopeType *ct)
1682*49c89c76SBlaise Bourdin {
1683*49c89c76SBlaise Bourdin   PetscBool flg;
1684*49c89c76SBlaise Bourdin 
1685*49c89c76SBlaise Bourdin   PetscFunctionBegin;
1686*49c89c76SBlaise Bourdin   *ct = DM_POLYTOPE_UNKNOWN;
1687*49c89c76SBlaise Bourdin   PetscCall(PetscStrcmp(elem_type, "BAR2", &flg));
1688*49c89c76SBlaise Bourdin   if (flg) {
1689*49c89c76SBlaise Bourdin     *ct = DM_POLYTOPE_SEGMENT;
1690*49c89c76SBlaise Bourdin     goto done;
1691*49c89c76SBlaise Bourdin   }
1692*49c89c76SBlaise Bourdin   PetscCall(PetscStrcmp(elem_type, "BAR3", &flg));
1693*49c89c76SBlaise Bourdin   if (flg) {
1694*49c89c76SBlaise Bourdin     *ct = DM_POLYTOPE_SEGMENT;
1695*49c89c76SBlaise Bourdin     goto done;
1696*49c89c76SBlaise Bourdin   }
1697*49c89c76SBlaise Bourdin   PetscCall(PetscStrcmp(elem_type, "TRI", &flg));
1698*49c89c76SBlaise Bourdin   if (flg) {
1699*49c89c76SBlaise Bourdin     *ct = DM_POLYTOPE_TRIANGLE;
1700*49c89c76SBlaise Bourdin     goto done;
1701*49c89c76SBlaise Bourdin   }
1702*49c89c76SBlaise Bourdin   PetscCall(PetscStrcmp(elem_type, "TRI3", &flg));
1703*49c89c76SBlaise Bourdin   if (flg) {
1704*49c89c76SBlaise Bourdin     *ct = DM_POLYTOPE_TRIANGLE;
1705*49c89c76SBlaise Bourdin     goto done;
1706*49c89c76SBlaise Bourdin   }
1707*49c89c76SBlaise Bourdin   PetscCall(PetscStrcmp(elem_type, "QUAD", &flg));
1708*49c89c76SBlaise Bourdin   if (flg) {
1709*49c89c76SBlaise Bourdin     *ct = DM_POLYTOPE_QUADRILATERAL;
1710*49c89c76SBlaise Bourdin     goto done;
1711*49c89c76SBlaise Bourdin   }
1712*49c89c76SBlaise Bourdin   PetscCall(PetscStrcmp(elem_type, "QUAD4", &flg));
1713*49c89c76SBlaise Bourdin   if (flg) {
1714*49c89c76SBlaise Bourdin     *ct = DM_POLYTOPE_QUADRILATERAL;
1715*49c89c76SBlaise Bourdin     goto done;
1716*49c89c76SBlaise Bourdin   }
1717*49c89c76SBlaise Bourdin   PetscCall(PetscStrcmp(elem_type, "SHELL4", &flg));
1718*49c89c76SBlaise Bourdin   if (flg) {
1719*49c89c76SBlaise Bourdin     *ct = DM_POLYTOPE_QUADRILATERAL;
1720*49c89c76SBlaise Bourdin     goto done;
1721*49c89c76SBlaise Bourdin   }
1722*49c89c76SBlaise Bourdin   PetscCall(PetscStrcmp(elem_type, "TETRA", &flg));
1723*49c89c76SBlaise Bourdin   if (flg) {
1724*49c89c76SBlaise Bourdin     *ct = DM_POLYTOPE_TETRAHEDRON;
1725*49c89c76SBlaise Bourdin     goto done;
1726*49c89c76SBlaise Bourdin   }
1727*49c89c76SBlaise Bourdin   PetscCall(PetscStrcmp(elem_type, "TET4", &flg));
1728*49c89c76SBlaise Bourdin   if (flg) {
1729*49c89c76SBlaise Bourdin     *ct = DM_POLYTOPE_TETRAHEDRON;
1730*49c89c76SBlaise Bourdin     goto done;
1731*49c89c76SBlaise Bourdin   }
1732*49c89c76SBlaise Bourdin   PetscCall(PetscStrcmp(elem_type, "WEDGE", &flg));
1733*49c89c76SBlaise Bourdin   if (flg) {
1734*49c89c76SBlaise Bourdin     *ct = DM_POLYTOPE_TRI_PRISM;
1735*49c89c76SBlaise Bourdin     goto done;
1736*49c89c76SBlaise Bourdin   }
1737*49c89c76SBlaise Bourdin   PetscCall(PetscStrcmp(elem_type, "HEX", &flg));
1738*49c89c76SBlaise Bourdin   if (flg) {
1739*49c89c76SBlaise Bourdin     *ct = DM_POLYTOPE_HEXAHEDRON;
1740*49c89c76SBlaise Bourdin     goto done;
1741*49c89c76SBlaise Bourdin   }
1742*49c89c76SBlaise Bourdin   PetscCall(PetscStrcmp(elem_type, "HEX8", &flg));
1743*49c89c76SBlaise Bourdin   if (flg) {
1744*49c89c76SBlaise Bourdin     *ct = DM_POLYTOPE_HEXAHEDRON;
1745*49c89c76SBlaise Bourdin     goto done;
1746*49c89c76SBlaise Bourdin   }
1747*49c89c76SBlaise Bourdin   PetscCall(PetscStrcmp(elem_type, "HEXAHEDRON", &flg));
1748*49c89c76SBlaise Bourdin   if (flg) {
1749*49c89c76SBlaise Bourdin     *ct = DM_POLYTOPE_HEXAHEDRON;
1750*49c89c76SBlaise Bourdin     goto done;
1751*49c89c76SBlaise Bourdin   }
1752*49c89c76SBlaise Bourdin   SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Unrecognized element type %s", elem_type);
1753*49c89c76SBlaise Bourdin done:
1754*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
1755*49c89c76SBlaise Bourdin }
1756*49c89c76SBlaise Bourdin 
1757*49c89c76SBlaise Bourdin /*@
1758*49c89c76SBlaise Bourdin   DMPlexCreateExodus - Create a `DMPLEX` mesh from an ExodusII file ID.
1759*49c89c76SBlaise Bourdin 
1760*49c89c76SBlaise Bourdin   Collective
1761*49c89c76SBlaise Bourdin 
1762*49c89c76SBlaise Bourdin   Input Parameters:
1763*49c89c76SBlaise Bourdin + comm        - The MPI communicator
1764*49c89c76SBlaise Bourdin . exoid       - The ExodusII id associated with a exodus file and obtained using ex_open
1765*49c89c76SBlaise Bourdin - interpolate - Create faces and edges in the mesh
1766*49c89c76SBlaise Bourdin 
1767*49c89c76SBlaise Bourdin   Output Parameter:
1768*49c89c76SBlaise Bourdin . dm - The `DM` object representing the mesh
1769*49c89c76SBlaise Bourdin 
1770*49c89c76SBlaise Bourdin   Level: beginner
1771*49c89c76SBlaise Bourdin 
1772*49c89c76SBlaise Bourdin .seealso: [](ch_unstructured), `DM`, `PETSCVIEWEREXODUSII`, `DMPLEX`, `DMCreate()`
1773*49c89c76SBlaise Bourdin @*/
1774*49c89c76SBlaise Bourdin PetscErrorCode DMPlexCreateExodus(MPI_Comm comm, PetscInt exoid, PetscBool interpolate, DM *dm)
1775*49c89c76SBlaise Bourdin {
1776*49c89c76SBlaise Bourdin   PetscMPIInt  num_proc, rank;
1777*49c89c76SBlaise Bourdin   DMLabel      cellSets = NULL, faceSets = NULL, vertSets = NULL;
1778*49c89c76SBlaise Bourdin   PetscSection coordSection;
1779*49c89c76SBlaise Bourdin   Vec          coordinates;
1780*49c89c76SBlaise Bourdin   PetscScalar *coords;
1781*49c89c76SBlaise Bourdin   PetscInt     coordSize, v;
1782*49c89c76SBlaise Bourdin   /* Read from ex_get_init() */
1783*49c89c76SBlaise Bourdin   char title[PETSC_MAX_PATH_LEN + 1];
1784*49c89c76SBlaise Bourdin   int  dim = 0, dimEmbed = 0, numVertices = 0, numCells = 0;
1785*49c89c76SBlaise Bourdin   int  num_cs = 0, num_vs = 0, num_fs = 0;
1786*49c89c76SBlaise Bourdin 
1787*49c89c76SBlaise Bourdin   PetscFunctionBegin;
1788*49c89c76SBlaise Bourdin   PetscCallMPI(MPI_Comm_rank(comm, &rank));
1789*49c89c76SBlaise Bourdin   PetscCallMPI(MPI_Comm_size(comm, &num_proc));
1790*49c89c76SBlaise Bourdin   PetscCall(DMCreate(comm, dm));
1791*49c89c76SBlaise Bourdin   PetscCall(DMSetType(*dm, DMPLEX));
1792*49c89c76SBlaise Bourdin   /* Open EXODUS II file and read basic information on rank 0, then broadcast to all processors */
1793*49c89c76SBlaise Bourdin   if (rank == 0) {
1794*49c89c76SBlaise Bourdin     PetscCall(PetscMemzero(title, PETSC_MAX_PATH_LEN + 1));
1795*49c89c76SBlaise Bourdin     PetscCallExternal(ex_get_init, exoid, title, &dimEmbed, &numVertices, &numCells, &num_cs, &num_vs, &num_fs);
1796*49c89c76SBlaise Bourdin     PetscCheck(num_cs, PETSC_COMM_SELF, PETSC_ERR_SUP, "Exodus file does not contain any cell set");
1797*49c89c76SBlaise Bourdin   }
1798*49c89c76SBlaise Bourdin   PetscCallMPI(MPI_Bcast(title, PETSC_MAX_PATH_LEN + 1, MPI_CHAR, 0, comm));
1799*49c89c76SBlaise Bourdin   PetscCallMPI(MPI_Bcast(&dim, 1, MPI_INT, 0, comm));
1800*49c89c76SBlaise Bourdin   PetscCall(PetscObjectSetName((PetscObject)*dm, title));
1801*49c89c76SBlaise Bourdin   PetscCall(DMPlexSetChart(*dm, 0, numCells + numVertices));
1802*49c89c76SBlaise Bourdin   /*   We do not want this label automatically computed, instead we compute it here */
1803*49c89c76SBlaise Bourdin   PetscCall(DMCreateLabel(*dm, "celltype"));
1804*49c89c76SBlaise Bourdin 
1805*49c89c76SBlaise Bourdin   /* Read cell sets information */
1806*49c89c76SBlaise Bourdin   if (rank == 0) {
1807*49c89c76SBlaise Bourdin     PetscInt *cone;
1808*49c89c76SBlaise Bourdin     int       c, cs, ncs, c_loc, v, v_loc;
1809*49c89c76SBlaise Bourdin     /* Read from ex_get_elem_blk_ids() */
1810*49c89c76SBlaise Bourdin     int *cs_id, *cs_order;
1811*49c89c76SBlaise Bourdin     /* Read from ex_get_elem_block() */
1812*49c89c76SBlaise Bourdin     char buffer[PETSC_MAX_PATH_LEN + 1];
1813*49c89c76SBlaise Bourdin     int  num_cell_in_set, num_vertex_per_cell, num_hybrid, num_attr;
1814*49c89c76SBlaise Bourdin     /* Read from ex_get_elem_conn() */
1815*49c89c76SBlaise Bourdin     int *cs_connect;
1816*49c89c76SBlaise Bourdin 
1817*49c89c76SBlaise Bourdin     /* Get cell sets IDs */
1818*49c89c76SBlaise Bourdin     PetscCall(PetscMalloc2(num_cs, &cs_id, num_cs, &cs_order));
1819*49c89c76SBlaise Bourdin     PetscCallExternal(ex_get_ids, exoid, EX_ELEM_BLOCK, cs_id);
1820*49c89c76SBlaise Bourdin     /* Read the cell set connectivity table and build mesh topology
1821*49c89c76SBlaise Bourdin        EXO standard requires that cells in cell sets be numbered sequentially and be pairwise disjoint. */
1822*49c89c76SBlaise Bourdin     /* Check for a hybrid mesh */
1823*49c89c76SBlaise Bourdin     for (cs = 0, num_hybrid = 0; cs < num_cs; ++cs) {
1824*49c89c76SBlaise Bourdin       DMPolytopeType ct;
1825*49c89c76SBlaise Bourdin       char           elem_type[PETSC_MAX_PATH_LEN];
1826*49c89c76SBlaise Bourdin 
1827*49c89c76SBlaise Bourdin       PetscCall(PetscArrayzero(elem_type, sizeof(elem_type)));
1828*49c89c76SBlaise Bourdin       PetscCallExternal(ex_get_elem_type, exoid, cs_id[cs], elem_type);
1829*49c89c76SBlaise Bourdin       PetscCall(ExodusGetCellType_Internal(elem_type, &ct));
1830*49c89c76SBlaise Bourdin       dim = PetscMax(dim, DMPolytopeTypeGetDim(ct));
1831*49c89c76SBlaise 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);
1832*49c89c76SBlaise Bourdin       switch (ct) {
1833*49c89c76SBlaise Bourdin       case DM_POLYTOPE_TRI_PRISM:
1834*49c89c76SBlaise Bourdin         cs_order[cs] = cs;
1835*49c89c76SBlaise Bourdin         ++num_hybrid;
1836*49c89c76SBlaise Bourdin         break;
1837*49c89c76SBlaise Bourdin       default:
1838*49c89c76SBlaise Bourdin         for (c = cs; c > cs - num_hybrid; --c) cs_order[c] = cs_order[c - 1];
1839*49c89c76SBlaise Bourdin         cs_order[cs - num_hybrid] = cs;
1840*49c89c76SBlaise Bourdin       }
1841*49c89c76SBlaise Bourdin     }
1842*49c89c76SBlaise Bourdin     /* First set sizes */
1843*49c89c76SBlaise Bourdin     for (ncs = 0, c = 0; ncs < num_cs; ++ncs) {
1844*49c89c76SBlaise Bourdin       DMPolytopeType ct;
1845*49c89c76SBlaise Bourdin       char           elem_type[PETSC_MAX_PATH_LEN];
1846*49c89c76SBlaise Bourdin       const PetscInt cs = cs_order[ncs];
1847*49c89c76SBlaise Bourdin 
1848*49c89c76SBlaise Bourdin       PetscCall(PetscArrayzero(elem_type, sizeof(elem_type)));
1849*49c89c76SBlaise Bourdin       PetscCallExternal(ex_get_elem_type, exoid, cs_id[cs], elem_type);
1850*49c89c76SBlaise Bourdin       PetscCall(ExodusGetCellType_Internal(elem_type, &ct));
1851*49c89c76SBlaise 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);
1852*49c89c76SBlaise Bourdin       for (c_loc = 0; c_loc < num_cell_in_set; ++c_loc, ++c) {
1853*49c89c76SBlaise Bourdin         PetscCall(DMPlexSetConeSize(*dm, c, num_vertex_per_cell));
1854*49c89c76SBlaise Bourdin         PetscCall(DMPlexSetCellType(*dm, c, ct));
1855*49c89c76SBlaise Bourdin       }
1856*49c89c76SBlaise Bourdin     }
1857*49c89c76SBlaise Bourdin     for (v = numCells; v < numCells + numVertices; ++v) PetscCall(DMPlexSetCellType(*dm, v, DM_POLYTOPE_POINT));
1858*49c89c76SBlaise Bourdin     PetscCall(DMSetUp(*dm));
1859*49c89c76SBlaise Bourdin     for (ncs = 0, c = 0; ncs < num_cs; ++ncs) {
1860*49c89c76SBlaise Bourdin       const PetscInt cs = cs_order[ncs];
1861*49c89c76SBlaise 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);
1862*49c89c76SBlaise Bourdin       PetscCall(PetscMalloc2(num_vertex_per_cell * num_cell_in_set, &cs_connect, num_vertex_per_cell, &cone));
1863*49c89c76SBlaise Bourdin       PetscCallExternal(ex_get_conn, exoid, EX_ELEM_BLOCK, cs_id[cs], cs_connect, NULL, NULL);
1864*49c89c76SBlaise Bourdin       /* EXO uses Fortran-based indexing, DMPlex uses C-style and numbers cell first then vertices. */
1865*49c89c76SBlaise Bourdin       for (c_loc = 0, v = 0; c_loc < num_cell_in_set; ++c_loc, ++c) {
1866*49c89c76SBlaise Bourdin         DMPolytopeType ct;
1867*49c89c76SBlaise Bourdin 
1868*49c89c76SBlaise Bourdin         for (v_loc = 0; v_loc < num_vertex_per_cell; ++v_loc, ++v) cone[v_loc] = cs_connect[v] + numCells - 1;
1869*49c89c76SBlaise Bourdin         PetscCall(DMPlexGetCellType(*dm, c, &ct));
1870*49c89c76SBlaise Bourdin         PetscCall(DMPlexInvertCell(ct, cone));
1871*49c89c76SBlaise Bourdin         PetscCall(DMPlexSetCone(*dm, c, cone));
1872*49c89c76SBlaise Bourdin         PetscCall(DMSetLabelValue_Fast(*dm, &cellSets, "Cell Sets", c, cs_id[cs]));
1873*49c89c76SBlaise Bourdin       }
1874*49c89c76SBlaise Bourdin       PetscCall(PetscFree2(cs_connect, cone));
1875*49c89c76SBlaise Bourdin     }
1876*49c89c76SBlaise Bourdin     PetscCall(PetscFree2(cs_id, cs_order));
1877*49c89c76SBlaise Bourdin   }
1878*49c89c76SBlaise Bourdin   {
1879*49c89c76SBlaise Bourdin     PetscInt ints[] = {dim, dimEmbed};
1880*49c89c76SBlaise Bourdin 
1881*49c89c76SBlaise Bourdin     PetscCallMPI(MPI_Bcast(ints, 2, MPIU_INT, 0, comm));
1882*49c89c76SBlaise Bourdin     PetscCall(DMSetDimension(*dm, ints[0]));
1883*49c89c76SBlaise Bourdin     PetscCall(DMSetCoordinateDim(*dm, ints[1]));
1884*49c89c76SBlaise Bourdin     dim      = ints[0];
1885*49c89c76SBlaise Bourdin     dimEmbed = ints[1];
1886*49c89c76SBlaise Bourdin   }
1887*49c89c76SBlaise Bourdin   PetscCall(DMPlexSymmetrize(*dm));
1888*49c89c76SBlaise Bourdin   PetscCall(DMPlexStratify(*dm));
1889*49c89c76SBlaise Bourdin   if (interpolate) {
1890*49c89c76SBlaise Bourdin     DM idm;
1891*49c89c76SBlaise Bourdin 
1892*49c89c76SBlaise Bourdin     PetscCall(DMPlexInterpolate(*dm, &idm));
1893*49c89c76SBlaise Bourdin     PetscCall(DMDestroy(dm));
1894*49c89c76SBlaise Bourdin     *dm = idm;
1895*49c89c76SBlaise Bourdin   }
1896*49c89c76SBlaise Bourdin 
1897*49c89c76SBlaise Bourdin   /* Create vertex set label */
1898*49c89c76SBlaise Bourdin   if (rank == 0 && (num_vs > 0)) {
1899*49c89c76SBlaise Bourdin     int vs, v;
1900*49c89c76SBlaise Bourdin     /* Read from ex_get_node_set_ids() */
1901*49c89c76SBlaise Bourdin     int *vs_id;
1902*49c89c76SBlaise Bourdin     /* Read from ex_get_node_set_param() */
1903*49c89c76SBlaise Bourdin     int num_vertex_in_set;
1904*49c89c76SBlaise Bourdin     /* Read from ex_get_node_set() */
1905*49c89c76SBlaise Bourdin     int *vs_vertex_list;
1906*49c89c76SBlaise Bourdin 
1907*49c89c76SBlaise Bourdin     /* Get vertex set ids */
1908*49c89c76SBlaise Bourdin     PetscCall(PetscMalloc1(num_vs, &vs_id));
1909*49c89c76SBlaise Bourdin     PetscCallExternal(ex_get_ids, exoid, EX_NODE_SET, vs_id);
1910*49c89c76SBlaise Bourdin     for (vs = 0; vs < num_vs; ++vs) {
1911*49c89c76SBlaise Bourdin       PetscCallExternal(ex_get_set_param, exoid, EX_NODE_SET, vs_id[vs], &num_vertex_in_set, NULL);
1912*49c89c76SBlaise Bourdin       PetscCall(PetscMalloc1(num_vertex_in_set, &vs_vertex_list));
1913*49c89c76SBlaise Bourdin       PetscCallExternal(ex_get_set, exoid, EX_NODE_SET, vs_id[vs], vs_vertex_list, NULL);
1914*49c89c76SBlaise 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]));
1915*49c89c76SBlaise Bourdin       PetscCall(PetscFree(vs_vertex_list));
1916*49c89c76SBlaise Bourdin     }
1917*49c89c76SBlaise Bourdin     PetscCall(PetscFree(vs_id));
1918*49c89c76SBlaise Bourdin   }
1919*49c89c76SBlaise Bourdin   /* Read coordinates */
1920*49c89c76SBlaise Bourdin   PetscCall(DMGetCoordinateSection(*dm, &coordSection));
1921*49c89c76SBlaise Bourdin   PetscCall(PetscSectionSetNumFields(coordSection, 1));
1922*49c89c76SBlaise Bourdin   PetscCall(PetscSectionSetFieldComponents(coordSection, 0, dimEmbed));
1923*49c89c76SBlaise Bourdin   PetscCall(PetscSectionSetChart(coordSection, numCells, numCells + numVertices));
1924*49c89c76SBlaise Bourdin   for (v = numCells; v < numCells + numVertices; ++v) {
1925*49c89c76SBlaise Bourdin     PetscCall(PetscSectionSetDof(coordSection, v, dimEmbed));
1926*49c89c76SBlaise Bourdin     PetscCall(PetscSectionSetFieldDof(coordSection, v, 0, dimEmbed));
1927*49c89c76SBlaise Bourdin   }
1928*49c89c76SBlaise Bourdin   PetscCall(PetscSectionSetUp(coordSection));
1929*49c89c76SBlaise Bourdin   PetscCall(PetscSectionGetStorageSize(coordSection, &coordSize));
1930*49c89c76SBlaise Bourdin   PetscCall(VecCreate(PETSC_COMM_SELF, &coordinates));
1931*49c89c76SBlaise Bourdin   PetscCall(PetscObjectSetName((PetscObject)coordinates, "coordinates"));
1932*49c89c76SBlaise Bourdin   PetscCall(VecSetSizes(coordinates, coordSize, PETSC_DETERMINE));
1933*49c89c76SBlaise Bourdin   PetscCall(VecSetBlockSize(coordinates, dimEmbed));
1934*49c89c76SBlaise Bourdin   PetscCall(VecSetType(coordinates, VECSTANDARD));
1935*49c89c76SBlaise Bourdin   PetscCall(VecGetArray(coordinates, &coords));
1936*49c89c76SBlaise Bourdin   if (rank == 0) {
1937*49c89c76SBlaise Bourdin     PetscReal *x, *y, *z;
1938*49c89c76SBlaise Bourdin 
1939*49c89c76SBlaise Bourdin     PetscCall(PetscMalloc3(numVertices, &x, numVertices, &y, numVertices, &z));
1940*49c89c76SBlaise Bourdin     PetscCallExternal(ex_get_coord, exoid, x, y, z);
1941*49c89c76SBlaise Bourdin     if (dimEmbed > 0) {
1942*49c89c76SBlaise Bourdin       for (v = 0; v < numVertices; ++v) coords[v * dimEmbed + 0] = x[v];
1943*49c89c76SBlaise Bourdin     }
1944*49c89c76SBlaise Bourdin     if (dimEmbed > 1) {
1945*49c89c76SBlaise Bourdin       for (v = 0; v < numVertices; ++v) coords[v * dimEmbed + 1] = y[v];
1946*49c89c76SBlaise Bourdin     }
1947*49c89c76SBlaise Bourdin     if (dimEmbed > 2) {
1948*49c89c76SBlaise Bourdin       for (v = 0; v < numVertices; ++v) coords[v * dimEmbed + 2] = z[v];
1949*49c89c76SBlaise Bourdin     }
1950*49c89c76SBlaise Bourdin     PetscCall(PetscFree3(x, y, z));
1951*49c89c76SBlaise Bourdin   }
1952*49c89c76SBlaise Bourdin   PetscCall(VecRestoreArray(coordinates, &coords));
1953*49c89c76SBlaise Bourdin   PetscCall(DMSetCoordinatesLocal(*dm, coordinates));
1954*49c89c76SBlaise Bourdin   PetscCall(VecDestroy(&coordinates));
1955*49c89c76SBlaise Bourdin 
1956*49c89c76SBlaise Bourdin   /* Create side set label */
1957*49c89c76SBlaise Bourdin   if (rank == 0 && interpolate && (num_fs > 0)) {
1958*49c89c76SBlaise Bourdin     int fs, f, voff;
1959*49c89c76SBlaise Bourdin     /* Read from ex_get_side_set_ids() */
1960*49c89c76SBlaise Bourdin     int *fs_id;
1961*49c89c76SBlaise Bourdin     /* Read from ex_get_side_set_param() */
1962*49c89c76SBlaise Bourdin     int num_side_in_set;
1963*49c89c76SBlaise Bourdin     /* Read from ex_get_side_set_node_list() */
1964*49c89c76SBlaise Bourdin     int *fs_vertex_count_list, *fs_vertex_list, *fs_side_list;
1965*49c89c76SBlaise Bourdin     /* Read side set labels */
1966*49c89c76SBlaise Bourdin     char   fs_name[MAX_STR_LENGTH + 1];
1967*49c89c76SBlaise Bourdin     size_t fs_name_len;
1968*49c89c76SBlaise Bourdin 
1969*49c89c76SBlaise Bourdin     /* Get side set ids */
1970*49c89c76SBlaise Bourdin     PetscCall(PetscMalloc1(num_fs, &fs_id));
1971*49c89c76SBlaise Bourdin     PetscCallExternal(ex_get_ids, exoid, EX_SIDE_SET, fs_id);
1972*49c89c76SBlaise Bourdin     // Ids 1 and 2 are reserved by ExodusII for indicating things in 3D
1973*49c89c76SBlaise Bourdin     for (fs = 0; fs < num_fs; ++fs) {
1974*49c89c76SBlaise Bourdin       PetscCallExternal(ex_get_set_param, exoid, EX_SIDE_SET, fs_id[fs], &num_side_in_set, NULL);
1975*49c89c76SBlaise 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));
1976*49c89c76SBlaise Bourdin       PetscCallExternal(ex_get_side_set_node_list, exoid, fs_id[fs], fs_vertex_count_list, fs_vertex_list);
1977*49c89c76SBlaise Bourdin       PetscCallExternal(ex_get_set, exoid, EX_SIDE_SET, fs_id[fs], NULL, fs_side_list);
1978*49c89c76SBlaise Bourdin 
1979*49c89c76SBlaise Bourdin       /* Get the specific name associated with this side set ID. */
1980*49c89c76SBlaise Bourdin       int fs_name_err = ex_get_name(exoid, EX_SIDE_SET, fs_id[fs], fs_name);
1981*49c89c76SBlaise Bourdin       if (!fs_name_err) {
1982*49c89c76SBlaise Bourdin         PetscCall(PetscStrlen(fs_name, &fs_name_len));
1983*49c89c76SBlaise Bourdin         if (fs_name_len == 0) PetscCall(PetscStrncpy(fs_name, "Face Sets", MAX_STR_LENGTH));
1984*49c89c76SBlaise Bourdin       }
1985*49c89c76SBlaise Bourdin       for (f = 0, voff = 0; f < num_side_in_set; ++f) {
1986*49c89c76SBlaise Bourdin         const PetscInt *faces    = NULL;
1987*49c89c76SBlaise Bourdin         PetscInt        faceSize = fs_vertex_count_list[f], numFaces;
1988*49c89c76SBlaise Bourdin         PetscInt        faceVertices[4], v;
1989*49c89c76SBlaise Bourdin 
1990*49c89c76SBlaise Bourdin         PetscCheck(faceSize <= 4, comm, PETSC_ERR_ARG_WRONG, "ExodusII side cannot have %" PetscInt_FMT " > 4 vertices", faceSize);
1991*49c89c76SBlaise Bourdin         for (v = 0; v < faceSize; ++v, ++voff) faceVertices[v] = fs_vertex_list[voff] + numCells - 1;
1992*49c89c76SBlaise Bourdin         PetscCall(DMPlexGetFullJoin(*dm, faceSize, faceVertices, &numFaces, &faces));
1993*49c89c76SBlaise Bourdin         PetscCheck(numFaces == 1, comm, PETSC_ERR_ARG_WRONG, "Invalid ExodusII side %d in set %d maps to %" PetscInt_FMT " faces", f, fs, numFaces);
1994*49c89c76SBlaise 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]);
1995*49c89c76SBlaise Bourdin         PetscCall(DMSetLabelValue_Fast(*dm, &faceSets, "Face Sets", faces[0], fs_id[fs]));
1996*49c89c76SBlaise Bourdin         /* Only add the label if one has been detected for this side set. */
1997*49c89c76SBlaise Bourdin         if (!fs_name_err) PetscCall(DMSetLabelValue(*dm, fs_name, faces[0], fs_id[fs]));
1998*49c89c76SBlaise Bourdin         PetscCall(DMPlexRestoreJoin(*dm, faceSize, faceVertices, &numFaces, &faces));
1999*49c89c76SBlaise Bourdin       }
2000*49c89c76SBlaise Bourdin       PetscCall(PetscFree3(fs_vertex_count_list, fs_vertex_list, fs_side_list));
2001*49c89c76SBlaise Bourdin     }
2002*49c89c76SBlaise Bourdin     PetscCall(PetscFree(fs_id));
2003*49c89c76SBlaise Bourdin   }
2004*49c89c76SBlaise Bourdin 
2005*49c89c76SBlaise Bourdin   { /* Create Cell/Face/Vertex Sets labels at all processes */
2006*49c89c76SBlaise Bourdin     enum {
2007*49c89c76SBlaise Bourdin       n = 3
2008*49c89c76SBlaise Bourdin     };
2009*49c89c76SBlaise Bourdin     PetscBool flag[n];
2010*49c89c76SBlaise Bourdin 
2011*49c89c76SBlaise Bourdin     flag[0] = cellSets ? PETSC_TRUE : PETSC_FALSE;
2012*49c89c76SBlaise Bourdin     flag[1] = faceSets ? PETSC_TRUE : PETSC_FALSE;
2013*49c89c76SBlaise Bourdin     flag[2] = vertSets ? PETSC_TRUE : PETSC_FALSE;
2014*49c89c76SBlaise Bourdin     PetscCallMPI(MPI_Bcast(flag, n, MPIU_BOOL, 0, comm));
2015*49c89c76SBlaise Bourdin     if (flag[0]) PetscCall(DMCreateLabel(*dm, "Cell Sets"));
2016*49c89c76SBlaise Bourdin     if (flag[1]) PetscCall(DMCreateLabel(*dm, "Face Sets"));
2017*49c89c76SBlaise Bourdin     if (flag[2]) PetscCall(DMCreateLabel(*dm, "Vertex Sets"));
2018*49c89c76SBlaise Bourdin   }
2019*49c89c76SBlaise Bourdin   PetscFunctionReturn(PETSC_SUCCESS);
2020*49c89c76SBlaise Bourdin }
2021