xref: /petsc/src/dm/impls/swarm/swarm.c (revision e8f1478504fc744590f99974189eaf6dec42c56e)
157795646SDave May #define PETSCDM_DLL
257795646SDave May #include <petsc/private/dmswarmimpl.h>    /*I   "petscdmswarm.h"   I*/
3*e8f14785SLisandro Dalcin #include <petsc/private/hashsetij.h>
45917a6f0SStefano Zampini #include <petscviewer.h>
55917a6f0SStefano Zampini #include <petscdraw.h>
683c47955SMatthew G. Knepley #include <petscdmplex.h>
7279f676cSBarry Smith #include "../src/dm/impls/swarm/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:
36e7af74c8SDave May 
3762741f57SDave May    The field with name fieldname must be defined as having a data type of PetscScalar.
38e7af74c8SDave May 
39d3a51819SDave May    This function must be called prior to calling DMCreateLocalVector(), DMCreateGlobalVector().
40d3a51819SDave May    Mutiple calls to DMSwarmVectorDefineField() are permitted.
4157795646SDave May 
428b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMCreateGlobalVector(), DMCreateLocalVector()
43d3a51819SDave May @*/
44b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmVectorDefineField(DM dm,const char fieldname[])
45b5bcf523SDave May {
46b5bcf523SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
47b5bcf523SDave May   PetscErrorCode ierr;
48b5bcf523SDave May   PetscInt       bs,n;
49b5bcf523SDave May   PetscScalar    *array;
50b5bcf523SDave May   PetscDataType  type;
51b5bcf523SDave May 
52a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
533454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
5477048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db,&n,NULL,NULL);CHKERRQ(ierr);
55b5bcf523SDave May   ierr = DMSwarmGetField(dm,fieldname,&bs,&type,(void**)&array);CHKERRQ(ierr);
56b5bcf523SDave May 
57b5bcf523SDave May   /* Check all fields are of type PETSC_REAL or PETSC_SCALAR */
58b5bcf523SDave May   if (type != PETSC_REAL) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only valid for PETSC_REAL");
59521f74f9SMatthew G. Knepley   ierr = PetscSNPrintf(swarm->vec_field_name,PETSC_MAX_PATH_LEN-1,"%s",fieldname);CHKERRQ(ierr);
60b5bcf523SDave May   swarm->vec_field_set = PETSC_TRUE;
611b1ea282SDave May   swarm->vec_field_bs = bs;
62b5bcf523SDave May   swarm->vec_field_nlocal = n;
63dcf43ee8SDave May   ierr = DMSwarmRestoreField(dm,fieldname,&bs,&type,(void**)&array);CHKERRQ(ierr);
64b5bcf523SDave May   PetscFunctionReturn(0);
65b5bcf523SDave May }
66b5bcf523SDave May 
67cc651181SDave May /* requires DMSwarmDefineFieldVector has been called */
68b5bcf523SDave May PetscErrorCode DMCreateGlobalVector_Swarm(DM dm,Vec *vec)
69b5bcf523SDave May {
70b5bcf523SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
71b5bcf523SDave May   PetscErrorCode ierr;
72b5bcf523SDave May   Vec            x;
73b5bcf523SDave May   char           name[PETSC_MAX_PATH_LEN];
74b5bcf523SDave May 
75a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
763454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
77b5bcf523SDave May   if (!swarm->vec_field_set) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmVectorDefineField first");
78cc651181SDave 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 */
79cc651181SDave May 
80521f74f9SMatthew G. Knepley   ierr = PetscSNPrintf(name,PETSC_MAX_PATH_LEN-1,"DMSwarmField_%s",swarm->vec_field_name);CHKERRQ(ierr);
81b5bcf523SDave May   ierr = VecCreate(PetscObjectComm((PetscObject)dm),&x);CHKERRQ(ierr);
82b5bcf523SDave May   ierr = PetscObjectSetName((PetscObject)x,name);CHKERRQ(ierr);
831b1ea282SDave May   ierr = VecSetSizes(x,swarm->db->L*swarm->vec_field_bs,PETSC_DETERMINE);CHKERRQ(ierr);
84b5bcf523SDave May   ierr = VecSetBlockSize(x,swarm->vec_field_bs);CHKERRQ(ierr);
85b5bcf523SDave May   ierr = VecSetFromOptions(x);CHKERRQ(ierr);
86b5bcf523SDave May   *vec = x;
87b5bcf523SDave May   PetscFunctionReturn(0);
88b5bcf523SDave May }
89b5bcf523SDave May 
90b5bcf523SDave May /* requires DMSwarmDefineFieldVector has been called */
91b5bcf523SDave May PetscErrorCode DMCreateLocalVector_Swarm(DM dm,Vec *vec)
92b5bcf523SDave May {
93b5bcf523SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
94b5bcf523SDave May   PetscErrorCode ierr;
95b5bcf523SDave May   Vec x;
96b5bcf523SDave May   char name[PETSC_MAX_PATH_LEN];
97b5bcf523SDave May 
98a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
993454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
100b5bcf523SDave May   if (!swarm->vec_field_set) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmVectorDefineField first");
101cc651181SDave 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 */
102cc651181SDave May 
103521f74f9SMatthew G. Knepley   ierr = PetscSNPrintf(name,PETSC_MAX_PATH_LEN-1,"DMSwarmField_%s",swarm->vec_field_name);CHKERRQ(ierr);
104b5bcf523SDave May   ierr = VecCreate(PETSC_COMM_SELF,&x);CHKERRQ(ierr);
105b5bcf523SDave May   ierr = PetscObjectSetName((PetscObject)x,name);CHKERRQ(ierr);
106071900c8SMatthew G. Knepley   ierr = VecSetSizes(x,swarm->db->L*swarm->vec_field_bs,PETSC_DETERMINE);CHKERRQ(ierr);
107b5bcf523SDave May   ierr = VecSetBlockSize(x,swarm->vec_field_bs);CHKERRQ(ierr);
108b5bcf523SDave May   ierr = VecSetFromOptions(x);CHKERRQ(ierr);
109b5bcf523SDave May   *vec = x;
110b5bcf523SDave May   PetscFunctionReturn(0);
111b5bcf523SDave May }
112b5bcf523SDave May 
113fb1bcc12SMatthew G. Knepley static PetscErrorCode DMSwarmDestroyVectorFromField_Private(DM dm, const char fieldname[], Vec *vec)
114fb1bcc12SMatthew G. Knepley {
115fb1bcc12SMatthew G. Knepley   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
11677048351SPatrick Sanan   DMSwarmDataField      gfield;
117fb1bcc12SMatthew G. Knepley   void         (*fptr)(void);
118fb1bcc12SMatthew G. Knepley   PetscInt       bs, nlocal;
119fb1bcc12SMatthew G. Knepley   char           name[PETSC_MAX_PATH_LEN];
120fb1bcc12SMatthew G. Knepley   PetscErrorCode ierr;
121d3a51819SDave May 
122fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
123fb1bcc12SMatthew G. Knepley   ierr = VecGetLocalSize(*vec, &nlocal);CHKERRQ(ierr);
124fb1bcc12SMatthew G. Knepley   ierr = VecGetBlockSize(*vec, &bs);CHKERRQ(ierr);
125fb1bcc12SMatthew 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 */
12677048351SPatrick Sanan   ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield);CHKERRQ(ierr);
127fb1bcc12SMatthew G. Knepley   /* check vector is an inplace array */
128521f74f9SMatthew G. Knepley   ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarm_VecFieldInPlace_%s", fieldname);CHKERRQ(ierr);
129fb1bcc12SMatthew G. Knepley   ierr = PetscObjectQueryFunction((PetscObject) *vec, name, &fptr);CHKERRQ(ierr);
130fb1bcc12SMatthew G. Knepley   if (!fptr) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_USER, "Vector being destroyed was not created from DMSwarm field(%s)", fieldname);
13177048351SPatrick Sanan   ierr = DMSwarmDataFieldRestoreAccess(gfield);CHKERRQ(ierr);
132fb1bcc12SMatthew G. Knepley   ierr = VecDestroy(vec);CHKERRQ(ierr);
133fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
134fb1bcc12SMatthew G. Knepley }
135fb1bcc12SMatthew G. Knepley 
136fb1bcc12SMatthew G. Knepley static PetscErrorCode DMSwarmCreateVectorFromField_Private(DM dm, const char fieldname[], MPI_Comm comm, Vec *vec)
137fb1bcc12SMatthew G. Knepley {
138fb1bcc12SMatthew G. Knepley   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
139fb1bcc12SMatthew G. Knepley   PetscDataType  type;
140fb1bcc12SMatthew G. Knepley   PetscScalar   *array;
141fb1bcc12SMatthew G. Knepley   PetscInt       bs, n;
142fb1bcc12SMatthew G. Knepley   char           name[PETSC_MAX_PATH_LEN];
143e4fbd051SBarry Smith   PetscMPIInt    size;
144fb1bcc12SMatthew G. Knepley   PetscErrorCode ierr;
145fb1bcc12SMatthew G. Knepley 
146fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
147fb1bcc12SMatthew G. Knepley   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
14877048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db, &n, NULL, NULL);CHKERRQ(ierr);
149fb1bcc12SMatthew G. Knepley   ierr = DMSwarmGetField(dm, fieldname, &bs, &type, (void **) &array);CHKERRQ(ierr);
150fb1bcc12SMatthew G. Knepley   if (type != PETSC_REAL) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Only valid for PETSC_REAL");
151fb1bcc12SMatthew G. Knepley 
152e4fbd051SBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
153e4fbd051SBarry Smith   if (size == 1) {
154fb1bcc12SMatthew G. Knepley     ierr = VecCreateSeqWithArray(comm, bs, n*bs, array, vec);CHKERRQ(ierr);
155fb1bcc12SMatthew G. Knepley   } else {
156fb1bcc12SMatthew G. Knepley     ierr = VecCreateMPIWithArray(comm, bs, n*bs, PETSC_DETERMINE, array, vec);CHKERRQ(ierr);
157fb1bcc12SMatthew G. Knepley   }
158fb1bcc12SMatthew G. Knepley   ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarmSharedField_%s", fieldname);CHKERRQ(ierr);
159fb1bcc12SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) *vec, name);CHKERRQ(ierr);
160fb1bcc12SMatthew G. Knepley 
161fb1bcc12SMatthew G. Knepley   /* Set guard */
162fb1bcc12SMatthew G. Knepley   ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarm_VecFieldInPlace_%s", fieldname);CHKERRQ(ierr);
163fb1bcc12SMatthew G. Knepley   ierr = PetscObjectComposeFunction((PetscObject) *vec, name, DMSwarmDestroyVectorFromField_Private);CHKERRQ(ierr);
164fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
165fb1bcc12SMatthew G. Knepley }
166fb1bcc12SMatthew G. Knepley 
16783c47955SMatthew G. Knepley static PetscErrorCode DMSwarmComputeMassMatrix_Private(DM dmc, DM dmf, Mat mass, void *ctx)
16883c47955SMatthew G. Knepley {
16983c47955SMatthew G. Knepley   const char    *name = "Mass Matrix";
17083c47955SMatthew G. Knepley   PetscDS        prob;
17183c47955SMatthew G. Knepley   PetscSection   fsection, globalFSection;
172*e8f14785SLisandro Dalcin   PetscHSetIJ    ht;
17383c47955SMatthew G. Knepley   PetscLayout    rLayout;
17483c47955SMatthew G. Knepley   PetscInt      *dnz, *onz;
17583c47955SMatthew G. Knepley   PetscInt       locRows, rStart, rEnd;
17683c47955SMatthew G. Knepley   PetscReal     *x, *v0, *J, *invJ, detJ;
17783c47955SMatthew G. Knepley   PetscScalar   *elemMat;
178fc7c92abSMatthew G. Knepley   PetscInt       dim, Nf, field, totDim, cStart, cEnd, cell, maxC = 0;
1794f482ee1SMatthew G. Knepley   PetscMPIInt    size;
18083c47955SMatthew G. Knepley   PetscErrorCode ierr;
18183c47955SMatthew G. Knepley 
18283c47955SMatthew G. Knepley   PetscFunctionBegin;
1834f482ee1SMatthew G. Knepley   ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dmf), &size);CHKERRQ(ierr);
18483c47955SMatthew G. Knepley   ierr = DMGetCoordinateDim(dmf, &dim);CHKERRQ(ierr);
18583c47955SMatthew G. Knepley   ierr = DMGetDS(dmf, &prob);CHKERRQ(ierr);
18683c47955SMatthew G. Knepley   ierr = PetscDSGetRefCoordArrays(prob, &x, NULL);CHKERRQ(ierr);
18783c47955SMatthew G. Knepley   ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr);
18883c47955SMatthew G. Knepley   ierr = PetscMalloc3(dim,&v0,dim*dim,&J,dim*dim,&invJ);CHKERRQ(ierr);
18983c47955SMatthew G. Knepley   ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);
19083c47955SMatthew G. Knepley   ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);
19183c47955SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd);CHKERRQ(ierr);
19283c47955SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr);
19383c47955SMatthew G. Knepley   ierr = DMSwarmSortGetAccess(dmc);CHKERRQ(ierr);
19483c47955SMatthew G. Knepley 
19583c47955SMatthew G. Knepley   ierr = MatGetLocalSize(mass, &locRows, NULL);CHKERRQ(ierr);
19683c47955SMatthew G. Knepley   ierr = PetscLayoutCreate(PetscObjectComm((PetscObject) mass), &rLayout);CHKERRQ(ierr);
19783c47955SMatthew G. Knepley   ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr);
19883c47955SMatthew G. Knepley   ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr);
19983c47955SMatthew G. Knepley   ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr);
20083c47955SMatthew G. Knepley   ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr);
20183c47955SMatthew G. Knepley   ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr);
20283c47955SMatthew G. Knepley   ierr = PetscCalloc2(locRows,&dnz,locRows,&onz);CHKERRQ(ierr);
203*e8f14785SLisandro Dalcin   ierr = PetscHSetIJCreate(&ht);CHKERRQ(ierr);
20483c47955SMatthew G. Knepley   for (field = 0; field < Nf; ++field) {
20583c47955SMatthew G. Knepley     PetscObject      obj;
20683c47955SMatthew G. Knepley     PetscQuadrature  quad;
20783c47955SMatthew G. Knepley     const PetscReal *qpoints;
20883c47955SMatthew G. Knepley     PetscInt         Nq, Nc, i;
20983c47955SMatthew G. Knepley 
21083c47955SMatthew G. Knepley     ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr);
21183c47955SMatthew G. Knepley     ierr = PetscFEGetQuadrature((PetscFE) obj, &quad);CHKERRQ(ierr);
21283c47955SMatthew G. Knepley     ierr = PetscQuadratureGetData(quad, NULL, &Nc, &Nq, &qpoints, NULL);CHKERRQ(ierr);
21383c47955SMatthew G. Knepley     /* For each fine grid cell */
21483c47955SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
21583c47955SMatthew G. Knepley       PetscInt  Np, c;
21683c47955SMatthew G. Knepley       PetscInt *findices,   *cindices;
21783c47955SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
21883c47955SMatthew G. Knepley 
21983c47955SMatthew G. Knepley       ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
22083c47955SMatthew G. Knepley       ierr = DMSwarmSortGetNumberOfPointsPerCell(dmc, cell, &Np);CHKERRQ(ierr);
221e8291c10SMatthew G. Knepley       if (Np != Nq) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Not all closure points located %D != %D", Np, Nq);
222fc7c92abSMatthew G. Knepley       ierr = DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices);CHKERRQ(ierr);
223fc7c92abSMatthew G. Knepley       maxC = PetscMax(maxC, numCIndices);
22483c47955SMatthew G. Knepley       /* Update preallocation info */
22583c47955SMatthew G. Knepley       {
226*e8f14785SLisandro Dalcin         PetscHashIJKey key;
227*e8f14785SLisandro Dalcin         PetscBool      missing;
22883c47955SMatthew G. Knepley 
22983c47955SMatthew G. Knepley         for (i = 0; i < numFIndices; ++i) {
230*e8f14785SLisandro Dalcin           key.i = findices[i];
231*e8f14785SLisandro Dalcin           if (key.i >= 0) {
23283c47955SMatthew G. Knepley             /* Get indices for coarse elements */
23383c47955SMatthew G. Knepley             for (c = 0; c < numCIndices; ++c) {
234*e8f14785SLisandro Dalcin               key.j = cindices[c];
235*e8f14785SLisandro Dalcin               if (key.j < 0) continue;
236*e8f14785SLisandro Dalcin               ierr = PetscHSetIJQueryAdd(ht, key, &missing);CHKERRQ(ierr);
23783c47955SMatthew G. Knepley               if (missing) {
238*e8f14785SLisandro Dalcin                 if ((size == 1) || ((key.j >= rStart) && (key.j < rEnd))) ++dnz[key.i-rStart];
239*e8f14785SLisandro Dalcin                 else                                                      ++onz[key.i-rStart];
24083c47955SMatthew G. Knepley               }
24183c47955SMatthew G. Knepley             }
242fc7c92abSMatthew G. Knepley           }
243fc7c92abSMatthew G. Knepley         }
24483c47955SMatthew G. Knepley         ierr = PetscFree(cindices);CHKERRQ(ierr);
24583c47955SMatthew G. Knepley       }
24683c47955SMatthew G. Knepley       ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
24783c47955SMatthew G. Knepley     }
24883c47955SMatthew G. Knepley   }
249*e8f14785SLisandro Dalcin   ierr = PetscHSetIJDestroy(&ht);CHKERRQ(ierr);
25083c47955SMatthew G. Knepley   ierr = MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL);CHKERRQ(ierr);
25183c47955SMatthew G. Knepley   ierr = MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
25283c47955SMatthew G. Knepley   ierr = PetscFree2(dnz,onz);CHKERRQ(ierr);
253fc7c92abSMatthew G. Knepley   ierr = PetscMalloc1(maxC, &elemMat);CHKERRQ(ierr);
25483c47955SMatthew G. Knepley   for (field = 0; field < Nf; ++field) {
25583c47955SMatthew G. Knepley     PetscObject      obj;
25683c47955SMatthew G. Knepley     PetscQuadrature  quad;
25783c47955SMatthew G. Knepley     PetscReal       *Bfine;
25883c47955SMatthew G. Knepley     const PetscReal *qweights;
25983c47955SMatthew G. Knepley     PetscInt         Nq, Nc, i;
26083c47955SMatthew G. Knepley 
26183c47955SMatthew G. Knepley     ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr);
26283c47955SMatthew G. Knepley     ierr = PetscFEGetDefaultTabulation((PetscFE) obj, &Bfine, NULL, NULL);CHKERRQ(ierr);
26383c47955SMatthew G. Knepley     ierr = PetscFEGetQuadrature((PetscFE) obj, &quad);CHKERRQ(ierr);
26483c47955SMatthew G. Knepley     ierr = PetscQuadratureGetData(quad, NULL, &Nc, &Nq, NULL, &qweights);CHKERRQ(ierr);
26583c47955SMatthew G. Knepley     /* For each fine grid cell */
26683c47955SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
26783c47955SMatthew G. Knepley       PetscInt           Np, c, j;
26883c47955SMatthew G. Knepley       PetscInt          *findices,   *cindices;
26983c47955SMatthew G. Knepley       PetscInt           numFIndices, numCIndices;
27083c47955SMatthew G. Knepley 
27183c47955SMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr);
27283c47955SMatthew G. Knepley       ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
27383c47955SMatthew G. Knepley       ierr = DMSwarmSortGetNumberOfPointsPerCell(dmc, cell, &Np);CHKERRQ(ierr);
274e8291c10SMatthew G. Knepley       if (Np != Nq) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Not all closure points located %D != %D", Np, Nq);
27583c47955SMatthew G. Knepley       ierr = DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices);CHKERRQ(ierr);
27683c47955SMatthew G. Knepley       /* Get elemMat entries by multiplying by weight */
27783c47955SMatthew G. Knepley       for (i = 0; i < numFIndices; ++i) {
27883c47955SMatthew G. Knepley         ierr = PetscMemzero(elemMat, numCIndices * sizeof(PetscScalar));CHKERRQ(ierr);
27983c47955SMatthew G. Knepley         for (j = 0; j < numCIndices; ++j) {
28083c47955SMatthew G. Knepley           for (c = 0; c < Nc; ++c) elemMat[j] += Bfine[(j*numFIndices + i)*Nc + c]*qweights[j*Nc + c]*detJ;
28183c47955SMatthew G. Knepley         }
28283c47955SMatthew G. Knepley         /* Update interpolator */
28383c47955SMatthew G. Knepley         if (0) {ierr = DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat);CHKERRQ(ierr);}
28483c47955SMatthew G. Knepley         ierr = MatSetValues(mass, 1, &findices[i], numCIndices, cindices, elemMat, ADD_VALUES);CHKERRQ(ierr);
28583c47955SMatthew G. Knepley       }
28683c47955SMatthew G. Knepley       ierr = PetscFree(cindices);CHKERRQ(ierr);
28783c47955SMatthew G. Knepley       ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
28883c47955SMatthew G. Knepley     }
28983c47955SMatthew G. Knepley   }
29083c47955SMatthew G. Knepley   ierr = DMSwarmSortRestoreAccess(dmc);CHKERRQ(ierr);
29183c47955SMatthew G. Knepley   ierr = PetscFree3(v0,J,invJ);CHKERRQ(ierr);
29283c47955SMatthew G. Knepley   ierr = PetscFree(elemMat);CHKERRQ(ierr);
29383c47955SMatthew G. Knepley   ierr = MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
29483c47955SMatthew G. Knepley   ierr = MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
29583c47955SMatthew G. Knepley   PetscFunctionReturn(0);
29683c47955SMatthew G. Knepley }
29783c47955SMatthew G. Knepley 
29883c47955SMatthew G. Knepley static PetscErrorCode DMCreateMassMatrix_Swarm(DM dmCoarse, DM dmFine, Mat *mass)
29983c47955SMatthew G. Knepley {
300895a1698SMatthew G. Knepley   PetscSection   gsf;
30183c47955SMatthew G. Knepley   PetscInt       m, n;
30283c47955SMatthew G. Knepley   void          *ctx;
30383c47955SMatthew G. Knepley   PetscErrorCode ierr;
30483c47955SMatthew G. Knepley 
30583c47955SMatthew G. Knepley   PetscFunctionBegin;
30683c47955SMatthew G. Knepley   ierr = DMGetDefaultGlobalSection(dmFine, &gsf);CHKERRQ(ierr);
30783c47955SMatthew G. Knepley   ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr);
308895a1698SMatthew G. Knepley   ierr = DMSwarmGetLocalSize(dmCoarse, &n);CHKERRQ(ierr);
30983c47955SMatthew G. Knepley 
31083c47955SMatthew G. Knepley   ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr);
31183c47955SMatthew G. Knepley   ierr = MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
31283c47955SMatthew G. Knepley   ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr);
31383c47955SMatthew G. Knepley   ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr);
31483c47955SMatthew G. Knepley 
31583c47955SMatthew G. Knepley   ierr = DMSwarmComputeMassMatrix_Private(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);
31683c47955SMatthew G. Knepley   ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr);
31783c47955SMatthew G. Knepley   PetscFunctionReturn(0);
31883c47955SMatthew G. Knepley }
31983c47955SMatthew G. Knepley 
320fb1bcc12SMatthew G. Knepley /*@C
321d3a51819SDave May    DMSwarmCreateGlobalVectorFromField - Creates a Vec object sharing the array associated with a given field
322d3a51819SDave May 
323d3a51819SDave May    Collective on DM
324d3a51819SDave May 
325d3a51819SDave May    Input parameters:
32662741f57SDave May +  dm - a DMSwarm
32762741f57SDave May -  fieldname - the textual name given to a registered field
328d3a51819SDave May 
3298b8a3813SDave May    Output parameter:
330d3a51819SDave May .  vec - the vector
331d3a51819SDave May 
332d3a51819SDave May    Level: beginner
333d3a51819SDave May 
3348b8a3813SDave May    Notes:
3358b8a3813SDave May    The vector must be returned using a matching call to DMSwarmDestroyGlobalVectorFromField().
3368b8a3813SDave May 
3378b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmDestroyGlobalVectorFromField()
338d3a51819SDave May @*/
339b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmCreateGlobalVectorFromField(DM dm,const char fieldname[],Vec *vec)
340b5bcf523SDave May {
341fb1bcc12SMatthew G. Knepley   MPI_Comm       comm = PetscObjectComm((PetscObject) dm);
342b5bcf523SDave May   PetscErrorCode ierr;
343b5bcf523SDave May 
344fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
345fb1bcc12SMatthew G. Knepley   ierr = DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec);CHKERRQ(ierr);
346b5bcf523SDave May   PetscFunctionReturn(0);
347b5bcf523SDave May }
348b5bcf523SDave May 
349d3a51819SDave May /*@C
350d3a51819SDave May    DMSwarmDestroyGlobalVectorFromField - Destroys the Vec object which share the array associated with a given field
351d3a51819SDave May 
352d3a51819SDave May    Collective on DM
353d3a51819SDave May 
354d3a51819SDave May    Input parameters:
35562741f57SDave May +  dm - a DMSwarm
35662741f57SDave May -  fieldname - the textual name given to a registered field
357d3a51819SDave May 
3588b8a3813SDave May    Output parameter:
359d3a51819SDave May .  vec - the vector
360d3a51819SDave May 
361d3a51819SDave May    Level: beginner
362d3a51819SDave May 
3638b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmCreateGlobalVectorFromField()
364d3a51819SDave May @*/
365b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmDestroyGlobalVectorFromField(DM dm,const char fieldname[],Vec *vec)
366b5bcf523SDave May {
367b5bcf523SDave May   PetscErrorCode ierr;
368cc651181SDave May 
369fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
370fb1bcc12SMatthew G. Knepley   ierr = DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec);CHKERRQ(ierr);
371b5bcf523SDave May   PetscFunctionReturn(0);
372b5bcf523SDave May }
373b5bcf523SDave May 
374fb1bcc12SMatthew G. Knepley /*@C
375fb1bcc12SMatthew G. Knepley    DMSwarmCreateLocalVectorFromField - Creates a Vec object sharing the array associated with a given field
376fb1bcc12SMatthew G. Knepley 
377fb1bcc12SMatthew G. Knepley    Collective on DM
378fb1bcc12SMatthew G. Knepley 
379fb1bcc12SMatthew G. Knepley    Input parameters:
38062741f57SDave May +  dm - a DMSwarm
38162741f57SDave May -  fieldname - the textual name given to a registered field
382fb1bcc12SMatthew G. Knepley 
3838b8a3813SDave May    Output parameter:
384fb1bcc12SMatthew G. Knepley .  vec - the vector
385fb1bcc12SMatthew G. Knepley 
386fb1bcc12SMatthew G. Knepley    Level: beginner
387fb1bcc12SMatthew G. Knepley 
3888b8a3813SDave May    Notes:
3898b8a3813SDave May    The vector must be returned using a matching call to DMSwarmDestroyLocalVectorFromField().
3908b8a3813SDave May 
3918b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmDestroyLocalVectorFromField()
392fb1bcc12SMatthew G. Knepley @*/
393fb1bcc12SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMSwarmCreateLocalVectorFromField(DM dm,const char fieldname[],Vec *vec)
394bbe8250bSMatthew G. Knepley {
395fb1bcc12SMatthew G. Knepley   MPI_Comm       comm = PETSC_COMM_SELF;
396bbe8250bSMatthew G. Knepley   PetscErrorCode ierr;
397bbe8250bSMatthew G. Knepley 
398fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
399fb1bcc12SMatthew G. Knepley   ierr = DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec);CHKERRQ(ierr);
400fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
401bbe8250bSMatthew G. Knepley }
402fb1bcc12SMatthew G. Knepley 
403fb1bcc12SMatthew G. Knepley /*@C
404fb1bcc12SMatthew G. Knepley    DMSwarmDestroyLocalVectorFromField - Destroys the Vec object which share the array associated with a given field
405fb1bcc12SMatthew G. Knepley 
406fb1bcc12SMatthew G. Knepley    Collective on DM
407fb1bcc12SMatthew G. Knepley 
408fb1bcc12SMatthew G. Knepley    Input parameters:
40962741f57SDave May +  dm - a DMSwarm
41062741f57SDave May -  fieldname - the textual name given to a registered field
411fb1bcc12SMatthew G. Knepley 
4128b8a3813SDave May    Output parameter:
413fb1bcc12SMatthew G. Knepley .  vec - the vector
414fb1bcc12SMatthew G. Knepley 
415fb1bcc12SMatthew G. Knepley    Level: beginner
416fb1bcc12SMatthew G. Knepley 
4178b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmCreateLocalVectorFromField()
418fb1bcc12SMatthew G. Knepley @*/
419fb1bcc12SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMSwarmDestroyLocalVectorFromField(DM dm,const char fieldname[],Vec *vec)
420fb1bcc12SMatthew G. Knepley {
421fb1bcc12SMatthew G. Knepley   PetscErrorCode ierr;
422fb1bcc12SMatthew G. Knepley 
423fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
424fb1bcc12SMatthew G. Knepley   ierr = DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec);CHKERRQ(ierr);
425bbe8250bSMatthew G. Knepley   PetscFunctionReturn(0);
426bbe8250bSMatthew G. Knepley }
427bbe8250bSMatthew G. Knepley 
428b5bcf523SDave May /*
429b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmCreateGlobalVectorFromFields(DM dm,const PetscInt nf,const char *fieldnames[],Vec *vec)
430b5bcf523SDave May {
431b5bcf523SDave May   PetscFunctionReturn(0);
432b5bcf523SDave May }
433b5bcf523SDave May 
434b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmRestoreGlobalVectorFromFields(DM dm,Vec *vec)
435b5bcf523SDave May {
436b5bcf523SDave May   PetscFunctionReturn(0);
437b5bcf523SDave May }
438b5bcf523SDave May */
439b5bcf523SDave May 
440d3a51819SDave May /*@C
441d3a51819SDave May    DMSwarmInitializeFieldRegister - Initiates the registration of fields to a DMSwarm
442d3a51819SDave May 
443d3a51819SDave May    Collective on DM
444d3a51819SDave May 
445d3a51819SDave May    Input parameter:
446d3a51819SDave May .  dm - a DMSwarm
447d3a51819SDave May 
448d3a51819SDave May    Level: beginner
449d3a51819SDave May 
450d3a51819SDave May    Notes:
4518b8a3813SDave May    After all fields have been registered, you must call DMSwarmFinalizeFieldRegister().
452d3a51819SDave May 
453d3a51819SDave May .seealso: DMSwarmFinalizeFieldRegister(), DMSwarmRegisterPetscDatatypeField(),
454d3a51819SDave May  DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
455d3a51819SDave May @*/
4565f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmInitializeFieldRegister(DM dm)
4575f50eb2eSDave May {
4585f50eb2eSDave May   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
4593454631fSDave May   PetscErrorCode ierr;
4603454631fSDave May 
461521f74f9SMatthew G. Knepley   PetscFunctionBegin;
462cc651181SDave May   if (!swarm->field_registration_initialized) {
4635f50eb2eSDave May     swarm->field_registration_initialized = PETSC_TRUE;
464f0cdbbbaSDave May     ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_pid,1,PETSC_LONG);CHKERRQ(ierr); /* unique identifer */
465f0cdbbbaSDave May     ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_rank,1,PETSC_INT);CHKERRQ(ierr); /* used for communication */
466cc651181SDave May   }
4675f50eb2eSDave May   PetscFunctionReturn(0);
4685f50eb2eSDave May }
4695f50eb2eSDave May 
470d3a51819SDave May /*@C
471d3a51819SDave May    DMSwarmFinalizeFieldRegister - Finalizes the registration of fields to a DMSwarm
472d3a51819SDave May 
473d3a51819SDave May    Collective on DM
474d3a51819SDave May 
475d3a51819SDave May    Input parameter:
476d3a51819SDave May .  dm - a DMSwarm
477d3a51819SDave May 
478d3a51819SDave May    Level: beginner
479d3a51819SDave May 
480d3a51819SDave May    Notes:
48162741f57SDave May    After DMSwarmFinalizeFieldRegister() has been called, no new fields can be defined on the DMSwarm.
482d3a51819SDave May 
483d3a51819SDave May .seealso: DMSwarmInitializeFieldRegister(), DMSwarmRegisterPetscDatatypeField(),
484d3a51819SDave May  DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
485d3a51819SDave May @*/
4865f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmFinalizeFieldRegister(DM dm)
4875f50eb2eSDave May {
4885f50eb2eSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
4896845f8f5SDave May   PetscErrorCode ierr;
4906845f8f5SDave May 
491521f74f9SMatthew G. Knepley   PetscFunctionBegin;
492f0cdbbbaSDave May   if (!swarm->field_registration_finalized) {
49377048351SPatrick Sanan     ierr = DMSwarmDataBucketFinalize(swarm->db);CHKERRQ(ierr);
494f0cdbbbaSDave May   }
495f0cdbbbaSDave May   swarm->field_registration_finalized = PETSC_TRUE;
4965f50eb2eSDave May   PetscFunctionReturn(0);
4975f50eb2eSDave May }
4985f50eb2eSDave May 
499d3a51819SDave May /*@C
500d3a51819SDave May    DMSwarmSetLocalSizes - Sets the length of all registered fields on the DMSwarm
501d3a51819SDave May 
502d3a51819SDave May    Not collective
503d3a51819SDave May 
504d3a51819SDave May    Input parameters:
50562741f57SDave May +  dm - a DMSwarm
506d3a51819SDave May .  nlocal - the length of each registered field
50762741f57SDave May -  buffer - the length of the buffer used to efficient dynamic re-sizing
508d3a51819SDave May 
509d3a51819SDave May    Level: beginner
510d3a51819SDave May 
511d3a51819SDave May .seealso: DMSwarmGetLocalSize()
512d3a51819SDave May @*/
5135f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmSetLocalSizes(DM dm,PetscInt nlocal,PetscInt buffer)
5145f50eb2eSDave May {
5155f50eb2eSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
5166845f8f5SDave May   PetscErrorCode ierr;
5175f50eb2eSDave May 
518521f74f9SMatthew G. Knepley   PetscFunctionBegin;
519f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_SetSizes,0,0,0,0);CHKERRQ(ierr);
52077048351SPatrick Sanan   ierr = DMSwarmDataBucketSetSizes(swarm->db,nlocal,buffer);CHKERRQ(ierr);
521f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_SetSizes,0,0,0,0);CHKERRQ(ierr);
5225f50eb2eSDave May   PetscFunctionReturn(0);
5235f50eb2eSDave May }
5245f50eb2eSDave May 
525d3a51819SDave May /*@C
526d3a51819SDave May    DMSwarmSetCellDM - Attachs a DM to a DMSwarm
527d3a51819SDave May 
528d3a51819SDave May    Collective on DM
529d3a51819SDave May 
530d3a51819SDave May    Input parameters:
53162741f57SDave May +  dm - a DMSwarm
53262741f57SDave May -  dmcell - the DM to attach to the DMSwarm
533d3a51819SDave May 
534d3a51819SDave May    Level: beginner
535d3a51819SDave May 
536d3a51819SDave May    Notes:
537d3a51819SDave May    The attached DM (dmcell) will be queried for point location and
5388b8a3813SDave May    neighbor MPI-rank information if DMSwarmMigrate() is called.
539d3a51819SDave May 
5408b8a3813SDave May .seealso: DMSwarmSetType(), DMSwarmGetCellDM(), DMSwarmMigrate()
541d3a51819SDave May @*/
542b16650c8SDave May PETSC_EXTERN PetscErrorCode DMSwarmSetCellDM(DM dm,DM dmcell)
543b16650c8SDave May {
544b16650c8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
545521f74f9SMatthew G. Knepley 
546521f74f9SMatthew G. Knepley   PetscFunctionBegin;
547b16650c8SDave May   swarm->dmcell = dmcell;
548b16650c8SDave May   PetscFunctionReturn(0);
549b16650c8SDave May }
550b16650c8SDave May 
551d3a51819SDave May /*@C
552d3a51819SDave May    DMSwarmGetCellDM - Fetches the attached cell DM
553d3a51819SDave May 
554d3a51819SDave May    Collective on DM
555d3a51819SDave May 
556d3a51819SDave May    Input parameter:
557d3a51819SDave May .  dm - a DMSwarm
558d3a51819SDave May 
559d3a51819SDave May    Output parameter:
560d3a51819SDave May .  dmcell - the DM which was attached to the DMSwarm
561d3a51819SDave May 
562d3a51819SDave May    Level: beginner
563d3a51819SDave May 
564d3a51819SDave May .seealso: DMSwarmSetCellDM()
565d3a51819SDave May @*/
566fe39f135SDave May PETSC_EXTERN PetscErrorCode DMSwarmGetCellDM(DM dm,DM *dmcell)
567fe39f135SDave May {
568fe39f135SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
569521f74f9SMatthew G. Knepley 
570521f74f9SMatthew G. Knepley   PetscFunctionBegin;
571fe39f135SDave May   *dmcell = swarm->dmcell;
572fe39f135SDave May   PetscFunctionReturn(0);
573fe39f135SDave May }
574fe39f135SDave May 
575d3a51819SDave May /*@C
576d3a51819SDave May    DMSwarmGetLocalSize - Retrives the local length of fields registered
577d3a51819SDave May 
578d3a51819SDave May    Not collective
579d3a51819SDave May 
580d3a51819SDave May    Input parameter:
581d3a51819SDave May .  dm - a DMSwarm
582d3a51819SDave May 
583d3a51819SDave May    Output parameter:
584d3a51819SDave May .  nlocal - the length of each registered field
585d3a51819SDave May 
586d3a51819SDave May    Level: beginner
587d3a51819SDave May 
5888b8a3813SDave May .seealso: DMSwarmGetSize(), DMSwarmSetLocalSizes()
589d3a51819SDave May @*/
590dcf43ee8SDave May PETSC_EXTERN PetscErrorCode DMSwarmGetLocalSize(DM dm,PetscInt *nlocal)
591dcf43ee8SDave May {
592dcf43ee8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
593dcf43ee8SDave May   PetscErrorCode ierr;
594dcf43ee8SDave May 
595521f74f9SMatthew G. Knepley   PetscFunctionBegin;
59677048351SPatrick Sanan   if (nlocal) {ierr = DMSwarmDataBucketGetSizes(swarm->db,nlocal,NULL,NULL);CHKERRQ(ierr);}
597dcf43ee8SDave May   PetscFunctionReturn(0);
598dcf43ee8SDave May }
599dcf43ee8SDave May 
600d3a51819SDave May /*@C
601d3a51819SDave May    DMSwarmGetSize - Retrives the total length of fields registered
602d3a51819SDave May 
603d3a51819SDave May    Collective on DM
604d3a51819SDave May 
605d3a51819SDave May    Input parameter:
606d3a51819SDave May .  dm - a DMSwarm
607d3a51819SDave May 
608d3a51819SDave May    Output parameter:
609d3a51819SDave May .  n - the total length of each registered field
610d3a51819SDave May 
611d3a51819SDave May    Level: beginner
612d3a51819SDave May 
613d3a51819SDave May    Note:
614d3a51819SDave May    This calls MPI_Allreduce upon each call (inefficient but safe)
615d3a51819SDave May 
6168b8a3813SDave May .seealso: DMSwarmGetLocalSize(), DMSwarmSetLocalSizes()
617d3a51819SDave May @*/
618dcf43ee8SDave May PETSC_EXTERN PetscErrorCode DMSwarmGetSize(DM dm,PetscInt *n)
619dcf43ee8SDave May {
620dcf43ee8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
621dcf43ee8SDave May   PetscErrorCode ierr;
622dcf43ee8SDave May   PetscInt       nlocal,ng;
623dcf43ee8SDave May 
624521f74f9SMatthew G. Knepley   PetscFunctionBegin;
62577048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
626dcf43ee8SDave May   ierr = MPI_Allreduce(&nlocal,&ng,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
627dcf43ee8SDave May   if (n) { *n = ng; }
628dcf43ee8SDave May   PetscFunctionReturn(0);
629dcf43ee8SDave May }
630dcf43ee8SDave May 
631d3a51819SDave May /*@C
6328b8a3813SDave May    DMSwarmRegisterPetscDatatypeField - Register a field to a DMSwarm with a native PETSc data type
633d3a51819SDave May 
634d3a51819SDave May    Collective on DM
635d3a51819SDave May 
636d3a51819SDave May    Input parameters:
63762741f57SDave May +  dm - a DMSwarm
638d3a51819SDave May .  fieldname - the textual name to identify this field
639d3a51819SDave May .  blocksize - the number of each data type
64062741f57SDave May -  type - a valid PETSc data type (PETSC_CHAR, PETSC_SHORT, PETSC_INT, PETSC_FLOAT, PETSC_REAL, PETSC_LONG)
641d3a51819SDave May 
642d3a51819SDave May    Level: beginner
643d3a51819SDave May 
644d3a51819SDave May    Notes:
6458b8a3813SDave May    The textual name for each registered field must be unique.
646d3a51819SDave May 
647d3a51819SDave May .seealso: DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
648d3a51819SDave May @*/
6495f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmRegisterPetscDatatypeField(DM dm,const char fieldname[],PetscInt blocksize,PetscDataType type)
650b62e03f8SDave May {
6512eac95f8SDave May   PetscErrorCode ierr;
652b62e03f8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
653b62e03f8SDave May   size_t         size;
654b62e03f8SDave May 
655521f74f9SMatthew G. Knepley   PetscFunctionBegin;
6565f50eb2eSDave May   if (!swarm->field_registration_initialized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmInitializeFieldRegister() first");
6575f50eb2eSDave May   if (swarm->field_registration_finalized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Cannot register additional fields after calling DMSwarmFinalizeFieldRegister() first");
6585f50eb2eSDave May 
6595f50eb2eSDave May   if (type == PETSC_OBJECT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
6605f50eb2eSDave May   if (type == PETSC_FUNCTION) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
6615f50eb2eSDave May   if (type == PETSC_STRING) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
6625f50eb2eSDave May   if (type == PETSC_STRUCT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
6635f50eb2eSDave May   if (type == PETSC_DATATYPE_UNKNOWN) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
664b62e03f8SDave May 
6652ddcf43eSMatthew G. Knepley   ierr = PetscDataTypeGetSize(type, &size);CHKERRQ(ierr);
666b62e03f8SDave May   /* Load a specific data type into data bucket, specifying textual name and its size in bytes */
66777048351SPatrick Sanan   ierr = DMSwarmDataBucketRegisterField(swarm->db,"DMSwarmRegisterPetscDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
66852c3ed93SDave May   {
66977048351SPatrick Sanan     DMSwarmDataField gfield;
67052c3ed93SDave May 
67177048351SPatrick Sanan     ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
67277048351SPatrick Sanan     ierr = DMSwarmDataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
67352c3ed93SDave May   }
674b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = type;
675b62e03f8SDave May   PetscFunctionReturn(0);
676b62e03f8SDave May }
677b62e03f8SDave May 
678d3a51819SDave May /*@C
679d3a51819SDave May    DMSwarmRegisterUserStructField - Register a user defined struct to a DMSwarm
680d3a51819SDave May 
681d3a51819SDave May    Collective on DM
682d3a51819SDave May 
683d3a51819SDave May    Input parameters:
68462741f57SDave May +  dm - a DMSwarm
685d3a51819SDave May .  fieldname - the textual name to identify this field
68662741f57SDave May -  size - the size in bytes of the user struct of each data type
687d3a51819SDave May 
688d3a51819SDave May    Level: beginner
689d3a51819SDave May 
690d3a51819SDave May    Notes:
6918b8a3813SDave May    The textual name for each registered field must be unique.
692d3a51819SDave May 
693d3a51819SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserDatatypeField()
694d3a51819SDave May @*/
6955f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmRegisterUserStructField(DM dm,const char fieldname[],size_t size)
696b62e03f8SDave May {
6972eac95f8SDave May   PetscErrorCode ierr;
698b62e03f8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
699b62e03f8SDave May 
700521f74f9SMatthew G. Knepley   PetscFunctionBegin;
70177048351SPatrick Sanan   ierr = DMSwarmDataBucketRegisterField(swarm->db,"DMSwarmRegisterUserStructField",fieldname,size,NULL);CHKERRQ(ierr);
702b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_STRUCT ;
703b62e03f8SDave May   PetscFunctionReturn(0);
704b62e03f8SDave May }
705b62e03f8SDave May 
706d3a51819SDave May /*@C
707d3a51819SDave May    DMSwarmRegisterUserDatatypeField - Register a user defined data type to a DMSwarm
708d3a51819SDave May 
709d3a51819SDave May    Collective on DM
710d3a51819SDave May 
711d3a51819SDave May    Input parameters:
71262741f57SDave May +  dm - a DMSwarm
713d3a51819SDave May .  fieldname - the textual name to identify this field
714d3a51819SDave May .  size - the size in bytes of the user data type
71562741f57SDave May -  blocksize - the number of each data type
716d3a51819SDave May 
717d3a51819SDave May    Level: beginner
718d3a51819SDave May 
719d3a51819SDave May    Notes:
7208b8a3813SDave May    The textual name for each registered field must be unique.
721d3a51819SDave May 
722d3a51819SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
723d3a51819SDave May @*/
724320740a0SDave May PETSC_EXTERN PetscErrorCode DMSwarmRegisterUserDatatypeField(DM dm,const char fieldname[],size_t size,PetscInt blocksize)
725b62e03f8SDave May {
726b62e03f8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
7276845f8f5SDave May   PetscErrorCode ierr;
728b62e03f8SDave May 
729521f74f9SMatthew G. Knepley   PetscFunctionBegin;
73077048351SPatrick Sanan   ierr = DMSwarmDataBucketRegisterField(swarm->db,"DMSwarmRegisterUserDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
731320740a0SDave May   {
73277048351SPatrick Sanan     DMSwarmDataField gfield;
733320740a0SDave May 
73477048351SPatrick Sanan     ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
73577048351SPatrick Sanan     ierr = DMSwarmDataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
736320740a0SDave May   }
737b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_DATATYPE_UNKNOWN;
738b62e03f8SDave May   PetscFunctionReturn(0);
739b62e03f8SDave May }
740b62e03f8SDave May 
741d3a51819SDave May /*@C
742d3a51819SDave May    DMSwarmGetField - Get access to the underlying array storing all entries associated with a registered field
743d3a51819SDave May 
744d3a51819SDave May    Not collective
745d3a51819SDave May 
746d3a51819SDave May    Input parameters:
74762741f57SDave May +  dm - a DMSwarm
74862741f57SDave May -  fieldname - the textual name to identify this field
749d3a51819SDave May 
750d3a51819SDave May    Output parameters:
75162741f57SDave May +  blocksize - the number of each data type
752d3a51819SDave May .  type - the data type
75362741f57SDave May -  data - pointer to raw array
754d3a51819SDave May 
755d3a51819SDave May    Level: beginner
756d3a51819SDave May 
757d3a51819SDave May    Notes:
7588b8a3813SDave May    The array must be returned using a matching call to DMSwarmRestoreField().
759d3a51819SDave May 
760d3a51819SDave May .seealso: DMSwarmRestoreField()
761d3a51819SDave May @*/
7625f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmGetField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
763b62e03f8SDave May {
764b62e03f8SDave May   DM_Swarm         *swarm = (DM_Swarm*)dm->data;
76577048351SPatrick Sanan   DMSwarmDataField gfield;
7662eac95f8SDave May   PetscErrorCode ierr;
767b62e03f8SDave May 
768521f74f9SMatthew G. Knepley   PetscFunctionBegin;
7693454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
77077048351SPatrick Sanan   ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
77177048351SPatrick Sanan   ierr = DMSwarmDataFieldGetAccess(gfield);CHKERRQ(ierr);
77277048351SPatrick Sanan   ierr = DMSwarmDataFieldGetEntries(gfield,data);CHKERRQ(ierr);
7731b1ea282SDave May   if (blocksize) {*blocksize = gfield->bs; }
774b5bcf523SDave May   if (type) { *type = gfield->petsc_type; }
775b62e03f8SDave May   PetscFunctionReturn(0);
776b62e03f8SDave May }
777b62e03f8SDave May 
778d3a51819SDave May /*@C
779d3a51819SDave May    DMSwarmRestoreField - Restore access to the underlying array storing all entries associated with a registered field
780d3a51819SDave May 
781d3a51819SDave May    Not collective
782d3a51819SDave May 
783d3a51819SDave May    Input parameters:
78462741f57SDave May +  dm - a DMSwarm
78562741f57SDave May -  fieldname - the textual name to identify this field
786d3a51819SDave May 
787d3a51819SDave May    Output parameters:
78862741f57SDave May +  blocksize - the number of each data type
789d3a51819SDave May .  type - the data type
79062741f57SDave May -  data - pointer to raw array
791d3a51819SDave May 
792d3a51819SDave May    Level: beginner
793d3a51819SDave May 
794d3a51819SDave May    Notes:
7958b8a3813SDave May    The user must call DMSwarmGetField() prior to calling DMSwarmRestoreField().
796d3a51819SDave May 
797d3a51819SDave May .seealso: DMSwarmGetField()
798d3a51819SDave May @*/
7995f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmRestoreField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
800b62e03f8SDave May {
801b62e03f8SDave May   DM_Swarm         *swarm = (DM_Swarm*)dm->data;
80277048351SPatrick Sanan   DMSwarmDataField gfield;
8032eac95f8SDave May   PetscErrorCode ierr;
804b62e03f8SDave May 
805521f74f9SMatthew G. Knepley   PetscFunctionBegin;
80677048351SPatrick Sanan   ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
80777048351SPatrick Sanan   ierr = DMSwarmDataFieldRestoreAccess(gfield);CHKERRQ(ierr);
808b62e03f8SDave May   if (data) *data = NULL;
809b62e03f8SDave May   PetscFunctionReturn(0);
810b62e03f8SDave May }
811b62e03f8SDave May 
812d3a51819SDave May /*@C
813d3a51819SDave May    DMSwarmAddPoint - Add space for one new point in the DMSwarm
814d3a51819SDave May 
815d3a51819SDave May    Not collective
816d3a51819SDave May 
817d3a51819SDave May    Input parameter:
818d3a51819SDave May .  dm - a DMSwarm
819d3a51819SDave May 
820d3a51819SDave May    Level: beginner
821d3a51819SDave May 
822d3a51819SDave May    Notes:
8238b8a3813SDave May    The new point will have all fields initialized to zero.
824d3a51819SDave May 
825d3a51819SDave May .seealso: DMSwarmAddNPoints()
826d3a51819SDave May @*/
827cb1d1399SDave May PETSC_EXTERN PetscErrorCode DMSwarmAddPoint(DM dm)
828cb1d1399SDave May {
829cb1d1399SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
830cb1d1399SDave May   PetscErrorCode ierr;
831cb1d1399SDave May 
832521f74f9SMatthew G. Knepley   PetscFunctionBegin;
8333454631fSDave May   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
834f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
83577048351SPatrick Sanan   ierr = DMSwarmDataBucketAddPoint(swarm->db);CHKERRQ(ierr);
836f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
837cb1d1399SDave May   PetscFunctionReturn(0);
838cb1d1399SDave May }
839cb1d1399SDave May 
840d3a51819SDave May /*@C
841d3a51819SDave May    DMSwarmAddNPoints - Add space for a number of new points in the DMSwarm
842d3a51819SDave May 
843d3a51819SDave May    Not collective
844d3a51819SDave May 
845d3a51819SDave May    Input parameters:
84662741f57SDave May +  dm - a DMSwarm
84762741f57SDave May -  npoints - the number of new points to add
848d3a51819SDave May 
849d3a51819SDave May    Level: beginner
850d3a51819SDave May 
851d3a51819SDave May    Notes:
8528b8a3813SDave May    The new point will have all fields initialized to zero.
853d3a51819SDave May 
854d3a51819SDave May .seealso: DMSwarmAddPoint()
855d3a51819SDave May @*/
856cb1d1399SDave May PETSC_EXTERN PetscErrorCode DMSwarmAddNPoints(DM dm,PetscInt npoints)
857cb1d1399SDave May {
858cb1d1399SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
859cb1d1399SDave May   PetscErrorCode ierr;
860cb1d1399SDave May   PetscInt       nlocal;
861cb1d1399SDave May 
862521f74f9SMatthew G. Knepley   PetscFunctionBegin;
863f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
86477048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
865cb1d1399SDave May   nlocal = nlocal + npoints;
86677048351SPatrick Sanan   ierr = DMSwarmDataBucketSetSizes(swarm->db,nlocal,DMSWARM_DATA_BUCKET_BUFFER_DEFAULT);CHKERRQ(ierr);
867f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
868cb1d1399SDave May   PetscFunctionReturn(0);
869cb1d1399SDave May }
870cb1d1399SDave May 
871d3a51819SDave May /*@C
872d3a51819SDave May    DMSwarmRemovePoint - Remove the last point from the DMSwarm
873d3a51819SDave May 
874d3a51819SDave May    Not collective
875d3a51819SDave May 
876d3a51819SDave May    Input parameter:
877d3a51819SDave May .  dm - a DMSwarm
878d3a51819SDave May 
879d3a51819SDave May    Level: beginner
880d3a51819SDave May 
881d3a51819SDave May .seealso: DMSwarmRemovePointAtIndex()
882d3a51819SDave May @*/
883cb1d1399SDave May PETSC_EXTERN PetscErrorCode DMSwarmRemovePoint(DM dm)
884cb1d1399SDave May {
885cb1d1399SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
886cb1d1399SDave May   PetscErrorCode ierr;
887cb1d1399SDave May 
888521f74f9SMatthew G. Knepley   PetscFunctionBegin;
889f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
89077048351SPatrick Sanan   ierr = DMSwarmDataBucketRemovePoint(swarm->db);CHKERRQ(ierr);
891f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
892cb1d1399SDave May   PetscFunctionReturn(0);
893cb1d1399SDave May }
894cb1d1399SDave May 
895d3a51819SDave May /*@C
896d3a51819SDave May    DMSwarmRemovePointAtIndex - Removes a specific point from the DMSwarm
897d3a51819SDave May 
898d3a51819SDave May    Not collective
899d3a51819SDave May 
900d3a51819SDave May    Input parameters:
90162741f57SDave May +  dm - a DMSwarm
90262741f57SDave May -  idx - index of point to remove
903d3a51819SDave May 
904d3a51819SDave May    Level: beginner
905d3a51819SDave May 
906d3a51819SDave May .seealso: DMSwarmRemovePoint()
907d3a51819SDave May @*/
908cb1d1399SDave May PETSC_EXTERN PetscErrorCode DMSwarmRemovePointAtIndex(DM dm,PetscInt idx)
909cb1d1399SDave May {
910cb1d1399SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
911cb1d1399SDave May   PetscErrorCode ierr;
912cb1d1399SDave May 
913521f74f9SMatthew G. Knepley   PetscFunctionBegin;
914f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
91577048351SPatrick Sanan   ierr = DMSwarmDataBucketRemovePointAtIndex(swarm->db,idx);CHKERRQ(ierr);
916f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
917cb1d1399SDave May   PetscFunctionReturn(0);
918cb1d1399SDave May }
919b62e03f8SDave May 
920ba4fc9c6SDave May /*@C
921ba4fc9c6SDave May    DMSwarmCopyPoint - Copy point pj to point pi in the DMSwarm
922ba4fc9c6SDave May 
923ba4fc9c6SDave May    Not collective
924ba4fc9c6SDave May 
925ba4fc9c6SDave May    Input parameters:
926ba4fc9c6SDave May +  dm - a DMSwarm
927ba4fc9c6SDave May .  pi - the index of the point to copy
928ba4fc9c6SDave May -  pj - the point index where the copy should be located
929ba4fc9c6SDave May 
930ba4fc9c6SDave May  Level: beginner
931ba4fc9c6SDave May 
932ba4fc9c6SDave May .seealso: DMSwarmRemovePoint()
933ba4fc9c6SDave May @*/
934ba4fc9c6SDave May PETSC_EXTERN PetscErrorCode DMSwarmCopyPoint(DM dm,PetscInt pi,PetscInt pj)
935ba4fc9c6SDave May {
936ba4fc9c6SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
937ba4fc9c6SDave May   PetscErrorCode ierr;
938ba4fc9c6SDave May 
939ba4fc9c6SDave May   PetscFunctionBegin;
940ba4fc9c6SDave May   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
94177048351SPatrick Sanan   ierr = DMSwarmDataBucketCopyPoint(swarm->db,pi,swarm->db,pj);CHKERRQ(ierr);
942ba4fc9c6SDave May   PetscFunctionReturn(0);
943ba4fc9c6SDave May }
944ba4fc9c6SDave May 
945095059a4SDave May PetscErrorCode DMSwarmMigrate_Basic(DM dm,PetscBool remove_sent_points)
9463454631fSDave May {
947dcf43ee8SDave May   PetscErrorCode ierr;
948521f74f9SMatthew G. Knepley 
949521f74f9SMatthew G. Knepley   PetscFunctionBegin;
950dcf43ee8SDave May   ierr = DMSwarmMigrate_Push_Basic(dm,remove_sent_points);CHKERRQ(ierr);
9513454631fSDave May   PetscFunctionReturn(0);
9523454631fSDave May }
9533454631fSDave May 
954d3a51819SDave May /*@C
955d3a51819SDave May    DMSwarmMigrate - Relocates points defined in the DMSwarm to other MPI-ranks
956d3a51819SDave May 
957d3a51819SDave May    Collective on DM
958d3a51819SDave May 
959d3a51819SDave May    Input parameters:
96062741f57SDave May +  dm - the DMSwarm
96162741f57SDave May -  remove_sent_points - flag indicating if sent points should be removed from the current MPI-rank
962d3a51819SDave May 
963d3a51819SDave May    Notes:
9648b8a3813SDave May    The DM will be modified to accomodate received points.
9658b8a3813SDave May    If remove_sent_points = PETSC_TRUE, any points that were sent will be removed from the DM.
9668b8a3813SDave May    Different styles of migration are supported. See DMSwarmSetMigrateType().
967d3a51819SDave May 
968d3a51819SDave May    Level: advanced
969d3a51819SDave May 
970d3a51819SDave May .seealso: DMSwarmSetMigrateType()
971d3a51819SDave May @*/
972095059a4SDave May PETSC_EXTERN PetscErrorCode DMSwarmMigrate(DM dm,PetscBool remove_sent_points)
9733454631fSDave May {
974f0cdbbbaSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
9753454631fSDave May   PetscErrorCode ierr;
976f0cdbbbaSDave May 
977521f74f9SMatthew G. Knepley   PetscFunctionBegin;
978ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
979f0cdbbbaSDave May   switch (swarm->migrate_type) {
980f0cdbbbaSDave May     case DMSWARM_MIGRATE_BASIC:
981095059a4SDave May       ierr = DMSwarmMigrate_Basic(dm,remove_sent_points);CHKERRQ(ierr);
982f0cdbbbaSDave May       break;
983f0cdbbbaSDave May     case DMSWARM_MIGRATE_DMCELLNSCATTER:
984f0cdbbbaSDave May       ierr = DMSwarmMigrate_CellDMScatter(dm,remove_sent_points);CHKERRQ(ierr);
985f0cdbbbaSDave May       break;
986f0cdbbbaSDave May     case DMSWARM_MIGRATE_DMCELLEXACT:
987f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_DMCELLEXACT not implemented");
988521f74f9SMatthew G. Knepley       /*ierr = DMSwarmMigrate_CellDMExact(dm,remove_sent_points);CHKERRQ(ierr);*/
989f0cdbbbaSDave May       break;
990f0cdbbbaSDave May     case DMSWARM_MIGRATE_USER:
991f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_USER not implemented");
992521f74f9SMatthew G. Knepley       /*ierr = swarm->migrate(dm,remove_sent_points);CHKERRQ(ierr);*/
993f0cdbbbaSDave May       break;
994f0cdbbbaSDave May     default:
995f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE type unknown");
996f0cdbbbaSDave May       break;
997f0cdbbbaSDave May   }
998ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
9993454631fSDave May   PetscFunctionReturn(0);
10003454631fSDave May }
10013454631fSDave May 
1002f0cdbbbaSDave May PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm,PetscInt *globalsize);
1003f0cdbbbaSDave May 
1004d3a51819SDave May /*
1005d3a51819SDave May  DMSwarmCollectViewCreate
1006d3a51819SDave May 
1007d3a51819SDave May  * Applies a collection method and gathers point neighbour points into dm
1008d3a51819SDave May 
1009d3a51819SDave May  Notes:
10108b8a3813SDave May  Users should call DMSwarmCollectViewDestroy() after
1011d3a51819SDave May  they have finished computations associated with the collected points
1012d3a51819SDave May */
1013d3a51819SDave May 
1014d3a51819SDave May /*@C
1015d3a51819SDave May    DMSwarmCollectViewCreate - Applies a collection method and gathers points
1016d3a51819SDave May    in neighbour MPI-ranks into the DMSwarm
1017d3a51819SDave May 
1018d3a51819SDave May    Collective on DM
1019d3a51819SDave May 
1020d3a51819SDave May    Input parameter:
1021d3a51819SDave May .  dm - the DMSwarm
1022d3a51819SDave May 
1023d3a51819SDave May    Notes:
1024d3a51819SDave May    Users should call DMSwarmCollectViewDestroy() after
1025d3a51819SDave May    they have finished computations associated with the collected points
10268b8a3813SDave May    Different collect methods are supported. See DMSwarmSetCollectType().
1027d3a51819SDave May 
1028d3a51819SDave May    Level: advanced
1029d3a51819SDave May 
1030d3a51819SDave May .seealso: DMSwarmCollectViewDestroy(), DMSwarmSetCollectType()
1031d3a51819SDave May @*/
1032fe39f135SDave May PETSC_EXTERN PetscErrorCode DMSwarmCollectViewCreate(DM dm)
10332712d1f2SDave May {
10342712d1f2SDave May   PetscErrorCode ierr;
10352712d1f2SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
10362712d1f2SDave May   PetscInt ng;
10372712d1f2SDave May 
1038521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1039480eef7bSDave May   if (swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView currently active");
1040480eef7bSDave May   ierr = DMSwarmGetLocalSize(dm,&ng);CHKERRQ(ierr);
1041480eef7bSDave May   switch (swarm->collect_type) {
1042f0cdbbbaSDave May 
1043480eef7bSDave May     case DMSWARM_COLLECT_BASIC:
10442712d1f2SDave May       ierr = DMSwarmMigrate_GlobalToLocal_Basic(dm,&ng);CHKERRQ(ierr);
1045480eef7bSDave May       break;
1046480eef7bSDave May     case DMSWARM_COLLECT_DMDABOUNDINGBOX:
1047f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_DMDABOUNDINGBOX not implemented");
1048521f74f9SMatthew G. Knepley       /*ierr = DMSwarmCollect_DMDABoundingBox(dm,&ng);CHKERRQ(ierr);*/
1049480eef7bSDave May       break;
1050480eef7bSDave May     case DMSWARM_COLLECT_GENERAL:
1051f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_GENERAL not implemented");
1052521f74f9SMatthew G. Knepley       /*ierr = DMSwarmCollect_General(dm,..,,..,&ng);CHKERRQ(ierr);*/
1053480eef7bSDave May       break;
1054480eef7bSDave May     default:
1055f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT type unknown");
1056480eef7bSDave May       break;
1057480eef7bSDave May   }
1058480eef7bSDave May   swarm->collect_view_active = PETSC_TRUE;
1059480eef7bSDave May   swarm->collect_view_reset_nlocal = ng;
10602712d1f2SDave May   PetscFunctionReturn(0);
10612712d1f2SDave May }
10622712d1f2SDave May 
1063d3a51819SDave May /*@C
1064d3a51819SDave May    DMSwarmCollectViewDestroy - Resets the DMSwarm to the size prior to calling DMSwarmCollectViewCreate()
1065d3a51819SDave May 
1066d3a51819SDave May    Collective on DM
1067d3a51819SDave May 
1068d3a51819SDave May    Input parameters:
1069d3a51819SDave May .  dm - the DMSwarm
1070d3a51819SDave May 
1071d3a51819SDave May    Notes:
1072d3a51819SDave May    Users should call DMSwarmCollectViewCreate() before this function is called.
1073d3a51819SDave May 
1074d3a51819SDave May    Level: advanced
1075d3a51819SDave May 
1076d3a51819SDave May .seealso: DMSwarmCollectViewCreate(), DMSwarmSetCollectType()
1077d3a51819SDave May @*/
1078fe39f135SDave May PETSC_EXTERN PetscErrorCode DMSwarmCollectViewDestroy(DM dm)
10792712d1f2SDave May {
10802712d1f2SDave May   PetscErrorCode ierr;
10812712d1f2SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
10822712d1f2SDave May 
1083521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1084480eef7bSDave May   if (!swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView is currently not active");
1085480eef7bSDave May   ierr = DMSwarmSetLocalSizes(dm,swarm->collect_view_reset_nlocal,-1);CHKERRQ(ierr);
1086480eef7bSDave May   swarm->collect_view_active = PETSC_FALSE;
10872712d1f2SDave May   PetscFunctionReturn(0);
10882712d1f2SDave May }
10893454631fSDave May 
1090f0cdbbbaSDave May PetscErrorCode DMSwarmSetUpPIC(DM dm)
1091f0cdbbbaSDave May {
1092f0cdbbbaSDave May   PetscInt       dim;
1093f0cdbbbaSDave May   PetscErrorCode ierr;
1094f0cdbbbaSDave May 
1095521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1096f0cdbbbaSDave May   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
1097f0cdbbbaSDave May   if (dim < 1) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
1098f0cdbbbaSDave May   if (dim > 3) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
1099f0cdbbbaSDave May   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_coor,dim,PETSC_DOUBLE);CHKERRQ(ierr);
1100e2d107dbSDave May   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_cellid,1,PETSC_INT);CHKERRQ(ierr);
1101f0cdbbbaSDave May   PetscFunctionReturn(0);
1102f0cdbbbaSDave May }
1103f0cdbbbaSDave May 
1104d3a51819SDave May /*@C
1105d3a51819SDave May    DMSwarmSetType - Set particular flavor of DMSwarm
1106d3a51819SDave May 
1107d3a51819SDave May    Collective on DM
1108d3a51819SDave May 
1109d3a51819SDave May    Input parameters:
111062741f57SDave May +  dm - the DMSwarm
111162741f57SDave May -  stype - the DMSwarm type (e.g. DMSWARM_PIC)
1112d3a51819SDave May 
1113d3a51819SDave May    Level: advanced
1114d3a51819SDave May 
1115d3a51819SDave May .seealso: DMSwarmSetMigrateType(), DMSwarmSetCollectType()
1116d3a51819SDave May @*/
1117f0cdbbbaSDave May PETSC_EXTERN PetscErrorCode DMSwarmSetType(DM dm,DMSwarmType stype)
1118f0cdbbbaSDave May {
1119f0cdbbbaSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1120f0cdbbbaSDave May   PetscErrorCode ierr;
1121f0cdbbbaSDave May 
1122521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1123f0cdbbbaSDave May   swarm->swarm_type = stype;
1124f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
1125f0cdbbbaSDave May     ierr = DMSwarmSetUpPIC(dm);CHKERRQ(ierr);
1126f0cdbbbaSDave May   }
1127f0cdbbbaSDave May   PetscFunctionReturn(0);
1128f0cdbbbaSDave May }
1129f0cdbbbaSDave May 
11303454631fSDave May PetscErrorCode DMSetup_Swarm(DM dm)
11313454631fSDave May {
11323454631fSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
11333454631fSDave May   PetscErrorCode ierr;
11343454631fSDave May   PetscMPIInt    rank;
11353454631fSDave May   PetscInt       p,npoints,*rankval;
11363454631fSDave May 
1137521f74f9SMatthew G. Knepley   PetscFunctionBegin;
11383454631fSDave May   if (swarm->issetup) PetscFunctionReturn(0);
11393454631fSDave May 
11403454631fSDave May   swarm->issetup = PETSC_TRUE;
11413454631fSDave May 
1142f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
1143f0cdbbbaSDave May     /* check dmcell exists */
1144f0cdbbbaSDave May     if (!swarm->dmcell) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires you call DMSwarmSetCellDM");
1145f0cdbbbaSDave May 
1146f0cdbbbaSDave May     if (swarm->dmcell->ops->locatepointssubdomain) {
1147f0cdbbbaSDave May       /* check methods exists for exact ownership identificiation */
1148521f74f9SMatthew G. Knepley       ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->ops->LocatePointsSubdomain\n");CHKERRQ(ierr);
1149f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLEXACT;
1150f0cdbbbaSDave May     } else {
1151f0cdbbbaSDave May       /* check methods exist for point location AND rank neighbor identification */
1152f0cdbbbaSDave May       if (swarm->dmcell->ops->locatepoints) {
1153521f74f9SMatthew G. Knepley         ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->LocatePoints\n");CHKERRQ(ierr);
1154f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->locatepoints be defined");
1155f0cdbbbaSDave May 
1156f0cdbbbaSDave May       if (swarm->dmcell->ops->getneighbors) {
1157521f74f9SMatthew G. Knepley         ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->GetNeigbors\n");CHKERRQ(ierr);
1158f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->getneighbors be defined");
1159f0cdbbbaSDave May 
1160f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLNSCATTER;
1161f0cdbbbaSDave May     }
1162f0cdbbbaSDave May   }
1163f0cdbbbaSDave May 
1164f0cdbbbaSDave May   ierr = DMSwarmFinalizeFieldRegister(dm);CHKERRQ(ierr);
1165f0cdbbbaSDave May 
11663454631fSDave May   /* check some fields were registered */
11673454631fSDave May   if (swarm->db->nfields <= 2) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"At least one field user must be registered via DMSwarmRegisterXXX()");
11683454631fSDave May 
11693454631fSDave May   /* check local sizes were set */
11703454631fSDave May   if (swarm->db->L == -1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Local sizes must be set via DMSwarmSetLocalSizes()");
11713454631fSDave May 
11723454631fSDave May   /* initialize values in pid and rank placeholders */
11733454631fSDave May   /* TODO: [pid - use MPI_Scan] */
11743454631fSDave May   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
117577048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db,&npoints,NULL,NULL);CHKERRQ(ierr);
1176f0cdbbbaSDave May   ierr = DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
11773454631fSDave May   for (p=0; p<npoints; p++) {
11783454631fSDave May     rankval[p] = (PetscInt)rank;
11793454631fSDave May   }
1180f0cdbbbaSDave May   ierr = DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
11813454631fSDave May   PetscFunctionReturn(0);
11823454631fSDave May }
11833454631fSDave May 
1184dc5f5ce9SDave May extern PetscErrorCode DMSwarmSortDestroy(DMSwarmSort *_ctx);
1185dc5f5ce9SDave May 
118657795646SDave May PetscErrorCode DMDestroy_Swarm(DM dm)
118757795646SDave May {
118857795646SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
118957795646SDave May   PetscErrorCode ierr;
119057795646SDave May 
119157795646SDave May   PetscFunctionBegin;
119277048351SPatrick Sanan   ierr = DMSwarmDataBucketDestroy(&swarm->db);CHKERRQ(ierr);
1193dc5f5ce9SDave May   if (swarm->sort_context) {
1194dc5f5ce9SDave May     ierr = DMSwarmSortDestroy(&swarm->sort_context);CHKERRQ(ierr);
1195dc5f5ce9SDave May   }
119657795646SDave May   ierr = PetscFree(swarm);CHKERRQ(ierr);
119757795646SDave May   PetscFunctionReturn(0);
119857795646SDave May }
119957795646SDave May 
1200a9ee3421SMatthew G. Knepley PetscErrorCode DMSwarmView_Draw(DM dm, PetscViewer viewer)
1201a9ee3421SMatthew G. Knepley {
1202a9ee3421SMatthew G. Knepley   DM             cdm;
1203a9ee3421SMatthew G. Knepley   PetscDraw      draw;
1204a9ee3421SMatthew G. Knepley   PetscReal     *coords, oldPause;
1205a9ee3421SMatthew G. Knepley   PetscInt       Np, p, bs;
1206a9ee3421SMatthew G. Knepley   PetscErrorCode ierr;
1207a9ee3421SMatthew G. Knepley 
1208a9ee3421SMatthew G. Knepley   PetscFunctionBegin;
1209a9ee3421SMatthew G. Knepley   ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr);
1210a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetCellDM(dm, &cdm);CHKERRQ(ierr);
1211a9ee3421SMatthew G. Knepley   ierr = PetscDrawGetPause(draw, &oldPause);CHKERRQ(ierr);
1212a9ee3421SMatthew G. Knepley   ierr = PetscDrawSetPause(draw, 0.0);CHKERRQ(ierr);
1213a9ee3421SMatthew G. Knepley   ierr = DMView(cdm, viewer);CHKERRQ(ierr);
1214a9ee3421SMatthew G. Knepley   ierr = PetscDrawSetPause(draw, oldPause);CHKERRQ(ierr);
1215a9ee3421SMatthew G. Knepley 
1216a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetLocalSize(dm, &Np);CHKERRQ(ierr);
1217a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1218a9ee3421SMatthew G. Knepley   for (p = 0; p < Np; ++p) {
1219a9ee3421SMatthew G. Knepley     const PetscInt i = p*bs;
1220a9ee3421SMatthew G. Knepley 
1221a9ee3421SMatthew G. Knepley     ierr = PetscDrawEllipse(draw, coords[i], coords[i+1], 0.01, 0.01, PETSC_DRAW_BLUE);CHKERRQ(ierr);
1222a9ee3421SMatthew G. Knepley   }
1223a9ee3421SMatthew G. Knepley   ierr = DMSwarmRestoreField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1224a9ee3421SMatthew G. Knepley   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
1225a9ee3421SMatthew G. Knepley   ierr = PetscDrawPause(draw);CHKERRQ(ierr);
1226a9ee3421SMatthew G. Knepley   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
1227a9ee3421SMatthew G. Knepley   PetscFunctionReturn(0);
1228a9ee3421SMatthew G. Knepley }
1229a9ee3421SMatthew G. Knepley 
12305f50eb2eSDave May PetscErrorCode DMView_Swarm(DM dm, PetscViewer viewer)
12315f50eb2eSDave May {
12325f50eb2eSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1233a9ee3421SMatthew G. Knepley   PetscBool      iascii,ibinary,ishdf5,isvtk,isdraw;
12345f50eb2eSDave May   PetscErrorCode ierr;
12355f50eb2eSDave May 
12365f50eb2eSDave May   PetscFunctionBegin;
12375f50eb2eSDave May   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
12385f50eb2eSDave May   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
12395f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
12405f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY,&ibinary);CHKERRQ(ierr);
12415f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK,   &isvtk);CHKERRQ(ierr);
12425f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
1243a9ee3421SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW,  &isdraw);CHKERRQ(ierr);
12445f50eb2eSDave May   if (iascii) {
124577048351SPatrick Sanan     ierr = DMSwarmDataBucketView(PetscObjectComm((PetscObject)dm),swarm->db,NULL,DATABUCKET_VIEW_STDOUT);CHKERRQ(ierr);
1246298827fbSBarry Smith   } else if (ibinary) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO Binary support");
12475f50eb2eSDave May #if defined(PETSC_HAVE_HDF5)
1248298827fbSBarry Smith   else if (ishdf5) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO HDF5 support");
12495f50eb2eSDave May #else
1250298827fbSBarry Smith   else if (ishdf5) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"HDF5 not supported. Please reconfigure using --download-hdf5");
12515f50eb2eSDave May #endif
1252298827fbSBarry Smith   else if (isvtk) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO VTK support");
1253298827fbSBarry Smith   else if (isdraw) {
1254a9ee3421SMatthew G. Knepley     ierr = DMSwarmView_Draw(dm, viewer);CHKERRQ(ierr);
12555f50eb2eSDave May   }
12565f50eb2eSDave May   PetscFunctionReturn(0);
12575f50eb2eSDave May }
12585f50eb2eSDave May 
1259d3a51819SDave May /*MC
1260d3a51819SDave May 
1261d3a51819SDave May  DMSWARM = "swarm" - A DM object used to represent arrays of data (fields) of arbitrary data type.
126262741f57SDave May  This implementation was designed for particle methods in which the underlying
1263d3a51819SDave May  data required to be represented is both (i) dynamic in length, (ii) and of arbitrary data type.
1264d3a51819SDave May 
126562741f57SDave May  User data can be represented by DMSwarm through a registering "fields".
126662741f57SDave May  To register a field, the user must provide;
126762741f57SDave May  (a) a unique name;
126862741f57SDave May  (b) the data type (or size in bytes);
126962741f57SDave May  (c) the block size of the data.
1270d3a51819SDave May 
1271d3a51819SDave May  For example, suppose the application requires a unique id, energy, momentum and density to be stored
127262741f57SDave May  on a set of of particles. Then the following code could be used
1273d3a51819SDave May 
127462741f57SDave May $    DMSwarmInitializeFieldRegister(dm)
127562741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"uid",1,PETSC_LONG);
127662741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"energy",1,PETSC_REAL);
127762741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"momentum",3,PETSC_REAL);
127862741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"density",1,PETSC_FLOAT);
127962741f57SDave May $    DMSwarmFinalizeFieldRegister(dm)
1280d3a51819SDave May 
1281d3a51819SDave May  The fields represented by DMSwarm are dynamic and can be re-sized at any time.
128262741f57SDave May  The only restriction imposed by DMSwarm is that all fields contain the same number of points.
1283d3a51819SDave May 
1284d3a51819SDave May  To support particle methods, "migration" techniques are provided. These methods migrate data
1285d3a51819SDave May  between MPI-ranks.
1286d3a51819SDave May 
1287d3a51819SDave May  DMSwarm supports the methods DMCreateGlobalVector() and DMCreateLocalVector().
1288d3a51819SDave May  As a DMSwarm may internally define and store values of different data types,
128962741f57SDave May  before calling DMCreateGlobalVector() or DMCreateLocalVector(), the user must inform DMSwarm which
1290d3a51819SDave May  fields should be used to define a Vec object via
1291d3a51819SDave May    DMSwarmVectorDefineField()
1292d3a51819SDave May  The specified field can can changed be changed at any time - thereby permitting vectors
1293d3a51819SDave May  compatable with different fields to be created.
1294d3a51819SDave May 
129562741f57SDave May  A dual representation of fields in the DMSwarm and a Vec object is permitted via
1296d3a51819SDave May    DMSwarmCreateGlobalVectorFromField()
1297d3a51819SDave May  Here the data defining the field in the DMSwarm is shared with a Vec.
1298d3a51819SDave May  This is inherently unsafe if you alter the size of the field at any time between
1299d3a51819SDave May  calls to DMSwarmCreateGlobalVectorFromField() and DMSwarmDestroyGlobalVectorFromField().
1300cc651181SDave May  If the local size of the DMSwarm does not match the local size of the global vector
1301cc651181SDave May  when DMSwarmDestroyGlobalVectorFromField() is called, an error is thrown.
1302d3a51819SDave May 
130362741f57SDave May  Additional high-level support is provided for Particle-In-Cell methods.
130462741f57SDave May  Please refer to the man page for DMSwarmSetType().
130562741f57SDave May 
1306d3a51819SDave May  Level: beginner
1307d3a51819SDave May 
1308d3a51819SDave May .seealso: DMType, DMCreate(), DMSetType()
1309d3a51819SDave May M*/
131057795646SDave May PETSC_EXTERN PetscErrorCode DMCreate_Swarm(DM dm)
131157795646SDave May {
131257795646SDave May   DM_Swarm      *swarm;
131357795646SDave May   PetscErrorCode ierr;
131457795646SDave May 
131557795646SDave May   PetscFunctionBegin;
131657795646SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
131757795646SDave May   ierr     = PetscNewLog(dm,&swarm);CHKERRQ(ierr);
1318f0cdbbbaSDave May   dm->data = swarm;
131957795646SDave May 
132077048351SPatrick Sanan   ierr = DMSwarmDataBucketCreate(&swarm->db);CHKERRQ(ierr);
1321f0cdbbbaSDave May   ierr = DMSwarmInitializeFieldRegister(dm);CHKERRQ(ierr);
1322f0cdbbbaSDave May 
1323b5bcf523SDave May   swarm->vec_field_set = PETSC_FALSE;
13243454631fSDave May   swarm->issetup = PETSC_FALSE;
1325480eef7bSDave May   swarm->swarm_type = DMSWARM_BASIC;
1326480eef7bSDave May   swarm->migrate_type = DMSWARM_MIGRATE_BASIC;
1327480eef7bSDave May   swarm->collect_type = DMSWARM_COLLECT_BASIC;
132840c453e9SDave May   swarm->migrate_error_on_missing_point = PETSC_FALSE;
1329b62e03f8SDave May 
1330f0cdbbbaSDave May   swarm->dmcell = NULL;
1331f0cdbbbaSDave May   swarm->collect_view_active = PETSC_FALSE;
1332f0cdbbbaSDave May   swarm->collect_view_reset_nlocal = -1;
133357795646SDave May 
1334f0cdbbbaSDave May   dm->dim  = 0;
13355f50eb2eSDave May   dm->ops->view                            = DMView_Swarm;
133657795646SDave May   dm->ops->load                            = NULL;
133757795646SDave May   dm->ops->setfromoptions                  = NULL;
133857795646SDave May   dm->ops->clone                           = NULL;
13393454631fSDave May   dm->ops->setup                           = DMSetup_Swarm;
134057795646SDave May   dm->ops->createdefaultsection            = NULL;
134157795646SDave May   dm->ops->createdefaultconstraints        = NULL;
1342b5bcf523SDave May   dm->ops->createglobalvector              = DMCreateGlobalVector_Swarm;
1343b5bcf523SDave May   dm->ops->createlocalvector               = DMCreateLocalVector_Swarm;
134457795646SDave May   dm->ops->getlocaltoglobalmapping         = NULL;
134557795646SDave May   dm->ops->createfieldis                   = NULL;
134657795646SDave May   dm->ops->createcoordinatedm              = NULL;
134757795646SDave May   dm->ops->getcoloring                     = NULL;
134857795646SDave May   dm->ops->creatematrix                    = NULL;
134957795646SDave May   dm->ops->createinterpolation             = NULL;
135057795646SDave May   dm->ops->getaggregates                   = NULL;
135157795646SDave May   dm->ops->getinjection                    = NULL;
135283c47955SMatthew G. Knepley   dm->ops->createmassmatrix                = DMCreateMassMatrix_Swarm;
135357795646SDave May   dm->ops->refine                          = NULL;
135457795646SDave May   dm->ops->coarsen                         = NULL;
135557795646SDave May   dm->ops->refinehierarchy                 = NULL;
135657795646SDave May   dm->ops->coarsenhierarchy                = NULL;
135757795646SDave May   dm->ops->globaltolocalbegin              = NULL;
135857795646SDave May   dm->ops->globaltolocalend                = NULL;
135957795646SDave May   dm->ops->localtoglobalbegin              = NULL;
136057795646SDave May   dm->ops->localtoglobalend                = NULL;
136157795646SDave May   dm->ops->destroy                         = DMDestroy_Swarm;
136257795646SDave May   dm->ops->createsubdm                     = NULL;
136357795646SDave May   dm->ops->getdimpoints                    = NULL;
136457795646SDave May   dm->ops->locatepoints                    = NULL;
136557795646SDave May   PetscFunctionReturn(0);
136657795646SDave May }
1367