xref: /petsc/src/dm/impls/swarm/swarm.c (revision ed923d712065d5cd07973a5b5fb0ac097e7d6cf0)
1 
2 #define PETSCDM_DLL
3 #include <petsc/private/dmswarmimpl.h>    /*I   "petscdmswarm.h"   I*/
4 #include "data_bucket.h"
5 
6 PetscLogEvent DMSWARM_Migrate;
7 PetscLogEvent DMSWARM_DataExchangerTopologySetup, DMSWARM_DataExchangerBegin, DMSWARM_DataExchangerEnd;
8 PetscLogEvent DMSWARM_DataExchangerSendCount, DMSWARM_DataExchangerPack;
9 
10 const char* DMSwarmTypeNames[] = { "basic", "pic", 0 };
11 const char* DMSwarmMigrateTypeNames[] = { "basic", "dmcellnscatter", "dmcellexact", "user", 0 };
12 const char* DMSwarmCollectTypeNames[] = { "basic", "boundingbox", "general", "user", 0 };
13 const char* DMSwarmPICLayoutTypeNames[] = { "regular", "gauss", "subdivision", 0 };
14 
15 const char DMSwarmField_pid[] = "DMSwarm_pid";
16 const char DMSwarmField_rank[] = "DMSwarm_rank";
17 const char DMSwarmPICField_coor[] = "DMSwarmPIC_coor";
18 const char DMSwarmPICField_cellid[] = "DMSwarm_cellid";
19 
20 /*@C
21    DMSwarmVectorDefineField - Sets the field from which to define a Vec object
22                              when DMCreateLocalVector(), or DMCreateGlobalVector() is called
23 
24    Collective on DM
25 
26    Input parameters:
27 +  dm - a DMSwarm
28 -  fieldname - the textual name given to a registered field
29 
30    Level: beginner
31 
32    Notes:
33    The field with name fieldname must be defined as having a data type of PetscScalar.
34    This function must be called prior to calling DMCreateLocalVector(), DMCreateGlobalVector().
35    Mutiple calls to DMSwarmVectorDefineField() are permitted.
36 
37 .seealso: DMSwarmRegisterPetscDatatypeField(), DMCreateGlobalVector(), DMCreateLocalVector()
38 @*/
39 PETSC_EXTERN PetscErrorCode DMSwarmVectorDefineField(DM dm,const char fieldname[])
40 {
41   DM_Swarm *swarm = (DM_Swarm*)dm->data;
42   PetscErrorCode ierr;
43   PetscInt bs,n;
44   PetscScalar *array;
45   PetscDataType type;
46 
47   PetscFunctionBegin;
48   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
49   ierr = DataBucketGetSizes(swarm->db,&n,NULL,NULL);CHKERRQ(ierr);
50   ierr = DMSwarmGetField(dm,fieldname,&bs,&type,(void**)&array);CHKERRQ(ierr);
51 
52   /* Check all fields are of type PETSC_REAL or PETSC_SCALAR */
53   if (type != PETSC_REAL) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only valid for PETSC_REAL");
54   ierr = PetscSNPrintf(swarm->vec_field_name,PETSC_MAX_PATH_LEN-1,"%s",fieldname);CHKERRQ(ierr);
55   swarm->vec_field_set = PETSC_TRUE;
56   swarm->vec_field_bs = bs;
57   swarm->vec_field_nlocal = n;
58   ierr = DMSwarmRestoreField(dm,fieldname,&bs,&type,(void**)&array);CHKERRQ(ierr);
59   PetscFunctionReturn(0);
60 }
61 
62 /* requires DMSwarmDefineFieldVector has been called */
63 PetscErrorCode DMCreateGlobalVector_Swarm(DM dm,Vec *vec)
64 {
65   DM_Swarm *swarm = (DM_Swarm*)dm->data;
66   PetscErrorCode ierr;
67   Vec x;
68   char name[PETSC_MAX_PATH_LEN];
69 
70   PetscFunctionBegin;
71   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
72   if (!swarm->vec_field_set) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmVectorDefineField first");
73   if (swarm->vec_field_nlocal != swarm->db->L) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSwarm sizes have changed since last call to VectorDefineField first"); /* Stale data */
74 
75   ierr = PetscSNPrintf(name,PETSC_MAX_PATH_LEN-1,"DMSwarmField_%s",swarm->vec_field_name);CHKERRQ(ierr);
76   ierr = VecCreate(PetscObjectComm((PetscObject)dm),&x);CHKERRQ(ierr);
77   ierr = PetscObjectSetName((PetscObject)x,name);CHKERRQ(ierr);
78   ierr = VecSetSizes(x,swarm->db->L*swarm->vec_field_bs,PETSC_DETERMINE);CHKERRQ(ierr);
79   ierr = VecSetBlockSize(x,swarm->vec_field_bs);CHKERRQ(ierr);
80   ierr = VecSetFromOptions(x);CHKERRQ(ierr);
81   *vec = x;
82   PetscFunctionReturn(0);
83 }
84 
85 /* requires DMSwarmDefineFieldVector has been called */
86 PetscErrorCode DMCreateLocalVector_Swarm(DM dm,Vec *vec)
87 {
88   DM_Swarm *swarm = (DM_Swarm*)dm->data;
89   PetscErrorCode ierr;
90   Vec x;
91   char name[PETSC_MAX_PATH_LEN];
92 
93   PetscFunctionBegin;
94   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
95   if (!swarm->vec_field_set) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmVectorDefineField first");
96   if (swarm->vec_field_nlocal != swarm->db->L) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSwarm sizes have changed since last call to VectorDefineField first"); /* Stale data */
97 
98   ierr = PetscSNPrintf(name,PETSC_MAX_PATH_LEN-1,"DMSwarmField_%s",swarm->vec_field_name);CHKERRQ(ierr);
99   ierr = VecCreate(PETSC_COMM_SELF,&x);CHKERRQ(ierr);
100   ierr = PetscObjectSetName((PetscObject)x,name);CHKERRQ(ierr);
101   ierr = VecSetSizes(x,swarm->db->L*swarm->vec_field_bs,PETSC_DETERMINE);CHKERRQ(ierr);
102   ierr = VecSetBlockSize(x,swarm->vec_field_bs);CHKERRQ(ierr);
103   ierr = VecSetFromOptions(x);CHKERRQ(ierr);
104   *vec = x;
105   PetscFunctionReturn(0);
106 }
107 
108 static PetscErrorCode DMSwarmDestroyVectorFromField_Private(DM dm, const char fieldname[], Vec *vec)
109 {
110   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
111   DataField      gfield;
112   void         (*fptr)(void);
113   PetscInt       bs, nlocal;
114   char           name[PETSC_MAX_PATH_LEN];
115   PetscErrorCode ierr;
116 
117   PetscFunctionBegin;
118   ierr = VecGetLocalSize(*vec, &nlocal);CHKERRQ(ierr);
119   ierr = VecGetBlockSize(*vec, &bs);CHKERRQ(ierr);
120   if (nlocal/bs != swarm->db->L) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSwarm sizes have changed since vector was created - cannot ensure pointers are valid"); /* Stale data */
121   ierr = DataBucketGetDataFieldByName(swarm->db, fieldname, &gfield);CHKERRQ(ierr);
122   /* check vector is an inplace array */
123   ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarm_VecFieldInPlace_%s", fieldname);CHKERRQ(ierr);
124   ierr = PetscObjectQueryFunction((PetscObject) *vec, name, &fptr);CHKERRQ(ierr);
125   if (!fptr) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_USER, "Vector being destroyed was not created from DMSwarm field(%s)", fieldname);
126   ierr = DataFieldRestoreAccess(gfield);CHKERRQ(ierr);
127   ierr = VecDestroy(vec);CHKERRQ(ierr);
128   PetscFunctionReturn(0);
129 }
130 
131 static PetscErrorCode DMSwarmCreateVectorFromField_Private(DM dm, const char fieldname[], MPI_Comm comm, Vec *vec)
132 {
133   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
134   PetscDataType  type;
135   PetscScalar   *array;
136   PetscInt       bs, n;
137   char           name[PETSC_MAX_PATH_LEN];
138   PetscMPIInt    commsize;
139   PetscErrorCode ierr;
140 
141   PetscFunctionBegin;
142   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
143   ierr = DataBucketGetSizes(swarm->db, &n, NULL, NULL);CHKERRQ(ierr);
144   ierr = DMSwarmGetField(dm, fieldname, &bs, &type, (void **) &array);CHKERRQ(ierr);
145   if (type != PETSC_REAL) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Only valid for PETSC_REAL");
146 
147   ierr = MPI_Comm_size(comm, &commsize);CHKERRQ(ierr);
148   if (commsize == 1) {
149     ierr = VecCreateSeqWithArray(comm, bs, n*bs, array, vec);CHKERRQ(ierr);
150   } else {
151     ierr = VecCreateMPIWithArray(comm, bs, n*bs, PETSC_DETERMINE, array, vec);CHKERRQ(ierr);
152   }
153   ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarmSharedField_%s", fieldname);CHKERRQ(ierr);
154   ierr = PetscObjectSetName((PetscObject) *vec, name);CHKERRQ(ierr);
155 
156   /* Set guard */
157   ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarm_VecFieldInPlace_%s", fieldname);CHKERRQ(ierr);
158   ierr = PetscObjectComposeFunction((PetscObject) *vec, name, DMSwarmDestroyVectorFromField_Private);CHKERRQ(ierr);
159   PetscFunctionReturn(0);
160 }
161 
162 /*@C
163    DMSwarmCreateGlobalVectorFromField - Creates a Vec object sharing the array associated with a given field
164 
165    Collective on DM
166 
167    Input parameters:
168 +  dm - a DMSwarm
169 -  fieldname - the textual name given to a registered field
170 
171    Output parameter:
172 .  vec - the vector
173 
174    Level: beginner
175 
176    Notes:
177    The vector must be returned using a matching call to DMSwarmDestroyGlobalVectorFromField().
178 
179 .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmDestroyGlobalVectorFromField()
180 @*/
181 PETSC_EXTERN PetscErrorCode DMSwarmCreateGlobalVectorFromField(DM dm,const char fieldname[],Vec *vec)
182 {
183   MPI_Comm       comm = PetscObjectComm((PetscObject) dm);
184   PetscErrorCode ierr;
185 
186   PetscFunctionBegin;
187   ierr = DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec);CHKERRQ(ierr);
188   PetscFunctionReturn(0);
189 }
190 
191 /*@C
192    DMSwarmDestroyGlobalVectorFromField - Destroys the Vec object which share the array associated with a given field
193 
194    Collective on DM
195 
196    Input parameters:
197 +  dm - a DMSwarm
198 -  fieldname - the textual name given to a registered field
199 
200    Output parameter:
201 .  vec - the vector
202 
203    Level: beginner
204 
205 .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmCreateGlobalVectorFromField()
206 @*/
207 PETSC_EXTERN PetscErrorCode DMSwarmDestroyGlobalVectorFromField(DM dm,const char fieldname[],Vec *vec)
208 {
209   PetscErrorCode ierr;
210 
211   PetscFunctionBegin;
212   ierr = DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec);CHKERRQ(ierr);
213   PetscFunctionReturn(0);
214 }
215 
216 /*@C
217    DMSwarmCreateLocalVectorFromField - Creates a Vec object sharing the array associated with a given field
218 
219    Collective on DM
220 
221    Input parameters:
222 +  dm - a DMSwarm
223 -  fieldname - the textual name given to a registered field
224 
225    Output parameter:
226 .  vec - the vector
227 
228    Level: beginner
229 
230    Notes:
231    The vector must be returned using a matching call to DMSwarmDestroyLocalVectorFromField().
232 
233 .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmDestroyLocalVectorFromField()
234 @*/
235 PETSC_EXTERN PetscErrorCode DMSwarmCreateLocalVectorFromField(DM dm,const char fieldname[],Vec *vec)
236 {
237   MPI_Comm       comm = PETSC_COMM_SELF;
238   PetscErrorCode ierr;
239 
240   PetscFunctionBegin;
241   ierr = DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec);CHKERRQ(ierr);
242   PetscFunctionReturn(0);
243 }
244 
245 /*@C
246    DMSwarmDestroyLocalVectorFromField - Destroys the Vec object which share the array associated with a given field
247 
248    Collective on DM
249 
250    Input parameters:
251 +  dm - a DMSwarm
252 -  fieldname - the textual name given to a registered field
253 
254    Output parameter:
255 .  vec - the vector
256 
257    Level: beginner
258 
259 .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmCreateLocalVectorFromField()
260 @*/
261 PETSC_EXTERN PetscErrorCode DMSwarmDestroyLocalVectorFromField(DM dm,const char fieldname[],Vec *vec)
262 {
263   PetscErrorCode ierr;
264 
265   PetscFunctionBegin;
266   ierr = DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec);CHKERRQ(ierr);
267   PetscFunctionReturn(0);
268 }
269 
270 /*
271 PETSC_EXTERN PetscErrorCode DMSwarmCreateGlobalVectorFromFields(DM dm,const PetscInt nf,const char *fieldnames[],Vec *vec)
272 {
273   PetscFunctionReturn(0);
274 }
275 
276 PETSC_EXTERN PetscErrorCode DMSwarmRestoreGlobalVectorFromFields(DM dm,Vec *vec)
277 {
278   PetscFunctionReturn(0);
279 }
280 */
281 
282 /*@C
283    DMSwarmInitializeFieldRegister - Initiates the registration of fields to a DMSwarm
284 
285    Collective on DM
286 
287    Input parameter:
288 .  dm - a DMSwarm
289 
290    Level: beginner
291 
292    Notes:
293    After all fields have been registered, you must call DMSwarmFinalizeFieldRegister().
294 
295 .seealso: DMSwarmFinalizeFieldRegister(), DMSwarmRegisterPetscDatatypeField(),
296  DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
297 @*/
298 PETSC_EXTERN PetscErrorCode DMSwarmInitializeFieldRegister(DM dm)
299 {
300   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
301   PetscErrorCode ierr;
302 
303   PetscFunctionBegin;
304   if (!swarm->field_registration_initialized) {
305     swarm->field_registration_initialized = PETSC_TRUE;
306     ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_pid,1,PETSC_LONG);CHKERRQ(ierr); /* unique identifer */
307     ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_rank,1,PETSC_INT);CHKERRQ(ierr); /* used for communication */
308   }
309   PetscFunctionReturn(0);
310 }
311 
312 /*@C
313    DMSwarmFinalizeFieldRegister - Finalizes the registration of fields to a DMSwarm
314 
315    Collective on DM
316 
317    Input parameter:
318 .  dm - a DMSwarm
319 
320    Level: beginner
321 
322    Notes:
323    After DMSwarmFinalizeFieldRegister() has been called, no new fields can be defined on the DMSwarm.
324 
325 .seealso: DMSwarmInitializeFieldRegister(), DMSwarmRegisterPetscDatatypeField(),
326  DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
327 @*/
328 PETSC_EXTERN PetscErrorCode DMSwarmFinalizeFieldRegister(DM dm)
329 {
330   DM_Swarm *swarm = (DM_Swarm*)dm->data;
331   PetscErrorCode ierr;
332 
333   PetscFunctionBegin;
334   if (!swarm->field_registration_finalized) {
335     ierr = DataBucketFinalize(swarm->db);CHKERRQ(ierr);
336   }
337   swarm->field_registration_finalized = PETSC_TRUE;
338   PetscFunctionReturn(0);
339 }
340 
341 /*@C
342    DMSwarmSetLocalSizes - Sets the length of all registered fields on the DMSwarm
343 
344    Not collective
345 
346    Input parameters:
347 +  dm - a DMSwarm
348 .  nlocal - the length of each registered field
349 -  buffer - the length of the buffer used to efficient dynamic re-sizing
350 
351    Level: beginner
352 
353 .seealso: DMSwarmGetLocalSize()
354 @*/
355 PETSC_EXTERN PetscErrorCode DMSwarmSetLocalSizes(DM dm,PetscInt nlocal,PetscInt buffer)
356 {
357   DM_Swarm *swarm = (DM_Swarm*)dm->data;
358   PetscErrorCode ierr;
359 
360   PetscFunctionBegin;
361   ierr = DataBucketSetSizes(swarm->db,nlocal,buffer);CHKERRQ(ierr);
362   PetscFunctionReturn(0);
363 }
364 
365 /*@C
366    DMSwarmSetCellDM - Attachs a DM to a DMSwarm
367 
368    Collective on DM
369 
370    Input parameters:
371 +  dm - a DMSwarm
372 -  dmcell - the DM to attach to the DMSwarm
373 
374    Level: beginner
375 
376    Notes:
377    The attached DM (dmcell) will be queried for point location and
378    neighbor MPI-rank information if DMSwarmMigrate() is called.
379 
380 .seealso: DMSwarmSetType(), DMSwarmGetCellDM(), DMSwarmMigrate()
381 @*/
382 PETSC_EXTERN PetscErrorCode DMSwarmSetCellDM(DM dm,DM dmcell)
383 {
384   DM_Swarm *swarm = (DM_Swarm*)dm->data;
385 
386   PetscFunctionBegin;
387   swarm->dmcell = dmcell;
388   PetscFunctionReturn(0);
389 }
390 
391 /*@C
392    DMSwarmGetCellDM - Fetches the attached cell DM
393 
394    Collective on DM
395 
396    Input parameter:
397 .  dm - a DMSwarm
398 
399    Output parameter:
400 .  dmcell - the DM which was attached to the DMSwarm
401 
402    Level: beginner
403 
404 .seealso: DMSwarmSetCellDM()
405 @*/
406 PETSC_EXTERN PetscErrorCode DMSwarmGetCellDM(DM dm,DM *dmcell)
407 {
408   DM_Swarm *swarm = (DM_Swarm*)dm->data;
409 
410   PetscFunctionBegin;
411   *dmcell = swarm->dmcell;
412   PetscFunctionReturn(0);
413 }
414 
415 /*@C
416    DMSwarmGetLocalSize - Retrives the local length of fields registered
417 
418    Not collective
419 
420    Input parameter:
421 .  dm - a DMSwarm
422 
423    Output parameter:
424 .  nlocal - the length of each registered field
425 
426    Level: beginner
427 
428 .seealso: DMSwarmGetSize(), DMSwarmSetLocalSizes()
429 @*/
430 PETSC_EXTERN PetscErrorCode DMSwarmGetLocalSize(DM dm,PetscInt *nlocal)
431 {
432   DM_Swarm *swarm = (DM_Swarm*)dm->data;
433   PetscErrorCode ierr;
434 
435   PetscFunctionBegin;
436   if (nlocal) {ierr = DataBucketGetSizes(swarm->db,nlocal,NULL,NULL);CHKERRQ(ierr);}
437   PetscFunctionReturn(0);
438 }
439 
440 /*@C
441    DMSwarmGetSize - Retrives the total length of fields registered
442 
443    Collective on DM
444 
445    Input parameter:
446 .  dm - a DMSwarm
447 
448    Output parameter:
449 .  n - the total length of each registered field
450 
451    Level: beginner
452 
453    Note:
454    This calls MPI_Allreduce upon each call (inefficient but safe)
455 
456 .seealso: DMSwarmGetLocalSize(), DMSwarmSetLocalSizes()
457 @*/
458 PETSC_EXTERN PetscErrorCode DMSwarmGetSize(DM dm,PetscInt *n)
459 {
460   DM_Swarm *swarm = (DM_Swarm*)dm->data;
461   PetscErrorCode ierr;
462   PetscInt nlocal,ng;
463 
464   PetscFunctionBegin;
465   ierr = DataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
466   ierr = MPI_Allreduce(&nlocal,&ng,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
467   if (n) { *n = ng; }
468   PetscFunctionReturn(0);
469 }
470 
471 /*@C
472    DMSwarmRegisterPetscDatatypeField - Register a field to a DMSwarm with a native PETSc data type
473 
474    Collective on DM
475 
476    Input parameters:
477 +  dm - a DMSwarm
478 .  fieldname - the textual name to identify this field
479 .  blocksize - the number of each data type
480 -  type - a valid PETSc data type (PETSC_CHAR, PETSC_SHORT, PETSC_INT, PETSC_FLOAT, PETSC_REAL, PETSC_LONG)
481 
482    Level: beginner
483 
484    Notes:
485    The textual name for each registered field must be unique.
486 
487 .seealso: DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
488 @*/
489 PETSC_EXTERN PetscErrorCode DMSwarmRegisterPetscDatatypeField(DM dm,const char fieldname[],PetscInt blocksize,PetscDataType type)
490 {
491   PetscErrorCode ierr;
492   DM_Swarm *swarm = (DM_Swarm*)dm->data;
493   size_t size;
494 
495   PetscFunctionBegin;
496   if (!swarm->field_registration_initialized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmInitializeFieldRegister() first");
497   if (swarm->field_registration_finalized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Cannot register additional fields after calling DMSwarmFinalizeFieldRegister() first");
498 
499   if (type == PETSC_OBJECT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
500   if (type == PETSC_FUNCTION) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
501   if (type == PETSC_STRING) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
502   if (type == PETSC_STRUCT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
503   if (type == PETSC_DATATYPE_UNKNOWN) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
504 
505   ierr = PetscDataTypeGetSize(type, &size);CHKERRQ(ierr);
506   /* Load a specific data type into data bucket, specifying textual name and its size in bytes */
507   ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterPetscDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
508   {
509     DataField gfield;
510 
511     ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
512     ierr = DataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
513   }
514   swarm->db->field[swarm->db->nfields-1]->petsc_type = type;
515   PetscFunctionReturn(0);
516 }
517 
518 /*@C
519    DMSwarmRegisterUserStructField - Register a user defined struct to a DMSwarm
520 
521    Collective on DM
522 
523    Input parameters:
524 +  dm - a DMSwarm
525 .  fieldname - the textual name to identify this field
526 -  size - the size in bytes of the user struct of each data type
527 
528    Level: beginner
529 
530    Notes:
531    The textual name for each registered field must be unique.
532 
533 .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserDatatypeField()
534 @*/
535 PETSC_EXTERN PetscErrorCode DMSwarmRegisterUserStructField(DM dm,const char fieldname[],size_t size)
536 {
537   PetscErrorCode ierr;
538   DM_Swarm *swarm = (DM_Swarm*)dm->data;
539 
540   PetscFunctionBegin;
541   ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterUserStructField",fieldname,size,NULL);CHKERRQ(ierr);
542   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_STRUCT ;
543   PetscFunctionReturn(0);
544 }
545 
546 /*@C
547    DMSwarmRegisterUserDatatypeField - Register a user defined data type to a DMSwarm
548 
549    Collective on DM
550 
551    Input parameters:
552 +  dm - a DMSwarm
553 .  fieldname - the textual name to identify this field
554 .  size - the size in bytes of the user data type
555 -  blocksize - the number of each data type
556 
557    Level: beginner
558 
559    Notes:
560    The textual name for each registered field must be unique.
561 
562 .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
563 @*/
564 PETSC_EXTERN PetscErrorCode DMSwarmRegisterUserDatatypeField(DM dm,const char fieldname[],size_t size,PetscInt blocksize)
565 {
566   DM_Swarm *swarm = (DM_Swarm*)dm->data;
567   PetscErrorCode ierr;
568 
569   PetscFunctionBegin;
570   ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterUserDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
571   {
572     DataField gfield;
573 
574     ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
575     ierr = DataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
576   }
577   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_DATATYPE_UNKNOWN;
578   PetscFunctionReturn(0);
579 }
580 
581 /*@C
582    DMSwarmGetField - Get access to the underlying array storing all entries associated with a registered field
583 
584    Not collective
585 
586    Input parameters:
587 +  dm - a DMSwarm
588 -  fieldname - the textual name to identify this field
589 
590    Output parameters:
591 +  blocksize - the number of each data type
592 .  type - the data type
593 -  data - pointer to raw array
594 
595    Level: beginner
596 
597    Notes:
598    The array must be returned using a matching call to DMSwarmRestoreField().
599 
600 .seealso: DMSwarmRestoreField()
601 @*/
602 PETSC_EXTERN PetscErrorCode DMSwarmGetField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
603 {
604   DM_Swarm *swarm = (DM_Swarm*)dm->data;
605   DataField gfield;
606   PetscErrorCode ierr;
607 
608   PetscFunctionBegin;
609   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
610   ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
611   ierr = DataFieldGetAccess(gfield);CHKERRQ(ierr);
612   ierr = DataFieldGetEntries(gfield,data);CHKERRQ(ierr);
613   if (blocksize) {*blocksize = gfield->bs; }
614   if (type) { *type = gfield->petsc_type; }
615   PetscFunctionReturn(0);
616 }
617 
618 /*@C
619    DMSwarmRestoreField - Restore access to the underlying array storing all entries associated with a registered field
620 
621    Not collective
622 
623    Input parameters:
624 +  dm - a DMSwarm
625 -  fieldname - the textual name to identify this field
626 
627    Output parameters:
628 +  blocksize - the number of each data type
629 .  type - the data type
630 -  data - pointer to raw array
631 
632    Level: beginner
633 
634    Notes:
635    The user must call DMSwarmGetField() prior to calling DMSwarmRestoreField().
636 
637 .seealso: DMSwarmGetField()
638 @*/
639 PETSC_EXTERN PetscErrorCode DMSwarmRestoreField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
640 {
641   DM_Swarm *swarm = (DM_Swarm*)dm->data;
642   DataField gfield;
643   PetscErrorCode ierr;
644 
645   PetscFunctionBegin;
646   ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
647   ierr = DataFieldRestoreAccess(gfield);CHKERRQ(ierr);
648   if (data) *data = NULL;
649   PetscFunctionReturn(0);
650 }
651 
652 /*@C
653    DMSwarmAddPoint - Add space for one new point in the DMSwarm
654 
655    Not collective
656 
657    Input parameter:
658 .  dm - a DMSwarm
659 
660    Level: beginner
661 
662    Notes:
663    The new point will have all fields initialized to zero.
664 
665 .seealso: DMSwarmAddNPoints()
666 @*/
667 PETSC_EXTERN PetscErrorCode DMSwarmAddPoint(DM dm)
668 {
669   DM_Swarm *swarm = (DM_Swarm*)dm->data;
670   PetscErrorCode ierr;
671 
672   PetscFunctionBegin;
673   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
674   ierr = DataBucketAddPoint(swarm->db);CHKERRQ(ierr);
675   PetscFunctionReturn(0);
676 }
677 
678 /*@C
679    DMSwarmAddNPoints - Add space for a number of new points in the DMSwarm
680 
681    Not collective
682 
683    Input parameters:
684 +  dm - a DMSwarm
685 -  npoints - the number of new points to add
686 
687    Level: beginner
688 
689    Notes:
690    The new point will have all fields initialized to zero.
691 
692 .seealso: DMSwarmAddPoint()
693 @*/
694 PETSC_EXTERN PetscErrorCode DMSwarmAddNPoints(DM dm,PetscInt npoints)
695 {
696   DM_Swarm *swarm = (DM_Swarm*)dm->data;
697   PetscErrorCode ierr;
698   PetscInt nlocal;
699 
700   PetscFunctionBegin;
701   ierr = DataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
702   nlocal = nlocal + npoints;
703   ierr = DataBucketSetSizes(swarm->db,nlocal,DATA_BUCKET_BUFFER_DEFAULT);CHKERRQ(ierr);
704   PetscFunctionReturn(0);
705 }
706 
707 /*@C
708    DMSwarmRemovePoint - Remove the last point from the DMSwarm
709 
710    Not collective
711 
712    Input parameter:
713 .  dm - a DMSwarm
714 
715    Level: beginner
716 
717 .seealso: DMSwarmRemovePointAtIndex()
718 @*/
719 PETSC_EXTERN PetscErrorCode DMSwarmRemovePoint(DM dm)
720 {
721   DM_Swarm *swarm = (DM_Swarm*)dm->data;
722   PetscErrorCode ierr;
723 
724   PetscFunctionBegin;
725   ierr = DataBucketRemovePoint(swarm->db);CHKERRQ(ierr);
726   PetscFunctionReturn(0);
727 }
728 
729 /*@C
730    DMSwarmRemovePointAtIndex - Removes a specific point from the DMSwarm
731 
732    Not collective
733 
734    Input parameters:
735 +  dm - a DMSwarm
736 -  idx - index of point to remove
737 
738    Level: beginner
739 
740 .seealso: DMSwarmRemovePoint()
741 @*/
742 PETSC_EXTERN PetscErrorCode DMSwarmRemovePointAtIndex(DM dm,PetscInt idx)
743 {
744   DM_Swarm *swarm = (DM_Swarm*)dm->data;
745   PetscErrorCode ierr;
746 
747   PetscFunctionBegin;
748   ierr = DataBucketRemovePointAtIndex(swarm->db,idx);CHKERRQ(ierr);
749   PetscFunctionReturn(0);
750 }
751 
752 PetscErrorCode DMSwarmMigrate_Basic(DM dm,PetscBool remove_sent_points)
753 {
754   PetscErrorCode ierr;
755 
756   PetscFunctionBegin;
757   ierr = DMSwarmMigrate_Push_Basic(dm,remove_sent_points);CHKERRQ(ierr);
758   PetscFunctionReturn(0);
759 }
760 
761 /*@C
762    DMSwarmMigrate - Relocates points defined in the DMSwarm to other MPI-ranks
763 
764    Collective on DM
765 
766    Input parameters:
767 +  dm - the DMSwarm
768 -  remove_sent_points - flag indicating if sent points should be removed from the current MPI-rank
769 
770    Notes:
771    The DM will be modified to accomodate received points.
772    If remove_sent_points = PETSC_TRUE, any points that were sent will be removed from the DM.
773    Different styles of migration are supported. See DMSwarmSetMigrateType().
774 
775    Level: advanced
776 
777 .seealso: DMSwarmSetMigrateType()
778 @*/
779 PETSC_EXTERN PetscErrorCode DMSwarmMigrate(DM dm,PetscBool remove_sent_points)
780 {
781   DM_Swarm *swarm = (DM_Swarm*)dm->data;
782   PetscErrorCode ierr;
783 
784   PetscFunctionBegin;
785   ierr = PetscLogEventBegin(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
786   switch (swarm->migrate_type) {
787     case DMSWARM_MIGRATE_BASIC:
788       ierr = DMSwarmMigrate_Basic(dm,remove_sent_points);CHKERRQ(ierr);
789       break;
790     case DMSWARM_MIGRATE_DMCELLNSCATTER:
791       ierr = DMSwarmMigrate_CellDMScatter(dm,remove_sent_points);CHKERRQ(ierr);
792       break;
793     case DMSWARM_MIGRATE_DMCELLEXACT:
794       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_DMCELLEXACT not implemented");
795       /*ierr = DMSwarmMigrate_CellDMExact(dm,remove_sent_points);CHKERRQ(ierr);*/
796       break;
797     case DMSWARM_MIGRATE_USER:
798       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_USER not implemented");
799       /*ierr = swarm->migrate(dm,remove_sent_points);CHKERRQ(ierr);*/
800       break;
801     default:
802       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE type unknown");
803       break;
804   }
805   ierr = PetscLogEventEnd(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
806   PetscFunctionReturn(0);
807 }
808 
809 PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm,PetscInt *globalsize);
810 
811 /*
812  DMSwarmCollectViewCreate
813 
814  * Applies a collection method and gathers point neighbour points into dm
815 
816  Notes:
817  Users should call DMSwarmCollectViewDestroy() after
818  they have finished computations associated with the collected points
819 */
820 
821 /*@C
822    DMSwarmCollectViewCreate - Applies a collection method and gathers points
823    in neighbour MPI-ranks into the DMSwarm
824 
825    Collective on DM
826 
827    Input parameter:
828 .  dm - the DMSwarm
829 
830    Notes:
831    Users should call DMSwarmCollectViewDestroy() after
832    they have finished computations associated with the collected points
833    Different collect methods are supported. See DMSwarmSetCollectType().
834 
835    Level: advanced
836 
837 .seealso: DMSwarmCollectViewDestroy(), DMSwarmSetCollectType()
838 @*/
839 PETSC_EXTERN PetscErrorCode DMSwarmCollectViewCreate(DM dm)
840 {
841   PetscErrorCode ierr;
842   DM_Swarm *swarm = (DM_Swarm*)dm->data;
843   PetscInt ng;
844 
845   PetscFunctionBegin;
846   if (swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView currently active");
847   ierr = DMSwarmGetLocalSize(dm,&ng);CHKERRQ(ierr);
848   switch (swarm->collect_type) {
849 
850     case DMSWARM_COLLECT_BASIC:
851       ierr = DMSwarmMigrate_GlobalToLocal_Basic(dm,&ng);CHKERRQ(ierr);
852       break;
853     case DMSWARM_COLLECT_DMDABOUNDINGBOX:
854       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_DMDABOUNDINGBOX not implemented");
855       /*ierr = DMSwarmCollect_DMDABoundingBox(dm,&ng);CHKERRQ(ierr);*/
856       break;
857     case DMSWARM_COLLECT_GENERAL:
858       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_GENERAL not implemented");
859       /*ierr = DMSwarmCollect_General(dm,..,,..,&ng);CHKERRQ(ierr);*/
860       break;
861     default:
862       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT type unknown");
863       break;
864   }
865   swarm->collect_view_active = PETSC_TRUE;
866   swarm->collect_view_reset_nlocal = ng;
867   PetscFunctionReturn(0);
868 }
869 
870 /*@C
871    DMSwarmCollectViewDestroy - Resets the DMSwarm to the size prior to calling DMSwarmCollectViewCreate()
872 
873    Collective on DM
874 
875    Input parameters:
876 .  dm - the DMSwarm
877 
878    Notes:
879    Users should call DMSwarmCollectViewCreate() before this function is called.
880 
881    Level: advanced
882 
883 .seealso: DMSwarmCollectViewCreate(), DMSwarmSetCollectType()
884 @*/
885 PETSC_EXTERN PetscErrorCode DMSwarmCollectViewDestroy(DM dm)
886 {
887   PetscErrorCode ierr;
888   DM_Swarm *swarm = (DM_Swarm*)dm->data;
889 
890   PetscFunctionBegin;
891   if (!swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView is currently not active");
892   ierr = DMSwarmSetLocalSizes(dm,swarm->collect_view_reset_nlocal,-1);CHKERRQ(ierr);
893   swarm->collect_view_active = PETSC_FALSE;
894   PetscFunctionReturn(0);
895 }
896 
897 PetscErrorCode DMSwarmSetUpPIC(DM dm)
898 {
899   PetscInt dim;
900   PetscErrorCode ierr;
901 
902   PetscFunctionBegin;
903   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
904   if (dim < 1) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
905   if (dim > 3) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
906   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_coor,dim,PETSC_DOUBLE);CHKERRQ(ierr);
907   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_cellid,1,PETSC_INT);CHKERRQ(ierr);
908   PetscFunctionReturn(0);
909 }
910 
911 /*@C
912    DMSwarmSetType - Set particular flavor of DMSwarm
913 
914    Collective on DM
915 
916    Input parameters:
917 +  dm - the DMSwarm
918 -  stype - the DMSwarm type (e.g. DMSWARM_PIC)
919 
920    Level: advanced
921 
922 .seealso: DMSwarmSetMigrateType(), DMSwarmSetCollectType()
923 @*/
924 PETSC_EXTERN PetscErrorCode DMSwarmSetType(DM dm,DMSwarmType stype)
925 {
926   DM_Swarm *swarm = (DM_Swarm*)dm->data;
927   PetscErrorCode ierr;
928 
929   PetscFunctionBegin;
930   swarm->swarm_type = stype;
931   if (swarm->swarm_type == DMSWARM_PIC) {
932     ierr = DMSwarmSetUpPIC(dm);CHKERRQ(ierr);
933   }
934   PetscFunctionReturn(0);
935 }
936 
937 PetscErrorCode DMSetup_Swarm(DM dm)
938 {
939   DM_Swarm *swarm = (DM_Swarm*)dm->data;
940   PetscErrorCode ierr;
941   PetscMPIInt rank;
942   PetscInt p,npoints,*rankval;
943 
944   PetscFunctionBegin;
945   if (swarm->issetup) PetscFunctionReturn(0);
946 
947   swarm->issetup = PETSC_TRUE;
948 
949   if (swarm->swarm_type == DMSWARM_PIC) {
950     /* check dmcell exists */
951     if (!swarm->dmcell) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires you call DMSwarmSetCellDM");
952 
953     if (swarm->dmcell->ops->locatepointssubdomain) {
954       /* check methods exists for exact ownership identificiation */
955       ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->ops->LocatePointsSubdomain\n");CHKERRQ(ierr);
956       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLEXACT;
957     } else {
958       /* check methods exist for point location AND rank neighbor identification */
959       if (swarm->dmcell->ops->locatepoints) {
960         ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->LocatePoints\n");CHKERRQ(ierr);
961       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->locatepoints be defined");
962 
963       if (swarm->dmcell->ops->getneighbors) {
964         ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->GetNeigbors\n");CHKERRQ(ierr);
965       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->getneighbors be defined");
966 
967       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLNSCATTER;
968     }
969   }
970 
971   ierr = DMSwarmFinalizeFieldRegister(dm);CHKERRQ(ierr);
972 
973   /* check some fields were registered */
974   if (swarm->db->nfields <= 2) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"At least one field user must be registered via DMSwarmRegisterXXX()");
975 
976   /* check local sizes were set */
977   if (swarm->db->L == -1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Local sizes must be set via DMSwarmSetLocalSizes()");
978 
979   /* initialize values in pid and rank placeholders */
980   /* TODO: [pid - use MPI_Scan] */
981   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
982   ierr = DataBucketGetSizes(swarm->db,&npoints,NULL,NULL);CHKERRQ(ierr);
983   ierr = DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
984   for (p=0; p<npoints; p++) {
985     rankval[p] = (PetscInt)rank;
986   }
987   ierr = DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
988   PetscFunctionReturn(0);
989 }
990 
991 extern PetscErrorCode DMSwarmSortDestroy(DMSwarmSort *_ctx);
992 
993 PetscErrorCode DMDestroy_Swarm(DM dm)
994 {
995   DM_Swarm *swarm = (DM_Swarm*)dm->data;
996   PetscErrorCode ierr;
997 
998   PetscFunctionBegin;
999   ierr = DataBucketDestroy(&swarm->db);CHKERRQ(ierr);
1000   if (swarm->sort_context) {
1001     ierr = DMSwarmSortDestroy(&swarm->sort_context);CHKERRQ(ierr);
1002   }
1003   ierr = PetscFree(swarm);CHKERRQ(ierr);
1004   PetscFunctionReturn(0);
1005 }
1006 
1007 PetscErrorCode DMSwarmView_Draw(DM dm, PetscViewer viewer)
1008 {
1009   DM             cdm;
1010   PetscDraw      draw;
1011   PetscReal     *coords, oldPause;
1012   PetscInt       Np, p, bs;
1013   PetscErrorCode ierr;
1014 
1015   PetscFunctionBegin;
1016   ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr);
1017   ierr = DMSwarmGetCellDM(dm, &cdm);CHKERRQ(ierr);
1018   ierr = PetscDrawGetPause(draw, &oldPause);CHKERRQ(ierr);
1019   ierr = PetscDrawSetPause(draw, 0.0);CHKERRQ(ierr);
1020   ierr = DMView(cdm, viewer);CHKERRQ(ierr);
1021   ierr = PetscDrawSetPause(draw, oldPause);CHKERRQ(ierr);
1022 
1023   ierr = DMSwarmGetLocalSize(dm, &Np);CHKERRQ(ierr);
1024   ierr = DMSwarmGetField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1025   for (p = 0; p < Np; ++p) {
1026     const PetscInt i = p*bs;
1027 
1028     ierr = PetscDrawEllipse(draw, coords[i], coords[i+1], 0.01, 0.01, PETSC_DRAW_BLUE);CHKERRQ(ierr);
1029   }
1030   ierr = DMSwarmRestoreField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1031   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
1032   ierr = PetscDrawPause(draw);CHKERRQ(ierr);
1033   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
1034   PetscFunctionReturn(0);
1035 }
1036 
1037 PetscErrorCode DMView_Swarm(DM dm, PetscViewer viewer)
1038 {
1039   DM_Swarm *swarm = (DM_Swarm*)dm->data;
1040   PetscBool      iascii,ibinary,ishdf5,isvtk,isdraw;
1041   PetscErrorCode ierr;
1042 
1043   PetscFunctionBegin;
1044   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1045   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
1046   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
1047   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY,&ibinary);CHKERRQ(ierr);
1048   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK,   &isvtk);CHKERRQ(ierr);
1049   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
1050   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW,  &isdraw);CHKERRQ(ierr);
1051   if (iascii) {
1052     ierr = DataBucketView(PetscObjectComm((PetscObject)dm),swarm->db,NULL,DATABUCKET_VIEW_STDOUT);CHKERRQ(ierr);
1053   } else if (ibinary) {
1054     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO Binary support");
1055   } else if (ishdf5) {
1056 #if defined(PETSC_HAVE_HDF5)
1057     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO HDF5 support");
1058 #else
1059     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"HDF5 not supported. Please reconfigure using --download-hdf5");
1060 #endif
1061   } else if (isvtk) {
1062     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO VTK support");
1063   } else if (isdraw) {
1064     ierr = DMSwarmView_Draw(dm, viewer);CHKERRQ(ierr);
1065   }
1066   PetscFunctionReturn(0);
1067 }
1068 
1069 /*MC
1070 
1071  DMSWARM = "swarm" - A DM object used to represent arrays of data (fields) of arbitrary data type.
1072  This implementation was designed for particle methods in which the underlying
1073  data required to be represented is both (i) dynamic in length, (ii) and of arbitrary data type.
1074 
1075  User data can be represented by DMSwarm through a registering "fields".
1076  To register a field, the user must provide;
1077  (a) a unique name;
1078  (b) the data type (or size in bytes);
1079  (c) the block size of the data.
1080 
1081  For example, suppose the application requires a unique id, energy, momentum and density to be stored
1082  on a set of of particles. Then the following code could be used
1083 
1084 $    DMSwarmInitializeFieldRegister(dm)
1085 $    DMSwarmRegisterPetscDatatypeField(dm,"uid",1,PETSC_LONG);
1086 $    DMSwarmRegisterPetscDatatypeField(dm,"energy",1,PETSC_REAL);
1087 $    DMSwarmRegisterPetscDatatypeField(dm,"momentum",3,PETSC_REAL);
1088 $    DMSwarmRegisterPetscDatatypeField(dm,"density",1,PETSC_FLOAT);
1089 $    DMSwarmFinalizeFieldRegister(dm)
1090 
1091  The fields represented by DMSwarm are dynamic and can be re-sized at any time.
1092  The only restriction imposed by DMSwarm is that all fields contain the same number of points.
1093 
1094  To support particle methods, "migration" techniques are provided. These methods migrate data
1095  between MPI-ranks.
1096 
1097  DMSwarm supports the methods DMCreateGlobalVector() and DMCreateLocalVector().
1098  As a DMSwarm may internally define and store values of different data types,
1099  before calling DMCreateGlobalVector() or DMCreateLocalVector(), the user must inform DMSwarm which
1100  fields should be used to define a Vec object via
1101    DMSwarmVectorDefineField()
1102  The specified field can can changed be changed at any time - thereby permitting vectors
1103  compatable with different fields to be created.
1104 
1105  A dual representation of fields in the DMSwarm and a Vec object is permitted via
1106    DMSwarmCreateGlobalVectorFromField()
1107  Here the data defining the field in the DMSwarm is shared with a Vec.
1108  This is inherently unsafe if you alter the size of the field at any time between
1109  calls to DMSwarmCreateGlobalVectorFromField() and DMSwarmDestroyGlobalVectorFromField().
1110  If the local size of the DMSwarm does not match the local size of the global vector
1111  when DMSwarmDestroyGlobalVectorFromField() is called, an error is thrown.
1112 
1113  Additional high-level support is provided for Particle-In-Cell methods.
1114  Please refer to the man page for DMSwarmSetType().
1115 
1116  Level: beginner
1117 
1118 .seealso: DMType, DMCreate(), DMSetType()
1119 M*/
1120 PETSC_EXTERN PetscErrorCode DMCreate_Swarm(DM dm)
1121 {
1122   DM_Swarm      *swarm;
1123   PetscErrorCode ierr;
1124 
1125   PetscFunctionBegin;
1126   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1127   ierr     = PetscNewLog(dm,&swarm);CHKERRQ(ierr);
1128   dm->data = swarm;
1129 
1130   ierr = DataBucketCreate(&swarm->db);CHKERRQ(ierr);
1131   ierr = DMSwarmInitializeFieldRegister(dm);CHKERRQ(ierr);
1132 
1133   swarm->vec_field_set = PETSC_FALSE;
1134   swarm->issetup = PETSC_FALSE;
1135   swarm->swarm_type = DMSWARM_BASIC;
1136   swarm->migrate_type = DMSWARM_MIGRATE_BASIC;
1137   swarm->collect_type = DMSWARM_COLLECT_BASIC;
1138   swarm->migrate_error_on_missing_point = PETSC_FALSE;
1139 
1140   swarm->dmcell = NULL;
1141   swarm->collect_view_active = PETSC_FALSE;
1142   swarm->collect_view_reset_nlocal = -1;
1143 
1144   dm->dim  = 0;
1145   dm->ops->view                            = DMView_Swarm;
1146   dm->ops->load                            = NULL;
1147   dm->ops->setfromoptions                  = NULL;
1148   dm->ops->clone                           = NULL;
1149   dm->ops->setup                           = DMSetup_Swarm;
1150   dm->ops->createdefaultsection            = NULL;
1151   dm->ops->createdefaultconstraints        = NULL;
1152   dm->ops->createglobalvector              = DMCreateGlobalVector_Swarm;
1153   dm->ops->createlocalvector               = DMCreateLocalVector_Swarm;
1154   dm->ops->getlocaltoglobalmapping         = NULL;
1155   dm->ops->createfieldis                   = NULL;
1156   dm->ops->createcoordinatedm              = NULL;
1157   dm->ops->getcoloring                     = NULL;
1158   dm->ops->creatematrix                    = NULL;
1159   dm->ops->createinterpolation             = NULL;
1160   dm->ops->getaggregates                   = NULL;
1161   dm->ops->getinjection                    = NULL;
1162   dm->ops->refine                          = NULL;
1163   dm->ops->coarsen                         = NULL;
1164   dm->ops->refinehierarchy                 = NULL;
1165   dm->ops->coarsenhierarchy                = NULL;
1166   dm->ops->globaltolocalbegin              = NULL;
1167   dm->ops->globaltolocalend                = NULL;
1168   dm->ops->localtoglobalbegin              = NULL;
1169   dm->ops->localtoglobalend                = NULL;
1170   dm->ops->destroy                         = DMDestroy_Swarm;
1171   dm->ops->createsubdm                     = NULL;
1172   dm->ops->getdimpoints                    = NULL;
1173   dm->ops->locatepoints                    = NULL;
1174   PetscFunctionReturn(0);
1175 }
1176