xref: /petsc/src/dm/impls/swarm/swarm.c (revision f2b2bee7b5cdd241b909bdb0beb4248990b03264)
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 PetscErrorCode DMSwarmMigrate_Basic(DM dm,PetscBool remove_sent_points)
763 {
764   PetscErrorCode ierr;
765 
766   PetscFunctionBegin;
767   ierr = DMSwarmMigrate_Push_Basic(dm,remove_sent_points);CHKERRQ(ierr);
768   PetscFunctionReturn(0);
769 }
770 
771 /*@C
772    DMSwarmMigrate - Relocates points defined in the DMSwarm to other MPI-ranks
773 
774    Collective on DM
775 
776    Input parameters:
777 +  dm - the DMSwarm
778 -  remove_sent_points - flag indicating if sent points should be removed from the current MPI-rank
779 
780    Notes:
781    The DM will be modified to accomodate received points.
782    If remove_sent_points = PETSC_TRUE, any points that were sent will be removed from the DM.
783    Different styles of migration are supported. See DMSwarmSetMigrateType().
784 
785    Level: advanced
786 
787 .seealso: DMSwarmSetMigrateType()
788 @*/
789 PETSC_EXTERN PetscErrorCode DMSwarmMigrate(DM dm,PetscBool remove_sent_points)
790 {
791   DM_Swarm *swarm = (DM_Swarm*)dm->data;
792   PetscErrorCode ierr;
793 
794   PetscFunctionBegin;
795   ierr = PetscLogEventBegin(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
796   switch (swarm->migrate_type) {
797     case DMSWARM_MIGRATE_BASIC:
798       ierr = DMSwarmMigrate_Basic(dm,remove_sent_points);CHKERRQ(ierr);
799       break;
800     case DMSWARM_MIGRATE_DMCELLNSCATTER:
801       ierr = DMSwarmMigrate_CellDMScatter(dm,remove_sent_points);CHKERRQ(ierr);
802       break;
803     case DMSWARM_MIGRATE_DMCELLEXACT:
804       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_DMCELLEXACT not implemented");
805       /*ierr = DMSwarmMigrate_CellDMExact(dm,remove_sent_points);CHKERRQ(ierr);*/
806       break;
807     case DMSWARM_MIGRATE_USER:
808       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_USER not implemented");
809       /*ierr = swarm->migrate(dm,remove_sent_points);CHKERRQ(ierr);*/
810       break;
811     default:
812       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE type unknown");
813       break;
814   }
815   ierr = PetscLogEventEnd(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
816   PetscFunctionReturn(0);
817 }
818 
819 PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm,PetscInt *globalsize);
820 
821 /*
822  DMSwarmCollectViewCreate
823 
824  * Applies a collection method and gathers point neighbour points into dm
825 
826  Notes:
827  Users should call DMSwarmCollectViewDestroy() after
828  they have finished computations associated with the collected points
829 */
830 
831 /*@C
832    DMSwarmCollectViewCreate - Applies a collection method and gathers points
833    in neighbour MPI-ranks into the DMSwarm
834 
835    Collective on DM
836 
837    Input parameter:
838 .  dm - the DMSwarm
839 
840    Notes:
841    Users should call DMSwarmCollectViewDestroy() after
842    they have finished computations associated with the collected points
843    Different collect methods are supported. See DMSwarmSetCollectType().
844 
845    Level: advanced
846 
847 .seealso: DMSwarmCollectViewDestroy(), DMSwarmSetCollectType()
848 @*/
849 PETSC_EXTERN PetscErrorCode DMSwarmCollectViewCreate(DM dm)
850 {
851   PetscErrorCode ierr;
852   DM_Swarm *swarm = (DM_Swarm*)dm->data;
853   PetscInt ng;
854 
855   PetscFunctionBegin;
856   if (swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView currently active");
857   ierr = DMSwarmGetLocalSize(dm,&ng);CHKERRQ(ierr);
858   switch (swarm->collect_type) {
859 
860     case DMSWARM_COLLECT_BASIC:
861       ierr = DMSwarmMigrate_GlobalToLocal_Basic(dm,&ng);CHKERRQ(ierr);
862       break;
863     case DMSWARM_COLLECT_DMDABOUNDINGBOX:
864       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_DMDABOUNDINGBOX not implemented");
865       /*ierr = DMSwarmCollect_DMDABoundingBox(dm,&ng);CHKERRQ(ierr);*/
866       break;
867     case DMSWARM_COLLECT_GENERAL:
868       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_GENERAL not implemented");
869       /*ierr = DMSwarmCollect_General(dm,..,,..,&ng);CHKERRQ(ierr);*/
870       break;
871     default:
872       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT type unknown");
873       break;
874   }
875   swarm->collect_view_active = PETSC_TRUE;
876   swarm->collect_view_reset_nlocal = ng;
877   PetscFunctionReturn(0);
878 }
879 
880 /*@C
881    DMSwarmCollectViewDestroy - Resets the DMSwarm to the size prior to calling DMSwarmCollectViewCreate()
882 
883    Collective on DM
884 
885    Input parameters:
886 .  dm - the DMSwarm
887 
888    Notes:
889    Users should call DMSwarmCollectViewCreate() before this function is called.
890 
891    Level: advanced
892 
893 .seealso: DMSwarmCollectViewCreate(), DMSwarmSetCollectType()
894 @*/
895 PETSC_EXTERN PetscErrorCode DMSwarmCollectViewDestroy(DM dm)
896 {
897   PetscErrorCode ierr;
898   DM_Swarm *swarm = (DM_Swarm*)dm->data;
899 
900   PetscFunctionBegin;
901   if (!swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView is currently not active");
902   ierr = DMSwarmSetLocalSizes(dm,swarm->collect_view_reset_nlocal,-1);CHKERRQ(ierr);
903   swarm->collect_view_active = PETSC_FALSE;
904   PetscFunctionReturn(0);
905 }
906 
907 PetscErrorCode DMSwarmSetUpPIC(DM dm)
908 {
909   PetscInt dim;
910   PetscErrorCode ierr;
911 
912   PetscFunctionBegin;
913   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
914   if (dim < 1) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
915   if (dim > 3) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
916   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_coor,dim,PETSC_DOUBLE);CHKERRQ(ierr);
917   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_cellid,1,PETSC_INT);CHKERRQ(ierr);
918   PetscFunctionReturn(0);
919 }
920 
921 /*@C
922    DMSwarmSetType - Set particular flavor of DMSwarm
923 
924    Collective on DM
925 
926    Input parameters:
927 +  dm - the DMSwarm
928 -  stype - the DMSwarm type (e.g. DMSWARM_PIC)
929 
930    Level: advanced
931 
932 .seealso: DMSwarmSetMigrateType(), DMSwarmSetCollectType()
933 @*/
934 PETSC_EXTERN PetscErrorCode DMSwarmSetType(DM dm,DMSwarmType stype)
935 {
936   DM_Swarm *swarm = (DM_Swarm*)dm->data;
937   PetscErrorCode ierr;
938 
939   PetscFunctionBegin;
940   swarm->swarm_type = stype;
941   if (swarm->swarm_type == DMSWARM_PIC) {
942     ierr = DMSwarmSetUpPIC(dm);CHKERRQ(ierr);
943   }
944   PetscFunctionReturn(0);
945 }
946 
947 PetscErrorCode DMSetup_Swarm(DM dm)
948 {
949   DM_Swarm *swarm = (DM_Swarm*)dm->data;
950   PetscErrorCode ierr;
951   PetscMPIInt rank;
952   PetscInt p,npoints,*rankval;
953 
954   PetscFunctionBegin;
955   if (swarm->issetup) PetscFunctionReturn(0);
956 
957   swarm->issetup = PETSC_TRUE;
958 
959   if (swarm->swarm_type == DMSWARM_PIC) {
960     /* check dmcell exists */
961     if (!swarm->dmcell) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires you call DMSwarmSetCellDM");
962 
963     if (swarm->dmcell->ops->locatepointssubdomain) {
964       /* check methods exists for exact ownership identificiation */
965       ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->ops->LocatePointsSubdomain\n");CHKERRQ(ierr);
966       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLEXACT;
967     } else {
968       /* check methods exist for point location AND rank neighbor identification */
969       if (swarm->dmcell->ops->locatepoints) {
970         ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->LocatePoints\n");CHKERRQ(ierr);
971       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->locatepoints be defined");
972 
973       if (swarm->dmcell->ops->getneighbors) {
974         ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->GetNeigbors\n");CHKERRQ(ierr);
975       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->getneighbors be defined");
976 
977       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLNSCATTER;
978     }
979   }
980 
981   ierr = DMSwarmFinalizeFieldRegister(dm);CHKERRQ(ierr);
982 
983   /* check some fields were registered */
984   if (swarm->db->nfields <= 2) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"At least one field user must be registered via DMSwarmRegisterXXX()");
985 
986   /* check local sizes were set */
987   if (swarm->db->L == -1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Local sizes must be set via DMSwarmSetLocalSizes()");
988 
989   /* initialize values in pid and rank placeholders */
990   /* TODO: [pid - use MPI_Scan] */
991   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
992   ierr = DataBucketGetSizes(swarm->db,&npoints,NULL,NULL);CHKERRQ(ierr);
993   ierr = DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
994   for (p=0; p<npoints; p++) {
995     rankval[p] = (PetscInt)rank;
996   }
997   ierr = DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
998   PetscFunctionReturn(0);
999 }
1000 
1001 extern PetscErrorCode DMSwarmSortDestroy(DMSwarmSort *_ctx);
1002 
1003 PetscErrorCode DMDestroy_Swarm(DM dm)
1004 {
1005   DM_Swarm *swarm = (DM_Swarm*)dm->data;
1006   PetscErrorCode ierr;
1007 
1008   PetscFunctionBegin;
1009   ierr = DataBucketDestroy(&swarm->db);CHKERRQ(ierr);
1010   if (swarm->sort_context) {
1011     ierr = DMSwarmSortDestroy(&swarm->sort_context);CHKERRQ(ierr);
1012   }
1013   ierr = PetscFree(swarm);CHKERRQ(ierr);
1014   PetscFunctionReturn(0);
1015 }
1016 
1017 PetscErrorCode DMSwarmView_Draw(DM dm, PetscViewer viewer)
1018 {
1019   DM             cdm;
1020   PetscDraw      draw;
1021   PetscReal     *coords, oldPause;
1022   PetscInt       Np, p, bs;
1023   PetscErrorCode ierr;
1024 
1025   PetscFunctionBegin;
1026   ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr);
1027   ierr = DMSwarmGetCellDM(dm, &cdm);CHKERRQ(ierr);
1028   ierr = PetscDrawGetPause(draw, &oldPause);CHKERRQ(ierr);
1029   ierr = PetscDrawSetPause(draw, 0.0);CHKERRQ(ierr);
1030   ierr = DMView(cdm, viewer);CHKERRQ(ierr);
1031   ierr = PetscDrawSetPause(draw, oldPause);CHKERRQ(ierr);
1032 
1033   ierr = DMSwarmGetLocalSize(dm, &Np);CHKERRQ(ierr);
1034   ierr = DMSwarmGetField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1035   for (p = 0; p < Np; ++p) {
1036     const PetscInt i = p*bs;
1037 
1038     ierr = PetscDrawEllipse(draw, coords[i], coords[i+1], 0.01, 0.01, PETSC_DRAW_BLUE);CHKERRQ(ierr);
1039   }
1040   ierr = DMSwarmRestoreField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1041   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
1042   ierr = PetscDrawPause(draw);CHKERRQ(ierr);
1043   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
1044   PetscFunctionReturn(0);
1045 }
1046 
1047 PetscErrorCode DMView_Swarm(DM dm, PetscViewer viewer)
1048 {
1049   DM_Swarm *swarm = (DM_Swarm*)dm->data;
1050   PetscBool      iascii,ibinary,ishdf5,isvtk,isdraw;
1051   PetscErrorCode ierr;
1052 
1053   PetscFunctionBegin;
1054   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1055   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
1056   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
1057   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY,&ibinary);CHKERRQ(ierr);
1058   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK,   &isvtk);CHKERRQ(ierr);
1059   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
1060   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW,  &isdraw);CHKERRQ(ierr);
1061   if (iascii) {
1062     ierr = DataBucketView(PetscObjectComm((PetscObject)dm),swarm->db,NULL,DATABUCKET_VIEW_STDOUT);CHKERRQ(ierr);
1063   } else if (ibinary) {
1064     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO Binary support");
1065   } else if (ishdf5) {
1066 #if defined(PETSC_HAVE_HDF5)
1067     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO HDF5 support");
1068 #else
1069     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"HDF5 not supported. Please reconfigure using --download-hdf5");
1070 #endif
1071   } else if (isvtk) {
1072     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO VTK support");
1073   } else if (isdraw) {
1074     ierr = DMSwarmView_Draw(dm, viewer);CHKERRQ(ierr);
1075   }
1076   PetscFunctionReturn(0);
1077 }
1078 
1079 /*MC
1080 
1081  DMSWARM = "swarm" - A DM object used to represent arrays of data (fields) of arbitrary data type.
1082  This implementation was designed for particle methods in which the underlying
1083  data required to be represented is both (i) dynamic in length, (ii) and of arbitrary data type.
1084 
1085  User data can be represented by DMSwarm through a registering "fields".
1086  To register a field, the user must provide;
1087  (a) a unique name;
1088  (b) the data type (or size in bytes);
1089  (c) the block size of the data.
1090 
1091  For example, suppose the application requires a unique id, energy, momentum and density to be stored
1092  on a set of of particles. Then the following code could be used
1093 
1094 $    DMSwarmInitializeFieldRegister(dm)
1095 $    DMSwarmRegisterPetscDatatypeField(dm,"uid",1,PETSC_LONG);
1096 $    DMSwarmRegisterPetscDatatypeField(dm,"energy",1,PETSC_REAL);
1097 $    DMSwarmRegisterPetscDatatypeField(dm,"momentum",3,PETSC_REAL);
1098 $    DMSwarmRegisterPetscDatatypeField(dm,"density",1,PETSC_FLOAT);
1099 $    DMSwarmFinalizeFieldRegister(dm)
1100 
1101  The fields represented by DMSwarm are dynamic and can be re-sized at any time.
1102  The only restriction imposed by DMSwarm is that all fields contain the same number of points.
1103 
1104  To support particle methods, "migration" techniques are provided. These methods migrate data
1105  between MPI-ranks.
1106 
1107  DMSwarm supports the methods DMCreateGlobalVector() and DMCreateLocalVector().
1108  As a DMSwarm may internally define and store values of different data types,
1109  before calling DMCreateGlobalVector() or DMCreateLocalVector(), the user must inform DMSwarm which
1110  fields should be used to define a Vec object via
1111    DMSwarmVectorDefineField()
1112  The specified field can can changed be changed at any time - thereby permitting vectors
1113  compatable with different fields to be created.
1114 
1115  A dual representation of fields in the DMSwarm and a Vec object is permitted via
1116    DMSwarmCreateGlobalVectorFromField()
1117  Here the data defining the field in the DMSwarm is shared with a Vec.
1118  This is inherently unsafe if you alter the size of the field at any time between
1119  calls to DMSwarmCreateGlobalVectorFromField() and DMSwarmDestroyGlobalVectorFromField().
1120  If the local size of the DMSwarm does not match the local size of the global vector
1121  when DMSwarmDestroyGlobalVectorFromField() is called, an error is thrown.
1122 
1123  Additional high-level support is provided for Particle-In-Cell methods.
1124  Please refer to the man page for DMSwarmSetType().
1125 
1126  Level: beginner
1127 
1128 .seealso: DMType, DMCreate(), DMSetType()
1129 M*/
1130 PETSC_EXTERN PetscErrorCode DMCreate_Swarm(DM dm)
1131 {
1132   DM_Swarm      *swarm;
1133   PetscErrorCode ierr;
1134 
1135   PetscFunctionBegin;
1136   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1137   ierr     = PetscNewLog(dm,&swarm);CHKERRQ(ierr);
1138   dm->data = swarm;
1139 
1140   ierr = DataBucketCreate(&swarm->db);CHKERRQ(ierr);
1141   ierr = DMSwarmInitializeFieldRegister(dm);CHKERRQ(ierr);
1142 
1143   swarm->vec_field_set = PETSC_FALSE;
1144   swarm->issetup = PETSC_FALSE;
1145   swarm->swarm_type = DMSWARM_BASIC;
1146   swarm->migrate_type = DMSWARM_MIGRATE_BASIC;
1147   swarm->collect_type = DMSWARM_COLLECT_BASIC;
1148   swarm->migrate_error_on_missing_point = PETSC_FALSE;
1149 
1150   swarm->dmcell = NULL;
1151   swarm->collect_view_active = PETSC_FALSE;
1152   swarm->collect_view_reset_nlocal = -1;
1153 
1154   dm->dim  = 0;
1155   dm->ops->view                            = DMView_Swarm;
1156   dm->ops->load                            = NULL;
1157   dm->ops->setfromoptions                  = NULL;
1158   dm->ops->clone                           = NULL;
1159   dm->ops->setup                           = DMSetup_Swarm;
1160   dm->ops->createdefaultsection            = NULL;
1161   dm->ops->createdefaultconstraints        = NULL;
1162   dm->ops->createglobalvector              = DMCreateGlobalVector_Swarm;
1163   dm->ops->createlocalvector               = DMCreateLocalVector_Swarm;
1164   dm->ops->getlocaltoglobalmapping         = NULL;
1165   dm->ops->createfieldis                   = NULL;
1166   dm->ops->createcoordinatedm              = NULL;
1167   dm->ops->getcoloring                     = NULL;
1168   dm->ops->creatematrix                    = NULL;
1169   dm->ops->createinterpolation             = NULL;
1170   dm->ops->getaggregates                   = NULL;
1171   dm->ops->getinjection                    = NULL;
1172   dm->ops->refine                          = NULL;
1173   dm->ops->coarsen                         = NULL;
1174   dm->ops->refinehierarchy                 = NULL;
1175   dm->ops->coarsenhierarchy                = NULL;
1176   dm->ops->globaltolocalbegin              = NULL;
1177   dm->ops->globaltolocalend                = NULL;
1178   dm->ops->localtoglobalbegin              = NULL;
1179   dm->ops->localtoglobalend                = NULL;
1180   dm->ops->destroy                         = DMDestroy_Swarm;
1181   dm->ops->createsubdm                     = NULL;
1182   dm->ops->getdimpoints                    = NULL;
1183   dm->ops->locatepoints                    = NULL;
1184   PetscFunctionReturn(0);
1185 }
1186