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