xref: /petsc/src/dm/impls/swarm/swarm.c (revision 895a1698f8b367a403f6cc7079c284c6ba82f4f1)
1 #define PETSCDM_DLL
2 #include <petsc/private/dmswarmimpl.h>    /*I   "petscdmswarm.h"   I*/
3 #include <petsc/private/hash.h>
4 #include <petscviewer.h>
5 #include <petscdraw.h>
6 #include <petscdmplex.h>
7 #include "data_bucket.h"
8 
9 PetscLogEvent DMSWARM_Migrate, DMSWARM_SetSizes, DMSWARM_AddPoints, DMSWARM_RemovePoints, DMSWARM_Sort;
10 PetscLogEvent DMSWARM_DataExchangerTopologySetup, DMSWARM_DataExchangerBegin, DMSWARM_DataExchangerEnd;
11 PetscLogEvent DMSWARM_DataExchangerSendCount, DMSWARM_DataExchangerPack;
12 
13 const char* DMSwarmTypeNames[] = { "basic", "pic", 0 };
14 const char* DMSwarmMigrateTypeNames[] = { "basic", "dmcellnscatter", "dmcellexact", "user", 0 };
15 const char* DMSwarmCollectTypeNames[] = { "basic", "boundingbox", "general", "user", 0 };
16 const char* DMSwarmPICLayoutTypeNames[] = { "regular", "gauss", "subdivision", 0 };
17 
18 const char DMSwarmField_pid[] = "DMSwarm_pid";
19 const char DMSwarmField_rank[] = "DMSwarm_rank";
20 const char DMSwarmPICField_coor[] = "DMSwarmPIC_coor";
21 const char DMSwarmPICField_cellid[] = "DMSwarm_cellid";
22 
23 /*@C
24    DMSwarmVectorDefineField - Sets the field from which to define a Vec object
25                              when DMCreateLocalVector(), or DMCreateGlobalVector() is called
26 
27    Collective on DM
28 
29    Input parameters:
30 +  dm - a DMSwarm
31 -  fieldname - the textual name given to a registered field
32 
33    Level: beginner
34 
35    Notes:
36    The field with name fieldname must be defined as having a data type of PetscScalar.
37    This function must be called prior to calling DMCreateLocalVector(), DMCreateGlobalVector().
38    Mutiple calls to DMSwarmVectorDefineField() are permitted.
39 
40 .seealso: DMSwarmRegisterPetscDatatypeField(), DMCreateGlobalVector(), DMCreateLocalVector()
41 @*/
42 PETSC_EXTERN PetscErrorCode DMSwarmVectorDefineField(DM dm,const char fieldname[])
43 {
44   DM_Swarm *swarm = (DM_Swarm*)dm->data;
45   PetscErrorCode ierr;
46   PetscInt bs,n;
47   PetscScalar *array;
48   PetscDataType type;
49 
50   PetscFunctionBegin;
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   ierr = PetscSNPrintf(swarm->vec_field_name,PETSC_MAX_PATH_LEN-1,"%s",fieldname);CHKERRQ(ierr);
58   swarm->vec_field_set = PETSC_TRUE;
59   swarm->vec_field_bs = bs;
60   swarm->vec_field_nlocal = n;
61   ierr = DMSwarmRestoreField(dm,fieldname,&bs,&type,(void**)&array);CHKERRQ(ierr);
62   PetscFunctionReturn(0);
63 }
64 
65 /* requires DMSwarmDefineFieldVector has been called */
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   PetscFunctionBegin;
74   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
75   if (!swarm->vec_field_set) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmVectorDefineField first");
76   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 */
77 
78   ierr = PetscSNPrintf(name,PETSC_MAX_PATH_LEN-1,"DMSwarmField_%s",swarm->vec_field_name);CHKERRQ(ierr);
79   ierr = VecCreate(PetscObjectComm((PetscObject)dm),&x);CHKERRQ(ierr);
80   ierr = PetscObjectSetName((PetscObject)x,name);CHKERRQ(ierr);
81   ierr = VecSetSizes(x,swarm->db->L*swarm->vec_field_bs,PETSC_DETERMINE);CHKERRQ(ierr);
82   ierr = VecSetBlockSize(x,swarm->vec_field_bs);CHKERRQ(ierr);
83   ierr = VecSetFromOptions(x);CHKERRQ(ierr);
84   *vec = x;
85   PetscFunctionReturn(0);
86 }
87 
88 /* requires DMSwarmDefineFieldVector has been called */
89 PetscErrorCode DMCreateLocalVector_Swarm(DM dm,Vec *vec)
90 {
91   DM_Swarm *swarm = (DM_Swarm*)dm->data;
92   PetscErrorCode ierr;
93   Vec x;
94   char name[PETSC_MAX_PATH_LEN];
95 
96   PetscFunctionBegin;
97   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
98   if (!swarm->vec_field_set) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmVectorDefineField first");
99   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 */
100 
101   ierr = PetscSNPrintf(name,PETSC_MAX_PATH_LEN-1,"DMSwarmField_%s",swarm->vec_field_name);CHKERRQ(ierr);
102   ierr = VecCreate(PETSC_COMM_SELF,&x);CHKERRQ(ierr);
103   ierr = PetscObjectSetName((PetscObject)x,name);CHKERRQ(ierr);
104   ierr = VecSetSizes(x,swarm->db->L*swarm->vec_field_bs,PETSC_DETERMINE);CHKERRQ(ierr);
105   ierr = VecSetBlockSize(x,swarm->vec_field_bs);CHKERRQ(ierr);
106   ierr = VecSetFromOptions(x);CHKERRQ(ierr);
107   *vec = x;
108   PetscFunctionReturn(0);
109 }
110 
111 static PetscErrorCode DMSwarmDestroyVectorFromField_Private(DM dm, const char fieldname[], Vec *vec)
112 {
113   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
114   DataField      gfield;
115   void         (*fptr)(void);
116   PetscInt       bs, nlocal;
117   char           name[PETSC_MAX_PATH_LEN];
118   PetscErrorCode ierr;
119 
120   PetscFunctionBegin;
121   ierr = VecGetLocalSize(*vec, &nlocal);CHKERRQ(ierr);
122   ierr = VecGetBlockSize(*vec, &bs);CHKERRQ(ierr);
123   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 */
124   ierr = DataBucketGetDataFieldByName(swarm->db, fieldname, &gfield);CHKERRQ(ierr);
125   /* check vector is an inplace array */
126   ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarm_VecFieldInPlace_%s", fieldname);CHKERRQ(ierr);
127   ierr = PetscObjectQueryFunction((PetscObject) *vec, name, &fptr);CHKERRQ(ierr);
128   if (!fptr) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_USER, "Vector being destroyed was not created from DMSwarm field(%s)", fieldname);
129   ierr = DataFieldRestoreAccess(gfield);CHKERRQ(ierr);
130   ierr = VecDestroy(vec);CHKERRQ(ierr);
131   PetscFunctionReturn(0);
132 }
133 
134 static PetscErrorCode DMSwarmCreateVectorFromField_Private(DM dm, const char fieldname[], MPI_Comm comm, Vec *vec)
135 {
136   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
137   PetscDataType  type;
138   PetscScalar   *array;
139   PetscInt       bs, n;
140   char           name[PETSC_MAX_PATH_LEN];
141   PetscMPIInt    commsize;
142   PetscErrorCode ierr;
143 
144   PetscFunctionBegin;
145   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
146   ierr = DataBucketGetSizes(swarm->db, &n, NULL, NULL);CHKERRQ(ierr);
147   ierr = DMSwarmGetField(dm, fieldname, &bs, &type, (void **) &array);CHKERRQ(ierr);
148   if (type != PETSC_REAL) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Only valid for PETSC_REAL");
149 
150   ierr = MPI_Comm_size(comm, &commsize);CHKERRQ(ierr);
151   if (commsize == 1) {
152     ierr = VecCreateSeqWithArray(comm, bs, n*bs, array, vec);CHKERRQ(ierr);
153   } else {
154     ierr = VecCreateMPIWithArray(comm, bs, n*bs, PETSC_DETERMINE, array, vec);CHKERRQ(ierr);
155   }
156   ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarmSharedField_%s", fieldname);CHKERRQ(ierr);
157   ierr = PetscObjectSetName((PetscObject) *vec, name);CHKERRQ(ierr);
158 
159   /* Set guard */
160   ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarm_VecFieldInPlace_%s", fieldname);CHKERRQ(ierr);
161   ierr = PetscObjectComposeFunction((PetscObject) *vec, name, DMSwarmDestroyVectorFromField_Private);CHKERRQ(ierr);
162   PetscFunctionReturn(0);
163 }
164 
165 static PetscErrorCode DMSwarmComputeMassMatrix_Private(DM dmc, DM dmf, Mat mass, void *ctx)
166 {
167   const char    *name = "Mass Matrix";
168   PetscDS        prob;
169   PetscSection   fsection, globalFSection;
170   PetscHashJK    ht;
171   PetscLayout    rLayout;
172   PetscInt      *dnz, *onz;
173   PetscInt       locRows, rStart, rEnd;
174   PetscReal     *x, *v0, *J, *invJ, detJ;
175   PetscScalar   *elemMat;
176   PetscInt       dim, Nf, field, totDim, cStart, cEnd, cell;
177   PetscErrorCode ierr;
178 
179   PetscFunctionBegin;
180   ierr = DMGetCoordinateDim(dmf, &dim);CHKERRQ(ierr);
181   ierr = DMGetDS(dmf, &prob);CHKERRQ(ierr);
182   ierr = PetscDSGetRefCoordArrays(prob, &x, NULL);CHKERRQ(ierr);
183   ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr);
184   ierr = PetscMalloc3(dim,&v0,dim*dim,&J,dim*dim,&invJ);CHKERRQ(ierr);
185   ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);
186   ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);
187   ierr = DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd);CHKERRQ(ierr);
188   ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr);
189   ierr = PetscMalloc1(totDim, &elemMat);CHKERRQ(ierr);
190   ierr = DMSwarmSortGetAccess(dmc);CHKERRQ(ierr);
191 
192   ierr = MatGetLocalSize(mass, &locRows, NULL);CHKERRQ(ierr);
193   ierr = PetscLayoutCreate(PetscObjectComm((PetscObject) mass), &rLayout);CHKERRQ(ierr);
194   ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr);
195   ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr);
196   ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr);
197   ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr);
198   ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr);
199   ierr = PetscCalloc2(locRows,&dnz,locRows,&onz);CHKERRQ(ierr);
200   ierr = PetscHashJKCreate(&ht);CHKERRQ(ierr);
201   for (field = 0; field < Nf; ++field) {
202     PetscObject      obj;
203     PetscQuadrature  quad;
204     const PetscReal *qpoints;
205     PetscInt         Nq, Nc, i;
206 
207     ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr);
208     ierr = PetscFEGetQuadrature((PetscFE) obj, &quad);CHKERRQ(ierr);
209     ierr = PetscQuadratureGetData(quad, NULL, &Nc, &Nq, &qpoints, NULL);CHKERRQ(ierr);
210     /* For each fine grid cell */
211     for (cell = cStart; cell < cEnd; ++cell) {
212       PetscInt  Np, c;
213       PetscInt *findices,   *cindices;
214       PetscInt  numFIndices, numCIndices;
215 
216       ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
217       ierr = DMSwarmSortGetNumberOfPointsPerCell(dmc, cell, &Np);CHKERRQ(ierr);
218       /* Update preallocation info */
219       if (Np != Nq) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not all closure points located");
220       {
221         PetscHashJKKey  key;
222         PetscHashJKIter missing, iter;
223 
224         for (i = 0; i < numFIndices; ++i) {
225           key.j = findices[i];
226           if (key.j >= 0) {
227             /* Get indices for coarse elements */
228             ierr = DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices);CHKERRQ(ierr);
229             for (c = 0; c < numCIndices; ++c) {
230               key.k = cindices[c];
231               if (key.k < 0) continue;
232               ierr = PetscHashJKPut(ht, key, &missing, &iter);CHKERRQ(ierr);
233               if (missing) {
234                 ierr = PetscHashJKSet(ht, iter, 1);CHKERRQ(ierr);
235                 if ((key.k >= rStart) && (key.k < rEnd)) ++dnz[key.j-rStart];
236                 else                                     ++onz[key.j-rStart];
237               }
238             }
239             ierr = PetscFree(cindices);CHKERRQ(ierr);
240           }
241         }
242       }
243       ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
244     }
245   }
246   ierr = PetscHashJKDestroy(&ht);CHKERRQ(ierr);
247   ierr = MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL);CHKERRQ(ierr);
248   ierr = MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
249   ierr = PetscFree2(dnz,onz);CHKERRQ(ierr);
250   for (field = 0; field < Nf; ++field) {
251     PetscObject      obj;
252     PetscQuadrature  quad;
253     PetscReal       *Bfine;
254     const PetscReal *qweights;
255     PetscInt         Nq, Nc, i;
256 
257     ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr);
258     ierr = PetscFEGetDefaultTabulation((PetscFE) obj, &Bfine, NULL, NULL);CHKERRQ(ierr);
259     ierr = PetscFEGetQuadrature((PetscFE) obj, &quad);CHKERRQ(ierr);
260     ierr = PetscQuadratureGetData(quad, NULL, &Nc, &Nq, NULL, &qweights);CHKERRQ(ierr);
261     /* For each fine grid cell */
262     for (cell = cStart; cell < cEnd; ++cell) {
263       PetscInt           Np, c, j;
264       PetscInt          *findices,   *cindices;
265       PetscInt           numFIndices, numCIndices;
266 
267       ierr = DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr);
268       ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
269       ierr = DMSwarmSortGetNumberOfPointsPerCell(dmc, cell, &Np);CHKERRQ(ierr);
270       if (Np != Nq) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not all closure points located");
271       ierr = DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices);CHKERRQ(ierr);
272       /* Get elemMat entries by multiplying by weight */
273       for (i = 0; i < numFIndices; ++i) {
274         ierr = PetscMemzero(elemMat, numCIndices * sizeof(PetscScalar));CHKERRQ(ierr);
275         for (j = 0; j < numCIndices; ++j) {
276           for (c = 0; c < Nc; ++c) elemMat[j] += Bfine[(j*numFIndices + i)*Nc + c]*qweights[j*Nc + c]*detJ;
277         }
278         /* Update interpolator */
279         if (0) {ierr = DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat);CHKERRQ(ierr);}
280         ierr = MatSetValues(mass, 1, &findices[i], numCIndices, cindices, elemMat, ADD_VALUES);CHKERRQ(ierr);
281       }
282       ierr = PetscFree(cindices);CHKERRQ(ierr);
283       ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
284     }
285   }
286   ierr = DMSwarmSortRestoreAccess(dmc);CHKERRQ(ierr);
287   ierr = PetscFree3(v0,J,invJ);CHKERRQ(ierr);
288   ierr = PetscFree(elemMat);CHKERRQ(ierr);
289   ierr = MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
290   ierr = MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
291   PetscFunctionReturn(0);
292 }
293 
294 static PetscErrorCode DMCreateMassMatrix_Swarm(DM dmCoarse, DM dmFine, Mat *mass)
295 {
296   PetscSection   gsf;
297   PetscInt       m, n;
298   void          *ctx;
299   PetscErrorCode ierr;
300 
301   PetscFunctionBegin;
302   ierr = DMGetDefaultGlobalSection(dmFine, &gsf);CHKERRQ(ierr);
303   ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr);
304   ierr = DMSwarmGetLocalSize(dmCoarse, &n);CHKERRQ(ierr);
305 
306   ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr);
307   ierr = MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
308   ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr);
309   ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr);
310 
311   ierr = DMSwarmComputeMassMatrix_Private(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);
312   ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr);
313   PetscFunctionReturn(0);
314 }
315 
316 /*@C
317    DMSwarmCreateGlobalVectorFromField - Creates a Vec object sharing the array associated with a given field
318 
319    Collective on DM
320 
321    Input parameters:
322 +  dm - a DMSwarm
323 -  fieldname - the textual name given to a registered field
324 
325    Output parameter:
326 .  vec - the vector
327 
328    Level: beginner
329 
330    Notes:
331    The vector must be returned using a matching call to DMSwarmDestroyGlobalVectorFromField().
332 
333 .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmDestroyGlobalVectorFromField()
334 @*/
335 PETSC_EXTERN PetscErrorCode DMSwarmCreateGlobalVectorFromField(DM dm,const char fieldname[],Vec *vec)
336 {
337   MPI_Comm       comm = PetscObjectComm((PetscObject) dm);
338   PetscErrorCode ierr;
339 
340   PetscFunctionBegin;
341   ierr = DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec);CHKERRQ(ierr);
342   PetscFunctionReturn(0);
343 }
344 
345 /*@C
346    DMSwarmDestroyGlobalVectorFromField - Destroys the Vec object which share the array associated with a given field
347 
348    Collective on DM
349 
350    Input parameters:
351 +  dm - a DMSwarm
352 -  fieldname - the textual name given to a registered field
353 
354    Output parameter:
355 .  vec - the vector
356 
357    Level: beginner
358 
359 .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmCreateGlobalVectorFromField()
360 @*/
361 PETSC_EXTERN PetscErrorCode DMSwarmDestroyGlobalVectorFromField(DM dm,const char fieldname[],Vec *vec)
362 {
363   PetscErrorCode ierr;
364 
365   PetscFunctionBegin;
366   ierr = DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec);CHKERRQ(ierr);
367   PetscFunctionReturn(0);
368 }
369 
370 /*@C
371    DMSwarmCreateLocalVectorFromField - Creates a Vec object sharing the array associated with a given field
372 
373    Collective on DM
374 
375    Input parameters:
376 +  dm - a DMSwarm
377 -  fieldname - the textual name given to a registered field
378 
379    Output parameter:
380 .  vec - the vector
381 
382    Level: beginner
383 
384    Notes:
385    The vector must be returned using a matching call to DMSwarmDestroyLocalVectorFromField().
386 
387 .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmDestroyLocalVectorFromField()
388 @*/
389 PETSC_EXTERN PetscErrorCode DMSwarmCreateLocalVectorFromField(DM dm,const char fieldname[],Vec *vec)
390 {
391   MPI_Comm       comm = PETSC_COMM_SELF;
392   PetscErrorCode ierr;
393 
394   PetscFunctionBegin;
395   ierr = DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec);CHKERRQ(ierr);
396   PetscFunctionReturn(0);
397 }
398 
399 /*@C
400    DMSwarmDestroyLocalVectorFromField - Destroys the Vec object which share the array associated with a given field
401 
402    Collective on DM
403 
404    Input parameters:
405 +  dm - a DMSwarm
406 -  fieldname - the textual name given to a registered field
407 
408    Output parameter:
409 .  vec - the vector
410 
411    Level: beginner
412 
413 .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmCreateLocalVectorFromField()
414 @*/
415 PETSC_EXTERN PetscErrorCode DMSwarmDestroyLocalVectorFromField(DM dm,const char fieldname[],Vec *vec)
416 {
417   PetscErrorCode ierr;
418 
419   PetscFunctionBegin;
420   ierr = DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec);CHKERRQ(ierr);
421   PetscFunctionReturn(0);
422 }
423 
424 /*
425 PETSC_EXTERN PetscErrorCode DMSwarmCreateGlobalVectorFromFields(DM dm,const PetscInt nf,const char *fieldnames[],Vec *vec)
426 {
427   PetscFunctionReturn(0);
428 }
429 
430 PETSC_EXTERN PetscErrorCode DMSwarmRestoreGlobalVectorFromFields(DM dm,Vec *vec)
431 {
432   PetscFunctionReturn(0);
433 }
434 */
435 
436 /*@C
437    DMSwarmInitializeFieldRegister - Initiates the registration of fields to a DMSwarm
438 
439    Collective on DM
440 
441    Input parameter:
442 .  dm - a DMSwarm
443 
444    Level: beginner
445 
446    Notes:
447    After all fields have been registered, you must call DMSwarmFinalizeFieldRegister().
448 
449 .seealso: DMSwarmFinalizeFieldRegister(), DMSwarmRegisterPetscDatatypeField(),
450  DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
451 @*/
452 PETSC_EXTERN PetscErrorCode DMSwarmInitializeFieldRegister(DM dm)
453 {
454   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
455   PetscErrorCode ierr;
456 
457   PetscFunctionBegin;
458   if (!swarm->field_registration_initialized) {
459     swarm->field_registration_initialized = PETSC_TRUE;
460     ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_pid,1,PETSC_LONG);CHKERRQ(ierr); /* unique identifer */
461     ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_rank,1,PETSC_INT);CHKERRQ(ierr); /* used for communication */
462   }
463   PetscFunctionReturn(0);
464 }
465 
466 /*@C
467    DMSwarmFinalizeFieldRegister - Finalizes the registration of fields to a DMSwarm
468 
469    Collective on DM
470 
471    Input parameter:
472 .  dm - a DMSwarm
473 
474    Level: beginner
475 
476    Notes:
477    After DMSwarmFinalizeFieldRegister() has been called, no new fields can be defined on the DMSwarm.
478 
479 .seealso: DMSwarmInitializeFieldRegister(), DMSwarmRegisterPetscDatatypeField(),
480  DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
481 @*/
482 PETSC_EXTERN PetscErrorCode DMSwarmFinalizeFieldRegister(DM dm)
483 {
484   DM_Swarm *swarm = (DM_Swarm*)dm->data;
485   PetscErrorCode ierr;
486 
487   PetscFunctionBegin;
488   if (!swarm->field_registration_finalized) {
489     ierr = DataBucketFinalize(swarm->db);CHKERRQ(ierr);
490   }
491   swarm->field_registration_finalized = PETSC_TRUE;
492   PetscFunctionReturn(0);
493 }
494 
495 /*@C
496    DMSwarmSetLocalSizes - Sets the length of all registered fields on the DMSwarm
497 
498    Not collective
499 
500    Input parameters:
501 +  dm - a DMSwarm
502 .  nlocal - the length of each registered field
503 -  buffer - the length of the buffer used to efficient dynamic re-sizing
504 
505    Level: beginner
506 
507 .seealso: DMSwarmGetLocalSize()
508 @*/
509 PETSC_EXTERN PetscErrorCode DMSwarmSetLocalSizes(DM dm,PetscInt nlocal,PetscInt buffer)
510 {
511   DM_Swarm *swarm = (DM_Swarm*)dm->data;
512   PetscErrorCode ierr;
513 
514   PetscFunctionBegin;
515   ierr = PetscLogEventBegin(DMSWARM_SetSizes,0,0,0,0);CHKERRQ(ierr);
516   ierr = DataBucketSetSizes(swarm->db,nlocal,buffer);CHKERRQ(ierr);
517   ierr = PetscLogEventEnd(DMSWARM_SetSizes,0,0,0,0);CHKERRQ(ierr);
518   PetscFunctionReturn(0);
519 }
520 
521 /*@C
522    DMSwarmSetCellDM - Attachs a DM to a DMSwarm
523 
524    Collective on DM
525 
526    Input parameters:
527 +  dm - a DMSwarm
528 -  dmcell - the DM to attach to the DMSwarm
529 
530    Level: beginner
531 
532    Notes:
533    The attached DM (dmcell) will be queried for point location and
534    neighbor MPI-rank information if DMSwarmMigrate() is called.
535 
536 .seealso: DMSwarmSetType(), DMSwarmGetCellDM(), DMSwarmMigrate()
537 @*/
538 PETSC_EXTERN PetscErrorCode DMSwarmSetCellDM(DM dm,DM dmcell)
539 {
540   DM_Swarm *swarm = (DM_Swarm*)dm->data;
541 
542   PetscFunctionBegin;
543   swarm->dmcell = dmcell;
544   PetscFunctionReturn(0);
545 }
546 
547 /*@C
548    DMSwarmGetCellDM - Fetches the attached cell DM
549 
550    Collective on DM
551 
552    Input parameter:
553 .  dm - a DMSwarm
554 
555    Output parameter:
556 .  dmcell - the DM which was attached to the DMSwarm
557 
558    Level: beginner
559 
560 .seealso: DMSwarmSetCellDM()
561 @*/
562 PETSC_EXTERN PetscErrorCode DMSwarmGetCellDM(DM dm,DM *dmcell)
563 {
564   DM_Swarm *swarm = (DM_Swarm*)dm->data;
565 
566   PetscFunctionBegin;
567   *dmcell = swarm->dmcell;
568   PetscFunctionReturn(0);
569 }
570 
571 /*@C
572    DMSwarmGetLocalSize - Retrives the local length of fields registered
573 
574    Not collective
575 
576    Input parameter:
577 .  dm - a DMSwarm
578 
579    Output parameter:
580 .  nlocal - the length of each registered field
581 
582    Level: beginner
583 
584 .seealso: DMSwarmGetSize(), DMSwarmSetLocalSizes()
585 @*/
586 PETSC_EXTERN PetscErrorCode DMSwarmGetLocalSize(DM dm,PetscInt *nlocal)
587 {
588   DM_Swarm *swarm = (DM_Swarm*)dm->data;
589   PetscErrorCode ierr;
590 
591   PetscFunctionBegin;
592   if (nlocal) {ierr = DataBucketGetSizes(swarm->db,nlocal,NULL,NULL);CHKERRQ(ierr);}
593   PetscFunctionReturn(0);
594 }
595 
596 /*@C
597    DMSwarmGetSize - Retrives the total length of fields registered
598 
599    Collective on DM
600 
601    Input parameter:
602 .  dm - a DMSwarm
603 
604    Output parameter:
605 .  n - the total length of each registered field
606 
607    Level: beginner
608 
609    Note:
610    This calls MPI_Allreduce upon each call (inefficient but safe)
611 
612 .seealso: DMSwarmGetLocalSize(), DMSwarmSetLocalSizes()
613 @*/
614 PETSC_EXTERN PetscErrorCode DMSwarmGetSize(DM dm,PetscInt *n)
615 {
616   DM_Swarm *swarm = (DM_Swarm*)dm->data;
617   PetscErrorCode ierr;
618   PetscInt nlocal,ng;
619 
620   PetscFunctionBegin;
621   ierr = DataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
622   ierr = MPI_Allreduce(&nlocal,&ng,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
623   if (n) { *n = ng; }
624   PetscFunctionReturn(0);
625 }
626 
627 /*@C
628    DMSwarmRegisterPetscDatatypeField - Register a field to a DMSwarm with a native PETSc data type
629 
630    Collective on DM
631 
632    Input parameters:
633 +  dm - a DMSwarm
634 .  fieldname - the textual name to identify this field
635 .  blocksize - the number of each data type
636 -  type - a valid PETSc data type (PETSC_CHAR, PETSC_SHORT, PETSC_INT, PETSC_FLOAT, PETSC_REAL, PETSC_LONG)
637 
638    Level: beginner
639 
640    Notes:
641    The textual name for each registered field must be unique.
642 
643 .seealso: DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
644 @*/
645 PETSC_EXTERN PetscErrorCode DMSwarmRegisterPetscDatatypeField(DM dm,const char fieldname[],PetscInt blocksize,PetscDataType type)
646 {
647   PetscErrorCode ierr;
648   DM_Swarm *swarm = (DM_Swarm*)dm->data;
649   size_t size;
650 
651   PetscFunctionBegin;
652   if (!swarm->field_registration_initialized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmInitializeFieldRegister() first");
653   if (swarm->field_registration_finalized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Cannot register additional fields after calling DMSwarmFinalizeFieldRegister() first");
654 
655   if (type == PETSC_OBJECT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
656   if (type == PETSC_FUNCTION) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
657   if (type == PETSC_STRING) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
658   if (type == PETSC_STRUCT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
659   if (type == PETSC_DATATYPE_UNKNOWN) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
660 
661   ierr = PetscDataTypeGetSize(type, &size);CHKERRQ(ierr);
662   /* Load a specific data type into data bucket, specifying textual name and its size in bytes */
663   ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterPetscDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
664   {
665     DataField gfield;
666 
667     ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
668     ierr = DataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
669   }
670   swarm->db->field[swarm->db->nfields-1]->petsc_type = type;
671   PetscFunctionReturn(0);
672 }
673 
674 /*@C
675    DMSwarmRegisterUserStructField - Register a user defined struct to a DMSwarm
676 
677    Collective on DM
678 
679    Input parameters:
680 +  dm - a DMSwarm
681 .  fieldname - the textual name to identify this field
682 -  size - the size in bytes of the user struct of each data type
683 
684    Level: beginner
685 
686    Notes:
687    The textual name for each registered field must be unique.
688 
689 .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserDatatypeField()
690 @*/
691 PETSC_EXTERN PetscErrorCode DMSwarmRegisterUserStructField(DM dm,const char fieldname[],size_t size)
692 {
693   PetscErrorCode ierr;
694   DM_Swarm *swarm = (DM_Swarm*)dm->data;
695 
696   PetscFunctionBegin;
697   ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterUserStructField",fieldname,size,NULL);CHKERRQ(ierr);
698   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_STRUCT ;
699   PetscFunctionReturn(0);
700 }
701 
702 /*@C
703    DMSwarmRegisterUserDatatypeField - Register a user defined data type to a DMSwarm
704 
705    Collective on DM
706 
707    Input parameters:
708 +  dm - a DMSwarm
709 .  fieldname - the textual name to identify this field
710 .  size - the size in bytes of the user data type
711 -  blocksize - the number of each data type
712 
713    Level: beginner
714 
715    Notes:
716    The textual name for each registered field must be unique.
717 
718 .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
719 @*/
720 PETSC_EXTERN PetscErrorCode DMSwarmRegisterUserDatatypeField(DM dm,const char fieldname[],size_t size,PetscInt blocksize)
721 {
722   DM_Swarm *swarm = (DM_Swarm*)dm->data;
723   PetscErrorCode ierr;
724 
725   PetscFunctionBegin;
726   ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterUserDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
727   {
728     DataField gfield;
729 
730     ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
731     ierr = DataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
732   }
733   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_DATATYPE_UNKNOWN;
734   PetscFunctionReturn(0);
735 }
736 
737 /*@C
738    DMSwarmGetField - Get access to the underlying array storing all entries associated with a registered field
739 
740    Not collective
741 
742    Input parameters:
743 +  dm - a DMSwarm
744 -  fieldname - the textual name to identify this field
745 
746    Output parameters:
747 +  blocksize - the number of each data type
748 .  type - the data type
749 -  data - pointer to raw array
750 
751    Level: beginner
752 
753    Notes:
754    The array must be returned using a matching call to DMSwarmRestoreField().
755 
756 .seealso: DMSwarmRestoreField()
757 @*/
758 PETSC_EXTERN PetscErrorCode DMSwarmGetField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
759 {
760   DM_Swarm *swarm = (DM_Swarm*)dm->data;
761   DataField gfield;
762   PetscErrorCode ierr;
763 
764   PetscFunctionBegin;
765   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
766   ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
767   ierr = DataFieldGetAccess(gfield);CHKERRQ(ierr);
768   ierr = DataFieldGetEntries(gfield,data);CHKERRQ(ierr);
769   if (blocksize) {*blocksize = gfield->bs; }
770   if (type) { *type = gfield->petsc_type; }
771   PetscFunctionReturn(0);
772 }
773 
774 /*@C
775    DMSwarmRestoreField - Restore access to the underlying array storing all entries associated with a registered field
776 
777    Not collective
778 
779    Input parameters:
780 +  dm - a DMSwarm
781 -  fieldname - the textual name to identify this field
782 
783    Output parameters:
784 +  blocksize - the number of each data type
785 .  type - the data type
786 -  data - pointer to raw array
787 
788    Level: beginner
789 
790    Notes:
791    The user must call DMSwarmGetField() prior to calling DMSwarmRestoreField().
792 
793 .seealso: DMSwarmGetField()
794 @*/
795 PETSC_EXTERN PetscErrorCode DMSwarmRestoreField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
796 {
797   DM_Swarm *swarm = (DM_Swarm*)dm->data;
798   DataField gfield;
799   PetscErrorCode ierr;
800 
801   PetscFunctionBegin;
802   ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
803   ierr = DataFieldRestoreAccess(gfield);CHKERRQ(ierr);
804   if (data) *data = NULL;
805   PetscFunctionReturn(0);
806 }
807 
808 /*@C
809    DMSwarmAddPoint - Add space for one new point in the DMSwarm
810 
811    Not collective
812 
813    Input parameter:
814 .  dm - a DMSwarm
815 
816    Level: beginner
817 
818    Notes:
819    The new point will have all fields initialized to zero.
820 
821 .seealso: DMSwarmAddNPoints()
822 @*/
823 PETSC_EXTERN PetscErrorCode DMSwarmAddPoint(DM dm)
824 {
825   DM_Swarm *swarm = (DM_Swarm*)dm->data;
826   PetscErrorCode ierr;
827 
828   PetscFunctionBegin;
829   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
830   ierr = PetscLogEventBegin(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
831   ierr = DataBucketAddPoint(swarm->db);CHKERRQ(ierr);
832   ierr = PetscLogEventEnd(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
833   PetscFunctionReturn(0);
834 }
835 
836 /*@C
837    DMSwarmAddNPoints - Add space for a number of new points in the DMSwarm
838 
839    Not collective
840 
841    Input parameters:
842 +  dm - a DMSwarm
843 -  npoints - the number of new points to add
844 
845    Level: beginner
846 
847    Notes:
848    The new point will have all fields initialized to zero.
849 
850 .seealso: DMSwarmAddPoint()
851 @*/
852 PETSC_EXTERN PetscErrorCode DMSwarmAddNPoints(DM dm,PetscInt npoints)
853 {
854   DM_Swarm *swarm = (DM_Swarm*)dm->data;
855   PetscErrorCode ierr;
856   PetscInt nlocal;
857 
858   PetscFunctionBegin;
859   ierr = PetscLogEventBegin(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
860   ierr = DataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
861   nlocal = nlocal + npoints;
862   ierr = DataBucketSetSizes(swarm->db,nlocal,DATA_BUCKET_BUFFER_DEFAULT);CHKERRQ(ierr);
863   ierr = PetscLogEventEnd(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
864   PetscFunctionReturn(0);
865 }
866 
867 /*@C
868    DMSwarmRemovePoint - Remove the last point from the DMSwarm
869 
870    Not collective
871 
872    Input parameter:
873 .  dm - a DMSwarm
874 
875    Level: beginner
876 
877 .seealso: DMSwarmRemovePointAtIndex()
878 @*/
879 PETSC_EXTERN PetscErrorCode DMSwarmRemovePoint(DM dm)
880 {
881   DM_Swarm *swarm = (DM_Swarm*)dm->data;
882   PetscErrorCode ierr;
883 
884   PetscFunctionBegin;
885   ierr = PetscLogEventBegin(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
886   ierr = DataBucketRemovePoint(swarm->db);CHKERRQ(ierr);
887   ierr = PetscLogEventEnd(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
888   PetscFunctionReturn(0);
889 }
890 
891 /*@C
892    DMSwarmRemovePointAtIndex - Removes a specific point from the DMSwarm
893 
894    Not collective
895 
896    Input parameters:
897 +  dm - a DMSwarm
898 -  idx - index of point to remove
899 
900    Level: beginner
901 
902 .seealso: DMSwarmRemovePoint()
903 @*/
904 PETSC_EXTERN PetscErrorCode DMSwarmRemovePointAtIndex(DM dm,PetscInt idx)
905 {
906   DM_Swarm *swarm = (DM_Swarm*)dm->data;
907   PetscErrorCode ierr;
908 
909   PetscFunctionBegin;
910   ierr = PetscLogEventBegin(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
911   ierr = DataBucketRemovePointAtIndex(swarm->db,idx);CHKERRQ(ierr);
912   ierr = PetscLogEventEnd(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
913   PetscFunctionReturn(0);
914 }
915 
916 /*@C
917    DMSwarmCopyPoint - Copy point pj to point pi in the DMSwarm
918 
919    Not collective
920 
921    Input parameters:
922 +  dm - a DMSwarm
923 .  pi - the index of the point to copy
924 -  pj - the point index where the copy should be located
925 
926  Level: beginner
927 
928 .seealso: DMSwarmRemovePoint()
929 @*/
930 PETSC_EXTERN PetscErrorCode DMSwarmCopyPoint(DM dm,PetscInt pi,PetscInt pj)
931 {
932   DM_Swarm *swarm = (DM_Swarm*)dm->data;
933   PetscErrorCode ierr;
934 
935   PetscFunctionBegin;
936   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
937   ierr = DataBucketCopyPoint(swarm->db,pi,swarm->db,pj);CHKERRQ(ierr);
938   PetscFunctionReturn(0);
939 }
940 
941 PetscErrorCode DMSwarmMigrate_Basic(DM dm,PetscBool remove_sent_points)
942 {
943   PetscErrorCode ierr;
944 
945   PetscFunctionBegin;
946   ierr = DMSwarmMigrate_Push_Basic(dm,remove_sent_points);CHKERRQ(ierr);
947   PetscFunctionReturn(0);
948 }
949 
950 /*@C
951    DMSwarmMigrate - Relocates points defined in the DMSwarm to other MPI-ranks
952 
953    Collective on DM
954 
955    Input parameters:
956 +  dm - the DMSwarm
957 -  remove_sent_points - flag indicating if sent points should be removed from the current MPI-rank
958 
959    Notes:
960    The DM will be modified to accomodate received points.
961    If remove_sent_points = PETSC_TRUE, any points that were sent will be removed from the DM.
962    Different styles of migration are supported. See DMSwarmSetMigrateType().
963 
964    Level: advanced
965 
966 .seealso: DMSwarmSetMigrateType()
967 @*/
968 PETSC_EXTERN PetscErrorCode DMSwarmMigrate(DM dm,PetscBool remove_sent_points)
969 {
970   DM_Swarm *swarm = (DM_Swarm*)dm->data;
971   PetscErrorCode ierr;
972 
973   PetscFunctionBegin;
974   ierr = PetscLogEventBegin(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
975   switch (swarm->migrate_type) {
976     case DMSWARM_MIGRATE_BASIC:
977       ierr = DMSwarmMigrate_Basic(dm,remove_sent_points);CHKERRQ(ierr);
978       break;
979     case DMSWARM_MIGRATE_DMCELLNSCATTER:
980       ierr = DMSwarmMigrate_CellDMScatter(dm,remove_sent_points);CHKERRQ(ierr);
981       break;
982     case DMSWARM_MIGRATE_DMCELLEXACT:
983       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_DMCELLEXACT not implemented");
984       /*ierr = DMSwarmMigrate_CellDMExact(dm,remove_sent_points);CHKERRQ(ierr);*/
985       break;
986     case DMSWARM_MIGRATE_USER:
987       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_USER not implemented");
988       /*ierr = swarm->migrate(dm,remove_sent_points);CHKERRQ(ierr);*/
989       break;
990     default:
991       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE type unknown");
992       break;
993   }
994   ierr = PetscLogEventEnd(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
995   PetscFunctionReturn(0);
996 }
997 
998 PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm,PetscInt *globalsize);
999 
1000 /*
1001  DMSwarmCollectViewCreate
1002 
1003  * Applies a collection method and gathers point neighbour points into dm
1004 
1005  Notes:
1006  Users should call DMSwarmCollectViewDestroy() after
1007  they have finished computations associated with the collected points
1008 */
1009 
1010 /*@C
1011    DMSwarmCollectViewCreate - Applies a collection method and gathers points
1012    in neighbour MPI-ranks into the DMSwarm
1013 
1014    Collective on DM
1015 
1016    Input parameter:
1017 .  dm - the DMSwarm
1018 
1019    Notes:
1020    Users should call DMSwarmCollectViewDestroy() after
1021    they have finished computations associated with the collected points
1022    Different collect methods are supported. See DMSwarmSetCollectType().
1023 
1024    Level: advanced
1025 
1026 .seealso: DMSwarmCollectViewDestroy(), DMSwarmSetCollectType()
1027 @*/
1028 PETSC_EXTERN PetscErrorCode DMSwarmCollectViewCreate(DM dm)
1029 {
1030   PetscErrorCode ierr;
1031   DM_Swarm *swarm = (DM_Swarm*)dm->data;
1032   PetscInt ng;
1033 
1034   PetscFunctionBegin;
1035   if (swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView currently active");
1036   ierr = DMSwarmGetLocalSize(dm,&ng);CHKERRQ(ierr);
1037   switch (swarm->collect_type) {
1038 
1039     case DMSWARM_COLLECT_BASIC:
1040       ierr = DMSwarmMigrate_GlobalToLocal_Basic(dm,&ng);CHKERRQ(ierr);
1041       break;
1042     case DMSWARM_COLLECT_DMDABOUNDINGBOX:
1043       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_DMDABOUNDINGBOX not implemented");
1044       /*ierr = DMSwarmCollect_DMDABoundingBox(dm,&ng);CHKERRQ(ierr);*/
1045       break;
1046     case DMSWARM_COLLECT_GENERAL:
1047       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_GENERAL not implemented");
1048       /*ierr = DMSwarmCollect_General(dm,..,,..,&ng);CHKERRQ(ierr);*/
1049       break;
1050     default:
1051       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT type unknown");
1052       break;
1053   }
1054   swarm->collect_view_active = PETSC_TRUE;
1055   swarm->collect_view_reset_nlocal = ng;
1056   PetscFunctionReturn(0);
1057 }
1058 
1059 /*@C
1060    DMSwarmCollectViewDestroy - Resets the DMSwarm to the size prior to calling DMSwarmCollectViewCreate()
1061 
1062    Collective on DM
1063 
1064    Input parameters:
1065 .  dm - the DMSwarm
1066 
1067    Notes:
1068    Users should call DMSwarmCollectViewCreate() before this function is called.
1069 
1070    Level: advanced
1071 
1072 .seealso: DMSwarmCollectViewCreate(), DMSwarmSetCollectType()
1073 @*/
1074 PETSC_EXTERN PetscErrorCode DMSwarmCollectViewDestroy(DM dm)
1075 {
1076   PetscErrorCode ierr;
1077   DM_Swarm *swarm = (DM_Swarm*)dm->data;
1078 
1079   PetscFunctionBegin;
1080   if (!swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView is currently not active");
1081   ierr = DMSwarmSetLocalSizes(dm,swarm->collect_view_reset_nlocal,-1);CHKERRQ(ierr);
1082   swarm->collect_view_active = PETSC_FALSE;
1083   PetscFunctionReturn(0);
1084 }
1085 
1086 PetscErrorCode DMSwarmSetUpPIC(DM dm)
1087 {
1088   PetscInt dim;
1089   PetscErrorCode ierr;
1090 
1091   PetscFunctionBegin;
1092   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
1093   if (dim < 1) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
1094   if (dim > 3) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
1095   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_coor,dim,PETSC_DOUBLE);CHKERRQ(ierr);
1096   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_cellid,1,PETSC_INT);CHKERRQ(ierr);
1097   PetscFunctionReturn(0);
1098 }
1099 
1100 /*@C
1101    DMSwarmSetType - Set particular flavor of DMSwarm
1102 
1103    Collective on DM
1104 
1105    Input parameters:
1106 +  dm - the DMSwarm
1107 -  stype - the DMSwarm type (e.g. DMSWARM_PIC)
1108 
1109    Level: advanced
1110 
1111 .seealso: DMSwarmSetMigrateType(), DMSwarmSetCollectType()
1112 @*/
1113 PETSC_EXTERN PetscErrorCode DMSwarmSetType(DM dm,DMSwarmType stype)
1114 {
1115   DM_Swarm *swarm = (DM_Swarm*)dm->data;
1116   PetscErrorCode ierr;
1117 
1118   PetscFunctionBegin;
1119   swarm->swarm_type = stype;
1120   if (swarm->swarm_type == DMSWARM_PIC) {
1121     ierr = DMSwarmSetUpPIC(dm);CHKERRQ(ierr);
1122   }
1123   PetscFunctionReturn(0);
1124 }
1125 
1126 PetscErrorCode DMSetup_Swarm(DM dm)
1127 {
1128   DM_Swarm *swarm = (DM_Swarm*)dm->data;
1129   PetscErrorCode ierr;
1130   PetscMPIInt rank;
1131   PetscInt p,npoints,*rankval;
1132 
1133   PetscFunctionBegin;
1134   if (swarm->issetup) PetscFunctionReturn(0);
1135 
1136   swarm->issetup = PETSC_TRUE;
1137 
1138   if (swarm->swarm_type == DMSWARM_PIC) {
1139     /* check dmcell exists */
1140     if (!swarm->dmcell) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires you call DMSwarmSetCellDM");
1141 
1142     if (swarm->dmcell->ops->locatepointssubdomain) {
1143       /* check methods exists for exact ownership identificiation */
1144       ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->ops->LocatePointsSubdomain\n");CHKERRQ(ierr);
1145       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLEXACT;
1146     } else {
1147       /* check methods exist for point location AND rank neighbor identification */
1148       if (swarm->dmcell->ops->locatepoints) {
1149         ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->LocatePoints\n");CHKERRQ(ierr);
1150       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->locatepoints be defined");
1151 
1152       if (swarm->dmcell->ops->getneighbors) {
1153         ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->GetNeigbors\n");CHKERRQ(ierr);
1154       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->getneighbors be defined");
1155 
1156       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLNSCATTER;
1157     }
1158   }
1159 
1160   ierr = DMSwarmFinalizeFieldRegister(dm);CHKERRQ(ierr);
1161 
1162   /* check some fields were registered */
1163   if (swarm->db->nfields <= 2) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"At least one field user must be registered via DMSwarmRegisterXXX()");
1164 
1165   /* check local sizes were set */
1166   if (swarm->db->L == -1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Local sizes must be set via DMSwarmSetLocalSizes()");
1167 
1168   /* initialize values in pid and rank placeholders */
1169   /* TODO: [pid - use MPI_Scan] */
1170   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
1171   ierr = DataBucketGetSizes(swarm->db,&npoints,NULL,NULL);CHKERRQ(ierr);
1172   ierr = DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
1173   for (p=0; p<npoints; p++) {
1174     rankval[p] = (PetscInt)rank;
1175   }
1176   ierr = DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
1177   PetscFunctionReturn(0);
1178 }
1179 
1180 extern PetscErrorCode DMSwarmSortDestroy(DMSwarmSort *_ctx);
1181 
1182 PetscErrorCode DMDestroy_Swarm(DM dm)
1183 {
1184   DM_Swarm *swarm = (DM_Swarm*)dm->data;
1185   PetscErrorCode ierr;
1186 
1187   PetscFunctionBegin;
1188   ierr = DataBucketDestroy(&swarm->db);CHKERRQ(ierr);
1189   if (swarm->sort_context) {
1190     ierr = DMSwarmSortDestroy(&swarm->sort_context);CHKERRQ(ierr);
1191   }
1192   ierr = PetscFree(swarm);CHKERRQ(ierr);
1193   PetscFunctionReturn(0);
1194 }
1195 
1196 PetscErrorCode DMSwarmView_Draw(DM dm, PetscViewer viewer)
1197 {
1198   DM             cdm;
1199   PetscDraw      draw;
1200   PetscReal     *coords, oldPause;
1201   PetscInt       Np, p, bs;
1202   PetscErrorCode ierr;
1203 
1204   PetscFunctionBegin;
1205   ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr);
1206   ierr = DMSwarmGetCellDM(dm, &cdm);CHKERRQ(ierr);
1207   ierr = PetscDrawGetPause(draw, &oldPause);CHKERRQ(ierr);
1208   ierr = PetscDrawSetPause(draw, 0.0);CHKERRQ(ierr);
1209   ierr = DMView(cdm, viewer);CHKERRQ(ierr);
1210   ierr = PetscDrawSetPause(draw, oldPause);CHKERRQ(ierr);
1211 
1212   ierr = DMSwarmGetLocalSize(dm, &Np);CHKERRQ(ierr);
1213   ierr = DMSwarmGetField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1214   for (p = 0; p < Np; ++p) {
1215     const PetscInt i = p*bs;
1216 
1217     ierr = PetscDrawEllipse(draw, coords[i], coords[i+1], 0.01, 0.01, PETSC_DRAW_BLUE);CHKERRQ(ierr);
1218   }
1219   ierr = DMSwarmRestoreField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1220   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
1221   ierr = PetscDrawPause(draw);CHKERRQ(ierr);
1222   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
1223   PetscFunctionReturn(0);
1224 }
1225 
1226 PetscErrorCode DMView_Swarm(DM dm, PetscViewer viewer)
1227 {
1228   DM_Swarm *swarm = (DM_Swarm*)dm->data;
1229   PetscBool      iascii,ibinary,ishdf5,isvtk,isdraw;
1230   PetscErrorCode ierr;
1231 
1232   PetscFunctionBegin;
1233   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
1234   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
1235   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
1236   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY,&ibinary);CHKERRQ(ierr);
1237   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK,   &isvtk);CHKERRQ(ierr);
1238   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
1239   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW,  &isdraw);CHKERRQ(ierr);
1240   if (iascii) {
1241     ierr = DataBucketView(PetscObjectComm((PetscObject)dm),swarm->db,NULL,DATABUCKET_VIEW_STDOUT);CHKERRQ(ierr);
1242   } else if (ibinary) {
1243     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO Binary support");
1244   } else if (ishdf5) {
1245 #if defined(PETSC_HAVE_HDF5)
1246     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO HDF5 support");
1247 #else
1248     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"HDF5 not supported. Please reconfigure using --download-hdf5");
1249 #endif
1250   } else if (isvtk) {
1251     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO VTK support");
1252   } else if (isdraw) {
1253     ierr = DMSwarmView_Draw(dm, viewer);CHKERRQ(ierr);
1254   }
1255   PetscFunctionReturn(0);
1256 }
1257 
1258 /*MC
1259 
1260  DMSWARM = "swarm" - A DM object used to represent arrays of data (fields) of arbitrary data type.
1261  This implementation was designed for particle methods in which the underlying
1262  data required to be represented is both (i) dynamic in length, (ii) and of arbitrary data type.
1263 
1264  User data can be represented by DMSwarm through a registering "fields".
1265  To register a field, the user must provide;
1266  (a) a unique name;
1267  (b) the data type (or size in bytes);
1268  (c) the block size of the data.
1269 
1270  For example, suppose the application requires a unique id, energy, momentum and density to be stored
1271  on a set of of particles. Then the following code could be used
1272 
1273 $    DMSwarmInitializeFieldRegister(dm)
1274 $    DMSwarmRegisterPetscDatatypeField(dm,"uid",1,PETSC_LONG);
1275 $    DMSwarmRegisterPetscDatatypeField(dm,"energy",1,PETSC_REAL);
1276 $    DMSwarmRegisterPetscDatatypeField(dm,"momentum",3,PETSC_REAL);
1277 $    DMSwarmRegisterPetscDatatypeField(dm,"density",1,PETSC_FLOAT);
1278 $    DMSwarmFinalizeFieldRegister(dm)
1279 
1280  The fields represented by DMSwarm are dynamic and can be re-sized at any time.
1281  The only restriction imposed by DMSwarm is that all fields contain the same number of points.
1282 
1283  To support particle methods, "migration" techniques are provided. These methods migrate data
1284  between MPI-ranks.
1285 
1286  DMSwarm supports the methods DMCreateGlobalVector() and DMCreateLocalVector().
1287  As a DMSwarm may internally define and store values of different data types,
1288  before calling DMCreateGlobalVector() or DMCreateLocalVector(), the user must inform DMSwarm which
1289  fields should be used to define a Vec object via
1290    DMSwarmVectorDefineField()
1291  The specified field can can changed be changed at any time - thereby permitting vectors
1292  compatable with different fields to be created.
1293 
1294  A dual representation of fields in the DMSwarm and a Vec object is permitted via
1295    DMSwarmCreateGlobalVectorFromField()
1296  Here the data defining the field in the DMSwarm is shared with a Vec.
1297  This is inherently unsafe if you alter the size of the field at any time between
1298  calls to DMSwarmCreateGlobalVectorFromField() and DMSwarmDestroyGlobalVectorFromField().
1299  If the local size of the DMSwarm does not match the local size of the global vector
1300  when DMSwarmDestroyGlobalVectorFromField() is called, an error is thrown.
1301 
1302  Additional high-level support is provided for Particle-In-Cell methods.
1303  Please refer to the man page for DMSwarmSetType().
1304 
1305  Level: beginner
1306 
1307 .seealso: DMType, DMCreate(), DMSetType()
1308 M*/
1309 PETSC_EXTERN PetscErrorCode DMCreate_Swarm(DM dm)
1310 {
1311   DM_Swarm      *swarm;
1312   PetscErrorCode ierr;
1313 
1314   PetscFunctionBegin;
1315   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
1316   ierr     = PetscNewLog(dm,&swarm);CHKERRQ(ierr);
1317   dm->data = swarm;
1318 
1319   ierr = DataBucketCreate(&swarm->db);CHKERRQ(ierr);
1320   ierr = DMSwarmInitializeFieldRegister(dm);CHKERRQ(ierr);
1321 
1322   swarm->vec_field_set = PETSC_FALSE;
1323   swarm->issetup = PETSC_FALSE;
1324   swarm->swarm_type = DMSWARM_BASIC;
1325   swarm->migrate_type = DMSWARM_MIGRATE_BASIC;
1326   swarm->collect_type = DMSWARM_COLLECT_BASIC;
1327   swarm->migrate_error_on_missing_point = PETSC_FALSE;
1328 
1329   swarm->dmcell = NULL;
1330   swarm->collect_view_active = PETSC_FALSE;
1331   swarm->collect_view_reset_nlocal = -1;
1332 
1333   dm->dim  = 0;
1334   dm->ops->view                            = DMView_Swarm;
1335   dm->ops->load                            = NULL;
1336   dm->ops->setfromoptions                  = NULL;
1337   dm->ops->clone                           = NULL;
1338   dm->ops->setup                           = DMSetup_Swarm;
1339   dm->ops->createdefaultsection            = NULL;
1340   dm->ops->createdefaultconstraints        = NULL;
1341   dm->ops->createglobalvector              = DMCreateGlobalVector_Swarm;
1342   dm->ops->createlocalvector               = DMCreateLocalVector_Swarm;
1343   dm->ops->getlocaltoglobalmapping         = NULL;
1344   dm->ops->createfieldis                   = NULL;
1345   dm->ops->createcoordinatedm              = NULL;
1346   dm->ops->getcoloring                     = NULL;
1347   dm->ops->creatematrix                    = NULL;
1348   dm->ops->createinterpolation             = NULL;
1349   dm->ops->getaggregates                   = NULL;
1350   dm->ops->getinjection                    = NULL;
1351   dm->ops->createmassmatrix                = DMCreateMassMatrix_Swarm;
1352   dm->ops->refine                          = NULL;
1353   dm->ops->coarsen                         = NULL;
1354   dm->ops->refinehierarchy                 = NULL;
1355   dm->ops->coarsenhierarchy                = NULL;
1356   dm->ops->globaltolocalbegin              = NULL;
1357   dm->ops->globaltolocalend                = NULL;
1358   dm->ops->localtoglobalbegin              = NULL;
1359   dm->ops->localtoglobalend                = NULL;
1360   dm->ops->destroy                         = DMDestroy_Swarm;
1361   dm->ops->createsubdm                     = NULL;
1362   dm->ops->getdimpoints                    = NULL;
1363   dm->ops->locatepoints                    = NULL;
1364   PetscFunctionReturn(0);
1365 }
1366