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