xref: /petsc/src/dm/impls/swarm/swarm.c (revision cc65118127171f6f2b2fee5dff3971f4ffb2a07d)
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   switch (type) {
488     case PETSC_CHAR:
489       size = sizeof(PetscChar);
490       break;
491     case PETSC_SHORT:
492       size = sizeof(PetscShort);
493       break;
494     case PETSC_INT:
495       size = sizeof(PetscInt);
496       break;
497     case PETSC_LONG:
498       size = sizeof(Petsc64bitInt);
499       break;
500     case PETSC_FLOAT:
501       size = sizeof(PetscFloat);
502       break;
503     case PETSC_DOUBLE:
504       size = sizeof(PetscReal);
505       break;
506 
507     default:
508       SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
509       break;
510   }
511 
512   /* Load a specific data type into data bucket, specifying textual name and its size in bytes */
513 	ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterPetscDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
514   {
515     DataField gfield;
516 
517     ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
518     ierr = DataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
519   }
520   swarm->db->field[swarm->db->nfields-1]->petsc_type = type;
521 
522   PetscFunctionReturn(0);
523 }
524 
525 /*@C
526 
527  DMSwarmRegisterUserStructField - Register a user defined struct to a DMSwarm
528 
529  Collective on DM
530 
531  Input parameters:
532  . dm - a DMSwarm
533  . fieldname - the textual name to identify this field
534  . size - the size in bytes of the user struct of each data type
535 
536  Level: beginner
537 
538  Notes:
539  The textual name for each registered field must be unique
540 
541  . seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserDatatypeField()
542 
543 @*/
544 #undef __FUNCT__
545 #define __FUNCT__ "DMSwarmRegisterUserStructField"
546 PETSC_EXTERN PetscErrorCode DMSwarmRegisterUserStructField(DM dm,const char fieldname[],size_t size)
547 {
548   PetscErrorCode ierr;
549   DM_Swarm *swarm = (DM_Swarm*)dm->data;
550 
551 	ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterUserStructField",fieldname,size,NULL);CHKERRQ(ierr);
552   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_STRUCT ;
553 
554   PetscFunctionReturn(0);
555 }
556 
557 /*@C
558 
559  DMSwarmRegisterUserDatatypeField - Register a user defined data type to a DMSwarm
560 
561  Collective on DM
562 
563  Input parameters:
564  . dm - a DMSwarm
565  . fieldname - the textual name to identify this field
566  . size - the size in bytes of the user data type
567  . blocksize - the number of each data type
568 
569  Level: beginner
570 
571  Notes:
572  The textual name for each registered field must be unique
573 
574  . seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
575 
576 @*/
577 #undef __FUNCT__
578 #define __FUNCT__ "DMSwarmRegisterUserDatatypeField"
579 PETSC_EXTERN PetscErrorCode DMSwarmRegisterUserDatatypeField(DM dm,const char fieldname[],size_t size,PetscInt blocksize)
580 {
581   DM_Swarm *swarm = (DM_Swarm*)dm->data;
582   PetscErrorCode ierr;
583 
584 	ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterUserDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
585   {
586     DataField gfield;
587 
588     ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
589     ierr = DataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
590   }
591   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_DATATYPE_UNKNOWN;
592 
593   PetscFunctionReturn(0);
594 }
595 
596 /*@C
597 
598  DMSwarmGetField - Get access to the underlying array storing all entries associated with a registered field
599 
600  Not collective
601 
602  Input parameters:
603  . dm - a DMSwarm
604  . fieldname - the textual name to identify this field
605 
606  Output parameters:
607  . blocksize - the number of each data type
608  . type - the data type
609  . data - pointer to raw array
610 
611  Level: beginner
612 
613  Notes:
614  The user must call DMSwarmRestoreField()
615 
616  . seealso: DMSwarmRestoreField()
617 
618 @*/
619 #undef __FUNCT__
620 #define __FUNCT__ "DMSwarmGetField"
621 PETSC_EXTERN PetscErrorCode DMSwarmGetField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
622 {
623   DM_Swarm *swarm = (DM_Swarm*)dm->data;
624   DataField gfield;
625   PetscErrorCode ierr;
626 
627   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
628 
629   ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
630   ierr = DataFieldGetAccess(gfield);CHKERRQ(ierr);
631   ierr = DataFieldGetEntries(gfield,data);CHKERRQ(ierr);
632   if (blocksize) {*blocksize = gfield->bs; }
633   if (type) { *type = gfield->petsc_type; }
634 
635   PetscFunctionReturn(0);
636 }
637 
638 /*@C
639 
640  DMSwarmRestoreField - Restore access to the underlying array storing all entries associated with a registered field
641 
642  Not collective
643 
644  Input parameters:
645  . dm - a DMSwarm
646  . fieldname - the textual name to identify this field
647 
648  Output parameters:
649  . blocksize - the number of each data type
650  . type - the data type
651  . data - pointer to raw array
652 
653  Level: beginner
654 
655  Notes:
656  The user must call DMSwarmGetField() prior to calling DMSwarmRestoreField()
657 
658  . seealso: DMSwarmGetField()
659 
660 @*/
661 #undef __FUNCT__
662 #define __FUNCT__ "DMSwarmRestoreField"
663 PETSC_EXTERN PetscErrorCode DMSwarmRestoreField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
664 {
665   DM_Swarm *swarm = (DM_Swarm*)dm->data;
666   DataField gfield;
667   PetscErrorCode ierr;
668 
669   ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
670   ierr = DataFieldRestoreAccess(gfield);CHKERRQ(ierr);
671   if (data) *data = NULL;
672 
673   PetscFunctionReturn(0);
674 }
675 
676 /*@C
677 
678  DMSwarmAddPoint - Add space for one new point in the DMSwarm
679 
680  Not collective
681 
682  Input parameter:
683  . dm - a DMSwarm
684 
685  Level: beginner
686 
687  Notes:
688  The new point will have all fields initialized to zero
689 
690  . seealso: DMSwarmAddNPoints()
691 
692 @*/
693 #undef __FUNCT__
694 #define __FUNCT__ "DMSwarmAddPoint"
695 PETSC_EXTERN PetscErrorCode DMSwarmAddPoint(DM dm)
696 {
697   DM_Swarm *swarm = (DM_Swarm*)dm->data;
698   PetscErrorCode ierr;
699 
700   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
701   ierr = DataBucketAddPoint(swarm->db);CHKERRQ(ierr);
702   PetscFunctionReturn(0);
703 }
704 
705 /*@C
706 
707  DMSwarmAddNPoints - Add space for a number of new points in the DMSwarm
708 
709  Not collective
710 
711  Input parameters:
712  . dm - a DMSwarm
713  . npoints - the number of new points to add
714 
715  Level: beginner
716 
717  Notes:
718  The new point will have all fields initialized to zero
719 
720  . seealso: DMSwarmAddPoint()
721 
722 @*/
723 #undef __FUNCT__
724 #define __FUNCT__ "DMSwarmAddNPoints"
725 PETSC_EXTERN PetscErrorCode DMSwarmAddNPoints(DM dm,PetscInt npoints)
726 {
727   DM_Swarm *swarm = (DM_Swarm*)dm->data;
728   PetscErrorCode ierr;
729   PetscInt nlocal;
730 
731   ierr = DataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
732   nlocal = nlocal + npoints;
733   ierr = DataBucketSetSizes(swarm->db,nlocal,-1);CHKERRQ(ierr);
734   PetscFunctionReturn(0);
735 }
736 
737 /*@C
738 
739  DMSwarmRemovePoint - Remove the last point from the DMSwarm
740 
741  Not collective
742 
743  Input parameter:
744  . dm - a DMSwarm
745 
746  Level: beginner
747 
748  . seealso: DMSwarmRemovePointAtIndex()
749 
750 @*/
751 #undef __FUNCT__
752 #define __FUNCT__ "DMSwarmRemovePoint"
753 PETSC_EXTERN PetscErrorCode DMSwarmRemovePoint(DM dm)
754 {
755   DM_Swarm *swarm = (DM_Swarm*)dm->data;
756   PetscErrorCode ierr;
757 
758   ierr = DataBucketRemovePoint(swarm->db);CHKERRQ(ierr);
759   PetscFunctionReturn(0);
760 }
761 
762 /*@C
763 
764  DMSwarmRemovePointAtIndex - Removes a specific point from the DMSwarm
765 
766  Not collective
767 
768  Input parameters:
769  . dm - a DMSwarm
770  . idx - index of point to remove
771 
772  Level: beginner
773 
774  . seealso: DMSwarmRemovePoint()
775 
776 @*/
777 #undef __FUNCT__
778 #define __FUNCT__ "DMSwarmRemovePointAtIndex"
779 PETSC_EXTERN PetscErrorCode DMSwarmRemovePointAtIndex(DM dm,PetscInt idx)
780 {
781   DM_Swarm *swarm = (DM_Swarm*)dm->data;
782   PetscErrorCode ierr;
783 
784   ierr = DataBucketRemovePointAtIndex(swarm->db,idx);CHKERRQ(ierr);
785   PetscFunctionReturn(0);
786 }
787 
788 #undef __FUNCT__
789 #define __FUNCT__ "DMSwarmMigrate_Basic"
790 PetscErrorCode DMSwarmMigrate_Basic(DM dm,PetscBool remove_sent_points)
791 {
792   PetscErrorCode ierr;
793   ierr = DMSwarmMigrate_Push_Basic(dm,remove_sent_points);CHKERRQ(ierr);
794   PetscFunctionReturn(0);
795 }
796 
797 PetscErrorCode DMSwarmMigrate_CellDMScatter(DM dm,PetscBool remove_sent_points);
798 PetscErrorCode DMSwarmMigrate_CellDMExact(DM dm,PetscBool remove_sent_points);
799 
800 /*@C
801 
802  DMSwarmMigrate - Relocates points defined in the DMSwarm to other MPI-ranks
803 
804  Collective on DM
805 
806  Input parameters:
807  . dm - the DMSwarm
808  . remove_sent_points - flag indicating if sent points should be removed from the current MPI-rank
809 
810  Notes:
811  The DM wil be modified to accomodate received points.
812  If remove_sent_points = PETSC_TRUE, send points will be removed from the DM
813  Different styles of migration are supported. See DMSwarmSetMigrateType()
814 
815  Level: advanced
816 
817  . seealso: DMSwarmSetMigrateType()
818 
819 @*/
820 #undef __FUNCT__
821 #define __FUNCT__ "DMSwarmMigrate"
822 PETSC_EXTERN PetscErrorCode DMSwarmMigrate(DM dm,PetscBool remove_sent_points)
823 {
824   DM_Swarm *swarm = (DM_Swarm*)dm->data;
825   PetscErrorCode ierr;
826 
827   switch (swarm->migrate_type) {
828 
829     case DMSWARM_MIGRATE_BASIC:
830       ierr = DMSwarmMigrate_Basic(dm,remove_sent_points);CHKERRQ(ierr);
831       break;
832 
833     case DMSWARM_MIGRATE_DMCELLNSCATTER:
834       ierr = DMSwarmMigrate_CellDMScatter(dm,remove_sent_points);CHKERRQ(ierr);
835       break;
836 
837     case DMSWARM_MIGRATE_DMCELLEXACT:
838       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_DMCELLEXACT not implemented");
839       //ierr = DMSwarmMigrate_CellDMExact(dm,remove_sent_points);CHKERRQ(ierr);
840       break;
841 
842     case DMSWARM_MIGRATE_USER:
843       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_USER not implemented");
844       //ierr = swarm->migrate(dm,remove_sent_points);CHKERRQ(ierr);
845       break;
846 
847     default:
848       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE type unknown");
849       break;
850   }
851   PetscFunctionReturn(0);
852 }
853 
854 PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm,PetscInt *globalsize);
855 
856 /*
857  DMSwarmCollectViewCreate
858 
859  * Applies a collection method and gathers point neighbour points into dm
860 
861  Notes:
862  - Users should call DMSwarmCollectViewDestroy() after
863  they have finished computations associated with the collected points
864 */
865 
866 /*@C
867 
868  DMSwarmCollectViewCreate - Applies a collection method and gathers points
869  in neighbour MPI-ranks into the DMSwarm
870 
871  Collective on DM
872 
873  Input parameter:
874  . dm - the DMSwarm
875 
876  Notes:
877  Users should call DMSwarmCollectViewDestroy() after
878  they have finished computations associated with the collected points
879  Different collect methods are supported. See DMSwarmSetCollectType()
880 
881  Level: advanced
882 
883  . seealso: DMSwarmCollectViewDestroy(), DMSwarmSetCollectType()
884 
885 @*/
886 #undef __FUNCT__
887 #define __FUNCT__ "DMSwarmCollectViewCreate"
888 PETSC_EXTERN PetscErrorCode DMSwarmCollectViewCreate(DM dm)
889 {
890   PetscErrorCode ierr;
891   DM_Swarm *swarm = (DM_Swarm*)dm->data;
892   PetscInt ng;
893 
894   if (swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView currently active");
895 
896   ierr = DMSwarmGetLocalSize(dm,&ng);CHKERRQ(ierr);
897   switch (swarm->collect_type) {
898 
899     case DMSWARM_COLLECT_BASIC:
900       ierr = DMSwarmMigrate_GlobalToLocal_Basic(dm,&ng);CHKERRQ(ierr);
901       break;
902 
903     case DMSWARM_COLLECT_DMDABOUNDINGBOX:
904       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_DMDABOUNDINGBOX not implemented");
905       //ierr = DMSwarmCollect_DMDABoundingBox(dm,&ng);CHKERRQ(ierr);
906       break;
907 
908     case DMSWARM_COLLECT_GENERAL:
909       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_GENERAL not implemented");
910       //ierr = DMSwarmCollect_General(dm,..,,..,&ng);CHKERRQ(ierr);
911       break;
912 
913     default:
914       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT type unknown");
915       break;
916   }
917 
918   swarm->collect_view_active = PETSC_TRUE;
919   swarm->collect_view_reset_nlocal = ng;
920 
921   PetscFunctionReturn(0);
922 }
923 
924 /*@C
925 
926  DMSwarmCollectViewDestroy - Resets the DMSwarm to the size prior to calling DMSwarmCollectViewCreate()
927 
928  Collective on DM
929 
930  Input parameters:
931  . dm - the DMSwarm
932 
933  Notes:
934  Users should call DMSwarmCollectViewCreate() before this function is called.
935 
936  Level: advanced
937 
938  . seealso: DMSwarmCollectViewCreate(), DMSwarmSetCollectType()
939 
940 @*/
941 #undef __FUNCT__
942 #define __FUNCT__ "DMSwarmCollectViewDestroy"
943 PETSC_EXTERN PetscErrorCode DMSwarmCollectViewDestroy(DM dm)
944 {
945   PetscErrorCode ierr;
946   DM_Swarm *swarm = (DM_Swarm*)dm->data;
947 
948   if (!swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView is currently not active");
949   ierr = DMSwarmSetLocalSizes(dm,swarm->collect_view_reset_nlocal,-1);CHKERRQ(ierr);
950   swarm->collect_view_active = PETSC_FALSE;
951 
952   PetscFunctionReturn(0);
953 }
954 
955 #undef __FUNCT__
956 #define __FUNCT__ "DMSwarmSetUpPIC"
957 PetscErrorCode DMSwarmSetUpPIC(DM dm)
958 {
959   PetscInt dim;
960   PetscErrorCode ierr;
961 
962   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
963   if (dim < 1) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
964   if (dim > 3) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
965   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_coor,dim,PETSC_DOUBLE);CHKERRQ(ierr);
966   PetscFunctionReturn(0);
967 }
968 
969 /*@C
970 
971  DMSwarmSetType - Set particular flavor of DMSwarm
972 
973  Collective on DM
974 
975  Input parameters:
976  . dm - the DMSwarm
977  . stype - the DMSwarm type (e.g. DMSWARM_PIC)
978 
979  Level: advanced
980 
981  . seealso: DMSwarmSetMigrateType(), DMSwarmSetCollectType()
982 
983 @*/
984 #undef __FUNCT__
985 #define __FUNCT__ "DMSwarmSetType"
986 PETSC_EXTERN PetscErrorCode DMSwarmSetType(DM dm,DMSwarmType stype)
987 {
988   DM_Swarm *swarm = (DM_Swarm*)dm->data;
989   PetscErrorCode ierr;
990 
991   swarm->swarm_type = stype;
992   if (swarm->swarm_type == DMSWARM_PIC) {
993     ierr = DMSwarmSetUpPIC(dm);CHKERRQ(ierr);
994   }
995   PetscFunctionReturn(0);
996 }
997 
998 #undef __FUNCT__
999 #define __FUNCT__ "DMSetup_Swarm"
1000 PetscErrorCode DMSetup_Swarm(DM dm)
1001 {
1002   DM_Swarm *swarm = (DM_Swarm*)dm->data;
1003   PetscErrorCode ierr;
1004   PetscMPIInt rank;
1005   PetscInt p,npoints,*rankval;
1006 
1007   if (swarm->issetup) PetscFunctionReturn(0);
1008 
1009   swarm->issetup = PETSC_TRUE;
1010 
1011   if (swarm->swarm_type == DMSWARM_PIC) {
1012     /* check dmcell exists */
1013     if (!swarm->dmcell) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires you call DMSwarmSetCellDM");
1014 
1015     if (swarm->dmcell->ops->locatepointssubdomain) {
1016       /* check methods exists for exact ownership identificiation */
1017       PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->ops->LocatePointsSubdomain\n");
1018       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLEXACT;
1019     } else {
1020       /* check methods exist for point location AND rank neighbor identification */
1021       if (swarm->dmcell->ops->locatepoints) {
1022         PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->LocatePoints\n");
1023       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->locatepoints be defined");
1024 
1025       if (swarm->dmcell->ops->getneighbors) {
1026         PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->GetNeigbors\n");
1027       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->getneighbors be defined");
1028 
1029       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLNSCATTER;
1030     }
1031   }
1032 
1033   ierr = DMSwarmFinalizeFieldRegister(dm);CHKERRQ(ierr);
1034 
1035   /* check some fields were registered */
1036   if (swarm->db->nfields <= 2) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"At least one field user must be registered via DMSwarmRegisterXXX()");
1037 
1038   /* check local sizes were set */
1039   if (swarm->db->L == -1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Local sizes must be set via DMSwarmSetLocalSizes()");
1040 
1041   /* initialize values in pid and rank placeholders */
1042   /* TODO: [pid - use MPI_Scan] */
1043 
1044   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
1045   ierr = DataBucketGetSizes(swarm->db,&npoints,NULL,NULL);CHKERRQ(ierr);
1046   ierr = DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
1047   for (p=0; p<npoints; p++) {
1048     rankval[p] = (PetscInt)rank;
1049   }
1050   ierr = DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
1051 
1052   PetscFunctionReturn(0);
1053 }
1054 
1055 #undef __FUNCT__
1056 #define __FUNCT__ "DMDestroy_Swarm"
1057 PetscErrorCode DMDestroy_Swarm(DM dm)
1058 {
1059   DM_Swarm *swarm = (DM_Swarm*)dm->data;
1060   PetscErrorCode ierr;
1061 
1062   PetscFunctionBegin;
1063   ierr = DataBucketDestroy(&swarm->db);CHKERRQ(ierr);
1064   ierr = PetscFree(swarm);CHKERRQ(ierr);
1065   PetscFunctionReturn(0);
1066 }
1067 
1068 #undef __FUNCT__
1069 #define __FUNCT__ "DMView_Swarm"
1070 PetscErrorCode DMView_Swarm(DM dm, PetscViewer viewer)
1071 {
1072   DM_Swarm *swarm = (DM_Swarm*)dm->data;
1073   PetscBool      iascii,ibinary,ishdf5,isvtk;
1074   PetscErrorCode ierr;
1075 
1076   PetscFunctionBegin;
1077   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1078   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
1079   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
1080   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY,&ibinary);CHKERRQ(ierr);
1081   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK,   &isvtk);CHKERRQ(ierr);
1082   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
1083   if (iascii) {
1084     ierr = DataBucketView(PetscObjectComm((PetscObject)dm),swarm->db,NULL,DATABUCKET_VIEW_STDOUT);CHKERRQ(ierr);
1085   } else if (ibinary) {
1086     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO VTK support");
1087   } else if (ishdf5) {
1088 #if defined(PETSC_HAVE_HDF5)
1089     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO HDF5 support");
1090 #else
1091     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"HDF5 not supported. Please reconfigure using --download-hdf5");
1092 #endif
1093   } else if (isvtk) {
1094     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO VTK support");
1095   }
1096   PetscFunctionReturn(0);
1097 }
1098 
1099 /*MC
1100 
1101  DMSWARM = "swarm" - A DM object used to represent arrays of data (fields) of arbitrary data type.
1102  This implementation was designed for particle-in-cell type methods in which the underlying
1103  data required to be represented is both (i) dynamic in length, (ii) and of arbitrary data type.
1104 
1105  User data can be represented by DMSwarm through a registring "fields".
1106  To register a field, the user must provide:
1107  (a) a unique name
1108  (b) the data type (or size in bytes)
1109  (c) the block size of the data
1110 
1111  For example, suppose the application requires a unique id, energy, momentum and density to be stored
1112  on a set of of particles. Then the following application could be used
1113 
1114  DMSwarmInitializeFieldRegister(dm)
1115  DMSwarmRegisterPetscDatatypeField(dm,"uid",1,PETSC_LONG);
1116  DMSwarmRegisterPetscDatatypeField(dm,"energy",1,PETSC_REAL);
1117  DMSwarmRegisterPetscDatatypeField(dm,"momentum",3,PETSC_REAL);
1118  DMSwarmRegisterPetscDatatypeField(dm,"density",1,PETSC_FLOAT);
1119  DMSwarmFinalizeFieldRegister(dm)
1120 
1121  The fields represented by DMSwarm are dynamic and can be re-sized at any time.
1122  The only restriction imposed by DMSwarm is that all fields contain the same number of points
1123 
1124  To support particle methods, "migration" techniques are provided. These methods migrate data
1125  between MPI-ranks.
1126 
1127  DMSwarm supports the methods DMCreateGlobalVector() and DMCreateLocalVector().
1128  As a DMSwarm may internally define and store values of different data types,
1129  before calling DMCreate{Global/Local}Vector() the user must inform DMSwarm which
1130  fields should be used to define a Vec object via
1131    DMSwarmVectorDefineField()
1132  The specified field can can changed be changed at any time - thereby permitting vectors
1133  compatable with different fields to be created.
1134 
1135  A dual representation of fields in the DMSwarm and a Vec object are permitted via
1136    DMSwarmCreateGlobalVectorFromField()
1137  Here the data defining the field in the DMSwarm is shared with a Vec.
1138  This is inherently unsafe if you alter the size of the field at any time between
1139  calls to DMSwarmCreateGlobalVectorFromField() and DMSwarmDestroyGlobalVectorFromField().
1140  If the local size of the DMSwarm does not match the localsize of the global vector
1141  when DMSwarmDestroyGlobalVectorFromField() is called, an error is thrown.
1142 
1143  Level: beginner
1144 
1145  .seealso: DMType, DMCreate(), DMSetType()
1146 
1147 M*/
1148 #undef __FUNCT__
1149 #define __FUNCT__ "DMCreate_Swarm"
1150 PETSC_EXTERN PetscErrorCode DMCreate_Swarm(DM dm)
1151 {
1152   DM_Swarm      *swarm;
1153   PetscErrorCode ierr;
1154 
1155   PetscFunctionBegin;
1156   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1157   ierr     = PetscNewLog(dm,&swarm);CHKERRQ(ierr);
1158   dm->data = swarm;
1159 
1160   ierr = DataBucketCreate(&swarm->db);CHKERRQ(ierr);
1161   ierr = DMSwarmInitializeFieldRegister(dm);CHKERRQ(ierr);
1162 
1163   swarm->vec_field_set = PETSC_FALSE;
1164   swarm->issetup = PETSC_FALSE;
1165   swarm->swarm_type = DMSWARM_BASIC;
1166   swarm->migrate_type = DMSWARM_MIGRATE_BASIC;
1167   swarm->collect_type = DMSWARM_COLLECT_BASIC;
1168   swarm->migrate_error_on_missing_point = PETSC_FALSE;
1169 
1170   swarm->dmcell = NULL;
1171   swarm->collect_view_active = PETSC_FALSE;
1172   swarm->collect_view_reset_nlocal = -1;
1173 
1174   dm->dim  = 0;
1175   dm->ops->view                            = DMView_Swarm;
1176   dm->ops->load                            = NULL;
1177   dm->ops->setfromoptions                  = NULL;
1178   dm->ops->clone                           = NULL;
1179   dm->ops->setup                           = DMSetup_Swarm;
1180   dm->ops->createdefaultsection            = NULL;
1181   dm->ops->createdefaultconstraints        = NULL;
1182   dm->ops->createglobalvector              = DMCreateGlobalVector_Swarm;
1183   dm->ops->createlocalvector               = DMCreateLocalVector_Swarm;
1184   dm->ops->getlocaltoglobalmapping         = NULL;
1185   dm->ops->createfieldis                   = NULL;
1186   dm->ops->createcoordinatedm              = NULL;
1187   dm->ops->getcoloring                     = NULL;
1188   dm->ops->creatematrix                    = NULL;
1189   dm->ops->createinterpolation             = NULL;
1190   dm->ops->getaggregates                   = NULL;
1191   dm->ops->getinjection                    = NULL;
1192   dm->ops->refine                          = NULL;
1193   dm->ops->coarsen                         = NULL;
1194   dm->ops->refinehierarchy                 = NULL;
1195   dm->ops->coarsenhierarchy                = NULL;
1196   dm->ops->globaltolocalbegin              = NULL;
1197   dm->ops->globaltolocalend                = NULL;
1198   dm->ops->localtoglobalbegin              = NULL;
1199   dm->ops->localtoglobalend                = NULL;
1200   dm->ops->destroy                         = DMDestroy_Swarm;
1201   dm->ops->createsubdm                     = NULL;
1202   dm->ops->getdimpoints                    = NULL;
1203   dm->ops->locatepoints                    = NULL;
1204 
1205   PetscFunctionReturn(0);
1206 }