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