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