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