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