xref: /petsc/src/dm/impls/swarm/swarm.c (revision 83c479555f8cf72361a082ffb9bcbac5b50c2e28)
157795646SDave May #define PETSCDM_DLL
257795646SDave May #include <petsc/private/dmswarmimpl.h>    /*I   "petscdmswarm.h"   I*/
3*83c47955SMatthew G. Knepley #include <petsc/private/hash.h>
45917a6f0SStefano Zampini #include <petscviewer.h>
55917a6f0SStefano Zampini #include <petscdraw.h>
6*83c47955SMatthew G. Knepley #include <petscdmplex.h>
7b62e03f8SDave May #include "data_bucket.h"
857795646SDave May 
9f2b2bee7SDave May PetscLogEvent DMSWARM_Migrate, DMSWARM_SetSizes, DMSWARM_AddPoints, DMSWARM_RemovePoints, DMSWARM_Sort;
10ed923d71SDave May PetscLogEvent DMSWARM_DataExchangerTopologySetup, DMSWARM_DataExchangerBegin, DMSWARM_DataExchangerEnd;
11ed923d71SDave May PetscLogEvent DMSWARM_DataExchangerSendCount, DMSWARM_DataExchangerPack;
12ed923d71SDave May 
13f0cdbbbaSDave May const char* DMSwarmTypeNames[] = { "basic", "pic", 0 };
14f0cdbbbaSDave May const char* DMSwarmMigrateTypeNames[] = { "basic", "dmcellnscatter", "dmcellexact", "user", 0 };
15f0cdbbbaSDave May const char* DMSwarmCollectTypeNames[] = { "basic", "boundingbox", "general", "user", 0 };
16e2d107dbSDave May const char* DMSwarmPICLayoutTypeNames[] = { "regular", "gauss", "subdivision", 0 };
17f0cdbbbaSDave May 
18f0cdbbbaSDave May const char DMSwarmField_pid[] = "DMSwarm_pid";
19f0cdbbbaSDave May const char DMSwarmField_rank[] = "DMSwarm_rank";
20f0cdbbbaSDave May const char DMSwarmPICField_coor[] = "DMSwarmPIC_coor";
21e2d107dbSDave May const char DMSwarmPICField_cellid[] = "DMSwarm_cellid";
22f0cdbbbaSDave May 
23d3a51819SDave May /*@C
2462741f57SDave May    DMSwarmVectorDefineField - Sets the field from which to define a Vec object
2562741f57SDave May                              when DMCreateLocalVector(), or DMCreateGlobalVector() is called
2657795646SDave May 
27d3a51819SDave May    Collective on DM
2857795646SDave May 
29d3a51819SDave May    Input parameters:
3062741f57SDave May +  dm - a DMSwarm
3162741f57SDave May -  fieldname - the textual name given to a registered field
3257795646SDave May 
33d3a51819SDave May    Level: beginner
3457795646SDave May 
35d3a51819SDave May    Notes:
3662741f57SDave May    The field with name fieldname must be defined as having a data type of PetscScalar.
37d3a51819SDave May    This function must be called prior to calling DMCreateLocalVector(), DMCreateGlobalVector().
38d3a51819SDave May    Mutiple calls to DMSwarmVectorDefineField() are permitted.
3957795646SDave May 
408b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMCreateGlobalVector(), DMCreateLocalVector()
41d3a51819SDave May @*/
42b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmVectorDefineField(DM dm,const char fieldname[])
43b5bcf523SDave May {
44b5bcf523SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
45b5bcf523SDave May   PetscErrorCode ierr;
46b5bcf523SDave May   PetscInt bs,n;
47b5bcf523SDave May   PetscScalar *array;
48b5bcf523SDave May   PetscDataType type;
49b5bcf523SDave May 
50a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
513454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
526845f8f5SDave May   ierr = DataBucketGetSizes(swarm->db,&n,NULL,NULL);CHKERRQ(ierr);
53b5bcf523SDave May   ierr = DMSwarmGetField(dm,fieldname,&bs,&type,(void**)&array);CHKERRQ(ierr);
54b5bcf523SDave May 
55b5bcf523SDave May   /* Check all fields are of type PETSC_REAL or PETSC_SCALAR */
56b5bcf523SDave May   if (type != PETSC_REAL) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only valid for PETSC_REAL");
57521f74f9SMatthew G. Knepley   ierr = PetscSNPrintf(swarm->vec_field_name,PETSC_MAX_PATH_LEN-1,"%s",fieldname);CHKERRQ(ierr);
58b5bcf523SDave May   swarm->vec_field_set = PETSC_TRUE;
591b1ea282SDave May   swarm->vec_field_bs = bs;
60b5bcf523SDave May   swarm->vec_field_nlocal = n;
61dcf43ee8SDave May   ierr = DMSwarmRestoreField(dm,fieldname,&bs,&type,(void**)&array);CHKERRQ(ierr);
62b5bcf523SDave May   PetscFunctionReturn(0);
63b5bcf523SDave May }
64b5bcf523SDave May 
65cc651181SDave May /* requires DMSwarmDefineFieldVector has been called */
66b5bcf523SDave May PetscErrorCode DMCreateGlobalVector_Swarm(DM dm,Vec *vec)
67b5bcf523SDave May {
68b5bcf523SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
69b5bcf523SDave May   PetscErrorCode ierr;
70b5bcf523SDave May   Vec x;
71b5bcf523SDave May   char name[PETSC_MAX_PATH_LEN];
72b5bcf523SDave May 
73a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
743454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
75b5bcf523SDave May   if (!swarm->vec_field_set) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmVectorDefineField first");
76cc651181SDave May   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 */
77cc651181SDave May 
78521f74f9SMatthew G. Knepley   ierr = PetscSNPrintf(name,PETSC_MAX_PATH_LEN-1,"DMSwarmField_%s",swarm->vec_field_name);CHKERRQ(ierr);
79b5bcf523SDave May   ierr = VecCreate(PetscObjectComm((PetscObject)dm),&x);CHKERRQ(ierr);
80b5bcf523SDave May   ierr = PetscObjectSetName((PetscObject)x,name);CHKERRQ(ierr);
811b1ea282SDave May   ierr = VecSetSizes(x,swarm->db->L*swarm->vec_field_bs,PETSC_DETERMINE);CHKERRQ(ierr);
82b5bcf523SDave May   ierr = VecSetBlockSize(x,swarm->vec_field_bs);CHKERRQ(ierr);
83b5bcf523SDave May   ierr = VecSetFromOptions(x);CHKERRQ(ierr);
84b5bcf523SDave May   *vec = x;
85b5bcf523SDave May   PetscFunctionReturn(0);
86b5bcf523SDave May }
87b5bcf523SDave May 
88b5bcf523SDave May /* requires DMSwarmDefineFieldVector has been called */
89b5bcf523SDave May PetscErrorCode DMCreateLocalVector_Swarm(DM dm,Vec *vec)
90b5bcf523SDave May {
91b5bcf523SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
92b5bcf523SDave May   PetscErrorCode ierr;
93b5bcf523SDave May   Vec x;
94b5bcf523SDave May   char name[PETSC_MAX_PATH_LEN];
95b5bcf523SDave May 
96a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
973454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
98b5bcf523SDave May   if (!swarm->vec_field_set) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmVectorDefineField first");
99cc651181SDave May   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 */
100cc651181SDave May 
101521f74f9SMatthew G. Knepley   ierr = PetscSNPrintf(name,PETSC_MAX_PATH_LEN-1,"DMSwarmField_%s",swarm->vec_field_name);CHKERRQ(ierr);
102b5bcf523SDave May   ierr = VecCreate(PETSC_COMM_SELF,&x);CHKERRQ(ierr);
103b5bcf523SDave May   ierr = PetscObjectSetName((PetscObject)x,name);CHKERRQ(ierr);
104071900c8SMatthew G. Knepley   ierr = VecSetSizes(x,swarm->db->L*swarm->vec_field_bs,PETSC_DETERMINE);CHKERRQ(ierr);
105b5bcf523SDave May   ierr = VecSetBlockSize(x,swarm->vec_field_bs);CHKERRQ(ierr);
106b5bcf523SDave May   ierr = VecSetFromOptions(x);CHKERRQ(ierr);
107b5bcf523SDave May   *vec = x;
108b5bcf523SDave May   PetscFunctionReturn(0);
109b5bcf523SDave May }
110b5bcf523SDave May 
111fb1bcc12SMatthew G. Knepley static PetscErrorCode DMSwarmDestroyVectorFromField_Private(DM dm, const char fieldname[], Vec *vec)
112fb1bcc12SMatthew G. Knepley {
113fb1bcc12SMatthew G. Knepley   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
114fb1bcc12SMatthew G. Knepley   DataField      gfield;
115fb1bcc12SMatthew G. Knepley   void         (*fptr)(void);
116fb1bcc12SMatthew G. Knepley   PetscInt       bs, nlocal;
117fb1bcc12SMatthew G. Knepley   char           name[PETSC_MAX_PATH_LEN];
118fb1bcc12SMatthew G. Knepley   PetscErrorCode ierr;
119d3a51819SDave May 
120fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
121fb1bcc12SMatthew G. Knepley   ierr = VecGetLocalSize(*vec, &nlocal);CHKERRQ(ierr);
122fb1bcc12SMatthew G. Knepley   ierr = VecGetBlockSize(*vec, &bs);CHKERRQ(ierr);
123fb1bcc12SMatthew G. Knepley   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 */
124fb1bcc12SMatthew G. Knepley   ierr = DataBucketGetDataFieldByName(swarm->db, fieldname, &gfield);CHKERRQ(ierr);
125fb1bcc12SMatthew G. Knepley   /* check vector is an inplace array */
126521f74f9SMatthew G. Knepley   ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarm_VecFieldInPlace_%s", fieldname);CHKERRQ(ierr);
127fb1bcc12SMatthew G. Knepley   ierr = PetscObjectQueryFunction((PetscObject) *vec, name, &fptr);CHKERRQ(ierr);
128fb1bcc12SMatthew G. Knepley   if (!fptr) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_USER, "Vector being destroyed was not created from DMSwarm field(%s)", fieldname);
129fb1bcc12SMatthew G. Knepley   ierr = DataFieldRestoreAccess(gfield);CHKERRQ(ierr);
130fb1bcc12SMatthew G. Knepley   ierr = VecDestroy(vec);CHKERRQ(ierr);
131fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
132fb1bcc12SMatthew G. Knepley }
133fb1bcc12SMatthew G. Knepley 
134fb1bcc12SMatthew G. Knepley static PetscErrorCode DMSwarmCreateVectorFromField_Private(DM dm, const char fieldname[], MPI_Comm comm, Vec *vec)
135fb1bcc12SMatthew G. Knepley {
136fb1bcc12SMatthew G. Knepley   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
137fb1bcc12SMatthew G. Knepley   PetscDataType  type;
138fb1bcc12SMatthew G. Knepley   PetscScalar   *array;
139fb1bcc12SMatthew G. Knepley   PetscInt       bs, n;
140fb1bcc12SMatthew G. Knepley   char           name[PETSC_MAX_PATH_LEN];
141fb1bcc12SMatthew G. Knepley   PetscMPIInt    commsize;
142fb1bcc12SMatthew G. Knepley   PetscErrorCode ierr;
143fb1bcc12SMatthew G. Knepley 
144fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
145fb1bcc12SMatthew G. Knepley   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
146fb1bcc12SMatthew G. Knepley   ierr = DataBucketGetSizes(swarm->db, &n, NULL, NULL);CHKERRQ(ierr);
147fb1bcc12SMatthew G. Knepley   ierr = DMSwarmGetField(dm, fieldname, &bs, &type, (void **) &array);CHKERRQ(ierr);
148fb1bcc12SMatthew G. Knepley   if (type != PETSC_REAL) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Only valid for PETSC_REAL");
149fb1bcc12SMatthew G. Knepley 
150fb1bcc12SMatthew G. Knepley   ierr = MPI_Comm_size(comm, &commsize);CHKERRQ(ierr);
151fb1bcc12SMatthew G. Knepley   if (commsize == 1) {
152fb1bcc12SMatthew G. Knepley     ierr = VecCreateSeqWithArray(comm, bs, n*bs, array, vec);CHKERRQ(ierr);
153fb1bcc12SMatthew G. Knepley   } else {
154fb1bcc12SMatthew G. Knepley     ierr = VecCreateMPIWithArray(comm, bs, n*bs, PETSC_DETERMINE, array, vec);CHKERRQ(ierr);
155fb1bcc12SMatthew G. Knepley   }
156fb1bcc12SMatthew G. Knepley   ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarmSharedField_%s", fieldname);CHKERRQ(ierr);
157fb1bcc12SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) *vec, name);CHKERRQ(ierr);
158fb1bcc12SMatthew G. Knepley 
159fb1bcc12SMatthew G. Knepley   /* Set guard */
160fb1bcc12SMatthew G. Knepley   ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarm_VecFieldInPlace_%s", fieldname);CHKERRQ(ierr);
161fb1bcc12SMatthew G. Knepley   ierr = PetscObjectComposeFunction((PetscObject) *vec, name, DMSwarmDestroyVectorFromField_Private);CHKERRQ(ierr);
162fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
163fb1bcc12SMatthew G. Knepley }
164fb1bcc12SMatthew G. Knepley 
165*83c47955SMatthew G. Knepley static PetscErrorCode DMSwarmComputeMassMatrix_Private(DM dmc, DM dmf, Mat mass, void *ctx)
166*83c47955SMatthew G. Knepley {
167*83c47955SMatthew G. Knepley   const char    *name = "Mass Matrix";
168*83c47955SMatthew G. Knepley   PetscDS        prob;
169*83c47955SMatthew G. Knepley   PetscSection   fsection, globalFSection;
170*83c47955SMatthew G. Knepley   PetscHashJK    ht;
171*83c47955SMatthew G. Knepley   PetscLayout    rLayout;
172*83c47955SMatthew G. Knepley   PetscInt      *dnz, *onz;
173*83c47955SMatthew G. Knepley   PetscInt       locRows, rStart, rEnd;
174*83c47955SMatthew G. Knepley   PetscReal     *x, *v0, *J, *invJ, detJ;
175*83c47955SMatthew G. Knepley   PetscScalar   *elemMat;
176*83c47955SMatthew G. Knepley   PetscInt       dim, Nf, field, totDim, cStart, cEnd, cell;
177*83c47955SMatthew G. Knepley   PetscErrorCode ierr;
178*83c47955SMatthew G. Knepley 
179*83c47955SMatthew G. Knepley   PetscFunctionBegin;
180*83c47955SMatthew G. Knepley   ierr = DMGetCoordinateDim(dmf, &dim);CHKERRQ(ierr);
181*83c47955SMatthew G. Knepley   ierr = DMGetDS(dmf, &prob);CHKERRQ(ierr);
182*83c47955SMatthew G. Knepley   ierr = PetscDSGetRefCoordArrays(prob, &x, NULL);CHKERRQ(ierr);
183*83c47955SMatthew G. Knepley   ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr);
184*83c47955SMatthew G. Knepley   ierr = PetscMalloc3(dim,&v0,dim*dim,&J,dim*dim,&invJ);CHKERRQ(ierr);
185*83c47955SMatthew G. Knepley   ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);
186*83c47955SMatthew G. Knepley   ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);
187*83c47955SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd);CHKERRQ(ierr);
188*83c47955SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr);
189*83c47955SMatthew G. Knepley   ierr = PetscMalloc1(totDim, &elemMat);CHKERRQ(ierr);
190*83c47955SMatthew G. Knepley   ierr = DMSwarmSortGetAccess(dmc);CHKERRQ(ierr);
191*83c47955SMatthew G. Knepley 
192*83c47955SMatthew G. Knepley   ierr = MatGetLocalSize(mass, &locRows, NULL);CHKERRQ(ierr);
193*83c47955SMatthew G. Knepley   ierr = PetscLayoutCreate(PetscObjectComm((PetscObject) mass), &rLayout);CHKERRQ(ierr);
194*83c47955SMatthew G. Knepley   ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr);
195*83c47955SMatthew G. Knepley   ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr);
196*83c47955SMatthew G. Knepley   ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr);
197*83c47955SMatthew G. Knepley   ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr);
198*83c47955SMatthew G. Knepley   ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr);
199*83c47955SMatthew G. Knepley   ierr = PetscCalloc2(locRows,&dnz,locRows,&onz);CHKERRQ(ierr);
200*83c47955SMatthew G. Knepley   ierr = PetscHashJKCreate(&ht);CHKERRQ(ierr);
201*83c47955SMatthew G. Knepley   for (field = 0; field < Nf; ++field) {
202*83c47955SMatthew G. Knepley     PetscObject      obj;
203*83c47955SMatthew G. Knepley     PetscQuadrature  quad;
204*83c47955SMatthew G. Knepley     const PetscReal *qpoints;
205*83c47955SMatthew G. Knepley     PetscInt         Nq, Nc, i;
206*83c47955SMatthew G. Knepley 
207*83c47955SMatthew G. Knepley     ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr);
208*83c47955SMatthew G. Knepley     ierr = PetscFEGetQuadrature((PetscFE) obj, &quad);CHKERRQ(ierr);
209*83c47955SMatthew G. Knepley     ierr = PetscQuadratureGetData(quad, NULL, &Nc, &Nq, &qpoints, NULL);CHKERRQ(ierr);
210*83c47955SMatthew G. Knepley     /* For each fine grid cell */
211*83c47955SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
212*83c47955SMatthew G. Knepley       PetscInt  Np, c;
213*83c47955SMatthew G. Knepley       PetscInt *findices,   *cindices;
214*83c47955SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
215*83c47955SMatthew G. Knepley 
216*83c47955SMatthew G. Knepley       ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
217*83c47955SMatthew G. Knepley       ierr = DMSwarmSortGetNumberOfPointsPerCell(dmc, cell, &Np);CHKERRQ(ierr);
218*83c47955SMatthew G. Knepley       /* Update preallocation info */
219*83c47955SMatthew G. Knepley       if (Np != Nq) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not all closure points located");
220*83c47955SMatthew G. Knepley       {
221*83c47955SMatthew G. Knepley         PetscHashJKKey  key;
222*83c47955SMatthew G. Knepley         PetscHashJKIter missing, iter;
223*83c47955SMatthew G. Knepley 
224*83c47955SMatthew G. Knepley         for (i = 0; i < numFIndices; ++i) {
225*83c47955SMatthew G. Knepley           key.j = findices[i];
226*83c47955SMatthew G. Knepley           if (key.j >= 0) {
227*83c47955SMatthew G. Knepley             /* Get indices for coarse elements */
228*83c47955SMatthew G. Knepley             ierr = DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices);CHKERRQ(ierr);
229*83c47955SMatthew G. Knepley             for (c = 0; c < numCIndices; ++c) {
230*83c47955SMatthew G. Knepley               key.k = cindices[c];
231*83c47955SMatthew G. Knepley               if (key.k < 0) continue;
232*83c47955SMatthew G. Knepley               ierr = PetscHashJKPut(ht, key, &missing, &iter);CHKERRQ(ierr);
233*83c47955SMatthew G. Knepley               if (missing) {
234*83c47955SMatthew G. Knepley                 ierr = PetscHashJKSet(ht, iter, 1);CHKERRQ(ierr);
235*83c47955SMatthew G. Knepley                 if ((key.k >= rStart) && (key.k < rEnd)) ++dnz[key.j-rStart];
236*83c47955SMatthew G. Knepley                 else                                     ++onz[key.j-rStart];
237*83c47955SMatthew G. Knepley               }
238*83c47955SMatthew G. Knepley             }
239*83c47955SMatthew G. Knepley             ierr = PetscFree(cindices);CHKERRQ(ierr);
240*83c47955SMatthew G. Knepley           }
241*83c47955SMatthew G. Knepley         }
242*83c47955SMatthew G. Knepley       }
243*83c47955SMatthew G. Knepley       ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
244*83c47955SMatthew G. Knepley     }
245*83c47955SMatthew G. Knepley   }
246*83c47955SMatthew G. Knepley   ierr = PetscHashJKDestroy(&ht);CHKERRQ(ierr);
247*83c47955SMatthew G. Knepley   ierr = MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL);CHKERRQ(ierr);
248*83c47955SMatthew G. Knepley   ierr = MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
249*83c47955SMatthew G. Knepley   ierr = PetscFree2(dnz,onz);CHKERRQ(ierr);
250*83c47955SMatthew G. Knepley   for (field = 0; field < Nf; ++field) {
251*83c47955SMatthew G. Knepley     PetscObject      obj;
252*83c47955SMatthew G. Knepley     PetscQuadrature  quad;
253*83c47955SMatthew G. Knepley     PetscReal       *Bfine;
254*83c47955SMatthew G. Knepley     const PetscReal *qweights;
255*83c47955SMatthew G. Knepley     PetscInt         Nq, Nc, i;
256*83c47955SMatthew G. Knepley 
257*83c47955SMatthew G. Knepley     ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr);
258*83c47955SMatthew G. Knepley     ierr = PetscFEGetDefaultTabulation((PetscFE) obj, &Bfine, NULL, NULL);CHKERRQ(ierr);
259*83c47955SMatthew G. Knepley     ierr = PetscFEGetQuadrature((PetscFE) obj, &quad);CHKERRQ(ierr);
260*83c47955SMatthew G. Knepley     ierr = PetscQuadratureGetData(quad, NULL, &Nc, &Nq, NULL, &qweights);CHKERRQ(ierr);
261*83c47955SMatthew G. Knepley     /* For each fine grid cell */
262*83c47955SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
263*83c47955SMatthew G. Knepley       PetscInt           Np, c, j;
264*83c47955SMatthew G. Knepley       PetscInt          *findices,   *cindices;
265*83c47955SMatthew G. Knepley       PetscInt           numFIndices, numCIndices;
266*83c47955SMatthew G. Knepley 
267*83c47955SMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr);
268*83c47955SMatthew G. Knepley       ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
269*83c47955SMatthew G. Knepley       ierr = DMSwarmSortGetNumberOfPointsPerCell(dmc, cell, &Np);CHKERRQ(ierr);
270*83c47955SMatthew G. Knepley       if (Np != Nq) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not all closure points located");
271*83c47955SMatthew G. Knepley       ierr = DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices);CHKERRQ(ierr);
272*83c47955SMatthew G. Knepley       /* Get elemMat entries by multiplying by weight */
273*83c47955SMatthew G. Knepley       for (i = 0; i < numFIndices; ++i) {
274*83c47955SMatthew G. Knepley         ierr = PetscMemzero(elemMat, numCIndices * sizeof(PetscScalar));CHKERRQ(ierr);
275*83c47955SMatthew G. Knepley         for (j = 0; j < numCIndices; ++j) {
276*83c47955SMatthew G. Knepley           for (c = 0; c < Nc; ++c) elemMat[j] += Bfine[(j*numFIndices + i)*Nc + c]*qweights[j*Nc + c]*detJ;
277*83c47955SMatthew G. Knepley         }
278*83c47955SMatthew G. Knepley         /* Update interpolator */
279*83c47955SMatthew G. Knepley         if (0) {ierr = DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat);CHKERRQ(ierr);}
280*83c47955SMatthew G. Knepley         ierr = MatSetValues(mass, 1, &findices[i], numCIndices, cindices, elemMat, ADD_VALUES);CHKERRQ(ierr);
281*83c47955SMatthew G. Knepley       }
282*83c47955SMatthew G. Knepley       ierr = PetscFree(cindices);CHKERRQ(ierr);
283*83c47955SMatthew G. Knepley       ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
284*83c47955SMatthew G. Knepley     }
285*83c47955SMatthew G. Knepley   }
286*83c47955SMatthew G. Knepley   ierr = DMSwarmSortRestoreAccess(dmc);CHKERRQ(ierr);
287*83c47955SMatthew G. Knepley   ierr = PetscFree3(v0,J,invJ);CHKERRQ(ierr);
288*83c47955SMatthew G. Knepley   ierr = PetscFree(elemMat);CHKERRQ(ierr);
289*83c47955SMatthew G. Knepley   ierr = MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
290*83c47955SMatthew G. Knepley   ierr = MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
291*83c47955SMatthew G. Knepley   PetscFunctionReturn(0);
292*83c47955SMatthew G. Knepley }
293*83c47955SMatthew G. Knepley 
294*83c47955SMatthew G. Knepley static PetscErrorCode DMCreateMassMatrix_Swarm(DM dmCoarse, DM dmFine, Mat *mass)
295*83c47955SMatthew G. Knepley {
296*83c47955SMatthew G. Knepley   PetscSection   gsc, gsf;
297*83c47955SMatthew G. Knepley   PetscInt       m, n;
298*83c47955SMatthew G. Knepley   void          *ctx;
299*83c47955SMatthew G. Knepley   PetscErrorCode ierr;
300*83c47955SMatthew G. Knepley 
301*83c47955SMatthew G. Knepley   PetscFunctionBegin;
302*83c47955SMatthew G. Knepley   ierr = DMGetDefaultGlobalSection(dmFine, &gsf);CHKERRQ(ierr);
303*83c47955SMatthew G. Knepley   ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr);
304*83c47955SMatthew G. Knepley   /* TODO Dave needs to determine the sizes based on the selected fields*/
305*83c47955SMatthew G. Knepley   ierr = DMGetDefaultGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr);
306*83c47955SMatthew G. Knepley   ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr);
307*83c47955SMatthew G. Knepley 
308*83c47955SMatthew G. Knepley   ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr);
309*83c47955SMatthew G. Knepley   ierr = MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
310*83c47955SMatthew G. Knepley   ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr);
311*83c47955SMatthew G. Knepley   ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr);
312*83c47955SMatthew G. Knepley 
313*83c47955SMatthew G. Knepley   ierr = DMSwarmComputeMassMatrix_Private(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);
314*83c47955SMatthew G. Knepley   ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr);
315*83c47955SMatthew G. Knepley   PetscFunctionReturn(0);
316*83c47955SMatthew G. Knepley }
317*83c47955SMatthew G. Knepley 
318fb1bcc12SMatthew G. Knepley /*@C
319d3a51819SDave May    DMSwarmCreateGlobalVectorFromField - Creates a Vec object sharing the array associated with a given field
320d3a51819SDave May 
321d3a51819SDave May    Collective on DM
322d3a51819SDave May 
323d3a51819SDave May    Input parameters:
32462741f57SDave May +  dm - a DMSwarm
32562741f57SDave May -  fieldname - the textual name given to a registered field
326d3a51819SDave May 
3278b8a3813SDave May    Output parameter:
328d3a51819SDave May .  vec - the vector
329d3a51819SDave May 
330d3a51819SDave May    Level: beginner
331d3a51819SDave May 
3328b8a3813SDave May    Notes:
3338b8a3813SDave May    The vector must be returned using a matching call to DMSwarmDestroyGlobalVectorFromField().
3348b8a3813SDave May 
3358b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmDestroyGlobalVectorFromField()
336d3a51819SDave May @*/
337b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmCreateGlobalVectorFromField(DM dm,const char fieldname[],Vec *vec)
338b5bcf523SDave May {
339fb1bcc12SMatthew G. Knepley   MPI_Comm       comm = PetscObjectComm((PetscObject) dm);
340b5bcf523SDave May   PetscErrorCode ierr;
341b5bcf523SDave May 
342fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
343fb1bcc12SMatthew G. Knepley   ierr = DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec);CHKERRQ(ierr);
344b5bcf523SDave May   PetscFunctionReturn(0);
345b5bcf523SDave May }
346b5bcf523SDave May 
347d3a51819SDave May /*@C
348d3a51819SDave May    DMSwarmDestroyGlobalVectorFromField - Destroys the Vec object which share the array associated with a given field
349d3a51819SDave May 
350d3a51819SDave May    Collective on DM
351d3a51819SDave May 
352d3a51819SDave May    Input parameters:
35362741f57SDave May +  dm - a DMSwarm
35462741f57SDave May -  fieldname - the textual name given to a registered field
355d3a51819SDave May 
3568b8a3813SDave May    Output parameter:
357d3a51819SDave May .  vec - the vector
358d3a51819SDave May 
359d3a51819SDave May    Level: beginner
360d3a51819SDave May 
3618b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmCreateGlobalVectorFromField()
362d3a51819SDave May @*/
363b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmDestroyGlobalVectorFromField(DM dm,const char fieldname[],Vec *vec)
364b5bcf523SDave May {
365b5bcf523SDave May   PetscErrorCode ierr;
366cc651181SDave May 
367fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
368fb1bcc12SMatthew G. Knepley   ierr = DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec);CHKERRQ(ierr);
369b5bcf523SDave May   PetscFunctionReturn(0);
370b5bcf523SDave May }
371b5bcf523SDave May 
372fb1bcc12SMatthew G. Knepley /*@C
373fb1bcc12SMatthew G. Knepley    DMSwarmCreateLocalVectorFromField - Creates a Vec object sharing the array associated with a given field
374fb1bcc12SMatthew G. Knepley 
375fb1bcc12SMatthew G. Knepley    Collective on DM
376fb1bcc12SMatthew G. Knepley 
377fb1bcc12SMatthew G. Knepley    Input parameters:
37862741f57SDave May +  dm - a DMSwarm
37962741f57SDave May -  fieldname - the textual name given to a registered field
380fb1bcc12SMatthew G. Knepley 
3818b8a3813SDave May    Output parameter:
382fb1bcc12SMatthew G. Knepley .  vec - the vector
383fb1bcc12SMatthew G. Knepley 
384fb1bcc12SMatthew G. Knepley    Level: beginner
385fb1bcc12SMatthew G. Knepley 
3868b8a3813SDave May    Notes:
3878b8a3813SDave May    The vector must be returned using a matching call to DMSwarmDestroyLocalVectorFromField().
3888b8a3813SDave May 
3898b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmDestroyLocalVectorFromField()
390fb1bcc12SMatthew G. Knepley @*/
391fb1bcc12SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMSwarmCreateLocalVectorFromField(DM dm,const char fieldname[],Vec *vec)
392bbe8250bSMatthew G. Knepley {
393fb1bcc12SMatthew G. Knepley   MPI_Comm       comm = PETSC_COMM_SELF;
394bbe8250bSMatthew G. Knepley   PetscErrorCode ierr;
395bbe8250bSMatthew G. Knepley 
396fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
397fb1bcc12SMatthew G. Knepley   ierr = DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec);CHKERRQ(ierr);
398fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
399bbe8250bSMatthew G. Knepley }
400fb1bcc12SMatthew G. Knepley 
401fb1bcc12SMatthew G. Knepley /*@C
402fb1bcc12SMatthew G. Knepley    DMSwarmDestroyLocalVectorFromField - Destroys the Vec object which share the array associated with a given field
403fb1bcc12SMatthew G. Knepley 
404fb1bcc12SMatthew G. Knepley    Collective on DM
405fb1bcc12SMatthew G. Knepley 
406fb1bcc12SMatthew G. Knepley    Input parameters:
40762741f57SDave May +  dm - a DMSwarm
40862741f57SDave May -  fieldname - the textual name given to a registered field
409fb1bcc12SMatthew G. Knepley 
4108b8a3813SDave May    Output parameter:
411fb1bcc12SMatthew G. Knepley .  vec - the vector
412fb1bcc12SMatthew G. Knepley 
413fb1bcc12SMatthew G. Knepley    Level: beginner
414fb1bcc12SMatthew G. Knepley 
4158b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmCreateLocalVectorFromField()
416fb1bcc12SMatthew G. Knepley @*/
417fb1bcc12SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMSwarmDestroyLocalVectorFromField(DM dm,const char fieldname[],Vec *vec)
418fb1bcc12SMatthew G. Knepley {
419fb1bcc12SMatthew G. Knepley   PetscErrorCode ierr;
420fb1bcc12SMatthew G. Knepley 
421fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
422fb1bcc12SMatthew G. Knepley   ierr = DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec);CHKERRQ(ierr);
423bbe8250bSMatthew G. Knepley   PetscFunctionReturn(0);
424bbe8250bSMatthew G. Knepley }
425bbe8250bSMatthew G. Knepley 
426b5bcf523SDave May /*
427b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmCreateGlobalVectorFromFields(DM dm,const PetscInt nf,const char *fieldnames[],Vec *vec)
428b5bcf523SDave May {
429b5bcf523SDave May   PetscFunctionReturn(0);
430b5bcf523SDave May }
431b5bcf523SDave May 
432b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmRestoreGlobalVectorFromFields(DM dm,Vec *vec)
433b5bcf523SDave May {
434b5bcf523SDave May   PetscFunctionReturn(0);
435b5bcf523SDave May }
436b5bcf523SDave May */
437b5bcf523SDave May 
438d3a51819SDave May /*@C
439d3a51819SDave May    DMSwarmInitializeFieldRegister - Initiates the registration of fields to a DMSwarm
440d3a51819SDave May 
441d3a51819SDave May    Collective on DM
442d3a51819SDave May 
443d3a51819SDave May    Input parameter:
444d3a51819SDave May .  dm - a DMSwarm
445d3a51819SDave May 
446d3a51819SDave May    Level: beginner
447d3a51819SDave May 
448d3a51819SDave May    Notes:
4498b8a3813SDave May    After all fields have been registered, you must call DMSwarmFinalizeFieldRegister().
450d3a51819SDave May 
451d3a51819SDave May .seealso: DMSwarmFinalizeFieldRegister(), DMSwarmRegisterPetscDatatypeField(),
452d3a51819SDave May  DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
453d3a51819SDave May @*/
4545f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmInitializeFieldRegister(DM dm)
4555f50eb2eSDave May {
4565f50eb2eSDave May   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
4573454631fSDave May   PetscErrorCode ierr;
4583454631fSDave May 
459521f74f9SMatthew G. Knepley   PetscFunctionBegin;
460cc651181SDave May   if (!swarm->field_registration_initialized) {
4615f50eb2eSDave May     swarm->field_registration_initialized = PETSC_TRUE;
462f0cdbbbaSDave May     ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_pid,1,PETSC_LONG);CHKERRQ(ierr); /* unique identifer */
463f0cdbbbaSDave May     ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_rank,1,PETSC_INT);CHKERRQ(ierr); /* used for communication */
464cc651181SDave May   }
4655f50eb2eSDave May   PetscFunctionReturn(0);
4665f50eb2eSDave May }
4675f50eb2eSDave May 
468d3a51819SDave May /*@C
469d3a51819SDave May    DMSwarmFinalizeFieldRegister - Finalizes the registration of fields to a DMSwarm
470d3a51819SDave May 
471d3a51819SDave May    Collective on DM
472d3a51819SDave May 
473d3a51819SDave May    Input parameter:
474d3a51819SDave May .  dm - a DMSwarm
475d3a51819SDave May 
476d3a51819SDave May    Level: beginner
477d3a51819SDave May 
478d3a51819SDave May    Notes:
47962741f57SDave May    After DMSwarmFinalizeFieldRegister() has been called, no new fields can be defined on the DMSwarm.
480d3a51819SDave May 
481d3a51819SDave May .seealso: DMSwarmInitializeFieldRegister(), DMSwarmRegisterPetscDatatypeField(),
482d3a51819SDave May  DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
483d3a51819SDave May @*/
4845f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmFinalizeFieldRegister(DM dm)
4855f50eb2eSDave May {
4865f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
4876845f8f5SDave May   PetscErrorCode ierr;
4886845f8f5SDave May 
489521f74f9SMatthew G. Knepley   PetscFunctionBegin;
490f0cdbbbaSDave May   if (!swarm->field_registration_finalized) {
4916845f8f5SDave May     ierr = DataBucketFinalize(swarm->db);CHKERRQ(ierr);
492f0cdbbbaSDave May   }
493f0cdbbbaSDave May   swarm->field_registration_finalized = PETSC_TRUE;
4945f50eb2eSDave May   PetscFunctionReturn(0);
4955f50eb2eSDave May }
4965f50eb2eSDave May 
497d3a51819SDave May /*@C
498d3a51819SDave May    DMSwarmSetLocalSizes - Sets the length of all registered fields on the DMSwarm
499d3a51819SDave May 
500d3a51819SDave May    Not collective
501d3a51819SDave May 
502d3a51819SDave May    Input parameters:
50362741f57SDave May +  dm - a DMSwarm
504d3a51819SDave May .  nlocal - the length of each registered field
50562741f57SDave May -  buffer - the length of the buffer used to efficient dynamic re-sizing
506d3a51819SDave May 
507d3a51819SDave May    Level: beginner
508d3a51819SDave May 
509d3a51819SDave May .seealso: DMSwarmGetLocalSize()
510d3a51819SDave May @*/
5115f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmSetLocalSizes(DM dm,PetscInt nlocal,PetscInt buffer)
5125f50eb2eSDave May {
5135f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
5146845f8f5SDave May   PetscErrorCode ierr;
5155f50eb2eSDave May 
516521f74f9SMatthew G. Knepley   PetscFunctionBegin;
517f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_SetSizes,0,0,0,0);CHKERRQ(ierr);
5186845f8f5SDave May   ierr = DataBucketSetSizes(swarm->db,nlocal,buffer);CHKERRQ(ierr);
519f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_SetSizes,0,0,0,0);CHKERRQ(ierr);
5205f50eb2eSDave May   PetscFunctionReturn(0);
5215f50eb2eSDave May }
5225f50eb2eSDave May 
523d3a51819SDave May /*@C
524d3a51819SDave May    DMSwarmSetCellDM - Attachs a DM to a DMSwarm
525d3a51819SDave May 
526d3a51819SDave May    Collective on DM
527d3a51819SDave May 
528d3a51819SDave May    Input parameters:
52962741f57SDave May +  dm - a DMSwarm
53062741f57SDave May -  dmcell - the DM to attach to the DMSwarm
531d3a51819SDave May 
532d3a51819SDave May    Level: beginner
533d3a51819SDave May 
534d3a51819SDave May    Notes:
535d3a51819SDave May    The attached DM (dmcell) will be queried for point location and
5368b8a3813SDave May    neighbor MPI-rank information if DMSwarmMigrate() is called.
537d3a51819SDave May 
5388b8a3813SDave May .seealso: DMSwarmSetType(), DMSwarmGetCellDM(), DMSwarmMigrate()
539d3a51819SDave May @*/
540b16650c8SDave May PETSC_EXTERN PetscErrorCode DMSwarmSetCellDM(DM dm,DM dmcell)
541b16650c8SDave May {
542b16650c8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
543521f74f9SMatthew G. Knepley 
544521f74f9SMatthew G. Knepley   PetscFunctionBegin;
545b16650c8SDave May   swarm->dmcell = dmcell;
546b16650c8SDave May   PetscFunctionReturn(0);
547b16650c8SDave May }
548b16650c8SDave May 
549d3a51819SDave May /*@C
550d3a51819SDave May    DMSwarmGetCellDM - Fetches the attached cell DM
551d3a51819SDave May 
552d3a51819SDave May    Collective on DM
553d3a51819SDave May 
554d3a51819SDave May    Input parameter:
555d3a51819SDave May .  dm - a DMSwarm
556d3a51819SDave May 
557d3a51819SDave May    Output parameter:
558d3a51819SDave May .  dmcell - the DM which was attached to the DMSwarm
559d3a51819SDave May 
560d3a51819SDave May    Level: beginner
561d3a51819SDave May 
562d3a51819SDave May .seealso: DMSwarmSetCellDM()
563d3a51819SDave May @*/
564fe39f135SDave May PETSC_EXTERN PetscErrorCode DMSwarmGetCellDM(DM dm,DM *dmcell)
565fe39f135SDave May {
566fe39f135SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
567521f74f9SMatthew G. Knepley 
568521f74f9SMatthew G. Knepley   PetscFunctionBegin;
569fe39f135SDave May   *dmcell = swarm->dmcell;
570fe39f135SDave May   PetscFunctionReturn(0);
571fe39f135SDave May }
572fe39f135SDave May 
573d3a51819SDave May /*@C
574d3a51819SDave May    DMSwarmGetLocalSize - Retrives the local length of fields registered
575d3a51819SDave May 
576d3a51819SDave May    Not collective
577d3a51819SDave May 
578d3a51819SDave May    Input parameter:
579d3a51819SDave May .  dm - a DMSwarm
580d3a51819SDave May 
581d3a51819SDave May    Output parameter:
582d3a51819SDave May .  nlocal - the length of each registered field
583d3a51819SDave May 
584d3a51819SDave May    Level: beginner
585d3a51819SDave May 
5868b8a3813SDave May .seealso: DMSwarmGetSize(), DMSwarmSetLocalSizes()
587d3a51819SDave May @*/
588dcf43ee8SDave May PETSC_EXTERN PetscErrorCode DMSwarmGetLocalSize(DM dm,PetscInt *nlocal)
589dcf43ee8SDave May {
590dcf43ee8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
591dcf43ee8SDave May   PetscErrorCode ierr;
592dcf43ee8SDave May 
593521f74f9SMatthew G. Knepley   PetscFunctionBegin;
594521f74f9SMatthew G. Knepley   if (nlocal) {ierr = DataBucketGetSizes(swarm->db,nlocal,NULL,NULL);CHKERRQ(ierr);}
595dcf43ee8SDave May   PetscFunctionReturn(0);
596dcf43ee8SDave May }
597dcf43ee8SDave May 
598d3a51819SDave May /*@C
599d3a51819SDave May    DMSwarmGetSize - Retrives the total length of fields registered
600d3a51819SDave May 
601d3a51819SDave May    Collective on DM
602d3a51819SDave May 
603d3a51819SDave May    Input parameter:
604d3a51819SDave May .  dm - a DMSwarm
605d3a51819SDave May 
606d3a51819SDave May    Output parameter:
607d3a51819SDave May .  n - the total length of each registered field
608d3a51819SDave May 
609d3a51819SDave May    Level: beginner
610d3a51819SDave May 
611d3a51819SDave May    Note:
612d3a51819SDave May    This calls MPI_Allreduce upon each call (inefficient but safe)
613d3a51819SDave May 
6148b8a3813SDave May .seealso: DMSwarmGetLocalSize(), DMSwarmSetLocalSizes()
615d3a51819SDave May @*/
616dcf43ee8SDave May PETSC_EXTERN PetscErrorCode DMSwarmGetSize(DM dm,PetscInt *n)
617dcf43ee8SDave May {
618dcf43ee8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
619dcf43ee8SDave May   PetscErrorCode ierr;
620dcf43ee8SDave May   PetscInt nlocal,ng;
621dcf43ee8SDave May 
622521f74f9SMatthew G. Knepley   PetscFunctionBegin;
623dcf43ee8SDave May   ierr = DataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
624dcf43ee8SDave May   ierr = MPI_Allreduce(&nlocal,&ng,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
625dcf43ee8SDave May   if (n) { *n = ng; }
626dcf43ee8SDave May   PetscFunctionReturn(0);
627dcf43ee8SDave May }
628dcf43ee8SDave May 
629d3a51819SDave May /*@C
6308b8a3813SDave May    DMSwarmRegisterPetscDatatypeField - Register a field to a DMSwarm with a native PETSc data type
631d3a51819SDave May 
632d3a51819SDave May    Collective on DM
633d3a51819SDave May 
634d3a51819SDave May    Input parameters:
63562741f57SDave May +  dm - a DMSwarm
636d3a51819SDave May .  fieldname - the textual name to identify this field
637d3a51819SDave May .  blocksize - the number of each data type
63862741f57SDave May -  type - a valid PETSc data type (PETSC_CHAR, PETSC_SHORT, PETSC_INT, PETSC_FLOAT, PETSC_REAL, PETSC_LONG)
639d3a51819SDave May 
640d3a51819SDave May    Level: beginner
641d3a51819SDave May 
642d3a51819SDave May    Notes:
6438b8a3813SDave May    The textual name for each registered field must be unique.
644d3a51819SDave May 
645d3a51819SDave May .seealso: DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
646d3a51819SDave May @*/
6475f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmRegisterPetscDatatypeField(DM dm,const char fieldname[],PetscInt blocksize,PetscDataType type)
648b62e03f8SDave May {
6492eac95f8SDave May   PetscErrorCode ierr;
650b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
651b62e03f8SDave May   size_t size;
652b62e03f8SDave May 
653521f74f9SMatthew G. Knepley   PetscFunctionBegin;
6545f50eb2eSDave May   if (!swarm->field_registration_initialized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmInitializeFieldRegister() first");
6555f50eb2eSDave May   if (swarm->field_registration_finalized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Cannot register additional fields after calling DMSwarmFinalizeFieldRegister() first");
6565f50eb2eSDave May 
6575f50eb2eSDave May   if (type == PETSC_OBJECT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
6585f50eb2eSDave May   if (type == PETSC_FUNCTION) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
6595f50eb2eSDave May   if (type == PETSC_STRING) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
6605f50eb2eSDave May   if (type == PETSC_STRUCT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
6615f50eb2eSDave May   if (type == PETSC_DATATYPE_UNKNOWN) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
662b62e03f8SDave May 
6632ddcf43eSMatthew G. Knepley   ierr = PetscDataTypeGetSize(type, &size);CHKERRQ(ierr);
664b62e03f8SDave May   /* Load a specific data type into data bucket, specifying textual name and its size in bytes */
66552c3ed93SDave May   ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterPetscDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
66652c3ed93SDave May   {
66752c3ed93SDave May     DataField gfield;
66852c3ed93SDave May 
66952c3ed93SDave May     ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
67052c3ed93SDave May     ierr = DataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
67152c3ed93SDave May   }
672b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = type;
673b62e03f8SDave May   PetscFunctionReturn(0);
674b62e03f8SDave May }
675b62e03f8SDave May 
676d3a51819SDave May /*@C
677d3a51819SDave May    DMSwarmRegisterUserStructField - Register a user defined struct to a DMSwarm
678d3a51819SDave May 
679d3a51819SDave May    Collective on DM
680d3a51819SDave May 
681d3a51819SDave May    Input parameters:
68262741f57SDave May +  dm - a DMSwarm
683d3a51819SDave May .  fieldname - the textual name to identify this field
68462741f57SDave May -  size - the size in bytes of the user struct of each data type
685d3a51819SDave May 
686d3a51819SDave May    Level: beginner
687d3a51819SDave May 
688d3a51819SDave May    Notes:
6898b8a3813SDave May    The textual name for each registered field must be unique.
690d3a51819SDave May 
691d3a51819SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserDatatypeField()
692d3a51819SDave May @*/
6935f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmRegisterUserStructField(DM dm,const char fieldname[],size_t size)
694b62e03f8SDave May {
6952eac95f8SDave May   PetscErrorCode ierr;
696b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
697b62e03f8SDave May 
698521f74f9SMatthew G. Knepley   PetscFunctionBegin;
6992eac95f8SDave May   ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterUserStructField",fieldname,size,NULL);CHKERRQ(ierr);
700b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_STRUCT ;
701b62e03f8SDave May   PetscFunctionReturn(0);
702b62e03f8SDave May }
703b62e03f8SDave May 
704d3a51819SDave May /*@C
705d3a51819SDave May    DMSwarmRegisterUserDatatypeField - Register a user defined data type to a DMSwarm
706d3a51819SDave May 
707d3a51819SDave May    Collective on DM
708d3a51819SDave May 
709d3a51819SDave May    Input parameters:
71062741f57SDave May +  dm - a DMSwarm
711d3a51819SDave May .  fieldname - the textual name to identify this field
712d3a51819SDave May .  size - the size in bytes of the user data type
71362741f57SDave May -  blocksize - the number of each data type
714d3a51819SDave May 
715d3a51819SDave May    Level: beginner
716d3a51819SDave May 
717d3a51819SDave May    Notes:
7188b8a3813SDave May    The textual name for each registered field must be unique.
719d3a51819SDave May 
720d3a51819SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
721d3a51819SDave May @*/
722320740a0SDave May PETSC_EXTERN PetscErrorCode DMSwarmRegisterUserDatatypeField(DM dm,const char fieldname[],size_t size,PetscInt blocksize)
723b62e03f8SDave May {
724b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
7256845f8f5SDave May   PetscErrorCode ierr;
726b62e03f8SDave May 
727521f74f9SMatthew G. Knepley   PetscFunctionBegin;
728320740a0SDave May   ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterUserDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
729320740a0SDave May   {
730320740a0SDave May     DataField gfield;
731320740a0SDave May 
732320740a0SDave May     ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
733320740a0SDave May     ierr = DataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
734320740a0SDave May   }
735b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_DATATYPE_UNKNOWN;
736b62e03f8SDave May   PetscFunctionReturn(0);
737b62e03f8SDave May }
738b62e03f8SDave May 
739d3a51819SDave May /*@C
740d3a51819SDave May    DMSwarmGetField - Get access to the underlying array storing all entries associated with a registered field
741d3a51819SDave May 
742d3a51819SDave May    Not collective
743d3a51819SDave May 
744d3a51819SDave May    Input parameters:
74562741f57SDave May +  dm - a DMSwarm
74662741f57SDave May -  fieldname - the textual name to identify this field
747d3a51819SDave May 
748d3a51819SDave May    Output parameters:
74962741f57SDave May +  blocksize - the number of each data type
750d3a51819SDave May .  type - the data type
75162741f57SDave May -  data - pointer to raw array
752d3a51819SDave May 
753d3a51819SDave May    Level: beginner
754d3a51819SDave May 
755d3a51819SDave May    Notes:
7568b8a3813SDave May    The array must be returned using a matching call to DMSwarmRestoreField().
757d3a51819SDave May 
758d3a51819SDave May .seealso: DMSwarmRestoreField()
759d3a51819SDave May @*/
7605f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmGetField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
761b62e03f8SDave May {
762b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
763b62e03f8SDave May   DataField gfield;
7642eac95f8SDave May   PetscErrorCode ierr;
765b62e03f8SDave May 
766521f74f9SMatthew G. Knepley   PetscFunctionBegin;
7673454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
7682eac95f8SDave May   ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
7696845f8f5SDave May   ierr = DataFieldGetAccess(gfield);CHKERRQ(ierr);
7706845f8f5SDave May   ierr = DataFieldGetEntries(gfield,data);CHKERRQ(ierr);
7711b1ea282SDave May   if (blocksize) {*blocksize = gfield->bs; }
772b5bcf523SDave May   if (type) { *type = gfield->petsc_type; }
773b62e03f8SDave May   PetscFunctionReturn(0);
774b62e03f8SDave May }
775b62e03f8SDave May 
776d3a51819SDave May /*@C
777d3a51819SDave May    DMSwarmRestoreField - Restore access to the underlying array storing all entries associated with a registered field
778d3a51819SDave May 
779d3a51819SDave May    Not collective
780d3a51819SDave May 
781d3a51819SDave May    Input parameters:
78262741f57SDave May +  dm - a DMSwarm
78362741f57SDave May -  fieldname - the textual name to identify this field
784d3a51819SDave May 
785d3a51819SDave May    Output parameters:
78662741f57SDave May +  blocksize - the number of each data type
787d3a51819SDave May .  type - the data type
78862741f57SDave May -  data - pointer to raw array
789d3a51819SDave May 
790d3a51819SDave May    Level: beginner
791d3a51819SDave May 
792d3a51819SDave May    Notes:
7938b8a3813SDave May    The user must call DMSwarmGetField() prior to calling DMSwarmRestoreField().
794d3a51819SDave May 
795d3a51819SDave May .seealso: DMSwarmGetField()
796d3a51819SDave May @*/
7975f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmRestoreField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
798b62e03f8SDave May {
799b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
800b62e03f8SDave May   DataField gfield;
8012eac95f8SDave May   PetscErrorCode ierr;
802b62e03f8SDave May 
803521f74f9SMatthew G. Knepley   PetscFunctionBegin;
8042eac95f8SDave May   ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
8056845f8f5SDave May   ierr = DataFieldRestoreAccess(gfield);CHKERRQ(ierr);
806b62e03f8SDave May   if (data) *data = NULL;
807b62e03f8SDave May   PetscFunctionReturn(0);
808b62e03f8SDave May }
809b62e03f8SDave May 
810d3a51819SDave May /*@C
811d3a51819SDave May    DMSwarmAddPoint - Add space for one new point in the DMSwarm
812d3a51819SDave May 
813d3a51819SDave May    Not collective
814d3a51819SDave May 
815d3a51819SDave May    Input parameter:
816d3a51819SDave May .  dm - a DMSwarm
817d3a51819SDave May 
818d3a51819SDave May    Level: beginner
819d3a51819SDave May 
820d3a51819SDave May    Notes:
8218b8a3813SDave May    The new point will have all fields initialized to zero.
822d3a51819SDave May 
823d3a51819SDave May .seealso: DMSwarmAddNPoints()
824d3a51819SDave May @*/
825cb1d1399SDave May PETSC_EXTERN PetscErrorCode DMSwarmAddPoint(DM dm)
826cb1d1399SDave May {
827cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
828cb1d1399SDave May   PetscErrorCode ierr;
829cb1d1399SDave May 
830521f74f9SMatthew G. Knepley   PetscFunctionBegin;
8313454631fSDave May   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
832f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
833cb1d1399SDave May   ierr = DataBucketAddPoint(swarm->db);CHKERRQ(ierr);
834f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
835cb1d1399SDave May   PetscFunctionReturn(0);
836cb1d1399SDave May }
837cb1d1399SDave May 
838d3a51819SDave May /*@C
839d3a51819SDave May    DMSwarmAddNPoints - Add space for a number of new points in the DMSwarm
840d3a51819SDave May 
841d3a51819SDave May    Not collective
842d3a51819SDave May 
843d3a51819SDave May    Input parameters:
84462741f57SDave May +  dm - a DMSwarm
84562741f57SDave May -  npoints - the number of new points to add
846d3a51819SDave May 
847d3a51819SDave May    Level: beginner
848d3a51819SDave May 
849d3a51819SDave May    Notes:
8508b8a3813SDave May    The new point will have all fields initialized to zero.
851d3a51819SDave May 
852d3a51819SDave May .seealso: DMSwarmAddPoint()
853d3a51819SDave May @*/
854cb1d1399SDave May PETSC_EXTERN PetscErrorCode DMSwarmAddNPoints(DM dm,PetscInt npoints)
855cb1d1399SDave May {
856cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
857cb1d1399SDave May   PetscErrorCode ierr;
858cb1d1399SDave May   PetscInt nlocal;
859cb1d1399SDave May 
860521f74f9SMatthew G. Knepley   PetscFunctionBegin;
861f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
862cb1d1399SDave May   ierr = DataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
863cb1d1399SDave May   nlocal = nlocal + npoints;
86465141ba8SDave May   ierr = DataBucketSetSizes(swarm->db,nlocal,DATA_BUCKET_BUFFER_DEFAULT);CHKERRQ(ierr);
865f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
866cb1d1399SDave May   PetscFunctionReturn(0);
867cb1d1399SDave May }
868cb1d1399SDave May 
869d3a51819SDave May /*@C
870d3a51819SDave May    DMSwarmRemovePoint - Remove the last point from the DMSwarm
871d3a51819SDave May 
872d3a51819SDave May    Not collective
873d3a51819SDave May 
874d3a51819SDave May    Input parameter:
875d3a51819SDave May .  dm - a DMSwarm
876d3a51819SDave May 
877d3a51819SDave May    Level: beginner
878d3a51819SDave May 
879d3a51819SDave May .seealso: DMSwarmRemovePointAtIndex()
880d3a51819SDave May @*/
881cb1d1399SDave May PETSC_EXTERN PetscErrorCode DMSwarmRemovePoint(DM dm)
882cb1d1399SDave May {
883cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
884cb1d1399SDave May   PetscErrorCode ierr;
885cb1d1399SDave May 
886521f74f9SMatthew G. Knepley   PetscFunctionBegin;
887f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
888cb1d1399SDave May   ierr = DataBucketRemovePoint(swarm->db);CHKERRQ(ierr);
889f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
890cb1d1399SDave May   PetscFunctionReturn(0);
891cb1d1399SDave May }
892cb1d1399SDave May 
893d3a51819SDave May /*@C
894d3a51819SDave May    DMSwarmRemovePointAtIndex - Removes a specific point from the DMSwarm
895d3a51819SDave May 
896d3a51819SDave May    Not collective
897d3a51819SDave May 
898d3a51819SDave May    Input parameters:
89962741f57SDave May +  dm - a DMSwarm
90062741f57SDave May -  idx - index of point to remove
901d3a51819SDave May 
902d3a51819SDave May    Level: beginner
903d3a51819SDave May 
904d3a51819SDave May .seealso: DMSwarmRemovePoint()
905d3a51819SDave May @*/
906cb1d1399SDave May PETSC_EXTERN PetscErrorCode DMSwarmRemovePointAtIndex(DM dm,PetscInt idx)
907cb1d1399SDave May {
908cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
909cb1d1399SDave May   PetscErrorCode ierr;
910cb1d1399SDave May 
911521f74f9SMatthew G. Knepley   PetscFunctionBegin;
912f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
913cb1d1399SDave May   ierr = DataBucketRemovePointAtIndex(swarm->db,idx);CHKERRQ(ierr);
914f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
915cb1d1399SDave May   PetscFunctionReturn(0);
916cb1d1399SDave May }
917b62e03f8SDave May 
918ba4fc9c6SDave May /*@C
919ba4fc9c6SDave May    DMSwarmCopyPoint - Copy point pj to point pi in the DMSwarm
920ba4fc9c6SDave May 
921ba4fc9c6SDave May    Not collective
922ba4fc9c6SDave May 
923ba4fc9c6SDave May    Input parameters:
924ba4fc9c6SDave May +  dm - a DMSwarm
925ba4fc9c6SDave May .  pi - the index of the point to copy
926ba4fc9c6SDave May -  pj - the point index where the copy should be located
927ba4fc9c6SDave May 
928ba4fc9c6SDave May  Level: beginner
929ba4fc9c6SDave May 
930ba4fc9c6SDave May .seealso: DMSwarmRemovePoint()
931ba4fc9c6SDave May @*/
932ba4fc9c6SDave May PETSC_EXTERN PetscErrorCode DMSwarmCopyPoint(DM dm,PetscInt pi,PetscInt pj)
933ba4fc9c6SDave May {
934ba4fc9c6SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
935ba4fc9c6SDave May   PetscErrorCode ierr;
936ba4fc9c6SDave May 
937ba4fc9c6SDave May   PetscFunctionBegin;
938ba4fc9c6SDave May   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
939ba4fc9c6SDave May   ierr = DataBucketCopyPoint(swarm->db,pi,swarm->db,pj);CHKERRQ(ierr);
940ba4fc9c6SDave May   PetscFunctionReturn(0);
941ba4fc9c6SDave May }
942ba4fc9c6SDave May 
943095059a4SDave May PetscErrorCode DMSwarmMigrate_Basic(DM dm,PetscBool remove_sent_points)
9443454631fSDave May {
945dcf43ee8SDave May   PetscErrorCode ierr;
946521f74f9SMatthew G. Knepley 
947521f74f9SMatthew G. Knepley   PetscFunctionBegin;
948dcf43ee8SDave May   ierr = DMSwarmMigrate_Push_Basic(dm,remove_sent_points);CHKERRQ(ierr);
9493454631fSDave May   PetscFunctionReturn(0);
9503454631fSDave May }
9513454631fSDave May 
952d3a51819SDave May /*@C
953d3a51819SDave May    DMSwarmMigrate - Relocates points defined in the DMSwarm to other MPI-ranks
954d3a51819SDave May 
955d3a51819SDave May    Collective on DM
956d3a51819SDave May 
957d3a51819SDave May    Input parameters:
95862741f57SDave May +  dm - the DMSwarm
95962741f57SDave May -  remove_sent_points - flag indicating if sent points should be removed from the current MPI-rank
960d3a51819SDave May 
961d3a51819SDave May    Notes:
9628b8a3813SDave May    The DM will be modified to accomodate received points.
9638b8a3813SDave May    If remove_sent_points = PETSC_TRUE, any points that were sent will be removed from the DM.
9648b8a3813SDave May    Different styles of migration are supported. See DMSwarmSetMigrateType().
965d3a51819SDave May 
966d3a51819SDave May    Level: advanced
967d3a51819SDave May 
968d3a51819SDave May .seealso: DMSwarmSetMigrateType()
969d3a51819SDave May @*/
970095059a4SDave May PETSC_EXTERN PetscErrorCode DMSwarmMigrate(DM dm,PetscBool remove_sent_points)
9713454631fSDave May {
972f0cdbbbaSDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
9733454631fSDave May   PetscErrorCode ierr;
974f0cdbbbaSDave May 
975521f74f9SMatthew G. Knepley   PetscFunctionBegin;
976ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
977f0cdbbbaSDave May   switch (swarm->migrate_type) {
978f0cdbbbaSDave May     case DMSWARM_MIGRATE_BASIC:
979095059a4SDave May       ierr = DMSwarmMigrate_Basic(dm,remove_sent_points);CHKERRQ(ierr);
980f0cdbbbaSDave May       break;
981f0cdbbbaSDave May     case DMSWARM_MIGRATE_DMCELLNSCATTER:
982f0cdbbbaSDave May       ierr = DMSwarmMigrate_CellDMScatter(dm,remove_sent_points);CHKERRQ(ierr);
983f0cdbbbaSDave May       break;
984f0cdbbbaSDave May     case DMSWARM_MIGRATE_DMCELLEXACT:
985f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_DMCELLEXACT not implemented");
986521f74f9SMatthew G. Knepley       /*ierr = DMSwarmMigrate_CellDMExact(dm,remove_sent_points);CHKERRQ(ierr);*/
987f0cdbbbaSDave May       break;
988f0cdbbbaSDave May     case DMSWARM_MIGRATE_USER:
989f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_USER not implemented");
990521f74f9SMatthew G. Knepley       /*ierr = swarm->migrate(dm,remove_sent_points);CHKERRQ(ierr);*/
991f0cdbbbaSDave May       break;
992f0cdbbbaSDave May     default:
993f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE type unknown");
994f0cdbbbaSDave May       break;
995f0cdbbbaSDave May   }
996ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
9973454631fSDave May   PetscFunctionReturn(0);
9983454631fSDave May }
9993454631fSDave May 
1000f0cdbbbaSDave May PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm,PetscInt *globalsize);
1001f0cdbbbaSDave May 
1002d3a51819SDave May /*
1003d3a51819SDave May  DMSwarmCollectViewCreate
1004d3a51819SDave May 
1005d3a51819SDave May  * Applies a collection method and gathers point neighbour points into dm
1006d3a51819SDave May 
1007d3a51819SDave May  Notes:
10088b8a3813SDave May  Users should call DMSwarmCollectViewDestroy() after
1009d3a51819SDave May  they have finished computations associated with the collected points
1010d3a51819SDave May */
1011d3a51819SDave May 
1012d3a51819SDave May /*@C
1013d3a51819SDave May    DMSwarmCollectViewCreate - Applies a collection method and gathers points
1014d3a51819SDave May    in neighbour MPI-ranks into the DMSwarm
1015d3a51819SDave May 
1016d3a51819SDave May    Collective on DM
1017d3a51819SDave May 
1018d3a51819SDave May    Input parameter:
1019d3a51819SDave May .  dm - the DMSwarm
1020d3a51819SDave May 
1021d3a51819SDave May    Notes:
1022d3a51819SDave May    Users should call DMSwarmCollectViewDestroy() after
1023d3a51819SDave May    they have finished computations associated with the collected points
10248b8a3813SDave May    Different collect methods are supported. See DMSwarmSetCollectType().
1025d3a51819SDave May 
1026d3a51819SDave May    Level: advanced
1027d3a51819SDave May 
1028d3a51819SDave May .seealso: DMSwarmCollectViewDestroy(), DMSwarmSetCollectType()
1029d3a51819SDave May @*/
1030fe39f135SDave May PETSC_EXTERN PetscErrorCode DMSwarmCollectViewCreate(DM dm)
10312712d1f2SDave May {
10322712d1f2SDave May   PetscErrorCode ierr;
10332712d1f2SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
10342712d1f2SDave May   PetscInt ng;
10352712d1f2SDave May 
1036521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1037480eef7bSDave May   if (swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView currently active");
1038480eef7bSDave May   ierr = DMSwarmGetLocalSize(dm,&ng);CHKERRQ(ierr);
1039480eef7bSDave May   switch (swarm->collect_type) {
1040f0cdbbbaSDave May 
1041480eef7bSDave May     case DMSWARM_COLLECT_BASIC:
10422712d1f2SDave May       ierr = DMSwarmMigrate_GlobalToLocal_Basic(dm,&ng);CHKERRQ(ierr);
1043480eef7bSDave May       break;
1044480eef7bSDave May     case DMSWARM_COLLECT_DMDABOUNDINGBOX:
1045f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_DMDABOUNDINGBOX not implemented");
1046521f74f9SMatthew G. Knepley       /*ierr = DMSwarmCollect_DMDABoundingBox(dm,&ng);CHKERRQ(ierr);*/
1047480eef7bSDave May       break;
1048480eef7bSDave May     case DMSWARM_COLLECT_GENERAL:
1049f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_GENERAL not implemented");
1050521f74f9SMatthew G. Knepley       /*ierr = DMSwarmCollect_General(dm,..,,..,&ng);CHKERRQ(ierr);*/
1051480eef7bSDave May       break;
1052480eef7bSDave May     default:
1053f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT type unknown");
1054480eef7bSDave May       break;
1055480eef7bSDave May   }
1056480eef7bSDave May   swarm->collect_view_active = PETSC_TRUE;
1057480eef7bSDave May   swarm->collect_view_reset_nlocal = ng;
10582712d1f2SDave May   PetscFunctionReturn(0);
10592712d1f2SDave May }
10602712d1f2SDave May 
1061d3a51819SDave May /*@C
1062d3a51819SDave May    DMSwarmCollectViewDestroy - Resets the DMSwarm to the size prior to calling DMSwarmCollectViewCreate()
1063d3a51819SDave May 
1064d3a51819SDave May    Collective on DM
1065d3a51819SDave May 
1066d3a51819SDave May    Input parameters:
1067d3a51819SDave May .  dm - the DMSwarm
1068d3a51819SDave May 
1069d3a51819SDave May    Notes:
1070d3a51819SDave May    Users should call DMSwarmCollectViewCreate() before this function is called.
1071d3a51819SDave May 
1072d3a51819SDave May    Level: advanced
1073d3a51819SDave May 
1074d3a51819SDave May .seealso: DMSwarmCollectViewCreate(), DMSwarmSetCollectType()
1075d3a51819SDave May @*/
1076fe39f135SDave May PETSC_EXTERN PetscErrorCode DMSwarmCollectViewDestroy(DM dm)
10772712d1f2SDave May {
10782712d1f2SDave May   PetscErrorCode ierr;
10792712d1f2SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
10802712d1f2SDave May 
1081521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1082480eef7bSDave May   if (!swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView is currently not active");
1083480eef7bSDave May   ierr = DMSwarmSetLocalSizes(dm,swarm->collect_view_reset_nlocal,-1);CHKERRQ(ierr);
1084480eef7bSDave May   swarm->collect_view_active = PETSC_FALSE;
10852712d1f2SDave May   PetscFunctionReturn(0);
10862712d1f2SDave May }
10873454631fSDave May 
1088f0cdbbbaSDave May PetscErrorCode DMSwarmSetUpPIC(DM dm)
1089f0cdbbbaSDave May {
1090f0cdbbbaSDave May   PetscInt dim;
1091f0cdbbbaSDave May   PetscErrorCode ierr;
1092f0cdbbbaSDave May 
1093521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1094f0cdbbbaSDave May   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
1095f0cdbbbaSDave May   if (dim < 1) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
1096f0cdbbbaSDave May   if (dim > 3) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
1097f0cdbbbaSDave May   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_coor,dim,PETSC_DOUBLE);CHKERRQ(ierr);
1098e2d107dbSDave May   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_cellid,1,PETSC_INT);CHKERRQ(ierr);
1099f0cdbbbaSDave May   PetscFunctionReturn(0);
1100f0cdbbbaSDave May }
1101f0cdbbbaSDave May 
1102d3a51819SDave May /*@C
1103d3a51819SDave May    DMSwarmSetType - Set particular flavor of DMSwarm
1104d3a51819SDave May 
1105d3a51819SDave May    Collective on DM
1106d3a51819SDave May 
1107d3a51819SDave May    Input parameters:
110862741f57SDave May +  dm - the DMSwarm
110962741f57SDave May -  stype - the DMSwarm type (e.g. DMSWARM_PIC)
1110d3a51819SDave May 
1111d3a51819SDave May    Level: advanced
1112d3a51819SDave May 
1113d3a51819SDave May .seealso: DMSwarmSetMigrateType(), DMSwarmSetCollectType()
1114d3a51819SDave May @*/
1115f0cdbbbaSDave May PETSC_EXTERN PetscErrorCode DMSwarmSetType(DM dm,DMSwarmType stype)
1116f0cdbbbaSDave May {
1117f0cdbbbaSDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
1118f0cdbbbaSDave May   PetscErrorCode ierr;
1119f0cdbbbaSDave May 
1120521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1121f0cdbbbaSDave May   swarm->swarm_type = stype;
1122f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
1123f0cdbbbaSDave May     ierr = DMSwarmSetUpPIC(dm);CHKERRQ(ierr);
1124f0cdbbbaSDave May   }
1125f0cdbbbaSDave May   PetscFunctionReturn(0);
1126f0cdbbbaSDave May }
1127f0cdbbbaSDave May 
11283454631fSDave May PetscErrorCode DMSetup_Swarm(DM dm)
11293454631fSDave May {
11303454631fSDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
11313454631fSDave May   PetscErrorCode ierr;
11323454631fSDave May   PetscMPIInt rank;
11333454631fSDave May   PetscInt p,npoints,*rankval;
11343454631fSDave May 
1135521f74f9SMatthew G. Knepley   PetscFunctionBegin;
11363454631fSDave May   if (swarm->issetup) PetscFunctionReturn(0);
11373454631fSDave May 
11383454631fSDave May   swarm->issetup = PETSC_TRUE;
11393454631fSDave May 
1140f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
1141f0cdbbbaSDave May     /* check dmcell exists */
1142f0cdbbbaSDave May     if (!swarm->dmcell) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires you call DMSwarmSetCellDM");
1143f0cdbbbaSDave May 
1144f0cdbbbaSDave May     if (swarm->dmcell->ops->locatepointssubdomain) {
1145f0cdbbbaSDave May       /* check methods exists for exact ownership identificiation */
1146521f74f9SMatthew G. Knepley       ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->ops->LocatePointsSubdomain\n");CHKERRQ(ierr);
1147f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLEXACT;
1148f0cdbbbaSDave May     } else {
1149f0cdbbbaSDave May       /* check methods exist for point location AND rank neighbor identification */
1150f0cdbbbaSDave May       if (swarm->dmcell->ops->locatepoints) {
1151521f74f9SMatthew G. Knepley         ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->LocatePoints\n");CHKERRQ(ierr);
1152f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->locatepoints be defined");
1153f0cdbbbaSDave May 
1154f0cdbbbaSDave May       if (swarm->dmcell->ops->getneighbors) {
1155521f74f9SMatthew G. Knepley         ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->GetNeigbors\n");CHKERRQ(ierr);
1156f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->getneighbors be defined");
1157f0cdbbbaSDave May 
1158f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLNSCATTER;
1159f0cdbbbaSDave May     }
1160f0cdbbbaSDave May   }
1161f0cdbbbaSDave May 
1162f0cdbbbaSDave May   ierr = DMSwarmFinalizeFieldRegister(dm);CHKERRQ(ierr);
1163f0cdbbbaSDave May 
11643454631fSDave May   /* check some fields were registered */
11653454631fSDave May   if (swarm->db->nfields <= 2) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"At least one field user must be registered via DMSwarmRegisterXXX()");
11663454631fSDave May 
11673454631fSDave May   /* check local sizes were set */
11683454631fSDave May   if (swarm->db->L == -1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Local sizes must be set via DMSwarmSetLocalSizes()");
11693454631fSDave May 
11703454631fSDave May   /* initialize values in pid and rank placeholders */
11713454631fSDave May   /* TODO: [pid - use MPI_Scan] */
11723454631fSDave May   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
11733454631fSDave May   ierr = DataBucketGetSizes(swarm->db,&npoints,NULL,NULL);CHKERRQ(ierr);
1174f0cdbbbaSDave May   ierr = DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
11753454631fSDave May   for (p=0; p<npoints; p++) {
11763454631fSDave May     rankval[p] = (PetscInt)rank;
11773454631fSDave May   }
1178f0cdbbbaSDave May   ierr = DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
11793454631fSDave May   PetscFunctionReturn(0);
11803454631fSDave May }
11813454631fSDave May 
1182dc5f5ce9SDave May extern PetscErrorCode DMSwarmSortDestroy(DMSwarmSort *_ctx);
1183dc5f5ce9SDave May 
118457795646SDave May PetscErrorCode DMDestroy_Swarm(DM dm)
118557795646SDave May {
118657795646SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
118757795646SDave May   PetscErrorCode ierr;
118857795646SDave May 
118957795646SDave May   PetscFunctionBegin;
11906845f8f5SDave May   ierr = DataBucketDestroy(&swarm->db);CHKERRQ(ierr);
1191dc5f5ce9SDave May   if (swarm->sort_context) {
1192dc5f5ce9SDave May     ierr = DMSwarmSortDestroy(&swarm->sort_context);CHKERRQ(ierr);
1193dc5f5ce9SDave May   }
119457795646SDave May   ierr = PetscFree(swarm);CHKERRQ(ierr);
119557795646SDave May   PetscFunctionReturn(0);
119657795646SDave May }
119757795646SDave May 
1198a9ee3421SMatthew G. Knepley PetscErrorCode DMSwarmView_Draw(DM dm, PetscViewer viewer)
1199a9ee3421SMatthew G. Knepley {
1200a9ee3421SMatthew G. Knepley   DM             cdm;
1201a9ee3421SMatthew G. Knepley   PetscDraw      draw;
1202a9ee3421SMatthew G. Knepley   PetscReal     *coords, oldPause;
1203a9ee3421SMatthew G. Knepley   PetscInt       Np, p, bs;
1204a9ee3421SMatthew G. Knepley   PetscErrorCode ierr;
1205a9ee3421SMatthew G. Knepley 
1206a9ee3421SMatthew G. Knepley   PetscFunctionBegin;
1207a9ee3421SMatthew G. Knepley   ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr);
1208a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetCellDM(dm, &cdm);CHKERRQ(ierr);
1209a9ee3421SMatthew G. Knepley   ierr = PetscDrawGetPause(draw, &oldPause);CHKERRQ(ierr);
1210a9ee3421SMatthew G. Knepley   ierr = PetscDrawSetPause(draw, 0.0);CHKERRQ(ierr);
1211a9ee3421SMatthew G. Knepley   ierr = DMView(cdm, viewer);CHKERRQ(ierr);
1212a9ee3421SMatthew G. Knepley   ierr = PetscDrawSetPause(draw, oldPause);CHKERRQ(ierr);
1213a9ee3421SMatthew G. Knepley 
1214a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetLocalSize(dm, &Np);CHKERRQ(ierr);
1215a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1216a9ee3421SMatthew G. Knepley   for (p = 0; p < Np; ++p) {
1217a9ee3421SMatthew G. Knepley     const PetscInt i = p*bs;
1218a9ee3421SMatthew G. Knepley 
1219a9ee3421SMatthew G. Knepley     ierr = PetscDrawEllipse(draw, coords[i], coords[i+1], 0.01, 0.01, PETSC_DRAW_BLUE);CHKERRQ(ierr);
1220a9ee3421SMatthew G. Knepley   }
1221a9ee3421SMatthew G. Knepley   ierr = DMSwarmRestoreField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1222a9ee3421SMatthew G. Knepley   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
1223a9ee3421SMatthew G. Knepley   ierr = PetscDrawPause(draw);CHKERRQ(ierr);
1224a9ee3421SMatthew G. Knepley   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
1225a9ee3421SMatthew G. Knepley   PetscFunctionReturn(0);
1226a9ee3421SMatthew G. Knepley }
1227a9ee3421SMatthew G. Knepley 
12285f50eb2eSDave May PetscErrorCode DMView_Swarm(DM dm, PetscViewer viewer)
12295f50eb2eSDave May {
12305f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
1231a9ee3421SMatthew G. Knepley   PetscBool      iascii,ibinary,ishdf5,isvtk,isdraw;
12325f50eb2eSDave May   PetscErrorCode ierr;
12335f50eb2eSDave May 
12345f50eb2eSDave May   PetscFunctionBegin;
12355f50eb2eSDave May   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
12365f50eb2eSDave May   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
12375f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
12385f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY,&ibinary);CHKERRQ(ierr);
12395f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK,   &isvtk);CHKERRQ(ierr);
12405f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
1241a9ee3421SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW,  &isdraw);CHKERRQ(ierr);
12425f50eb2eSDave May   if (iascii) {
12436845f8f5SDave May     ierr = DataBucketView(PetscObjectComm((PetscObject)dm),swarm->db,NULL,DATABUCKET_VIEW_STDOUT);CHKERRQ(ierr);
12445f50eb2eSDave May   } else if (ibinary) {
1245a9ee3421SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO Binary support");
12465f50eb2eSDave May   } else if (ishdf5) {
12475f50eb2eSDave May #if defined(PETSC_HAVE_HDF5)
12485f50eb2eSDave May     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO HDF5 support");
12495f50eb2eSDave May #else
12505f50eb2eSDave May     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"HDF5 not supported. Please reconfigure using --download-hdf5");
12515f50eb2eSDave May #endif
12525f50eb2eSDave May   } else if (isvtk) {
12535f50eb2eSDave May     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO VTK support");
1254a9ee3421SMatthew G. Knepley   } else if (isdraw) {
1255a9ee3421SMatthew G. Knepley     ierr = DMSwarmView_Draw(dm, viewer);CHKERRQ(ierr);
12565f50eb2eSDave May   }
12575f50eb2eSDave May   PetscFunctionReturn(0);
12585f50eb2eSDave May }
12595f50eb2eSDave May 
1260d3a51819SDave May /*MC
1261d3a51819SDave May 
1262d3a51819SDave May  DMSWARM = "swarm" - A DM object used to represent arrays of data (fields) of arbitrary data type.
126362741f57SDave May  This implementation was designed for particle methods in which the underlying
1264d3a51819SDave May  data required to be represented is both (i) dynamic in length, (ii) and of arbitrary data type.
1265d3a51819SDave May 
126662741f57SDave May  User data can be represented by DMSwarm through a registering "fields".
126762741f57SDave May  To register a field, the user must provide;
126862741f57SDave May  (a) a unique name;
126962741f57SDave May  (b) the data type (or size in bytes);
127062741f57SDave May  (c) the block size of the data.
1271d3a51819SDave May 
1272d3a51819SDave May  For example, suppose the application requires a unique id, energy, momentum and density to be stored
127362741f57SDave May  on a set of of particles. Then the following code could be used
1274d3a51819SDave May 
127562741f57SDave May $    DMSwarmInitializeFieldRegister(dm)
127662741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"uid",1,PETSC_LONG);
127762741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"energy",1,PETSC_REAL);
127862741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"momentum",3,PETSC_REAL);
127962741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"density",1,PETSC_FLOAT);
128062741f57SDave May $    DMSwarmFinalizeFieldRegister(dm)
1281d3a51819SDave May 
1282d3a51819SDave May  The fields represented by DMSwarm are dynamic and can be re-sized at any time.
128362741f57SDave May  The only restriction imposed by DMSwarm is that all fields contain the same number of points.
1284d3a51819SDave May 
1285d3a51819SDave May  To support particle methods, "migration" techniques are provided. These methods migrate data
1286d3a51819SDave May  between MPI-ranks.
1287d3a51819SDave May 
1288d3a51819SDave May  DMSwarm supports the methods DMCreateGlobalVector() and DMCreateLocalVector().
1289d3a51819SDave May  As a DMSwarm may internally define and store values of different data types,
129062741f57SDave May  before calling DMCreateGlobalVector() or DMCreateLocalVector(), the user must inform DMSwarm which
1291d3a51819SDave May  fields should be used to define a Vec object via
1292d3a51819SDave May    DMSwarmVectorDefineField()
1293d3a51819SDave May  The specified field can can changed be changed at any time - thereby permitting vectors
1294d3a51819SDave May  compatable with different fields to be created.
1295d3a51819SDave May 
129662741f57SDave May  A dual representation of fields in the DMSwarm and a Vec object is permitted via
1297d3a51819SDave May    DMSwarmCreateGlobalVectorFromField()
1298d3a51819SDave May  Here the data defining the field in the DMSwarm is shared with a Vec.
1299d3a51819SDave May  This is inherently unsafe if you alter the size of the field at any time between
1300d3a51819SDave May  calls to DMSwarmCreateGlobalVectorFromField() and DMSwarmDestroyGlobalVectorFromField().
1301cc651181SDave May  If the local size of the DMSwarm does not match the local size of the global vector
1302cc651181SDave May  when DMSwarmDestroyGlobalVectorFromField() is called, an error is thrown.
1303d3a51819SDave May 
130462741f57SDave May  Additional high-level support is provided for Particle-In-Cell methods.
130562741f57SDave May  Please refer to the man page for DMSwarmSetType().
130662741f57SDave May 
1307d3a51819SDave May  Level: beginner
1308d3a51819SDave May 
1309d3a51819SDave May .seealso: DMType, DMCreate(), DMSetType()
1310d3a51819SDave May M*/
131157795646SDave May PETSC_EXTERN PetscErrorCode DMCreate_Swarm(DM dm)
131257795646SDave May {
131357795646SDave May   DM_Swarm      *swarm;
131457795646SDave May   PetscErrorCode ierr;
131557795646SDave May 
131657795646SDave May   PetscFunctionBegin;
131757795646SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
131857795646SDave May   ierr     = PetscNewLog(dm,&swarm);CHKERRQ(ierr);
1319f0cdbbbaSDave May   dm->data = swarm;
132057795646SDave May 
13216845f8f5SDave May   ierr = DataBucketCreate(&swarm->db);CHKERRQ(ierr);
1322f0cdbbbaSDave May   ierr = DMSwarmInitializeFieldRegister(dm);CHKERRQ(ierr);
1323f0cdbbbaSDave May 
1324b5bcf523SDave May   swarm->vec_field_set = PETSC_FALSE;
13253454631fSDave May   swarm->issetup = PETSC_FALSE;
1326480eef7bSDave May   swarm->swarm_type = DMSWARM_BASIC;
1327480eef7bSDave May   swarm->migrate_type = DMSWARM_MIGRATE_BASIC;
1328480eef7bSDave May   swarm->collect_type = DMSWARM_COLLECT_BASIC;
132940c453e9SDave May   swarm->migrate_error_on_missing_point = PETSC_FALSE;
1330b62e03f8SDave May 
1331f0cdbbbaSDave May   swarm->dmcell = NULL;
1332f0cdbbbaSDave May   swarm->collect_view_active = PETSC_FALSE;
1333f0cdbbbaSDave May   swarm->collect_view_reset_nlocal = -1;
133457795646SDave May 
1335f0cdbbbaSDave May   dm->dim  = 0;
13365f50eb2eSDave May   dm->ops->view                            = DMView_Swarm;
133757795646SDave May   dm->ops->load                            = NULL;
133857795646SDave May   dm->ops->setfromoptions                  = NULL;
133957795646SDave May   dm->ops->clone                           = NULL;
13403454631fSDave May   dm->ops->setup                           = DMSetup_Swarm;
134157795646SDave May   dm->ops->createdefaultsection            = NULL;
134257795646SDave May   dm->ops->createdefaultconstraints        = NULL;
1343b5bcf523SDave May   dm->ops->createglobalvector              = DMCreateGlobalVector_Swarm;
1344b5bcf523SDave May   dm->ops->createlocalvector               = DMCreateLocalVector_Swarm;
134557795646SDave May   dm->ops->getlocaltoglobalmapping         = NULL;
134657795646SDave May   dm->ops->createfieldis                   = NULL;
134757795646SDave May   dm->ops->createcoordinatedm              = NULL;
134857795646SDave May   dm->ops->getcoloring                     = NULL;
134957795646SDave May   dm->ops->creatematrix                    = NULL;
135057795646SDave May   dm->ops->createinterpolation             = NULL;
135157795646SDave May   dm->ops->getaggregates                   = NULL;
135257795646SDave May   dm->ops->getinjection                    = NULL;
1353*83c47955SMatthew G. Knepley   dm->ops->createmassmatrix                = DMCreateMassMatrix_Swarm;
135457795646SDave May   dm->ops->refine                          = NULL;
135557795646SDave May   dm->ops->coarsen                         = NULL;
135657795646SDave May   dm->ops->refinehierarchy                 = NULL;
135757795646SDave May   dm->ops->coarsenhierarchy                = NULL;
135857795646SDave May   dm->ops->globaltolocalbegin              = NULL;
135957795646SDave May   dm->ops->globaltolocalend                = NULL;
136057795646SDave May   dm->ops->localtoglobalbegin              = NULL;
136157795646SDave May   dm->ops->localtoglobalend                = NULL;
136257795646SDave May   dm->ops->destroy                         = DMDestroy_Swarm;
136357795646SDave May   dm->ops->createsubdm                     = NULL;
136457795646SDave May   dm->ops->getdimpoints                    = NULL;
136557795646SDave May   dm->ops->locatepoints                    = NULL;
136657795646SDave May   PetscFunctionReturn(0);
136757795646SDave May }
1368