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