xref: /petsc/src/dm/impls/swarm/swarm.c (revision fc7c92ab687896508d6e9b986ce51948bd9e0c08)
157795646SDave May #define PETSCDM_DLL
257795646SDave May #include <petsc/private/dmswarmimpl.h>    /*I   "petscdmswarm.h"   I*/
383c47955SMatthew G. Knepley #include <petsc/private/hash.h>
45917a6f0SStefano Zampini #include <petscviewer.h>
55917a6f0SStefano Zampini #include <petscdraw.h>
683c47955SMatthew 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 
16583c47955SMatthew G. Knepley static PetscErrorCode DMSwarmComputeMassMatrix_Private(DM dmc, DM dmf, Mat mass, void *ctx)
16683c47955SMatthew G. Knepley {
16783c47955SMatthew G. Knepley   const char    *name = "Mass Matrix";
16883c47955SMatthew G. Knepley   PetscDS        prob;
16983c47955SMatthew G. Knepley   PetscSection   fsection, globalFSection;
17083c47955SMatthew G. Knepley   PetscHashJK    ht;
17183c47955SMatthew G. Knepley   PetscLayout    rLayout;
17283c47955SMatthew G. Knepley   PetscInt      *dnz, *onz;
17383c47955SMatthew G. Knepley   PetscInt       locRows, rStart, rEnd;
17483c47955SMatthew G. Knepley   PetscReal     *x, *v0, *J, *invJ, detJ;
17583c47955SMatthew G. Knepley   PetscScalar   *elemMat;
176*fc7c92abSMatthew G. Knepley   PetscInt       dim, Nf, field, totDim, cStart, cEnd, cell, maxC = 0;
1774f482ee1SMatthew G. Knepley   PetscMPIInt    size;
17883c47955SMatthew G. Knepley   PetscErrorCode ierr;
17983c47955SMatthew G. Knepley 
18083c47955SMatthew G. Knepley   PetscFunctionBegin;
1814f482ee1SMatthew G. Knepley   ierr = MPI_Comm_size(PetscObjectComm((PetscObject) dmf), &size);CHKERRQ(ierr);
18283c47955SMatthew G. Knepley   ierr = DMGetCoordinateDim(dmf, &dim);CHKERRQ(ierr);
18383c47955SMatthew G. Knepley   ierr = DMGetDS(dmf, &prob);CHKERRQ(ierr);
18483c47955SMatthew G. Knepley   ierr = PetscDSGetRefCoordArrays(prob, &x, NULL);CHKERRQ(ierr);
18583c47955SMatthew G. Knepley   ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr);
18683c47955SMatthew G. Knepley   ierr = PetscMalloc3(dim,&v0,dim*dim,&J,dim*dim,&invJ);CHKERRQ(ierr);
18783c47955SMatthew G. Knepley   ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);
18883c47955SMatthew G. Knepley   ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);
18983c47955SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd);CHKERRQ(ierr);
19083c47955SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr);
19183c47955SMatthew G. Knepley   ierr = DMSwarmSortGetAccess(dmc);CHKERRQ(ierr);
19283c47955SMatthew G. Knepley 
19383c47955SMatthew G. Knepley   ierr = MatGetLocalSize(mass, &locRows, NULL);CHKERRQ(ierr);
19483c47955SMatthew G. Knepley   ierr = PetscLayoutCreate(PetscObjectComm((PetscObject) mass), &rLayout);CHKERRQ(ierr);
19583c47955SMatthew G. Knepley   ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr);
19683c47955SMatthew G. Knepley   ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr);
19783c47955SMatthew G. Knepley   ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr);
19883c47955SMatthew G. Knepley   ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr);
19983c47955SMatthew G. Knepley   ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr);
20083c47955SMatthew G. Knepley   ierr = PetscCalloc2(locRows,&dnz,locRows,&onz);CHKERRQ(ierr);
20183c47955SMatthew G. Knepley   ierr = PetscHashJKCreate(&ht);CHKERRQ(ierr);
20283c47955SMatthew G. Knepley   for (field = 0; field < Nf; ++field) {
20383c47955SMatthew G. Knepley     PetscObject      obj;
20483c47955SMatthew G. Knepley     PetscQuadrature  quad;
20583c47955SMatthew G. Knepley     const PetscReal *qpoints;
20683c47955SMatthew G. Knepley     PetscInt         Nq, Nc, i;
20783c47955SMatthew G. Knepley 
20883c47955SMatthew G. Knepley     ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr);
20983c47955SMatthew G. Knepley     ierr = PetscFEGetQuadrature((PetscFE) obj, &quad);CHKERRQ(ierr);
21083c47955SMatthew G. Knepley     ierr = PetscQuadratureGetData(quad, NULL, &Nc, &Nq, &qpoints, NULL);CHKERRQ(ierr);
21183c47955SMatthew G. Knepley     /* For each fine grid cell */
21283c47955SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
21383c47955SMatthew G. Knepley       PetscInt  Np, c;
21483c47955SMatthew G. Knepley       PetscInt *findices,   *cindices;
21583c47955SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
21683c47955SMatthew G. Knepley 
21783c47955SMatthew G. Knepley       ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
21883c47955SMatthew G. Knepley       ierr = DMSwarmSortGetNumberOfPointsPerCell(dmc, cell, &Np);CHKERRQ(ierr);
219e8291c10SMatthew G. Knepley       if (Np != Nq) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Not all closure points located %D != %D", Np, Nq);
220*fc7c92abSMatthew G. Knepley       ierr = DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices);CHKERRQ(ierr);
221*fc7c92abSMatthew G. Knepley       maxC = PetscMax(maxC, numCIndices);
22283c47955SMatthew G. Knepley       /* Update preallocation info */
22383c47955SMatthew G. Knepley       {
22483c47955SMatthew G. Knepley         PetscHashJKKey  key;
22583c47955SMatthew G. Knepley         PetscHashJKIter missing, iter;
22683c47955SMatthew G. Knepley 
22783c47955SMatthew G. Knepley         for (i = 0; i < numFIndices; ++i) {
22883c47955SMatthew G. Knepley           key.j = findices[i];
22983c47955SMatthew G. Knepley           if (key.j >= 0) {
23083c47955SMatthew G. Knepley             /* Get indices for coarse elements */
23183c47955SMatthew G. Knepley             for (c = 0; c < numCIndices; ++c) {
23283c47955SMatthew G. Knepley               key.k = cindices[c];
23383c47955SMatthew G. Knepley               if (key.k < 0) continue;
23483c47955SMatthew G. Knepley               ierr = PetscHashJKPut(ht, key, &missing, &iter);CHKERRQ(ierr);
23583c47955SMatthew G. Knepley               if (missing) {
23683c47955SMatthew G. Knepley                 ierr = PetscHashJKSet(ht, iter, 1);CHKERRQ(ierr);
2374f482ee1SMatthew G. Knepley                 if ((size == 1) || ((key.k >= rStart) && (key.k < rEnd))) ++dnz[key.j-rStart];
23883c47955SMatthew G. Knepley                 else                                                      ++onz[key.j-rStart];
23983c47955SMatthew G. Knepley               }
24083c47955SMatthew G. Knepley             }
241*fc7c92abSMatthew G. Knepley           }
242*fc7c92abSMatthew G. Knepley         }
24383c47955SMatthew G. Knepley         ierr = PetscFree(cindices);CHKERRQ(ierr);
24483c47955SMatthew G. Knepley       }
24583c47955SMatthew G. Knepley       ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
24683c47955SMatthew G. Knepley     }
24783c47955SMatthew G. Knepley   }
24883c47955SMatthew G. Knepley   ierr = PetscHashJKDestroy(&ht);CHKERRQ(ierr);
24983c47955SMatthew G. Knepley   ierr = MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL);CHKERRQ(ierr);
25083c47955SMatthew G. Knepley   ierr = MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
25183c47955SMatthew G. Knepley   ierr = PetscFree2(dnz,onz);CHKERRQ(ierr);
252*fc7c92abSMatthew G. Knepley   ierr = PetscMalloc1(maxC, &elemMat);CHKERRQ(ierr);
25383c47955SMatthew G. Knepley   for (field = 0; field < Nf; ++field) {
25483c47955SMatthew G. Knepley     PetscObject      obj;
25583c47955SMatthew G. Knepley     PetscQuadrature  quad;
25683c47955SMatthew G. Knepley     PetscReal       *Bfine;
25783c47955SMatthew G. Knepley     const PetscReal *qweights;
25883c47955SMatthew G. Knepley     PetscInt         Nq, Nc, i;
25983c47955SMatthew G. Knepley 
26083c47955SMatthew G. Knepley     ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr);
26183c47955SMatthew G. Knepley     ierr = PetscFEGetDefaultTabulation((PetscFE) obj, &Bfine, NULL, NULL);CHKERRQ(ierr);
26283c47955SMatthew G. Knepley     ierr = PetscFEGetQuadrature((PetscFE) obj, &quad);CHKERRQ(ierr);
26383c47955SMatthew G. Knepley     ierr = PetscQuadratureGetData(quad, NULL, &Nc, &Nq, NULL, &qweights);CHKERRQ(ierr);
26483c47955SMatthew G. Knepley     /* For each fine grid cell */
26583c47955SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
26683c47955SMatthew G. Knepley       PetscInt           Np, c, j;
26783c47955SMatthew G. Knepley       PetscInt          *findices,   *cindices;
26883c47955SMatthew G. Knepley       PetscInt           numFIndices, numCIndices;
26983c47955SMatthew G. Knepley 
27083c47955SMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr);
27183c47955SMatthew G. Knepley       ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
27283c47955SMatthew G. Knepley       ierr = DMSwarmSortGetNumberOfPointsPerCell(dmc, cell, &Np);CHKERRQ(ierr);
273e8291c10SMatthew G. Knepley       if (Np != Nq) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Not all closure points located %D != %D", Np, Nq);
27483c47955SMatthew G. Knepley       ierr = DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices);CHKERRQ(ierr);
27583c47955SMatthew G. Knepley       /* Get elemMat entries by multiplying by weight */
27683c47955SMatthew G. Knepley       for (i = 0; i < numFIndices; ++i) {
27783c47955SMatthew G. Knepley         ierr = PetscMemzero(elemMat, numCIndices * sizeof(PetscScalar));CHKERRQ(ierr);
27883c47955SMatthew G. Knepley         for (j = 0; j < numCIndices; ++j) {
27983c47955SMatthew G. Knepley           for (c = 0; c < Nc; ++c) elemMat[j] += Bfine[(j*numFIndices + i)*Nc + c]*qweights[j*Nc + c]*detJ;
28083c47955SMatthew G. Knepley         }
28183c47955SMatthew G. Knepley         /* Update interpolator */
28283c47955SMatthew G. Knepley         if (0) {ierr = DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat);CHKERRQ(ierr);}
28383c47955SMatthew G. Knepley         ierr = MatSetValues(mass, 1, &findices[i], numCIndices, cindices, elemMat, ADD_VALUES);CHKERRQ(ierr);
28483c47955SMatthew G. Knepley       }
28583c47955SMatthew G. Knepley       ierr = PetscFree(cindices);CHKERRQ(ierr);
28683c47955SMatthew G. Knepley       ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
28783c47955SMatthew G. Knepley     }
28883c47955SMatthew G. Knepley   }
28983c47955SMatthew G. Knepley   ierr = DMSwarmSortRestoreAccess(dmc);CHKERRQ(ierr);
29083c47955SMatthew G. Knepley   ierr = PetscFree3(v0,J,invJ);CHKERRQ(ierr);
29183c47955SMatthew G. Knepley   ierr = PetscFree(elemMat);CHKERRQ(ierr);
29283c47955SMatthew G. Knepley   ierr = MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
29383c47955SMatthew G. Knepley   ierr = MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
29483c47955SMatthew G. Knepley   PetscFunctionReturn(0);
29583c47955SMatthew G. Knepley }
29683c47955SMatthew G. Knepley 
29783c47955SMatthew G. Knepley static PetscErrorCode DMCreateMassMatrix_Swarm(DM dmCoarse, DM dmFine, Mat *mass)
29883c47955SMatthew G. Knepley {
299895a1698SMatthew G. Knepley   PetscSection   gsf;
30083c47955SMatthew G. Knepley   PetscInt       m, n;
30183c47955SMatthew G. Knepley   void          *ctx;
30283c47955SMatthew G. Knepley   PetscErrorCode ierr;
30383c47955SMatthew G. Knepley 
30483c47955SMatthew G. Knepley   PetscFunctionBegin;
30583c47955SMatthew G. Knepley   ierr = DMGetDefaultGlobalSection(dmFine, &gsf);CHKERRQ(ierr);
30683c47955SMatthew G. Knepley   ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr);
307895a1698SMatthew G. Knepley   ierr = DMSwarmGetLocalSize(dmCoarse, &n);CHKERRQ(ierr);
30883c47955SMatthew G. Knepley 
30983c47955SMatthew G. Knepley   ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr);
31083c47955SMatthew G. Knepley   ierr = MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
31183c47955SMatthew G. Knepley   ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr);
31283c47955SMatthew G. Knepley   ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr);
31383c47955SMatthew G. Knepley 
31483c47955SMatthew G. Knepley   ierr = DMSwarmComputeMassMatrix_Private(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);
31583c47955SMatthew G. Knepley   ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr);
31683c47955SMatthew G. Knepley   PetscFunctionReturn(0);
31783c47955SMatthew G. Knepley }
31883c47955SMatthew G. Knepley 
319fb1bcc12SMatthew G. Knepley /*@C
320d3a51819SDave May    DMSwarmCreateGlobalVectorFromField - Creates a Vec object sharing the array associated with a given field
321d3a51819SDave May 
322d3a51819SDave May    Collective on DM
323d3a51819SDave May 
324d3a51819SDave May    Input parameters:
32562741f57SDave May +  dm - a DMSwarm
32662741f57SDave May -  fieldname - the textual name given to a registered field
327d3a51819SDave May 
3288b8a3813SDave May    Output parameter:
329d3a51819SDave May .  vec - the vector
330d3a51819SDave May 
331d3a51819SDave May    Level: beginner
332d3a51819SDave May 
3338b8a3813SDave May    Notes:
3348b8a3813SDave May    The vector must be returned using a matching call to DMSwarmDestroyGlobalVectorFromField().
3358b8a3813SDave May 
3368b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmDestroyGlobalVectorFromField()
337d3a51819SDave May @*/
338b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmCreateGlobalVectorFromField(DM dm,const char fieldname[],Vec *vec)
339b5bcf523SDave May {
340fb1bcc12SMatthew G. Knepley   MPI_Comm       comm = PetscObjectComm((PetscObject) dm);
341b5bcf523SDave May   PetscErrorCode ierr;
342b5bcf523SDave May 
343fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
344fb1bcc12SMatthew G. Knepley   ierr = DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec);CHKERRQ(ierr);
345b5bcf523SDave May   PetscFunctionReturn(0);
346b5bcf523SDave May }
347b5bcf523SDave May 
348d3a51819SDave May /*@C
349d3a51819SDave May    DMSwarmDestroyGlobalVectorFromField - Destroys the Vec object which share the array associated with a given field
350d3a51819SDave May 
351d3a51819SDave May    Collective on DM
352d3a51819SDave May 
353d3a51819SDave May    Input parameters:
35462741f57SDave May +  dm - a DMSwarm
35562741f57SDave May -  fieldname - the textual name given to a registered field
356d3a51819SDave May 
3578b8a3813SDave May    Output parameter:
358d3a51819SDave May .  vec - the vector
359d3a51819SDave May 
360d3a51819SDave May    Level: beginner
361d3a51819SDave May 
3628b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmCreateGlobalVectorFromField()
363d3a51819SDave May @*/
364b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmDestroyGlobalVectorFromField(DM dm,const char fieldname[],Vec *vec)
365b5bcf523SDave May {
366b5bcf523SDave May   PetscErrorCode ierr;
367cc651181SDave May 
368fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
369fb1bcc12SMatthew G. Knepley   ierr = DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec);CHKERRQ(ierr);
370b5bcf523SDave May   PetscFunctionReturn(0);
371b5bcf523SDave May }
372b5bcf523SDave May 
373fb1bcc12SMatthew G. Knepley /*@C
374fb1bcc12SMatthew G. Knepley    DMSwarmCreateLocalVectorFromField - Creates a Vec object sharing the array associated with a given field
375fb1bcc12SMatthew G. Knepley 
376fb1bcc12SMatthew G. Knepley    Collective on DM
377fb1bcc12SMatthew G. Knepley 
378fb1bcc12SMatthew G. Knepley    Input parameters:
37962741f57SDave May +  dm - a DMSwarm
38062741f57SDave May -  fieldname - the textual name given to a registered field
381fb1bcc12SMatthew G. Knepley 
3828b8a3813SDave May    Output parameter:
383fb1bcc12SMatthew G. Knepley .  vec - the vector
384fb1bcc12SMatthew G. Knepley 
385fb1bcc12SMatthew G. Knepley    Level: beginner
386fb1bcc12SMatthew G. Knepley 
3878b8a3813SDave May    Notes:
3888b8a3813SDave May    The vector must be returned using a matching call to DMSwarmDestroyLocalVectorFromField().
3898b8a3813SDave May 
3908b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmDestroyLocalVectorFromField()
391fb1bcc12SMatthew G. Knepley @*/
392fb1bcc12SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMSwarmCreateLocalVectorFromField(DM dm,const char fieldname[],Vec *vec)
393bbe8250bSMatthew G. Knepley {
394fb1bcc12SMatthew G. Knepley   MPI_Comm       comm = PETSC_COMM_SELF;
395bbe8250bSMatthew G. Knepley   PetscErrorCode ierr;
396bbe8250bSMatthew G. Knepley 
397fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
398fb1bcc12SMatthew G. Knepley   ierr = DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec);CHKERRQ(ierr);
399fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
400bbe8250bSMatthew G. Knepley }
401fb1bcc12SMatthew G. Knepley 
402fb1bcc12SMatthew G. Knepley /*@C
403fb1bcc12SMatthew G. Knepley    DMSwarmDestroyLocalVectorFromField - Destroys the Vec object which share the array associated with a given field
404fb1bcc12SMatthew G. Knepley 
405fb1bcc12SMatthew G. Knepley    Collective on DM
406fb1bcc12SMatthew G. Knepley 
407fb1bcc12SMatthew G. Knepley    Input parameters:
40862741f57SDave May +  dm - a DMSwarm
40962741f57SDave May -  fieldname - the textual name given to a registered field
410fb1bcc12SMatthew G. Knepley 
4118b8a3813SDave May    Output parameter:
412fb1bcc12SMatthew G. Knepley .  vec - the vector
413fb1bcc12SMatthew G. Knepley 
414fb1bcc12SMatthew G. Knepley    Level: beginner
415fb1bcc12SMatthew G. Knepley 
4168b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmCreateLocalVectorFromField()
417fb1bcc12SMatthew G. Knepley @*/
418fb1bcc12SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMSwarmDestroyLocalVectorFromField(DM dm,const char fieldname[],Vec *vec)
419fb1bcc12SMatthew G. Knepley {
420fb1bcc12SMatthew G. Knepley   PetscErrorCode ierr;
421fb1bcc12SMatthew G. Knepley 
422fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
423fb1bcc12SMatthew G. Knepley   ierr = DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec);CHKERRQ(ierr);
424bbe8250bSMatthew G. Knepley   PetscFunctionReturn(0);
425bbe8250bSMatthew G. Knepley }
426bbe8250bSMatthew G. Knepley 
427b5bcf523SDave May /*
428b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmCreateGlobalVectorFromFields(DM dm,const PetscInt nf,const char *fieldnames[],Vec *vec)
429b5bcf523SDave May {
430b5bcf523SDave May   PetscFunctionReturn(0);
431b5bcf523SDave May }
432b5bcf523SDave May 
433b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmRestoreGlobalVectorFromFields(DM dm,Vec *vec)
434b5bcf523SDave May {
435b5bcf523SDave May   PetscFunctionReturn(0);
436b5bcf523SDave May }
437b5bcf523SDave May */
438b5bcf523SDave May 
439d3a51819SDave May /*@C
440d3a51819SDave May    DMSwarmInitializeFieldRegister - Initiates the registration of fields to a DMSwarm
441d3a51819SDave May 
442d3a51819SDave May    Collective on DM
443d3a51819SDave May 
444d3a51819SDave May    Input parameter:
445d3a51819SDave May .  dm - a DMSwarm
446d3a51819SDave May 
447d3a51819SDave May    Level: beginner
448d3a51819SDave May 
449d3a51819SDave May    Notes:
4508b8a3813SDave May    After all fields have been registered, you must call DMSwarmFinalizeFieldRegister().
451d3a51819SDave May 
452d3a51819SDave May .seealso: DMSwarmFinalizeFieldRegister(), DMSwarmRegisterPetscDatatypeField(),
453d3a51819SDave May  DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
454d3a51819SDave May @*/
4555f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmInitializeFieldRegister(DM dm)
4565f50eb2eSDave May {
4575f50eb2eSDave May   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
4583454631fSDave May   PetscErrorCode ierr;
4593454631fSDave May 
460521f74f9SMatthew G. Knepley   PetscFunctionBegin;
461cc651181SDave May   if (!swarm->field_registration_initialized) {
4625f50eb2eSDave May     swarm->field_registration_initialized = PETSC_TRUE;
463f0cdbbbaSDave May     ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_pid,1,PETSC_LONG);CHKERRQ(ierr); /* unique identifer */
464f0cdbbbaSDave May     ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_rank,1,PETSC_INT);CHKERRQ(ierr); /* used for communication */
465cc651181SDave May   }
4665f50eb2eSDave May   PetscFunctionReturn(0);
4675f50eb2eSDave May }
4685f50eb2eSDave May 
469d3a51819SDave May /*@C
470d3a51819SDave May    DMSwarmFinalizeFieldRegister - Finalizes the registration of fields to a DMSwarm
471d3a51819SDave May 
472d3a51819SDave May    Collective on DM
473d3a51819SDave May 
474d3a51819SDave May    Input parameter:
475d3a51819SDave May .  dm - a DMSwarm
476d3a51819SDave May 
477d3a51819SDave May    Level: beginner
478d3a51819SDave May 
479d3a51819SDave May    Notes:
48062741f57SDave May    After DMSwarmFinalizeFieldRegister() has been called, no new fields can be defined on the DMSwarm.
481d3a51819SDave May 
482d3a51819SDave May .seealso: DMSwarmInitializeFieldRegister(), DMSwarmRegisterPetscDatatypeField(),
483d3a51819SDave May  DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
484d3a51819SDave May @*/
4855f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmFinalizeFieldRegister(DM dm)
4865f50eb2eSDave May {
4875f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
4886845f8f5SDave May   PetscErrorCode ierr;
4896845f8f5SDave May 
490521f74f9SMatthew G. Knepley   PetscFunctionBegin;
491f0cdbbbaSDave May   if (!swarm->field_registration_finalized) {
4926845f8f5SDave May     ierr = DataBucketFinalize(swarm->db);CHKERRQ(ierr);
493f0cdbbbaSDave May   }
494f0cdbbbaSDave May   swarm->field_registration_finalized = PETSC_TRUE;
4955f50eb2eSDave May   PetscFunctionReturn(0);
4965f50eb2eSDave May }
4975f50eb2eSDave May 
498d3a51819SDave May /*@C
499d3a51819SDave May    DMSwarmSetLocalSizes - Sets the length of all registered fields on the DMSwarm
500d3a51819SDave May 
501d3a51819SDave May    Not collective
502d3a51819SDave May 
503d3a51819SDave May    Input parameters:
50462741f57SDave May +  dm - a DMSwarm
505d3a51819SDave May .  nlocal - the length of each registered field
50662741f57SDave May -  buffer - the length of the buffer used to efficient dynamic re-sizing
507d3a51819SDave May 
508d3a51819SDave May    Level: beginner
509d3a51819SDave May 
510d3a51819SDave May .seealso: DMSwarmGetLocalSize()
511d3a51819SDave May @*/
5125f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmSetLocalSizes(DM dm,PetscInt nlocal,PetscInt buffer)
5135f50eb2eSDave May {
5145f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
5156845f8f5SDave May   PetscErrorCode ierr;
5165f50eb2eSDave May 
517521f74f9SMatthew G. Knepley   PetscFunctionBegin;
518f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_SetSizes,0,0,0,0);CHKERRQ(ierr);
5196845f8f5SDave May   ierr = DataBucketSetSizes(swarm->db,nlocal,buffer);CHKERRQ(ierr);
520f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_SetSizes,0,0,0,0);CHKERRQ(ierr);
5215f50eb2eSDave May   PetscFunctionReturn(0);
5225f50eb2eSDave May }
5235f50eb2eSDave May 
524d3a51819SDave May /*@C
525d3a51819SDave May    DMSwarmSetCellDM - Attachs a DM to a DMSwarm
526d3a51819SDave May 
527d3a51819SDave May    Collective on DM
528d3a51819SDave May 
529d3a51819SDave May    Input parameters:
53062741f57SDave May +  dm - a DMSwarm
53162741f57SDave May -  dmcell - the DM to attach to the DMSwarm
532d3a51819SDave May 
533d3a51819SDave May    Level: beginner
534d3a51819SDave May 
535d3a51819SDave May    Notes:
536d3a51819SDave May    The attached DM (dmcell) will be queried for point location and
5378b8a3813SDave May    neighbor MPI-rank information if DMSwarmMigrate() is called.
538d3a51819SDave May 
5398b8a3813SDave May .seealso: DMSwarmSetType(), DMSwarmGetCellDM(), DMSwarmMigrate()
540d3a51819SDave May @*/
541b16650c8SDave May PETSC_EXTERN PetscErrorCode DMSwarmSetCellDM(DM dm,DM dmcell)
542b16650c8SDave May {
543b16650c8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
544521f74f9SMatthew G. Knepley 
545521f74f9SMatthew G. Knepley   PetscFunctionBegin;
546b16650c8SDave May   swarm->dmcell = dmcell;
547b16650c8SDave May   PetscFunctionReturn(0);
548b16650c8SDave May }
549b16650c8SDave May 
550d3a51819SDave May /*@C
551d3a51819SDave May    DMSwarmGetCellDM - Fetches the attached cell DM
552d3a51819SDave May 
553d3a51819SDave May    Collective on DM
554d3a51819SDave May 
555d3a51819SDave May    Input parameter:
556d3a51819SDave May .  dm - a DMSwarm
557d3a51819SDave May 
558d3a51819SDave May    Output parameter:
559d3a51819SDave May .  dmcell - the DM which was attached to the DMSwarm
560d3a51819SDave May 
561d3a51819SDave May    Level: beginner
562d3a51819SDave May 
563d3a51819SDave May .seealso: DMSwarmSetCellDM()
564d3a51819SDave May @*/
565fe39f135SDave May PETSC_EXTERN PetscErrorCode DMSwarmGetCellDM(DM dm,DM *dmcell)
566fe39f135SDave May {
567fe39f135SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
568521f74f9SMatthew G. Knepley 
569521f74f9SMatthew G. Knepley   PetscFunctionBegin;
570fe39f135SDave May   *dmcell = swarm->dmcell;
571fe39f135SDave May   PetscFunctionReturn(0);
572fe39f135SDave May }
573fe39f135SDave May 
574d3a51819SDave May /*@C
575d3a51819SDave May    DMSwarmGetLocalSize - Retrives the local length of fields registered
576d3a51819SDave May 
577d3a51819SDave May    Not collective
578d3a51819SDave May 
579d3a51819SDave May    Input parameter:
580d3a51819SDave May .  dm - a DMSwarm
581d3a51819SDave May 
582d3a51819SDave May    Output parameter:
583d3a51819SDave May .  nlocal - the length of each registered field
584d3a51819SDave May 
585d3a51819SDave May    Level: beginner
586d3a51819SDave May 
5878b8a3813SDave May .seealso: DMSwarmGetSize(), DMSwarmSetLocalSizes()
588d3a51819SDave May @*/
589dcf43ee8SDave May PETSC_EXTERN PetscErrorCode DMSwarmGetLocalSize(DM dm,PetscInt *nlocal)
590dcf43ee8SDave May {
591dcf43ee8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
592dcf43ee8SDave May   PetscErrorCode ierr;
593dcf43ee8SDave May 
594521f74f9SMatthew G. Knepley   PetscFunctionBegin;
595521f74f9SMatthew G. Knepley   if (nlocal) {ierr = DataBucketGetSizes(swarm->db,nlocal,NULL,NULL);CHKERRQ(ierr);}
596dcf43ee8SDave May   PetscFunctionReturn(0);
597dcf43ee8SDave May }
598dcf43ee8SDave May 
599d3a51819SDave May /*@C
600d3a51819SDave May    DMSwarmGetSize - Retrives the total length of fields registered
601d3a51819SDave May 
602d3a51819SDave May    Collective on DM
603d3a51819SDave May 
604d3a51819SDave May    Input parameter:
605d3a51819SDave May .  dm - a DMSwarm
606d3a51819SDave May 
607d3a51819SDave May    Output parameter:
608d3a51819SDave May .  n - the total length of each registered field
609d3a51819SDave May 
610d3a51819SDave May    Level: beginner
611d3a51819SDave May 
612d3a51819SDave May    Note:
613d3a51819SDave May    This calls MPI_Allreduce upon each call (inefficient but safe)
614d3a51819SDave May 
6158b8a3813SDave May .seealso: DMSwarmGetLocalSize(), DMSwarmSetLocalSizes()
616d3a51819SDave May @*/
617dcf43ee8SDave May PETSC_EXTERN PetscErrorCode DMSwarmGetSize(DM dm,PetscInt *n)
618dcf43ee8SDave May {
619dcf43ee8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
620dcf43ee8SDave May   PetscErrorCode ierr;
621dcf43ee8SDave May   PetscInt nlocal,ng;
622dcf43ee8SDave May 
623521f74f9SMatthew G. Knepley   PetscFunctionBegin;
624dcf43ee8SDave May   ierr = DataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
625dcf43ee8SDave May   ierr = MPI_Allreduce(&nlocal,&ng,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
626dcf43ee8SDave May   if (n) { *n = ng; }
627dcf43ee8SDave May   PetscFunctionReturn(0);
628dcf43ee8SDave May }
629dcf43ee8SDave May 
630d3a51819SDave May /*@C
6318b8a3813SDave May    DMSwarmRegisterPetscDatatypeField - Register a field to a DMSwarm with a native PETSc data type
632d3a51819SDave May 
633d3a51819SDave May    Collective on DM
634d3a51819SDave May 
635d3a51819SDave May    Input parameters:
63662741f57SDave May +  dm - a DMSwarm
637d3a51819SDave May .  fieldname - the textual name to identify this field
638d3a51819SDave May .  blocksize - the number of each data type
63962741f57SDave May -  type - a valid PETSc data type (PETSC_CHAR, PETSC_SHORT, PETSC_INT, PETSC_FLOAT, PETSC_REAL, PETSC_LONG)
640d3a51819SDave May 
641d3a51819SDave May    Level: beginner
642d3a51819SDave May 
643d3a51819SDave May    Notes:
6448b8a3813SDave May    The textual name for each registered field must be unique.
645d3a51819SDave May 
646d3a51819SDave May .seealso: DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
647d3a51819SDave May @*/
6485f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmRegisterPetscDatatypeField(DM dm,const char fieldname[],PetscInt blocksize,PetscDataType type)
649b62e03f8SDave May {
6502eac95f8SDave May   PetscErrorCode ierr;
651b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
652b62e03f8SDave May   size_t size;
653b62e03f8SDave May 
654521f74f9SMatthew G. Knepley   PetscFunctionBegin;
6555f50eb2eSDave May   if (!swarm->field_registration_initialized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmInitializeFieldRegister() first");
6565f50eb2eSDave May   if (swarm->field_registration_finalized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Cannot register additional fields after calling DMSwarmFinalizeFieldRegister() first");
6575f50eb2eSDave May 
6585f50eb2eSDave May   if (type == PETSC_OBJECT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
6595f50eb2eSDave May   if (type == PETSC_FUNCTION) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
6605f50eb2eSDave May   if (type == PETSC_STRING) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
6615f50eb2eSDave May   if (type == PETSC_STRUCT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
6625f50eb2eSDave May   if (type == PETSC_DATATYPE_UNKNOWN) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
663b62e03f8SDave May 
6642ddcf43eSMatthew G. Knepley   ierr = PetscDataTypeGetSize(type, &size);CHKERRQ(ierr);
665b62e03f8SDave May   /* Load a specific data type into data bucket, specifying textual name and its size in bytes */
66652c3ed93SDave May   ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterPetscDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
66752c3ed93SDave May   {
66852c3ed93SDave May     DataField gfield;
66952c3ed93SDave May 
67052c3ed93SDave May     ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
67152c3ed93SDave May     ierr = DataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
67252c3ed93SDave May   }
673b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = type;
674b62e03f8SDave May   PetscFunctionReturn(0);
675b62e03f8SDave May }
676b62e03f8SDave May 
677d3a51819SDave May /*@C
678d3a51819SDave May    DMSwarmRegisterUserStructField - Register a user defined struct to a DMSwarm
679d3a51819SDave May 
680d3a51819SDave May    Collective on DM
681d3a51819SDave May 
682d3a51819SDave May    Input parameters:
68362741f57SDave May +  dm - a DMSwarm
684d3a51819SDave May .  fieldname - the textual name to identify this field
68562741f57SDave May -  size - the size in bytes of the user struct of each data type
686d3a51819SDave May 
687d3a51819SDave May    Level: beginner
688d3a51819SDave May 
689d3a51819SDave May    Notes:
6908b8a3813SDave May    The textual name for each registered field must be unique.
691d3a51819SDave May 
692d3a51819SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserDatatypeField()
693d3a51819SDave May @*/
6945f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmRegisterUserStructField(DM dm,const char fieldname[],size_t size)
695b62e03f8SDave May {
6962eac95f8SDave May   PetscErrorCode ierr;
697b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
698b62e03f8SDave May 
699521f74f9SMatthew G. Knepley   PetscFunctionBegin;
7002eac95f8SDave May   ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterUserStructField",fieldname,size,NULL);CHKERRQ(ierr);
701b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_STRUCT ;
702b62e03f8SDave May   PetscFunctionReturn(0);
703b62e03f8SDave May }
704b62e03f8SDave May 
705d3a51819SDave May /*@C
706d3a51819SDave May    DMSwarmRegisterUserDatatypeField - Register a user defined data type to a DMSwarm
707d3a51819SDave May 
708d3a51819SDave May    Collective on DM
709d3a51819SDave May 
710d3a51819SDave May    Input parameters:
71162741f57SDave May +  dm - a DMSwarm
712d3a51819SDave May .  fieldname - the textual name to identify this field
713d3a51819SDave May .  size - the size in bytes of the user data type
71462741f57SDave May -  blocksize - the number of each data type
715d3a51819SDave May 
716d3a51819SDave May    Level: beginner
717d3a51819SDave May 
718d3a51819SDave May    Notes:
7198b8a3813SDave May    The textual name for each registered field must be unique.
720d3a51819SDave May 
721d3a51819SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
722d3a51819SDave May @*/
723320740a0SDave May PETSC_EXTERN PetscErrorCode DMSwarmRegisterUserDatatypeField(DM dm,const char fieldname[],size_t size,PetscInt blocksize)
724b62e03f8SDave May {
725b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
7266845f8f5SDave May   PetscErrorCode ierr;
727b62e03f8SDave May 
728521f74f9SMatthew G. Knepley   PetscFunctionBegin;
729320740a0SDave May   ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterUserDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
730320740a0SDave May   {
731320740a0SDave May     DataField gfield;
732320740a0SDave May 
733320740a0SDave May     ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
734320740a0SDave May     ierr = DataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
735320740a0SDave May   }
736b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_DATATYPE_UNKNOWN;
737b62e03f8SDave May   PetscFunctionReturn(0);
738b62e03f8SDave May }
739b62e03f8SDave May 
740d3a51819SDave May /*@C
741d3a51819SDave May    DMSwarmGetField - Get access to the underlying array storing all entries associated with a registered field
742d3a51819SDave May 
743d3a51819SDave May    Not collective
744d3a51819SDave May 
745d3a51819SDave May    Input parameters:
74662741f57SDave May +  dm - a DMSwarm
74762741f57SDave May -  fieldname - the textual name to identify this field
748d3a51819SDave May 
749d3a51819SDave May    Output parameters:
75062741f57SDave May +  blocksize - the number of each data type
751d3a51819SDave May .  type - the data type
75262741f57SDave May -  data - pointer to raw array
753d3a51819SDave May 
754d3a51819SDave May    Level: beginner
755d3a51819SDave May 
756d3a51819SDave May    Notes:
7578b8a3813SDave May    The array must be returned using a matching call to DMSwarmRestoreField().
758d3a51819SDave May 
759d3a51819SDave May .seealso: DMSwarmRestoreField()
760d3a51819SDave May @*/
7615f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmGetField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
762b62e03f8SDave May {
763b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
764b62e03f8SDave May   DataField gfield;
7652eac95f8SDave May   PetscErrorCode ierr;
766b62e03f8SDave May 
767521f74f9SMatthew G. Knepley   PetscFunctionBegin;
7683454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
7692eac95f8SDave May   ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
7706845f8f5SDave May   ierr = DataFieldGetAccess(gfield);CHKERRQ(ierr);
7716845f8f5SDave May   ierr = DataFieldGetEntries(gfield,data);CHKERRQ(ierr);
7721b1ea282SDave May   if (blocksize) {*blocksize = gfield->bs; }
773b5bcf523SDave May   if (type) { *type = gfield->petsc_type; }
774b62e03f8SDave May   PetscFunctionReturn(0);
775b62e03f8SDave May }
776b62e03f8SDave May 
777d3a51819SDave May /*@C
778d3a51819SDave May    DMSwarmRestoreField - Restore access to the underlying array storing all entries associated with a registered field
779d3a51819SDave May 
780d3a51819SDave May    Not collective
781d3a51819SDave May 
782d3a51819SDave May    Input parameters:
78362741f57SDave May +  dm - a DMSwarm
78462741f57SDave May -  fieldname - the textual name to identify this field
785d3a51819SDave May 
786d3a51819SDave May    Output parameters:
78762741f57SDave May +  blocksize - the number of each data type
788d3a51819SDave May .  type - the data type
78962741f57SDave May -  data - pointer to raw array
790d3a51819SDave May 
791d3a51819SDave May    Level: beginner
792d3a51819SDave May 
793d3a51819SDave May    Notes:
7948b8a3813SDave May    The user must call DMSwarmGetField() prior to calling DMSwarmRestoreField().
795d3a51819SDave May 
796d3a51819SDave May .seealso: DMSwarmGetField()
797d3a51819SDave May @*/
7985f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmRestoreField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
799b62e03f8SDave May {
800b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
801b62e03f8SDave May   DataField gfield;
8022eac95f8SDave May   PetscErrorCode ierr;
803b62e03f8SDave May 
804521f74f9SMatthew G. Knepley   PetscFunctionBegin;
8052eac95f8SDave May   ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
8066845f8f5SDave May   ierr = DataFieldRestoreAccess(gfield);CHKERRQ(ierr);
807b62e03f8SDave May   if (data) *data = NULL;
808b62e03f8SDave May   PetscFunctionReturn(0);
809b62e03f8SDave May }
810b62e03f8SDave May 
811d3a51819SDave May /*@C
812d3a51819SDave May    DMSwarmAddPoint - Add space for one new point in the DMSwarm
813d3a51819SDave May 
814d3a51819SDave May    Not collective
815d3a51819SDave May 
816d3a51819SDave May    Input parameter:
817d3a51819SDave May .  dm - a DMSwarm
818d3a51819SDave May 
819d3a51819SDave May    Level: beginner
820d3a51819SDave May 
821d3a51819SDave May    Notes:
8228b8a3813SDave May    The new point will have all fields initialized to zero.
823d3a51819SDave May 
824d3a51819SDave May .seealso: DMSwarmAddNPoints()
825d3a51819SDave May @*/
826cb1d1399SDave May PETSC_EXTERN PetscErrorCode DMSwarmAddPoint(DM dm)
827cb1d1399SDave May {
828cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
829cb1d1399SDave May   PetscErrorCode ierr;
830cb1d1399SDave May 
831521f74f9SMatthew G. Knepley   PetscFunctionBegin;
8323454631fSDave May   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
833f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
834cb1d1399SDave May   ierr = DataBucketAddPoint(swarm->db);CHKERRQ(ierr);
835f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
836cb1d1399SDave May   PetscFunctionReturn(0);
837cb1d1399SDave May }
838cb1d1399SDave May 
839d3a51819SDave May /*@C
840d3a51819SDave May    DMSwarmAddNPoints - Add space for a number of new points in the DMSwarm
841d3a51819SDave May 
842d3a51819SDave May    Not collective
843d3a51819SDave May 
844d3a51819SDave May    Input parameters:
84562741f57SDave May +  dm - a DMSwarm
84662741f57SDave May -  npoints - the number of new points to add
847d3a51819SDave May 
848d3a51819SDave May    Level: beginner
849d3a51819SDave May 
850d3a51819SDave May    Notes:
8518b8a3813SDave May    The new point will have all fields initialized to zero.
852d3a51819SDave May 
853d3a51819SDave May .seealso: DMSwarmAddPoint()
854d3a51819SDave May @*/
855cb1d1399SDave May PETSC_EXTERN PetscErrorCode DMSwarmAddNPoints(DM dm,PetscInt npoints)
856cb1d1399SDave May {
857cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
858cb1d1399SDave May   PetscErrorCode ierr;
859cb1d1399SDave May   PetscInt nlocal;
860cb1d1399SDave May 
861521f74f9SMatthew G. Knepley   PetscFunctionBegin;
862f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
863cb1d1399SDave May   ierr = DataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
864cb1d1399SDave May   nlocal = nlocal + npoints;
86565141ba8SDave May   ierr = DataBucketSetSizes(swarm->db,nlocal,DATA_BUCKET_BUFFER_DEFAULT);CHKERRQ(ierr);
866f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
867cb1d1399SDave May   PetscFunctionReturn(0);
868cb1d1399SDave May }
869cb1d1399SDave May 
870d3a51819SDave May /*@C
871d3a51819SDave May    DMSwarmRemovePoint - Remove the last point from the DMSwarm
872d3a51819SDave May 
873d3a51819SDave May    Not collective
874d3a51819SDave May 
875d3a51819SDave May    Input parameter:
876d3a51819SDave May .  dm - a DMSwarm
877d3a51819SDave May 
878d3a51819SDave May    Level: beginner
879d3a51819SDave May 
880d3a51819SDave May .seealso: DMSwarmRemovePointAtIndex()
881d3a51819SDave May @*/
882cb1d1399SDave May PETSC_EXTERN PetscErrorCode DMSwarmRemovePoint(DM dm)
883cb1d1399SDave May {
884cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
885cb1d1399SDave May   PetscErrorCode ierr;
886cb1d1399SDave May 
887521f74f9SMatthew G. Knepley   PetscFunctionBegin;
888f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
889cb1d1399SDave May   ierr = DataBucketRemovePoint(swarm->db);CHKERRQ(ierr);
890f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
891cb1d1399SDave May   PetscFunctionReturn(0);
892cb1d1399SDave May }
893cb1d1399SDave May 
894d3a51819SDave May /*@C
895d3a51819SDave May    DMSwarmRemovePointAtIndex - Removes a specific point from the DMSwarm
896d3a51819SDave May 
897d3a51819SDave May    Not collective
898d3a51819SDave May 
899d3a51819SDave May    Input parameters:
90062741f57SDave May +  dm - a DMSwarm
90162741f57SDave May -  idx - index of point to remove
902d3a51819SDave May 
903d3a51819SDave May    Level: beginner
904d3a51819SDave May 
905d3a51819SDave May .seealso: DMSwarmRemovePoint()
906d3a51819SDave May @*/
907cb1d1399SDave May PETSC_EXTERN PetscErrorCode DMSwarmRemovePointAtIndex(DM dm,PetscInt idx)
908cb1d1399SDave May {
909cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
910cb1d1399SDave May   PetscErrorCode ierr;
911cb1d1399SDave May 
912521f74f9SMatthew G. Knepley   PetscFunctionBegin;
913f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
914cb1d1399SDave May   ierr = DataBucketRemovePointAtIndex(swarm->db,idx);CHKERRQ(ierr);
915f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
916cb1d1399SDave May   PetscFunctionReturn(0);
917cb1d1399SDave May }
918b62e03f8SDave May 
919ba4fc9c6SDave May /*@C
920ba4fc9c6SDave May    DMSwarmCopyPoint - Copy point pj to point pi in the DMSwarm
921ba4fc9c6SDave May 
922ba4fc9c6SDave May    Not collective
923ba4fc9c6SDave May 
924ba4fc9c6SDave May    Input parameters:
925ba4fc9c6SDave May +  dm - a DMSwarm
926ba4fc9c6SDave May .  pi - the index of the point to copy
927ba4fc9c6SDave May -  pj - the point index where the copy should be located
928ba4fc9c6SDave May 
929ba4fc9c6SDave May  Level: beginner
930ba4fc9c6SDave May 
931ba4fc9c6SDave May .seealso: DMSwarmRemovePoint()
932ba4fc9c6SDave May @*/
933ba4fc9c6SDave May PETSC_EXTERN PetscErrorCode DMSwarmCopyPoint(DM dm,PetscInt pi,PetscInt pj)
934ba4fc9c6SDave May {
935ba4fc9c6SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
936ba4fc9c6SDave May   PetscErrorCode ierr;
937ba4fc9c6SDave May 
938ba4fc9c6SDave May   PetscFunctionBegin;
939ba4fc9c6SDave May   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
940ba4fc9c6SDave May   ierr = DataBucketCopyPoint(swarm->db,pi,swarm->db,pj);CHKERRQ(ierr);
941ba4fc9c6SDave May   PetscFunctionReturn(0);
942ba4fc9c6SDave May }
943ba4fc9c6SDave May 
944095059a4SDave May PetscErrorCode DMSwarmMigrate_Basic(DM dm,PetscBool remove_sent_points)
9453454631fSDave May {
946dcf43ee8SDave May   PetscErrorCode ierr;
947521f74f9SMatthew G. Knepley 
948521f74f9SMatthew G. Knepley   PetscFunctionBegin;
949dcf43ee8SDave May   ierr = DMSwarmMigrate_Push_Basic(dm,remove_sent_points);CHKERRQ(ierr);
9503454631fSDave May   PetscFunctionReturn(0);
9513454631fSDave May }
9523454631fSDave May 
953d3a51819SDave May /*@C
954d3a51819SDave May    DMSwarmMigrate - Relocates points defined in the DMSwarm to other MPI-ranks
955d3a51819SDave May 
956d3a51819SDave May    Collective on DM
957d3a51819SDave May 
958d3a51819SDave May    Input parameters:
95962741f57SDave May +  dm - the DMSwarm
96062741f57SDave May -  remove_sent_points - flag indicating if sent points should be removed from the current MPI-rank
961d3a51819SDave May 
962d3a51819SDave May    Notes:
9638b8a3813SDave May    The DM will be modified to accomodate received points.
9648b8a3813SDave May    If remove_sent_points = PETSC_TRUE, any points that were sent will be removed from the DM.
9658b8a3813SDave May    Different styles of migration are supported. See DMSwarmSetMigrateType().
966d3a51819SDave May 
967d3a51819SDave May    Level: advanced
968d3a51819SDave May 
969d3a51819SDave May .seealso: DMSwarmSetMigrateType()
970d3a51819SDave May @*/
971095059a4SDave May PETSC_EXTERN PetscErrorCode DMSwarmMigrate(DM dm,PetscBool remove_sent_points)
9723454631fSDave May {
973f0cdbbbaSDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
9743454631fSDave May   PetscErrorCode ierr;
975f0cdbbbaSDave May 
976521f74f9SMatthew G. Knepley   PetscFunctionBegin;
977ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
978f0cdbbbaSDave May   switch (swarm->migrate_type) {
979f0cdbbbaSDave May     case DMSWARM_MIGRATE_BASIC:
980095059a4SDave May       ierr = DMSwarmMigrate_Basic(dm,remove_sent_points);CHKERRQ(ierr);
981f0cdbbbaSDave May       break;
982f0cdbbbaSDave May     case DMSWARM_MIGRATE_DMCELLNSCATTER:
983f0cdbbbaSDave May       ierr = DMSwarmMigrate_CellDMScatter(dm,remove_sent_points);CHKERRQ(ierr);
984f0cdbbbaSDave May       break;
985f0cdbbbaSDave May     case DMSWARM_MIGRATE_DMCELLEXACT:
986f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_DMCELLEXACT not implemented");
987521f74f9SMatthew G. Knepley       /*ierr = DMSwarmMigrate_CellDMExact(dm,remove_sent_points);CHKERRQ(ierr);*/
988f0cdbbbaSDave May       break;
989f0cdbbbaSDave May     case DMSWARM_MIGRATE_USER:
990f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_USER not implemented");
991521f74f9SMatthew G. Knepley       /*ierr = swarm->migrate(dm,remove_sent_points);CHKERRQ(ierr);*/
992f0cdbbbaSDave May       break;
993f0cdbbbaSDave May     default:
994f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE type unknown");
995f0cdbbbaSDave May       break;
996f0cdbbbaSDave May   }
997ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
9983454631fSDave May   PetscFunctionReturn(0);
9993454631fSDave May }
10003454631fSDave May 
1001f0cdbbbaSDave May PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm,PetscInt *globalsize);
1002f0cdbbbaSDave May 
1003d3a51819SDave May /*
1004d3a51819SDave May  DMSwarmCollectViewCreate
1005d3a51819SDave May 
1006d3a51819SDave May  * Applies a collection method and gathers point neighbour points into dm
1007d3a51819SDave May 
1008d3a51819SDave May  Notes:
10098b8a3813SDave May  Users should call DMSwarmCollectViewDestroy() after
1010d3a51819SDave May  they have finished computations associated with the collected points
1011d3a51819SDave May */
1012d3a51819SDave May 
1013d3a51819SDave May /*@C
1014d3a51819SDave May    DMSwarmCollectViewCreate - Applies a collection method and gathers points
1015d3a51819SDave May    in neighbour MPI-ranks into the DMSwarm
1016d3a51819SDave May 
1017d3a51819SDave May    Collective on DM
1018d3a51819SDave May 
1019d3a51819SDave May    Input parameter:
1020d3a51819SDave May .  dm - the DMSwarm
1021d3a51819SDave May 
1022d3a51819SDave May    Notes:
1023d3a51819SDave May    Users should call DMSwarmCollectViewDestroy() after
1024d3a51819SDave May    they have finished computations associated with the collected points
10258b8a3813SDave May    Different collect methods are supported. See DMSwarmSetCollectType().
1026d3a51819SDave May 
1027d3a51819SDave May    Level: advanced
1028d3a51819SDave May 
1029d3a51819SDave May .seealso: DMSwarmCollectViewDestroy(), DMSwarmSetCollectType()
1030d3a51819SDave May @*/
1031fe39f135SDave May PETSC_EXTERN PetscErrorCode DMSwarmCollectViewCreate(DM dm)
10322712d1f2SDave May {
10332712d1f2SDave May   PetscErrorCode ierr;
10342712d1f2SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
10352712d1f2SDave May   PetscInt ng;
10362712d1f2SDave May 
1037521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1038480eef7bSDave May   if (swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView currently active");
1039480eef7bSDave May   ierr = DMSwarmGetLocalSize(dm,&ng);CHKERRQ(ierr);
1040480eef7bSDave May   switch (swarm->collect_type) {
1041f0cdbbbaSDave May 
1042480eef7bSDave May     case DMSWARM_COLLECT_BASIC:
10432712d1f2SDave May       ierr = DMSwarmMigrate_GlobalToLocal_Basic(dm,&ng);CHKERRQ(ierr);
1044480eef7bSDave May       break;
1045480eef7bSDave May     case DMSWARM_COLLECT_DMDABOUNDINGBOX:
1046f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_DMDABOUNDINGBOX not implemented");
1047521f74f9SMatthew G. Knepley       /*ierr = DMSwarmCollect_DMDABoundingBox(dm,&ng);CHKERRQ(ierr);*/
1048480eef7bSDave May       break;
1049480eef7bSDave May     case DMSWARM_COLLECT_GENERAL:
1050f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_GENERAL not implemented");
1051521f74f9SMatthew G. Knepley       /*ierr = DMSwarmCollect_General(dm,..,,..,&ng);CHKERRQ(ierr);*/
1052480eef7bSDave May       break;
1053480eef7bSDave May     default:
1054f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT type unknown");
1055480eef7bSDave May       break;
1056480eef7bSDave May   }
1057480eef7bSDave May   swarm->collect_view_active = PETSC_TRUE;
1058480eef7bSDave May   swarm->collect_view_reset_nlocal = ng;
10592712d1f2SDave May   PetscFunctionReturn(0);
10602712d1f2SDave May }
10612712d1f2SDave May 
1062d3a51819SDave May /*@C
1063d3a51819SDave May    DMSwarmCollectViewDestroy - Resets the DMSwarm to the size prior to calling DMSwarmCollectViewCreate()
1064d3a51819SDave May 
1065d3a51819SDave May    Collective on DM
1066d3a51819SDave May 
1067d3a51819SDave May    Input parameters:
1068d3a51819SDave May .  dm - the DMSwarm
1069d3a51819SDave May 
1070d3a51819SDave May    Notes:
1071d3a51819SDave May    Users should call DMSwarmCollectViewCreate() before this function is called.
1072d3a51819SDave May 
1073d3a51819SDave May    Level: advanced
1074d3a51819SDave May 
1075d3a51819SDave May .seealso: DMSwarmCollectViewCreate(), DMSwarmSetCollectType()
1076d3a51819SDave May @*/
1077fe39f135SDave May PETSC_EXTERN PetscErrorCode DMSwarmCollectViewDestroy(DM dm)
10782712d1f2SDave May {
10792712d1f2SDave May   PetscErrorCode ierr;
10802712d1f2SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
10812712d1f2SDave May 
1082521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1083480eef7bSDave May   if (!swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView is currently not active");
1084480eef7bSDave May   ierr = DMSwarmSetLocalSizes(dm,swarm->collect_view_reset_nlocal,-1);CHKERRQ(ierr);
1085480eef7bSDave May   swarm->collect_view_active = PETSC_FALSE;
10862712d1f2SDave May   PetscFunctionReturn(0);
10872712d1f2SDave May }
10883454631fSDave May 
1089f0cdbbbaSDave May PetscErrorCode DMSwarmSetUpPIC(DM dm)
1090f0cdbbbaSDave May {
1091f0cdbbbaSDave May   PetscInt dim;
1092f0cdbbbaSDave May   PetscErrorCode ierr;
1093f0cdbbbaSDave May 
1094521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1095f0cdbbbaSDave May   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
1096f0cdbbbaSDave May   if (dim < 1) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
1097f0cdbbbaSDave May   if (dim > 3) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
1098f0cdbbbaSDave May   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_coor,dim,PETSC_DOUBLE);CHKERRQ(ierr);
1099e2d107dbSDave May   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_cellid,1,PETSC_INT);CHKERRQ(ierr);
1100f0cdbbbaSDave May   PetscFunctionReturn(0);
1101f0cdbbbaSDave May }
1102f0cdbbbaSDave May 
1103d3a51819SDave May /*@C
1104d3a51819SDave May    DMSwarmSetType - Set particular flavor of DMSwarm
1105d3a51819SDave May 
1106d3a51819SDave May    Collective on DM
1107d3a51819SDave May 
1108d3a51819SDave May    Input parameters:
110962741f57SDave May +  dm - the DMSwarm
111062741f57SDave May -  stype - the DMSwarm type (e.g. DMSWARM_PIC)
1111d3a51819SDave May 
1112d3a51819SDave May    Level: advanced
1113d3a51819SDave May 
1114d3a51819SDave May .seealso: DMSwarmSetMigrateType(), DMSwarmSetCollectType()
1115d3a51819SDave May @*/
1116f0cdbbbaSDave May PETSC_EXTERN PetscErrorCode DMSwarmSetType(DM dm,DMSwarmType stype)
1117f0cdbbbaSDave May {
1118f0cdbbbaSDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
1119f0cdbbbaSDave May   PetscErrorCode ierr;
1120f0cdbbbaSDave May 
1121521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1122f0cdbbbaSDave May   swarm->swarm_type = stype;
1123f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
1124f0cdbbbaSDave May     ierr = DMSwarmSetUpPIC(dm);CHKERRQ(ierr);
1125f0cdbbbaSDave May   }
1126f0cdbbbaSDave May   PetscFunctionReturn(0);
1127f0cdbbbaSDave May }
1128f0cdbbbaSDave May 
11293454631fSDave May PetscErrorCode DMSetup_Swarm(DM dm)
11303454631fSDave May {
11313454631fSDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
11323454631fSDave May   PetscErrorCode ierr;
11333454631fSDave May   PetscMPIInt rank;
11343454631fSDave May   PetscInt p,npoints,*rankval;
11353454631fSDave May 
1136521f74f9SMatthew G. Knepley   PetscFunctionBegin;
11373454631fSDave May   if (swarm->issetup) PetscFunctionReturn(0);
11383454631fSDave May 
11393454631fSDave May   swarm->issetup = PETSC_TRUE;
11403454631fSDave May 
1141f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
1142f0cdbbbaSDave May     /* check dmcell exists */
1143f0cdbbbaSDave May     if (!swarm->dmcell) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires you call DMSwarmSetCellDM");
1144f0cdbbbaSDave May 
1145f0cdbbbaSDave May     if (swarm->dmcell->ops->locatepointssubdomain) {
1146f0cdbbbaSDave May       /* check methods exists for exact ownership identificiation */
1147521f74f9SMatthew G. Knepley       ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->ops->LocatePointsSubdomain\n");CHKERRQ(ierr);
1148f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLEXACT;
1149f0cdbbbaSDave May     } else {
1150f0cdbbbaSDave May       /* check methods exist for point location AND rank neighbor identification */
1151f0cdbbbaSDave May       if (swarm->dmcell->ops->locatepoints) {
1152521f74f9SMatthew G. Knepley         ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->LocatePoints\n");CHKERRQ(ierr);
1153f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->locatepoints be defined");
1154f0cdbbbaSDave May 
1155f0cdbbbaSDave May       if (swarm->dmcell->ops->getneighbors) {
1156521f74f9SMatthew G. Knepley         ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->GetNeigbors\n");CHKERRQ(ierr);
1157f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->getneighbors be defined");
1158f0cdbbbaSDave May 
1159f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLNSCATTER;
1160f0cdbbbaSDave May     }
1161f0cdbbbaSDave May   }
1162f0cdbbbaSDave May 
1163f0cdbbbaSDave May   ierr = DMSwarmFinalizeFieldRegister(dm);CHKERRQ(ierr);
1164f0cdbbbaSDave May 
11653454631fSDave May   /* check some fields were registered */
11663454631fSDave May   if (swarm->db->nfields <= 2) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"At least one field user must be registered via DMSwarmRegisterXXX()");
11673454631fSDave May 
11683454631fSDave May   /* check local sizes were set */
11693454631fSDave May   if (swarm->db->L == -1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Local sizes must be set via DMSwarmSetLocalSizes()");
11703454631fSDave May 
11713454631fSDave May   /* initialize values in pid and rank placeholders */
11723454631fSDave May   /* TODO: [pid - use MPI_Scan] */
11733454631fSDave May   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
11743454631fSDave May   ierr = DataBucketGetSizes(swarm->db,&npoints,NULL,NULL);CHKERRQ(ierr);
1175f0cdbbbaSDave May   ierr = DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
11763454631fSDave May   for (p=0; p<npoints; p++) {
11773454631fSDave May     rankval[p] = (PetscInt)rank;
11783454631fSDave May   }
1179f0cdbbbaSDave May   ierr = DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
11803454631fSDave May   PetscFunctionReturn(0);
11813454631fSDave May }
11823454631fSDave May 
1183dc5f5ce9SDave May extern PetscErrorCode DMSwarmSortDestroy(DMSwarmSort *_ctx);
1184dc5f5ce9SDave May 
118557795646SDave May PetscErrorCode DMDestroy_Swarm(DM dm)
118657795646SDave May {
118757795646SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
118857795646SDave May   PetscErrorCode ierr;
118957795646SDave May 
119057795646SDave May   PetscFunctionBegin;
11916845f8f5SDave May   ierr = DataBucketDestroy(&swarm->db);CHKERRQ(ierr);
1192dc5f5ce9SDave May   if (swarm->sort_context) {
1193dc5f5ce9SDave May     ierr = DMSwarmSortDestroy(&swarm->sort_context);CHKERRQ(ierr);
1194dc5f5ce9SDave May   }
119557795646SDave May   ierr = PetscFree(swarm);CHKERRQ(ierr);
119657795646SDave May   PetscFunctionReturn(0);
119757795646SDave May }
119857795646SDave May 
1199a9ee3421SMatthew G. Knepley PetscErrorCode DMSwarmView_Draw(DM dm, PetscViewer viewer)
1200a9ee3421SMatthew G. Knepley {
1201a9ee3421SMatthew G. Knepley   DM             cdm;
1202a9ee3421SMatthew G. Knepley   PetscDraw      draw;
1203a9ee3421SMatthew G. Knepley   PetscReal     *coords, oldPause;
1204a9ee3421SMatthew G. Knepley   PetscInt       Np, p, bs;
1205a9ee3421SMatthew G. Knepley   PetscErrorCode ierr;
1206a9ee3421SMatthew G. Knepley 
1207a9ee3421SMatthew G. Knepley   PetscFunctionBegin;
1208a9ee3421SMatthew G. Knepley   ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr);
1209a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetCellDM(dm, &cdm);CHKERRQ(ierr);
1210a9ee3421SMatthew G. Knepley   ierr = PetscDrawGetPause(draw, &oldPause);CHKERRQ(ierr);
1211a9ee3421SMatthew G. Knepley   ierr = PetscDrawSetPause(draw, 0.0);CHKERRQ(ierr);
1212a9ee3421SMatthew G. Knepley   ierr = DMView(cdm, viewer);CHKERRQ(ierr);
1213a9ee3421SMatthew G. Knepley   ierr = PetscDrawSetPause(draw, oldPause);CHKERRQ(ierr);
1214a9ee3421SMatthew G. Knepley 
1215a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetLocalSize(dm, &Np);CHKERRQ(ierr);
1216a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1217a9ee3421SMatthew G. Knepley   for (p = 0; p < Np; ++p) {
1218a9ee3421SMatthew G. Knepley     const PetscInt i = p*bs;
1219a9ee3421SMatthew G. Knepley 
1220a9ee3421SMatthew G. Knepley     ierr = PetscDrawEllipse(draw, coords[i], coords[i+1], 0.01, 0.01, PETSC_DRAW_BLUE);CHKERRQ(ierr);
1221a9ee3421SMatthew G. Knepley   }
1222a9ee3421SMatthew G. Knepley   ierr = DMSwarmRestoreField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1223a9ee3421SMatthew G. Knepley   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
1224a9ee3421SMatthew G. Knepley   ierr = PetscDrawPause(draw);CHKERRQ(ierr);
1225a9ee3421SMatthew G. Knepley   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
1226a9ee3421SMatthew G. Knepley   PetscFunctionReturn(0);
1227a9ee3421SMatthew G. Knepley }
1228a9ee3421SMatthew G. Knepley 
12295f50eb2eSDave May PetscErrorCode DMView_Swarm(DM dm, PetscViewer viewer)
12305f50eb2eSDave May {
12315f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
1232a9ee3421SMatthew G. Knepley   PetscBool      iascii,ibinary,ishdf5,isvtk,isdraw;
12335f50eb2eSDave May   PetscErrorCode ierr;
12345f50eb2eSDave May 
12355f50eb2eSDave May   PetscFunctionBegin;
12365f50eb2eSDave May   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
12375f50eb2eSDave May   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
12385f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
12395f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY,&ibinary);CHKERRQ(ierr);
12405f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK,   &isvtk);CHKERRQ(ierr);
12415f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
1242a9ee3421SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW,  &isdraw);CHKERRQ(ierr);
12435f50eb2eSDave May   if (iascii) {
12446845f8f5SDave May     ierr = DataBucketView(PetscObjectComm((PetscObject)dm),swarm->db,NULL,DATABUCKET_VIEW_STDOUT);CHKERRQ(ierr);
12455f50eb2eSDave May   } else if (ibinary) {
1246a9ee3421SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO Binary support");
12475f50eb2eSDave May   } else if (ishdf5) {
12485f50eb2eSDave May #if defined(PETSC_HAVE_HDF5)
12495f50eb2eSDave May     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO HDF5 support");
12505f50eb2eSDave May #else
12515f50eb2eSDave May     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"HDF5 not supported. Please reconfigure using --download-hdf5");
12525f50eb2eSDave May #endif
12535f50eb2eSDave May   } else if (isvtk) {
12545f50eb2eSDave May     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO VTK support");
1255a9ee3421SMatthew G. Knepley   } else if (isdraw) {
1256a9ee3421SMatthew G. Knepley     ierr = DMSwarmView_Draw(dm, viewer);CHKERRQ(ierr);
12575f50eb2eSDave May   }
12585f50eb2eSDave May   PetscFunctionReturn(0);
12595f50eb2eSDave May }
12605f50eb2eSDave May 
1261d3a51819SDave May /*MC
1262d3a51819SDave May 
1263d3a51819SDave May  DMSWARM = "swarm" - A DM object used to represent arrays of data (fields) of arbitrary data type.
126462741f57SDave May  This implementation was designed for particle methods in which the underlying
1265d3a51819SDave May  data required to be represented is both (i) dynamic in length, (ii) and of arbitrary data type.
1266d3a51819SDave May 
126762741f57SDave May  User data can be represented by DMSwarm through a registering "fields".
126862741f57SDave May  To register a field, the user must provide;
126962741f57SDave May  (a) a unique name;
127062741f57SDave May  (b) the data type (or size in bytes);
127162741f57SDave May  (c) the block size of the data.
1272d3a51819SDave May 
1273d3a51819SDave May  For example, suppose the application requires a unique id, energy, momentum and density to be stored
127462741f57SDave May  on a set of of particles. Then the following code could be used
1275d3a51819SDave May 
127662741f57SDave May $    DMSwarmInitializeFieldRegister(dm)
127762741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"uid",1,PETSC_LONG);
127862741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"energy",1,PETSC_REAL);
127962741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"momentum",3,PETSC_REAL);
128062741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"density",1,PETSC_FLOAT);
128162741f57SDave May $    DMSwarmFinalizeFieldRegister(dm)
1282d3a51819SDave May 
1283d3a51819SDave May  The fields represented by DMSwarm are dynamic and can be re-sized at any time.
128462741f57SDave May  The only restriction imposed by DMSwarm is that all fields contain the same number of points.
1285d3a51819SDave May 
1286d3a51819SDave May  To support particle methods, "migration" techniques are provided. These methods migrate data
1287d3a51819SDave May  between MPI-ranks.
1288d3a51819SDave May 
1289d3a51819SDave May  DMSwarm supports the methods DMCreateGlobalVector() and DMCreateLocalVector().
1290d3a51819SDave May  As a DMSwarm may internally define and store values of different data types,
129162741f57SDave May  before calling DMCreateGlobalVector() or DMCreateLocalVector(), the user must inform DMSwarm which
1292d3a51819SDave May  fields should be used to define a Vec object via
1293d3a51819SDave May    DMSwarmVectorDefineField()
1294d3a51819SDave May  The specified field can can changed be changed at any time - thereby permitting vectors
1295d3a51819SDave May  compatable with different fields to be created.
1296d3a51819SDave May 
129762741f57SDave May  A dual representation of fields in the DMSwarm and a Vec object is permitted via
1298d3a51819SDave May    DMSwarmCreateGlobalVectorFromField()
1299d3a51819SDave May  Here the data defining the field in the DMSwarm is shared with a Vec.
1300d3a51819SDave May  This is inherently unsafe if you alter the size of the field at any time between
1301d3a51819SDave May  calls to DMSwarmCreateGlobalVectorFromField() and DMSwarmDestroyGlobalVectorFromField().
1302cc651181SDave May  If the local size of the DMSwarm does not match the local size of the global vector
1303cc651181SDave May  when DMSwarmDestroyGlobalVectorFromField() is called, an error is thrown.
1304d3a51819SDave May 
130562741f57SDave May  Additional high-level support is provided for Particle-In-Cell methods.
130662741f57SDave May  Please refer to the man page for DMSwarmSetType().
130762741f57SDave May 
1308d3a51819SDave May  Level: beginner
1309d3a51819SDave May 
1310d3a51819SDave May .seealso: DMType, DMCreate(), DMSetType()
1311d3a51819SDave May M*/
131257795646SDave May PETSC_EXTERN PetscErrorCode DMCreate_Swarm(DM dm)
131357795646SDave May {
131457795646SDave May   DM_Swarm      *swarm;
131557795646SDave May   PetscErrorCode ierr;
131657795646SDave May 
131757795646SDave May   PetscFunctionBegin;
131857795646SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
131957795646SDave May   ierr     = PetscNewLog(dm,&swarm);CHKERRQ(ierr);
1320f0cdbbbaSDave May   dm->data = swarm;
132157795646SDave May 
13226845f8f5SDave May   ierr = DataBucketCreate(&swarm->db);CHKERRQ(ierr);
1323f0cdbbbaSDave May   ierr = DMSwarmInitializeFieldRegister(dm);CHKERRQ(ierr);
1324f0cdbbbaSDave May 
1325b5bcf523SDave May   swarm->vec_field_set = PETSC_FALSE;
13263454631fSDave May   swarm->issetup = PETSC_FALSE;
1327480eef7bSDave May   swarm->swarm_type = DMSWARM_BASIC;
1328480eef7bSDave May   swarm->migrate_type = DMSWARM_MIGRATE_BASIC;
1329480eef7bSDave May   swarm->collect_type = DMSWARM_COLLECT_BASIC;
133040c453e9SDave May   swarm->migrate_error_on_missing_point = PETSC_FALSE;
1331b62e03f8SDave May 
1332f0cdbbbaSDave May   swarm->dmcell = NULL;
1333f0cdbbbaSDave May   swarm->collect_view_active = PETSC_FALSE;
1334f0cdbbbaSDave May   swarm->collect_view_reset_nlocal = -1;
133557795646SDave May 
1336f0cdbbbaSDave May   dm->dim  = 0;
13375f50eb2eSDave May   dm->ops->view                            = DMView_Swarm;
133857795646SDave May   dm->ops->load                            = NULL;
133957795646SDave May   dm->ops->setfromoptions                  = NULL;
134057795646SDave May   dm->ops->clone                           = NULL;
13413454631fSDave May   dm->ops->setup                           = DMSetup_Swarm;
134257795646SDave May   dm->ops->createdefaultsection            = NULL;
134357795646SDave May   dm->ops->createdefaultconstraints        = NULL;
1344b5bcf523SDave May   dm->ops->createglobalvector              = DMCreateGlobalVector_Swarm;
1345b5bcf523SDave May   dm->ops->createlocalvector               = DMCreateLocalVector_Swarm;
134657795646SDave May   dm->ops->getlocaltoglobalmapping         = NULL;
134757795646SDave May   dm->ops->createfieldis                   = NULL;
134857795646SDave May   dm->ops->createcoordinatedm              = NULL;
134957795646SDave May   dm->ops->getcoloring                     = NULL;
135057795646SDave May   dm->ops->creatematrix                    = NULL;
135157795646SDave May   dm->ops->createinterpolation             = NULL;
135257795646SDave May   dm->ops->getaggregates                   = NULL;
135357795646SDave May   dm->ops->getinjection                    = NULL;
135483c47955SMatthew G. Knepley   dm->ops->createmassmatrix                = DMCreateMassMatrix_Swarm;
135557795646SDave May   dm->ops->refine                          = NULL;
135657795646SDave May   dm->ops->coarsen                         = NULL;
135757795646SDave May   dm->ops->refinehierarchy                 = NULL;
135857795646SDave May   dm->ops->coarsenhierarchy                = NULL;
135957795646SDave May   dm->ops->globaltolocalbegin              = NULL;
136057795646SDave May   dm->ops->globaltolocalend                = NULL;
136157795646SDave May   dm->ops->localtoglobalbegin              = NULL;
136257795646SDave May   dm->ops->localtoglobalend                = NULL;
136357795646SDave May   dm->ops->destroy                         = DMDestroy_Swarm;
136457795646SDave May   dm->ops->createsubdm                     = NULL;
136557795646SDave May   dm->ops->getdimpoints                    = NULL;
136657795646SDave May   dm->ops->locatepoints                    = NULL;
136757795646SDave May   PetscFunctionReturn(0);
136857795646SDave May }
1369