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: }