xref: /petsc/src/dm/impls/swarm/swarm.c (revision ef0bb6c736604ce380bf8bea4ebd4a7bda431d97)
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 
28d083f849SBarry Smith    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;
196adb2528bSMark 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);
20992fd8e1eSJed Brown   ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);
210e87a4003SBarry Smith   ierr = DMGetGlobalSection(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);
23053e60ab4SJoseph Pusztay 
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;
24683c47955SMatthew G. Knepley         for (i = 0; i < numFIndices; ++i) {
247adb2528bSMark Adams           key.j = findices[i]; /* global column (from Plex) */
248adb2528bSMark Adams           if (key.j >= 0) {
24983c47955SMatthew G. Knepley             /* Get indices for coarse elements */
25083c47955SMatthew G. Knepley             for (c = 0; c < numCIndices; ++c) {
251adb2528bSMark Adams               key.i = cindices[c] + rStart; /* global cols (from Swarm) */
252adb2528bSMark Adams               if (key.i < 0) continue;
253e8f14785SLisandro Dalcin               ierr = PetscHSetIJQueryAdd(ht, key, &missing);CHKERRQ(ierr);
25483c47955SMatthew G. Knepley               if (missing) {
2550643ed39SMatthew G. Knepley                 if ((key.j >= colStart) && (key.j < colEnd)) ++dnz[key.i - rStart];
256e8f14785SLisandro Dalcin                 else                                         ++onz[key.i - rStart];
2570643ed39SMatthew G. Knepley               } else SETERRQ2(PetscObjectComm((PetscObject) dmf), PETSC_ERR_SUP, "Set new value at %D,%D", key.i, key.j);
25883c47955SMatthew G. Knepley             }
259fc7c92abSMatthew G. Knepley           }
260fc7c92abSMatthew G. Knepley         }
26183c47955SMatthew G. Knepley         ierr = PetscFree(cindices);CHKERRQ(ierr);
26283c47955SMatthew G. Knepley       }
26383c47955SMatthew G. Knepley       ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
26483c47955SMatthew G. Knepley     }
26583c47955SMatthew G. Knepley   }
266e8f14785SLisandro Dalcin   ierr = PetscHSetIJDestroy(&ht);CHKERRQ(ierr);
26783c47955SMatthew G. Knepley   ierr = MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL);CHKERRQ(ierr);
26883c47955SMatthew G. Knepley   ierr = MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE);CHKERRQ(ierr);
26983c47955SMatthew G. Knepley   ierr = PetscFree2(dnz, onz);CHKERRQ(ierr);
270adb2528bSMark Adams   ierr = PetscMalloc3(maxC*totDim, &elemMat, maxC, &rowIDXs, maxC*dim, &xi);CHKERRQ(ierr);
27183c47955SMatthew G. Knepley   for (field = 0; field < Nf; ++field) {
272*ef0bb6c7SMatthew G. Knepley     PetscTabulation Tcoarse;
27383c47955SMatthew G. Knepley     PetscObject       obj;
274*ef0bb6c7SMatthew G. Knepley     PetscReal        *coords;
2750643ed39SMatthew G. Knepley     PetscInt          Nc, i;
27683c47955SMatthew G. Knepley 
27783c47955SMatthew G. Knepley     ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr);
2780643ed39SMatthew G. Knepley     ierr = PetscFEGetNumComponents((PetscFE) obj, &Nc);CHKERRQ(ierr);
2790643ed39SMatthew G. Knepley     if (Nc != 1) SETERRQ1(PetscObjectComm((PetscObject) dmf), PETSC_ERR_SUP, "Can only interpolate a scalar field from particles, Nc = %D", Nc);
2800643ed39SMatthew G. Knepley     ierr = DMSwarmGetField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **) &coords);CHKERRQ(ierr);
28183c47955SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
28283c47955SMatthew G. Knepley       PetscInt *findices  , *cindices;
28383c47955SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
2840643ed39SMatthew G. Knepley       PetscInt  p, c;
28583c47955SMatthew G. Knepley 
2860643ed39SMatthew G. Knepley       /* TODO: Use DMField instead of assuming affine */
28783c47955SMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr);
28883c47955SMatthew G. Knepley       ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
28983c47955SMatthew G. Knepley       ierr = DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices);CHKERRQ(ierr);
2900643ed39SMatthew G. Knepley       for (p = 0; p < numCIndices; ++p) {
2910643ed39SMatthew G. Knepley         CoordinatesRealToRef(dim, dim, v0ref, v0, invJ, &coords[cindices[p]*dim], &xi[p*dim]);
2920643ed39SMatthew G. Knepley       }
293*ef0bb6c7SMatthew G. Knepley       ierr = PetscFECreateTabulation((PetscFE) obj, 1, numCIndices, xi, 0, &Tcoarse);CHKERRQ(ierr);
29483c47955SMatthew G. Knepley       /* Get elemMat entries by multiplying by weight */
295580bdb30SBarry Smith       ierr = PetscArrayzero(elemMat, numCIndices*totDim);CHKERRQ(ierr);
29683c47955SMatthew G. Knepley       for (i = 0; i < numFIndices; ++i) {
2970643ed39SMatthew G. Knepley         for (p = 0; p < numCIndices; ++p) {
2980643ed39SMatthew G. Knepley           for (c = 0; c < Nc; ++c) {
2990643ed39SMatthew G. Knepley             /* B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c */
300*ef0bb6c7SMatthew G. Knepley             elemMat[p*numFIndices+i] += Tcoarse->T[0][(p*numFIndices + i)*Nc + c]*(useDeltaFunction ? 1.0 : detJ);
30183c47955SMatthew G. Knepley           }
3020643ed39SMatthew G. Knepley         }
3030643ed39SMatthew G. Knepley       }
304adb2528bSMark Adams       for (p = 0; p < numCIndices; ++p) rowIDXs[p] = cindices[p] + rStart;
30583c47955SMatthew G. Knepley       if (0) {ierr = DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat);CHKERRQ(ierr);}
306adb2528bSMark Adams       ierr = MatSetValues(mass, numCIndices, rowIDXs, numFIndices, findices, elemMat, ADD_VALUES);CHKERRQ(ierr);
30783c47955SMatthew G. Knepley       ierr = PetscFree(cindices);CHKERRQ(ierr);
30883c47955SMatthew G. Knepley       ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
309*ef0bb6c7SMatthew G. Knepley       ierr = PetscTabulationDestroy(&Tcoarse);CHKERRQ(ierr);
31083c47955SMatthew G. Knepley     }
3110643ed39SMatthew G. Knepley     ierr = DMSwarmRestoreField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **) &coords);CHKERRQ(ierr);
31283c47955SMatthew G. Knepley   }
313adb2528bSMark Adams   ierr = PetscFree3(elemMat, rowIDXs, xi);CHKERRQ(ierr);
31483c47955SMatthew G. Knepley   ierr = DMSwarmSortRestoreAccess(dmc);CHKERRQ(ierr);
31583c47955SMatthew G. Knepley   ierr = PetscFree3(v0, J, invJ);CHKERRQ(ierr);
31683c47955SMatthew G. Knepley   ierr = MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
31783c47955SMatthew G. Knepley   ierr = MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
31883c47955SMatthew G. Knepley   PetscFunctionReturn(0);
31983c47955SMatthew G. Knepley }
32083c47955SMatthew G. Knepley 
321adb2528bSMark Adams /* FEM cols, Particle rows */
32283c47955SMatthew G. Knepley static PetscErrorCode DMCreateMassMatrix_Swarm(DM dmCoarse, DM dmFine, Mat *mass)
32383c47955SMatthew G. Knepley {
324895a1698SMatthew G. Knepley   PetscSection   gsf;
32583c47955SMatthew G. Knepley   PetscInt       m, n;
32683c47955SMatthew G. Knepley   void          *ctx;
32783c47955SMatthew G. Knepley   PetscErrorCode ierr;
32883c47955SMatthew G. Knepley 
32983c47955SMatthew G. Knepley   PetscFunctionBegin;
330e87a4003SBarry Smith   ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr);
33183c47955SMatthew G. Knepley   ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr);
332895a1698SMatthew G. Knepley   ierr = DMSwarmGetLocalSize(dmCoarse, &n);CHKERRQ(ierr);
33383c47955SMatthew G. Knepley   ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr);
334adb2528bSMark Adams   ierr = MatSetSizes(*mass, n, m, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
33583c47955SMatthew G. Knepley   ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr);
33683c47955SMatthew G. Knepley   ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr);
33783c47955SMatthew G. Knepley 
3380643ed39SMatthew G. Knepley   ierr = DMSwarmComputeMassMatrix_Private(dmCoarse, dmFine, *mass, PETSC_TRUE, ctx);CHKERRQ(ierr);
33983c47955SMatthew G. Knepley   ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr);
34083c47955SMatthew G. Knepley   PetscFunctionReturn(0);
34183c47955SMatthew G. Knepley }
34283c47955SMatthew G. Knepley 
343fb1bcc12SMatthew G. Knepley /*@C
344d3a51819SDave May    DMSwarmCreateGlobalVectorFromField - Creates a Vec object sharing the array associated with a given field
345d3a51819SDave May 
346d083f849SBarry Smith    Collective on dm
347d3a51819SDave May 
348d3a51819SDave May    Input parameters:
34962741f57SDave May +  dm - a DMSwarm
35062741f57SDave May -  fieldname - the textual name given to a registered field
351d3a51819SDave May 
3528b8a3813SDave May    Output parameter:
353d3a51819SDave May .  vec - the vector
354d3a51819SDave May 
355d3a51819SDave May    Level: beginner
356d3a51819SDave May 
3578b8a3813SDave May    Notes:
3588b8a3813SDave May    The vector must be returned using a matching call to DMSwarmDestroyGlobalVectorFromField().
3598b8a3813SDave May 
3608b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmDestroyGlobalVectorFromField()
361d3a51819SDave May @*/
362b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmCreateGlobalVectorFromField(DM dm,const char fieldname[],Vec *vec)
363b5bcf523SDave May {
364fb1bcc12SMatthew G. Knepley   MPI_Comm       comm = PetscObjectComm((PetscObject) dm);
365b5bcf523SDave May   PetscErrorCode ierr;
366b5bcf523SDave May 
367fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
368fb1bcc12SMatthew G. Knepley   ierr = DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec);CHKERRQ(ierr);
369b5bcf523SDave May   PetscFunctionReturn(0);
370b5bcf523SDave May }
371b5bcf523SDave May 
372d3a51819SDave May /*@C
373d3a51819SDave May    DMSwarmDestroyGlobalVectorFromField - Destroys the Vec object which share the array associated with a given field
374d3a51819SDave May 
375d083f849SBarry Smith    Collective on dm
376d3a51819SDave May 
377d3a51819SDave May    Input parameters:
37862741f57SDave May +  dm - a DMSwarm
37962741f57SDave May -  fieldname - the textual name given to a registered field
380d3a51819SDave May 
3818b8a3813SDave May    Output parameter:
382d3a51819SDave May .  vec - the vector
383d3a51819SDave May 
384d3a51819SDave May    Level: beginner
385d3a51819SDave May 
3868b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmCreateGlobalVectorFromField()
387d3a51819SDave May @*/
388b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmDestroyGlobalVectorFromField(DM dm,const char fieldname[],Vec *vec)
389b5bcf523SDave May {
390b5bcf523SDave May   PetscErrorCode ierr;
391cc651181SDave May 
392fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
393fb1bcc12SMatthew G. Knepley   ierr = DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec);CHKERRQ(ierr);
394b5bcf523SDave May   PetscFunctionReturn(0);
395b5bcf523SDave May }
396b5bcf523SDave May 
397fb1bcc12SMatthew G. Knepley /*@C
398fb1bcc12SMatthew G. Knepley    DMSwarmCreateLocalVectorFromField - Creates a Vec object sharing the array associated with a given field
399fb1bcc12SMatthew G. Knepley 
400d083f849SBarry Smith    Collective on dm
401fb1bcc12SMatthew G. Knepley 
402fb1bcc12SMatthew G. Knepley    Input parameters:
40362741f57SDave May +  dm - a DMSwarm
40462741f57SDave May -  fieldname - the textual name given to a registered field
405fb1bcc12SMatthew G. Knepley 
4068b8a3813SDave May    Output parameter:
407fb1bcc12SMatthew G. Knepley .  vec - the vector
408fb1bcc12SMatthew G. Knepley 
409fb1bcc12SMatthew G. Knepley    Level: beginner
410fb1bcc12SMatthew G. Knepley 
4118b8a3813SDave May    Notes:
4128b8a3813SDave May    The vector must be returned using a matching call to DMSwarmDestroyLocalVectorFromField().
4138b8a3813SDave May 
4148b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmDestroyLocalVectorFromField()
415fb1bcc12SMatthew G. Knepley @*/
416fb1bcc12SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMSwarmCreateLocalVectorFromField(DM dm,const char fieldname[],Vec *vec)
417bbe8250bSMatthew G. Knepley {
418fb1bcc12SMatthew G. Knepley   MPI_Comm       comm = PETSC_COMM_SELF;
419bbe8250bSMatthew G. Knepley   PetscErrorCode ierr;
420bbe8250bSMatthew G. Knepley 
421fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
422fb1bcc12SMatthew G. Knepley   ierr = DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec);CHKERRQ(ierr);
423fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
424bbe8250bSMatthew G. Knepley }
425fb1bcc12SMatthew G. Knepley 
426fb1bcc12SMatthew G. Knepley /*@C
427fb1bcc12SMatthew G. Knepley    DMSwarmDestroyLocalVectorFromField - Destroys the Vec object which share the array associated with a given field
428fb1bcc12SMatthew G. Knepley 
429d083f849SBarry Smith    Collective on dm
430fb1bcc12SMatthew G. Knepley 
431fb1bcc12SMatthew G. Knepley    Input parameters:
43262741f57SDave May +  dm - a DMSwarm
43362741f57SDave May -  fieldname - the textual name given to a registered field
434fb1bcc12SMatthew G. Knepley 
4358b8a3813SDave May    Output parameter:
436fb1bcc12SMatthew G. Knepley .  vec - the vector
437fb1bcc12SMatthew G. Knepley 
438fb1bcc12SMatthew G. Knepley    Level: beginner
439fb1bcc12SMatthew G. Knepley 
4408b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmCreateLocalVectorFromField()
441fb1bcc12SMatthew G. Knepley @*/
442fb1bcc12SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMSwarmDestroyLocalVectorFromField(DM dm,const char fieldname[],Vec *vec)
443fb1bcc12SMatthew G. Knepley {
444fb1bcc12SMatthew G. Knepley   PetscErrorCode ierr;
445fb1bcc12SMatthew G. Knepley 
446fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
447fb1bcc12SMatthew G. Knepley   ierr = DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec);CHKERRQ(ierr);
448bbe8250bSMatthew G. Knepley   PetscFunctionReturn(0);
449bbe8250bSMatthew G. Knepley }
450bbe8250bSMatthew G. Knepley 
451b5bcf523SDave May /*
452b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmCreateGlobalVectorFromFields(DM dm,const PetscInt nf,const char *fieldnames[],Vec *vec)
453b5bcf523SDave May {
454b5bcf523SDave May   PetscFunctionReturn(0);
455b5bcf523SDave May }
456b5bcf523SDave May 
457b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmRestoreGlobalVectorFromFields(DM dm,Vec *vec)
458b5bcf523SDave May {
459b5bcf523SDave May   PetscFunctionReturn(0);
460b5bcf523SDave May }
461b5bcf523SDave May */
462b5bcf523SDave May 
463d3a51819SDave May /*@C
464d3a51819SDave May    DMSwarmInitializeFieldRegister - Initiates the registration of fields to a DMSwarm
465d3a51819SDave May 
466d083f849SBarry Smith    Collective on dm
467d3a51819SDave May 
468d3a51819SDave May    Input parameter:
469d3a51819SDave May .  dm - a DMSwarm
470d3a51819SDave May 
471d3a51819SDave May    Level: beginner
472d3a51819SDave May 
473d3a51819SDave May    Notes:
4748b8a3813SDave May    After all fields have been registered, you must call DMSwarmFinalizeFieldRegister().
475d3a51819SDave May 
476d3a51819SDave May .seealso: DMSwarmFinalizeFieldRegister(), DMSwarmRegisterPetscDatatypeField(),
477d3a51819SDave May  DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
478d3a51819SDave May @*/
4795f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmInitializeFieldRegister(DM dm)
4805f50eb2eSDave May {
4815f50eb2eSDave May   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
4823454631fSDave May   PetscErrorCode ierr;
4833454631fSDave May 
484521f74f9SMatthew G. Knepley   PetscFunctionBegin;
485cc651181SDave May   if (!swarm->field_registration_initialized) {
4865f50eb2eSDave May     swarm->field_registration_initialized = PETSC_TRUE;
48743f984edSMatthew G. Knepley     ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_pid,1,PETSC_INT64);CHKERRQ(ierr); /* unique identifer */
488f0cdbbbaSDave May     ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_rank,1,PETSC_INT);CHKERRQ(ierr); /* used for communication */
489cc651181SDave May   }
4905f50eb2eSDave May   PetscFunctionReturn(0);
4915f50eb2eSDave May }
4925f50eb2eSDave May 
493d3a51819SDave May /*@C
494d3a51819SDave May    DMSwarmFinalizeFieldRegister - Finalizes the registration of fields to a DMSwarm
495d3a51819SDave May 
496d083f849SBarry Smith    Collective on dm
497d3a51819SDave May 
498d3a51819SDave May    Input parameter:
499d3a51819SDave May .  dm - a DMSwarm
500d3a51819SDave May 
501d3a51819SDave May    Level: beginner
502d3a51819SDave May 
503d3a51819SDave May    Notes:
50462741f57SDave May    After DMSwarmFinalizeFieldRegister() has been called, no new fields can be defined on the DMSwarm.
505d3a51819SDave May 
506d3a51819SDave May .seealso: DMSwarmInitializeFieldRegister(), DMSwarmRegisterPetscDatatypeField(),
507d3a51819SDave May  DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
508d3a51819SDave May @*/
5095f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmFinalizeFieldRegister(DM dm)
5105f50eb2eSDave May {
5115f50eb2eSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
5126845f8f5SDave May   PetscErrorCode ierr;
5136845f8f5SDave May 
514521f74f9SMatthew G. Knepley   PetscFunctionBegin;
515f0cdbbbaSDave May   if (!swarm->field_registration_finalized) {
51677048351SPatrick Sanan     ierr = DMSwarmDataBucketFinalize(swarm->db);CHKERRQ(ierr);
517f0cdbbbaSDave May   }
518f0cdbbbaSDave May   swarm->field_registration_finalized = PETSC_TRUE;
5195f50eb2eSDave May   PetscFunctionReturn(0);
5205f50eb2eSDave May }
5215f50eb2eSDave May 
522d3a51819SDave May /*@C
523d3a51819SDave May    DMSwarmSetLocalSizes - Sets the length of all registered fields on the DMSwarm
524d3a51819SDave May 
525d3a51819SDave May    Not collective
526d3a51819SDave May 
527d3a51819SDave May    Input parameters:
52862741f57SDave May +  dm - a DMSwarm
529d3a51819SDave May .  nlocal - the length of each registered field
53062741f57SDave May -  buffer - the length of the buffer used to efficient dynamic re-sizing
531d3a51819SDave May 
532d3a51819SDave May    Level: beginner
533d3a51819SDave May 
534d3a51819SDave May .seealso: DMSwarmGetLocalSize()
535d3a51819SDave May @*/
5365f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmSetLocalSizes(DM dm,PetscInt nlocal,PetscInt buffer)
5375f50eb2eSDave May {
5385f50eb2eSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
5396845f8f5SDave May   PetscErrorCode ierr;
5405f50eb2eSDave May 
541521f74f9SMatthew G. Knepley   PetscFunctionBegin;
542f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_SetSizes,0,0,0,0);CHKERRQ(ierr);
54377048351SPatrick Sanan   ierr = DMSwarmDataBucketSetSizes(swarm->db,nlocal,buffer);CHKERRQ(ierr);
544f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_SetSizes,0,0,0,0);CHKERRQ(ierr);
5455f50eb2eSDave May   PetscFunctionReturn(0);
5465f50eb2eSDave May }
5475f50eb2eSDave May 
548d3a51819SDave May /*@C
549d3a51819SDave May    DMSwarmSetCellDM - Attachs a DM to a DMSwarm
550d3a51819SDave May 
551d083f849SBarry Smith    Collective on dm
552d3a51819SDave May 
553d3a51819SDave May    Input parameters:
55462741f57SDave May +  dm - a DMSwarm
55562741f57SDave May -  dmcell - the DM to attach to the DMSwarm
556d3a51819SDave May 
557d3a51819SDave May    Level: beginner
558d3a51819SDave May 
559d3a51819SDave May    Notes:
560d3a51819SDave May    The attached DM (dmcell) will be queried for point location and
5618b8a3813SDave May    neighbor MPI-rank information if DMSwarmMigrate() is called.
562d3a51819SDave May 
5638b8a3813SDave May .seealso: DMSwarmSetType(), DMSwarmGetCellDM(), DMSwarmMigrate()
564d3a51819SDave May @*/
565b16650c8SDave May PETSC_EXTERN PetscErrorCode DMSwarmSetCellDM(DM dm,DM dmcell)
566b16650c8SDave May {
567b16650c8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
568521f74f9SMatthew G. Knepley 
569521f74f9SMatthew G. Knepley   PetscFunctionBegin;
570b16650c8SDave May   swarm->dmcell = dmcell;
571b16650c8SDave May   PetscFunctionReturn(0);
572b16650c8SDave May }
573b16650c8SDave May 
574d3a51819SDave May /*@C
575d3a51819SDave May    DMSwarmGetCellDM - Fetches the attached cell DM
576d3a51819SDave May 
577d083f849SBarry Smith    Collective on dm
578d3a51819SDave May 
579d3a51819SDave May    Input parameter:
580d3a51819SDave May .  dm - a DMSwarm
581d3a51819SDave May 
582d3a51819SDave May    Output parameter:
583d3a51819SDave May .  dmcell - the DM which was attached to the DMSwarm
584d3a51819SDave May 
585d3a51819SDave May    Level: beginner
586d3a51819SDave May 
587d3a51819SDave May .seealso: DMSwarmSetCellDM()
588d3a51819SDave May @*/
589fe39f135SDave May PETSC_EXTERN PetscErrorCode DMSwarmGetCellDM(DM dm,DM *dmcell)
590fe39f135SDave May {
591fe39f135SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
592521f74f9SMatthew G. Knepley 
593521f74f9SMatthew G. Knepley   PetscFunctionBegin;
594fe39f135SDave May   *dmcell = swarm->dmcell;
595fe39f135SDave May   PetscFunctionReturn(0);
596fe39f135SDave May }
597fe39f135SDave May 
598d3a51819SDave May /*@C
599d3a51819SDave May    DMSwarmGetLocalSize - Retrives the local length of fields registered
600d3a51819SDave May 
601d3a51819SDave May    Not collective
602d3a51819SDave May 
603d3a51819SDave May    Input parameter:
604d3a51819SDave May .  dm - a DMSwarm
605d3a51819SDave May 
606d3a51819SDave May    Output parameter:
607d3a51819SDave May .  nlocal - the length of each registered field
608d3a51819SDave May 
609d3a51819SDave May    Level: beginner
610d3a51819SDave May 
6118b8a3813SDave May .seealso: DMSwarmGetSize(), DMSwarmSetLocalSizes()
612d3a51819SDave May @*/
613dcf43ee8SDave May PETSC_EXTERN PetscErrorCode DMSwarmGetLocalSize(DM dm,PetscInt *nlocal)
614dcf43ee8SDave May {
615dcf43ee8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
616dcf43ee8SDave May   PetscErrorCode ierr;
617dcf43ee8SDave May 
618521f74f9SMatthew G. Knepley   PetscFunctionBegin;
61977048351SPatrick Sanan   if (nlocal) {ierr = DMSwarmDataBucketGetSizes(swarm->db,nlocal,NULL,NULL);CHKERRQ(ierr);}
620dcf43ee8SDave May   PetscFunctionReturn(0);
621dcf43ee8SDave May }
622dcf43ee8SDave May 
623d3a51819SDave May /*@C
624d3a51819SDave May    DMSwarmGetSize - Retrives the total length of fields registered
625d3a51819SDave May 
626d083f849SBarry Smith    Collective on dm
627d3a51819SDave May 
628d3a51819SDave May    Input parameter:
629d3a51819SDave May .  dm - a DMSwarm
630d3a51819SDave May 
631d3a51819SDave May    Output parameter:
632d3a51819SDave May .  n - the total length of each registered field
633d3a51819SDave May 
634d3a51819SDave May    Level: beginner
635d3a51819SDave May 
636d3a51819SDave May    Note:
637d3a51819SDave May    This calls MPI_Allreduce upon each call (inefficient but safe)
638d3a51819SDave May 
6398b8a3813SDave May .seealso: DMSwarmGetLocalSize(), DMSwarmSetLocalSizes()
640d3a51819SDave May @*/
641dcf43ee8SDave May PETSC_EXTERN PetscErrorCode DMSwarmGetSize(DM dm,PetscInt *n)
642dcf43ee8SDave May {
643dcf43ee8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
644dcf43ee8SDave May   PetscErrorCode ierr;
645dcf43ee8SDave May   PetscInt       nlocal,ng;
646dcf43ee8SDave May 
647521f74f9SMatthew G. Knepley   PetscFunctionBegin;
64877048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
649dcf43ee8SDave May   ierr = MPI_Allreduce(&nlocal,&ng,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
650dcf43ee8SDave May   if (n) { *n = ng; }
651dcf43ee8SDave May   PetscFunctionReturn(0);
652dcf43ee8SDave May }
653dcf43ee8SDave May 
654d3a51819SDave May /*@C
6558b8a3813SDave May    DMSwarmRegisterPetscDatatypeField - Register a field to a DMSwarm with a native PETSc data type
656d3a51819SDave May 
657d083f849SBarry Smith    Collective on dm
658d3a51819SDave May 
659d3a51819SDave May    Input parameters:
66062741f57SDave May +  dm - a DMSwarm
661d3a51819SDave May .  fieldname - the textual name to identify this field
662d3a51819SDave May .  blocksize - the number of each data type
66362741f57SDave May -  type - a valid PETSc data type (PETSC_CHAR, PETSC_SHORT, PETSC_INT, PETSC_FLOAT, PETSC_REAL, PETSC_LONG)
664d3a51819SDave May 
665d3a51819SDave May    Level: beginner
666d3a51819SDave May 
667d3a51819SDave May    Notes:
6688b8a3813SDave May    The textual name for each registered field must be unique.
669d3a51819SDave May 
670d3a51819SDave May .seealso: DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
671d3a51819SDave May @*/
6725f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmRegisterPetscDatatypeField(DM dm,const char fieldname[],PetscInt blocksize,PetscDataType type)
673b62e03f8SDave May {
6742eac95f8SDave May   PetscErrorCode ierr;
675b62e03f8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
676b62e03f8SDave May   size_t         size;
677b62e03f8SDave May 
678521f74f9SMatthew G. Knepley   PetscFunctionBegin;
6795f50eb2eSDave May   if (!swarm->field_registration_initialized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmInitializeFieldRegister() first");
6805f50eb2eSDave May   if (swarm->field_registration_finalized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Cannot register additional fields after calling DMSwarmFinalizeFieldRegister() first");
6815f50eb2eSDave May 
6825f50eb2eSDave May   if (type == PETSC_OBJECT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
6835f50eb2eSDave May   if (type == PETSC_FUNCTION) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
6845f50eb2eSDave May   if (type == PETSC_STRING) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
6855f50eb2eSDave May   if (type == PETSC_STRUCT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
6865f50eb2eSDave May   if (type == PETSC_DATATYPE_UNKNOWN) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
687b62e03f8SDave May 
6882ddcf43eSMatthew G. Knepley   ierr = PetscDataTypeGetSize(type, &size);CHKERRQ(ierr);
689b62e03f8SDave May   /* Load a specific data type into data bucket, specifying textual name and its size in bytes */
69077048351SPatrick Sanan   ierr = DMSwarmDataBucketRegisterField(swarm->db,"DMSwarmRegisterPetscDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
69152c3ed93SDave May   {
69277048351SPatrick Sanan     DMSwarmDataField gfield;
69352c3ed93SDave May 
69477048351SPatrick Sanan     ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
69577048351SPatrick Sanan     ierr = DMSwarmDataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
69652c3ed93SDave May   }
697b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = type;
698b62e03f8SDave May   PetscFunctionReturn(0);
699b62e03f8SDave May }
700b62e03f8SDave May 
701d3a51819SDave May /*@C
702d3a51819SDave May    DMSwarmRegisterUserStructField - Register a user defined struct to a DMSwarm
703d3a51819SDave May 
704d083f849SBarry Smith    Collective on dm
705d3a51819SDave May 
706d3a51819SDave May    Input parameters:
70762741f57SDave May +  dm - a DMSwarm
708d3a51819SDave May .  fieldname - the textual name to identify this field
70962741f57SDave May -  size - the size in bytes of the user struct of each data type
710d3a51819SDave May 
711d3a51819SDave May    Level: beginner
712d3a51819SDave May 
713d3a51819SDave May    Notes:
7148b8a3813SDave May    The textual name for each registered field must be unique.
715d3a51819SDave May 
716d3a51819SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserDatatypeField()
717d3a51819SDave May @*/
7185f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmRegisterUserStructField(DM dm,const char fieldname[],size_t size)
719b62e03f8SDave May {
7202eac95f8SDave May   PetscErrorCode ierr;
721b62e03f8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
722b62e03f8SDave May 
723521f74f9SMatthew G. Knepley   PetscFunctionBegin;
72477048351SPatrick Sanan   ierr = DMSwarmDataBucketRegisterField(swarm->db,"DMSwarmRegisterUserStructField",fieldname,size,NULL);CHKERRQ(ierr);
725b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_STRUCT ;
726b62e03f8SDave May   PetscFunctionReturn(0);
727b62e03f8SDave May }
728b62e03f8SDave May 
729d3a51819SDave May /*@C
730d3a51819SDave May    DMSwarmRegisterUserDatatypeField - Register a user defined data type to a DMSwarm
731d3a51819SDave May 
732d083f849SBarry Smith    Collective on dm
733d3a51819SDave May 
734d3a51819SDave May    Input parameters:
73562741f57SDave May +  dm - a DMSwarm
736d3a51819SDave May .  fieldname - the textual name to identify this field
737d3a51819SDave May .  size - the size in bytes of the user data type
73862741f57SDave May -  blocksize - the number of each data type
739d3a51819SDave May 
740d3a51819SDave May    Level: beginner
741d3a51819SDave May 
742d3a51819SDave May    Notes:
7438b8a3813SDave May    The textual name for each registered field must be unique.
744d3a51819SDave May 
745d3a51819SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
746d3a51819SDave May @*/
747320740a0SDave May PETSC_EXTERN PetscErrorCode DMSwarmRegisterUserDatatypeField(DM dm,const char fieldname[],size_t size,PetscInt blocksize)
748b62e03f8SDave May {
749b62e03f8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
7506845f8f5SDave May   PetscErrorCode ierr;
751b62e03f8SDave May 
752521f74f9SMatthew G. Knepley   PetscFunctionBegin;
75377048351SPatrick Sanan   ierr = DMSwarmDataBucketRegisterField(swarm->db,"DMSwarmRegisterUserDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
754320740a0SDave May   {
75577048351SPatrick Sanan     DMSwarmDataField gfield;
756320740a0SDave May 
75777048351SPatrick Sanan     ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
75877048351SPatrick Sanan     ierr = DMSwarmDataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
759320740a0SDave May   }
760b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_DATATYPE_UNKNOWN;
761b62e03f8SDave May   PetscFunctionReturn(0);
762b62e03f8SDave May }
763b62e03f8SDave May 
764d3a51819SDave May /*@C
765d3a51819SDave May    DMSwarmGetField - Get access to the underlying array storing all entries associated with a registered field
766d3a51819SDave May 
767d3a51819SDave May    Not collective
768d3a51819SDave May 
769d3a51819SDave May    Input parameters:
77062741f57SDave May +  dm - a DMSwarm
77162741f57SDave May -  fieldname - the textual name to identify this field
772d3a51819SDave May 
773d3a51819SDave May    Output parameters:
77462741f57SDave May +  blocksize - the number of each data type
775d3a51819SDave May .  type - the data type
77662741f57SDave May -  data - pointer to raw array
777d3a51819SDave May 
778d3a51819SDave May    Level: beginner
779d3a51819SDave May 
780d3a51819SDave May    Notes:
7818b8a3813SDave May    The array must be returned using a matching call to DMSwarmRestoreField().
782d3a51819SDave May 
783d3a51819SDave May .seealso: DMSwarmRestoreField()
784d3a51819SDave May @*/
7855f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmGetField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
786b62e03f8SDave May {
787b62e03f8SDave May   DM_Swarm         *swarm = (DM_Swarm*)dm->data;
78877048351SPatrick Sanan   DMSwarmDataField gfield;
7892eac95f8SDave May   PetscErrorCode ierr;
790b62e03f8SDave May 
791521f74f9SMatthew G. Knepley   PetscFunctionBegin;
7923454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
79377048351SPatrick Sanan   ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
79477048351SPatrick Sanan   ierr = DMSwarmDataFieldGetAccess(gfield);CHKERRQ(ierr);
79577048351SPatrick Sanan   ierr = DMSwarmDataFieldGetEntries(gfield,data);CHKERRQ(ierr);
7961b1ea282SDave May   if (blocksize) {*blocksize = gfield->bs; }
797b5bcf523SDave May   if (type) { *type = gfield->petsc_type; }
798b62e03f8SDave May   PetscFunctionReturn(0);
799b62e03f8SDave May }
800b62e03f8SDave May 
801d3a51819SDave May /*@C
802d3a51819SDave May    DMSwarmRestoreField - Restore access to the underlying array storing all entries associated with a registered field
803d3a51819SDave May 
804d3a51819SDave May    Not collective
805d3a51819SDave May 
806d3a51819SDave May    Input parameters:
80762741f57SDave May +  dm - a DMSwarm
80862741f57SDave May -  fieldname - the textual name to identify this field
809d3a51819SDave May 
810d3a51819SDave May    Output parameters:
81162741f57SDave May +  blocksize - the number of each data type
812d3a51819SDave May .  type - the data type
81362741f57SDave May -  data - pointer to raw array
814d3a51819SDave May 
815d3a51819SDave May    Level: beginner
816d3a51819SDave May 
817d3a51819SDave May    Notes:
8188b8a3813SDave May    The user must call DMSwarmGetField() prior to calling DMSwarmRestoreField().
819d3a51819SDave May 
820d3a51819SDave May .seealso: DMSwarmGetField()
821d3a51819SDave May @*/
8225f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmRestoreField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
823b62e03f8SDave May {
824b62e03f8SDave May   DM_Swarm         *swarm = (DM_Swarm*)dm->data;
82577048351SPatrick Sanan   DMSwarmDataField gfield;
8262eac95f8SDave May   PetscErrorCode ierr;
827b62e03f8SDave May 
828521f74f9SMatthew G. Knepley   PetscFunctionBegin;
82977048351SPatrick Sanan   ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
83077048351SPatrick Sanan   ierr = DMSwarmDataFieldRestoreAccess(gfield);CHKERRQ(ierr);
831b62e03f8SDave May   if (data) *data = NULL;
832b62e03f8SDave May   PetscFunctionReturn(0);
833b62e03f8SDave May }
834b62e03f8SDave May 
835d3a51819SDave May /*@C
836d3a51819SDave May    DMSwarmAddPoint - Add space for one new point in the DMSwarm
837d3a51819SDave May 
838d3a51819SDave May    Not collective
839d3a51819SDave May 
840d3a51819SDave May    Input parameter:
841d3a51819SDave May .  dm - a DMSwarm
842d3a51819SDave May 
843d3a51819SDave May    Level: beginner
844d3a51819SDave May 
845d3a51819SDave May    Notes:
8468b8a3813SDave May    The new point will have all fields initialized to zero.
847d3a51819SDave May 
848d3a51819SDave May .seealso: DMSwarmAddNPoints()
849d3a51819SDave May @*/
850cb1d1399SDave May PETSC_EXTERN PetscErrorCode DMSwarmAddPoint(DM dm)
851cb1d1399SDave May {
852cb1d1399SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
853cb1d1399SDave May   PetscErrorCode ierr;
854cb1d1399SDave May 
855521f74f9SMatthew G. Knepley   PetscFunctionBegin;
8563454631fSDave May   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
857f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
85877048351SPatrick Sanan   ierr = DMSwarmDataBucketAddPoint(swarm->db);CHKERRQ(ierr);
859f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
860cb1d1399SDave May   PetscFunctionReturn(0);
861cb1d1399SDave May }
862cb1d1399SDave May 
863d3a51819SDave May /*@C
864d3a51819SDave May    DMSwarmAddNPoints - Add space for a number of new points in the DMSwarm
865d3a51819SDave May 
866d3a51819SDave May    Not collective
867d3a51819SDave May 
868d3a51819SDave May    Input parameters:
86962741f57SDave May +  dm - a DMSwarm
87062741f57SDave May -  npoints - the number of new points to add
871d3a51819SDave May 
872d3a51819SDave May    Level: beginner
873d3a51819SDave May 
874d3a51819SDave May    Notes:
8758b8a3813SDave May    The new point will have all fields initialized to zero.
876d3a51819SDave May 
877d3a51819SDave May .seealso: DMSwarmAddPoint()
878d3a51819SDave May @*/
879cb1d1399SDave May PETSC_EXTERN PetscErrorCode DMSwarmAddNPoints(DM dm,PetscInt npoints)
880cb1d1399SDave May {
881cb1d1399SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
882cb1d1399SDave May   PetscErrorCode ierr;
883cb1d1399SDave May   PetscInt       nlocal;
884cb1d1399SDave May 
885521f74f9SMatthew G. Knepley   PetscFunctionBegin;
886f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
88777048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
888cb1d1399SDave May   nlocal = nlocal + npoints;
88977048351SPatrick Sanan   ierr = DMSwarmDataBucketSetSizes(swarm->db,nlocal,DMSWARM_DATA_BUCKET_BUFFER_DEFAULT);CHKERRQ(ierr);
890f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
891cb1d1399SDave May   PetscFunctionReturn(0);
892cb1d1399SDave May }
893cb1d1399SDave May 
894d3a51819SDave May /*@C
895d3a51819SDave May    DMSwarmRemovePoint - Remove the last point from the DMSwarm
896d3a51819SDave May 
897d3a51819SDave May    Not collective
898d3a51819SDave May 
899d3a51819SDave May    Input parameter:
900d3a51819SDave May .  dm - a DMSwarm
901d3a51819SDave May 
902d3a51819SDave May    Level: beginner
903d3a51819SDave May 
904d3a51819SDave May .seealso: DMSwarmRemovePointAtIndex()
905d3a51819SDave May @*/
906cb1d1399SDave May PETSC_EXTERN PetscErrorCode DMSwarmRemovePoint(DM dm)
907cb1d1399SDave May {
908cb1d1399SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
909cb1d1399SDave May   PetscErrorCode ierr;
910cb1d1399SDave May 
911521f74f9SMatthew G. Knepley   PetscFunctionBegin;
912f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
91377048351SPatrick Sanan   ierr = DMSwarmDataBucketRemovePoint(swarm->db);CHKERRQ(ierr);
914f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
915cb1d1399SDave May   PetscFunctionReturn(0);
916cb1d1399SDave May }
917cb1d1399SDave May 
918d3a51819SDave May /*@C
919d3a51819SDave May    DMSwarmRemovePointAtIndex - Removes a specific point from the DMSwarm
920d3a51819SDave May 
921d3a51819SDave May    Not collective
922d3a51819SDave May 
923d3a51819SDave May    Input parameters:
92462741f57SDave May +  dm - a DMSwarm
92562741f57SDave May -  idx - index of point to remove
926d3a51819SDave May 
927d3a51819SDave May    Level: beginner
928d3a51819SDave May 
929d3a51819SDave May .seealso: DMSwarmRemovePoint()
930d3a51819SDave May @*/
931cb1d1399SDave May PETSC_EXTERN PetscErrorCode DMSwarmRemovePointAtIndex(DM dm,PetscInt idx)
932cb1d1399SDave May {
933cb1d1399SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
934cb1d1399SDave May   PetscErrorCode ierr;
935cb1d1399SDave May 
936521f74f9SMatthew G. Knepley   PetscFunctionBegin;
937f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
93877048351SPatrick Sanan   ierr = DMSwarmDataBucketRemovePointAtIndex(swarm->db,idx);CHKERRQ(ierr);
939f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
940cb1d1399SDave May   PetscFunctionReturn(0);
941cb1d1399SDave May }
942b62e03f8SDave May 
943ba4fc9c6SDave May /*@C
944ba4fc9c6SDave May    DMSwarmCopyPoint - Copy point pj to point pi in the DMSwarm
945ba4fc9c6SDave May 
946ba4fc9c6SDave May    Not collective
947ba4fc9c6SDave May 
948ba4fc9c6SDave May    Input parameters:
949ba4fc9c6SDave May +  dm - a DMSwarm
950ba4fc9c6SDave May .  pi - the index of the point to copy
951ba4fc9c6SDave May -  pj - the point index where the copy should be located
952ba4fc9c6SDave May 
953ba4fc9c6SDave May  Level: beginner
954ba4fc9c6SDave May 
955ba4fc9c6SDave May .seealso: DMSwarmRemovePoint()
956ba4fc9c6SDave May @*/
957ba4fc9c6SDave May PETSC_EXTERN PetscErrorCode DMSwarmCopyPoint(DM dm,PetscInt pi,PetscInt pj)
958ba4fc9c6SDave May {
959ba4fc9c6SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
960ba4fc9c6SDave May   PetscErrorCode ierr;
961ba4fc9c6SDave May 
962ba4fc9c6SDave May   PetscFunctionBegin;
963ba4fc9c6SDave May   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
96477048351SPatrick Sanan   ierr = DMSwarmDataBucketCopyPoint(swarm->db,pi,swarm->db,pj);CHKERRQ(ierr);
965ba4fc9c6SDave May   PetscFunctionReturn(0);
966ba4fc9c6SDave May }
967ba4fc9c6SDave May 
968095059a4SDave May PetscErrorCode DMSwarmMigrate_Basic(DM dm,PetscBool remove_sent_points)
9693454631fSDave May {
970dcf43ee8SDave May   PetscErrorCode ierr;
971521f74f9SMatthew G. Knepley 
972521f74f9SMatthew G. Knepley   PetscFunctionBegin;
973dcf43ee8SDave May   ierr = DMSwarmMigrate_Push_Basic(dm,remove_sent_points);CHKERRQ(ierr);
9743454631fSDave May   PetscFunctionReturn(0);
9753454631fSDave May }
9763454631fSDave May 
977d3a51819SDave May /*@C
978d3a51819SDave May    DMSwarmMigrate - Relocates points defined in the DMSwarm to other MPI-ranks
979d3a51819SDave May 
980d083f849SBarry Smith    Collective on dm
981d3a51819SDave May 
982d3a51819SDave May    Input parameters:
98362741f57SDave May +  dm - the DMSwarm
98462741f57SDave May -  remove_sent_points - flag indicating if sent points should be removed from the current MPI-rank
985d3a51819SDave May 
986d3a51819SDave May    Notes:
9878b8a3813SDave May    The DM will be modified to accomodate received points.
9888b8a3813SDave May    If remove_sent_points = PETSC_TRUE, any points that were sent will be removed from the DM.
9898b8a3813SDave May    Different styles of migration are supported. See DMSwarmSetMigrateType().
990d3a51819SDave May 
991d3a51819SDave May    Level: advanced
992d3a51819SDave May 
993d3a51819SDave May .seealso: DMSwarmSetMigrateType()
994d3a51819SDave May @*/
995095059a4SDave May PETSC_EXTERN PetscErrorCode DMSwarmMigrate(DM dm,PetscBool remove_sent_points)
9963454631fSDave May {
997f0cdbbbaSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
9983454631fSDave May   PetscErrorCode ierr;
999f0cdbbbaSDave May 
1000521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1001ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
1002f0cdbbbaSDave May   switch (swarm->migrate_type) {
1003f0cdbbbaSDave May     case DMSWARM_MIGRATE_BASIC:
1004095059a4SDave May       ierr = DMSwarmMigrate_Basic(dm,remove_sent_points);CHKERRQ(ierr);
1005f0cdbbbaSDave May       break;
1006f0cdbbbaSDave May     case DMSWARM_MIGRATE_DMCELLNSCATTER:
1007f0cdbbbaSDave May       ierr = DMSwarmMigrate_CellDMScatter(dm,remove_sent_points);CHKERRQ(ierr);
1008f0cdbbbaSDave May       break;
1009f0cdbbbaSDave May     case DMSWARM_MIGRATE_DMCELLEXACT:
1010f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_DMCELLEXACT not implemented");
1011f0cdbbbaSDave May       break;
1012f0cdbbbaSDave May     case DMSWARM_MIGRATE_USER:
1013f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_USER not implemented");
1014f0cdbbbaSDave May       break;
1015f0cdbbbaSDave May     default:
1016f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE type unknown");
1017f0cdbbbaSDave May       break;
1018f0cdbbbaSDave May   }
1019ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
10203454631fSDave May   PetscFunctionReturn(0);
10213454631fSDave May }
10223454631fSDave May 
1023f0cdbbbaSDave May PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm,PetscInt *globalsize);
1024f0cdbbbaSDave May 
1025d3a51819SDave May /*
1026d3a51819SDave May  DMSwarmCollectViewCreate
1027d3a51819SDave May 
1028d3a51819SDave May  * Applies a collection method and gathers point neighbour points into dm
1029d3a51819SDave May 
1030d3a51819SDave May  Notes:
10318b8a3813SDave May  Users should call DMSwarmCollectViewDestroy() after
1032d3a51819SDave May  they have finished computations associated with the collected points
1033d3a51819SDave May */
1034d3a51819SDave May 
1035d3a51819SDave May /*@C
1036d3a51819SDave May    DMSwarmCollectViewCreate - Applies a collection method and gathers points
1037d3a51819SDave May    in neighbour MPI-ranks into the DMSwarm
1038d3a51819SDave May 
1039d083f849SBarry Smith    Collective on dm
1040d3a51819SDave May 
1041d3a51819SDave May    Input parameter:
1042d3a51819SDave May .  dm - the DMSwarm
1043d3a51819SDave May 
1044d3a51819SDave May    Notes:
1045d3a51819SDave May    Users should call DMSwarmCollectViewDestroy() after
1046d3a51819SDave May    they have finished computations associated with the collected points
10478b8a3813SDave May    Different collect methods are supported. See DMSwarmSetCollectType().
1048d3a51819SDave May 
1049d3a51819SDave May    Level: advanced
1050d3a51819SDave May 
1051d3a51819SDave May .seealso: DMSwarmCollectViewDestroy(), DMSwarmSetCollectType()
1052d3a51819SDave May @*/
1053fe39f135SDave May PETSC_EXTERN PetscErrorCode DMSwarmCollectViewCreate(DM dm)
10542712d1f2SDave May {
10552712d1f2SDave May   PetscErrorCode ierr;
10562712d1f2SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
10572712d1f2SDave May   PetscInt ng;
10582712d1f2SDave May 
1059521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1060480eef7bSDave May   if (swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView currently active");
1061480eef7bSDave May   ierr = DMSwarmGetLocalSize(dm,&ng);CHKERRQ(ierr);
1062480eef7bSDave May   switch (swarm->collect_type) {
1063f0cdbbbaSDave May 
1064480eef7bSDave May     case DMSWARM_COLLECT_BASIC:
10652712d1f2SDave May       ierr = DMSwarmMigrate_GlobalToLocal_Basic(dm,&ng);CHKERRQ(ierr);
1066480eef7bSDave May       break;
1067480eef7bSDave May     case DMSWARM_COLLECT_DMDABOUNDINGBOX:
1068f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_DMDABOUNDINGBOX not implemented");
1069480eef7bSDave May       break;
1070480eef7bSDave May     case DMSWARM_COLLECT_GENERAL:
1071f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_GENERAL not implemented");
1072480eef7bSDave May       break;
1073480eef7bSDave May     default:
1074f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT type unknown");
1075480eef7bSDave May       break;
1076480eef7bSDave May   }
1077480eef7bSDave May   swarm->collect_view_active = PETSC_TRUE;
1078480eef7bSDave May   swarm->collect_view_reset_nlocal = ng;
10792712d1f2SDave May   PetscFunctionReturn(0);
10802712d1f2SDave May }
10812712d1f2SDave May 
1082d3a51819SDave May /*@C
1083d3a51819SDave May    DMSwarmCollectViewDestroy - Resets the DMSwarm to the size prior to calling DMSwarmCollectViewCreate()
1084d3a51819SDave May 
1085d083f849SBarry Smith    Collective on dm
1086d3a51819SDave May 
1087d3a51819SDave May    Input parameters:
1088d3a51819SDave May .  dm - the DMSwarm
1089d3a51819SDave May 
1090d3a51819SDave May    Notes:
1091d3a51819SDave May    Users should call DMSwarmCollectViewCreate() before this function is called.
1092d3a51819SDave May 
1093d3a51819SDave May    Level: advanced
1094d3a51819SDave May 
1095d3a51819SDave May .seealso: DMSwarmCollectViewCreate(), DMSwarmSetCollectType()
1096d3a51819SDave May @*/
1097fe39f135SDave May PETSC_EXTERN PetscErrorCode DMSwarmCollectViewDestroy(DM dm)
10982712d1f2SDave May {
10992712d1f2SDave May   PetscErrorCode ierr;
11002712d1f2SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
11012712d1f2SDave May 
1102521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1103480eef7bSDave May   if (!swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView is currently not active");
1104480eef7bSDave May   ierr = DMSwarmSetLocalSizes(dm,swarm->collect_view_reset_nlocal,-1);CHKERRQ(ierr);
1105480eef7bSDave May   swarm->collect_view_active = PETSC_FALSE;
11062712d1f2SDave May   PetscFunctionReturn(0);
11072712d1f2SDave May }
11083454631fSDave May 
1109f0cdbbbaSDave May PetscErrorCode DMSwarmSetUpPIC(DM dm)
1110f0cdbbbaSDave May {
1111f0cdbbbaSDave May   PetscInt       dim;
1112f0cdbbbaSDave May   PetscErrorCode ierr;
1113f0cdbbbaSDave May 
1114521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1115f0cdbbbaSDave May   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
1116f0cdbbbaSDave May   if (dim < 1) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
1117f0cdbbbaSDave May   if (dim > 3) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
1118f0cdbbbaSDave May   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_coor,dim,PETSC_DOUBLE);CHKERRQ(ierr);
1119e2d107dbSDave May   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_cellid,1,PETSC_INT);CHKERRQ(ierr);
1120f0cdbbbaSDave May   PetscFunctionReturn(0);
1121f0cdbbbaSDave May }
1122f0cdbbbaSDave May 
1123d3a51819SDave May /*@C
1124d3a51819SDave May    DMSwarmSetType - Set particular flavor of DMSwarm
1125d3a51819SDave May 
1126d083f849SBarry Smith    Collective on dm
1127d3a51819SDave May 
1128d3a51819SDave May    Input parameters:
112962741f57SDave May +  dm - the DMSwarm
113062741f57SDave May -  stype - the DMSwarm type (e.g. DMSWARM_PIC)
1131d3a51819SDave May 
1132d3a51819SDave May    Level: advanced
1133d3a51819SDave May 
1134d3a51819SDave May .seealso: DMSwarmSetMigrateType(), DMSwarmSetCollectType()
1135d3a51819SDave May @*/
1136f0cdbbbaSDave May PETSC_EXTERN PetscErrorCode DMSwarmSetType(DM dm,DMSwarmType stype)
1137f0cdbbbaSDave May {
1138f0cdbbbaSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1139f0cdbbbaSDave May   PetscErrorCode ierr;
1140f0cdbbbaSDave May 
1141521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1142f0cdbbbaSDave May   swarm->swarm_type = stype;
1143f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
1144f0cdbbbaSDave May     ierr = DMSwarmSetUpPIC(dm);CHKERRQ(ierr);
1145f0cdbbbaSDave May   }
1146f0cdbbbaSDave May   PetscFunctionReturn(0);
1147f0cdbbbaSDave May }
1148f0cdbbbaSDave May 
11493454631fSDave May PetscErrorCode DMSetup_Swarm(DM dm)
11503454631fSDave May {
11513454631fSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
11523454631fSDave May   PetscErrorCode ierr;
11533454631fSDave May   PetscMPIInt    rank;
11543454631fSDave May   PetscInt       p,npoints,*rankval;
11553454631fSDave May 
1156521f74f9SMatthew G. Knepley   PetscFunctionBegin;
11573454631fSDave May   if (swarm->issetup) PetscFunctionReturn(0);
11583454631fSDave May 
11593454631fSDave May   swarm->issetup = PETSC_TRUE;
11603454631fSDave May 
1161f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
1162f0cdbbbaSDave May     /* check dmcell exists */
1163f0cdbbbaSDave May     if (!swarm->dmcell) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires you call DMSwarmSetCellDM");
1164f0cdbbbaSDave May 
1165f0cdbbbaSDave May     if (swarm->dmcell->ops->locatepointssubdomain) {
1166f0cdbbbaSDave May       /* check methods exists for exact ownership identificiation */
116777b6ec44SMatthew G. Knepley       ierr = PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->ops->LocatePointsSubdomain\n");CHKERRQ(ierr);
1168f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLEXACT;
1169f0cdbbbaSDave May     } else {
1170f0cdbbbaSDave May       /* check methods exist for point location AND rank neighbor identification */
1171f0cdbbbaSDave May       if (swarm->dmcell->ops->locatepoints) {
117277b6ec44SMatthew G. Knepley         ierr = PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->LocatePoints\n");CHKERRQ(ierr);
1173f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->locatepoints be defined");
1174f0cdbbbaSDave May 
1175f0cdbbbaSDave May       if (swarm->dmcell->ops->getneighbors) {
117677b6ec44SMatthew G. Knepley         ierr = PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->GetNeigbors\n");CHKERRQ(ierr);
1177f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->getneighbors be defined");
1178f0cdbbbaSDave May 
1179f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLNSCATTER;
1180f0cdbbbaSDave May     }
1181f0cdbbbaSDave May   }
1182f0cdbbbaSDave May 
1183f0cdbbbaSDave May   ierr = DMSwarmFinalizeFieldRegister(dm);CHKERRQ(ierr);
1184f0cdbbbaSDave May 
11853454631fSDave May   /* check some fields were registered */
11863454631fSDave May   if (swarm->db->nfields <= 2) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"At least one field user must be registered via DMSwarmRegisterXXX()");
11873454631fSDave May 
11883454631fSDave May   /* check local sizes were set */
11893454631fSDave May   if (swarm->db->L == -1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Local sizes must be set via DMSwarmSetLocalSizes()");
11903454631fSDave May 
11913454631fSDave May   /* initialize values in pid and rank placeholders */
11923454631fSDave May   /* TODO: [pid - use MPI_Scan] */
11933454631fSDave May   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
119477048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db,&npoints,NULL,NULL);CHKERRQ(ierr);
1195f0cdbbbaSDave May   ierr = DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
11963454631fSDave May   for (p=0; p<npoints; p++) {
11973454631fSDave May     rankval[p] = (PetscInt)rank;
11983454631fSDave May   }
1199f0cdbbbaSDave May   ierr = DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
12003454631fSDave May   PetscFunctionReturn(0);
12013454631fSDave May }
12023454631fSDave May 
1203dc5f5ce9SDave May extern PetscErrorCode DMSwarmSortDestroy(DMSwarmSort *_ctx);
1204dc5f5ce9SDave May 
120557795646SDave May PetscErrorCode DMDestroy_Swarm(DM dm)
120657795646SDave May {
120757795646SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
120857795646SDave May   PetscErrorCode ierr;
120957795646SDave May 
121057795646SDave May   PetscFunctionBegin;
121177048351SPatrick Sanan   ierr = DMSwarmDataBucketDestroy(&swarm->db);CHKERRQ(ierr);
1212dc5f5ce9SDave May   if (swarm->sort_context) {
1213dc5f5ce9SDave May     ierr = DMSwarmSortDestroy(&swarm->sort_context);CHKERRQ(ierr);
1214dc5f5ce9SDave May   }
121557795646SDave May   ierr = PetscFree(swarm);CHKERRQ(ierr);
121657795646SDave May   PetscFunctionReturn(0);
121757795646SDave May }
121857795646SDave May 
1219a9ee3421SMatthew G. Knepley PetscErrorCode DMSwarmView_Draw(DM dm, PetscViewer viewer)
1220a9ee3421SMatthew G. Knepley {
1221a9ee3421SMatthew G. Knepley   DM             cdm;
1222a9ee3421SMatthew G. Knepley   PetscDraw      draw;
1223a9ee3421SMatthew G. Knepley   PetscReal     *coords, oldPause;
1224a9ee3421SMatthew G. Knepley   PetscInt       Np, p, bs;
1225a9ee3421SMatthew G. Knepley   PetscErrorCode ierr;
1226a9ee3421SMatthew G. Knepley 
1227a9ee3421SMatthew G. Knepley   PetscFunctionBegin;
1228a9ee3421SMatthew G. Knepley   ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr);
1229a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetCellDM(dm, &cdm);CHKERRQ(ierr);
1230a9ee3421SMatthew G. Knepley   ierr = PetscDrawGetPause(draw, &oldPause);CHKERRQ(ierr);
1231a9ee3421SMatthew G. Knepley   ierr = PetscDrawSetPause(draw, 0.0);CHKERRQ(ierr);
1232a9ee3421SMatthew G. Knepley   ierr = DMView(cdm, viewer);CHKERRQ(ierr);
1233a9ee3421SMatthew G. Knepley   ierr = PetscDrawSetPause(draw, oldPause);CHKERRQ(ierr);
1234a9ee3421SMatthew G. Knepley 
1235a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetLocalSize(dm, &Np);CHKERRQ(ierr);
1236a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1237a9ee3421SMatthew G. Knepley   for (p = 0; p < Np; ++p) {
1238a9ee3421SMatthew G. Knepley     const PetscInt i = p*bs;
1239a9ee3421SMatthew G. Knepley 
1240a9ee3421SMatthew G. Knepley     ierr = PetscDrawEllipse(draw, coords[i], coords[i+1], 0.01, 0.01, PETSC_DRAW_BLUE);CHKERRQ(ierr);
1241a9ee3421SMatthew G. Knepley   }
1242a9ee3421SMatthew G. Knepley   ierr = DMSwarmRestoreField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1243a9ee3421SMatthew G. Knepley   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
1244a9ee3421SMatthew G. Knepley   ierr = PetscDrawPause(draw);CHKERRQ(ierr);
1245a9ee3421SMatthew G. Knepley   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
1246a9ee3421SMatthew G. Knepley   PetscFunctionReturn(0);
1247a9ee3421SMatthew G. Knepley }
1248a9ee3421SMatthew G. Knepley 
12495f50eb2eSDave May PetscErrorCode DMView_Swarm(DM dm, PetscViewer viewer)
12505f50eb2eSDave May {
12515f50eb2eSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1252a9ee3421SMatthew G. Knepley   PetscBool      iascii,ibinary,ishdf5,isvtk,isdraw;
12535f50eb2eSDave May   PetscErrorCode ierr;
12545f50eb2eSDave May 
12555f50eb2eSDave May   PetscFunctionBegin;
12565f50eb2eSDave May   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
12575f50eb2eSDave May   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
12585f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
12595f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY,&ibinary);CHKERRQ(ierr);
12605f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK,   &isvtk);CHKERRQ(ierr);
12615f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
1262a9ee3421SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW,  &isdraw);CHKERRQ(ierr);
12635f50eb2eSDave May   if (iascii) {
126477048351SPatrick Sanan     ierr = DMSwarmDataBucketView(PetscObjectComm((PetscObject)dm),swarm->db,NULL,DATABUCKET_VIEW_STDOUT);CHKERRQ(ierr);
1265298827fbSBarry Smith   } else if (ibinary) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO Binary support");
12665f50eb2eSDave May #if defined(PETSC_HAVE_HDF5)
1267298827fbSBarry Smith   else if (ishdf5) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO HDF5 support");
12685f50eb2eSDave May #else
1269298827fbSBarry Smith   else if (ishdf5) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"HDF5 not supported. Please reconfigure using --download-hdf5");
12705f50eb2eSDave May #endif
1271298827fbSBarry Smith   else if (isvtk) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO VTK support");
1272298827fbSBarry Smith   else if (isdraw) {
1273a9ee3421SMatthew G. Knepley     ierr = DMSwarmView_Draw(dm, viewer);CHKERRQ(ierr);
12745f50eb2eSDave May   }
12755f50eb2eSDave May   PetscFunctionReturn(0);
12765f50eb2eSDave May }
12775f50eb2eSDave May 
1278d3a51819SDave May /*MC
1279d3a51819SDave May 
1280d3a51819SDave May  DMSWARM = "swarm" - A DM object used to represent arrays of data (fields) of arbitrary data type.
128162741f57SDave May  This implementation was designed for particle methods in which the underlying
1282d3a51819SDave May  data required to be represented is both (i) dynamic in length, (ii) and of arbitrary data type.
1283d3a51819SDave May 
128462741f57SDave May  User data can be represented by DMSwarm through a registering "fields".
128562741f57SDave May  To register a field, the user must provide;
128662741f57SDave May  (a) a unique name;
128762741f57SDave May  (b) the data type (or size in bytes);
128862741f57SDave May  (c) the block size of the data.
1289d3a51819SDave May 
1290d3a51819SDave May  For example, suppose the application requires a unique id, energy, momentum and density to be stored
1291c215a47eSMatthew Knepley  on a set of particles. Then the following code could be used
1292d3a51819SDave May 
129362741f57SDave May $    DMSwarmInitializeFieldRegister(dm)
129462741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"uid",1,PETSC_LONG);
129562741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"energy",1,PETSC_REAL);
129662741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"momentum",3,PETSC_REAL);
129762741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"density",1,PETSC_FLOAT);
129862741f57SDave May $    DMSwarmFinalizeFieldRegister(dm)
1299d3a51819SDave May 
1300d3a51819SDave May  The fields represented by DMSwarm are dynamic and can be re-sized at any time.
130162741f57SDave May  The only restriction imposed by DMSwarm is that all fields contain the same number of points.
1302d3a51819SDave May 
1303d3a51819SDave May  To support particle methods, "migration" techniques are provided. These methods migrate data
1304d3a51819SDave May  between MPI-ranks.
1305d3a51819SDave May 
1306d3a51819SDave May  DMSwarm supports the methods DMCreateGlobalVector() and DMCreateLocalVector().
1307d3a51819SDave May  As a DMSwarm may internally define and store values of different data types,
130862741f57SDave May  before calling DMCreateGlobalVector() or DMCreateLocalVector(), the user must inform DMSwarm which
1309d3a51819SDave May  fields should be used to define a Vec object via
1310d3a51819SDave May    DMSwarmVectorDefineField()
1311c215a47eSMatthew Knepley  The specified field can be changed at any time - thereby permitting vectors
1312c215a47eSMatthew Knepley  compatible with different fields to be created.
1313d3a51819SDave May 
131462741f57SDave May  A dual representation of fields in the DMSwarm and a Vec object is permitted via
1315d3a51819SDave May    DMSwarmCreateGlobalVectorFromField()
1316d3a51819SDave May  Here the data defining the field in the DMSwarm is shared with a Vec.
1317d3a51819SDave May  This is inherently unsafe if you alter the size of the field at any time between
1318d3a51819SDave May  calls to DMSwarmCreateGlobalVectorFromField() and DMSwarmDestroyGlobalVectorFromField().
1319cc651181SDave May  If the local size of the DMSwarm does not match the local size of the global vector
1320cc651181SDave May  when DMSwarmDestroyGlobalVectorFromField() is called, an error is thrown.
1321d3a51819SDave May 
132262741f57SDave May  Additional high-level support is provided for Particle-In-Cell methods.
132362741f57SDave May  Please refer to the man page for DMSwarmSetType().
132462741f57SDave May 
1325d3a51819SDave May  Level: beginner
1326d3a51819SDave May 
1327d3a51819SDave May .seealso: DMType, DMCreate(), DMSetType()
1328d3a51819SDave May M*/
132957795646SDave May PETSC_EXTERN PetscErrorCode DMCreate_Swarm(DM dm)
133057795646SDave May {
133157795646SDave May   DM_Swarm      *swarm;
133257795646SDave May   PetscErrorCode ierr;
133357795646SDave May 
133457795646SDave May   PetscFunctionBegin;
133557795646SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
133657795646SDave May   ierr     = PetscNewLog(dm,&swarm);CHKERRQ(ierr);
1337f0cdbbbaSDave May   dm->data = swarm;
133857795646SDave May 
133977048351SPatrick Sanan   ierr = DMSwarmDataBucketCreate(&swarm->db);CHKERRQ(ierr);
1340f0cdbbbaSDave May   ierr = DMSwarmInitializeFieldRegister(dm);CHKERRQ(ierr);
1341f0cdbbbaSDave May 
1342b5bcf523SDave May   swarm->vec_field_set = PETSC_FALSE;
13433454631fSDave May   swarm->issetup = PETSC_FALSE;
1344480eef7bSDave May   swarm->swarm_type = DMSWARM_BASIC;
1345480eef7bSDave May   swarm->migrate_type = DMSWARM_MIGRATE_BASIC;
1346480eef7bSDave May   swarm->collect_type = DMSWARM_COLLECT_BASIC;
134740c453e9SDave May   swarm->migrate_error_on_missing_point = PETSC_FALSE;
1348b62e03f8SDave May 
1349f0cdbbbaSDave May   swarm->dmcell = NULL;
1350f0cdbbbaSDave May   swarm->collect_view_active = PETSC_FALSE;
1351f0cdbbbaSDave May   swarm->collect_view_reset_nlocal = -1;
135257795646SDave May 
1353f0cdbbbaSDave May   dm->dim  = 0;
13545f50eb2eSDave May   dm->ops->view                            = DMView_Swarm;
135557795646SDave May   dm->ops->load                            = NULL;
135657795646SDave May   dm->ops->setfromoptions                  = NULL;
135757795646SDave May   dm->ops->clone                           = NULL;
13583454631fSDave May   dm->ops->setup                           = DMSetup_Swarm;
13591bb6d2a8SBarry Smith   dm->ops->createlocalsection              = NULL;
136057795646SDave May   dm->ops->createdefaultconstraints        = NULL;
1361b5bcf523SDave May   dm->ops->createglobalvector              = DMCreateGlobalVector_Swarm;
1362b5bcf523SDave May   dm->ops->createlocalvector               = DMCreateLocalVector_Swarm;
136357795646SDave May   dm->ops->getlocaltoglobalmapping         = NULL;
136457795646SDave May   dm->ops->createfieldis                   = NULL;
136557795646SDave May   dm->ops->createcoordinatedm              = NULL;
136657795646SDave May   dm->ops->getcoloring                     = NULL;
136757795646SDave May   dm->ops->creatematrix                    = NULL;
136857795646SDave May   dm->ops->createinterpolation             = NULL;
13695a84ad33SLisandro Dalcin   dm->ops->createinjection                 = NULL;
137083c47955SMatthew G. Knepley   dm->ops->createmassmatrix                = DMCreateMassMatrix_Swarm;
137157795646SDave May   dm->ops->refine                          = NULL;
137257795646SDave May   dm->ops->coarsen                         = NULL;
137357795646SDave May   dm->ops->refinehierarchy                 = NULL;
137457795646SDave May   dm->ops->coarsenhierarchy                = NULL;
137557795646SDave May   dm->ops->globaltolocalbegin              = NULL;
137657795646SDave May   dm->ops->globaltolocalend                = NULL;
137757795646SDave May   dm->ops->localtoglobalbegin              = NULL;
137857795646SDave May   dm->ops->localtoglobalend                = NULL;
137957795646SDave May   dm->ops->destroy                         = DMDestroy_Swarm;
138057795646SDave May   dm->ops->createsubdm                     = NULL;
138157795646SDave May   dm->ops->getdimpoints                    = NULL;
138257795646SDave May   dm->ops->locatepoints                    = NULL;
138357795646SDave May   PetscFunctionReturn(0);
138457795646SDave May }
1385