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, °ree)); 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