xref: /petsc/src/dm/impls/swarm/swarm.c (revision adb2528b553d527cfac768400eebfea01e6428b8)
157795646SDave May #define PETSCDM_DLL
257795646SDave May #include <petsc/private/dmswarmimpl.h>    /*I   "petscdmswarm.h"   I*/
3e8f14785SLisandro Dalcin #include <petsc/private/hashsetij.h>
40643ed39SMatthew G. Knepley #include <petsc/private/petscfeimpl.h>
55917a6f0SStefano Zampini #include <petscviewer.h>
65917a6f0SStefano Zampini #include <petscdraw.h>
783c47955SMatthew G. Knepley #include <petscdmplex.h>
8279f676cSBarry Smith #include "../src/dm/impls/swarm/data_bucket.h"
957795646SDave May 
10f2b2bee7SDave May PetscLogEvent DMSWARM_Migrate, DMSWARM_SetSizes, DMSWARM_AddPoints, DMSWARM_RemovePoints, DMSWARM_Sort;
11ed923d71SDave May PetscLogEvent DMSWARM_DataExchangerTopologySetup, DMSWARM_DataExchangerBegin, DMSWARM_DataExchangerEnd;
12ed923d71SDave May PetscLogEvent DMSWARM_DataExchangerSendCount, DMSWARM_DataExchangerPack;
13ed923d71SDave May 
14f0cdbbbaSDave May const char* DMSwarmTypeNames[] = { "basic", "pic", 0 };
15f0cdbbbaSDave May const char* DMSwarmMigrateTypeNames[] = { "basic", "dmcellnscatter", "dmcellexact", "user", 0 };
16f0cdbbbaSDave May const char* DMSwarmCollectTypeNames[] = { "basic", "boundingbox", "general", "user", 0 };
17e2d107dbSDave May const char* DMSwarmPICLayoutTypeNames[] = { "regular", "gauss", "subdivision", 0 };
18f0cdbbbaSDave May 
19f0cdbbbaSDave May const char DMSwarmField_pid[] = "DMSwarm_pid";
20f0cdbbbaSDave May const char DMSwarmField_rank[] = "DMSwarm_rank";
21f0cdbbbaSDave May const char DMSwarmPICField_coor[] = "DMSwarmPIC_coor";
22e2d107dbSDave May const char DMSwarmPICField_cellid[] = "DMSwarm_cellid";
23f0cdbbbaSDave May 
24d3a51819SDave May /*@C
2562741f57SDave May    DMSwarmVectorDefineField - Sets the field from which to define a Vec object
2662741f57SDave May                              when DMCreateLocalVector(), or DMCreateGlobalVector() is called
2757795646SDave May 
28d3a51819SDave May    Collective on DM
2957795646SDave May 
30d3a51819SDave May    Input parameters:
3162741f57SDave May +  dm - a DMSwarm
3262741f57SDave May -  fieldname - the textual name given to a registered field
3357795646SDave May 
34d3a51819SDave May    Level: beginner
3557795646SDave May 
36d3a51819SDave May    Notes:
37e7af74c8SDave May 
3862741f57SDave May    The field with name fieldname must be defined as having a data type of PetscScalar.
39e7af74c8SDave May 
40d3a51819SDave May    This function must be called prior to calling DMCreateLocalVector(), DMCreateGlobalVector().
41d3a51819SDave May    Mutiple calls to DMSwarmVectorDefineField() are permitted.
4257795646SDave May 
438b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMCreateGlobalVector(), DMCreateLocalVector()
44d3a51819SDave May @*/
45b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmVectorDefineField(DM dm,const char fieldname[])
46b5bcf523SDave May {
47b5bcf523SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
48b5bcf523SDave May   PetscErrorCode ierr;
49b5bcf523SDave May   PetscInt       bs,n;
50b5bcf523SDave May   PetscScalar    *array;
51b5bcf523SDave May   PetscDataType  type;
52b5bcf523SDave May 
53a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
543454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
5577048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db,&n,NULL,NULL);CHKERRQ(ierr);
56b5bcf523SDave May   ierr = DMSwarmGetField(dm,fieldname,&bs,&type,(void**)&array);CHKERRQ(ierr);
57b5bcf523SDave May 
58b5bcf523SDave May   /* Check all fields are of type PETSC_REAL or PETSC_SCALAR */
59b5bcf523SDave May   if (type != PETSC_REAL) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only valid for PETSC_REAL");
60521f74f9SMatthew G. Knepley   ierr = PetscSNPrintf(swarm->vec_field_name,PETSC_MAX_PATH_LEN-1,"%s",fieldname);CHKERRQ(ierr);
61b5bcf523SDave May   swarm->vec_field_set = PETSC_TRUE;
621b1ea282SDave May   swarm->vec_field_bs = bs;
63b5bcf523SDave May   swarm->vec_field_nlocal = n;
64dcf43ee8SDave May   ierr = DMSwarmRestoreField(dm,fieldname,&bs,&type,(void**)&array);CHKERRQ(ierr);
65b5bcf523SDave May   PetscFunctionReturn(0);
66b5bcf523SDave May }
67b5bcf523SDave May 
68cc651181SDave May /* requires DMSwarmDefineFieldVector has been called */
69b5bcf523SDave May PetscErrorCode DMCreateGlobalVector_Swarm(DM dm,Vec *vec)
70b5bcf523SDave May {
71b5bcf523SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
72b5bcf523SDave May   PetscErrorCode ierr;
73b5bcf523SDave May   Vec            x;
74b5bcf523SDave May   char           name[PETSC_MAX_PATH_LEN];
75b5bcf523SDave May 
76a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
773454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
78b5bcf523SDave May   if (!swarm->vec_field_set) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmVectorDefineField first");
79cc651181SDave 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 */
80cc651181SDave May 
81521f74f9SMatthew G. Knepley   ierr = PetscSNPrintf(name,PETSC_MAX_PATH_LEN-1,"DMSwarmField_%s",swarm->vec_field_name);CHKERRQ(ierr);
82b5bcf523SDave May   ierr = VecCreate(PetscObjectComm((PetscObject)dm),&x);CHKERRQ(ierr);
83b5bcf523SDave May   ierr = PetscObjectSetName((PetscObject)x,name);CHKERRQ(ierr);
841b1ea282SDave May   ierr = VecSetSizes(x,swarm->db->L*swarm->vec_field_bs,PETSC_DETERMINE);CHKERRQ(ierr);
85b5bcf523SDave May   ierr = VecSetBlockSize(x,swarm->vec_field_bs);CHKERRQ(ierr);
86b5bcf523SDave May   ierr = VecSetFromOptions(x);CHKERRQ(ierr);
87b5bcf523SDave May   *vec = x;
88b5bcf523SDave May   PetscFunctionReturn(0);
89b5bcf523SDave May }
90b5bcf523SDave May 
91b5bcf523SDave May /* requires DMSwarmDefineFieldVector has been called */
92b5bcf523SDave May PetscErrorCode DMCreateLocalVector_Swarm(DM dm,Vec *vec)
93b5bcf523SDave May {
94b5bcf523SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
95b5bcf523SDave May   PetscErrorCode ierr;
96b5bcf523SDave May   Vec x;
97b5bcf523SDave May   char name[PETSC_MAX_PATH_LEN];
98b5bcf523SDave May 
99a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
1003454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
101b5bcf523SDave May   if (!swarm->vec_field_set) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmVectorDefineField first");
102cc651181SDave 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 */
103cc651181SDave May 
104521f74f9SMatthew G. Knepley   ierr = PetscSNPrintf(name,PETSC_MAX_PATH_LEN-1,"DMSwarmField_%s",swarm->vec_field_name);CHKERRQ(ierr);
105b5bcf523SDave May   ierr = VecCreate(PETSC_COMM_SELF,&x);CHKERRQ(ierr);
106b5bcf523SDave May   ierr = PetscObjectSetName((PetscObject)x,name);CHKERRQ(ierr);
107071900c8SMatthew G. Knepley   ierr = VecSetSizes(x,swarm->db->L*swarm->vec_field_bs,PETSC_DETERMINE);CHKERRQ(ierr);
108b5bcf523SDave May   ierr = VecSetBlockSize(x,swarm->vec_field_bs);CHKERRQ(ierr);
109b5bcf523SDave May   ierr = VecSetFromOptions(x);CHKERRQ(ierr);
110b5bcf523SDave May   *vec = x;
111b5bcf523SDave May   PetscFunctionReturn(0);
112b5bcf523SDave May }
113b5bcf523SDave May 
114fb1bcc12SMatthew G. Knepley static PetscErrorCode DMSwarmDestroyVectorFromField_Private(DM dm, const char fieldname[], Vec *vec)
115fb1bcc12SMatthew G. Knepley {
116fb1bcc12SMatthew G. Knepley   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
11777048351SPatrick Sanan   DMSwarmDataField      gfield;
118fb1bcc12SMatthew G. Knepley   void         (*fptr)(void);
119fb1bcc12SMatthew G. Knepley   PetscInt       bs, nlocal;
120fb1bcc12SMatthew G. Knepley   char           name[PETSC_MAX_PATH_LEN];
121fb1bcc12SMatthew G. Knepley   PetscErrorCode ierr;
122d3a51819SDave May 
123fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
124fb1bcc12SMatthew G. Knepley   ierr = VecGetLocalSize(*vec, &nlocal);CHKERRQ(ierr);
125fb1bcc12SMatthew G. Knepley   ierr = VecGetBlockSize(*vec, &bs);CHKERRQ(ierr);
126fb1bcc12SMatthew 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 */
12777048351SPatrick Sanan   ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield);CHKERRQ(ierr);
128fb1bcc12SMatthew G. Knepley   /* check vector is an inplace array */
129521f74f9SMatthew G. Knepley   ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarm_VecFieldInPlace_%s", fieldname);CHKERRQ(ierr);
130fb1bcc12SMatthew G. Knepley   ierr = PetscObjectQueryFunction((PetscObject) *vec, name, &fptr);CHKERRQ(ierr);
131fb1bcc12SMatthew G. Knepley   if (!fptr) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_USER, "Vector being destroyed was not created from DMSwarm field(%s)", fieldname);
13277048351SPatrick Sanan   ierr = DMSwarmDataFieldRestoreAccess(gfield);CHKERRQ(ierr);
133fb1bcc12SMatthew G. Knepley   ierr = VecDestroy(vec);CHKERRQ(ierr);
134fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
135fb1bcc12SMatthew G. Knepley }
136fb1bcc12SMatthew G. Knepley 
137fb1bcc12SMatthew G. Knepley static PetscErrorCode DMSwarmCreateVectorFromField_Private(DM dm, const char fieldname[], MPI_Comm comm, Vec *vec)
138fb1bcc12SMatthew G. Knepley {
139fb1bcc12SMatthew G. Knepley   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
140fb1bcc12SMatthew G. Knepley   PetscDataType  type;
141fb1bcc12SMatthew G. Knepley   PetscScalar   *array;
142fb1bcc12SMatthew G. Knepley   PetscInt       bs, n;
143fb1bcc12SMatthew G. Knepley   char           name[PETSC_MAX_PATH_LEN];
144e4fbd051SBarry Smith   PetscMPIInt    size;
145fb1bcc12SMatthew G. Knepley   PetscErrorCode ierr;
146fb1bcc12SMatthew G. Knepley 
147fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
148fb1bcc12SMatthew G. Knepley   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
14977048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db, &n, NULL, NULL);CHKERRQ(ierr);
150fb1bcc12SMatthew G. Knepley   ierr = DMSwarmGetField(dm, fieldname, &bs, &type, (void **) &array);CHKERRQ(ierr);
151fb1bcc12SMatthew G. Knepley   if (type != PETSC_REAL) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Only valid for PETSC_REAL");
152fb1bcc12SMatthew G. Knepley 
153e4fbd051SBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr);
154e4fbd051SBarry Smith   if (size == 1) {
155fb1bcc12SMatthew G. Knepley     ierr = VecCreateSeqWithArray(comm, bs, n*bs, array, vec);CHKERRQ(ierr);
156fb1bcc12SMatthew G. Knepley   } else {
157fb1bcc12SMatthew G. Knepley     ierr = VecCreateMPIWithArray(comm, bs, n*bs, PETSC_DETERMINE, array, vec);CHKERRQ(ierr);
158fb1bcc12SMatthew G. Knepley   }
159fb1bcc12SMatthew G. Knepley   ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarmSharedField_%s", fieldname);CHKERRQ(ierr);
160fb1bcc12SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) *vec, name);CHKERRQ(ierr);
161fb1bcc12SMatthew G. Knepley 
162fb1bcc12SMatthew G. Knepley   /* Set guard */
163fb1bcc12SMatthew G. Knepley   ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarm_VecFieldInPlace_%s", fieldname);CHKERRQ(ierr);
164fb1bcc12SMatthew G. Knepley   ierr = PetscObjectComposeFunction((PetscObject) *vec, name, DMSwarmDestroyVectorFromField_Private);CHKERRQ(ierr);
165fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
166fb1bcc12SMatthew G. Knepley }
167fb1bcc12SMatthew G. Knepley 
1680643ed39SMatthew G. Knepley /* This creates a "mass matrix" between a finite element and particle space. If a finite element interpolant is given by
1690643ed39SMatthew G. Knepley 
1700643ed39SMatthew G. Knepley      \hat f = \sum_i f_i \phi_i
1710643ed39SMatthew G. Knepley 
1720643ed39SMatthew G. Knepley    and a particle function is given by
1730643ed39SMatthew G. Knepley 
1740643ed39SMatthew G. Knepley      f = \sum_i w_i \delta(x - x_i)
1750643ed39SMatthew G. Knepley 
1760643ed39SMatthew G. Knepley    then we want to require that
1770643ed39SMatthew G. Knepley 
1780643ed39SMatthew G. Knepley      M \hat f = M_p f
1790643ed39SMatthew G. Knepley 
1800643ed39SMatthew G. Knepley    where the particle mass matrix is given by
1810643ed39SMatthew G. Knepley 
1820643ed39SMatthew G. Knepley      (M_p)_{ij} = \int \phi_i \delta(x - x_j)
1830643ed39SMatthew G. Knepley 
1840643ed39SMatthew G. Knepley    The way Dave May does particles, they amount to quadratue weights rather than delta functions, so he has |J| is in
1850643ed39SMatthew G. Knepley    his integral. We allow this with the boolean flag.
1860643ed39SMatthew G. Knepley */
1870643ed39SMatthew G. Knepley static PetscErrorCode DMSwarmComputeMassMatrix_Private(DM dmc, DM dmf, Mat mass, PetscBool useDeltaFunction, void *ctx)
18883c47955SMatthew G. Knepley {
18983c47955SMatthew G. Knepley   const char    *name = "Mass Matrix";
1900643ed39SMatthew G. Knepley   MPI_Comm       comm;
19183c47955SMatthew G. Knepley   PetscDS        prob;
19283c47955SMatthew G. Knepley   PetscSection   fsection, globalFSection;
193e8f14785SLisandro Dalcin   PetscHSetIJ    ht;
1940643ed39SMatthew G. Knepley   PetscLayout    rLayout, colLayout;
19583c47955SMatthew G. Knepley   PetscInt      *dnz, *onz;
196*adb2528bSMark Adams   PetscInt       locRows, locCols, rStart, colStart, colEnd, *rowIDXs;
1970643ed39SMatthew G. Knepley   PetscReal     *xi, *v0, *J, *invJ, detJ = 1.0, v0ref[3] = {-1.0, -1.0, -1.0};
19883c47955SMatthew G. Knepley   PetscScalar   *elemMat;
1990643ed39SMatthew G. Knepley   PetscInt       dim, Nf, field, cStart, cEnd, cell, totDim, maxC = 0;
20083c47955SMatthew G. Knepley   PetscErrorCode ierr;
20183c47955SMatthew G. Knepley 
20283c47955SMatthew G. Knepley   PetscFunctionBegin;
2030643ed39SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) mass, &comm);CHKERRQ(ierr);
20483c47955SMatthew G. Knepley   ierr = DMGetCoordinateDim(dmf, &dim);CHKERRQ(ierr);
20583c47955SMatthew G. Knepley   ierr = DMGetDS(dmf, &prob);CHKERRQ(ierr);
20683c47955SMatthew G. Knepley   ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr);
2070643ed39SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr);
20883c47955SMatthew G. Knepley   ierr = PetscMalloc3(dim, &v0, dim*dim, &J, dim*dim,&invJ);CHKERRQ(ierr);
20983c47955SMatthew G. Knepley   ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);
21083c47955SMatthew G. Knepley   ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);
21183c47955SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd);CHKERRQ(ierr);
2120643ed39SMatthew G. Knepley   ierr = MatGetLocalSize(mass, &locRows, &locCols);CHKERRQ(ierr);
21383c47955SMatthew G. Knepley 
2140643ed39SMatthew G. Knepley   ierr = PetscLayoutCreate(comm, &colLayout);CHKERRQ(ierr);
2150643ed39SMatthew G. Knepley   ierr = PetscLayoutSetLocalSize(colLayout, locCols);CHKERRQ(ierr);
2160643ed39SMatthew G. Knepley   ierr = PetscLayoutSetBlockSize(colLayout, 1);CHKERRQ(ierr);
2170643ed39SMatthew G. Knepley   ierr = PetscLayoutSetUp(colLayout);CHKERRQ(ierr);
2180643ed39SMatthew G. Knepley   ierr = PetscLayoutGetRange(colLayout, &colStart, &colEnd);CHKERRQ(ierr);
2190643ed39SMatthew G. Knepley   ierr = PetscLayoutDestroy(&colLayout);CHKERRQ(ierr);
2200643ed39SMatthew G. Knepley 
2210643ed39SMatthew G. Knepley   ierr = PetscLayoutCreate(comm, &rLayout);CHKERRQ(ierr);
22283c47955SMatthew G. Knepley   ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr);
22383c47955SMatthew G. Knepley   ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr);
22483c47955SMatthew G. Knepley   ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr);
2250643ed39SMatthew G. Knepley   ierr = PetscLayoutGetRange(rLayout, &rStart, NULL);CHKERRQ(ierr);
22683c47955SMatthew G. Knepley   ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr);
2270643ed39SMatthew G. Knepley 
22883c47955SMatthew G. Knepley   ierr = PetscCalloc2(locRows, &dnz, locRows, &onz);CHKERRQ(ierr);
229e8f14785SLisandro Dalcin   ierr = PetscHSetIJCreate(&ht);CHKERRQ(ierr);
230*adb2528bSMark Adams   /* ierr = PetscSynchronizedPrintf(comm, "DMSwarmComputeMassMatrix_Private: rStart = %D rEnd = %D colStart = %D colEnd = %D\n", rStart, rStart+locRows, colStart, colEnd);CHKERRQ(ierr); */
2310643ed39SMatthew G. Knepley   ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);
2320643ed39SMatthew G. Knepley   /* count non-zeros */
2330643ed39SMatthew G. Knepley   ierr = DMSwarmSortGetAccess(dmc);CHKERRQ(ierr);
23483c47955SMatthew G. Knepley   for (field = 0; field < Nf; ++field) {
23583c47955SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
2360643ed39SMatthew G. Knepley       PetscInt  c, i;
2370643ed39SMatthew G. Knepley       PetscInt *findices,   *cindices; /* fine is vertices, coarse is particles */
23883c47955SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
23983c47955SMatthew G. Knepley 
24083c47955SMatthew G. Knepley       ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
241fc7c92abSMatthew G. Knepley       ierr = DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices);CHKERRQ(ierr);
242fc7c92abSMatthew G. Knepley       maxC = PetscMax(maxC, numCIndices);
24383c47955SMatthew G. Knepley       {
244e8f14785SLisandro Dalcin         PetscHashIJKey key;
245e8f14785SLisandro Dalcin         PetscBool      missing;
2460643ed39SMatthew G. Knepley         /* PetscPrintf(PETSC_COMM_SELF, "\t[%D]DMSwarmComputeMassMatrix_Private: cell %D\n",rank,cell); */
24783c47955SMatthew G. Knepley         for (i = 0; i < numFIndices; ++i) {
248*adb2528bSMark Adams           key.j = findices[i]; /* global column (from Plex) */
2490643ed39SMatthew G. Knepley           /* PetscPrintf(PETSC_COMM_SELF, "\t\t[%D]DMSwarmComputeMassMatrix_Private: j ('fine',vertices) = %D, num rows ('coarse',particles) = %D\n",rank,key.i,numCIndices); */
250*adb2528bSMark Adams           if (key.j >= 0) {
25183c47955SMatthew G. Knepley             /* Get indices for coarse elements */
25283c47955SMatthew G. Knepley             for (c = 0; c < numCIndices; ++c) {
253*adb2528bSMark Adams               key.i = cindices[c] + rStart; /* global cols (from Swarm) */
254*adb2528bSMark Adams               if (key.i < 0) continue;
255e8f14785SLisandro Dalcin               ierr = PetscHSetIJQueryAdd(ht, key, &missing);CHKERRQ(ierr);
25683c47955SMatthew G. Knepley               if (missing) {
257*adb2528bSMark Adams /* PetscPrintf(PETSC_COMM_SELF, "\t\t\t[%D]DMSwarmComputeMassMatrix_Private: new key j (row,particle) = %D, i (col,vertices) = %D\n",-1,key.j,key.i); */
2580643ed39SMatthew G. Knepley                 if ((key.j >= colStart) && (key.j < colEnd)) ++dnz[key.i - rStart];
259e8f14785SLisandro Dalcin                 else                                         ++onz[key.i - rStart];
2600643ed39SMatthew G. Knepley               } else SETERRQ2(PetscObjectComm((PetscObject) dmf), PETSC_ERR_SUP, "Set new value at %D,%D", key.i, key.j);
26183c47955SMatthew G. Knepley             }
262fc7c92abSMatthew G. Knepley           }
263fc7c92abSMatthew G. Knepley         }
26483c47955SMatthew G. Knepley         ierr = PetscFree(cindices);CHKERRQ(ierr);
26583c47955SMatthew G. Knepley       }
26683c47955SMatthew G. Knepley       ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
26783c47955SMatthew G. Knepley     }
26883c47955SMatthew G. Knepley   }
269e8f14785SLisandro Dalcin   ierr = PetscHSetIJDestroy(&ht);CHKERRQ(ierr);
27083c47955SMatthew G. Knepley   ierr = MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL);CHKERRQ(ierr);
27183c47955SMatthew G. Knepley   ierr = MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE);CHKERRQ(ierr);
27283c47955SMatthew G. Knepley   ierr = PetscFree2(dnz, onz);CHKERRQ(ierr);
273*adb2528bSMark Adams   ierr = PetscMalloc3(maxC*totDim, &elemMat, maxC, &rowIDXs, maxC*dim, &xi);CHKERRQ(ierr);
27483c47955SMatthew G. Knepley   for (field = 0; field < Nf; ++field) {
27583c47955SMatthew G. Knepley     PetscObject     obj;
2760643ed39SMatthew G. Knepley     PetscReal      *Bcoarse, *coords;
2770643ed39SMatthew G. Knepley     PetscInt        Nc, i;
27883c47955SMatthew G. Knepley 
27983c47955SMatthew G. Knepley     ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr);
2800643ed39SMatthew G. Knepley     ierr = PetscFEGetNumComponents((PetscFE) obj, &Nc);CHKERRQ(ierr);
2810643ed39SMatthew G. Knepley     if (Nc != 1) SETERRQ1(PetscObjectComm((PetscObject) dmf), PETSC_ERR_SUP, "Can only interpolate a scalar field from particles, Nc = %D", Nc);
2820643ed39SMatthew G. Knepley     ierr = DMSwarmGetField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **) &coords);CHKERRQ(ierr);
28383c47955SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
28483c47955SMatthew G. Knepley       PetscInt *findices  , *cindices;
28583c47955SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
2860643ed39SMatthew G. Knepley       PetscInt  p, c;
28783c47955SMatthew G. Knepley 
2880643ed39SMatthew G. Knepley       /* TODO: Use DMField instead of assuming affine */
28983c47955SMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr);
29083c47955SMatthew G. Knepley       ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
29183c47955SMatthew G. Knepley       ierr = DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices);CHKERRQ(ierr);
2920643ed39SMatthew G. Knepley       for (p = 0; p < numCIndices; ++p) {
2930643ed39SMatthew G. Knepley         CoordinatesRealToRef(dim, dim, v0ref, v0, invJ, &coords[cindices[p]*dim], &xi[p*dim]);
294b30fe131SMark Adams         /* PetscPrintf(PETSC_COMM_SELF,"[%D]DMSwarmComputeMassMatrix_Private: %2D.%D) coord[%D] = (%12.5e, %12.5e) element coord = (%12.5e, %12.5e) cindices[%D]=%D detJ=%12.5e\n",-1,cell,p,cindices[p]*dim,coords[cindices[p]*dim],coords[cindices[p]*dim+1],xi[p*dim],xi[p*dim+1],p,cindices[p],detJ); */
2950643ed39SMatthew G. Knepley       }
2960643ed39SMatthew G. Knepley       ierr = PetscFEGetTabulation((PetscFE) obj, numCIndices, xi, &Bcoarse, NULL, NULL);CHKERRQ(ierr);
29783c47955SMatthew G. Knepley       /* Get elemMat entries by multiplying by weight */
2980643ed39SMatthew G. Knepley       ierr = PetscMemzero(elemMat, numCIndices*totDim * sizeof(PetscScalar));CHKERRQ(ierr);
29983c47955SMatthew G. Knepley       for (i = 0; i < numFIndices; ++i) {
3000643ed39SMatthew G. Knepley         for (p = 0; p < numCIndices; ++p) {
3010643ed39SMatthew G. Knepley           for (c = 0; c < Nc; ++c) {
3020643ed39SMatthew G. Knepley             /* B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c */
303*adb2528bSMark Adams             elemMat[p*numFIndices+i] += Bcoarse[(p*numFIndices + i)*Nc + c]*(useDeltaFunction ? 1.0 : detJ);
3040643ed39SMatthew G. Knepley             /* PetscPrintf(PETSC_COMM_SELF, "\t[%D]DMSwarmComputeMassMatrix_Private: %2D) findices[%D] (col) %D, particle (row) %D (nc=%D) Bcoarse[%2D]=%12.5e\n",rank,cell,i,findices[i],cindices[p],c,(p*numFIndices + i)*Nc + c,Bcoarse[(p*numFIndices + i)*Nc + c]); */
30583c47955SMatthew G. Knepley           }
3060643ed39SMatthew G. Knepley         }
3070643ed39SMatthew G. Knepley       }
308*adb2528bSMark Adams       for (p = 0; p < numCIndices; ++p) rowIDXs[p] = cindices[p] + rStart;
30983c47955SMatthew G. Knepley       if (0) {ierr = DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat);CHKERRQ(ierr);}
310*adb2528bSMark Adams       ierr = MatSetValues(mass, numCIndices, rowIDXs, numFIndices, findices, elemMat, ADD_VALUES);CHKERRQ(ierr);
31183c47955SMatthew G. Knepley       ierr = PetscFree(cindices);CHKERRQ(ierr);
31283c47955SMatthew G. Knepley       ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
3130643ed39SMatthew G. Knepley       ierr = PetscFERestoreTabulation((PetscFE) obj, numCIndices, xi, &Bcoarse, NULL, NULL);CHKERRQ(ierr);
31483c47955SMatthew G. Knepley     }
3150643ed39SMatthew G. Knepley     ierr = DMSwarmRestoreField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **) &coords);CHKERRQ(ierr);
31683c47955SMatthew G. Knepley   }
317*adb2528bSMark Adams   ierr = PetscFree3(elemMat, rowIDXs, xi);CHKERRQ(ierr);
31883c47955SMatthew G. Knepley   ierr = DMSwarmSortRestoreAccess(dmc);CHKERRQ(ierr);
31983c47955SMatthew G. Knepley   ierr = PetscFree3(v0, J, invJ);CHKERRQ(ierr);
32083c47955SMatthew G. Knepley   ierr = MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
32183c47955SMatthew G. Knepley   ierr = MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
32283c47955SMatthew G. Knepley   PetscFunctionReturn(0);
32383c47955SMatthew G. Knepley }
32483c47955SMatthew G. Knepley 
325*adb2528bSMark Adams /* FEM cols, Particle rows */
32683c47955SMatthew G. Knepley static PetscErrorCode DMCreateMassMatrix_Swarm(DM dmCoarse, DM dmFine, Mat *mass)
32783c47955SMatthew G. Knepley {
328895a1698SMatthew G. Knepley   PetscSection   gsf;
32983c47955SMatthew G. Knepley   PetscInt       m, n;
33083c47955SMatthew G. Knepley   void          *ctx;
33183c47955SMatthew G. Knepley   PetscErrorCode ierr;
33283c47955SMatthew G. Knepley 
33383c47955SMatthew G. Knepley   PetscFunctionBegin;
33483c47955SMatthew G. Knepley   ierr = DMGetDefaultGlobalSection(dmFine, &gsf);CHKERRQ(ierr);
33583c47955SMatthew G. Knepley   ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr);
336895a1698SMatthew G. Knepley   ierr = DMSwarmGetLocalSize(dmCoarse, &n);CHKERRQ(ierr);
33783c47955SMatthew G. Knepley   ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr);
338*adb2528bSMark Adams   ierr = MatSetSizes(*mass, n, m, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
33983c47955SMatthew G. Knepley   ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr);
34083c47955SMatthew G. Knepley   ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr);
34183c47955SMatthew G. Knepley 
3420643ed39SMatthew G. Knepley   ierr = DMSwarmComputeMassMatrix_Private(dmCoarse, dmFine, *mass, PETSC_TRUE, ctx);CHKERRQ(ierr);
34383c47955SMatthew G. Knepley   ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr);
34483c47955SMatthew G. Knepley   PetscFunctionReturn(0);
34583c47955SMatthew G. Knepley }
34683c47955SMatthew G. Knepley 
347fb1bcc12SMatthew G. Knepley /*@C
348d3a51819SDave May    DMSwarmCreateGlobalVectorFromField - Creates a Vec object sharing the array associated with a given field
349d3a51819SDave May 
350d3a51819SDave May    Collective on DM
351d3a51819SDave May 
352d3a51819SDave May    Input parameters:
35362741f57SDave May +  dm - a DMSwarm
35462741f57SDave May -  fieldname - the textual name given to a registered field
355d3a51819SDave May 
3568b8a3813SDave May    Output parameter:
357d3a51819SDave May .  vec - the vector
358d3a51819SDave May 
359d3a51819SDave May    Level: beginner
360d3a51819SDave May 
3618b8a3813SDave May    Notes:
3628b8a3813SDave May    The vector must be returned using a matching call to DMSwarmDestroyGlobalVectorFromField().
3638b8a3813SDave May 
3648b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmDestroyGlobalVectorFromField()
365d3a51819SDave May @*/
366b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmCreateGlobalVectorFromField(DM dm,const char fieldname[],Vec *vec)
367b5bcf523SDave May {
368fb1bcc12SMatthew G. Knepley   MPI_Comm       comm = PetscObjectComm((PetscObject) dm);
369b5bcf523SDave May   PetscErrorCode ierr;
370b5bcf523SDave May 
371fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
372fb1bcc12SMatthew G. Knepley   ierr = DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec);CHKERRQ(ierr);
373b5bcf523SDave May   PetscFunctionReturn(0);
374b5bcf523SDave May }
375b5bcf523SDave May 
376d3a51819SDave May /*@C
377d3a51819SDave May    DMSwarmDestroyGlobalVectorFromField - Destroys the Vec object which share the array associated with a given field
378d3a51819SDave May 
379d3a51819SDave May    Collective on DM
380d3a51819SDave May 
381d3a51819SDave May    Input parameters:
38262741f57SDave May +  dm - a DMSwarm
38362741f57SDave May -  fieldname - the textual name given to a registered field
384d3a51819SDave May 
3858b8a3813SDave May    Output parameter:
386d3a51819SDave May .  vec - the vector
387d3a51819SDave May 
388d3a51819SDave May    Level: beginner
389d3a51819SDave May 
3908b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmCreateGlobalVectorFromField()
391d3a51819SDave May @*/
392b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmDestroyGlobalVectorFromField(DM dm,const char fieldname[],Vec *vec)
393b5bcf523SDave May {
394b5bcf523SDave May   PetscErrorCode ierr;
395cc651181SDave May 
396fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
397fb1bcc12SMatthew G. Knepley   ierr = DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec);CHKERRQ(ierr);
398b5bcf523SDave May   PetscFunctionReturn(0);
399b5bcf523SDave May }
400b5bcf523SDave May 
401fb1bcc12SMatthew G. Knepley /*@C
402fb1bcc12SMatthew G. Knepley    DMSwarmCreateLocalVectorFromField - Creates a Vec object sharing the array associated with a given field
403fb1bcc12SMatthew G. Knepley 
404fb1bcc12SMatthew G. Knepley    Collective on DM
405fb1bcc12SMatthew G. Knepley 
406fb1bcc12SMatthew G. Knepley    Input parameters:
40762741f57SDave May +  dm - a DMSwarm
40862741f57SDave May -  fieldname - the textual name given to a registered field
409fb1bcc12SMatthew G. Knepley 
4108b8a3813SDave May    Output parameter:
411fb1bcc12SMatthew G. Knepley .  vec - the vector
412fb1bcc12SMatthew G. Knepley 
413fb1bcc12SMatthew G. Knepley    Level: beginner
414fb1bcc12SMatthew G. Knepley 
4158b8a3813SDave May    Notes:
4168b8a3813SDave May    The vector must be returned using a matching call to DMSwarmDestroyLocalVectorFromField().
4178b8a3813SDave May 
4188b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmDestroyLocalVectorFromField()
419fb1bcc12SMatthew G. Knepley @*/
420fb1bcc12SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMSwarmCreateLocalVectorFromField(DM dm,const char fieldname[],Vec *vec)
421bbe8250bSMatthew G. Knepley {
422fb1bcc12SMatthew G. Knepley   MPI_Comm       comm = PETSC_COMM_SELF;
423bbe8250bSMatthew G. Knepley   PetscErrorCode ierr;
424bbe8250bSMatthew G. Knepley 
425fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
426fb1bcc12SMatthew G. Knepley   ierr = DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec);CHKERRQ(ierr);
427fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
428bbe8250bSMatthew G. Knepley }
429fb1bcc12SMatthew G. Knepley 
430fb1bcc12SMatthew G. Knepley /*@C
431fb1bcc12SMatthew G. Knepley    DMSwarmDestroyLocalVectorFromField - Destroys the Vec object which share the array associated with a given field
432fb1bcc12SMatthew G. Knepley 
433fb1bcc12SMatthew G. Knepley    Collective on DM
434fb1bcc12SMatthew G. Knepley 
435fb1bcc12SMatthew G. Knepley    Input parameters:
43662741f57SDave May +  dm - a DMSwarm
43762741f57SDave May -  fieldname - the textual name given to a registered field
438fb1bcc12SMatthew G. Knepley 
4398b8a3813SDave May    Output parameter:
440fb1bcc12SMatthew G. Knepley .  vec - the vector
441fb1bcc12SMatthew G. Knepley 
442fb1bcc12SMatthew G. Knepley    Level: beginner
443fb1bcc12SMatthew G. Knepley 
4448b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmCreateLocalVectorFromField()
445fb1bcc12SMatthew G. Knepley @*/
446fb1bcc12SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMSwarmDestroyLocalVectorFromField(DM dm,const char fieldname[],Vec *vec)
447fb1bcc12SMatthew G. Knepley {
448fb1bcc12SMatthew G. Knepley   PetscErrorCode ierr;
449fb1bcc12SMatthew G. Knepley 
450fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
451fb1bcc12SMatthew G. Knepley   ierr = DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec);CHKERRQ(ierr);
452bbe8250bSMatthew G. Knepley   PetscFunctionReturn(0);
453bbe8250bSMatthew G. Knepley }
454bbe8250bSMatthew G. Knepley 
455b5bcf523SDave May /*
456b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmCreateGlobalVectorFromFields(DM dm,const PetscInt nf,const char *fieldnames[],Vec *vec)
457b5bcf523SDave May {
458b5bcf523SDave May   PetscFunctionReturn(0);
459b5bcf523SDave May }
460b5bcf523SDave May 
461b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmRestoreGlobalVectorFromFields(DM dm,Vec *vec)
462b5bcf523SDave May {
463b5bcf523SDave May   PetscFunctionReturn(0);
464b5bcf523SDave May }
465b5bcf523SDave May */
466b5bcf523SDave May 
467d3a51819SDave May /*@C
468d3a51819SDave May    DMSwarmInitializeFieldRegister - Initiates the registration of fields to a DMSwarm
469d3a51819SDave May 
470d3a51819SDave May    Collective on DM
471d3a51819SDave May 
472d3a51819SDave May    Input parameter:
473d3a51819SDave May .  dm - a DMSwarm
474d3a51819SDave May 
475d3a51819SDave May    Level: beginner
476d3a51819SDave May 
477d3a51819SDave May    Notes:
4788b8a3813SDave May    After all fields have been registered, you must call DMSwarmFinalizeFieldRegister().
479d3a51819SDave May 
480d3a51819SDave May .seealso: DMSwarmFinalizeFieldRegister(), DMSwarmRegisterPetscDatatypeField(),
481d3a51819SDave May  DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
482d3a51819SDave May @*/
4835f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmInitializeFieldRegister(DM dm)
4845f50eb2eSDave May {
4855f50eb2eSDave May   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
4863454631fSDave May   PetscErrorCode ierr;
4873454631fSDave May 
488521f74f9SMatthew G. Knepley   PetscFunctionBegin;
489cc651181SDave May   if (!swarm->field_registration_initialized) {
4905f50eb2eSDave May     swarm->field_registration_initialized = PETSC_TRUE;
491f0cdbbbaSDave May     ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_pid,1,PETSC_LONG);CHKERRQ(ierr); /* unique identifer */
492f0cdbbbaSDave May     ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_rank,1,PETSC_INT);CHKERRQ(ierr); /* used for communication */
493cc651181SDave May   }
4945f50eb2eSDave May   PetscFunctionReturn(0);
4955f50eb2eSDave May }
4965f50eb2eSDave May 
497d3a51819SDave May /*@C
498d3a51819SDave May    DMSwarmFinalizeFieldRegister - Finalizes the registration of fields to a DMSwarm
499d3a51819SDave May 
500d3a51819SDave May    Collective on DM
501d3a51819SDave May 
502d3a51819SDave May    Input parameter:
503d3a51819SDave May .  dm - a DMSwarm
504d3a51819SDave May 
505d3a51819SDave May    Level: beginner
506d3a51819SDave May 
507d3a51819SDave May    Notes:
50862741f57SDave May    After DMSwarmFinalizeFieldRegister() has been called, no new fields can be defined on the DMSwarm.
509d3a51819SDave May 
510d3a51819SDave May .seealso: DMSwarmInitializeFieldRegister(), DMSwarmRegisterPetscDatatypeField(),
511d3a51819SDave May  DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
512d3a51819SDave May @*/
5135f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmFinalizeFieldRegister(DM dm)
5145f50eb2eSDave May {
5155f50eb2eSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
5166845f8f5SDave May   PetscErrorCode ierr;
5176845f8f5SDave May 
518521f74f9SMatthew G. Knepley   PetscFunctionBegin;
519f0cdbbbaSDave May   if (!swarm->field_registration_finalized) {
52077048351SPatrick Sanan     ierr = DMSwarmDataBucketFinalize(swarm->db);CHKERRQ(ierr);
521f0cdbbbaSDave May   }
522f0cdbbbaSDave May   swarm->field_registration_finalized = PETSC_TRUE;
5235f50eb2eSDave May   PetscFunctionReturn(0);
5245f50eb2eSDave May }
5255f50eb2eSDave May 
526d3a51819SDave May /*@C
527d3a51819SDave May    DMSwarmSetLocalSizes - Sets the length of all registered fields on the DMSwarm
528d3a51819SDave May 
529d3a51819SDave May    Not collective
530d3a51819SDave May 
531d3a51819SDave May    Input parameters:
53262741f57SDave May +  dm - a DMSwarm
533d3a51819SDave May .  nlocal - the length of each registered field
53462741f57SDave May -  buffer - the length of the buffer used to efficient dynamic re-sizing
535d3a51819SDave May 
536d3a51819SDave May    Level: beginner
537d3a51819SDave May 
538d3a51819SDave May .seealso: DMSwarmGetLocalSize()
539d3a51819SDave May @*/
5405f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmSetLocalSizes(DM dm,PetscInt nlocal,PetscInt buffer)
5415f50eb2eSDave May {
5425f50eb2eSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
5436845f8f5SDave May   PetscErrorCode ierr;
5445f50eb2eSDave May 
545521f74f9SMatthew G. Knepley   PetscFunctionBegin;
546f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_SetSizes,0,0,0,0);CHKERRQ(ierr);
54777048351SPatrick Sanan   ierr = DMSwarmDataBucketSetSizes(swarm->db,nlocal,buffer);CHKERRQ(ierr);
548f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_SetSizes,0,0,0,0);CHKERRQ(ierr);
5495f50eb2eSDave May   PetscFunctionReturn(0);
5505f50eb2eSDave May }
5515f50eb2eSDave May 
552d3a51819SDave May /*@C
553d3a51819SDave May    DMSwarmSetCellDM - Attachs a DM to a DMSwarm
554d3a51819SDave May 
555d3a51819SDave May    Collective on DM
556d3a51819SDave May 
557d3a51819SDave May    Input parameters:
55862741f57SDave May +  dm - a DMSwarm
55962741f57SDave May -  dmcell - the DM to attach to the DMSwarm
560d3a51819SDave May 
561d3a51819SDave May    Level: beginner
562d3a51819SDave May 
563d3a51819SDave May    Notes:
564d3a51819SDave May    The attached DM (dmcell) will be queried for point location and
5658b8a3813SDave May    neighbor MPI-rank information if DMSwarmMigrate() is called.
566d3a51819SDave May 
5678b8a3813SDave May .seealso: DMSwarmSetType(), DMSwarmGetCellDM(), DMSwarmMigrate()
568d3a51819SDave May @*/
569b16650c8SDave May PETSC_EXTERN PetscErrorCode DMSwarmSetCellDM(DM dm,DM dmcell)
570b16650c8SDave May {
571b16650c8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
572521f74f9SMatthew G. Knepley 
573521f74f9SMatthew G. Knepley   PetscFunctionBegin;
574b16650c8SDave May   swarm->dmcell = dmcell;
575b16650c8SDave May   PetscFunctionReturn(0);
576b16650c8SDave May }
577b16650c8SDave May 
578d3a51819SDave May /*@C
579d3a51819SDave May    DMSwarmGetCellDM - Fetches the attached cell DM
580d3a51819SDave May 
581d3a51819SDave May    Collective on DM
582d3a51819SDave May 
583d3a51819SDave May    Input parameter:
584d3a51819SDave May .  dm - a DMSwarm
585d3a51819SDave May 
586d3a51819SDave May    Output parameter:
587d3a51819SDave May .  dmcell - the DM which was attached to the DMSwarm
588d3a51819SDave May 
589d3a51819SDave May    Level: beginner
590d3a51819SDave May 
591d3a51819SDave May .seealso: DMSwarmSetCellDM()
592d3a51819SDave May @*/
593fe39f135SDave May PETSC_EXTERN PetscErrorCode DMSwarmGetCellDM(DM dm,DM *dmcell)
594fe39f135SDave May {
595fe39f135SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
596521f74f9SMatthew G. Knepley 
597521f74f9SMatthew G. Knepley   PetscFunctionBegin;
598fe39f135SDave May   *dmcell = swarm->dmcell;
599fe39f135SDave May   PetscFunctionReturn(0);
600fe39f135SDave May }
601fe39f135SDave May 
602d3a51819SDave May /*@C
603d3a51819SDave May    DMSwarmGetLocalSize - Retrives the local length of fields registered
604d3a51819SDave May 
605d3a51819SDave May    Not collective
606d3a51819SDave May 
607d3a51819SDave May    Input parameter:
608d3a51819SDave May .  dm - a DMSwarm
609d3a51819SDave May 
610d3a51819SDave May    Output parameter:
611d3a51819SDave May .  nlocal - the length of each registered field
612d3a51819SDave May 
613d3a51819SDave May    Level: beginner
614d3a51819SDave May 
6158b8a3813SDave May .seealso: DMSwarmGetSize(), DMSwarmSetLocalSizes()
616d3a51819SDave May @*/
617dcf43ee8SDave May PETSC_EXTERN PetscErrorCode DMSwarmGetLocalSize(DM dm,PetscInt *nlocal)
618dcf43ee8SDave May {
619dcf43ee8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
620dcf43ee8SDave May   PetscErrorCode ierr;
621dcf43ee8SDave May 
622521f74f9SMatthew G. Knepley   PetscFunctionBegin;
62377048351SPatrick Sanan   if (nlocal) {ierr = DMSwarmDataBucketGetSizes(swarm->db,nlocal,NULL,NULL);CHKERRQ(ierr);}
624dcf43ee8SDave May   PetscFunctionReturn(0);
625dcf43ee8SDave May }
626dcf43ee8SDave May 
627d3a51819SDave May /*@C
628d3a51819SDave May    DMSwarmGetSize - Retrives the total length of fields registered
629d3a51819SDave May 
630d3a51819SDave May    Collective on DM
631d3a51819SDave May 
632d3a51819SDave May    Input parameter:
633d3a51819SDave May .  dm - a DMSwarm
634d3a51819SDave May 
635d3a51819SDave May    Output parameter:
636d3a51819SDave May .  n - the total length of each registered field
637d3a51819SDave May 
638d3a51819SDave May    Level: beginner
639d3a51819SDave May 
640d3a51819SDave May    Note:
641d3a51819SDave May    This calls MPI_Allreduce upon each call (inefficient but safe)
642d3a51819SDave May 
6438b8a3813SDave May .seealso: DMSwarmGetLocalSize(), DMSwarmSetLocalSizes()
644d3a51819SDave May @*/
645dcf43ee8SDave May PETSC_EXTERN PetscErrorCode DMSwarmGetSize(DM dm,PetscInt *n)
646dcf43ee8SDave May {
647dcf43ee8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
648dcf43ee8SDave May   PetscErrorCode ierr;
649dcf43ee8SDave May   PetscInt       nlocal,ng;
650dcf43ee8SDave May 
651521f74f9SMatthew G. Knepley   PetscFunctionBegin;
65277048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
653dcf43ee8SDave May   ierr = MPI_Allreduce(&nlocal,&ng,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
654dcf43ee8SDave May   if (n) { *n = ng; }
655dcf43ee8SDave May   PetscFunctionReturn(0);
656dcf43ee8SDave May }
657dcf43ee8SDave May 
658d3a51819SDave May /*@C
6598b8a3813SDave May    DMSwarmRegisterPetscDatatypeField - Register a field to a DMSwarm with a native PETSc data type
660d3a51819SDave May 
661d3a51819SDave May    Collective on DM
662d3a51819SDave May 
663d3a51819SDave May    Input parameters:
66462741f57SDave May +  dm - a DMSwarm
665d3a51819SDave May .  fieldname - the textual name to identify this field
666d3a51819SDave May .  blocksize - the number of each data type
66762741f57SDave May -  type - a valid PETSc data type (PETSC_CHAR, PETSC_SHORT, PETSC_INT, PETSC_FLOAT, PETSC_REAL, PETSC_LONG)
668d3a51819SDave May 
669d3a51819SDave May    Level: beginner
670d3a51819SDave May 
671d3a51819SDave May    Notes:
6728b8a3813SDave May    The textual name for each registered field must be unique.
673d3a51819SDave May 
674d3a51819SDave May .seealso: DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
675d3a51819SDave May @*/
6765f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmRegisterPetscDatatypeField(DM dm,const char fieldname[],PetscInt blocksize,PetscDataType type)
677b62e03f8SDave May {
6782eac95f8SDave May   PetscErrorCode ierr;
679b62e03f8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
680b62e03f8SDave May   size_t         size;
681b62e03f8SDave May 
682521f74f9SMatthew G. Knepley   PetscFunctionBegin;
6835f50eb2eSDave May   if (!swarm->field_registration_initialized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmInitializeFieldRegister() first");
6845f50eb2eSDave May   if (swarm->field_registration_finalized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Cannot register additional fields after calling DMSwarmFinalizeFieldRegister() first");
6855f50eb2eSDave May 
6865f50eb2eSDave May   if (type == PETSC_OBJECT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
6875f50eb2eSDave May   if (type == PETSC_FUNCTION) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
6885f50eb2eSDave May   if (type == PETSC_STRING) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
6895f50eb2eSDave May   if (type == PETSC_STRUCT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
6905f50eb2eSDave May   if (type == PETSC_DATATYPE_UNKNOWN) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
691b62e03f8SDave May 
6922ddcf43eSMatthew G. Knepley   ierr = PetscDataTypeGetSize(type, &size);CHKERRQ(ierr);
693b62e03f8SDave May   /* Load a specific data type into data bucket, specifying textual name and its size in bytes */
69477048351SPatrick Sanan   ierr = DMSwarmDataBucketRegisterField(swarm->db,"DMSwarmRegisterPetscDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
69552c3ed93SDave May   {
69677048351SPatrick Sanan     DMSwarmDataField gfield;
69752c3ed93SDave May 
69877048351SPatrick Sanan     ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
69977048351SPatrick Sanan     ierr = DMSwarmDataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
70052c3ed93SDave May   }
701b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = type;
702b62e03f8SDave May   PetscFunctionReturn(0);
703b62e03f8SDave May }
704b62e03f8SDave May 
705d3a51819SDave May /*@C
706d3a51819SDave May    DMSwarmRegisterUserStructField - Register a user defined struct 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
71362741f57SDave May -  size - the size in bytes of the user struct of each data type
714d3a51819SDave May 
715d3a51819SDave May    Level: beginner
716d3a51819SDave May 
717d3a51819SDave May    Notes:
7188b8a3813SDave May    The textual name for each registered field must be unique.
719d3a51819SDave May 
720d3a51819SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserDatatypeField()
721d3a51819SDave May @*/
7225f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmRegisterUserStructField(DM dm,const char fieldname[],size_t size)
723b62e03f8SDave May {
7242eac95f8SDave May   PetscErrorCode ierr;
725b62e03f8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
726b62e03f8SDave May 
727521f74f9SMatthew G. Knepley   PetscFunctionBegin;
72877048351SPatrick Sanan   ierr = DMSwarmDataBucketRegisterField(swarm->db,"DMSwarmRegisterUserStructField",fieldname,size,NULL);CHKERRQ(ierr);
729b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_STRUCT ;
730b62e03f8SDave May   PetscFunctionReturn(0);
731b62e03f8SDave May }
732b62e03f8SDave May 
733d3a51819SDave May /*@C
734d3a51819SDave May    DMSwarmRegisterUserDatatypeField - Register a user defined data type to a DMSwarm
735d3a51819SDave May 
736d3a51819SDave May    Collective on DM
737d3a51819SDave May 
738d3a51819SDave May    Input parameters:
73962741f57SDave May +  dm - a DMSwarm
740d3a51819SDave May .  fieldname - the textual name to identify this field
741d3a51819SDave May .  size - the size in bytes of the user data type
74262741f57SDave May -  blocksize - the number of each data type
743d3a51819SDave May 
744d3a51819SDave May    Level: beginner
745d3a51819SDave May 
746d3a51819SDave May    Notes:
7478b8a3813SDave May    The textual name for each registered field must be unique.
748d3a51819SDave May 
749d3a51819SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
750d3a51819SDave May @*/
751320740a0SDave May PETSC_EXTERN PetscErrorCode DMSwarmRegisterUserDatatypeField(DM dm,const char fieldname[],size_t size,PetscInt blocksize)
752b62e03f8SDave May {
753b62e03f8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
7546845f8f5SDave May   PetscErrorCode ierr;
755b62e03f8SDave May 
756521f74f9SMatthew G. Knepley   PetscFunctionBegin;
75777048351SPatrick Sanan   ierr = DMSwarmDataBucketRegisterField(swarm->db,"DMSwarmRegisterUserDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
758320740a0SDave May   {
75977048351SPatrick Sanan     DMSwarmDataField gfield;
760320740a0SDave May 
76177048351SPatrick Sanan     ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
76277048351SPatrick Sanan     ierr = DMSwarmDataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
763320740a0SDave May   }
764b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_DATATYPE_UNKNOWN;
765b62e03f8SDave May   PetscFunctionReturn(0);
766b62e03f8SDave May }
767b62e03f8SDave May 
768d3a51819SDave May /*@C
769d3a51819SDave May    DMSwarmGetField - Get access to the underlying array storing all entries associated with a registered field
770d3a51819SDave May 
771d3a51819SDave May    Not collective
772d3a51819SDave May 
773d3a51819SDave May    Input parameters:
77462741f57SDave May +  dm - a DMSwarm
77562741f57SDave May -  fieldname - the textual name to identify this field
776d3a51819SDave May 
777d3a51819SDave May    Output parameters:
77862741f57SDave May +  blocksize - the number of each data type
779d3a51819SDave May .  type - the data type
78062741f57SDave May -  data - pointer to raw array
781d3a51819SDave May 
782d3a51819SDave May    Level: beginner
783d3a51819SDave May 
784d3a51819SDave May    Notes:
7858b8a3813SDave May    The array must be returned using a matching call to DMSwarmRestoreField().
786d3a51819SDave May 
787d3a51819SDave May .seealso: DMSwarmRestoreField()
788d3a51819SDave May @*/
7895f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmGetField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
790b62e03f8SDave May {
791b62e03f8SDave May   DM_Swarm         *swarm = (DM_Swarm*)dm->data;
79277048351SPatrick Sanan   DMSwarmDataField gfield;
7932eac95f8SDave May   PetscErrorCode ierr;
794b62e03f8SDave May 
795521f74f9SMatthew G. Knepley   PetscFunctionBegin;
7963454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
79777048351SPatrick Sanan   ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
79877048351SPatrick Sanan   ierr = DMSwarmDataFieldGetAccess(gfield);CHKERRQ(ierr);
79977048351SPatrick Sanan   ierr = DMSwarmDataFieldGetEntries(gfield,data);CHKERRQ(ierr);
8001b1ea282SDave May   if (blocksize) {*blocksize = gfield->bs; }
801b5bcf523SDave May   if (type) { *type = gfield->petsc_type; }
802b62e03f8SDave May   PetscFunctionReturn(0);
803b62e03f8SDave May }
804b62e03f8SDave May 
805d3a51819SDave May /*@C
806d3a51819SDave May    DMSwarmRestoreField - Restore access to the underlying array storing all entries associated with a registered field
807d3a51819SDave May 
808d3a51819SDave May    Not collective
809d3a51819SDave May 
810d3a51819SDave May    Input parameters:
81162741f57SDave May +  dm - a DMSwarm
81262741f57SDave May -  fieldname - the textual name to identify this field
813d3a51819SDave May 
814d3a51819SDave May    Output parameters:
81562741f57SDave May +  blocksize - the number of each data type
816d3a51819SDave May .  type - the data type
81762741f57SDave May -  data - pointer to raw array
818d3a51819SDave May 
819d3a51819SDave May    Level: beginner
820d3a51819SDave May 
821d3a51819SDave May    Notes:
8228b8a3813SDave May    The user must call DMSwarmGetField() prior to calling DMSwarmRestoreField().
823d3a51819SDave May 
824d3a51819SDave May .seealso: DMSwarmGetField()
825d3a51819SDave May @*/
8265f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmRestoreField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
827b62e03f8SDave May {
828b62e03f8SDave May   DM_Swarm         *swarm = (DM_Swarm*)dm->data;
82977048351SPatrick Sanan   DMSwarmDataField gfield;
8302eac95f8SDave May   PetscErrorCode ierr;
831b62e03f8SDave May 
832521f74f9SMatthew G. Knepley   PetscFunctionBegin;
83377048351SPatrick Sanan   ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
83477048351SPatrick Sanan   ierr = DMSwarmDataFieldRestoreAccess(gfield);CHKERRQ(ierr);
835b62e03f8SDave May   if (data) *data = NULL;
836b62e03f8SDave May   PetscFunctionReturn(0);
837b62e03f8SDave May }
838b62e03f8SDave May 
839d3a51819SDave May /*@C
840d3a51819SDave May    DMSwarmAddPoint - Add space for one new point in the DMSwarm
841d3a51819SDave May 
842d3a51819SDave May    Not collective
843d3a51819SDave May 
844d3a51819SDave May    Input parameter:
845d3a51819SDave May .  dm - a DMSwarm
846d3a51819SDave May 
847d3a51819SDave May    Level: beginner
848d3a51819SDave May 
849d3a51819SDave May    Notes:
8508b8a3813SDave May    The new point will have all fields initialized to zero.
851d3a51819SDave May 
852d3a51819SDave May .seealso: DMSwarmAddNPoints()
853d3a51819SDave May @*/
854cb1d1399SDave May PETSC_EXTERN PetscErrorCode DMSwarmAddPoint(DM dm)
855cb1d1399SDave May {
856cb1d1399SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
857cb1d1399SDave May   PetscErrorCode ierr;
858cb1d1399SDave May 
859521f74f9SMatthew G. Knepley   PetscFunctionBegin;
8603454631fSDave May   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
861f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
86277048351SPatrick Sanan   ierr = DMSwarmDataBucketAddPoint(swarm->db);CHKERRQ(ierr);
863f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
864cb1d1399SDave May   PetscFunctionReturn(0);
865cb1d1399SDave May }
866cb1d1399SDave May 
867d3a51819SDave May /*@C
868d3a51819SDave May    DMSwarmAddNPoints - Add space for a number of new points in the DMSwarm
869d3a51819SDave May 
870d3a51819SDave May    Not collective
871d3a51819SDave May 
872d3a51819SDave May    Input parameters:
87362741f57SDave May +  dm - a DMSwarm
87462741f57SDave May -  npoints - the number of new points to add
875d3a51819SDave May 
876d3a51819SDave May    Level: beginner
877d3a51819SDave May 
878d3a51819SDave May    Notes:
8798b8a3813SDave May    The new point will have all fields initialized to zero.
880d3a51819SDave May 
881d3a51819SDave May .seealso: DMSwarmAddPoint()
882d3a51819SDave May @*/
883cb1d1399SDave May PETSC_EXTERN PetscErrorCode DMSwarmAddNPoints(DM dm,PetscInt npoints)
884cb1d1399SDave May {
885cb1d1399SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
886cb1d1399SDave May   PetscErrorCode ierr;
887cb1d1399SDave May   PetscInt       nlocal;
888cb1d1399SDave May 
889521f74f9SMatthew G. Knepley   PetscFunctionBegin;
890f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
89177048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
892cb1d1399SDave May   nlocal = nlocal + npoints;
89377048351SPatrick Sanan   ierr = DMSwarmDataBucketSetSizes(swarm->db,nlocal,DMSWARM_DATA_BUCKET_BUFFER_DEFAULT);CHKERRQ(ierr);
894f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
895cb1d1399SDave May   PetscFunctionReturn(0);
896cb1d1399SDave May }
897cb1d1399SDave May 
898d3a51819SDave May /*@C
899d3a51819SDave May    DMSwarmRemovePoint - Remove the last point from the DMSwarm
900d3a51819SDave May 
901d3a51819SDave May    Not collective
902d3a51819SDave May 
903d3a51819SDave May    Input parameter:
904d3a51819SDave May .  dm - a DMSwarm
905d3a51819SDave May 
906d3a51819SDave May    Level: beginner
907d3a51819SDave May 
908d3a51819SDave May .seealso: DMSwarmRemovePointAtIndex()
909d3a51819SDave May @*/
910cb1d1399SDave May PETSC_EXTERN PetscErrorCode DMSwarmRemovePoint(DM dm)
911cb1d1399SDave May {
912cb1d1399SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
913cb1d1399SDave May   PetscErrorCode ierr;
914cb1d1399SDave May 
915521f74f9SMatthew G. Knepley   PetscFunctionBegin;
916f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
91777048351SPatrick Sanan   ierr = DMSwarmDataBucketRemovePoint(swarm->db);CHKERRQ(ierr);
918f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
919cb1d1399SDave May   PetscFunctionReturn(0);
920cb1d1399SDave May }
921cb1d1399SDave May 
922d3a51819SDave May /*@C
923d3a51819SDave May    DMSwarmRemovePointAtIndex - Removes a specific point from the DMSwarm
924d3a51819SDave May 
925d3a51819SDave May    Not collective
926d3a51819SDave May 
927d3a51819SDave May    Input parameters:
92862741f57SDave May +  dm - a DMSwarm
92962741f57SDave May -  idx - index of point to remove
930d3a51819SDave May 
931d3a51819SDave May    Level: beginner
932d3a51819SDave May 
933d3a51819SDave May .seealso: DMSwarmRemovePoint()
934d3a51819SDave May @*/
935cb1d1399SDave May PETSC_EXTERN PetscErrorCode DMSwarmRemovePointAtIndex(DM dm,PetscInt idx)
936cb1d1399SDave May {
937cb1d1399SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
938cb1d1399SDave May   PetscErrorCode ierr;
939cb1d1399SDave May 
940521f74f9SMatthew G. Knepley   PetscFunctionBegin;
941f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
94277048351SPatrick Sanan   ierr = DMSwarmDataBucketRemovePointAtIndex(swarm->db,idx);CHKERRQ(ierr);
943f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
944cb1d1399SDave May   PetscFunctionReturn(0);
945cb1d1399SDave May }
946b62e03f8SDave May 
947ba4fc9c6SDave May /*@C
948ba4fc9c6SDave May    DMSwarmCopyPoint - Copy point pj to point pi in the DMSwarm
949ba4fc9c6SDave May 
950ba4fc9c6SDave May    Not collective
951ba4fc9c6SDave May 
952ba4fc9c6SDave May    Input parameters:
953ba4fc9c6SDave May +  dm - a DMSwarm
954ba4fc9c6SDave May .  pi - the index of the point to copy
955ba4fc9c6SDave May -  pj - the point index where the copy should be located
956ba4fc9c6SDave May 
957ba4fc9c6SDave May  Level: beginner
958ba4fc9c6SDave May 
959ba4fc9c6SDave May .seealso: DMSwarmRemovePoint()
960ba4fc9c6SDave May @*/
961ba4fc9c6SDave May PETSC_EXTERN PetscErrorCode DMSwarmCopyPoint(DM dm,PetscInt pi,PetscInt pj)
962ba4fc9c6SDave May {
963ba4fc9c6SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
964ba4fc9c6SDave May   PetscErrorCode ierr;
965ba4fc9c6SDave May 
966ba4fc9c6SDave May   PetscFunctionBegin;
967ba4fc9c6SDave May   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
96877048351SPatrick Sanan   ierr = DMSwarmDataBucketCopyPoint(swarm->db,pi,swarm->db,pj);CHKERRQ(ierr);
969ba4fc9c6SDave May   PetscFunctionReturn(0);
970ba4fc9c6SDave May }
971ba4fc9c6SDave May 
972095059a4SDave May PetscErrorCode DMSwarmMigrate_Basic(DM dm,PetscBool remove_sent_points)
9733454631fSDave May {
974dcf43ee8SDave May   PetscErrorCode ierr;
975521f74f9SMatthew G. Knepley 
976521f74f9SMatthew G. Knepley   PetscFunctionBegin;
977dcf43ee8SDave May   ierr = DMSwarmMigrate_Push_Basic(dm,remove_sent_points);CHKERRQ(ierr);
9783454631fSDave May   PetscFunctionReturn(0);
9793454631fSDave May }
9803454631fSDave May 
981d3a51819SDave May /*@C
982d3a51819SDave May    DMSwarmMigrate - Relocates points defined in the DMSwarm to other MPI-ranks
983d3a51819SDave May 
984d3a51819SDave May    Collective on DM
985d3a51819SDave May 
986d3a51819SDave May    Input parameters:
98762741f57SDave May +  dm - the DMSwarm
98862741f57SDave May -  remove_sent_points - flag indicating if sent points should be removed from the current MPI-rank
989d3a51819SDave May 
990d3a51819SDave May    Notes:
9918b8a3813SDave May    The DM will be modified to accomodate received points.
9928b8a3813SDave May    If remove_sent_points = PETSC_TRUE, any points that were sent will be removed from the DM.
9938b8a3813SDave May    Different styles of migration are supported. See DMSwarmSetMigrateType().
994d3a51819SDave May 
995d3a51819SDave May    Level: advanced
996d3a51819SDave May 
997d3a51819SDave May .seealso: DMSwarmSetMigrateType()
998d3a51819SDave May @*/
999095059a4SDave May PETSC_EXTERN PetscErrorCode DMSwarmMigrate(DM dm,PetscBool remove_sent_points)
10003454631fSDave May {
1001f0cdbbbaSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
10023454631fSDave May   PetscErrorCode ierr;
1003f0cdbbbaSDave May 
1004521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1005ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
1006f0cdbbbaSDave May   switch (swarm->migrate_type) {
1007f0cdbbbaSDave May     case DMSWARM_MIGRATE_BASIC:
1008095059a4SDave May       ierr = DMSwarmMigrate_Basic(dm,remove_sent_points);CHKERRQ(ierr);
1009f0cdbbbaSDave May       break;
1010f0cdbbbaSDave May     case DMSWARM_MIGRATE_DMCELLNSCATTER:
1011f0cdbbbaSDave May       ierr = DMSwarmMigrate_CellDMScatter(dm,remove_sent_points);CHKERRQ(ierr);
1012f0cdbbbaSDave May       break;
1013f0cdbbbaSDave May     case DMSWARM_MIGRATE_DMCELLEXACT:
1014f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_DMCELLEXACT not implemented");
1015521f74f9SMatthew G. Knepley       /*ierr = DMSwarmMigrate_CellDMExact(dm,remove_sent_points);CHKERRQ(ierr);*/
1016f0cdbbbaSDave May       break;
1017f0cdbbbaSDave May     case DMSWARM_MIGRATE_USER:
1018f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_USER not implemented");
1019521f74f9SMatthew G. Knepley       /*ierr = swarm->migrate(dm,remove_sent_points);CHKERRQ(ierr);*/
1020f0cdbbbaSDave May       break;
1021f0cdbbbaSDave May     default:
1022f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE type unknown");
1023f0cdbbbaSDave May       break;
1024f0cdbbbaSDave May   }
1025ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
10263454631fSDave May   PetscFunctionReturn(0);
10273454631fSDave May }
10283454631fSDave May 
1029f0cdbbbaSDave May PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm,PetscInt *globalsize);
1030f0cdbbbaSDave May 
1031d3a51819SDave May /*
1032d3a51819SDave May  DMSwarmCollectViewCreate
1033d3a51819SDave May 
1034d3a51819SDave May  * Applies a collection method and gathers point neighbour points into dm
1035d3a51819SDave May 
1036d3a51819SDave May  Notes:
10378b8a3813SDave May  Users should call DMSwarmCollectViewDestroy() after
1038d3a51819SDave May  they have finished computations associated with the collected points
1039d3a51819SDave May */
1040d3a51819SDave May 
1041d3a51819SDave May /*@C
1042d3a51819SDave May    DMSwarmCollectViewCreate - Applies a collection method and gathers points
1043d3a51819SDave May    in neighbour MPI-ranks into the DMSwarm
1044d3a51819SDave May 
1045d3a51819SDave May    Collective on DM
1046d3a51819SDave May 
1047d3a51819SDave May    Input parameter:
1048d3a51819SDave May .  dm - the DMSwarm
1049d3a51819SDave May 
1050d3a51819SDave May    Notes:
1051d3a51819SDave May    Users should call DMSwarmCollectViewDestroy() after
1052d3a51819SDave May    they have finished computations associated with the collected points
10538b8a3813SDave May    Different collect methods are supported. See DMSwarmSetCollectType().
1054d3a51819SDave May 
1055d3a51819SDave May    Level: advanced
1056d3a51819SDave May 
1057d3a51819SDave May .seealso: DMSwarmCollectViewDestroy(), DMSwarmSetCollectType()
1058d3a51819SDave May @*/
1059fe39f135SDave May PETSC_EXTERN PetscErrorCode DMSwarmCollectViewCreate(DM dm)
10602712d1f2SDave May {
10612712d1f2SDave May   PetscErrorCode ierr;
10622712d1f2SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
10632712d1f2SDave May   PetscInt ng;
10642712d1f2SDave May 
1065521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1066480eef7bSDave May   if (swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView currently active");
1067480eef7bSDave May   ierr = DMSwarmGetLocalSize(dm,&ng);CHKERRQ(ierr);
1068480eef7bSDave May   switch (swarm->collect_type) {
1069f0cdbbbaSDave May 
1070480eef7bSDave May     case DMSWARM_COLLECT_BASIC:
10712712d1f2SDave May       ierr = DMSwarmMigrate_GlobalToLocal_Basic(dm,&ng);CHKERRQ(ierr);
1072480eef7bSDave May       break;
1073480eef7bSDave May     case DMSWARM_COLLECT_DMDABOUNDINGBOX:
1074f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_DMDABOUNDINGBOX not implemented");
1075521f74f9SMatthew G. Knepley       /*ierr = DMSwarmCollect_DMDABoundingBox(dm,&ng);CHKERRQ(ierr);*/
1076480eef7bSDave May       break;
1077480eef7bSDave May     case DMSWARM_COLLECT_GENERAL:
1078f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_GENERAL not implemented");
1079521f74f9SMatthew G. Knepley       /*ierr = DMSwarmCollect_General(dm,..,,..,&ng);CHKERRQ(ierr);*/
1080480eef7bSDave May       break;
1081480eef7bSDave May     default:
1082f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT type unknown");
1083480eef7bSDave May       break;
1084480eef7bSDave May   }
1085480eef7bSDave May   swarm->collect_view_active = PETSC_TRUE;
1086480eef7bSDave May   swarm->collect_view_reset_nlocal = ng;
10872712d1f2SDave May   PetscFunctionReturn(0);
10882712d1f2SDave May }
10892712d1f2SDave May 
1090d3a51819SDave May /*@C
1091d3a51819SDave May    DMSwarmCollectViewDestroy - Resets the DMSwarm to the size prior to calling DMSwarmCollectViewCreate()
1092d3a51819SDave May 
1093d3a51819SDave May    Collective on DM
1094d3a51819SDave May 
1095d3a51819SDave May    Input parameters:
1096d3a51819SDave May .  dm - the DMSwarm
1097d3a51819SDave May 
1098d3a51819SDave May    Notes:
1099d3a51819SDave May    Users should call DMSwarmCollectViewCreate() before this function is called.
1100d3a51819SDave May 
1101d3a51819SDave May    Level: advanced
1102d3a51819SDave May 
1103d3a51819SDave May .seealso: DMSwarmCollectViewCreate(), DMSwarmSetCollectType()
1104d3a51819SDave May @*/
1105fe39f135SDave May PETSC_EXTERN PetscErrorCode DMSwarmCollectViewDestroy(DM dm)
11062712d1f2SDave May {
11072712d1f2SDave May   PetscErrorCode ierr;
11082712d1f2SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
11092712d1f2SDave May 
1110521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1111480eef7bSDave May   if (!swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView is currently not active");
1112480eef7bSDave May   ierr = DMSwarmSetLocalSizes(dm,swarm->collect_view_reset_nlocal,-1);CHKERRQ(ierr);
1113480eef7bSDave May   swarm->collect_view_active = PETSC_FALSE;
11142712d1f2SDave May   PetscFunctionReturn(0);
11152712d1f2SDave May }
11163454631fSDave May 
1117f0cdbbbaSDave May PetscErrorCode DMSwarmSetUpPIC(DM dm)
1118f0cdbbbaSDave May {
1119f0cdbbbaSDave May   PetscInt       dim;
1120f0cdbbbaSDave May   PetscErrorCode ierr;
1121f0cdbbbaSDave May 
1122521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1123f0cdbbbaSDave May   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
1124f0cdbbbaSDave May   if (dim < 1) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
1125f0cdbbbaSDave May   if (dim > 3) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
1126f0cdbbbaSDave May   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_coor,dim,PETSC_DOUBLE);CHKERRQ(ierr);
1127e2d107dbSDave May   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_cellid,1,PETSC_INT);CHKERRQ(ierr);
1128f0cdbbbaSDave May   PetscFunctionReturn(0);
1129f0cdbbbaSDave May }
1130f0cdbbbaSDave May 
1131d3a51819SDave May /*@C
1132d3a51819SDave May    DMSwarmSetType - Set particular flavor of DMSwarm
1133d3a51819SDave May 
1134d3a51819SDave May    Collective on DM
1135d3a51819SDave May 
1136d3a51819SDave May    Input parameters:
113762741f57SDave May +  dm - the DMSwarm
113862741f57SDave May -  stype - the DMSwarm type (e.g. DMSWARM_PIC)
1139d3a51819SDave May 
1140d3a51819SDave May    Level: advanced
1141d3a51819SDave May 
1142d3a51819SDave May .seealso: DMSwarmSetMigrateType(), DMSwarmSetCollectType()
1143d3a51819SDave May @*/
1144f0cdbbbaSDave May PETSC_EXTERN PetscErrorCode DMSwarmSetType(DM dm,DMSwarmType stype)
1145f0cdbbbaSDave May {
1146f0cdbbbaSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1147f0cdbbbaSDave May   PetscErrorCode ierr;
1148f0cdbbbaSDave May 
1149521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1150f0cdbbbaSDave May   swarm->swarm_type = stype;
1151f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
1152f0cdbbbaSDave May     ierr = DMSwarmSetUpPIC(dm);CHKERRQ(ierr);
1153f0cdbbbaSDave May   }
1154f0cdbbbaSDave May   PetscFunctionReturn(0);
1155f0cdbbbaSDave May }
1156f0cdbbbaSDave May 
11573454631fSDave May PetscErrorCode DMSetup_Swarm(DM dm)
11583454631fSDave May {
11593454631fSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
11603454631fSDave May   PetscErrorCode ierr;
11613454631fSDave May   PetscMPIInt    rank;
11623454631fSDave May   PetscInt       p,npoints,*rankval;
11633454631fSDave May 
1164521f74f9SMatthew G. Knepley   PetscFunctionBegin;
11653454631fSDave May   if (swarm->issetup) PetscFunctionReturn(0);
11663454631fSDave May 
11673454631fSDave May   swarm->issetup = PETSC_TRUE;
11683454631fSDave May 
1169f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
1170f0cdbbbaSDave May     /* check dmcell exists */
1171f0cdbbbaSDave May     if (!swarm->dmcell) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires you call DMSwarmSetCellDM");
1172f0cdbbbaSDave May 
1173f0cdbbbaSDave May     if (swarm->dmcell->ops->locatepointssubdomain) {
1174f0cdbbbaSDave May       /* check methods exists for exact ownership identificiation */
1175521f74f9SMatthew G. Knepley       ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->ops->LocatePointsSubdomain\n");CHKERRQ(ierr);
1176f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLEXACT;
1177f0cdbbbaSDave May     } else {
1178f0cdbbbaSDave May       /* check methods exist for point location AND rank neighbor identification */
1179f0cdbbbaSDave May       if (swarm->dmcell->ops->locatepoints) {
1180521f74f9SMatthew G. Knepley         ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->LocatePoints\n");CHKERRQ(ierr);
1181f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->locatepoints be defined");
1182f0cdbbbaSDave May 
1183f0cdbbbaSDave May       if (swarm->dmcell->ops->getneighbors) {
1184521f74f9SMatthew G. Knepley         ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->GetNeigbors\n");CHKERRQ(ierr);
1185f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->getneighbors be defined");
1186f0cdbbbaSDave May 
1187f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLNSCATTER;
1188f0cdbbbaSDave May     }
1189f0cdbbbaSDave May   }
1190f0cdbbbaSDave May 
1191f0cdbbbaSDave May   ierr = DMSwarmFinalizeFieldRegister(dm);CHKERRQ(ierr);
1192f0cdbbbaSDave May 
11933454631fSDave May   /* check some fields were registered */
11943454631fSDave May   if (swarm->db->nfields <= 2) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"At least one field user must be registered via DMSwarmRegisterXXX()");
11953454631fSDave May 
11963454631fSDave May   /* check local sizes were set */
11973454631fSDave May   if (swarm->db->L == -1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Local sizes must be set via DMSwarmSetLocalSizes()");
11983454631fSDave May 
11993454631fSDave May   /* initialize values in pid and rank placeholders */
12003454631fSDave May   /* TODO: [pid - use MPI_Scan] */
12013454631fSDave May   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
120277048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db,&npoints,NULL,NULL);CHKERRQ(ierr);
1203f0cdbbbaSDave May   ierr = DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
12043454631fSDave May   for (p=0; p<npoints; p++) {
12053454631fSDave May     rankval[p] = (PetscInt)rank;
12063454631fSDave May   }
1207f0cdbbbaSDave May   ierr = DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
12083454631fSDave May   PetscFunctionReturn(0);
12093454631fSDave May }
12103454631fSDave May 
1211dc5f5ce9SDave May extern PetscErrorCode DMSwarmSortDestroy(DMSwarmSort *_ctx);
1212dc5f5ce9SDave May 
121357795646SDave May PetscErrorCode DMDestroy_Swarm(DM dm)
121457795646SDave May {
121557795646SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
121657795646SDave May   PetscErrorCode ierr;
121757795646SDave May 
121857795646SDave May   PetscFunctionBegin;
121977048351SPatrick Sanan   ierr = DMSwarmDataBucketDestroy(&swarm->db);CHKERRQ(ierr);
1220dc5f5ce9SDave May   if (swarm->sort_context) {
1221dc5f5ce9SDave May     ierr = DMSwarmSortDestroy(&swarm->sort_context);CHKERRQ(ierr);
1222dc5f5ce9SDave May   }
122357795646SDave May   ierr = PetscFree(swarm);CHKERRQ(ierr);
122457795646SDave May   PetscFunctionReturn(0);
122557795646SDave May }
122657795646SDave May 
1227a9ee3421SMatthew G. Knepley PetscErrorCode DMSwarmView_Draw(DM dm, PetscViewer viewer)
1228a9ee3421SMatthew G. Knepley {
1229a9ee3421SMatthew G. Knepley   DM             cdm;
1230a9ee3421SMatthew G. Knepley   PetscDraw      draw;
1231a9ee3421SMatthew G. Knepley   PetscReal     *coords, oldPause;
1232a9ee3421SMatthew G. Knepley   PetscInt       Np, p, bs;
1233a9ee3421SMatthew G. Knepley   PetscErrorCode ierr;
1234a9ee3421SMatthew G. Knepley 
1235a9ee3421SMatthew G. Knepley   PetscFunctionBegin;
1236a9ee3421SMatthew G. Knepley   ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr);
1237a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetCellDM(dm, &cdm);CHKERRQ(ierr);
1238a9ee3421SMatthew G. Knepley   ierr = PetscDrawGetPause(draw, &oldPause);CHKERRQ(ierr);
1239a9ee3421SMatthew G. Knepley   ierr = PetscDrawSetPause(draw, 0.0);CHKERRQ(ierr);
1240a9ee3421SMatthew G. Knepley   ierr = DMView(cdm, viewer);CHKERRQ(ierr);
1241a9ee3421SMatthew G. Knepley   ierr = PetscDrawSetPause(draw, oldPause);CHKERRQ(ierr);
1242a9ee3421SMatthew G. Knepley 
1243a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetLocalSize(dm, &Np);CHKERRQ(ierr);
1244a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1245a9ee3421SMatthew G. Knepley   for (p = 0; p < Np; ++p) {
1246a9ee3421SMatthew G. Knepley     const PetscInt i = p*bs;
1247a9ee3421SMatthew G. Knepley 
1248a9ee3421SMatthew G. Knepley     ierr = PetscDrawEllipse(draw, coords[i], coords[i+1], 0.01, 0.01, PETSC_DRAW_BLUE);CHKERRQ(ierr);
1249a9ee3421SMatthew G. Knepley   }
1250a9ee3421SMatthew G. Knepley   ierr = DMSwarmRestoreField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1251a9ee3421SMatthew G. Knepley   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
1252a9ee3421SMatthew G. Knepley   ierr = PetscDrawPause(draw);CHKERRQ(ierr);
1253a9ee3421SMatthew G. Knepley   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
1254a9ee3421SMatthew G. Knepley   PetscFunctionReturn(0);
1255a9ee3421SMatthew G. Knepley }
1256a9ee3421SMatthew G. Knepley 
12575f50eb2eSDave May PetscErrorCode DMView_Swarm(DM dm, PetscViewer viewer)
12585f50eb2eSDave May {
12595f50eb2eSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1260a9ee3421SMatthew G. Knepley   PetscBool      iascii,ibinary,ishdf5,isvtk,isdraw;
12615f50eb2eSDave May   PetscErrorCode ierr;
12625f50eb2eSDave May 
12635f50eb2eSDave May   PetscFunctionBegin;
12645f50eb2eSDave May   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
12655f50eb2eSDave May   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
12665f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
12675f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY,&ibinary);CHKERRQ(ierr);
12685f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK,   &isvtk);CHKERRQ(ierr);
12695f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
1270a9ee3421SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW,  &isdraw);CHKERRQ(ierr);
12715f50eb2eSDave May   if (iascii) {
127277048351SPatrick Sanan     ierr = DMSwarmDataBucketView(PetscObjectComm((PetscObject)dm),swarm->db,NULL,DATABUCKET_VIEW_STDOUT);CHKERRQ(ierr);
1273298827fbSBarry Smith   } else if (ibinary) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO Binary support");
12745f50eb2eSDave May #if defined(PETSC_HAVE_HDF5)
1275298827fbSBarry Smith   else if (ishdf5) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO HDF5 support");
12765f50eb2eSDave May #else
1277298827fbSBarry Smith   else if (ishdf5) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"HDF5 not supported. Please reconfigure using --download-hdf5");
12785f50eb2eSDave May #endif
1279298827fbSBarry Smith   else if (isvtk) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO VTK support");
1280298827fbSBarry Smith   else if (isdraw) {
1281a9ee3421SMatthew G. Knepley     ierr = DMSwarmView_Draw(dm, viewer);CHKERRQ(ierr);
12825f50eb2eSDave May   }
12835f50eb2eSDave May   PetscFunctionReturn(0);
12845f50eb2eSDave May }
12855f50eb2eSDave May 
1286d3a51819SDave May /*MC
1287d3a51819SDave May 
1288d3a51819SDave May  DMSWARM = "swarm" - A DM object used to represent arrays of data (fields) of arbitrary data type.
128962741f57SDave May  This implementation was designed for particle methods in which the underlying
1290d3a51819SDave May  data required to be represented is both (i) dynamic in length, (ii) and of arbitrary data type.
1291d3a51819SDave May 
129262741f57SDave May  User data can be represented by DMSwarm through a registering "fields".
129362741f57SDave May  To register a field, the user must provide;
129462741f57SDave May  (a) a unique name;
129562741f57SDave May  (b) the data type (or size in bytes);
129662741f57SDave May  (c) the block size of the data.
1297d3a51819SDave May 
1298d3a51819SDave May  For example, suppose the application requires a unique id, energy, momentum and density to be stored
129962741f57SDave May  on a set of of particles. Then the following code could be used
1300d3a51819SDave May 
130162741f57SDave May $    DMSwarmInitializeFieldRegister(dm)
130262741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"uid",1,PETSC_LONG);
130362741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"energy",1,PETSC_REAL);
130462741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"momentum",3,PETSC_REAL);
130562741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"density",1,PETSC_FLOAT);
130662741f57SDave May $    DMSwarmFinalizeFieldRegister(dm)
1307d3a51819SDave May 
1308d3a51819SDave May  The fields represented by DMSwarm are dynamic and can be re-sized at any time.
130962741f57SDave May  The only restriction imposed by DMSwarm is that all fields contain the same number of points.
1310d3a51819SDave May 
1311d3a51819SDave May  To support particle methods, "migration" techniques are provided. These methods migrate data
1312d3a51819SDave May  between MPI-ranks.
1313d3a51819SDave May 
1314d3a51819SDave May  DMSwarm supports the methods DMCreateGlobalVector() and DMCreateLocalVector().
1315d3a51819SDave May  As a DMSwarm may internally define and store values of different data types,
131662741f57SDave May  before calling DMCreateGlobalVector() or DMCreateLocalVector(), the user must inform DMSwarm which
1317d3a51819SDave May  fields should be used to define a Vec object via
1318d3a51819SDave May    DMSwarmVectorDefineField()
1319d3a51819SDave May  The specified field can can changed be changed at any time - thereby permitting vectors
1320d3a51819SDave May  compatable with different fields to be created.
1321d3a51819SDave May 
132262741f57SDave May  A dual representation of fields in the DMSwarm and a Vec object is permitted via
1323d3a51819SDave May    DMSwarmCreateGlobalVectorFromField()
1324d3a51819SDave May  Here the data defining the field in the DMSwarm is shared with a Vec.
1325d3a51819SDave May  This is inherently unsafe if you alter the size of the field at any time between
1326d3a51819SDave May  calls to DMSwarmCreateGlobalVectorFromField() and DMSwarmDestroyGlobalVectorFromField().
1327cc651181SDave May  If the local size of the DMSwarm does not match the local size of the global vector
1328cc651181SDave May  when DMSwarmDestroyGlobalVectorFromField() is called, an error is thrown.
1329d3a51819SDave May 
133062741f57SDave May  Additional high-level support is provided for Particle-In-Cell methods.
133162741f57SDave May  Please refer to the man page for DMSwarmSetType().
133262741f57SDave May 
1333d3a51819SDave May  Level: beginner
1334d3a51819SDave May 
1335d3a51819SDave May .seealso: DMType, DMCreate(), DMSetType()
1336d3a51819SDave May M*/
133757795646SDave May PETSC_EXTERN PetscErrorCode DMCreate_Swarm(DM dm)
133857795646SDave May {
133957795646SDave May   DM_Swarm      *swarm;
134057795646SDave May   PetscErrorCode ierr;
134157795646SDave May 
134257795646SDave May   PetscFunctionBegin;
134357795646SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
134457795646SDave May   ierr     = PetscNewLog(dm,&swarm);CHKERRQ(ierr);
1345f0cdbbbaSDave May   dm->data = swarm;
134657795646SDave May 
134777048351SPatrick Sanan   ierr = DMSwarmDataBucketCreate(&swarm->db);CHKERRQ(ierr);
1348f0cdbbbaSDave May   ierr = DMSwarmInitializeFieldRegister(dm);CHKERRQ(ierr);
1349f0cdbbbaSDave May 
1350b5bcf523SDave May   swarm->vec_field_set = PETSC_FALSE;
13513454631fSDave May   swarm->issetup = PETSC_FALSE;
1352480eef7bSDave May   swarm->swarm_type = DMSWARM_BASIC;
1353480eef7bSDave May   swarm->migrate_type = DMSWARM_MIGRATE_BASIC;
1354480eef7bSDave May   swarm->collect_type = DMSWARM_COLLECT_BASIC;
135540c453e9SDave May   swarm->migrate_error_on_missing_point = PETSC_FALSE;
1356b62e03f8SDave May 
1357f0cdbbbaSDave May   swarm->dmcell = NULL;
1358f0cdbbbaSDave May   swarm->collect_view_active = PETSC_FALSE;
1359f0cdbbbaSDave May   swarm->collect_view_reset_nlocal = -1;
136057795646SDave May 
1361f0cdbbbaSDave May   dm->dim  = 0;
13625f50eb2eSDave May   dm->ops->view                            = DMView_Swarm;
136357795646SDave May   dm->ops->load                            = NULL;
136457795646SDave May   dm->ops->setfromoptions                  = NULL;
136557795646SDave May   dm->ops->clone                           = NULL;
13663454631fSDave May   dm->ops->setup                           = DMSetup_Swarm;
136757795646SDave May   dm->ops->createdefaultsection            = NULL;
136857795646SDave May   dm->ops->createdefaultconstraints        = NULL;
1369b5bcf523SDave May   dm->ops->createglobalvector              = DMCreateGlobalVector_Swarm;
1370b5bcf523SDave May   dm->ops->createlocalvector               = DMCreateLocalVector_Swarm;
137157795646SDave May   dm->ops->getlocaltoglobalmapping         = NULL;
137257795646SDave May   dm->ops->createfieldis                   = NULL;
137357795646SDave May   dm->ops->createcoordinatedm              = NULL;
137457795646SDave May   dm->ops->getcoloring                     = NULL;
137557795646SDave May   dm->ops->creatematrix                    = NULL;
137657795646SDave May   dm->ops->createinterpolation             = NULL;
137757795646SDave May   dm->ops->getaggregates                   = NULL;
137857795646SDave May   dm->ops->getinjection                    = NULL;
137983c47955SMatthew G. Knepley   dm->ops->createmassmatrix                = DMCreateMassMatrix_Swarm;
138057795646SDave May   dm->ops->refine                          = NULL;
138157795646SDave May   dm->ops->coarsen                         = NULL;
138257795646SDave May   dm->ops->refinehierarchy                 = NULL;
138357795646SDave May   dm->ops->coarsenhierarchy                = NULL;
138457795646SDave May   dm->ops->globaltolocalbegin              = NULL;
138557795646SDave May   dm->ops->globaltolocalend                = NULL;
138657795646SDave May   dm->ops->localtoglobalbegin              = NULL;
138757795646SDave May   dm->ops->localtoglobalend                = NULL;
138857795646SDave May   dm->ops->destroy                         = DMDestroy_Swarm;
138957795646SDave May   dm->ops->createsubdm                     = NULL;
139057795646SDave May   dm->ops->getdimpoints                    = NULL;
139157795646SDave May   dm->ops->locatepoints                    = NULL;
139257795646SDave May   PetscFunctionReturn(0);
139357795646SDave May }
1394