xref: /petsc/src/dm/impls/swarm/swarm.c (revision 3d96e9964ff330fd2a9eee374bcd4376da7efe60)
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, DMSWARM_SetSizes, DMSWARM_AddPoints, DMSWARM_RemovePoints, DMSWARM_Sort;
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 = PetscLogEventBegin(DMSWARM_SetSizes,0,0,0,0);CHKERRQ(ierr);
362   ierr = DataBucketSetSizes(swarm->db,nlocal,buffer);CHKERRQ(ierr);
363   ierr = PetscLogEventEnd(DMSWARM_SetSizes,0,0,0,0);CHKERRQ(ierr);
364   PetscFunctionReturn(0);
365 }
366 
367 /*@C
368    DMSwarmSetCellDM - Attachs a DM to a DMSwarm
369 
370    Collective on DM
371 
372    Input parameters:
373 +  dm - a DMSwarm
374 -  dmcell - the DM to attach to the DMSwarm
375 
376    Level: beginner
377 
378    Notes:
379    The attached DM (dmcell) will be queried for point location and
380    neighbor MPI-rank information if DMSwarmMigrate() is called.
381 
382 .seealso: DMSwarmSetType(), DMSwarmGetCellDM(), DMSwarmMigrate()
383 @*/
384 PETSC_EXTERN PetscErrorCode DMSwarmSetCellDM(DM dm,DM dmcell)
385 {
386   DM_Swarm *swarm = (DM_Swarm*)dm->data;
387 
388   PetscFunctionBegin;
389   swarm->dmcell = dmcell;
390   PetscFunctionReturn(0);
391 }
392 
393 /*@C
394    DMSwarmGetCellDM - Fetches the attached cell DM
395 
396    Collective on DM
397 
398    Input parameter:
399 .  dm - a DMSwarm
400 
401    Output parameter:
402 .  dmcell - the DM which was attached to the DMSwarm
403 
404    Level: beginner
405 
406 .seealso: DMSwarmSetCellDM()
407 @*/
408 PETSC_EXTERN PetscErrorCode DMSwarmGetCellDM(DM dm,DM *dmcell)
409 {
410   DM_Swarm *swarm = (DM_Swarm*)dm->data;
411 
412   PetscFunctionBegin;
413   *dmcell = swarm->dmcell;
414   PetscFunctionReturn(0);
415 }
416 
417 /*@C
418    DMSwarmGetLocalSize - Retrives the local length of fields registered
419 
420    Not collective
421 
422    Input parameter:
423 .  dm - a DMSwarm
424 
425    Output parameter:
426 .  nlocal - the length of each registered field
427 
428    Level: beginner
429 
430 .seealso: DMSwarmGetSize(), DMSwarmSetLocalSizes()
431 @*/
432 PETSC_EXTERN PetscErrorCode DMSwarmGetLocalSize(DM dm,PetscInt *nlocal)
433 {
434   DM_Swarm *swarm = (DM_Swarm*)dm->data;
435   PetscErrorCode ierr;
436 
437   PetscFunctionBegin;
438   if (nlocal) {ierr = DataBucketGetSizes(swarm->db,nlocal,NULL,NULL);CHKERRQ(ierr);}
439   PetscFunctionReturn(0);
440 }
441 
442 /*@C
443    DMSwarmGetSize - Retrives the total length of fields registered
444 
445    Collective on DM
446 
447    Input parameter:
448 .  dm - a DMSwarm
449 
450    Output parameter:
451 .  n - the total length of each registered field
452 
453    Level: beginner
454 
455    Note:
456    This calls MPI_Allreduce upon each call (inefficient but safe)
457 
458 .seealso: DMSwarmGetLocalSize(), DMSwarmSetLocalSizes()
459 @*/
460 PETSC_EXTERN PetscErrorCode DMSwarmGetSize(DM dm,PetscInt *n)
461 {
462   DM_Swarm *swarm = (DM_Swarm*)dm->data;
463   PetscErrorCode ierr;
464   PetscInt nlocal,ng;
465 
466   PetscFunctionBegin;
467   ierr = DataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
468   ierr = MPI_Allreduce(&nlocal,&ng,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
469   if (n) { *n = ng; }
470   PetscFunctionReturn(0);
471 }
472 
473 /*@C
474    DMSwarmRegisterPetscDatatypeField - Register a field to a DMSwarm with a native PETSc data type
475 
476    Collective on DM
477 
478    Input parameters:
479 +  dm - a DMSwarm
480 .  fieldname - the textual name to identify this field
481 .  blocksize - the number of each data type
482 -  type - a valid PETSc data type (PETSC_CHAR, PETSC_SHORT, PETSC_INT, PETSC_FLOAT, PETSC_REAL, PETSC_LONG)
483 
484    Level: beginner
485 
486    Notes:
487    The textual name for each registered field must be unique.
488 
489 .seealso: DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
490 @*/
491 PETSC_EXTERN PetscErrorCode DMSwarmRegisterPetscDatatypeField(DM dm,const char fieldname[],PetscInt blocksize,PetscDataType type)
492 {
493   PetscErrorCode ierr;
494   DM_Swarm *swarm = (DM_Swarm*)dm->data;
495   size_t size;
496 
497   PetscFunctionBegin;
498   if (!swarm->field_registration_initialized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmInitializeFieldRegister() first");
499   if (swarm->field_registration_finalized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Cannot register additional fields after calling DMSwarmFinalizeFieldRegister() first");
500 
501   if (type == PETSC_OBJECT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
502   if (type == PETSC_FUNCTION) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
503   if (type == PETSC_STRING) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
504   if (type == PETSC_STRUCT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
505   if (type == PETSC_DATATYPE_UNKNOWN) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
506 
507   ierr = PetscDataTypeGetSize(type, &size);CHKERRQ(ierr);
508   /* Load a specific data type into data bucket, specifying textual name and its size in bytes */
509   ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterPetscDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
510   {
511     DataField gfield;
512 
513     ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
514     ierr = DataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
515   }
516   swarm->db->field[swarm->db->nfields-1]->petsc_type = type;
517   PetscFunctionReturn(0);
518 }
519 
520 /*@C
521    DMSwarmRegisterUserStructField - Register a user defined struct to a DMSwarm
522 
523    Collective on DM
524 
525    Input parameters:
526 +  dm - a DMSwarm
527 .  fieldname - the textual name to identify this field
528 -  size - the size in bytes of the user struct of each data type
529 
530    Level: beginner
531 
532    Notes:
533    The textual name for each registered field must be unique.
534 
535 .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserDatatypeField()
536 @*/
537 PETSC_EXTERN PetscErrorCode DMSwarmRegisterUserStructField(DM dm,const char fieldname[],size_t size)
538 {
539   PetscErrorCode ierr;
540   DM_Swarm *swarm = (DM_Swarm*)dm->data;
541 
542   PetscFunctionBegin;
543   ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterUserStructField",fieldname,size,NULL);CHKERRQ(ierr);
544   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_STRUCT ;
545   PetscFunctionReturn(0);
546 }
547 
548 /*@C
549    DMSwarmRegisterUserDatatypeField - Register a user defined data type to a DMSwarm
550 
551    Collective on DM
552 
553    Input parameters:
554 +  dm - a DMSwarm
555 .  fieldname - the textual name to identify this field
556 .  size - the size in bytes of the user data type
557 -  blocksize - the number of each data type
558 
559    Level: beginner
560 
561    Notes:
562    The textual name for each registered field must be unique.
563 
564 .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
565 @*/
566 PETSC_EXTERN PetscErrorCode DMSwarmRegisterUserDatatypeField(DM dm,const char fieldname[],size_t size,PetscInt blocksize)
567 {
568   DM_Swarm *swarm = (DM_Swarm*)dm->data;
569   PetscErrorCode ierr;
570 
571   PetscFunctionBegin;
572   ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterUserDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
573   {
574     DataField gfield;
575 
576     ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
577     ierr = DataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
578   }
579   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_DATATYPE_UNKNOWN;
580   PetscFunctionReturn(0);
581 }
582 
583 /*@C
584    DMSwarmGetField - Get access to the underlying array storing all entries associated with a registered field
585 
586    Not collective
587 
588    Input parameters:
589 +  dm - a DMSwarm
590 -  fieldname - the textual name to identify this field
591 
592    Output parameters:
593 +  blocksize - the number of each data type
594 .  type - the data type
595 -  data - pointer to raw array
596 
597    Level: beginner
598 
599    Notes:
600    The array must be returned using a matching call to DMSwarmRestoreField().
601 
602 .seealso: DMSwarmRestoreField()
603 @*/
604 PETSC_EXTERN PetscErrorCode DMSwarmGetField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
605 {
606   DM_Swarm *swarm = (DM_Swarm*)dm->data;
607   DataField gfield;
608   PetscErrorCode ierr;
609 
610   PetscFunctionBegin;
611   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
612   ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
613   ierr = DataFieldGetAccess(gfield);CHKERRQ(ierr);
614   ierr = DataFieldGetEntries(gfield,data);CHKERRQ(ierr);
615   if (blocksize) {*blocksize = gfield->bs; }
616   if (type) { *type = gfield->petsc_type; }
617   PetscFunctionReturn(0);
618 }
619 
620 /*@C
621    DMSwarmRestoreField - Restore access to the underlying array storing all entries associated with a registered field
622 
623    Not collective
624 
625    Input parameters:
626 +  dm - a DMSwarm
627 -  fieldname - the textual name to identify this field
628 
629    Output parameters:
630 +  blocksize - the number of each data type
631 .  type - the data type
632 -  data - pointer to raw array
633 
634    Level: beginner
635 
636    Notes:
637    The user must call DMSwarmGetField() prior to calling DMSwarmRestoreField().
638 
639 .seealso: DMSwarmGetField()
640 @*/
641 PETSC_EXTERN PetscErrorCode DMSwarmRestoreField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
642 {
643   DM_Swarm *swarm = (DM_Swarm*)dm->data;
644   DataField gfield;
645   PetscErrorCode ierr;
646 
647   PetscFunctionBegin;
648   ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
649   ierr = DataFieldRestoreAccess(gfield);CHKERRQ(ierr);
650   if (data) *data = NULL;
651   PetscFunctionReturn(0);
652 }
653 
654 /*@C
655    DMSwarmAddPoint - Add space for one new point in the DMSwarm
656 
657    Not collective
658 
659    Input parameter:
660 .  dm - a DMSwarm
661 
662    Level: beginner
663 
664    Notes:
665    The new point will have all fields initialized to zero.
666 
667 .seealso: DMSwarmAddNPoints()
668 @*/
669 PETSC_EXTERN PetscErrorCode DMSwarmAddPoint(DM dm)
670 {
671   DM_Swarm *swarm = (DM_Swarm*)dm->data;
672   PetscErrorCode ierr;
673 
674   PetscFunctionBegin;
675   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
676   ierr = PetscLogEventBegin(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
677   ierr = DataBucketAddPoint(swarm->db);CHKERRQ(ierr);
678   ierr = PetscLogEventEnd(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
679   PetscFunctionReturn(0);
680 }
681 
682 /*@C
683    DMSwarmAddNPoints - Add space for a number of new points in the DMSwarm
684 
685    Not collective
686 
687    Input parameters:
688 +  dm - a DMSwarm
689 -  npoints - the number of new points to add
690 
691    Level: beginner
692 
693    Notes:
694    The new point will have all fields initialized to zero.
695 
696 .seealso: DMSwarmAddPoint()
697 @*/
698 PETSC_EXTERN PetscErrorCode DMSwarmAddNPoints(DM dm,PetscInt npoints)
699 {
700   DM_Swarm *swarm = (DM_Swarm*)dm->data;
701   PetscErrorCode ierr;
702   PetscInt nlocal;
703 
704   PetscFunctionBegin;
705   ierr = PetscLogEventBegin(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
706   ierr = DataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
707   nlocal = nlocal + npoints;
708   ierr = DataBucketSetSizes(swarm->db,nlocal,DATA_BUCKET_BUFFER_DEFAULT);CHKERRQ(ierr);
709   ierr = PetscLogEventEnd(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
710   PetscFunctionReturn(0);
711 }
712 
713 /*@C
714    DMSwarmRemovePoint - Remove the last point from the DMSwarm
715 
716    Not collective
717 
718    Input parameter:
719 .  dm - a DMSwarm
720 
721    Level: beginner
722 
723 .seealso: DMSwarmRemovePointAtIndex()
724 @*/
725 PETSC_EXTERN PetscErrorCode DMSwarmRemovePoint(DM dm)
726 {
727   DM_Swarm *swarm = (DM_Swarm*)dm->data;
728   PetscErrorCode ierr;
729 
730   PetscFunctionBegin;
731   ierr = PetscLogEventBegin(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
732   ierr = DataBucketRemovePoint(swarm->db);CHKERRQ(ierr);
733   ierr = PetscLogEventEnd(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
734   PetscFunctionReturn(0);
735 }
736 
737 /*@C
738    DMSwarmRemovePointAtIndex - Removes a specific point from the DMSwarm
739 
740    Not collective
741 
742    Input parameters:
743 +  dm - a DMSwarm
744 -  idx - index of point to remove
745 
746    Level: beginner
747 
748 .seealso: DMSwarmRemovePoint()
749 @*/
750 PETSC_EXTERN PetscErrorCode DMSwarmRemovePointAtIndex(DM dm,PetscInt idx)
751 {
752   DM_Swarm *swarm = (DM_Swarm*)dm->data;
753   PetscErrorCode ierr;
754 
755   PetscFunctionBegin;
756   ierr = PetscLogEventBegin(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
757   ierr = DataBucketRemovePointAtIndex(swarm->db,idx);CHKERRQ(ierr);
758   ierr = PetscLogEventEnd(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
759   PetscFunctionReturn(0);
760 }
761 
762 /*@C
763    DMSwarmCopyPoint - Copy point pj to point pi in the DMSwarm
764 
765    Not collective
766 
767    Input parameters:
768 +  dm - a DMSwarm
769 .  pi - the index of the point to copy
770 -  pj - the point index where the copy should be located
771 
772  Level: beginner
773 
774 .seealso: DMSwarmRemovePoint()
775 @*/
776 PETSC_EXTERN PetscErrorCode DMSwarmCopyPoint(DM dm,PetscInt pi,PetscInt pj)
777 {
778   DM_Swarm *swarm = (DM_Swarm*)dm->data;
779   PetscErrorCode ierr;
780 
781   PetscFunctionBegin;
782   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
783   ierr = DataBucketCopyPoint(swarm->db,pi,swarm->db,pj);CHKERRQ(ierr);
784   PetscFunctionReturn(0);
785 }
786 
787 PetscErrorCode DMSwarmMigrate_Basic(DM dm,PetscBool remove_sent_points)
788 {
789   PetscErrorCode ierr;
790 
791   PetscFunctionBegin;
792   ierr = DMSwarmMigrate_Push_Basic(dm,remove_sent_points);CHKERRQ(ierr);
793   PetscFunctionReturn(0);
794 }
795 
796 /*@C
797    DMSwarmMigrate - Relocates points defined in the DMSwarm to other MPI-ranks
798 
799    Collective on DM
800 
801    Input parameters:
802 +  dm - the DMSwarm
803 -  remove_sent_points - flag indicating if sent points should be removed from the current MPI-rank
804 
805    Notes:
806    The DM will be modified to accomodate received points.
807    If remove_sent_points = PETSC_TRUE, any points that were sent will be removed from the DM.
808    Different styles of migration are supported. See DMSwarmSetMigrateType().
809 
810    Level: advanced
811 
812 .seealso: DMSwarmSetMigrateType()
813 @*/
814 PETSC_EXTERN PetscErrorCode DMSwarmMigrate(DM dm,PetscBool remove_sent_points)
815 {
816   DM_Swarm *swarm = (DM_Swarm*)dm->data;
817   PetscErrorCode ierr;
818 
819   PetscFunctionBegin;
820   ierr = PetscLogEventBegin(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
821   switch (swarm->migrate_type) {
822     case DMSWARM_MIGRATE_BASIC:
823       ierr = DMSwarmMigrate_Basic(dm,remove_sent_points);CHKERRQ(ierr);
824       break;
825     case DMSWARM_MIGRATE_DMCELLNSCATTER:
826       ierr = DMSwarmMigrate_CellDMScatter(dm,remove_sent_points);CHKERRQ(ierr);
827       break;
828     case DMSWARM_MIGRATE_DMCELLEXACT:
829       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_DMCELLEXACT not implemented");
830       /*ierr = DMSwarmMigrate_CellDMExact(dm,remove_sent_points);CHKERRQ(ierr);*/
831       break;
832     case DMSWARM_MIGRATE_USER:
833       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_USER not implemented");
834       /*ierr = swarm->migrate(dm,remove_sent_points);CHKERRQ(ierr);*/
835       break;
836     default:
837       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE type unknown");
838       break;
839   }
840   ierr = PetscLogEventEnd(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
841   PetscFunctionReturn(0);
842 }
843 
844 PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm,PetscInt *globalsize);
845 
846 /*
847  DMSwarmCollectViewCreate
848 
849  * Applies a collection method and gathers point neighbour points into dm
850 
851  Notes:
852  Users should call DMSwarmCollectViewDestroy() after
853  they have finished computations associated with the collected points
854 */
855 
856 /*@C
857    DMSwarmCollectViewCreate - Applies a collection method and gathers points
858    in neighbour MPI-ranks into the DMSwarm
859 
860    Collective on DM
861 
862    Input parameter:
863 .  dm - the DMSwarm
864 
865    Notes:
866    Users should call DMSwarmCollectViewDestroy() after
867    they have finished computations associated with the collected points
868    Different collect methods are supported. See DMSwarmSetCollectType().
869 
870    Level: advanced
871 
872 .seealso: DMSwarmCollectViewDestroy(), DMSwarmSetCollectType()
873 @*/
874 PETSC_EXTERN PetscErrorCode DMSwarmCollectViewCreate(DM dm)
875 {
876   PetscErrorCode ierr;
877   DM_Swarm *swarm = (DM_Swarm*)dm->data;
878   PetscInt ng;
879 
880   PetscFunctionBegin;
881   if (swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView currently active");
882   ierr = DMSwarmGetLocalSize(dm,&ng);CHKERRQ(ierr);
883   switch (swarm->collect_type) {
884 
885     case DMSWARM_COLLECT_BASIC:
886       ierr = DMSwarmMigrate_GlobalToLocal_Basic(dm,&ng);CHKERRQ(ierr);
887       break;
888     case DMSWARM_COLLECT_DMDABOUNDINGBOX:
889       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_DMDABOUNDINGBOX not implemented");
890       /*ierr = DMSwarmCollect_DMDABoundingBox(dm,&ng);CHKERRQ(ierr);*/
891       break;
892     case DMSWARM_COLLECT_GENERAL:
893       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_GENERAL not implemented");
894       /*ierr = DMSwarmCollect_General(dm,..,,..,&ng);CHKERRQ(ierr);*/
895       break;
896     default:
897       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT type unknown");
898       break;
899   }
900   swarm->collect_view_active = PETSC_TRUE;
901   swarm->collect_view_reset_nlocal = ng;
902   PetscFunctionReturn(0);
903 }
904 
905 /*@C
906    DMSwarmCollectViewDestroy - Resets the DMSwarm to the size prior to calling DMSwarmCollectViewCreate()
907 
908    Collective on DM
909 
910    Input parameters:
911 .  dm - the DMSwarm
912 
913    Notes:
914    Users should call DMSwarmCollectViewCreate() before this function is called.
915 
916    Level: advanced
917 
918 .seealso: DMSwarmCollectViewCreate(), DMSwarmSetCollectType()
919 @*/
920 PETSC_EXTERN PetscErrorCode DMSwarmCollectViewDestroy(DM dm)
921 {
922   PetscErrorCode ierr;
923   DM_Swarm *swarm = (DM_Swarm*)dm->data;
924 
925   PetscFunctionBegin;
926   if (!swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView is currently not active");
927   ierr = DMSwarmSetLocalSizes(dm,swarm->collect_view_reset_nlocal,-1);CHKERRQ(ierr);
928   swarm->collect_view_active = PETSC_FALSE;
929   PetscFunctionReturn(0);
930 }
931 
932 PetscErrorCode DMSwarmSetUpPIC(DM dm)
933 {
934   PetscInt dim;
935   PetscErrorCode ierr;
936 
937   PetscFunctionBegin;
938   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
939   if (dim < 1) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
940   if (dim > 3) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
941   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_coor,dim,PETSC_DOUBLE);CHKERRQ(ierr);
942   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_cellid,1,PETSC_INT);CHKERRQ(ierr);
943   PetscFunctionReturn(0);
944 }
945 
946 /*@C
947    DMSwarmSetType - Set particular flavor of DMSwarm
948 
949    Collective on DM
950 
951    Input parameters:
952 +  dm - the DMSwarm
953 -  stype - the DMSwarm type (e.g. DMSWARM_PIC)
954 
955    Level: advanced
956 
957 .seealso: DMSwarmSetMigrateType(), DMSwarmSetCollectType()
958 @*/
959 PETSC_EXTERN PetscErrorCode DMSwarmSetType(DM dm,DMSwarmType stype)
960 {
961   DM_Swarm *swarm = (DM_Swarm*)dm->data;
962   PetscErrorCode ierr;
963 
964   PetscFunctionBegin;
965   swarm->swarm_type = stype;
966   if (swarm->swarm_type == DMSWARM_PIC) {
967     ierr = DMSwarmSetUpPIC(dm);CHKERRQ(ierr);
968   }
969   PetscFunctionReturn(0);
970 }
971 
972 PetscErrorCode DMSetup_Swarm(DM dm)
973 {
974   DM_Swarm *swarm = (DM_Swarm*)dm->data;
975   PetscErrorCode ierr;
976   PetscMPIInt rank;
977   PetscInt p,npoints,*rankval;
978 
979   PetscFunctionBegin;
980   if (swarm->issetup) PetscFunctionReturn(0);
981 
982   swarm->issetup = PETSC_TRUE;
983 
984   if (swarm->swarm_type == DMSWARM_PIC) {
985     /* check dmcell exists */
986     if (!swarm->dmcell) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires you call DMSwarmSetCellDM");
987 
988     if (swarm->dmcell->ops->locatepointssubdomain) {
989       /* check methods exists for exact ownership identificiation */
990       ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->ops->LocatePointsSubdomain\n");CHKERRQ(ierr);
991       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLEXACT;
992     } else {
993       /* check methods exist for point location AND rank neighbor identification */
994       if (swarm->dmcell->ops->locatepoints) {
995         ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->LocatePoints\n");CHKERRQ(ierr);
996       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->locatepoints be defined");
997 
998       if (swarm->dmcell->ops->getneighbors) {
999         ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->GetNeigbors\n");CHKERRQ(ierr);
1000       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->getneighbors be defined");
1001 
1002       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLNSCATTER;
1003     }
1004   }
1005 
1006   ierr = DMSwarmFinalizeFieldRegister(dm);CHKERRQ(ierr);
1007 
1008   /* check some fields were registered */
1009   if (swarm->db->nfields <= 2) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"At least one field user must be registered via DMSwarmRegisterXXX()");
1010 
1011   /* check local sizes were set */
1012   if (swarm->db->L == -1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Local sizes must be set via DMSwarmSetLocalSizes()");
1013 
1014   /* initialize values in pid and rank placeholders */
1015   /* TODO: [pid - use MPI_Scan] */
1016   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
1017   ierr = DataBucketGetSizes(swarm->db,&npoints,NULL,NULL);CHKERRQ(ierr);
1018   ierr = DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
1019   for (p=0; p<npoints; p++) {
1020     rankval[p] = (PetscInt)rank;
1021   }
1022   ierr = DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
1023   PetscFunctionReturn(0);
1024 }
1025 
1026 extern PetscErrorCode DMSwarmSortDestroy(DMSwarmSort *_ctx);
1027 
1028 PetscErrorCode DMDestroy_Swarm(DM dm)
1029 {
1030   DM_Swarm *swarm = (DM_Swarm*)dm->data;
1031   PetscErrorCode ierr;
1032 
1033   PetscFunctionBegin;
1034   ierr = DataBucketDestroy(&swarm->db);CHKERRQ(ierr);
1035   if (swarm->sort_context) {
1036     ierr = DMSwarmSortDestroy(&swarm->sort_context);CHKERRQ(ierr);
1037   }
1038   ierr = PetscFree(swarm);CHKERRQ(ierr);
1039   PetscFunctionReturn(0);
1040 }
1041 
1042 PetscErrorCode DMSwarmView_Draw(DM dm, PetscViewer viewer)
1043 {
1044   DM             cdm;
1045   PetscDraw      draw;
1046   PetscReal     *coords, oldPause;
1047   PetscInt       Np, p, bs;
1048   PetscErrorCode ierr;
1049 
1050   PetscFunctionBegin;
1051   ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr);
1052   ierr = DMSwarmGetCellDM(dm, &cdm);CHKERRQ(ierr);
1053   ierr = PetscDrawGetPause(draw, &oldPause);CHKERRQ(ierr);
1054   ierr = PetscDrawSetPause(draw, 0.0);CHKERRQ(ierr);
1055   ierr = DMView(cdm, viewer);CHKERRQ(ierr);
1056   ierr = PetscDrawSetPause(draw, oldPause);CHKERRQ(ierr);
1057 
1058   ierr = DMSwarmGetLocalSize(dm, &Np);CHKERRQ(ierr);
1059   ierr = DMSwarmGetField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1060   for (p = 0; p < Np; ++p) {
1061     const PetscInt i = p*bs;
1062 
1063     ierr = PetscDrawEllipse(draw, coords[i], coords[i+1], 0.01, 0.01, PETSC_DRAW_BLUE);CHKERRQ(ierr);
1064   }
1065   ierr = DMSwarmRestoreField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1066   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
1067   ierr = PetscDrawPause(draw);CHKERRQ(ierr);
1068   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
1069   PetscFunctionReturn(0);
1070 }
1071 
1072 PetscErrorCode DMView_Swarm(DM dm, PetscViewer viewer)
1073 {
1074   DM_Swarm *swarm = (DM_Swarm*)dm->data;
1075   PetscBool      iascii,ibinary,ishdf5,isvtk,isdraw;
1076   PetscErrorCode ierr;
1077 
1078   PetscFunctionBegin;
1079   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1080   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
1081   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
1082   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY,&ibinary);CHKERRQ(ierr);
1083   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK,   &isvtk);CHKERRQ(ierr);
1084   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
1085   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW,  &isdraw);CHKERRQ(ierr);
1086   if (iascii) {
1087     ierr = DataBucketView(PetscObjectComm((PetscObject)dm),swarm->db,NULL,DATABUCKET_VIEW_STDOUT);CHKERRQ(ierr);
1088   } else if (ibinary) {
1089     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO Binary support");
1090   } else if (ishdf5) {
1091 #if defined(PETSC_HAVE_HDF5)
1092     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO HDF5 support");
1093 #else
1094     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"HDF5 not supported. Please reconfigure using --download-hdf5");
1095 #endif
1096   } else if (isvtk) {
1097     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO VTK support");
1098   } else if (isdraw) {
1099     ierr = DMSwarmView_Draw(dm, viewer);CHKERRQ(ierr);
1100   }
1101   PetscFunctionReturn(0);
1102 }
1103 
1104 /*MC
1105 
1106  DMSWARM = "swarm" - A DM object used to represent arrays of data (fields) of arbitrary data type.
1107  This implementation was designed for particle methods in which the underlying
1108  data required to be represented is both (i) dynamic in length, (ii) and of arbitrary data type.
1109 
1110  User data can be represented by DMSwarm through a registering "fields".
1111  To register a field, the user must provide;
1112  (a) a unique name;
1113  (b) the data type (or size in bytes);
1114  (c) the block size of the data.
1115 
1116  For example, suppose the application requires a unique id, energy, momentum and density to be stored
1117  on a set of of particles. Then the following code could be used
1118 
1119 $    DMSwarmInitializeFieldRegister(dm)
1120 $    DMSwarmRegisterPetscDatatypeField(dm,"uid",1,PETSC_LONG);
1121 $    DMSwarmRegisterPetscDatatypeField(dm,"energy",1,PETSC_REAL);
1122 $    DMSwarmRegisterPetscDatatypeField(dm,"momentum",3,PETSC_REAL);
1123 $    DMSwarmRegisterPetscDatatypeField(dm,"density",1,PETSC_FLOAT);
1124 $    DMSwarmFinalizeFieldRegister(dm)
1125 
1126  The fields represented by DMSwarm are dynamic and can be re-sized at any time.
1127  The only restriction imposed by DMSwarm is that all fields contain the same number of points.
1128 
1129  To support particle methods, "migration" techniques are provided. These methods migrate data
1130  between MPI-ranks.
1131 
1132  DMSwarm supports the methods DMCreateGlobalVector() and DMCreateLocalVector().
1133  As a DMSwarm may internally define and store values of different data types,
1134  before calling DMCreateGlobalVector() or DMCreateLocalVector(), the user must inform DMSwarm which
1135  fields should be used to define a Vec object via
1136    DMSwarmVectorDefineField()
1137  The specified field can can changed be changed at any time - thereby permitting vectors
1138  compatable with different fields to be created.
1139 
1140  A dual representation of fields in the DMSwarm and a Vec object is permitted via
1141    DMSwarmCreateGlobalVectorFromField()
1142  Here the data defining the field in the DMSwarm is shared with a Vec.
1143  This is inherently unsafe if you alter the size of the field at any time between
1144  calls to DMSwarmCreateGlobalVectorFromField() and DMSwarmDestroyGlobalVectorFromField().
1145  If the local size of the DMSwarm does not match the local size of the global vector
1146  when DMSwarmDestroyGlobalVectorFromField() is called, an error is thrown.
1147 
1148  Additional high-level support is provided for Particle-In-Cell methods.
1149  Please refer to the man page for DMSwarmSetType().
1150 
1151  Level: beginner
1152 
1153 .seealso: DMType, DMCreate(), DMSetType()
1154 M*/
1155 PETSC_EXTERN PetscErrorCode DMCreate_Swarm(DM dm)
1156 {
1157   DM_Swarm      *swarm;
1158   PetscErrorCode ierr;
1159 
1160   PetscFunctionBegin;
1161   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1162   ierr     = PetscNewLog(dm,&swarm);CHKERRQ(ierr);
1163   dm->data = swarm;
1164 
1165   ierr = DataBucketCreate(&swarm->db);CHKERRQ(ierr);
1166   ierr = DMSwarmInitializeFieldRegister(dm);CHKERRQ(ierr);
1167 
1168   swarm->vec_field_set = PETSC_FALSE;
1169   swarm->issetup = PETSC_FALSE;
1170   swarm->swarm_type = DMSWARM_BASIC;
1171   swarm->migrate_type = DMSWARM_MIGRATE_BASIC;
1172   swarm->collect_type = DMSWARM_COLLECT_BASIC;
1173   swarm->migrate_error_on_missing_point = PETSC_FALSE;
1174 
1175   swarm->dmcell = NULL;
1176   swarm->collect_view_active = PETSC_FALSE;
1177   swarm->collect_view_reset_nlocal = -1;
1178 
1179   dm->dim  = 0;
1180   dm->ops->view                            = DMView_Swarm;
1181   dm->ops->load                            = NULL;
1182   dm->ops->setfromoptions                  = NULL;
1183   dm->ops->clone                           = NULL;
1184   dm->ops->setup                           = DMSetup_Swarm;
1185   dm->ops->createdefaultsection            = NULL;
1186   dm->ops->createdefaultconstraints        = NULL;
1187   dm->ops->createglobalvector              = DMCreateGlobalVector_Swarm;
1188   dm->ops->createlocalvector               = DMCreateLocalVector_Swarm;
1189   dm->ops->getlocaltoglobalmapping         = NULL;
1190   dm->ops->createfieldis                   = NULL;
1191   dm->ops->createcoordinatedm              = NULL;
1192   dm->ops->getcoloring                     = NULL;
1193   dm->ops->creatematrix                    = NULL;
1194   dm->ops->createinterpolation             = NULL;
1195   dm->ops->getaggregates                   = NULL;
1196   dm->ops->getinjection                    = NULL;
1197   dm->ops->refine                          = NULL;
1198   dm->ops->coarsen                         = NULL;
1199   dm->ops->refinehierarchy                 = NULL;
1200   dm->ops->coarsenhierarchy                = NULL;
1201   dm->ops->globaltolocalbegin              = NULL;
1202   dm->ops->globaltolocalend                = NULL;
1203   dm->ops->localtoglobalbegin              = NULL;
1204   dm->ops->localtoglobalend                = NULL;
1205   dm->ops->destroy                         = DMDestroy_Swarm;
1206   dm->ops->createsubdm                     = NULL;
1207   dm->ops->getdimpoints                    = NULL;
1208   dm->ops->locatepoints                    = NULL;
1209   PetscFunctionReturn(0);
1210 }
1211