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