xref: /petsc/src/dm/impls/swarm/swarmpic_view.c (revision f13dfd9ea68e0ddeee984e65c377a1819eab8a8a)
1 #include <petscdm.h>
2 #include <petscdmda.h>
3 #include <petscdmswarm.h>
4 #include <petsc/private/dmswarmimpl.h>
5 #include "../src/dm/impls/swarm/data_bucket.h"
6 
7 static PetscErrorCode private_PetscViewerCreate_XDMF(MPI_Comm comm, const char filename[], PetscViewer *v)
8 {
9   long int      *bytes;
10   PetscContainer container;
11   PetscViewer    viewer;
12 
13   PetscFunctionBegin;
14   PetscCall(PetscViewerCreate(comm, &viewer));
15   PetscCall(PetscViewerSetType(viewer, PETSCVIEWERASCII));
16   PetscCall(PetscViewerFileSetMode(viewer, FILE_MODE_WRITE));
17   PetscCall(PetscViewerFileSetName(viewer, filename));
18 
19   PetscCall(PetscMalloc1(1, &bytes));
20   bytes[0] = 0;
21   PetscCall(PetscContainerCreate(comm, &container));
22   PetscCall(PetscContainerSetPointer(container, (void *)bytes));
23   PetscCall(PetscObjectCompose((PetscObject)viewer, "XDMFViewerContext", (PetscObject)container));
24 
25   /* write xdmf header */
26   PetscCall(PetscViewerASCIIPrintf(viewer, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"));
27   PetscCall(PetscViewerASCIIPrintf(viewer, "<Xdmf xmlns:xi=\"http://www.w3.org/2001/XInclude/\" Version=\"2.99\">\n"));
28   /* write xdmf domain */
29   PetscCall(PetscViewerASCIIPushTab(viewer));
30   PetscCall(PetscViewerASCIIPrintf(viewer, "<Domain>\n"));
31   *v = viewer;
32   PetscFunctionReturn(PETSC_SUCCESS);
33 }
34 
35 static PetscErrorCode private_PetscViewerDestroy_XDMF(PetscViewer *v)
36 {
37   PetscViewer    viewer;
38   DM             dm = NULL;
39   long int      *bytes;
40   PetscContainer container = NULL;
41 
42   PetscFunctionBegin;
43   if (!v) PetscFunctionReturn(PETSC_SUCCESS);
44   viewer = *v;
45 
46   PetscCall(PetscObjectQuery((PetscObject)viewer, "DMSwarm", (PetscObject *)&dm));
47   if (dm) {
48     PetscCall(PetscViewerASCIIPrintf(viewer, "</Grid>\n"));
49     PetscCall(PetscViewerASCIIPopTab(viewer));
50   }
51 
52   /* close xdmf header */
53   PetscCall(PetscViewerASCIIPrintf(viewer, "</Domain>\n"));
54   PetscCall(PetscViewerASCIIPopTab(viewer));
55   PetscCall(PetscViewerASCIIPrintf(viewer, "</Xdmf>\n"));
56 
57   PetscCall(PetscObjectQuery((PetscObject)viewer, "XDMFViewerContext", (PetscObject *)&container));
58   if (container) {
59     PetscCall(PetscContainerGetPointer(container, (void **)&bytes));
60     PetscCall(PetscFree(bytes));
61     PetscCall(PetscContainerDestroy(&container));
62   }
63   PetscCall(PetscViewerDestroy(&viewer));
64   *v = NULL;
65   PetscFunctionReturn(PETSC_SUCCESS);
66 }
67 
68 static PetscErrorCode private_CreateDataFileNameXDMF(const char filename[], char dfilename[])
69 {
70   const char dot_xmf[] = ".xmf";
71   size_t     len;
72   char       viewername_minus_ext[PETSC_MAX_PATH_LEN];
73   PetscBool  flg;
74 
75   PetscFunctionBegin;
76   PetscCall(PetscStrendswith(filename, dot_xmf, &flg));
77   PetscCheck(flg, PETSC_COMM_SELF, PETSC_ERR_SUP, "File extension must be %s", dot_xmf);
78   PetscCall(PetscStrncpy(viewername_minus_ext, filename, sizeof(viewername_minus_ext)));
79   PetscCall(PetscStrlen(filename, &len));
80   len -= sizeof(dot_xmf) - 1;
81   if (sizeof(viewername_minus_ext) > len) viewername_minus_ext[len] = '\0';
82   PetscCall(PetscSNPrintf(dfilename, PETSC_MAX_PATH_LEN - 1, "%s_swarm_fields.pbin", viewername_minus_ext));
83   PetscFunctionReturn(PETSC_SUCCESS);
84 }
85 
86 static PetscErrorCode private_DMSwarmView_XDMF(DM dm, PetscViewer viewer)
87 {
88   PetscBool      isswarm = PETSC_FALSE;
89   const char    *viewername;
90   char           datafile[PETSC_MAX_PATH_LEN];
91   char          *datafilename;
92   PetscViewer    fviewer;
93   PetscInt       k, ng, dim;
94   Vec            dvec;
95   long int      *bytes     = NULL;
96   PetscContainer container = NULL;
97   const char    *dmname;
98 
99   PetscFunctionBegin;
100   PetscCall(PetscObjectQuery((PetscObject)viewer, "XDMFViewerContext", (PetscObject *)&container));
101   if (container) {
102     PetscCall(PetscContainerGetPointer(container, (void **)&bytes));
103   } else SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Valid to find attached data XDMFViewerContext");
104 
105   PetscCall(PetscObjectTypeCompare((PetscObject)dm, DMSWARM, &isswarm));
106   PetscCheck(isswarm, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Only valid for DMSwarm");
107 
108   PetscCall(PetscObjectCompose((PetscObject)viewer, "DMSwarm", (PetscObject)dm));
109 
110   PetscCall(PetscViewerASCIIPushTab(viewer));
111   PetscCall(PetscObjectGetName((PetscObject)dm, &dmname));
112   if (!dmname) PetscCall(DMGetOptionsPrefix(dm, &dmname));
113   if (!dmname) {
114     PetscCall(PetscViewerASCIIPrintf(viewer, "<Grid Name=\"DMSwarm\" GridType=\"Uniform\">\n"));
115   } else {
116     PetscCall(PetscViewerASCIIPrintf(viewer, "<Grid Name=\"DMSwarm[%s]\" GridType=\"Uniform\">\n", dmname));
117   }
118 
119   /* create a sub-viewer for topology, geometry and all data fields */
120   /* name is viewer.name + "_swarm_fields.pbin" */
121   PetscCall(PetscViewerCreate(PetscObjectComm((PetscObject)viewer), &fviewer));
122   PetscCall(PetscViewerSetType(fviewer, PETSCVIEWERBINARY));
123   PetscCall(PetscViewerBinarySetSkipHeader(fviewer, PETSC_TRUE));
124   PetscCall(PetscViewerBinarySetSkipInfo(fviewer, PETSC_TRUE));
125   PetscCall(PetscViewerFileSetMode(fviewer, FILE_MODE_WRITE));
126 
127   PetscCall(PetscViewerFileGetName(viewer, &viewername));
128   PetscCall(private_CreateDataFileNameXDMF(viewername, datafile));
129   PetscCall(PetscViewerFileSetName(fviewer, datafile));
130   PetscCall(PetscStrrchr(datafile, '/', &datafilename));
131 
132   PetscCall(DMSwarmGetSize(dm, &ng));
133 
134   /* write topology header */
135   PetscCall(PetscViewerASCIIPushTab(viewer));
136   PetscCall(PetscViewerASCIIPrintf(viewer, "<Topology Dimensions=\"%" PetscInt_FMT "\" TopologyType=\"Mixed\">\n", ng));
137   PetscCall(PetscViewerASCIIPushTab(viewer));
138   PetscCall(PetscViewerASCIIPrintf(viewer, "<DataItem Format=\"Binary\" Endian=\"Big\" DataType=\"Int\" Dimensions=\"%" PetscInt_FMT "\" Seek=\"%ld\">\n", ng * 3, bytes[0]));
139   PetscCall(PetscViewerASCIIPushTab(viewer));
140   PetscCall(PetscViewerASCIIPrintf(viewer, "%s\n", datafilename));
141   PetscCall(PetscViewerASCIIPopTab(viewer));
142   PetscCall(PetscViewerASCIIPrintf(viewer, "</DataItem>\n"));
143   PetscCall(PetscViewerASCIIPopTab(viewer));
144   PetscCall(PetscViewerASCIIPrintf(viewer, "</Topology>\n"));
145   PetscCall(PetscViewerASCIIPopTab(viewer));
146 
147   /* write topology data */
148   for (k = 0; k < ng; k++) {
149     PetscInt pvertex[3];
150 
151     pvertex[0] = 1;
152     pvertex[1] = 1;
153     pvertex[2] = k;
154     PetscCall(PetscViewerBinaryWrite(fviewer, pvertex, 3, PETSC_INT));
155   }
156   bytes[0] += sizeof(PetscInt) * ng * 3;
157 
158   /* write geometry header */
159   PetscCall(PetscViewerASCIIPushTab(viewer));
160   PetscCall(DMGetDimension(dm, &dim));
161   switch (dim) {
162   case 1:
163     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "No support for 1D");
164   case 2:
165     PetscCall(PetscViewerASCIIPrintf(viewer, "<Geometry Type=\"XY\">\n"));
166     break;
167   case 3:
168     PetscCall(PetscViewerASCIIPrintf(viewer, "<Geometry Type=\"XYZ\">\n"));
169     break;
170   }
171   PetscCall(PetscViewerASCIIPushTab(viewer));
172   PetscCall(PetscViewerASCIIPrintf(viewer, "<DataItem Format=\"Binary\" Endian=\"Big\" DataType=\"Float\" Precision=\"8\" Dimensions=\"%" PetscInt_FMT " %" PetscInt_FMT "\" Seek=\"%ld\">\n", ng, dim, bytes[0]));
173   PetscCall(PetscViewerASCIIPushTab(viewer));
174   PetscCall(PetscViewerASCIIPrintf(viewer, "%s\n", datafilename));
175   PetscCall(PetscViewerASCIIPopTab(viewer));
176   PetscCall(PetscViewerASCIIPrintf(viewer, "</DataItem>\n"));
177   PetscCall(PetscViewerASCIIPopTab(viewer));
178   PetscCall(PetscViewerASCIIPrintf(viewer, "</Geometry>\n"));
179   PetscCall(PetscViewerASCIIPopTab(viewer));
180 
181   /* write geometry data */
182   PetscCall(DMSwarmCreateGlobalVectorFromField(dm, DMSwarmPICField_coor, &dvec));
183   PetscCall(VecView(dvec, fviewer));
184   PetscCall(DMSwarmDestroyGlobalVectorFromField(dm, DMSwarmPICField_coor, &dvec));
185   bytes[0] += sizeof(PetscReal) * ng * dim;
186 
187   PetscCall(PetscViewerDestroy(&fviewer));
188   PetscFunctionReturn(PETSC_SUCCESS);
189 }
190 
191 static PetscErrorCode private_VecView_Swarm_XDMF(Vec x, PetscViewer viewer)
192 {
193   long int      *bytes     = NULL;
194   PetscContainer container = NULL;
195   const char    *viewername;
196   char           datafile[PETSC_MAX_PATH_LEN];
197   char          *datafilename;
198   PetscViewer    fviewer;
199   PetscInt       N, bs;
200   const char    *vecname;
201   char           fieldname[PETSC_MAX_PATH_LEN];
202 
203   PetscFunctionBegin;
204   PetscCall(PetscObjectQuery((PetscObject)viewer, "XDMFViewerContext", (PetscObject *)&container));
205   PetscCheck(container, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unable to find attached data XDMFViewerContext");
206   PetscCall(PetscContainerGetPointer(container, (void **)&bytes));
207   PetscCall(PetscViewerFileGetName(viewer, &viewername));
208   PetscCall(private_CreateDataFileNameXDMF(viewername, datafile));
209 
210   /* re-open a sub-viewer for all data fields */
211   /* name is viewer.name + "_swarm_fields.pbin" */
212   PetscCall(PetscViewerCreate(PetscObjectComm((PetscObject)viewer), &fviewer));
213   PetscCall(PetscViewerSetType(fviewer, PETSCVIEWERBINARY));
214   PetscCall(PetscViewerBinarySetSkipHeader(fviewer, PETSC_TRUE));
215   PetscCall(PetscViewerBinarySetSkipInfo(fviewer, PETSC_TRUE));
216   PetscCall(PetscViewerFileSetMode(fviewer, FILE_MODE_APPEND));
217   PetscCall(PetscViewerFileSetName(fviewer, datafile));
218   PetscCall(PetscStrrchr(datafile, '/', &datafilename));
219 
220   PetscCall(VecGetSize(x, &N));
221   PetscCall(VecGetBlockSize(x, &bs));
222   N = N / bs;
223   PetscCall(PetscObjectGetName((PetscObject)x, &vecname));
224   if (!vecname) {
225     PetscCall(PetscSNPrintf(fieldname, PETSC_MAX_PATH_LEN - 1, "swarmfield_%d", ((PetscObject)x)->tag));
226   } else {
227     PetscCall(PetscSNPrintf(fieldname, PETSC_MAX_PATH_LEN - 1, "%s", vecname));
228   }
229 
230   /* write data header */
231   PetscCall(PetscViewerASCIIPushTab(viewer));
232   PetscCall(PetscViewerASCIIPrintf(viewer, "<Attribute Center=\"Node\" Name=\"%s\" Type=\"None\">\n", fieldname));
233   PetscCall(PetscViewerASCIIPushTab(viewer));
234   if (bs == 1) {
235     PetscCall(PetscViewerASCIIPrintf(viewer, "<DataItem Format=\"Binary\" Endian=\"Big\" DataType=\"Float\" Precision=\"8\" Dimensions=\"%" PetscInt_FMT "\" Seek=\"%ld\">\n", N, bytes[0]));
236   } else {
237     PetscCall(PetscViewerASCIIPrintf(viewer, "<DataItem Format=\"Binary\" Endian=\"Big\" DataType=\"Float\" Precision=\"8\" Dimensions=\"%" PetscInt_FMT " %" PetscInt_FMT "\" Seek=\"%ld\">\n", N, bs, bytes[0]));
238   }
239   PetscCall(PetscViewerASCIIPushTab(viewer));
240   PetscCall(PetscViewerASCIIPrintf(viewer, "%s\n", datafilename));
241   PetscCall(PetscViewerASCIIPopTab(viewer));
242   PetscCall(PetscViewerASCIIPrintf(viewer, "</DataItem>\n"));
243   PetscCall(PetscViewerASCIIPopTab(viewer));
244   PetscCall(PetscViewerASCIIPrintf(viewer, "</Attribute>\n"));
245   PetscCall(PetscViewerASCIIPopTab(viewer));
246 
247   /* write data */
248   PetscCall(VecView(x, fviewer));
249   bytes[0] += sizeof(PetscReal) * N * bs;
250 
251   PetscCall(PetscViewerDestroy(&fviewer));
252   PetscFunctionReturn(PETSC_SUCCESS);
253 }
254 
255 static PetscErrorCode private_ISView_Swarm_XDMF(IS is, PetscViewer viewer)
256 {
257   long int      *bytes     = NULL;
258   PetscContainer container = NULL;
259   const char    *viewername;
260   char           datafile[PETSC_MAX_PATH_LEN];
261   char          *datafilename;
262   PetscViewer    fviewer;
263   PetscInt       N, bs;
264   const char    *vecname;
265   char           fieldname[PETSC_MAX_PATH_LEN];
266 
267   PetscFunctionBegin;
268   PetscCall(PetscObjectQuery((PetscObject)viewer, "XDMFViewerContext", (PetscObject *)&container));
269   PetscCheck(container, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unable to find attached data XDMFViewerContext");
270   PetscCall(PetscContainerGetPointer(container, (void **)&bytes));
271   PetscCall(PetscViewerFileGetName(viewer, &viewername));
272   PetscCall(private_CreateDataFileNameXDMF(viewername, datafile));
273 
274   /* re-open a sub-viewer for all data fields */
275   /* name is viewer.name + "_swarm_fields.pbin" */
276   PetscCall(PetscViewerCreate(PetscObjectComm((PetscObject)viewer), &fviewer));
277   PetscCall(PetscViewerSetType(fviewer, PETSCVIEWERBINARY));
278   PetscCall(PetscViewerBinarySetSkipHeader(fviewer, PETSC_TRUE));
279   PetscCall(PetscViewerBinarySetSkipInfo(fviewer, PETSC_TRUE));
280   PetscCall(PetscViewerFileSetMode(fviewer, FILE_MODE_APPEND));
281   PetscCall(PetscViewerFileSetName(fviewer, datafile));
282   PetscCall(PetscStrrchr(datafile, '/', &datafilename));
283 
284   PetscCall(ISGetSize(is, &N));
285   PetscCall(ISGetBlockSize(is, &bs));
286   N = N / bs;
287   PetscCall(PetscObjectGetName((PetscObject)is, &vecname));
288   if (!vecname) {
289     PetscCall(PetscSNPrintf(fieldname, PETSC_MAX_PATH_LEN - 1, "swarmfield_%d", ((PetscObject)is)->tag));
290   } else {
291     PetscCall(PetscSNPrintf(fieldname, PETSC_MAX_PATH_LEN - 1, "%s", vecname));
292   }
293 
294   /* write data header */
295   PetscCall(PetscViewerASCIIPushTab(viewer));
296   PetscCall(PetscViewerASCIIPrintf(viewer, "<Attribute Center=\"Node\" Name=\"%s\" Type=\"None\">\n", fieldname));
297   PetscCall(PetscViewerASCIIPushTab(viewer));
298   if (bs == 1) {
299     PetscCall(PetscViewerASCIIPrintf(viewer, "<DataItem Format=\"Binary\" Endian=\"Big\" DataType=\"Int\" Precision=\"4\" Dimensions=\"%" PetscInt_FMT "\" Seek=\"%ld\">\n", N, bytes[0]));
300   } else {
301     PetscCall(PetscViewerASCIIPrintf(viewer, "<DataItem Format=\"Binary\" Endian=\"Big\" DataType=\"Int\" Precision=\"4\" Dimensions=\"%" PetscInt_FMT " %" PetscInt_FMT "\" Seek=\"%ld\">\n", N, bs, bytes[0]));
302   }
303   PetscCall(PetscViewerASCIIPushTab(viewer));
304   PetscCall(PetscViewerASCIIPrintf(viewer, "%s\n", datafilename));
305   PetscCall(PetscViewerASCIIPopTab(viewer));
306   PetscCall(PetscViewerASCIIPrintf(viewer, "</DataItem>\n"));
307   PetscCall(PetscViewerASCIIPopTab(viewer));
308   PetscCall(PetscViewerASCIIPrintf(viewer, "</Attribute>\n"));
309   PetscCall(PetscViewerASCIIPopTab(viewer));
310 
311   /* write data */
312   PetscCall(ISView(is, fviewer));
313   bytes[0] += sizeof(PetscInt) * N * bs;
314 
315   PetscCall(PetscViewerDestroy(&fviewer));
316   PetscFunctionReturn(PETSC_SUCCESS);
317 }
318 
319 /*@C
320   DMSwarmViewFieldsXDMF - Write a selection of DMSwarm fields to an XDMF3 file
321 
322   Collective
323 
324   Input Parameters:
325 + dm              - the `DMSWARM`
326 . filename        - the file name of the XDMF file (must have the extension .xmf)
327 . nfields         - the number of fields to write into the XDMF file
328 - field_name_list - array of length nfields containing the textual name of fields to write
329 
330   Level: beginner
331 
332   Note:
333   Only fields registered with data type `PETSC_DOUBLE` or `PETSC_INT` can be written into the file
334 
335 .seealso: `DM`, `DMSWARM`, `DMSwarmViewXDMF()`
336 @*/
337 PETSC_EXTERN PetscErrorCode DMSwarmViewFieldsXDMF(DM dm, const char filename[], PetscInt nfields, const char *field_name_list[])
338 {
339   Vec         dvec;
340   PetscInt    f, N;
341   PetscViewer viewer;
342 
343   PetscFunctionBegin;
344   PetscCall(private_PetscViewerCreate_XDMF(PetscObjectComm((PetscObject)dm), filename, &viewer));
345   PetscCall(private_DMSwarmView_XDMF(dm, viewer));
346   PetscCall(DMSwarmGetLocalSize(dm, &N));
347   for (f = 0; f < nfields; f++) {
348     void         *data;
349     PetscDataType type;
350 
351     PetscCall(DMSwarmGetField(dm, field_name_list[f], NULL, &type, &data));
352     PetscCall(DMSwarmRestoreField(dm, field_name_list[f], NULL, &type, &data));
353     if (type == PETSC_DOUBLE) {
354       PetscCall(DMSwarmCreateGlobalVectorFromField(dm, field_name_list[f], &dvec));
355       PetscCall(PetscObjectSetName((PetscObject)dvec, field_name_list[f]));
356       PetscCall(private_VecView_Swarm_XDMF(dvec, viewer));
357       PetscCall(DMSwarmDestroyGlobalVectorFromField(dm, field_name_list[f], &dvec));
358     } else if (type == PETSC_INT) {
359       IS              is;
360       const PetscInt *idx;
361 
362       PetscCall(DMSwarmGetField(dm, field_name_list[f], NULL, &type, &data));
363       idx = (const PetscInt *)data;
364 
365       PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), N, idx, PETSC_USE_POINTER, &is));
366       PetscCall(PetscObjectSetName((PetscObject)is, field_name_list[f]));
367       PetscCall(private_ISView_Swarm_XDMF(is, viewer));
368       PetscCall(ISDestroy(&is));
369       PetscCall(DMSwarmRestoreField(dm, field_name_list[f], NULL, &type, &data));
370     } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Can only write PETSC_INT and PETSC_DOUBLE");
371   }
372   PetscCall(private_PetscViewerDestroy_XDMF(&viewer));
373   PetscFunctionReturn(PETSC_SUCCESS);
374 }
375 
376 /*@C
377   DMSwarmViewXDMF - Write `DMSWARM` fields to an XDMF3 file
378 
379   Collective
380 
381   Input Parameters:
382 + dm       - the `DMSWARM`
383 - filename - the file name of the XDMF file (must have the extension .xmf)
384 
385   Level: beginner
386 
387   Note:
388   Only fields user registered with data type `PETSC_DOUBLE` or `PETSC_INT` will be written into the file
389 
390   Developer Note:
391   This should be removed and replaced with the standard use of `PetscViewer`
392 
393 .seealso: `DM`, `DMSWARM`, `DMSwarmViewFieldsXDMF()`
394 @*/
395 PETSC_EXTERN PetscErrorCode DMSwarmViewXDMF(DM dm, const char filename[])
396 {
397   DM_Swarm   *swarm = (DM_Swarm *)dm->data;
398   Vec         dvec;
399   PetscInt    f;
400   PetscViewer viewer;
401 
402   PetscFunctionBegin;
403   PetscCall(private_PetscViewerCreate_XDMF(PetscObjectComm((PetscObject)dm), filename, &viewer));
404   PetscCall(private_DMSwarmView_XDMF(dm, viewer));
405   for (f = 4; f < swarm->db->nfields; f++) { /* only examine user defined fields - the first 4 are internally created by DMSwarmPIC */
406     DMSwarmDataField field;
407 
408     /* query field type - accept all those of type PETSC_DOUBLE */
409     field = swarm->db->field[f];
410     if (field->petsc_type == PETSC_DOUBLE) {
411       PetscCall(DMSwarmCreateGlobalVectorFromField(dm, field->name, &dvec));
412       PetscCall(PetscObjectSetName((PetscObject)dvec, field->name));
413       PetscCall(private_VecView_Swarm_XDMF(dvec, viewer));
414       PetscCall(DMSwarmDestroyGlobalVectorFromField(dm, field->name, &dvec));
415     } else if (field->petsc_type == PETSC_INT) {
416       IS              is;
417       PetscInt        N;
418       const PetscInt *idx;
419       void           *data;
420 
421       PetscCall(DMSwarmGetLocalSize(dm, &N));
422       PetscCall(DMSwarmGetField(dm, field->name, NULL, NULL, &data));
423       idx = (const PetscInt *)data;
424 
425       PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), N, idx, PETSC_USE_POINTER, &is));
426       PetscCall(PetscObjectSetName((PetscObject)is, field->name));
427       PetscCall(private_ISView_Swarm_XDMF(is, viewer));
428       PetscCall(ISDestroy(&is));
429       PetscCall(DMSwarmRestoreField(dm, field->name, NULL, NULL, &data));
430     }
431   }
432   PetscCall(private_PetscViewerDestroy_XDMF(&viewer));
433   PetscFunctionReturn(PETSC_SUCCESS);
434 }
435