Date: 2025-03-29T05:58:24+00:00

Actual source code: swarmpic_view.c

      1: #include <petscdmda.h>
      2: #include <petsc/private/dmswarmimpl.h>
      3: #include "../src/dm/impls/swarm/data_bucket.h"

      5: static PetscErrorCode private_PetscViewerCreate_XDMF(MPI_Comm comm, const char filename[], PetscViewer *v)
      6: {
      7:   long int      *bytes;
      8:   PetscContainer container;
      9:   PetscViewer    viewer;

     11:   PetscFunctionBegin;
     12:   PetscCall(PetscViewerCreate(comm, &viewer));
     13:   PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII));
     14:   PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_WRITE));
     15:   PetscCall(PetscViewerFileSetName(viewer, filename));

     17:   PetscCall(PetscMalloc1(1, &bytes));
     18:   bytes[0] = 0;
     19:   PetscCall(PetscContainerCreate(comm, &container));
     20:   PetscCall(PetscContainerSetPointer(container, (void *)bytes));
     21:   PetscCall(PetscObjectCompose((PetscObject)viewer, "XDMFViewerContext", (PetscObject)container));

     23:   /* write xdmf header */
     24:   PetscCall(PetscViewerASCIIPrintf(viewer, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"));
     25:   PetscCall(PetscViewerASCIIPrintf(viewer, "<Xdmf xmlns:xi=\"http://www.w3.org/2001/XInclude/\" Version=\"2.99\">\n"));
     26:   /* write xdmf domain */
     27:   PetscCall(PetscViewerASCIIPushTab(viewer));
     28:   PetscCall(PetscViewerASCIIPrintf(viewer, "<Domain>\n"));
     29:   *v = viewer;
     30:   PetscFunctionReturn(PETSC_SUCCESS);
     31: }

     33: static PetscErrorCode private_PetscViewerDestroy_XDMF(PetscViewer *v)
     34: {
     35:   PetscViewer    viewer;
     36:   DM             dm = NULL;
     37:   long int      *bytes;
     38:   PetscContainer container = NULL;

     40:   PetscFunctionBegin;
     41:   if (!v) PetscFunctionReturn(PETSC_SUCCESS);
     42:   viewer = *v;

     44:   PetscCall(PetscObjectQuery((PetscObject)viewer, "DMSwarm", (PetscObject *)&dm));
     45:   if (dm) {
     46:     PetscCall(PetscViewerASCIIPrintf(viewer, "</Grid>\n"));
     47:     PetscCall(PetscViewerASCIIPopTab(viewer));
     48:   }

     50:   /* close xdmf header */
     51:   PetscCall(PetscViewerASCIIPrintf(viewer, "</Domain>\n"));
     52:   PetscCall(PetscViewerASCIIPopTab(viewer));
     53:   PetscCall(PetscViewerASCIIPrintf(viewer, "</Xdmf>\n"));

     55:   PetscCall(PetscObjectQuery((PetscObject)viewer, "XDMFViewerContext", (PetscObject *)&container));
     56:   if (container) {
     57:     PetscCall(PetscContainerGetPointer(container, (void **)&bytes));
     58:     PetscCall(PetscFree(bytes));
     59:     PetscCall(PetscContainerDestroy(&container));
     60:   }
     61:   PetscCall(PetscViewerDestroy(&viewer));
     62:   *v = NULL;
     63:   PetscFunctionReturn(PETSC_SUCCESS);
     64: }

     66: static PetscErrorCode private_CreateDataFileNameXDMF(const char filename[], char dfilename[])
     67: {
     68:   const char dot_xmf[] = ".xmf";
     69:   size_t     len;
     70:   char       viewername_minus_ext[PETSC_MAX_PATH_LEN];
     71:   PetscBool  flg;

     73:   PetscFunctionBegin;
     74:   PetscCall(PetscStrendswith(filename, dot_xmf, &flg));
     75:   PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "File extension must be %s", dot_xmf);
     76:   PetscCall(PetscStrncpy(viewername_minus_ext, filename, sizeof(viewername_minus_ext)));
     77:   PetscCall(PetscStrlen(filename, &len));
     78:   len -= sizeof(dot_xmf) - 1;
     79:   if (sizeof(viewername_minus_ext) > len) viewername_minus_ext[len] = '\0';
     80:   PetscCall(PetscSNPrintf(dfilename, PETSC_MAX_PATH_LEN - 1, "%s_swarm_fields.pbin", viewername_minus_ext));
     81:   PetscFunctionReturn(PETSC_SUCCESS);
     82: }

     84: static PetscErrorCode private_DMSwarmView_XDMF(DM dm, PetscViewer viewer)
     85: {
     86:   DMSwarmCellDM  celldm;
     87:   PetscBool      isswarm = PETSC_FALSE;
     88:   const char    *viewername;
     89:   char           datafile[PETSC_MAX_PATH_LEN];
     90:   char          *datafilename;
     91:   PetscViewer    fviewer;
     92:   PetscInt       k, ng, dim, Nfc;
     93:   Vec            dvec;
     94:   long int      *bytes     = NULL;
     95:   PetscContainer container = NULL;
     96:   const char    *dmname, **coordFields;

     98:   PetscFunctionBegin;
     99:   PetscCall(PetscObjectQuery((PetscObject)viewer, "XDMFViewerContext", (PetscObject *)&container));
    100:   if (container) {
    101:     PetscCall(PetscContainerGetPointer(container, (void **)&bytes));
    102:   } else SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Valid to find attached data XDMFViewerContext");

    104:   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSWARM, &isswarm));
    105:   PetscCheck(isswarm, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Only valid for DMSwarm");

    107:   PetscCall(PetscObjectCompose((PetscObject)viewer, "DMSwarm", (PetscObject)dm));

    109:   PetscCall(PetscViewerASCIIPushTab(viewer));
    110:   PetscCall(PetscObjectGetName((PetscObject)dm, &dmname));
    111:   if (!dmname) PetscCall(DMGetOptionsPrefix(dm, &dmname));
    112:   if (!dmname) {
    113:     PetscCall(PetscViewerASCIIPrintf(viewer, "<Grid Name=\"DMSwarm\" GridType=\"Uniform\">\n"));
    114:   } else {
    115:     PetscCall(PetscViewerASCIIPrintf(viewer, "<Grid Name=\"DMSwarm[%s]\" GridType=\"Uniform\">\n", dmname));
    116:   }

    118:   /* create a sub-viewer for topology, geometry and all data fields */
    119:   /* name is viewer.name + "_swarm_fields.pbin" */
    120:   PetscCall(PetscViewerCreate(PetscObjectComm((PetscObject)viewer), &fviewer));
    121:   PetscCall(PetscViewerSetType(fviewer, PETSCVIEWERBINARY));
    122:   PetscCall(PetscViewerBinarySetSkipHeader(fviewer, PETSC_TRUE));
    123:   PetscCall(PetscViewerBinarySetSkipInfo(fviewer, PETSC_TRUE));
    124:   PetscCall(PetscViewerFileSetMode(fviewer, FILE_MODE_WRITE));

    126:   PetscCall(PetscViewerFileGetName(viewer, &viewername));
    127:   PetscCall(private_CreateDataFileNameXDMF(viewername, datafile));
    128:   PetscCall(PetscViewerFileSetName(fviewer, datafile));
    129:   PetscCall(PetscStrrchr(datafile, '/', &datafilename));

    131:   PetscCall(DMSwarmGetSize(dm, &ng));

    133:   /* write topology header */
    134:   PetscCall(PetscViewerASCIIPushTab(viewer));
    135:   PetscCall(PetscViewerASCIIPrintf(viewer, "<Topology Dimensions=\"%" PetscInt_FMT "\" TopologyType=\"Mixed\">\n", ng));
    136:   PetscCall(PetscViewerASCIIPushTab(viewer));
    137:   PetscCall(PetscViewerASCIIPrintf(viewer, "<DataItem Format=\"Binary\" Endian=\"Big\" DataType=\"Int\" Dimensions=\"%" PetscInt_FMT "\" Seek=\"%ld\">\n", ng * 3, bytes[0]));
    138:   PetscCall(PetscViewerASCIIPushTab(viewer));
    139:   PetscCall(PetscViewerASCIIPrintf(viewer, "%s\n", datafilename));
    140:   PetscCall(PetscViewerASCIIPopTab(viewer));
    141:   PetscCall(PetscViewerASCIIPrintf(viewer, "</DataItem>\n"));
    142:   PetscCall(PetscViewerASCIIPopTab(viewer));
    143:   PetscCall(PetscViewerASCIIPrintf(viewer, "</Topology>\n"));
    144:   PetscCall(PetscViewerASCIIPopTab(viewer));

    146:   /* write topology data */
    147:   for (k = 0; k < ng; k++) {
    148:     PetscInt pvertex[3];

    150:     pvertex[0] = 1;
    151:     pvertex[1] = 1;
    152:     pvertex[2] = k;
    153:     PetscCall(PetscViewerBinaryWrite(fviewer, pvertex, 3, PETSC_INT));
    154:   }
    155:   bytes[0] += sizeof(PetscInt) * ng * 3;

    157:   /* write geometry header */
    158:   PetscCall(PetscViewerASCIIPushTab(viewer));
    159:   PetscCall(DMGetDimension(dm, &dim));
    160:   switch (dim) {
    161:   case 1:
    162:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for 1D");
    163:   case 2:
    164:     PetscCall(PetscViewerASCIIPrintf(viewer, "<Geometry Type=\"XY\">\n"));
    165:     break;
    166:   case 3:
    167:     PetscCall(PetscViewerASCIIPrintf(viewer, "<Geometry Type=\"XYZ\">\n"));
    168:     break;
    169:   }
    170:   PetscCall(PetscViewerASCIIPushTab(viewer));
    171:   PetscCall(PetscViewerASCIIPrintf(viewer, "<DataItem Format=\"Binary\" Endian=\"Big\" DataType=\"Float\" Precision=\"8\" Dimensions=\"%" PetscInt_FMT " %" PetscInt_FMT "\" Seek=\"%ld\">\n", ng, dim, bytes[0]));
    172:   PetscCall(PetscViewerASCIIPushTab(viewer));
    173:   PetscCall(PetscViewerASCIIPrintf(viewer, "%s\n", datafilename));
    174:   PetscCall(PetscViewerASCIIPopTab(viewer));
    175:   PetscCall(PetscViewerASCIIPrintf(viewer, "</DataItem>\n"));
    176:   PetscCall(PetscViewerASCIIPopTab(viewer));
    177:   PetscCall(PetscViewerASCIIPrintf(viewer, "</Geometry>\n"));
    178:   PetscCall(PetscViewerASCIIPopTab(viewer));

    180:   PetscCall(DMSwarmGetCellDMActive(dm, &celldm));
    181:   PetscCall(DMSwarmCellDMGetCoordinateFields(celldm, &Nfc, &coordFields));
    182:   PetscCheck(Nfc == 1, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "We only support a single coordinate field right now, not %" PetscInt_FMT, Nfc);

    184:   /* write geometry data */
    185:   PetscCall(DMSwarmCreateGlobalVectorFromField(dm, coordFields[0], &dvec));
    186:   PetscCall(VecView(dvec, fviewer));
    187:   PetscCall(DMSwarmDestroyGlobalVectorFromField(dm, coordFields[0], &dvec));
    188:   bytes[0] += sizeof(PetscReal) * ng * dim;

    190:   PetscCall(PetscViewerDestroy(&fviewer));
    191:   PetscFunctionReturn(PETSC_SUCCESS);
    192: }

    194: static PetscErrorCode private_VecView_Swarm_XDMF(Vec x, PetscViewer viewer)
    195: {
    196:   long int      *bytes     = NULL;
    197:   PetscContainer container = NULL;
    198:   const char    *viewername;
    199:   char           datafile[PETSC_MAX_PATH_LEN];
    200:   char          *datafilename;
    201:   PetscViewer    fviewer;
    202:   PetscInt       N, bs;
    203:   const char    *vecname;
    204:   char           fieldname[PETSC_MAX_PATH_LEN];

    206:   PetscFunctionBegin;
    207:   PetscCall(PetscObjectQuery((PetscObject)viewer, "XDMFViewerContext", (PetscObject *)&container));
    208:   PetscCheck(container, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unable to find attached data XDMFViewerContext");
    209:   PetscCall(PetscContainerGetPointer(container, (void **)&bytes));
    210:   PetscCall(PetscViewerFileGetName(viewer, &viewername));
    211:   PetscCall(private_CreateDataFileNameXDMF(viewername, datafile));

    213:   /* re-open a sub-viewer for all data fields */
    214:   /* name is viewer.name + "_swarm_fields.pbin" */
    215:   PetscCall(PetscViewerCreate(PetscObjectComm((PetscObject)viewer), &fviewer));
    216:   PetscCall(PetscViewerSetType(fviewer, PETSCVIEWERBINARY));
    217:   PetscCall(PetscViewerBinarySetSkipHeader(fviewer, PETSC_TRUE));
    218:   PetscCall(PetscViewerBinarySetSkipInfo(fviewer, PETSC_TRUE));
    219:   PetscCall(PetscViewerFileSetMode(fviewer, FILE_MODE_APPEND));
    220:   PetscCall(PetscViewerFileSetName(fviewer, datafile));
    221:   PetscCall(PetscStrrchr(datafile, '/', &datafilename));

    223:   PetscCall(VecGetSize(x, &N));
    224:   PetscCall(VecGetBlockSize(x, &bs));
    225:   N = N / bs;
    226:   PetscCall(PetscObjectGetName((PetscObject)x, &vecname));
    227:   if (!vecname) {
    228:     PetscCall(PetscSNPrintf(fieldname, PETSC_MAX_PATH_LEN - 1, "swarmfield_%d", ((PetscObject)x)->tag));
    229:   } else {
    230:     PetscCall(PetscSNPrintf(fieldname, PETSC_MAX_PATH_LEN - 1, "%s", vecname));
    231:   }

    233:   /* write data header */
    234:   PetscCall(PetscViewerASCIIPushTab(viewer));
    235:   PetscCall(PetscViewerASCIIPrintf(viewer, "<Attribute Center=\"Node\" Name=\"%s\" Type=\"None\">\n", fieldname));
    236:   PetscCall(PetscViewerASCIIPushTab(viewer));
    237:   if (bs == 1) {
    238:     PetscCall(PetscViewerASCIIPrintf(viewer, "<DataItem Format=\"Binary\" Endian=\"Big\" DataType=\"Float\" Precision=\"8\" Dimensions=\"%" PetscInt_FMT "\" Seek=\"%ld\">\n", N, bytes[0]));
    239:   } else {
    240:     PetscCall(PetscViewerASCIIPrintf(viewer, "<DataItem Format=\"Binary\" Endian=\"Big\" DataType=\"Float\" Precision=\"8\" Dimensions=\"%" PetscInt_FMT " %" PetscInt_FMT "\" Seek=\"%ld\">\n", N, bs, bytes[0]));
    241:   }
    242:   PetscCall(PetscViewerASCIIPushTab(viewer));
    243:   PetscCall(PetscViewerASCIIPrintf(viewer, "%s\n", datafilename));
    244:   PetscCall(PetscViewerASCIIPopTab(viewer));
    245:   PetscCall(PetscViewerASCIIPrintf(viewer, "</DataItem>\n"));
    246:   PetscCall(PetscViewerASCIIPopTab(viewer));
    247:   PetscCall(PetscViewerASCIIPrintf(viewer, "</Attribute>\n"));
    248:   PetscCall(PetscViewerASCIIPopTab(viewer));

    250:   /* write data */
    251:   PetscCall(VecView(x, fviewer));
    252:   bytes[0] += sizeof(PetscReal) * N * bs;

    254:   PetscCall(PetscViewerDestroy(&fviewer));
    255:   PetscFunctionReturn(PETSC_SUCCESS);
    256: }

    258: static PetscErrorCode private_ISView_Swarm_XDMF(IS is, PetscViewer viewer)
    259: {
    260:   long int      *bytes     = NULL;
    261:   PetscContainer container = NULL;
    262:   const char    *viewername;
    263:   char           datafile[PETSC_MAX_PATH_LEN];
    264:   char          *datafilename;
    265:   PetscViewer    fviewer;
    266:   PetscInt       N, bs;
    267:   const char    *vecname;
    268:   char           fieldname[PETSC_MAX_PATH_LEN];

    270:   PetscFunctionBegin;
    271:   PetscCall(PetscObjectQuery((PetscObject)viewer, "XDMFViewerContext", (PetscObject *)&container));
    272:   PetscCheck(container, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unable to find attached data XDMFViewerContext");
    273:   PetscCall(PetscContainerGetPointer(container, (void **)&bytes));
    274:   PetscCall(PetscViewerFileGetName(viewer, &viewername));
    275:   PetscCall(private_CreateDataFileNameXDMF(viewername, datafile));

    277:   /* re-open a sub-viewer for all data fields */
    278:   /* name is viewer.name + "_swarm_fields.pbin" */
    279:   PetscCall(PetscViewerCreate(PetscObjectComm((PetscObject)viewer), &fviewer));
    280:   PetscCall(PetscViewerSetType(fviewer, PETSCVIEWERBINARY));
    281:   PetscCall(PetscViewerBinarySetSkipHeader(fviewer, PETSC_TRUE));
    282:   PetscCall(PetscViewerBinarySetSkipInfo(fviewer, PETSC_TRUE));
    283:   PetscCall(PetscViewerFileSetMode(fviewer, FILE_MODE_APPEND));
    284:   PetscCall(PetscViewerFileSetName(fviewer, datafile));
    285:   PetscCall(PetscStrrchr(datafile, '/', &datafilename));

    287:   PetscCall(ISGetSize(is, &N));
    288:   PetscCall(ISGetBlockSize(is, &bs));
    289:   N = N / bs;
    290:   PetscCall(PetscObjectGetName((PetscObject)is, &vecname));
    291:   if (!vecname) {
    292:     PetscCall(PetscSNPrintf(fieldname, PETSC_MAX_PATH_LEN - 1, "swarmfield_%d", ((PetscObject)is)->tag));
    293:   } else {
    294:     PetscCall(PetscSNPrintf(fieldname, PETSC_MAX_PATH_LEN - 1, "%s", vecname));
    295:   }

    297:   /* write data header */
    298:   PetscCall(PetscViewerASCIIPushTab(viewer));
    299:   PetscCall(PetscViewerASCIIPrintf(viewer, "<Attribute Center=\"Node\" Name=\"%s\" Type=\"None\">\n", fieldname));
    300:   PetscCall(PetscViewerASCIIPushTab(viewer));
    301:   if (bs == 1) {
    302:     PetscCall(PetscViewerASCIIPrintf(viewer, "<DataItem Format=\"Binary\" Endian=\"Big\" DataType=\"Int\" Precision=\"4\" Dimensions=\"%" PetscInt_FMT "\" Seek=\"%ld\">\n", N, bytes[0]));
    303:   } else {
    304:     PetscCall(PetscViewerASCIIPrintf(viewer, "<DataItem Format=\"Binary\" Endian=\"Big\" DataType=\"Int\" Precision=\"4\" Dimensions=\"%" PetscInt_FMT " %" PetscInt_FMT "\" Seek=\"%ld\">\n", N, bs, bytes[0]));
    305:   }
    306:   PetscCall(PetscViewerASCIIPushTab(viewer));
    307:   PetscCall(PetscViewerASCIIPrintf(viewer, "%s\n", datafilename));
    308:   PetscCall(PetscViewerASCIIPopTab(viewer));
    309:   PetscCall(PetscViewerASCIIPrintf(viewer, "</DataItem>\n"));
    310:   PetscCall(PetscViewerASCIIPopTab(viewer));
    311:   PetscCall(PetscViewerASCIIPrintf(viewer, "</Attribute>\n"));
    312:   PetscCall(PetscViewerASCIIPopTab(viewer));

    314:   /* write data */
    315:   PetscCall(ISView(is, fviewer));
    316:   bytes[0] += sizeof(PetscInt) * N * bs;

    318:   PetscCall(PetscViewerDestroy(&fviewer));
    319:   PetscFunctionReturn(PETSC_SUCCESS);
    320: }

    322: /*@C
    323:   DMSwarmViewFieldsXDMF - Write a selection of DMSwarm fields to an XDMF3 file

    325:   Collective

    327:   Input Parameters:
    328: + dm              - the `DMSWARM`
    329: . filename        - the file name of the XDMF file (must have the extension .xmf)
    330: . nfields         - the number of fields to write into the XDMF file
    331: - field_name_list - array of length nfields containing the textual name of fields to write

    333:   Level: beginner

    335:   Note:
    336:   Only fields registered with data type `PETSC_DOUBLE` or `PETSC_INT` can be written into the file

    338: .seealso: `DM`, `DMSWARM`, `DMSwarmViewXDMF()`
    339: @*/
    340: PetscErrorCode DMSwarmViewFieldsXDMF(DM dm, const char filename[], PetscInt nfields, const char *field_name_list[])
    341: {
    342:   Vec         dvec;
    343:   PetscInt    f, N;
    344:   PetscViewer viewer;

    346:   PetscFunctionBegin;
    347:   PetscCall(private_PetscViewerCreate_XDMF(PetscObjectComm((PetscObject)dm), filename, &viewer));
    348:   PetscCall(private_DMSwarmView_XDMF(dm, viewer));
    349:   PetscCall(DMSwarmGetLocalSize(dm, &N));
    350:   for (f = 0; f < nfields; f++) {
    351:     void         *data;
    352:     PetscDataType type;

    354:     PetscCall(DMSwarmGetField(dm, field_name_list[f], NULL, &type, &data));
    355:     PetscCall(DMSwarmRestoreField(dm, field_name_list[f], NULL, &type, &data));
    356:     if (type == PETSC_DOUBLE) {
    357:       PetscCall(DMSwarmCreateGlobalVectorFromField(dm, field_name_list[f], &dvec));
    358:       PetscCall(PetscObjectSetName((PetscObject)dvec, field_name_list[f]));
    359:       PetscCall(private_VecView_Swarm_XDMF(dvec, viewer));
    360:       PetscCall(DMSwarmDestroyGlobalVectorFromField(dm, field_name_list[f], &dvec));
    361:     } else if (type == PETSC_INT) {
    362:       IS              is;
    363:       const PetscInt *idx;

    365:       PetscCall(DMSwarmGetField(dm, field_name_list[f], NULL, &type, &data));
    366:       idx = (const PetscInt *)data;

    368:       PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), N, idx, PETSC_USE_POINTER, &is));
    369:       PetscCall(PetscObjectSetName((PetscObject)is, field_name_list[f]));
    370:       PetscCall(private_ISView_Swarm_XDMF(is, viewer));
    371:       PetscCall(ISDestroy(&is));
    372:       PetscCall(DMSwarmRestoreField(dm, field_name_list[f], NULL, &type, &data));
    373:     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Can only write PETSC_INT and PETSC_DOUBLE");
    374:   }
    375:   PetscCall(private_PetscViewerDestroy_XDMF(&viewer));
    376:   PetscFunctionReturn(PETSC_SUCCESS);
    377: }

    379: /*@
    380:   DMSwarmViewXDMF - Write `DMSWARM` fields to an XDMF3 file

    382:   Collective

    384:   Input Parameters:
    385: + dm       - the `DMSWARM`
    386: - filename - the file name of the XDMF file (must have the extension .xmf)

    388:   Level: beginner

    390:   Note:
    391:   Only fields user registered with data type `PETSC_DOUBLE` or `PETSC_INT` will be written into the file

    393:   Developer Note:
    394:   This should be removed and replaced with the standard use of `PetscViewer`

    396: .seealso: `DM`, `DMSWARM`, `DMSwarmViewFieldsXDMF()`
    397: @*/
    398: PetscErrorCode DMSwarmViewXDMF(DM dm, const char filename[])
    399: {
    400:   DM_Swarm   *swarm = (DM_Swarm *)dm->data;
    401:   Vec         dvec;
    402:   PetscInt    f;
    403:   PetscViewer viewer;

    405:   PetscFunctionBegin;
    406:   PetscCall(private_PetscViewerCreate_XDMF(PetscObjectComm((PetscObject)dm), filename, &viewer));
    407:   PetscCall(private_DMSwarmView_XDMF(dm, viewer));
    408:   for (f = 4; f < swarm->db->nfields; f++) { /* only examine user defined fields - the first 4 are internally created by DMSwarmPIC */
    409:     DMSwarmDataField field;

    411:     /* query field type - accept all those of type PETSC_DOUBLE */
    412:     field = swarm->db->field[f];
    413:     if (field->petsc_type == PETSC_DOUBLE) {
    414:       PetscCall(DMSwarmCreateGlobalVectorFromField(dm, field->name, &dvec));
    415:       PetscCall(PetscObjectSetName((PetscObject)dvec, field->name));
    416:       PetscCall(private_VecView_Swarm_XDMF(dvec, viewer));
    417:       PetscCall(DMSwarmDestroyGlobalVectorFromField(dm, field->name, &dvec));
    418:     } else if (field->petsc_type == PETSC_INT) {
    419:       IS              is;
    420:       PetscInt        N;
    421:       const PetscInt *idx;
    422:       void           *data;

    424:       PetscCall(DMSwarmGetLocalSize(dm, &N));
    425:       PetscCall(DMSwarmGetField(dm, field->name, NULL, NULL, &data));
    426:       idx = (const PetscInt *)data;

    428:       PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), N, idx, PETSC_USE_POINTER, &is));
    429:       PetscCall(PetscObjectSetName((PetscObject)is, field->name));
    430:       PetscCall(private_ISView_Swarm_XDMF(is, viewer));
    431:       PetscCall(ISDestroy(&is));
    432:       PetscCall(DMSwarmRestoreField(dm, field->name, NULL, NULL, &data));
    433:     }
    434:   }
    435:   PetscCall(private_PetscViewerDestroy_XDMF(&viewer));
    436:   PetscFunctionReturn(PETSC_SUCCESS);
    437: }