xref: /petsc/src/dm/impls/swarm/swarm.c (revision f0cdbbba46eb2dee2dd444b383259dc1f084f526)
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 
18 //typedef PetscErrorCode (*swarm_project)(DM,DM,Vec) DMSwarmProjectMethod; /* swarm, geometry, result */
19 
20 //typedef enum { PROJECT_DMDA_AQ1=0, PROJECT_DMDA_P0 } DMSwarmDMDAProjectionType;
21 
22 #if 0
23 
24 /* Defines what the local space will be */
25 PetscErrorCode DMSwarmSetOverlap(void)
26 {
27 
28   PetscFunctionReturn(0);
29 }
30 
31 
32 /* coordinates */
33 /*
34 DMGetCoordinateDM returns self
35 DMGetCoordinates and DMGetCoordinatesLocal return same thing
36 Local view could be used to define overlapping information
37 */
38 
39 #endif
40 
41 #undef __FUNCT__
42 #define __FUNCT__ "DMSwarmVectorDefineField"
43 PETSC_EXTERN PetscErrorCode DMSwarmVectorDefineField(DM dm,const char fieldname[])
44 {
45   DM_Swarm *swarm = (DM_Swarm*)dm->data;
46   PetscErrorCode ierr;
47   PetscInt bs,n;
48   PetscScalar *array;
49   PetscDataType type;
50 
51   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
52   ierr = DataBucketGetSizes(swarm->db,&n,NULL,NULL);CHKERRQ(ierr);
53   ierr = DMSwarmGetField(dm,fieldname,&bs,&type,(void**)&array);CHKERRQ(ierr);
54 
55   /* Check all fields are of type PETSC_REAL or PETSC_SCALAR */
56   if (type != PETSC_REAL) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only valid for PETSC_REAL");
57 
58   PetscSNPrintf(swarm->vec_field_name,PETSC_MAX_PATH_LEN-1,"%s",fieldname);
59   swarm->vec_field_set = PETSC_TRUE;
60   swarm->vec_field_bs = bs;
61   swarm->vec_field_nlocal = n;
62   ierr = DMSwarmRestoreField(dm,fieldname,&bs,&type,(void**)&array);CHKERRQ(ierr);
63 
64   PetscFunctionReturn(0);
65 }
66 
67 /* requires DMSwarmDefineFieldVector has been called */
68 #undef __FUNCT__
69 #define __FUNCT__ "DMCreateGlobalVector_Swarm"
70 PetscErrorCode DMCreateGlobalVector_Swarm(DM dm,Vec *vec)
71 {
72   DM_Swarm *swarm = (DM_Swarm*)dm->data;
73   PetscErrorCode ierr;
74   Vec x;
75   char name[PETSC_MAX_PATH_LEN];
76 
77   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
78   if (!swarm->vec_field_set) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmVectorDefineField first");
79   PetscSNPrintf(name,PETSC_MAX_PATH_LEN-1,"DMSwarmField_%s",swarm->vec_field_name);
80   ierr = VecCreate(PetscObjectComm((PetscObject)dm),&x);CHKERRQ(ierr);
81   ierr = PetscObjectSetName((PetscObject)x,name);CHKERRQ(ierr);
82   ierr = VecSetSizes(x,swarm->db->L*swarm->vec_field_bs,PETSC_DETERMINE);CHKERRQ(ierr);
83   ierr = VecSetBlockSize(x,swarm->vec_field_bs);CHKERRQ(ierr);
84   ierr = VecSetFromOptions(x);CHKERRQ(ierr);
85   *vec = x;
86 
87   PetscFunctionReturn(0);
88 }
89 
90 /* requires DMSwarmDefineFieldVector has been called */
91 #undef __FUNCT__
92 #define __FUNCT__ "DMCreateLocalVector_Swarm"
93 PetscErrorCode DMCreateLocalVector_Swarm(DM dm,Vec *vec)
94 {
95   DM_Swarm *swarm = (DM_Swarm*)dm->data;
96   PetscErrorCode ierr;
97   Vec x;
98   char name[PETSC_MAX_PATH_LEN];
99 
100   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
101   if (!swarm->vec_field_set) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmVectorDefineField first");
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 #undef __FUNCT__
114 #define __FUNCT__ "DMSwarmCreateGlobalVectorFromField"
115 PETSC_EXTERN PetscErrorCode DMSwarmCreateGlobalVectorFromField(DM dm,const char fieldname[],Vec *vec)
116 {
117   DM_Swarm *swarm = (DM_Swarm*)dm->data;
118   PetscErrorCode ierr;
119   PetscInt bs,n;
120   PetscScalar *array;
121   Vec x;
122   PetscDataType type;
123   char name[PETSC_MAX_PATH_LEN];
124   PetscMPIInt commsize;
125 
126   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
127   ierr = DataBucketGetSizes(swarm->db,&n,NULL,NULL);CHKERRQ(ierr);
128   ierr = DMSwarmGetField(dm,fieldname,&bs,&type,(void**)&array);CHKERRQ(ierr);
129 
130   /* Check all fields are of type PETSC_REAL or PETSC_SCALAR */
131   if (type != PETSC_REAL) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only valid for PETSC_REAL");
132 
133   ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm),&commsize);CHKERRQ(ierr);
134   if (commsize == 1) {
135     ierr = VecCreateSeqWithArray(PetscObjectComm((PetscObject)dm),bs,n*bs,array,&x);CHKERRQ(ierr);
136   } else {
137     ierr = VecCreateMPIWithArray(PetscObjectComm((PetscObject)dm),bs,n*bs,PETSC_DETERMINE,array,&x);CHKERRQ(ierr);
138   }
139   PetscSNPrintf(name,PETSC_MAX_PATH_LEN-1,"DMSwarmSharedField_%s",fieldname);
140   ierr = PetscObjectSetName((PetscObject)x,name);CHKERRQ(ierr);
141 
142   /* Set guard */
143   PetscSNPrintf(name,PETSC_MAX_PATH_LEN-1,"DMSwarm_VecFieldInPlace_%s",fieldname);
144   ierr = PetscObjectComposeFunction((PetscObject)x,name,DMSwarmDestroyGlobalVectorFromField);CHKERRQ(ierr);
145 
146   *vec = x;
147   PetscFunctionReturn(0);
148 }
149 
150 #undef __FUNCT__
151 #define __FUNCT__ "DMSwarmDestroyGlobalVectorFromField"
152 PETSC_EXTERN PetscErrorCode DMSwarmDestroyGlobalVectorFromField(DM dm,const char fieldname[],Vec *vec)
153 {
154   DM_Swarm *swarm = (DM_Swarm*)dm->data;
155   PetscErrorCode ierr;
156   DataField gfield;
157   char name[PETSC_MAX_PATH_LEN];
158   void (*fptr)(void);
159 
160   /* get data field */
161   ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
162 
163   /* check vector is an inplace array */
164   PetscSNPrintf(name,PETSC_MAX_PATH_LEN-1,"DMSwarm_VecFieldInPlace_%s",fieldname);
165   ierr = PetscObjectQueryFunction((PetscObject)(*vec),name,&fptr);CHKERRQ(ierr);
166   if (!fptr) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Vector being destroyed was not created from DMSwarm field(%s)",fieldname);
167 
168   /* restore data field */
169   ierr = DataFieldRestoreAccess(gfield);CHKERRQ(ierr);
170 
171   ierr = VecDestroy(vec);CHKERRQ(ierr);
172 
173   PetscFunctionReturn(0);
174 }
175 
176 /*
177 PETSC_EXTERN PetscErrorCode DMSwarmCreateGlobalVectorFromFields(DM dm,const PetscInt nf,const char *fieldnames[],Vec *vec)
178 {
179   PetscFunctionReturn(0);
180 }
181 
182 PETSC_EXTERN PetscErrorCode DMSwarmRestoreGlobalVectorFromFields(DM dm,Vec *vec)
183 {
184   PetscFunctionReturn(0);
185 }
186 */
187 
188 #undef __FUNCT__
189 #define __FUNCT__ "DMSwarmInitializeFieldRegister"
190 PETSC_EXTERN PetscErrorCode DMSwarmInitializeFieldRegister(DM dm)
191 {
192   DM_Swarm *swarm = (DM_Swarm*)dm->data;
193   PetscErrorCode ierr;
194 
195   swarm->field_registration_initialized = PETSC_TRUE;
196 
197   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_pid,1,PETSC_LONG);CHKERRQ(ierr); /* unique identifer */
198   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_rank,1,PETSC_INT);CHKERRQ(ierr); /* used for communication */
199 
200   PetscFunctionReturn(0);
201 }
202 
203 #undef __FUNCT__
204 #define __FUNCT__ "DMSwarmFinalizeFieldRegister"
205 PETSC_EXTERN PetscErrorCode DMSwarmFinalizeFieldRegister(DM dm)
206 {
207   DM_Swarm *swarm = (DM_Swarm*)dm->data;
208   PetscErrorCode ierr;
209 
210   if (!swarm->field_registration_finalized) {
211     ierr = DataBucketFinalize(swarm->db);CHKERRQ(ierr);
212   }
213   swarm->field_registration_finalized = PETSC_TRUE;
214   PetscFunctionReturn(0);
215 }
216 
217 #undef __FUNCT__
218 #define __FUNCT__ "DMSwarmSetLocalSizes"
219 PETSC_EXTERN PetscErrorCode DMSwarmSetLocalSizes(DM dm,PetscInt nlocal,PetscInt buffer)
220 {
221   DM_Swarm *swarm = (DM_Swarm*)dm->data;
222   PetscErrorCode ierr;
223 
224   ierr = DataBucketSetSizes(swarm->db,nlocal,buffer);CHKERRQ(ierr);
225 
226   PetscFunctionReturn(0);
227 }
228 
229 #undef __FUNCT__
230 #define __FUNCT__ "DMSwarmSetCellDM"
231 PETSC_EXTERN PetscErrorCode DMSwarmSetCellDM(DM dm,DM dmcell)
232 {
233   DM_Swarm *swarm = (DM_Swarm*)dm->data;
234   swarm->dmcell = dmcell;
235   PetscFunctionReturn(0);
236 }
237 
238 #undef __FUNCT__
239 #define __FUNCT__ "DMSwarmGetCellDM"
240 PETSC_EXTERN PetscErrorCode DMSwarmGetCellDM(DM dm,DM *dmcell)
241 {
242   DM_Swarm *swarm = (DM_Swarm*)dm->data;
243   *dmcell = swarm->dmcell;
244   PetscFunctionReturn(0);
245 }
246 
247 #undef __FUNCT__
248 #define __FUNCT__ "DMSwarmGetLocalSize"
249 PETSC_EXTERN PetscErrorCode DMSwarmGetLocalSize(DM dm,PetscInt *nlocal)
250 {
251   DM_Swarm *swarm = (DM_Swarm*)dm->data;
252   PetscErrorCode ierr;
253 
254   if (nlocal) {
255     ierr = DataBucketGetSizes(swarm->db,nlocal,NULL,NULL);CHKERRQ(ierr);
256   }
257 
258   PetscFunctionReturn(0);
259 }
260 
261 #undef __FUNCT__
262 #define __FUNCT__ "DMSwarmGetSize"
263 PETSC_EXTERN PetscErrorCode DMSwarmGetSize(DM dm,PetscInt *n)
264 {
265   DM_Swarm *swarm = (DM_Swarm*)dm->data;
266   PetscErrorCode ierr;
267   PetscInt nlocal,ng;
268 
269   ierr = DataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
270   ierr = MPI_Allreduce(&nlocal,&ng,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
271   if (n) { *n = ng; }
272   PetscFunctionReturn(0);
273 }
274 
275 #undef __FUNCT__
276 #define __FUNCT__ "DMSwarmRegisterPetscDatatypeField"
277 PETSC_EXTERN PetscErrorCode DMSwarmRegisterPetscDatatypeField(DM dm,const char fieldname[],PetscInt blocksize,PetscDataType type)
278 {
279   PetscErrorCode ierr;
280   DM_Swarm *swarm = (DM_Swarm*)dm->data;
281   size_t size;
282 
283   if (!swarm->field_registration_initialized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmInitializeFieldRegister() first");
284   if (swarm->field_registration_finalized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Cannot register additional fields after calling DMSwarmFinalizeFieldRegister() first");
285 
286   if (type == PETSC_OBJECT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
287   if (type == PETSC_FUNCTION) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
288   if (type == PETSC_STRING) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
289   if (type == PETSC_STRUCT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
290   if (type == PETSC_DATATYPE_UNKNOWN) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
291 
292   switch (type) {
293     case PETSC_CHAR:
294       size = sizeof(PetscChar);
295       break;
296     case PETSC_SHORT:
297       size = sizeof(PetscShort);
298       break;
299     case PETSC_INT:
300       size = sizeof(PetscInt);
301       break;
302     case PETSC_LONG:
303       size = sizeof(Petsc64bitInt);
304       break;
305     case PETSC_FLOAT:
306       size = sizeof(PetscFloat);
307       break;
308     case PETSC_DOUBLE:
309       size = sizeof(PetscReal);
310       break;
311 
312     default:
313       SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
314       break;
315   }
316 
317   /* Load a specific data type into data bucket, specifying textual name and its size in bytes */
318 	ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterPetscDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
319   {
320     DataField gfield;
321 
322     ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
323     ierr = DataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
324   }
325   swarm->db->field[swarm->db->nfields-1]->petsc_type = type;
326 
327   PetscFunctionReturn(0);
328 }
329 
330 #undef __FUNCT__
331 #define __FUNCT__ "DMSwarmRegisterUserStructField"
332 PETSC_EXTERN PetscErrorCode DMSwarmRegisterUserStructField(DM dm,const char fieldname[],size_t size)
333 {
334   PetscErrorCode ierr;
335   DM_Swarm *swarm = (DM_Swarm*)dm->data;
336 
337 	ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterUserStructField",fieldname,size,NULL);CHKERRQ(ierr);
338   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_STRUCT ;
339 
340   PetscFunctionReturn(0);
341 }
342 
343 #undef __FUNCT__
344 #define __FUNCT__ "DMSwarmRegisterUserDatatypeField"
345 PETSC_EXTERN PetscErrorCode DMSwarmRegisterUserDatatypeField(DM dm,const char fieldname[],size_t size,PetscInt blocksize)
346 {
347   DM_Swarm *swarm = (DM_Swarm*)dm->data;
348   PetscErrorCode ierr;
349 
350 	ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterUserDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
351   {
352     DataField gfield;
353 
354     ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
355     ierr = DataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
356   }
357   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_DATATYPE_UNKNOWN;
358 
359   PetscFunctionReturn(0);
360 }
361 
362 #undef __FUNCT__
363 #define __FUNCT__ "DMSwarmGetField"
364 PETSC_EXTERN PetscErrorCode DMSwarmGetField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
365 {
366   DM_Swarm *swarm = (DM_Swarm*)dm->data;
367   DataField gfield;
368   PetscErrorCode ierr;
369 
370   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
371 
372   ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
373   ierr = DataFieldGetAccess(gfield);CHKERRQ(ierr);
374   ierr = DataFieldGetEntries(gfield,data);CHKERRQ(ierr);
375   if (blocksize) {*blocksize = gfield->bs; }
376   if (type) { *type = gfield->petsc_type; }
377 
378   PetscFunctionReturn(0);
379 }
380 
381 #undef __FUNCT__
382 #define __FUNCT__ "DMSwarmRestoreField"
383 PETSC_EXTERN PetscErrorCode DMSwarmRestoreField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
384 {
385   DM_Swarm *swarm = (DM_Swarm*)dm->data;
386   DataField gfield;
387   PetscErrorCode ierr;
388 
389   ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
390   ierr = DataFieldRestoreAccess(gfield);CHKERRQ(ierr);
391   if (data) *data = NULL;
392 
393   PetscFunctionReturn(0);
394 }
395 
396 #undef __FUNCT__
397 #define __FUNCT__ "DMSwarmAddPoint"
398 PETSC_EXTERN PetscErrorCode DMSwarmAddPoint(DM dm)
399 {
400   DM_Swarm *swarm = (DM_Swarm*)dm->data;
401   PetscErrorCode ierr;
402 
403   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
404   ierr = DataBucketAddPoint(swarm->db);CHKERRQ(ierr);
405   PetscFunctionReturn(0);
406 }
407 
408 #undef __FUNCT__
409 #define __FUNCT__ "DMSwarmAddNPoints"
410 PETSC_EXTERN PetscErrorCode DMSwarmAddNPoints(DM dm,PetscInt npoints)
411 {
412   DM_Swarm *swarm = (DM_Swarm*)dm->data;
413   PetscErrorCode ierr;
414   PetscInt nlocal;
415 
416   ierr = DataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
417   nlocal = nlocal + npoints;
418   ierr = DataBucketSetSizes(swarm->db,nlocal,-1);CHKERRQ(ierr);
419   PetscFunctionReturn(0);
420 }
421 
422 #undef __FUNCT__
423 #define __FUNCT__ "DMSwarmRemovePoint"
424 PETSC_EXTERN PetscErrorCode DMSwarmRemovePoint(DM dm)
425 {
426   DM_Swarm *swarm = (DM_Swarm*)dm->data;
427   PetscErrorCode ierr;
428 
429   ierr = DataBucketRemovePoint(swarm->db);CHKERRQ(ierr);
430   PetscFunctionReturn(0);
431 }
432 
433 #undef __FUNCT__
434 #define __FUNCT__ "DMSwarmRemovePointAtIndex"
435 PETSC_EXTERN PetscErrorCode DMSwarmRemovePointAtIndex(DM dm,PetscInt idx)
436 {
437   DM_Swarm *swarm = (DM_Swarm*)dm->data;
438   PetscErrorCode ierr;
439 
440   ierr = DataBucketRemovePointAtIndex(swarm->db,idx);CHKERRQ(ierr);
441   PetscFunctionReturn(0);
442 }
443 
444 #undef __FUNCT__
445 #define __FUNCT__ "DMSwarmMigrate_Basic"
446 PetscErrorCode DMSwarmMigrate_Basic(DM dm,PetscBool remove_sent_points)
447 {
448   PetscErrorCode ierr;
449   ierr = DMSwarmMigrate_Push_Basic(dm,remove_sent_points);CHKERRQ(ierr);
450   PetscFunctionReturn(0);
451 }
452 
453 PetscErrorCode DMSwarmMigrate_CellDMScatter(DM dm,PetscBool remove_sent_points);
454 PetscErrorCode DMSwarmMigrate_CellDMExact(DM dm,PetscBool remove_sent_points);
455 
456 #undef __FUNCT__
457 #define __FUNCT__ "DMSwarmMigrate"
458 PETSC_EXTERN PetscErrorCode DMSwarmMigrate(DM dm,PetscBool remove_sent_points)
459 {
460   DM_Swarm *swarm = (DM_Swarm*)dm->data;
461   PetscErrorCode ierr;
462 
463   switch (swarm->migrate_type) {
464 
465     case DMSWARM_MIGRATE_BASIC:
466       ierr = DMSwarmMigrate_Basic(dm,remove_sent_points);CHKERRQ(ierr);
467       break;
468 
469     case DMSWARM_MIGRATE_DMCELLNSCATTER:
470       ierr = DMSwarmMigrate_CellDMScatter(dm,remove_sent_points);CHKERRQ(ierr);
471       break;
472 
473     case DMSWARM_MIGRATE_DMCELLEXACT:
474       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_DMCELLEXACT not implemented");
475       //ierr = DMSwarmMigrate_CellDMExact(dm,remove_sent_points);CHKERRQ(ierr);
476       break;
477 
478     case DMSWARM_MIGRATE_USER:
479       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_USER not implemented");
480       //ierr = swarm->migrate(dm,remove_sent_points);CHKERRQ(ierr);
481       break;
482 
483     default:
484       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE type unknown");
485       break;
486   }
487   PetscFunctionReturn(0);
488 }
489 
490 PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm,PetscInt *globalsize);
491 
492 #undef __FUNCT__
493 #define __FUNCT__ "DMSwarmCollectViewCreate"
494 PETSC_EXTERN PetscErrorCode DMSwarmCollectViewCreate(DM dm)
495 {
496   PetscErrorCode ierr;
497   DM_Swarm *swarm = (DM_Swarm*)dm->data;
498   PetscInt ng;
499 
500   if (swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView currently active");
501 
502   ierr = DMSwarmGetLocalSize(dm,&ng);CHKERRQ(ierr);
503   switch (swarm->collect_type) {
504 
505     case DMSWARM_COLLECT_BASIC:
506       ierr = DMSwarmMigrate_GlobalToLocal_Basic(dm,&ng);CHKERRQ(ierr);
507       break;
508 
509     case DMSWARM_COLLECT_DMDABOUNDINGBOX:
510       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_DMDABOUNDINGBOX not implemented");
511       //ierr = DMSwarmCollect_DMDABoundingBox(dm,&ng);CHKERRQ(ierr);
512       break;
513 
514     case DMSWARM_COLLECT_GENERAL:
515       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_GENERAL not implemented");
516       //ierr = DMSwarmCollect_General(dm,..,,..,&ng);CHKERRQ(ierr);
517       break;
518 
519     default:
520       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT type unknown");
521       break;
522   }
523 
524   swarm->collect_view_active = PETSC_TRUE;
525   swarm->collect_view_reset_nlocal = ng;
526 
527   PetscFunctionReturn(0);
528 }
529 
530 #undef __FUNCT__
531 #define __FUNCT__ "DMSwarmCollectViewDestroy"
532 PETSC_EXTERN PetscErrorCode DMSwarmCollectViewDestroy(DM dm)
533 {
534   PetscErrorCode ierr;
535   DM_Swarm *swarm = (DM_Swarm*)dm->data;
536 
537   if (!swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView is currently not active");
538   ierr = DMSwarmSetLocalSizes(dm,swarm->collect_view_reset_nlocal,-1);CHKERRQ(ierr);
539   swarm->collect_view_active = PETSC_FALSE;
540 
541   PetscFunctionReturn(0);
542 }
543 
544 #undef __FUNCT__
545 #define __FUNCT__ "DMSwarmSetUpPIC"
546 PetscErrorCode DMSwarmSetUpPIC(DM dm)
547 {
548   PetscInt dim;
549   PetscErrorCode ierr;
550 
551   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
552   if (dim < 1) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
553   if (dim > 3) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
554   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_coor,dim,PETSC_DOUBLE);CHKERRQ(ierr);
555   PetscFunctionReturn(0);
556 }
557 
558 #undef __FUNCT__
559 #define __FUNCT__ "DMSwarmSetType"
560 PETSC_EXTERN PetscErrorCode DMSwarmSetType(DM dm,DMSwarmType stype)
561 {
562   DM_Swarm *swarm = (DM_Swarm*)dm->data;
563   PetscErrorCode ierr;
564 
565   swarm->swarm_type = stype;
566   if (swarm->swarm_type == DMSWARM_PIC) {
567     ierr = DMSwarmSetUpPIC(dm);CHKERRQ(ierr);
568   }
569   PetscFunctionReturn(0);
570 }
571 
572 #undef __FUNCT__
573 #define __FUNCT__ "DMSetup_Swarm"
574 PetscErrorCode DMSetup_Swarm(DM dm)
575 {
576   DM_Swarm *swarm = (DM_Swarm*)dm->data;
577   PetscErrorCode ierr;
578   PetscMPIInt rank;
579   PetscInt p,npoints,*rankval;
580 
581   if (swarm->issetup) PetscFunctionReturn(0);
582 
583   swarm->issetup = PETSC_TRUE;
584 
585   if (swarm->swarm_type == DMSWARM_PIC) {
586     /* check dmcell exists */
587     if (!swarm->dmcell) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires you call DMSwarmSetCellDM");
588 
589     if (swarm->dmcell->ops->locatepointssubdomain) {
590       /* check methods exists for exact ownership identificiation */
591       PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->ops->LocatePointsSubdomain\n");
592       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLEXACT;
593     } else {
594       /* check methods exist for point location AND rank neighbor identification */
595       if (swarm->dmcell->ops->locatepoints) {
596         PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->LocatePoints\n");
597       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->locatepoints be defined");
598 
599       if (swarm->dmcell->ops->getneighbors) {
600         PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->GetNeigbors\n");
601       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->getneighbors be defined");
602 
603       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLNSCATTER;
604     }
605   }
606 
607   ierr = DMSwarmFinalizeFieldRegister(dm);CHKERRQ(ierr);
608 
609   /* check some fields were registered */
610   if (swarm->db->nfields <= 2) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"At least one field user must be registered via DMSwarmRegisterXXX()");
611 
612   /* check local sizes were set */
613   if (swarm->db->L == -1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Local sizes must be set via DMSwarmSetLocalSizes()");
614 
615   /* initialize values in pid and rank placeholders */
616   /* TODO: [pid - use MPI_Scan] */
617 
618   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
619   ierr = DataBucketGetSizes(swarm->db,&npoints,NULL,NULL);CHKERRQ(ierr);
620   ierr = DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
621   for (p=0; p<npoints; p++) {
622     rankval[p] = (PetscInt)rank;
623   }
624   ierr = DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
625 
626   PetscFunctionReturn(0);
627 }
628 
629 #undef __FUNCT__
630 #define __FUNCT__ "DMDestroy_Swarm"
631 PetscErrorCode DMDestroy_Swarm(DM dm)
632 {
633   DM_Swarm *swarm = (DM_Swarm*)dm->data;
634   PetscErrorCode ierr;
635 
636   PetscFunctionBegin;
637   ierr = DataBucketDestroy(&swarm->db);CHKERRQ(ierr);
638   ierr = PetscFree(swarm);CHKERRQ(ierr);
639   PetscFunctionReturn(0);
640 }
641 
642 #undef __FUNCT__
643 #define __FUNCT__ "DMView_Swarm"
644 PetscErrorCode DMView_Swarm(DM dm, PetscViewer viewer)
645 {
646   DM_Swarm *swarm = (DM_Swarm*)dm->data;
647   PetscBool      iascii,ibinary,ishdf5,isvtk;
648   PetscErrorCode ierr;
649 
650   PetscFunctionBegin;
651   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
652   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
653   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
654   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY,&ibinary);CHKERRQ(ierr);
655   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK,   &isvtk);CHKERRQ(ierr);
656   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
657   if (iascii) {
658     ierr = DataBucketView(PetscObjectComm((PetscObject)dm),swarm->db,NULL,DATABUCKET_VIEW_STDOUT);CHKERRQ(ierr);
659   } else if (ibinary) {
660     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO VTK support");
661   } else if (ishdf5) {
662 #if defined(PETSC_HAVE_HDF5)
663     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO HDF5 support");
664 #else
665     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"HDF5 not supported. Please reconfigure using --download-hdf5");
666 #endif
667   } else if (isvtk) {
668     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO VTK support");
669   }
670   PetscFunctionReturn(0);
671 }
672 
673 #undef __FUNCT__
674 #define __FUNCT__ "DMCreate_Swarm"
675 PETSC_EXTERN PetscErrorCode DMCreate_Swarm(DM dm)
676 {
677   DM_Swarm      *swarm;
678   PetscErrorCode ierr;
679 
680   PetscFunctionBegin;
681   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
682   ierr     = PetscNewLog(dm,&swarm);CHKERRQ(ierr);
683   dm->data = swarm;
684 
685   ierr = DataBucketCreate(&swarm->db);CHKERRQ(ierr);
686   ierr = DMSwarmInitializeFieldRegister(dm);CHKERRQ(ierr);
687 
688   swarm->vec_field_set = PETSC_FALSE;
689   swarm->issetup = PETSC_FALSE;
690   swarm->swarm_type = DMSWARM_BASIC;
691   swarm->migrate_type = DMSWARM_MIGRATE_BASIC;
692   swarm->collect_type = DMSWARM_COLLECT_BASIC;
693   swarm->migrate_error_on_missing_point = PETSC_FALSE;
694 
695   swarm->dmcell = NULL;
696   swarm->collect_view_active = PETSC_FALSE;
697   swarm->collect_view_reset_nlocal = -1;
698 
699   dm->dim  = 0;
700   dm->ops->view                            = DMView_Swarm;
701   dm->ops->load                            = NULL;
702   dm->ops->setfromoptions                  = NULL;
703   dm->ops->clone                           = NULL;
704   dm->ops->setup                           = DMSetup_Swarm;
705   dm->ops->createdefaultsection            = NULL;
706   dm->ops->createdefaultconstraints        = NULL;
707   dm->ops->createglobalvector              = DMCreateGlobalVector_Swarm;
708   dm->ops->createlocalvector               = DMCreateLocalVector_Swarm;
709   dm->ops->getlocaltoglobalmapping         = NULL;
710   dm->ops->createfieldis                   = NULL;
711   dm->ops->createcoordinatedm              = NULL;
712   dm->ops->getcoloring                     = NULL;
713   dm->ops->creatematrix                    = NULL;
714   dm->ops->createinterpolation             = NULL;
715   dm->ops->getaggregates                   = NULL;
716   dm->ops->getinjection                    = NULL;
717   dm->ops->refine                          = NULL;
718   dm->ops->coarsen                         = NULL;
719   dm->ops->refinehierarchy                 = NULL;
720   dm->ops->coarsenhierarchy                = NULL;
721   dm->ops->globaltolocalbegin              = NULL;
722   dm->ops->globaltolocalend                = NULL;
723   dm->ops->localtoglobalbegin              = NULL;
724   dm->ops->localtoglobalend                = NULL;
725   dm->ops->destroy                         = DMDestroy_Swarm;
726   dm->ops->createsubdm                     = NULL;
727   dm->ops->getdimpoints                    = NULL;
728   dm->ops->locatepoints                    = NULL;
729 
730   PetscFunctionReturn(0);
731 }