xref: /petsc/src/dm/impls/swarm/swarm.c (revision e7af74c87aad982eb9733301f337f13b0ebfccb3)
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:
36*e7af74c8SDave May 
3762741f57SDave May    The field with name fieldname must be defined as having a data type of PetscScalar.
38*e7af74c8SDave 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); }
546845f8f5SDave May   ierr = DataBucketGetSizes(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;
116fb1bcc12SMatthew G. Knepley   DataField      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 */
126fb1bcc12SMatthew G. Knepley   ierr = DataBucketGetDataFieldByName(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);
131fb1bcc12SMatthew G. Knepley   ierr = DataFieldRestoreAccess(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];
143fb1bcc12SMatthew G. Knepley   PetscMPIInt    commsize;
144fb1bcc12SMatthew G. Knepley   PetscErrorCode ierr;
145fb1bcc12SMatthew G. Knepley 
146fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
147fb1bcc12SMatthew G. Knepley   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
148fb1bcc12SMatthew G. Knepley   ierr = DataBucketGetSizes(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 
152fb1bcc12SMatthew G. Knepley   ierr = MPI_Comm_size(comm, &commsize);CHKERRQ(ierr);
153fb1bcc12SMatthew G. Knepley   if (commsize == 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;
17283c47955SMatthew G. Knepley   PetscHashJK    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);
20383c47955SMatthew G. Knepley   ierr = PetscHashJKCreate(&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       {
22683c47955SMatthew G. Knepley         PetscHashJKKey  key;
22783c47955SMatthew G. Knepley         PetscHashJKIter missing, iter;
22883c47955SMatthew G. Knepley 
22983c47955SMatthew G. Knepley         for (i = 0; i < numFIndices; ++i) {
23083c47955SMatthew G. Knepley           key.j = findices[i];
23183c47955SMatthew G. Knepley           if (key.j >= 0) {
23283c47955SMatthew G. Knepley             /* Get indices for coarse elements */
23383c47955SMatthew G. Knepley             for (c = 0; c < numCIndices; ++c) {
23483c47955SMatthew G. Knepley               key.k = cindices[c];
23583c47955SMatthew G. Knepley               if (key.k < 0) continue;
23683c47955SMatthew G. Knepley               ierr = PetscHashJKPut(ht, key, &missing, &iter);CHKERRQ(ierr);
23783c47955SMatthew G. Knepley               if (missing) {
23883c47955SMatthew G. Knepley                 ierr = PetscHashJKSet(ht, iter, 1);CHKERRQ(ierr);
2394f482ee1SMatthew G. Knepley                 if ((size == 1) || ((key.k >= rStart) && (key.k < rEnd))) ++dnz[key.j-rStart];
24083c47955SMatthew G. Knepley                 else                                                      ++onz[key.j-rStart];
24183c47955SMatthew G. Knepley               }
24283c47955SMatthew G. Knepley             }
243fc7c92abSMatthew G. Knepley           }
244fc7c92abSMatthew G. Knepley         }
24583c47955SMatthew G. Knepley         ierr = PetscFree(cindices);CHKERRQ(ierr);
24683c47955SMatthew G. Knepley       }
24783c47955SMatthew G. Knepley       ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
24883c47955SMatthew G. Knepley     }
24983c47955SMatthew G. Knepley   }
25083c47955SMatthew G. Knepley   ierr = PetscHashJKDestroy(&ht);CHKERRQ(ierr);
25183c47955SMatthew G. Knepley   ierr = MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL);CHKERRQ(ierr);
25283c47955SMatthew G. Knepley   ierr = MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
25383c47955SMatthew G. Knepley   ierr = PetscFree2(dnz,onz);CHKERRQ(ierr);
254fc7c92abSMatthew G. Knepley   ierr = PetscMalloc1(maxC, &elemMat);CHKERRQ(ierr);
25583c47955SMatthew G. Knepley   for (field = 0; field < Nf; ++field) {
25683c47955SMatthew G. Knepley     PetscObject      obj;
25783c47955SMatthew G. Knepley     PetscQuadrature  quad;
25883c47955SMatthew G. Knepley     PetscReal       *Bfine;
25983c47955SMatthew G. Knepley     const PetscReal *qweights;
26083c47955SMatthew G. Knepley     PetscInt         Nq, Nc, i;
26183c47955SMatthew G. Knepley 
26283c47955SMatthew G. Knepley     ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr);
26383c47955SMatthew G. Knepley     ierr = PetscFEGetDefaultTabulation((PetscFE) obj, &Bfine, NULL, NULL);CHKERRQ(ierr);
26483c47955SMatthew G. Knepley     ierr = PetscFEGetQuadrature((PetscFE) obj, &quad);CHKERRQ(ierr);
26583c47955SMatthew G. Knepley     ierr = PetscQuadratureGetData(quad, NULL, &Nc, &Nq, NULL, &qweights);CHKERRQ(ierr);
26683c47955SMatthew G. Knepley     /* For each fine grid cell */
26783c47955SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
26883c47955SMatthew G. Knepley       PetscInt           Np, c, j;
26983c47955SMatthew G. Knepley       PetscInt          *findices,   *cindices;
27083c47955SMatthew G. Knepley       PetscInt           numFIndices, numCIndices;
27183c47955SMatthew G. Knepley 
27283c47955SMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr);
27383c47955SMatthew G. Knepley       ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
27483c47955SMatthew G. Knepley       ierr = DMSwarmSortGetNumberOfPointsPerCell(dmc, cell, &Np);CHKERRQ(ierr);
275e8291c10SMatthew G. Knepley       if (Np != Nq) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Not all closure points located %D != %D", Np, Nq);
27683c47955SMatthew G. Knepley       ierr = DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices);CHKERRQ(ierr);
27783c47955SMatthew G. Knepley       /* Get elemMat entries by multiplying by weight */
27883c47955SMatthew G. Knepley       for (i = 0; i < numFIndices; ++i) {
27983c47955SMatthew G. Knepley         ierr = PetscMemzero(elemMat, numCIndices * sizeof(PetscScalar));CHKERRQ(ierr);
28083c47955SMatthew G. Knepley         for (j = 0; j < numCIndices; ++j) {
28183c47955SMatthew G. Knepley           for (c = 0; c < Nc; ++c) elemMat[j] += Bfine[(j*numFIndices + i)*Nc + c]*qweights[j*Nc + c]*detJ;
28283c47955SMatthew G. Knepley         }
28383c47955SMatthew G. Knepley         /* Update interpolator */
28483c47955SMatthew G. Knepley         if (0) {ierr = DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat);CHKERRQ(ierr);}
28583c47955SMatthew G. Knepley         ierr = MatSetValues(mass, 1, &findices[i], numCIndices, cindices, elemMat, ADD_VALUES);CHKERRQ(ierr);
28683c47955SMatthew G. Knepley       }
28783c47955SMatthew G. Knepley       ierr = PetscFree(cindices);CHKERRQ(ierr);
28883c47955SMatthew G. Knepley       ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
28983c47955SMatthew G. Knepley     }
29083c47955SMatthew G. Knepley   }
29183c47955SMatthew G. Knepley   ierr = DMSwarmSortRestoreAccess(dmc);CHKERRQ(ierr);
29283c47955SMatthew G. Knepley   ierr = PetscFree3(v0,J,invJ);CHKERRQ(ierr);
29383c47955SMatthew G. Knepley   ierr = PetscFree(elemMat);CHKERRQ(ierr);
29483c47955SMatthew G. Knepley   ierr = MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
29583c47955SMatthew G. Knepley   ierr = MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
29683c47955SMatthew G. Knepley   PetscFunctionReturn(0);
29783c47955SMatthew G. Knepley }
29883c47955SMatthew G. Knepley 
29983c47955SMatthew G. Knepley static PetscErrorCode DMCreateMassMatrix_Swarm(DM dmCoarse, DM dmFine, Mat *mass)
30083c47955SMatthew G. Knepley {
301895a1698SMatthew G. Knepley   PetscSection   gsf;
30283c47955SMatthew G. Knepley   PetscInt       m, n;
30383c47955SMatthew G. Knepley   void          *ctx;
30483c47955SMatthew G. Knepley   PetscErrorCode ierr;
30583c47955SMatthew G. Knepley 
30683c47955SMatthew G. Knepley   PetscFunctionBegin;
30783c47955SMatthew G. Knepley   ierr = DMGetDefaultGlobalSection(dmFine, &gsf);CHKERRQ(ierr);
30883c47955SMatthew G. Knepley   ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr);
309895a1698SMatthew G. Knepley   ierr = DMSwarmGetLocalSize(dmCoarse, &n);CHKERRQ(ierr);
31083c47955SMatthew G. Knepley 
31183c47955SMatthew G. Knepley   ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr);
31283c47955SMatthew G. Knepley   ierr = MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
31383c47955SMatthew G. Knepley   ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr);
31483c47955SMatthew G. Knepley   ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr);
31583c47955SMatthew G. Knepley 
31683c47955SMatthew G. Knepley   ierr = DMSwarmComputeMassMatrix_Private(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);
31783c47955SMatthew G. Knepley   ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr);
31883c47955SMatthew G. Knepley   PetscFunctionReturn(0);
31983c47955SMatthew G. Knepley }
32083c47955SMatthew G. Knepley 
321fb1bcc12SMatthew G. Knepley /*@C
322d3a51819SDave May    DMSwarmCreateGlobalVectorFromField - Creates a Vec object sharing the array associated with a given field
323d3a51819SDave May 
324d3a51819SDave May    Collective on DM
325d3a51819SDave May 
326d3a51819SDave May    Input parameters:
32762741f57SDave May +  dm - a DMSwarm
32862741f57SDave May -  fieldname - the textual name given to a registered field
329d3a51819SDave May 
3308b8a3813SDave May    Output parameter:
331d3a51819SDave May .  vec - the vector
332d3a51819SDave May 
333d3a51819SDave May    Level: beginner
334d3a51819SDave May 
3358b8a3813SDave May    Notes:
3368b8a3813SDave May    The vector must be returned using a matching call to DMSwarmDestroyGlobalVectorFromField().
3378b8a3813SDave May 
3388b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmDestroyGlobalVectorFromField()
339d3a51819SDave May @*/
340b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmCreateGlobalVectorFromField(DM dm,const char fieldname[],Vec *vec)
341b5bcf523SDave May {
342fb1bcc12SMatthew G. Knepley   MPI_Comm       comm = PetscObjectComm((PetscObject) dm);
343b5bcf523SDave May   PetscErrorCode ierr;
344b5bcf523SDave May 
345fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
346fb1bcc12SMatthew G. Knepley   ierr = DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec);CHKERRQ(ierr);
347b5bcf523SDave May   PetscFunctionReturn(0);
348b5bcf523SDave May }
349b5bcf523SDave May 
350d3a51819SDave May /*@C
351d3a51819SDave May    DMSwarmDestroyGlobalVectorFromField - Destroys the Vec object which share the array associated with a given field
352d3a51819SDave May 
353d3a51819SDave May    Collective on DM
354d3a51819SDave May 
355d3a51819SDave May    Input parameters:
35662741f57SDave May +  dm - a DMSwarm
35762741f57SDave May -  fieldname - the textual name given to a registered field
358d3a51819SDave May 
3598b8a3813SDave May    Output parameter:
360d3a51819SDave May .  vec - the vector
361d3a51819SDave May 
362d3a51819SDave May    Level: beginner
363d3a51819SDave May 
3648b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmCreateGlobalVectorFromField()
365d3a51819SDave May @*/
366b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmDestroyGlobalVectorFromField(DM dm,const char fieldname[],Vec *vec)
367b5bcf523SDave May {
368b5bcf523SDave May   PetscErrorCode ierr;
369cc651181SDave May 
370fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
371fb1bcc12SMatthew G. Knepley   ierr = DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec);CHKERRQ(ierr);
372b5bcf523SDave May   PetscFunctionReturn(0);
373b5bcf523SDave May }
374b5bcf523SDave May 
375fb1bcc12SMatthew G. Knepley /*@C
376fb1bcc12SMatthew G. Knepley    DMSwarmCreateLocalVectorFromField - Creates a Vec object sharing the array associated with a given field
377fb1bcc12SMatthew G. Knepley 
378fb1bcc12SMatthew G. Knepley    Collective on DM
379fb1bcc12SMatthew G. Knepley 
380fb1bcc12SMatthew G. Knepley    Input parameters:
38162741f57SDave May +  dm - a DMSwarm
38262741f57SDave May -  fieldname - the textual name given to a registered field
383fb1bcc12SMatthew G. Knepley 
3848b8a3813SDave May    Output parameter:
385fb1bcc12SMatthew G. Knepley .  vec - the vector
386fb1bcc12SMatthew G. Knepley 
387fb1bcc12SMatthew G. Knepley    Level: beginner
388fb1bcc12SMatthew G. Knepley 
3898b8a3813SDave May    Notes:
3908b8a3813SDave May    The vector must be returned using a matching call to DMSwarmDestroyLocalVectorFromField().
3918b8a3813SDave May 
3928b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmDestroyLocalVectorFromField()
393fb1bcc12SMatthew G. Knepley @*/
394fb1bcc12SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMSwarmCreateLocalVectorFromField(DM dm,const char fieldname[],Vec *vec)
395bbe8250bSMatthew G. Knepley {
396fb1bcc12SMatthew G. Knepley   MPI_Comm       comm = PETSC_COMM_SELF;
397bbe8250bSMatthew G. Knepley   PetscErrorCode ierr;
398bbe8250bSMatthew G. Knepley 
399fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
400fb1bcc12SMatthew G. Knepley   ierr = DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec);CHKERRQ(ierr);
401fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
402bbe8250bSMatthew G. Knepley }
403fb1bcc12SMatthew G. Knepley 
404fb1bcc12SMatthew G. Knepley /*@C
405fb1bcc12SMatthew G. Knepley    DMSwarmDestroyLocalVectorFromField - Destroys the Vec object which share the array associated with a given field
406fb1bcc12SMatthew G. Knepley 
407fb1bcc12SMatthew G. Knepley    Collective on DM
408fb1bcc12SMatthew G. Knepley 
409fb1bcc12SMatthew G. Knepley    Input parameters:
41062741f57SDave May +  dm - a DMSwarm
41162741f57SDave May -  fieldname - the textual name given to a registered field
412fb1bcc12SMatthew G. Knepley 
4138b8a3813SDave May    Output parameter:
414fb1bcc12SMatthew G. Knepley .  vec - the vector
415fb1bcc12SMatthew G. Knepley 
416fb1bcc12SMatthew G. Knepley    Level: beginner
417fb1bcc12SMatthew G. Knepley 
4188b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmCreateLocalVectorFromField()
419fb1bcc12SMatthew G. Knepley @*/
420fb1bcc12SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMSwarmDestroyLocalVectorFromField(DM dm,const char fieldname[],Vec *vec)
421fb1bcc12SMatthew G. Knepley {
422fb1bcc12SMatthew G. Knepley   PetscErrorCode ierr;
423fb1bcc12SMatthew G. Knepley 
424fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
425fb1bcc12SMatthew G. Knepley   ierr = DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec);CHKERRQ(ierr);
426bbe8250bSMatthew G. Knepley   PetscFunctionReturn(0);
427bbe8250bSMatthew G. Knepley }
428bbe8250bSMatthew G. Knepley 
429b5bcf523SDave May /*
430b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmCreateGlobalVectorFromFields(DM dm,const PetscInt nf,const char *fieldnames[],Vec *vec)
431b5bcf523SDave May {
432b5bcf523SDave May   PetscFunctionReturn(0);
433b5bcf523SDave May }
434b5bcf523SDave May 
435b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmRestoreGlobalVectorFromFields(DM dm,Vec *vec)
436b5bcf523SDave May {
437b5bcf523SDave May   PetscFunctionReturn(0);
438b5bcf523SDave May }
439b5bcf523SDave May */
440b5bcf523SDave May 
441d3a51819SDave May /*@C
442d3a51819SDave May    DMSwarmInitializeFieldRegister - Initiates the registration of fields to a DMSwarm
443d3a51819SDave May 
444d3a51819SDave May    Collective on DM
445d3a51819SDave May 
446d3a51819SDave May    Input parameter:
447d3a51819SDave May .  dm - a DMSwarm
448d3a51819SDave May 
449d3a51819SDave May    Level: beginner
450d3a51819SDave May 
451d3a51819SDave May    Notes:
4528b8a3813SDave May    After all fields have been registered, you must call DMSwarmFinalizeFieldRegister().
453d3a51819SDave May 
454d3a51819SDave May .seealso: DMSwarmFinalizeFieldRegister(), DMSwarmRegisterPetscDatatypeField(),
455d3a51819SDave May  DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
456d3a51819SDave May @*/
4575f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmInitializeFieldRegister(DM dm)
4585f50eb2eSDave May {
4595f50eb2eSDave May   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
4603454631fSDave May   PetscErrorCode ierr;
4613454631fSDave May 
462521f74f9SMatthew G. Knepley   PetscFunctionBegin;
463cc651181SDave May   if (!swarm->field_registration_initialized) {
4645f50eb2eSDave May     swarm->field_registration_initialized = PETSC_TRUE;
465f0cdbbbaSDave May     ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_pid,1,PETSC_LONG);CHKERRQ(ierr); /* unique identifer */
466f0cdbbbaSDave May     ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_rank,1,PETSC_INT);CHKERRQ(ierr); /* used for communication */
467cc651181SDave May   }
4685f50eb2eSDave May   PetscFunctionReturn(0);
4695f50eb2eSDave May }
4705f50eb2eSDave May 
471d3a51819SDave May /*@C
472d3a51819SDave May    DMSwarmFinalizeFieldRegister - Finalizes the registration of fields to a DMSwarm
473d3a51819SDave May 
474d3a51819SDave May    Collective on DM
475d3a51819SDave May 
476d3a51819SDave May    Input parameter:
477d3a51819SDave May .  dm - a DMSwarm
478d3a51819SDave May 
479d3a51819SDave May    Level: beginner
480d3a51819SDave May 
481d3a51819SDave May    Notes:
48262741f57SDave May    After DMSwarmFinalizeFieldRegister() has been called, no new fields can be defined on the DMSwarm.
483d3a51819SDave May 
484d3a51819SDave May .seealso: DMSwarmInitializeFieldRegister(), DMSwarmRegisterPetscDatatypeField(),
485d3a51819SDave May  DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
486d3a51819SDave May @*/
4875f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmFinalizeFieldRegister(DM dm)
4885f50eb2eSDave May {
4895f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
4906845f8f5SDave May   PetscErrorCode ierr;
4916845f8f5SDave May 
492521f74f9SMatthew G. Knepley   PetscFunctionBegin;
493f0cdbbbaSDave May   if (!swarm->field_registration_finalized) {
4946845f8f5SDave May     ierr = DataBucketFinalize(swarm->db);CHKERRQ(ierr);
495f0cdbbbaSDave May   }
496f0cdbbbaSDave May   swarm->field_registration_finalized = PETSC_TRUE;
4975f50eb2eSDave May   PetscFunctionReturn(0);
4985f50eb2eSDave May }
4995f50eb2eSDave May 
500d3a51819SDave May /*@C
501d3a51819SDave May    DMSwarmSetLocalSizes - Sets the length of all registered fields on the DMSwarm
502d3a51819SDave May 
503d3a51819SDave May    Not collective
504d3a51819SDave May 
505d3a51819SDave May    Input parameters:
50662741f57SDave May +  dm - a DMSwarm
507d3a51819SDave May .  nlocal - the length of each registered field
50862741f57SDave May -  buffer - the length of the buffer used to efficient dynamic re-sizing
509d3a51819SDave May 
510d3a51819SDave May    Level: beginner
511d3a51819SDave May 
512d3a51819SDave May .seealso: DMSwarmGetLocalSize()
513d3a51819SDave May @*/
5145f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmSetLocalSizes(DM dm,PetscInt nlocal,PetscInt buffer)
5155f50eb2eSDave May {
5165f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
5176845f8f5SDave May   PetscErrorCode ierr;
5185f50eb2eSDave May 
519521f74f9SMatthew G. Knepley   PetscFunctionBegin;
520f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_SetSizes,0,0,0,0);CHKERRQ(ierr);
5216845f8f5SDave May   ierr = DataBucketSetSizes(swarm->db,nlocal,buffer);CHKERRQ(ierr);
522f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_SetSizes,0,0,0,0);CHKERRQ(ierr);
5235f50eb2eSDave May   PetscFunctionReturn(0);
5245f50eb2eSDave May }
5255f50eb2eSDave May 
526d3a51819SDave May /*@C
527d3a51819SDave May    DMSwarmSetCellDM - Attachs a DM to a DMSwarm
528d3a51819SDave May 
529d3a51819SDave May    Collective on DM
530d3a51819SDave May 
531d3a51819SDave May    Input parameters:
53262741f57SDave May +  dm - a DMSwarm
53362741f57SDave May -  dmcell - the DM to attach to the DMSwarm
534d3a51819SDave May 
535d3a51819SDave May    Level: beginner
536d3a51819SDave May 
537d3a51819SDave May    Notes:
538d3a51819SDave May    The attached DM (dmcell) will be queried for point location and
5398b8a3813SDave May    neighbor MPI-rank information if DMSwarmMigrate() is called.
540d3a51819SDave May 
5418b8a3813SDave May .seealso: DMSwarmSetType(), DMSwarmGetCellDM(), DMSwarmMigrate()
542d3a51819SDave May @*/
543b16650c8SDave May PETSC_EXTERN PetscErrorCode DMSwarmSetCellDM(DM dm,DM dmcell)
544b16650c8SDave May {
545b16650c8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
546521f74f9SMatthew G. Knepley 
547521f74f9SMatthew G. Knepley   PetscFunctionBegin;
548b16650c8SDave May   swarm->dmcell = dmcell;
549b16650c8SDave May   PetscFunctionReturn(0);
550b16650c8SDave May }
551b16650c8SDave May 
552d3a51819SDave May /*@C
553d3a51819SDave May    DMSwarmGetCellDM - Fetches the attached cell DM
554d3a51819SDave May 
555d3a51819SDave May    Collective on DM
556d3a51819SDave May 
557d3a51819SDave May    Input parameter:
558d3a51819SDave May .  dm - a DMSwarm
559d3a51819SDave May 
560d3a51819SDave May    Output parameter:
561d3a51819SDave May .  dmcell - the DM which was attached to the DMSwarm
562d3a51819SDave May 
563d3a51819SDave May    Level: beginner
564d3a51819SDave May 
565d3a51819SDave May .seealso: DMSwarmSetCellDM()
566d3a51819SDave May @*/
567fe39f135SDave May PETSC_EXTERN PetscErrorCode DMSwarmGetCellDM(DM dm,DM *dmcell)
568fe39f135SDave May {
569fe39f135SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
570521f74f9SMatthew G. Knepley 
571521f74f9SMatthew G. Knepley   PetscFunctionBegin;
572fe39f135SDave May   *dmcell = swarm->dmcell;
573fe39f135SDave May   PetscFunctionReturn(0);
574fe39f135SDave May }
575fe39f135SDave May 
576d3a51819SDave May /*@C
577d3a51819SDave May    DMSwarmGetLocalSize - Retrives the local length of fields registered
578d3a51819SDave May 
579d3a51819SDave May    Not collective
580d3a51819SDave May 
581d3a51819SDave May    Input parameter:
582d3a51819SDave May .  dm - a DMSwarm
583d3a51819SDave May 
584d3a51819SDave May    Output parameter:
585d3a51819SDave May .  nlocal - the length of each registered field
586d3a51819SDave May 
587d3a51819SDave May    Level: beginner
588d3a51819SDave May 
5898b8a3813SDave May .seealso: DMSwarmGetSize(), DMSwarmSetLocalSizes()
590d3a51819SDave May @*/
591dcf43ee8SDave May PETSC_EXTERN PetscErrorCode DMSwarmGetLocalSize(DM dm,PetscInt *nlocal)
592dcf43ee8SDave May {
593dcf43ee8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
594dcf43ee8SDave May   PetscErrorCode ierr;
595dcf43ee8SDave May 
596521f74f9SMatthew G. Knepley   PetscFunctionBegin;
597521f74f9SMatthew G. Knepley   if (nlocal) {ierr = DataBucketGetSizes(swarm->db,nlocal,NULL,NULL);CHKERRQ(ierr);}
598dcf43ee8SDave May   PetscFunctionReturn(0);
599dcf43ee8SDave May }
600dcf43ee8SDave May 
601d3a51819SDave May /*@C
602d3a51819SDave May    DMSwarmGetSize - Retrives the total length of fields registered
603d3a51819SDave May 
604d3a51819SDave May    Collective on DM
605d3a51819SDave May 
606d3a51819SDave May    Input parameter:
607d3a51819SDave May .  dm - a DMSwarm
608d3a51819SDave May 
609d3a51819SDave May    Output parameter:
610d3a51819SDave May .  n - the total length of each registered field
611d3a51819SDave May 
612d3a51819SDave May    Level: beginner
613d3a51819SDave May 
614d3a51819SDave May    Note:
615d3a51819SDave May    This calls MPI_Allreduce upon each call (inefficient but safe)
616d3a51819SDave May 
6178b8a3813SDave May .seealso: DMSwarmGetLocalSize(), DMSwarmSetLocalSizes()
618d3a51819SDave May @*/
619dcf43ee8SDave May PETSC_EXTERN PetscErrorCode DMSwarmGetSize(DM dm,PetscInt *n)
620dcf43ee8SDave May {
621dcf43ee8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
622dcf43ee8SDave May   PetscErrorCode ierr;
623dcf43ee8SDave May   PetscInt nlocal,ng;
624dcf43ee8SDave May 
625521f74f9SMatthew G. Knepley   PetscFunctionBegin;
626dcf43ee8SDave May   ierr = DataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
627dcf43ee8SDave May   ierr = MPI_Allreduce(&nlocal,&ng,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
628dcf43ee8SDave May   if (n) { *n = ng; }
629dcf43ee8SDave May   PetscFunctionReturn(0);
630dcf43ee8SDave May }
631dcf43ee8SDave May 
632d3a51819SDave May /*@C
6338b8a3813SDave May    DMSwarmRegisterPetscDatatypeField - Register a field to a DMSwarm with a native PETSc data type
634d3a51819SDave May 
635d3a51819SDave May    Collective on DM
636d3a51819SDave May 
637d3a51819SDave May    Input parameters:
63862741f57SDave May +  dm - a DMSwarm
639d3a51819SDave May .  fieldname - the textual name to identify this field
640d3a51819SDave May .  blocksize - the number of each data type
64162741f57SDave May -  type - a valid PETSc data type (PETSC_CHAR, PETSC_SHORT, PETSC_INT, PETSC_FLOAT, PETSC_REAL, PETSC_LONG)
642d3a51819SDave May 
643d3a51819SDave May    Level: beginner
644d3a51819SDave May 
645d3a51819SDave May    Notes:
6468b8a3813SDave May    The textual name for each registered field must be unique.
647d3a51819SDave May 
648d3a51819SDave May .seealso: DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
649d3a51819SDave May @*/
6505f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmRegisterPetscDatatypeField(DM dm,const char fieldname[],PetscInt blocksize,PetscDataType type)
651b62e03f8SDave May {
6522eac95f8SDave May   PetscErrorCode ierr;
653b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
654b62e03f8SDave May   size_t size;
655b62e03f8SDave May 
656521f74f9SMatthew G. Knepley   PetscFunctionBegin;
6575f50eb2eSDave May   if (!swarm->field_registration_initialized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmInitializeFieldRegister() first");
6585f50eb2eSDave May   if (swarm->field_registration_finalized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Cannot register additional fields after calling DMSwarmFinalizeFieldRegister() first");
6595f50eb2eSDave May 
6605f50eb2eSDave May   if (type == PETSC_OBJECT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
6615f50eb2eSDave May   if (type == PETSC_FUNCTION) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
6625f50eb2eSDave May   if (type == PETSC_STRING) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
6635f50eb2eSDave May   if (type == PETSC_STRUCT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
6645f50eb2eSDave May   if (type == PETSC_DATATYPE_UNKNOWN) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
665b62e03f8SDave May 
6662ddcf43eSMatthew G. Knepley   ierr = PetscDataTypeGetSize(type, &size);CHKERRQ(ierr);
667b62e03f8SDave May   /* Load a specific data type into data bucket, specifying textual name and its size in bytes */
66852c3ed93SDave May   ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterPetscDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
66952c3ed93SDave May   {
67052c3ed93SDave May     DataField gfield;
67152c3ed93SDave May 
67252c3ed93SDave May     ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
67352c3ed93SDave May     ierr = DataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
67452c3ed93SDave May   }
675b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = type;
676b62e03f8SDave May   PetscFunctionReturn(0);
677b62e03f8SDave May }
678b62e03f8SDave May 
679d3a51819SDave May /*@C
680d3a51819SDave May    DMSwarmRegisterUserStructField - Register a user defined struct to a DMSwarm
681d3a51819SDave May 
682d3a51819SDave May    Collective on DM
683d3a51819SDave May 
684d3a51819SDave May    Input parameters:
68562741f57SDave May +  dm - a DMSwarm
686d3a51819SDave May .  fieldname - the textual name to identify this field
68762741f57SDave May -  size - the size in bytes of the user struct of each data type
688d3a51819SDave May 
689d3a51819SDave May    Level: beginner
690d3a51819SDave May 
691d3a51819SDave May    Notes:
6928b8a3813SDave May    The textual name for each registered field must be unique.
693d3a51819SDave May 
694d3a51819SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserDatatypeField()
695d3a51819SDave May @*/
6965f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmRegisterUserStructField(DM dm,const char fieldname[],size_t size)
697b62e03f8SDave May {
6982eac95f8SDave May   PetscErrorCode ierr;
699b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
700b62e03f8SDave May 
701521f74f9SMatthew G. Knepley   PetscFunctionBegin;
7022eac95f8SDave May   ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterUserStructField",fieldname,size,NULL);CHKERRQ(ierr);
703b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_STRUCT ;
704b62e03f8SDave May   PetscFunctionReturn(0);
705b62e03f8SDave May }
706b62e03f8SDave May 
707d3a51819SDave May /*@C
708d3a51819SDave May    DMSwarmRegisterUserDatatypeField - Register a user defined data type to a DMSwarm
709d3a51819SDave May 
710d3a51819SDave May    Collective on DM
711d3a51819SDave May 
712d3a51819SDave May    Input parameters:
71362741f57SDave May +  dm - a DMSwarm
714d3a51819SDave May .  fieldname - the textual name to identify this field
715d3a51819SDave May .  size - the size in bytes of the user data type
71662741f57SDave May -  blocksize - the number of each data type
717d3a51819SDave May 
718d3a51819SDave May    Level: beginner
719d3a51819SDave May 
720d3a51819SDave May    Notes:
7218b8a3813SDave May    The textual name for each registered field must be unique.
722d3a51819SDave May 
723d3a51819SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
724d3a51819SDave May @*/
725320740a0SDave May PETSC_EXTERN PetscErrorCode DMSwarmRegisterUserDatatypeField(DM dm,const char fieldname[],size_t size,PetscInt blocksize)
726b62e03f8SDave May {
727b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
7286845f8f5SDave May   PetscErrorCode ierr;
729b62e03f8SDave May 
730521f74f9SMatthew G. Knepley   PetscFunctionBegin;
731320740a0SDave May   ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterUserDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
732320740a0SDave May   {
733320740a0SDave May     DataField gfield;
734320740a0SDave May 
735320740a0SDave May     ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
736320740a0SDave May     ierr = DataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
737320740a0SDave May   }
738b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_DATATYPE_UNKNOWN;
739b62e03f8SDave May   PetscFunctionReturn(0);
740b62e03f8SDave May }
741b62e03f8SDave May 
742d3a51819SDave May /*@C
743d3a51819SDave May    DMSwarmGetField - Get access to the underlying array storing all entries associated with a registered field
744d3a51819SDave May 
745d3a51819SDave May    Not collective
746d3a51819SDave May 
747d3a51819SDave May    Input parameters:
74862741f57SDave May +  dm - a DMSwarm
74962741f57SDave May -  fieldname - the textual name to identify this field
750d3a51819SDave May 
751d3a51819SDave May    Output parameters:
75262741f57SDave May +  blocksize - the number of each data type
753d3a51819SDave May .  type - the data type
75462741f57SDave May -  data - pointer to raw array
755d3a51819SDave May 
756d3a51819SDave May    Level: beginner
757d3a51819SDave May 
758d3a51819SDave May    Notes:
7598b8a3813SDave May    The array must be returned using a matching call to DMSwarmRestoreField().
760d3a51819SDave May 
761d3a51819SDave May .seealso: DMSwarmRestoreField()
762d3a51819SDave May @*/
7635f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmGetField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
764b62e03f8SDave May {
765b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
766b62e03f8SDave May   DataField gfield;
7672eac95f8SDave May   PetscErrorCode ierr;
768b62e03f8SDave May 
769521f74f9SMatthew G. Knepley   PetscFunctionBegin;
7703454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
7712eac95f8SDave May   ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
7726845f8f5SDave May   ierr = DataFieldGetAccess(gfield);CHKERRQ(ierr);
7736845f8f5SDave May   ierr = DataFieldGetEntries(gfield,data);CHKERRQ(ierr);
7741b1ea282SDave May   if (blocksize) {*blocksize = gfield->bs; }
775b5bcf523SDave May   if (type) { *type = gfield->petsc_type; }
776b62e03f8SDave May   PetscFunctionReturn(0);
777b62e03f8SDave May }
778b62e03f8SDave May 
779d3a51819SDave May /*@C
780d3a51819SDave May    DMSwarmRestoreField - Restore access to the underlying array storing all entries associated with a registered field
781d3a51819SDave May 
782d3a51819SDave May    Not collective
783d3a51819SDave May 
784d3a51819SDave May    Input parameters:
78562741f57SDave May +  dm - a DMSwarm
78662741f57SDave May -  fieldname - the textual name to identify this field
787d3a51819SDave May 
788d3a51819SDave May    Output parameters:
78962741f57SDave May +  blocksize - the number of each data type
790d3a51819SDave May .  type - the data type
79162741f57SDave May -  data - pointer to raw array
792d3a51819SDave May 
793d3a51819SDave May    Level: beginner
794d3a51819SDave May 
795d3a51819SDave May    Notes:
7968b8a3813SDave May    The user must call DMSwarmGetField() prior to calling DMSwarmRestoreField().
797d3a51819SDave May 
798d3a51819SDave May .seealso: DMSwarmGetField()
799d3a51819SDave May @*/
8005f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmRestoreField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
801b62e03f8SDave May {
802b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
803b62e03f8SDave May   DataField gfield;
8042eac95f8SDave May   PetscErrorCode ierr;
805b62e03f8SDave May 
806521f74f9SMatthew G. Knepley   PetscFunctionBegin;
8072eac95f8SDave May   ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
8086845f8f5SDave May   ierr = DataFieldRestoreAccess(gfield);CHKERRQ(ierr);
809b62e03f8SDave May   if (data) *data = NULL;
810b62e03f8SDave May   PetscFunctionReturn(0);
811b62e03f8SDave May }
812b62e03f8SDave May 
813d3a51819SDave May /*@C
814d3a51819SDave May    DMSwarmAddPoint - Add space for one new point in the DMSwarm
815d3a51819SDave May 
816d3a51819SDave May    Not collective
817d3a51819SDave May 
818d3a51819SDave May    Input parameter:
819d3a51819SDave May .  dm - a DMSwarm
820d3a51819SDave May 
821d3a51819SDave May    Level: beginner
822d3a51819SDave May 
823d3a51819SDave May    Notes:
8248b8a3813SDave May    The new point will have all fields initialized to zero.
825d3a51819SDave May 
826d3a51819SDave May .seealso: DMSwarmAddNPoints()
827d3a51819SDave May @*/
828cb1d1399SDave May PETSC_EXTERN PetscErrorCode DMSwarmAddPoint(DM dm)
829cb1d1399SDave May {
830cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
831cb1d1399SDave May   PetscErrorCode ierr;
832cb1d1399SDave May 
833521f74f9SMatthew G. Knepley   PetscFunctionBegin;
8343454631fSDave May   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
835f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
836cb1d1399SDave May   ierr = DataBucketAddPoint(swarm->db);CHKERRQ(ierr);
837f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
838cb1d1399SDave May   PetscFunctionReturn(0);
839cb1d1399SDave May }
840cb1d1399SDave May 
841d3a51819SDave May /*@C
842d3a51819SDave May    DMSwarmAddNPoints - Add space for a number of new points in the DMSwarm
843d3a51819SDave May 
844d3a51819SDave May    Not collective
845d3a51819SDave May 
846d3a51819SDave May    Input parameters:
84762741f57SDave May +  dm - a DMSwarm
84862741f57SDave May -  npoints - the number of new points to add
849d3a51819SDave May 
850d3a51819SDave May    Level: beginner
851d3a51819SDave May 
852d3a51819SDave May    Notes:
8538b8a3813SDave May    The new point will have all fields initialized to zero.
854d3a51819SDave May 
855d3a51819SDave May .seealso: DMSwarmAddPoint()
856d3a51819SDave May @*/
857cb1d1399SDave May PETSC_EXTERN PetscErrorCode DMSwarmAddNPoints(DM dm,PetscInt npoints)
858cb1d1399SDave May {
859cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
860cb1d1399SDave May   PetscErrorCode ierr;
861cb1d1399SDave May   PetscInt nlocal;
862cb1d1399SDave May 
863521f74f9SMatthew G. Knepley   PetscFunctionBegin;
864f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
865cb1d1399SDave May   ierr = DataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
866cb1d1399SDave May   nlocal = nlocal + npoints;
86765141ba8SDave May   ierr = DataBucketSetSizes(swarm->db,nlocal,DATA_BUCKET_BUFFER_DEFAULT);CHKERRQ(ierr);
868f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
869cb1d1399SDave May   PetscFunctionReturn(0);
870cb1d1399SDave May }
871cb1d1399SDave May 
872d3a51819SDave May /*@C
873d3a51819SDave May    DMSwarmRemovePoint - Remove the last point from the DMSwarm
874d3a51819SDave May 
875d3a51819SDave May    Not collective
876d3a51819SDave May 
877d3a51819SDave May    Input parameter:
878d3a51819SDave May .  dm - a DMSwarm
879d3a51819SDave May 
880d3a51819SDave May    Level: beginner
881d3a51819SDave May 
882d3a51819SDave May .seealso: DMSwarmRemovePointAtIndex()
883d3a51819SDave May @*/
884cb1d1399SDave May PETSC_EXTERN PetscErrorCode DMSwarmRemovePoint(DM dm)
885cb1d1399SDave May {
886cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
887cb1d1399SDave May   PetscErrorCode ierr;
888cb1d1399SDave May 
889521f74f9SMatthew G. Knepley   PetscFunctionBegin;
890f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
891cb1d1399SDave May   ierr = DataBucketRemovePoint(swarm->db);CHKERRQ(ierr);
892f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
893cb1d1399SDave May   PetscFunctionReturn(0);
894cb1d1399SDave May }
895cb1d1399SDave May 
896d3a51819SDave May /*@C
897d3a51819SDave May    DMSwarmRemovePointAtIndex - Removes a specific point from the DMSwarm
898d3a51819SDave May 
899d3a51819SDave May    Not collective
900d3a51819SDave May 
901d3a51819SDave May    Input parameters:
90262741f57SDave May +  dm - a DMSwarm
90362741f57SDave May -  idx - index of point to remove
904d3a51819SDave May 
905d3a51819SDave May    Level: beginner
906d3a51819SDave May 
907d3a51819SDave May .seealso: DMSwarmRemovePoint()
908d3a51819SDave May @*/
909cb1d1399SDave May PETSC_EXTERN PetscErrorCode DMSwarmRemovePointAtIndex(DM dm,PetscInt idx)
910cb1d1399SDave May {
911cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
912cb1d1399SDave May   PetscErrorCode ierr;
913cb1d1399SDave May 
914521f74f9SMatthew G. Knepley   PetscFunctionBegin;
915f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
916cb1d1399SDave May   ierr = DataBucketRemovePointAtIndex(swarm->db,idx);CHKERRQ(ierr);
917f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
918cb1d1399SDave May   PetscFunctionReturn(0);
919cb1d1399SDave May }
920b62e03f8SDave May 
921ba4fc9c6SDave May /*@C
922ba4fc9c6SDave May    DMSwarmCopyPoint - Copy point pj to point pi in the DMSwarm
923ba4fc9c6SDave May 
924ba4fc9c6SDave May    Not collective
925ba4fc9c6SDave May 
926ba4fc9c6SDave May    Input parameters:
927ba4fc9c6SDave May +  dm - a DMSwarm
928ba4fc9c6SDave May .  pi - the index of the point to copy
929ba4fc9c6SDave May -  pj - the point index where the copy should be located
930ba4fc9c6SDave May 
931ba4fc9c6SDave May  Level: beginner
932ba4fc9c6SDave May 
933ba4fc9c6SDave May .seealso: DMSwarmRemovePoint()
934ba4fc9c6SDave May @*/
935ba4fc9c6SDave May PETSC_EXTERN PetscErrorCode DMSwarmCopyPoint(DM dm,PetscInt pi,PetscInt pj)
936ba4fc9c6SDave May {
937ba4fc9c6SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
938ba4fc9c6SDave May   PetscErrorCode ierr;
939ba4fc9c6SDave May 
940ba4fc9c6SDave May   PetscFunctionBegin;
941ba4fc9c6SDave May   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
942ba4fc9c6SDave May   ierr = DataBucketCopyPoint(swarm->db,pi,swarm->db,pj);CHKERRQ(ierr);
943ba4fc9c6SDave May   PetscFunctionReturn(0);
944ba4fc9c6SDave May }
945ba4fc9c6SDave May 
946095059a4SDave May PetscErrorCode DMSwarmMigrate_Basic(DM dm,PetscBool remove_sent_points)
9473454631fSDave May {
948dcf43ee8SDave May   PetscErrorCode ierr;
949521f74f9SMatthew G. Knepley 
950521f74f9SMatthew G. Knepley   PetscFunctionBegin;
951dcf43ee8SDave May   ierr = DMSwarmMigrate_Push_Basic(dm,remove_sent_points);CHKERRQ(ierr);
9523454631fSDave May   PetscFunctionReturn(0);
9533454631fSDave May }
9543454631fSDave May 
955d3a51819SDave May /*@C
956d3a51819SDave May    DMSwarmMigrate - Relocates points defined in the DMSwarm to other MPI-ranks
957d3a51819SDave May 
958d3a51819SDave May    Collective on DM
959d3a51819SDave May 
960d3a51819SDave May    Input parameters:
96162741f57SDave May +  dm - the DMSwarm
96262741f57SDave May -  remove_sent_points - flag indicating if sent points should be removed from the current MPI-rank
963d3a51819SDave May 
964d3a51819SDave May    Notes:
9658b8a3813SDave May    The DM will be modified to accomodate received points.
9668b8a3813SDave May    If remove_sent_points = PETSC_TRUE, any points that were sent will be removed from the DM.
9678b8a3813SDave May    Different styles of migration are supported. See DMSwarmSetMigrateType().
968d3a51819SDave May 
969d3a51819SDave May    Level: advanced
970d3a51819SDave May 
971d3a51819SDave May .seealso: DMSwarmSetMigrateType()
972d3a51819SDave May @*/
973095059a4SDave May PETSC_EXTERN PetscErrorCode DMSwarmMigrate(DM dm,PetscBool remove_sent_points)
9743454631fSDave May {
975f0cdbbbaSDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
9763454631fSDave May   PetscErrorCode ierr;
977f0cdbbbaSDave May 
978521f74f9SMatthew G. Knepley   PetscFunctionBegin;
979ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
980f0cdbbbaSDave May   switch (swarm->migrate_type) {
981f0cdbbbaSDave May     case DMSWARM_MIGRATE_BASIC:
982095059a4SDave May       ierr = DMSwarmMigrate_Basic(dm,remove_sent_points);CHKERRQ(ierr);
983f0cdbbbaSDave May       break;
984f0cdbbbaSDave May     case DMSWARM_MIGRATE_DMCELLNSCATTER:
985f0cdbbbaSDave May       ierr = DMSwarmMigrate_CellDMScatter(dm,remove_sent_points);CHKERRQ(ierr);
986f0cdbbbaSDave May       break;
987f0cdbbbaSDave May     case DMSWARM_MIGRATE_DMCELLEXACT:
988f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_DMCELLEXACT not implemented");
989521f74f9SMatthew G. Knepley       /*ierr = DMSwarmMigrate_CellDMExact(dm,remove_sent_points);CHKERRQ(ierr);*/
990f0cdbbbaSDave May       break;
991f0cdbbbaSDave May     case DMSWARM_MIGRATE_USER:
992f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_USER not implemented");
993521f74f9SMatthew G. Knepley       /*ierr = swarm->migrate(dm,remove_sent_points);CHKERRQ(ierr);*/
994f0cdbbbaSDave May       break;
995f0cdbbbaSDave May     default:
996f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE type unknown");
997f0cdbbbaSDave May       break;
998f0cdbbbaSDave May   }
999ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
10003454631fSDave May   PetscFunctionReturn(0);
10013454631fSDave May }
10023454631fSDave May 
1003f0cdbbbaSDave May PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm,PetscInt *globalsize);
1004f0cdbbbaSDave May 
1005d3a51819SDave May /*
1006d3a51819SDave May  DMSwarmCollectViewCreate
1007d3a51819SDave May 
1008d3a51819SDave May  * Applies a collection method and gathers point neighbour points into dm
1009d3a51819SDave May 
1010d3a51819SDave May  Notes:
10118b8a3813SDave May  Users should call DMSwarmCollectViewDestroy() after
1012d3a51819SDave May  they have finished computations associated with the collected points
1013d3a51819SDave May */
1014d3a51819SDave May 
1015d3a51819SDave May /*@C
1016d3a51819SDave May    DMSwarmCollectViewCreate - Applies a collection method and gathers points
1017d3a51819SDave May    in neighbour MPI-ranks into the DMSwarm
1018d3a51819SDave May 
1019d3a51819SDave May    Collective on DM
1020d3a51819SDave May 
1021d3a51819SDave May    Input parameter:
1022d3a51819SDave May .  dm - the DMSwarm
1023d3a51819SDave May 
1024d3a51819SDave May    Notes:
1025d3a51819SDave May    Users should call DMSwarmCollectViewDestroy() after
1026d3a51819SDave May    they have finished computations associated with the collected points
10278b8a3813SDave May    Different collect methods are supported. See DMSwarmSetCollectType().
1028d3a51819SDave May 
1029d3a51819SDave May    Level: advanced
1030d3a51819SDave May 
1031d3a51819SDave May .seealso: DMSwarmCollectViewDestroy(), DMSwarmSetCollectType()
1032d3a51819SDave May @*/
1033fe39f135SDave May PETSC_EXTERN PetscErrorCode DMSwarmCollectViewCreate(DM dm)
10342712d1f2SDave May {
10352712d1f2SDave May   PetscErrorCode ierr;
10362712d1f2SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
10372712d1f2SDave May   PetscInt ng;
10382712d1f2SDave May 
1039521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1040480eef7bSDave May   if (swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView currently active");
1041480eef7bSDave May   ierr = DMSwarmGetLocalSize(dm,&ng);CHKERRQ(ierr);
1042480eef7bSDave May   switch (swarm->collect_type) {
1043f0cdbbbaSDave May 
1044480eef7bSDave May     case DMSWARM_COLLECT_BASIC:
10452712d1f2SDave May       ierr = DMSwarmMigrate_GlobalToLocal_Basic(dm,&ng);CHKERRQ(ierr);
1046480eef7bSDave May       break;
1047480eef7bSDave May     case DMSWARM_COLLECT_DMDABOUNDINGBOX:
1048f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_DMDABOUNDINGBOX not implemented");
1049521f74f9SMatthew G. Knepley       /*ierr = DMSwarmCollect_DMDABoundingBox(dm,&ng);CHKERRQ(ierr);*/
1050480eef7bSDave May       break;
1051480eef7bSDave May     case DMSWARM_COLLECT_GENERAL:
1052f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_GENERAL not implemented");
1053521f74f9SMatthew G. Knepley       /*ierr = DMSwarmCollect_General(dm,..,,..,&ng);CHKERRQ(ierr);*/
1054480eef7bSDave May       break;
1055480eef7bSDave May     default:
1056f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT type unknown");
1057480eef7bSDave May       break;
1058480eef7bSDave May   }
1059480eef7bSDave May   swarm->collect_view_active = PETSC_TRUE;
1060480eef7bSDave May   swarm->collect_view_reset_nlocal = ng;
10612712d1f2SDave May   PetscFunctionReturn(0);
10622712d1f2SDave May }
10632712d1f2SDave May 
1064d3a51819SDave May /*@C
1065d3a51819SDave May    DMSwarmCollectViewDestroy - Resets the DMSwarm to the size prior to calling DMSwarmCollectViewCreate()
1066d3a51819SDave May 
1067d3a51819SDave May    Collective on DM
1068d3a51819SDave May 
1069d3a51819SDave May    Input parameters:
1070d3a51819SDave May .  dm - the DMSwarm
1071d3a51819SDave May 
1072d3a51819SDave May    Notes:
1073d3a51819SDave May    Users should call DMSwarmCollectViewCreate() before this function is called.
1074d3a51819SDave May 
1075d3a51819SDave May    Level: advanced
1076d3a51819SDave May 
1077d3a51819SDave May .seealso: DMSwarmCollectViewCreate(), DMSwarmSetCollectType()
1078d3a51819SDave May @*/
1079fe39f135SDave May PETSC_EXTERN PetscErrorCode DMSwarmCollectViewDestroy(DM dm)
10802712d1f2SDave May {
10812712d1f2SDave May   PetscErrorCode ierr;
10822712d1f2SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
10832712d1f2SDave May 
1084521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1085480eef7bSDave May   if (!swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView is currently not active");
1086480eef7bSDave May   ierr = DMSwarmSetLocalSizes(dm,swarm->collect_view_reset_nlocal,-1);CHKERRQ(ierr);
1087480eef7bSDave May   swarm->collect_view_active = PETSC_FALSE;
10882712d1f2SDave May   PetscFunctionReturn(0);
10892712d1f2SDave May }
10903454631fSDave May 
1091f0cdbbbaSDave May PetscErrorCode DMSwarmSetUpPIC(DM dm)
1092f0cdbbbaSDave May {
1093f0cdbbbaSDave May   PetscInt dim;
1094f0cdbbbaSDave May   PetscErrorCode ierr;
1095f0cdbbbaSDave May 
1096521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1097f0cdbbbaSDave May   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
1098f0cdbbbaSDave May   if (dim < 1) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
1099f0cdbbbaSDave May   if (dim > 3) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
1100f0cdbbbaSDave May   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_coor,dim,PETSC_DOUBLE);CHKERRQ(ierr);
1101e2d107dbSDave May   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_cellid,1,PETSC_INT);CHKERRQ(ierr);
1102f0cdbbbaSDave May   PetscFunctionReturn(0);
1103f0cdbbbaSDave May }
1104f0cdbbbaSDave May 
1105d3a51819SDave May /*@C
1106d3a51819SDave May    DMSwarmSetType - Set particular flavor of DMSwarm
1107d3a51819SDave May 
1108d3a51819SDave May    Collective on DM
1109d3a51819SDave May 
1110d3a51819SDave May    Input parameters:
111162741f57SDave May +  dm - the DMSwarm
111262741f57SDave May -  stype - the DMSwarm type (e.g. DMSWARM_PIC)
1113d3a51819SDave May 
1114d3a51819SDave May    Level: advanced
1115d3a51819SDave May 
1116d3a51819SDave May .seealso: DMSwarmSetMigrateType(), DMSwarmSetCollectType()
1117d3a51819SDave May @*/
1118f0cdbbbaSDave May PETSC_EXTERN PetscErrorCode DMSwarmSetType(DM dm,DMSwarmType stype)
1119f0cdbbbaSDave May {
1120f0cdbbbaSDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
1121f0cdbbbaSDave May   PetscErrorCode ierr;
1122f0cdbbbaSDave May 
1123521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1124f0cdbbbaSDave May   swarm->swarm_type = stype;
1125f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
1126f0cdbbbaSDave May     ierr = DMSwarmSetUpPIC(dm);CHKERRQ(ierr);
1127f0cdbbbaSDave May   }
1128f0cdbbbaSDave May   PetscFunctionReturn(0);
1129f0cdbbbaSDave May }
1130f0cdbbbaSDave May 
11313454631fSDave May PetscErrorCode DMSetup_Swarm(DM dm)
11323454631fSDave May {
11333454631fSDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
11343454631fSDave May   PetscErrorCode ierr;
11353454631fSDave May   PetscMPIInt rank;
11363454631fSDave May   PetscInt p,npoints,*rankval;
11373454631fSDave May 
1138521f74f9SMatthew G. Knepley   PetscFunctionBegin;
11393454631fSDave May   if (swarm->issetup) PetscFunctionReturn(0);
11403454631fSDave May 
11413454631fSDave May   swarm->issetup = PETSC_TRUE;
11423454631fSDave May 
1143f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
1144f0cdbbbaSDave May     /* check dmcell exists */
1145f0cdbbbaSDave May     if (!swarm->dmcell) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires you call DMSwarmSetCellDM");
1146f0cdbbbaSDave May 
1147f0cdbbbaSDave May     if (swarm->dmcell->ops->locatepointssubdomain) {
1148f0cdbbbaSDave May       /* check methods exists for exact ownership identificiation */
1149521f74f9SMatthew G. Knepley       ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->ops->LocatePointsSubdomain\n");CHKERRQ(ierr);
1150f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLEXACT;
1151f0cdbbbaSDave May     } else {
1152f0cdbbbaSDave May       /* check methods exist for point location AND rank neighbor identification */
1153f0cdbbbaSDave May       if (swarm->dmcell->ops->locatepoints) {
1154521f74f9SMatthew G. Knepley         ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->LocatePoints\n");CHKERRQ(ierr);
1155f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->locatepoints be defined");
1156f0cdbbbaSDave May 
1157f0cdbbbaSDave May       if (swarm->dmcell->ops->getneighbors) {
1158521f74f9SMatthew G. Knepley         ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->GetNeigbors\n");CHKERRQ(ierr);
1159f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->getneighbors be defined");
1160f0cdbbbaSDave May 
1161f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLNSCATTER;
1162f0cdbbbaSDave May     }
1163f0cdbbbaSDave May   }
1164f0cdbbbaSDave May 
1165f0cdbbbaSDave May   ierr = DMSwarmFinalizeFieldRegister(dm);CHKERRQ(ierr);
1166f0cdbbbaSDave May 
11673454631fSDave May   /* check some fields were registered */
11683454631fSDave May   if (swarm->db->nfields <= 2) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"At least one field user must be registered via DMSwarmRegisterXXX()");
11693454631fSDave May 
11703454631fSDave May   /* check local sizes were set */
11713454631fSDave May   if (swarm->db->L == -1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Local sizes must be set via DMSwarmSetLocalSizes()");
11723454631fSDave May 
11733454631fSDave May   /* initialize values in pid and rank placeholders */
11743454631fSDave May   /* TODO: [pid - use MPI_Scan] */
11753454631fSDave May   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
11763454631fSDave May   ierr = DataBucketGetSizes(swarm->db,&npoints,NULL,NULL);CHKERRQ(ierr);
1177f0cdbbbaSDave May   ierr = DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
11783454631fSDave May   for (p=0; p<npoints; p++) {
11793454631fSDave May     rankval[p] = (PetscInt)rank;
11803454631fSDave May   }
1181f0cdbbbaSDave May   ierr = DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
11823454631fSDave May   PetscFunctionReturn(0);
11833454631fSDave May }
11843454631fSDave May 
1185dc5f5ce9SDave May extern PetscErrorCode DMSwarmSortDestroy(DMSwarmSort *_ctx);
1186dc5f5ce9SDave May 
118757795646SDave May PetscErrorCode DMDestroy_Swarm(DM dm)
118857795646SDave May {
118957795646SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
119057795646SDave May   PetscErrorCode ierr;
119157795646SDave May 
119257795646SDave May   PetscFunctionBegin;
11936845f8f5SDave May   ierr = DataBucketDestroy(&swarm->db);CHKERRQ(ierr);
1194dc5f5ce9SDave May   if (swarm->sort_context) {
1195dc5f5ce9SDave May     ierr = DMSwarmSortDestroy(&swarm->sort_context);CHKERRQ(ierr);
1196dc5f5ce9SDave May   }
119757795646SDave May   ierr = PetscFree(swarm);CHKERRQ(ierr);
119857795646SDave May   PetscFunctionReturn(0);
119957795646SDave May }
120057795646SDave May 
1201a9ee3421SMatthew G. Knepley PetscErrorCode DMSwarmView_Draw(DM dm, PetscViewer viewer)
1202a9ee3421SMatthew G. Knepley {
1203a9ee3421SMatthew G. Knepley   DM             cdm;
1204a9ee3421SMatthew G. Knepley   PetscDraw      draw;
1205a9ee3421SMatthew G. Knepley   PetscReal     *coords, oldPause;
1206a9ee3421SMatthew G. Knepley   PetscInt       Np, p, bs;
1207a9ee3421SMatthew G. Knepley   PetscErrorCode ierr;
1208a9ee3421SMatthew G. Knepley 
1209a9ee3421SMatthew G. Knepley   PetscFunctionBegin;
1210a9ee3421SMatthew G. Knepley   ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr);
1211a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetCellDM(dm, &cdm);CHKERRQ(ierr);
1212a9ee3421SMatthew G. Knepley   ierr = PetscDrawGetPause(draw, &oldPause);CHKERRQ(ierr);
1213a9ee3421SMatthew G. Knepley   ierr = PetscDrawSetPause(draw, 0.0);CHKERRQ(ierr);
1214a9ee3421SMatthew G. Knepley   ierr = DMView(cdm, viewer);CHKERRQ(ierr);
1215a9ee3421SMatthew G. Knepley   ierr = PetscDrawSetPause(draw, oldPause);CHKERRQ(ierr);
1216a9ee3421SMatthew G. Knepley 
1217a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetLocalSize(dm, &Np);CHKERRQ(ierr);
1218a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1219a9ee3421SMatthew G. Knepley   for (p = 0; p < Np; ++p) {
1220a9ee3421SMatthew G. Knepley     const PetscInt i = p*bs;
1221a9ee3421SMatthew G. Knepley 
1222a9ee3421SMatthew G. Knepley     ierr = PetscDrawEllipse(draw, coords[i], coords[i+1], 0.01, 0.01, PETSC_DRAW_BLUE);CHKERRQ(ierr);
1223a9ee3421SMatthew G. Knepley   }
1224a9ee3421SMatthew G. Knepley   ierr = DMSwarmRestoreField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1225a9ee3421SMatthew G. Knepley   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
1226a9ee3421SMatthew G. Knepley   ierr = PetscDrawPause(draw);CHKERRQ(ierr);
1227a9ee3421SMatthew G. Knepley   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
1228a9ee3421SMatthew G. Knepley   PetscFunctionReturn(0);
1229a9ee3421SMatthew G. Knepley }
1230a9ee3421SMatthew G. Knepley 
12315f50eb2eSDave May PetscErrorCode DMView_Swarm(DM dm, PetscViewer viewer)
12325f50eb2eSDave May {
12335f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
1234a9ee3421SMatthew G. Knepley   PetscBool      iascii,ibinary,ishdf5,isvtk,isdraw;
12355f50eb2eSDave May   PetscErrorCode ierr;
12365f50eb2eSDave May 
12375f50eb2eSDave May   PetscFunctionBegin;
12385f50eb2eSDave May   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
12395f50eb2eSDave May   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
12405f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
12415f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY,&ibinary);CHKERRQ(ierr);
12425f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK,   &isvtk);CHKERRQ(ierr);
12435f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
1244a9ee3421SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW,  &isdraw);CHKERRQ(ierr);
12455f50eb2eSDave May   if (iascii) {
12466845f8f5SDave May     ierr = DataBucketView(PetscObjectComm((PetscObject)dm),swarm->db,NULL,DATABUCKET_VIEW_STDOUT);CHKERRQ(ierr);
12475f50eb2eSDave May   } else if (ibinary) {
1248a9ee3421SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO Binary support");
12495f50eb2eSDave May   } else if (ishdf5) {
12505f50eb2eSDave May #if defined(PETSC_HAVE_HDF5)
12515f50eb2eSDave May     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO HDF5 support");
12525f50eb2eSDave May #else
12535f50eb2eSDave May     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"HDF5 not supported. Please reconfigure using --download-hdf5");
12545f50eb2eSDave May #endif
12555f50eb2eSDave May   } else if (isvtk) {
12565f50eb2eSDave May     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO VTK support");
1257a9ee3421SMatthew G. Knepley   } else if (isdraw) {
1258a9ee3421SMatthew G. Knepley     ierr = DMSwarmView_Draw(dm, viewer);CHKERRQ(ierr);
12595f50eb2eSDave May   }
12605f50eb2eSDave May   PetscFunctionReturn(0);
12615f50eb2eSDave May }
12625f50eb2eSDave May 
1263d3a51819SDave May /*MC
1264d3a51819SDave May 
1265d3a51819SDave May  DMSWARM = "swarm" - A DM object used to represent arrays of data (fields) of arbitrary data type.
126662741f57SDave May  This implementation was designed for particle methods in which the underlying
1267d3a51819SDave May  data required to be represented is both (i) dynamic in length, (ii) and of arbitrary data type.
1268d3a51819SDave May 
126962741f57SDave May  User data can be represented by DMSwarm through a registering "fields".
127062741f57SDave May  To register a field, the user must provide;
127162741f57SDave May  (a) a unique name;
127262741f57SDave May  (b) the data type (or size in bytes);
127362741f57SDave May  (c) the block size of the data.
1274d3a51819SDave May 
1275d3a51819SDave May  For example, suppose the application requires a unique id, energy, momentum and density to be stored
127662741f57SDave May  on a set of of particles. Then the following code could be used
1277d3a51819SDave May 
127862741f57SDave May $    DMSwarmInitializeFieldRegister(dm)
127962741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"uid",1,PETSC_LONG);
128062741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"energy",1,PETSC_REAL);
128162741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"momentum",3,PETSC_REAL);
128262741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"density",1,PETSC_FLOAT);
128362741f57SDave May $    DMSwarmFinalizeFieldRegister(dm)
1284d3a51819SDave May 
1285d3a51819SDave May  The fields represented by DMSwarm are dynamic and can be re-sized at any time.
128662741f57SDave May  The only restriction imposed by DMSwarm is that all fields contain the same number of points.
1287d3a51819SDave May 
1288d3a51819SDave May  To support particle methods, "migration" techniques are provided. These methods migrate data
1289d3a51819SDave May  between MPI-ranks.
1290d3a51819SDave May 
1291d3a51819SDave May  DMSwarm supports the methods DMCreateGlobalVector() and DMCreateLocalVector().
1292d3a51819SDave May  As a DMSwarm may internally define and store values of different data types,
129362741f57SDave May  before calling DMCreateGlobalVector() or DMCreateLocalVector(), the user must inform DMSwarm which
1294d3a51819SDave May  fields should be used to define a Vec object via
1295d3a51819SDave May    DMSwarmVectorDefineField()
1296d3a51819SDave May  The specified field can can changed be changed at any time - thereby permitting vectors
1297d3a51819SDave May  compatable with different fields to be created.
1298d3a51819SDave May 
129962741f57SDave May  A dual representation of fields in the DMSwarm and a Vec object is permitted via
1300d3a51819SDave May    DMSwarmCreateGlobalVectorFromField()
1301d3a51819SDave May  Here the data defining the field in the DMSwarm is shared with a Vec.
1302d3a51819SDave May  This is inherently unsafe if you alter the size of the field at any time between
1303d3a51819SDave May  calls to DMSwarmCreateGlobalVectorFromField() and DMSwarmDestroyGlobalVectorFromField().
1304cc651181SDave May  If the local size of the DMSwarm does not match the local size of the global vector
1305cc651181SDave May  when DMSwarmDestroyGlobalVectorFromField() is called, an error is thrown.
1306d3a51819SDave May 
130762741f57SDave May  Additional high-level support is provided for Particle-In-Cell methods.
130862741f57SDave May  Please refer to the man page for DMSwarmSetType().
130962741f57SDave May 
1310d3a51819SDave May  Level: beginner
1311d3a51819SDave May 
1312d3a51819SDave May .seealso: DMType, DMCreate(), DMSetType()
1313d3a51819SDave May M*/
131457795646SDave May PETSC_EXTERN PetscErrorCode DMCreate_Swarm(DM dm)
131557795646SDave May {
131657795646SDave May   DM_Swarm      *swarm;
131757795646SDave May   PetscErrorCode ierr;
131857795646SDave May 
131957795646SDave May   PetscFunctionBegin;
132057795646SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
132157795646SDave May   ierr     = PetscNewLog(dm,&swarm);CHKERRQ(ierr);
1322f0cdbbbaSDave May   dm->data = swarm;
132357795646SDave May 
13246845f8f5SDave May   ierr = DataBucketCreate(&swarm->db);CHKERRQ(ierr);
1325f0cdbbbaSDave May   ierr = DMSwarmInitializeFieldRegister(dm);CHKERRQ(ierr);
1326f0cdbbbaSDave May 
1327b5bcf523SDave May   swarm->vec_field_set = PETSC_FALSE;
13283454631fSDave May   swarm->issetup = PETSC_FALSE;
1329480eef7bSDave May   swarm->swarm_type = DMSWARM_BASIC;
1330480eef7bSDave May   swarm->migrate_type = DMSWARM_MIGRATE_BASIC;
1331480eef7bSDave May   swarm->collect_type = DMSWARM_COLLECT_BASIC;
133240c453e9SDave May   swarm->migrate_error_on_missing_point = PETSC_FALSE;
1333b62e03f8SDave May 
1334f0cdbbbaSDave May   swarm->dmcell = NULL;
1335f0cdbbbaSDave May   swarm->collect_view_active = PETSC_FALSE;
1336f0cdbbbaSDave May   swarm->collect_view_reset_nlocal = -1;
133757795646SDave May 
1338f0cdbbbaSDave May   dm->dim  = 0;
13395f50eb2eSDave May   dm->ops->view                            = DMView_Swarm;
134057795646SDave May   dm->ops->load                            = NULL;
134157795646SDave May   dm->ops->setfromoptions                  = NULL;
134257795646SDave May   dm->ops->clone                           = NULL;
13433454631fSDave May   dm->ops->setup                           = DMSetup_Swarm;
134457795646SDave May   dm->ops->createdefaultsection            = NULL;
134557795646SDave May   dm->ops->createdefaultconstraints        = NULL;
1346b5bcf523SDave May   dm->ops->createglobalvector              = DMCreateGlobalVector_Swarm;
1347b5bcf523SDave May   dm->ops->createlocalvector               = DMCreateLocalVector_Swarm;
134857795646SDave May   dm->ops->getlocaltoglobalmapping         = NULL;
134957795646SDave May   dm->ops->createfieldis                   = NULL;
135057795646SDave May   dm->ops->createcoordinatedm              = NULL;
135157795646SDave May   dm->ops->getcoloring                     = NULL;
135257795646SDave May   dm->ops->creatematrix                    = NULL;
135357795646SDave May   dm->ops->createinterpolation             = NULL;
135457795646SDave May   dm->ops->getaggregates                   = NULL;
135557795646SDave May   dm->ops->getinjection                    = NULL;
135683c47955SMatthew G. Knepley   dm->ops->createmassmatrix                = DMCreateMassMatrix_Swarm;
135757795646SDave May   dm->ops->refine                          = NULL;
135857795646SDave May   dm->ops->coarsen                         = NULL;
135957795646SDave May   dm->ops->refinehierarchy                 = NULL;
136057795646SDave May   dm->ops->coarsenhierarchy                = NULL;
136157795646SDave May   dm->ops->globaltolocalbegin              = NULL;
136257795646SDave May   dm->ops->globaltolocalend                = NULL;
136357795646SDave May   dm->ops->localtoglobalbegin              = NULL;
136457795646SDave May   dm->ops->localtoglobalend                = NULL;
136557795646SDave May   dm->ops->destroy                         = DMDestroy_Swarm;
136657795646SDave May   dm->ops->createsubdm                     = NULL;
136757795646SDave May   dm->ops->getdimpoints                    = NULL;
136857795646SDave May   dm->ops->locatepoints                    = NULL;
136957795646SDave May   PetscFunctionReturn(0);
137057795646SDave May }
1371