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