xref: /petsc/src/dm/impls/swarm/swarm.c (revision 895a1698f8b367a403f6cc7079c284c6ba82f4f1)
157795646SDave May #define PETSCDM_DLL
257795646SDave May #include <petsc/private/dmswarmimpl.h>    /*I   "petscdmswarm.h"   I*/
383c47955SMatthew G. Knepley #include <petsc/private/hash.h>
45917a6f0SStefano Zampini #include <petscviewer.h>
55917a6f0SStefano Zampini #include <petscdraw.h>
683c47955SMatthew G. Knepley #include <petscdmplex.h>
7b62e03f8SDave May #include "data_bucket.h"
857795646SDave May 
9f2b2bee7SDave May PetscLogEvent DMSWARM_Migrate, DMSWARM_SetSizes, DMSWARM_AddPoints, DMSWARM_RemovePoints, DMSWARM_Sort;
10ed923d71SDave May PetscLogEvent DMSWARM_DataExchangerTopologySetup, DMSWARM_DataExchangerBegin, DMSWARM_DataExchangerEnd;
11ed923d71SDave May PetscLogEvent DMSWARM_DataExchangerSendCount, DMSWARM_DataExchangerPack;
12ed923d71SDave May 
13f0cdbbbaSDave May const char* DMSwarmTypeNames[] = { "basic", "pic", 0 };
14f0cdbbbaSDave May const char* DMSwarmMigrateTypeNames[] = { "basic", "dmcellnscatter", "dmcellexact", "user", 0 };
15f0cdbbbaSDave May const char* DMSwarmCollectTypeNames[] = { "basic", "boundingbox", "general", "user", 0 };
16e2d107dbSDave May const char* DMSwarmPICLayoutTypeNames[] = { "regular", "gauss", "subdivision", 0 };
17f0cdbbbaSDave May 
18f0cdbbbaSDave May const char DMSwarmField_pid[] = "DMSwarm_pid";
19f0cdbbbaSDave May const char DMSwarmField_rank[] = "DMSwarm_rank";
20f0cdbbbaSDave May const char DMSwarmPICField_coor[] = "DMSwarmPIC_coor";
21e2d107dbSDave May const char DMSwarmPICField_cellid[] = "DMSwarm_cellid";
22f0cdbbbaSDave May 
23d3a51819SDave May /*@C
2462741f57SDave May    DMSwarmVectorDefineField - Sets the field from which to define a Vec object
2562741f57SDave May                              when DMCreateLocalVector(), or DMCreateGlobalVector() is called
2657795646SDave May 
27d3a51819SDave May    Collective on DM
2857795646SDave May 
29d3a51819SDave May    Input parameters:
3062741f57SDave May +  dm - a DMSwarm
3162741f57SDave May -  fieldname - the textual name given to a registered field
3257795646SDave May 
33d3a51819SDave May    Level: beginner
3457795646SDave May 
35d3a51819SDave May    Notes:
3662741f57SDave May    The field with name fieldname must be defined as having a data type of PetscScalar.
37d3a51819SDave May    This function must be called prior to calling DMCreateLocalVector(), DMCreateGlobalVector().
38d3a51819SDave May    Mutiple calls to DMSwarmVectorDefineField() are permitted.
3957795646SDave May 
408b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMCreateGlobalVector(), DMCreateLocalVector()
41d3a51819SDave May @*/
42b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmVectorDefineField(DM dm,const char fieldname[])
43b5bcf523SDave May {
44b5bcf523SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
45b5bcf523SDave May   PetscErrorCode ierr;
46b5bcf523SDave May   PetscInt bs,n;
47b5bcf523SDave May   PetscScalar *array;
48b5bcf523SDave May   PetscDataType type;
49b5bcf523SDave May 
50a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
513454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
526845f8f5SDave May   ierr = DataBucketGetSizes(swarm->db,&n,NULL,NULL);CHKERRQ(ierr);
53b5bcf523SDave May   ierr = DMSwarmGetField(dm,fieldname,&bs,&type,(void**)&array);CHKERRQ(ierr);
54b5bcf523SDave May 
55b5bcf523SDave May   /* Check all fields are of type PETSC_REAL or PETSC_SCALAR */
56b5bcf523SDave May   if (type != PETSC_REAL) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only valid for PETSC_REAL");
57521f74f9SMatthew G. Knepley   ierr = PetscSNPrintf(swarm->vec_field_name,PETSC_MAX_PATH_LEN-1,"%s",fieldname);CHKERRQ(ierr);
58b5bcf523SDave May   swarm->vec_field_set = PETSC_TRUE;
591b1ea282SDave May   swarm->vec_field_bs = bs;
60b5bcf523SDave May   swarm->vec_field_nlocal = n;
61dcf43ee8SDave May   ierr = DMSwarmRestoreField(dm,fieldname,&bs,&type,(void**)&array);CHKERRQ(ierr);
62b5bcf523SDave May   PetscFunctionReturn(0);
63b5bcf523SDave May }
64b5bcf523SDave May 
65cc651181SDave May /* requires DMSwarmDefineFieldVector has been called */
66b5bcf523SDave May PetscErrorCode DMCreateGlobalVector_Swarm(DM dm,Vec *vec)
67b5bcf523SDave May {
68b5bcf523SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
69b5bcf523SDave May   PetscErrorCode ierr;
70b5bcf523SDave May   Vec x;
71b5bcf523SDave May   char name[PETSC_MAX_PATH_LEN];
72b5bcf523SDave May 
73a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
743454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
75b5bcf523SDave May   if (!swarm->vec_field_set) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmVectorDefineField first");
76cc651181SDave May   if (swarm->vec_field_nlocal != swarm->db->L) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSwarm sizes have changed since last call to VectorDefineField first"); /* Stale data */
77cc651181SDave May 
78521f74f9SMatthew G. Knepley   ierr = PetscSNPrintf(name,PETSC_MAX_PATH_LEN-1,"DMSwarmField_%s",swarm->vec_field_name);CHKERRQ(ierr);
79b5bcf523SDave May   ierr = VecCreate(PetscObjectComm((PetscObject)dm),&x);CHKERRQ(ierr);
80b5bcf523SDave May   ierr = PetscObjectSetName((PetscObject)x,name);CHKERRQ(ierr);
811b1ea282SDave May   ierr = VecSetSizes(x,swarm->db->L*swarm->vec_field_bs,PETSC_DETERMINE);CHKERRQ(ierr);
82b5bcf523SDave May   ierr = VecSetBlockSize(x,swarm->vec_field_bs);CHKERRQ(ierr);
83b5bcf523SDave May   ierr = VecSetFromOptions(x);CHKERRQ(ierr);
84b5bcf523SDave May   *vec = x;
85b5bcf523SDave May   PetscFunctionReturn(0);
86b5bcf523SDave May }
87b5bcf523SDave May 
88b5bcf523SDave May /* requires DMSwarmDefineFieldVector has been called */
89b5bcf523SDave May PetscErrorCode DMCreateLocalVector_Swarm(DM dm,Vec *vec)
90b5bcf523SDave May {
91b5bcf523SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
92b5bcf523SDave May   PetscErrorCode ierr;
93b5bcf523SDave May   Vec x;
94b5bcf523SDave May   char name[PETSC_MAX_PATH_LEN];
95b5bcf523SDave May 
96a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
973454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
98b5bcf523SDave May   if (!swarm->vec_field_set) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmVectorDefineField first");
99cc651181SDave May   if (swarm->vec_field_nlocal != swarm->db->L) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSwarm sizes have changed since last call to VectorDefineField first"); /* Stale data */
100cc651181SDave May 
101521f74f9SMatthew G. Knepley   ierr = PetscSNPrintf(name,PETSC_MAX_PATH_LEN-1,"DMSwarmField_%s",swarm->vec_field_name);CHKERRQ(ierr);
102b5bcf523SDave May   ierr = VecCreate(PETSC_COMM_SELF,&x);CHKERRQ(ierr);
103b5bcf523SDave May   ierr = PetscObjectSetName((PetscObject)x,name);CHKERRQ(ierr);
104071900c8SMatthew G. Knepley   ierr = VecSetSizes(x,swarm->db->L*swarm->vec_field_bs,PETSC_DETERMINE);CHKERRQ(ierr);
105b5bcf523SDave May   ierr = VecSetBlockSize(x,swarm->vec_field_bs);CHKERRQ(ierr);
106b5bcf523SDave May   ierr = VecSetFromOptions(x);CHKERRQ(ierr);
107b5bcf523SDave May   *vec = x;
108b5bcf523SDave May   PetscFunctionReturn(0);
109b5bcf523SDave May }
110b5bcf523SDave May 
111fb1bcc12SMatthew G. Knepley static PetscErrorCode DMSwarmDestroyVectorFromField_Private(DM dm, const char fieldname[], Vec *vec)
112fb1bcc12SMatthew G. Knepley {
113fb1bcc12SMatthew G. Knepley   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
114fb1bcc12SMatthew G. Knepley   DataField      gfield;
115fb1bcc12SMatthew G. Knepley   void         (*fptr)(void);
116fb1bcc12SMatthew G. Knepley   PetscInt       bs, nlocal;
117fb1bcc12SMatthew G. Knepley   char           name[PETSC_MAX_PATH_LEN];
118fb1bcc12SMatthew G. Knepley   PetscErrorCode ierr;
119d3a51819SDave May 
120fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
121fb1bcc12SMatthew G. Knepley   ierr = VecGetLocalSize(*vec, &nlocal);CHKERRQ(ierr);
122fb1bcc12SMatthew G. Knepley   ierr = VecGetBlockSize(*vec, &bs);CHKERRQ(ierr);
123fb1bcc12SMatthew G. Knepley   if (nlocal/bs != swarm->db->L) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSwarm sizes have changed since vector was created - cannot ensure pointers are valid"); /* Stale data */
124fb1bcc12SMatthew G. Knepley   ierr = DataBucketGetDataFieldByName(swarm->db, fieldname, &gfield);CHKERRQ(ierr);
125fb1bcc12SMatthew G. Knepley   /* check vector is an inplace array */
126521f74f9SMatthew G. Knepley   ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarm_VecFieldInPlace_%s", fieldname);CHKERRQ(ierr);
127fb1bcc12SMatthew G. Knepley   ierr = PetscObjectQueryFunction((PetscObject) *vec, name, &fptr);CHKERRQ(ierr);
128fb1bcc12SMatthew G. Knepley   if (!fptr) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_USER, "Vector being destroyed was not created from DMSwarm field(%s)", fieldname);
129fb1bcc12SMatthew G. Knepley   ierr = DataFieldRestoreAccess(gfield);CHKERRQ(ierr);
130fb1bcc12SMatthew G. Knepley   ierr = VecDestroy(vec);CHKERRQ(ierr);
131fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
132fb1bcc12SMatthew G. Knepley }
133fb1bcc12SMatthew G. Knepley 
134fb1bcc12SMatthew G. Knepley static PetscErrorCode DMSwarmCreateVectorFromField_Private(DM dm, const char fieldname[], MPI_Comm comm, Vec *vec)
135fb1bcc12SMatthew G. Knepley {
136fb1bcc12SMatthew G. Knepley   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
137fb1bcc12SMatthew G. Knepley   PetscDataType  type;
138fb1bcc12SMatthew G. Knepley   PetscScalar   *array;
139fb1bcc12SMatthew G. Knepley   PetscInt       bs, n;
140fb1bcc12SMatthew G. Knepley   char           name[PETSC_MAX_PATH_LEN];
141fb1bcc12SMatthew G. Knepley   PetscMPIInt    commsize;
142fb1bcc12SMatthew G. Knepley   PetscErrorCode ierr;
143fb1bcc12SMatthew G. Knepley 
144fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
145fb1bcc12SMatthew G. Knepley   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
146fb1bcc12SMatthew G. Knepley   ierr = DataBucketGetSizes(swarm->db, &n, NULL, NULL);CHKERRQ(ierr);
147fb1bcc12SMatthew G. Knepley   ierr = DMSwarmGetField(dm, fieldname, &bs, &type, (void **) &array);CHKERRQ(ierr);
148fb1bcc12SMatthew G. Knepley   if (type != PETSC_REAL) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Only valid for PETSC_REAL");
149fb1bcc12SMatthew G. Knepley 
150fb1bcc12SMatthew G. Knepley   ierr = MPI_Comm_size(comm, &commsize);CHKERRQ(ierr);
151fb1bcc12SMatthew G. Knepley   if (commsize == 1) {
152fb1bcc12SMatthew G. Knepley     ierr = VecCreateSeqWithArray(comm, bs, n*bs, array, vec);CHKERRQ(ierr);
153fb1bcc12SMatthew G. Knepley   } else {
154fb1bcc12SMatthew G. Knepley     ierr = VecCreateMPIWithArray(comm, bs, n*bs, PETSC_DETERMINE, array, vec);CHKERRQ(ierr);
155fb1bcc12SMatthew G. Knepley   }
156fb1bcc12SMatthew G. Knepley   ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarmSharedField_%s", fieldname);CHKERRQ(ierr);
157fb1bcc12SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) *vec, name);CHKERRQ(ierr);
158fb1bcc12SMatthew G. Knepley 
159fb1bcc12SMatthew G. Knepley   /* Set guard */
160fb1bcc12SMatthew G. Knepley   ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarm_VecFieldInPlace_%s", fieldname);CHKERRQ(ierr);
161fb1bcc12SMatthew G. Knepley   ierr = PetscObjectComposeFunction((PetscObject) *vec, name, DMSwarmDestroyVectorFromField_Private);CHKERRQ(ierr);
162fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
163fb1bcc12SMatthew G. Knepley }
164fb1bcc12SMatthew G. Knepley 
16583c47955SMatthew G. Knepley static PetscErrorCode DMSwarmComputeMassMatrix_Private(DM dmc, DM dmf, Mat mass, void *ctx)
16683c47955SMatthew G. Knepley {
16783c47955SMatthew G. Knepley   const char    *name = "Mass Matrix";
16883c47955SMatthew G. Knepley   PetscDS        prob;
16983c47955SMatthew G. Knepley   PetscSection   fsection, globalFSection;
17083c47955SMatthew G. Knepley   PetscHashJK    ht;
17183c47955SMatthew G. Knepley   PetscLayout    rLayout;
17283c47955SMatthew G. Knepley   PetscInt      *dnz, *onz;
17383c47955SMatthew G. Knepley   PetscInt       locRows, rStart, rEnd;
17483c47955SMatthew G. Knepley   PetscReal     *x, *v0, *J, *invJ, detJ;
17583c47955SMatthew G. Knepley   PetscScalar   *elemMat;
17683c47955SMatthew G. Knepley   PetscInt       dim, Nf, field, totDim, cStart, cEnd, cell;
17783c47955SMatthew G. Knepley   PetscErrorCode ierr;
17883c47955SMatthew G. Knepley 
17983c47955SMatthew G. Knepley   PetscFunctionBegin;
18083c47955SMatthew G. Knepley   ierr = DMGetCoordinateDim(dmf, &dim);CHKERRQ(ierr);
18183c47955SMatthew G. Knepley   ierr = DMGetDS(dmf, &prob);CHKERRQ(ierr);
18283c47955SMatthew G. Knepley   ierr = PetscDSGetRefCoordArrays(prob, &x, NULL);CHKERRQ(ierr);
18383c47955SMatthew G. Knepley   ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr);
18483c47955SMatthew G. Knepley   ierr = PetscMalloc3(dim,&v0,dim*dim,&J,dim*dim,&invJ);CHKERRQ(ierr);
18583c47955SMatthew G. Knepley   ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);
18683c47955SMatthew G. Knepley   ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);
18783c47955SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd);CHKERRQ(ierr);
18883c47955SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr);
18983c47955SMatthew G. Knepley   ierr = PetscMalloc1(totDim, &elemMat);CHKERRQ(ierr);
19083c47955SMatthew G. Knepley   ierr = DMSwarmSortGetAccess(dmc);CHKERRQ(ierr);
19183c47955SMatthew G. Knepley 
19283c47955SMatthew G. Knepley   ierr = MatGetLocalSize(mass, &locRows, NULL);CHKERRQ(ierr);
19383c47955SMatthew G. Knepley   ierr = PetscLayoutCreate(PetscObjectComm((PetscObject) mass), &rLayout);CHKERRQ(ierr);
19483c47955SMatthew G. Knepley   ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr);
19583c47955SMatthew G. Knepley   ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr);
19683c47955SMatthew G. Knepley   ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr);
19783c47955SMatthew G. Knepley   ierr = PetscLayoutGetRange(rLayout, &rStart, &rEnd);CHKERRQ(ierr);
19883c47955SMatthew G. Knepley   ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr);
19983c47955SMatthew G. Knepley   ierr = PetscCalloc2(locRows,&dnz,locRows,&onz);CHKERRQ(ierr);
20083c47955SMatthew G. Knepley   ierr = PetscHashJKCreate(&ht);CHKERRQ(ierr);
20183c47955SMatthew G. Knepley   for (field = 0; field < Nf; ++field) {
20283c47955SMatthew G. Knepley     PetscObject      obj;
20383c47955SMatthew G. Knepley     PetscQuadrature  quad;
20483c47955SMatthew G. Knepley     const PetscReal *qpoints;
20583c47955SMatthew G. Knepley     PetscInt         Nq, Nc, i;
20683c47955SMatthew G. Knepley 
20783c47955SMatthew G. Knepley     ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr);
20883c47955SMatthew G. Knepley     ierr = PetscFEGetQuadrature((PetscFE) obj, &quad);CHKERRQ(ierr);
20983c47955SMatthew G. Knepley     ierr = PetscQuadratureGetData(quad, NULL, &Nc, &Nq, &qpoints, NULL);CHKERRQ(ierr);
21083c47955SMatthew G. Knepley     /* For each fine grid cell */
21183c47955SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
21283c47955SMatthew G. Knepley       PetscInt  Np, c;
21383c47955SMatthew G. Knepley       PetscInt *findices,   *cindices;
21483c47955SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
21583c47955SMatthew G. Knepley 
21683c47955SMatthew G. Knepley       ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
21783c47955SMatthew G. Knepley       ierr = DMSwarmSortGetNumberOfPointsPerCell(dmc, cell, &Np);CHKERRQ(ierr);
21883c47955SMatthew G. Knepley       /* Update preallocation info */
21983c47955SMatthew G. Knepley       if (Np != Nq) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not all closure points located");
22083c47955SMatthew G. Knepley       {
22183c47955SMatthew G. Knepley         PetscHashJKKey  key;
22283c47955SMatthew G. Knepley         PetscHashJKIter missing, iter;
22383c47955SMatthew G. Knepley 
22483c47955SMatthew G. Knepley         for (i = 0; i < numFIndices; ++i) {
22583c47955SMatthew G. Knepley           key.j = findices[i];
22683c47955SMatthew G. Knepley           if (key.j >= 0) {
22783c47955SMatthew G. Knepley             /* Get indices for coarse elements */
22883c47955SMatthew G. Knepley             ierr = DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices);CHKERRQ(ierr);
22983c47955SMatthew G. Knepley             for (c = 0; c < numCIndices; ++c) {
23083c47955SMatthew G. Knepley               key.k = cindices[c];
23183c47955SMatthew G. Knepley               if (key.k < 0) continue;
23283c47955SMatthew G. Knepley               ierr = PetscHashJKPut(ht, key, &missing, &iter);CHKERRQ(ierr);
23383c47955SMatthew G. Knepley               if (missing) {
23483c47955SMatthew G. Knepley                 ierr = PetscHashJKSet(ht, iter, 1);CHKERRQ(ierr);
23583c47955SMatthew G. Knepley                 if ((key.k >= rStart) && (key.k < rEnd)) ++dnz[key.j-rStart];
23683c47955SMatthew G. Knepley                 else                                     ++onz[key.j-rStart];
23783c47955SMatthew G. Knepley               }
23883c47955SMatthew G. Knepley             }
23983c47955SMatthew G. Knepley             ierr = PetscFree(cindices);CHKERRQ(ierr);
24083c47955SMatthew G. Knepley           }
24183c47955SMatthew G. Knepley         }
24283c47955SMatthew G. Knepley       }
24383c47955SMatthew G. Knepley       ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
24483c47955SMatthew G. Knepley     }
24583c47955SMatthew G. Knepley   }
24683c47955SMatthew G. Knepley   ierr = PetscHashJKDestroy(&ht);CHKERRQ(ierr);
24783c47955SMatthew G. Knepley   ierr = MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL);CHKERRQ(ierr);
24883c47955SMatthew G. Knepley   ierr = MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR,PETSC_TRUE);CHKERRQ(ierr);
24983c47955SMatthew G. Knepley   ierr = PetscFree2(dnz,onz);CHKERRQ(ierr);
25083c47955SMatthew G. Knepley   for (field = 0; field < Nf; ++field) {
25183c47955SMatthew G. Knepley     PetscObject      obj;
25283c47955SMatthew G. Knepley     PetscQuadrature  quad;
25383c47955SMatthew G. Knepley     PetscReal       *Bfine;
25483c47955SMatthew G. Knepley     const PetscReal *qweights;
25583c47955SMatthew G. Knepley     PetscInt         Nq, Nc, i;
25683c47955SMatthew G. Knepley 
25783c47955SMatthew G. Knepley     ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr);
25883c47955SMatthew G. Knepley     ierr = PetscFEGetDefaultTabulation((PetscFE) obj, &Bfine, NULL, NULL);CHKERRQ(ierr);
25983c47955SMatthew G. Knepley     ierr = PetscFEGetQuadrature((PetscFE) obj, &quad);CHKERRQ(ierr);
26083c47955SMatthew G. Knepley     ierr = PetscQuadratureGetData(quad, NULL, &Nc, &Nq, NULL, &qweights);CHKERRQ(ierr);
26183c47955SMatthew G. Knepley     /* For each fine grid cell */
26283c47955SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
26383c47955SMatthew G. Knepley       PetscInt           Np, c, j;
26483c47955SMatthew G. Knepley       PetscInt          *findices,   *cindices;
26583c47955SMatthew G. Knepley       PetscInt           numFIndices, numCIndices;
26683c47955SMatthew G. Knepley 
26783c47955SMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr);
26883c47955SMatthew G. Knepley       ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
26983c47955SMatthew G. Knepley       ierr = DMSwarmSortGetNumberOfPointsPerCell(dmc, cell, &Np);CHKERRQ(ierr);
27083c47955SMatthew G. Knepley       if (Np != Nq) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Not all closure points located");
27183c47955SMatthew G. Knepley       ierr = DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices);CHKERRQ(ierr);
27283c47955SMatthew G. Knepley       /* Get elemMat entries by multiplying by weight */
27383c47955SMatthew G. Knepley       for (i = 0; i < numFIndices; ++i) {
27483c47955SMatthew G. Knepley         ierr = PetscMemzero(elemMat, numCIndices * sizeof(PetscScalar));CHKERRQ(ierr);
27583c47955SMatthew G. Knepley         for (j = 0; j < numCIndices; ++j) {
27683c47955SMatthew G. Knepley           for (c = 0; c < Nc; ++c) elemMat[j] += Bfine[(j*numFIndices + i)*Nc + c]*qweights[j*Nc + c]*detJ;
27783c47955SMatthew G. Knepley         }
27883c47955SMatthew G. Knepley         /* Update interpolator */
27983c47955SMatthew G. Knepley         if (0) {ierr = DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat);CHKERRQ(ierr);}
28083c47955SMatthew G. Knepley         ierr = MatSetValues(mass, 1, &findices[i], numCIndices, cindices, elemMat, ADD_VALUES);CHKERRQ(ierr);
28183c47955SMatthew G. Knepley       }
28283c47955SMatthew G. Knepley       ierr = PetscFree(cindices);CHKERRQ(ierr);
28383c47955SMatthew G. Knepley       ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, &numFIndices, &findices, NULL);CHKERRQ(ierr);
28483c47955SMatthew G. Knepley     }
28583c47955SMatthew G. Knepley   }
28683c47955SMatthew G. Knepley   ierr = DMSwarmSortRestoreAccess(dmc);CHKERRQ(ierr);
28783c47955SMatthew G. Knepley   ierr = PetscFree3(v0,J,invJ);CHKERRQ(ierr);
28883c47955SMatthew G. Knepley   ierr = PetscFree(elemMat);CHKERRQ(ierr);
28983c47955SMatthew G. Knepley   ierr = MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
29083c47955SMatthew G. Knepley   ierr = MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
29183c47955SMatthew G. Knepley   PetscFunctionReturn(0);
29283c47955SMatthew G. Knepley }
29383c47955SMatthew G. Knepley 
29483c47955SMatthew G. Knepley static PetscErrorCode DMCreateMassMatrix_Swarm(DM dmCoarse, DM dmFine, Mat *mass)
29583c47955SMatthew G. Knepley {
296*895a1698SMatthew G. Knepley   PetscSection   gsf;
29783c47955SMatthew G. Knepley   PetscInt       m, n;
29883c47955SMatthew G. Knepley   void          *ctx;
29983c47955SMatthew G. Knepley   PetscErrorCode ierr;
30083c47955SMatthew G. Knepley 
30183c47955SMatthew G. Knepley   PetscFunctionBegin;
30283c47955SMatthew G. Knepley   ierr = DMGetDefaultGlobalSection(dmFine, &gsf);CHKERRQ(ierr);
30383c47955SMatthew G. Knepley   ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr);
304*895a1698SMatthew G. Knepley   ierr = DMSwarmGetLocalSize(dmCoarse, &n);CHKERRQ(ierr);
30583c47955SMatthew G. Knepley 
30683c47955SMatthew G. Knepley   ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr);
30783c47955SMatthew G. Knepley   ierr = MatSetSizes(*mass, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
30883c47955SMatthew G. Knepley   ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr);
30983c47955SMatthew G. Knepley   ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr);
31083c47955SMatthew G. Knepley 
31183c47955SMatthew G. Knepley   ierr = DMSwarmComputeMassMatrix_Private(dmCoarse, dmFine, *mass, ctx);CHKERRQ(ierr);
31283c47955SMatthew G. Knepley   ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr);
31383c47955SMatthew G. Knepley   PetscFunctionReturn(0);
31483c47955SMatthew G. Knepley }
31583c47955SMatthew G. Knepley 
316fb1bcc12SMatthew G. Knepley /*@C
317d3a51819SDave May    DMSwarmCreateGlobalVectorFromField - Creates a Vec object sharing the array associated with a given field
318d3a51819SDave May 
319d3a51819SDave May    Collective on DM
320d3a51819SDave May 
321d3a51819SDave May    Input parameters:
32262741f57SDave May +  dm - a DMSwarm
32362741f57SDave May -  fieldname - the textual name given to a registered field
324d3a51819SDave May 
3258b8a3813SDave May    Output parameter:
326d3a51819SDave May .  vec - the vector
327d3a51819SDave May 
328d3a51819SDave May    Level: beginner
329d3a51819SDave May 
3308b8a3813SDave May    Notes:
3318b8a3813SDave May    The vector must be returned using a matching call to DMSwarmDestroyGlobalVectorFromField().
3328b8a3813SDave May 
3338b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmDestroyGlobalVectorFromField()
334d3a51819SDave May @*/
335b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmCreateGlobalVectorFromField(DM dm,const char fieldname[],Vec *vec)
336b5bcf523SDave May {
337fb1bcc12SMatthew G. Knepley   MPI_Comm       comm = PetscObjectComm((PetscObject) dm);
338b5bcf523SDave May   PetscErrorCode ierr;
339b5bcf523SDave May 
340fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
341fb1bcc12SMatthew G. Knepley   ierr = DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec);CHKERRQ(ierr);
342b5bcf523SDave May   PetscFunctionReturn(0);
343b5bcf523SDave May }
344b5bcf523SDave May 
345d3a51819SDave May /*@C
346d3a51819SDave May    DMSwarmDestroyGlobalVectorFromField - Destroys the Vec object which share the array associated with a given field
347d3a51819SDave May 
348d3a51819SDave May    Collective on DM
349d3a51819SDave May 
350d3a51819SDave May    Input parameters:
35162741f57SDave May +  dm - a DMSwarm
35262741f57SDave May -  fieldname - the textual name given to a registered field
353d3a51819SDave May 
3548b8a3813SDave May    Output parameter:
355d3a51819SDave May .  vec - the vector
356d3a51819SDave May 
357d3a51819SDave May    Level: beginner
358d3a51819SDave May 
3598b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmCreateGlobalVectorFromField()
360d3a51819SDave May @*/
361b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmDestroyGlobalVectorFromField(DM dm,const char fieldname[],Vec *vec)
362b5bcf523SDave May {
363b5bcf523SDave May   PetscErrorCode ierr;
364cc651181SDave May 
365fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
366fb1bcc12SMatthew G. Knepley   ierr = DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec);CHKERRQ(ierr);
367b5bcf523SDave May   PetscFunctionReturn(0);
368b5bcf523SDave May }
369b5bcf523SDave May 
370fb1bcc12SMatthew G. Knepley /*@C
371fb1bcc12SMatthew G. Knepley    DMSwarmCreateLocalVectorFromField - Creates a Vec object sharing the array associated with a given field
372fb1bcc12SMatthew G. Knepley 
373fb1bcc12SMatthew G. Knepley    Collective on DM
374fb1bcc12SMatthew G. Knepley 
375fb1bcc12SMatthew G. Knepley    Input parameters:
37662741f57SDave May +  dm - a DMSwarm
37762741f57SDave May -  fieldname - the textual name given to a registered field
378fb1bcc12SMatthew G. Knepley 
3798b8a3813SDave May    Output parameter:
380fb1bcc12SMatthew G. Knepley .  vec - the vector
381fb1bcc12SMatthew G. Knepley 
382fb1bcc12SMatthew G. Knepley    Level: beginner
383fb1bcc12SMatthew G. Knepley 
3848b8a3813SDave May    Notes:
3858b8a3813SDave May    The vector must be returned using a matching call to DMSwarmDestroyLocalVectorFromField().
3868b8a3813SDave May 
3878b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmDestroyLocalVectorFromField()
388fb1bcc12SMatthew G. Knepley @*/
389fb1bcc12SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMSwarmCreateLocalVectorFromField(DM dm,const char fieldname[],Vec *vec)
390bbe8250bSMatthew G. Knepley {
391fb1bcc12SMatthew G. Knepley   MPI_Comm       comm = PETSC_COMM_SELF;
392bbe8250bSMatthew G. Knepley   PetscErrorCode ierr;
393bbe8250bSMatthew G. Knepley 
394fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
395fb1bcc12SMatthew G. Knepley   ierr = DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec);CHKERRQ(ierr);
396fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
397bbe8250bSMatthew G. Knepley }
398fb1bcc12SMatthew G. Knepley 
399fb1bcc12SMatthew G. Knepley /*@C
400fb1bcc12SMatthew G. Knepley    DMSwarmDestroyLocalVectorFromField - Destroys the Vec object which share the array associated with a given field
401fb1bcc12SMatthew G. Knepley 
402fb1bcc12SMatthew G. Knepley    Collective on DM
403fb1bcc12SMatthew G. Knepley 
404fb1bcc12SMatthew G. Knepley    Input parameters:
40562741f57SDave May +  dm - a DMSwarm
40662741f57SDave May -  fieldname - the textual name given to a registered field
407fb1bcc12SMatthew G. Knepley 
4088b8a3813SDave May    Output parameter:
409fb1bcc12SMatthew G. Knepley .  vec - the vector
410fb1bcc12SMatthew G. Knepley 
411fb1bcc12SMatthew G. Knepley    Level: beginner
412fb1bcc12SMatthew G. Knepley 
4138b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmCreateLocalVectorFromField()
414fb1bcc12SMatthew G. Knepley @*/
415fb1bcc12SMatthew G. Knepley PETSC_EXTERN PetscErrorCode DMSwarmDestroyLocalVectorFromField(DM dm,const char fieldname[],Vec *vec)
416fb1bcc12SMatthew G. Knepley {
417fb1bcc12SMatthew G. Knepley   PetscErrorCode ierr;
418fb1bcc12SMatthew G. Knepley 
419fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
420fb1bcc12SMatthew G. Knepley   ierr = DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec);CHKERRQ(ierr);
421bbe8250bSMatthew G. Knepley   PetscFunctionReturn(0);
422bbe8250bSMatthew G. Knepley }
423bbe8250bSMatthew G. Knepley 
424b5bcf523SDave May /*
425b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmCreateGlobalVectorFromFields(DM dm,const PetscInt nf,const char *fieldnames[],Vec *vec)
426b5bcf523SDave May {
427b5bcf523SDave May   PetscFunctionReturn(0);
428b5bcf523SDave May }
429b5bcf523SDave May 
430b5bcf523SDave May PETSC_EXTERN PetscErrorCode DMSwarmRestoreGlobalVectorFromFields(DM dm,Vec *vec)
431b5bcf523SDave May {
432b5bcf523SDave May   PetscFunctionReturn(0);
433b5bcf523SDave May }
434b5bcf523SDave May */
435b5bcf523SDave May 
436d3a51819SDave May /*@C
437d3a51819SDave May    DMSwarmInitializeFieldRegister - Initiates the registration of fields to a DMSwarm
438d3a51819SDave May 
439d3a51819SDave May    Collective on DM
440d3a51819SDave May 
441d3a51819SDave May    Input parameter:
442d3a51819SDave May .  dm - a DMSwarm
443d3a51819SDave May 
444d3a51819SDave May    Level: beginner
445d3a51819SDave May 
446d3a51819SDave May    Notes:
4478b8a3813SDave May    After all fields have been registered, you must call DMSwarmFinalizeFieldRegister().
448d3a51819SDave May 
449d3a51819SDave May .seealso: DMSwarmFinalizeFieldRegister(), DMSwarmRegisterPetscDatatypeField(),
450d3a51819SDave May  DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
451d3a51819SDave May @*/
4525f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmInitializeFieldRegister(DM dm)
4535f50eb2eSDave May {
4545f50eb2eSDave May   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
4553454631fSDave May   PetscErrorCode ierr;
4563454631fSDave May 
457521f74f9SMatthew G. Knepley   PetscFunctionBegin;
458cc651181SDave May   if (!swarm->field_registration_initialized) {
4595f50eb2eSDave May     swarm->field_registration_initialized = PETSC_TRUE;
460f0cdbbbaSDave May     ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_pid,1,PETSC_LONG);CHKERRQ(ierr); /* unique identifer */
461f0cdbbbaSDave May     ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_rank,1,PETSC_INT);CHKERRQ(ierr); /* used for communication */
462cc651181SDave May   }
4635f50eb2eSDave May   PetscFunctionReturn(0);
4645f50eb2eSDave May }
4655f50eb2eSDave May 
466d3a51819SDave May /*@C
467d3a51819SDave May    DMSwarmFinalizeFieldRegister - Finalizes the registration of fields to a DMSwarm
468d3a51819SDave May 
469d3a51819SDave May    Collective on DM
470d3a51819SDave May 
471d3a51819SDave May    Input parameter:
472d3a51819SDave May .  dm - a DMSwarm
473d3a51819SDave May 
474d3a51819SDave May    Level: beginner
475d3a51819SDave May 
476d3a51819SDave May    Notes:
47762741f57SDave May    After DMSwarmFinalizeFieldRegister() has been called, no new fields can be defined on the DMSwarm.
478d3a51819SDave May 
479d3a51819SDave May .seealso: DMSwarmInitializeFieldRegister(), DMSwarmRegisterPetscDatatypeField(),
480d3a51819SDave May  DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
481d3a51819SDave May @*/
4825f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmFinalizeFieldRegister(DM dm)
4835f50eb2eSDave May {
4845f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
4856845f8f5SDave May   PetscErrorCode ierr;
4866845f8f5SDave May 
487521f74f9SMatthew G. Knepley   PetscFunctionBegin;
488f0cdbbbaSDave May   if (!swarm->field_registration_finalized) {
4896845f8f5SDave May     ierr = DataBucketFinalize(swarm->db);CHKERRQ(ierr);
490f0cdbbbaSDave May   }
491f0cdbbbaSDave May   swarm->field_registration_finalized = PETSC_TRUE;
4925f50eb2eSDave May   PetscFunctionReturn(0);
4935f50eb2eSDave May }
4945f50eb2eSDave May 
495d3a51819SDave May /*@C
496d3a51819SDave May    DMSwarmSetLocalSizes - Sets the length of all registered fields on the DMSwarm
497d3a51819SDave May 
498d3a51819SDave May    Not collective
499d3a51819SDave May 
500d3a51819SDave May    Input parameters:
50162741f57SDave May +  dm - a DMSwarm
502d3a51819SDave May .  nlocal - the length of each registered field
50362741f57SDave May -  buffer - the length of the buffer used to efficient dynamic re-sizing
504d3a51819SDave May 
505d3a51819SDave May    Level: beginner
506d3a51819SDave May 
507d3a51819SDave May .seealso: DMSwarmGetLocalSize()
508d3a51819SDave May @*/
5095f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmSetLocalSizes(DM dm,PetscInt nlocal,PetscInt buffer)
5105f50eb2eSDave May {
5115f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
5126845f8f5SDave May   PetscErrorCode ierr;
5135f50eb2eSDave May 
514521f74f9SMatthew G. Knepley   PetscFunctionBegin;
515f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_SetSizes,0,0,0,0);CHKERRQ(ierr);
5166845f8f5SDave May   ierr = DataBucketSetSizes(swarm->db,nlocal,buffer);CHKERRQ(ierr);
517f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_SetSizes,0,0,0,0);CHKERRQ(ierr);
5185f50eb2eSDave May   PetscFunctionReturn(0);
5195f50eb2eSDave May }
5205f50eb2eSDave May 
521d3a51819SDave May /*@C
522d3a51819SDave May    DMSwarmSetCellDM - Attachs a DM to a DMSwarm
523d3a51819SDave May 
524d3a51819SDave May    Collective on DM
525d3a51819SDave May 
526d3a51819SDave May    Input parameters:
52762741f57SDave May +  dm - a DMSwarm
52862741f57SDave May -  dmcell - the DM to attach to the DMSwarm
529d3a51819SDave May 
530d3a51819SDave May    Level: beginner
531d3a51819SDave May 
532d3a51819SDave May    Notes:
533d3a51819SDave May    The attached DM (dmcell) will be queried for point location and
5348b8a3813SDave May    neighbor MPI-rank information if DMSwarmMigrate() is called.
535d3a51819SDave May 
5368b8a3813SDave May .seealso: DMSwarmSetType(), DMSwarmGetCellDM(), DMSwarmMigrate()
537d3a51819SDave May @*/
538b16650c8SDave May PETSC_EXTERN PetscErrorCode DMSwarmSetCellDM(DM dm,DM dmcell)
539b16650c8SDave May {
540b16650c8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
541521f74f9SMatthew G. Knepley 
542521f74f9SMatthew G. Knepley   PetscFunctionBegin;
543b16650c8SDave May   swarm->dmcell = dmcell;
544b16650c8SDave May   PetscFunctionReturn(0);
545b16650c8SDave May }
546b16650c8SDave May 
547d3a51819SDave May /*@C
548d3a51819SDave May    DMSwarmGetCellDM - Fetches the attached cell DM
549d3a51819SDave May 
550d3a51819SDave May    Collective on DM
551d3a51819SDave May 
552d3a51819SDave May    Input parameter:
553d3a51819SDave May .  dm - a DMSwarm
554d3a51819SDave May 
555d3a51819SDave May    Output parameter:
556d3a51819SDave May .  dmcell - the DM which was attached to the DMSwarm
557d3a51819SDave May 
558d3a51819SDave May    Level: beginner
559d3a51819SDave May 
560d3a51819SDave May .seealso: DMSwarmSetCellDM()
561d3a51819SDave May @*/
562fe39f135SDave May PETSC_EXTERN PetscErrorCode DMSwarmGetCellDM(DM dm,DM *dmcell)
563fe39f135SDave May {
564fe39f135SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
565521f74f9SMatthew G. Knepley 
566521f74f9SMatthew G. Knepley   PetscFunctionBegin;
567fe39f135SDave May   *dmcell = swarm->dmcell;
568fe39f135SDave May   PetscFunctionReturn(0);
569fe39f135SDave May }
570fe39f135SDave May 
571d3a51819SDave May /*@C
572d3a51819SDave May    DMSwarmGetLocalSize - Retrives the local length of fields registered
573d3a51819SDave May 
574d3a51819SDave May    Not collective
575d3a51819SDave May 
576d3a51819SDave May    Input parameter:
577d3a51819SDave May .  dm - a DMSwarm
578d3a51819SDave May 
579d3a51819SDave May    Output parameter:
580d3a51819SDave May .  nlocal - the length of each registered field
581d3a51819SDave May 
582d3a51819SDave May    Level: beginner
583d3a51819SDave May 
5848b8a3813SDave May .seealso: DMSwarmGetSize(), DMSwarmSetLocalSizes()
585d3a51819SDave May @*/
586dcf43ee8SDave May PETSC_EXTERN PetscErrorCode DMSwarmGetLocalSize(DM dm,PetscInt *nlocal)
587dcf43ee8SDave May {
588dcf43ee8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
589dcf43ee8SDave May   PetscErrorCode ierr;
590dcf43ee8SDave May 
591521f74f9SMatthew G. Knepley   PetscFunctionBegin;
592521f74f9SMatthew G. Knepley   if (nlocal) {ierr = DataBucketGetSizes(swarm->db,nlocal,NULL,NULL);CHKERRQ(ierr);}
593dcf43ee8SDave May   PetscFunctionReturn(0);
594dcf43ee8SDave May }
595dcf43ee8SDave May 
596d3a51819SDave May /*@C
597d3a51819SDave May    DMSwarmGetSize - Retrives the total length of fields registered
598d3a51819SDave May 
599d3a51819SDave May    Collective on DM
600d3a51819SDave May 
601d3a51819SDave May    Input parameter:
602d3a51819SDave May .  dm - a DMSwarm
603d3a51819SDave May 
604d3a51819SDave May    Output parameter:
605d3a51819SDave May .  n - the total length of each registered field
606d3a51819SDave May 
607d3a51819SDave May    Level: beginner
608d3a51819SDave May 
609d3a51819SDave May    Note:
610d3a51819SDave May    This calls MPI_Allreduce upon each call (inefficient but safe)
611d3a51819SDave May 
6128b8a3813SDave May .seealso: DMSwarmGetLocalSize(), DMSwarmSetLocalSizes()
613d3a51819SDave May @*/
614dcf43ee8SDave May PETSC_EXTERN PetscErrorCode DMSwarmGetSize(DM dm,PetscInt *n)
615dcf43ee8SDave May {
616dcf43ee8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
617dcf43ee8SDave May   PetscErrorCode ierr;
618dcf43ee8SDave May   PetscInt nlocal,ng;
619dcf43ee8SDave May 
620521f74f9SMatthew G. Knepley   PetscFunctionBegin;
621dcf43ee8SDave May   ierr = DataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
622dcf43ee8SDave May   ierr = MPI_Allreduce(&nlocal,&ng,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
623dcf43ee8SDave May   if (n) { *n = ng; }
624dcf43ee8SDave May   PetscFunctionReturn(0);
625dcf43ee8SDave May }
626dcf43ee8SDave May 
627d3a51819SDave May /*@C
6288b8a3813SDave May    DMSwarmRegisterPetscDatatypeField - Register a field to a DMSwarm with a native PETSc data type
629d3a51819SDave May 
630d3a51819SDave May    Collective on DM
631d3a51819SDave May 
632d3a51819SDave May    Input parameters:
63362741f57SDave May +  dm - a DMSwarm
634d3a51819SDave May .  fieldname - the textual name to identify this field
635d3a51819SDave May .  blocksize - the number of each data type
63662741f57SDave May -  type - a valid PETSc data type (PETSC_CHAR, PETSC_SHORT, PETSC_INT, PETSC_FLOAT, PETSC_REAL, PETSC_LONG)
637d3a51819SDave May 
638d3a51819SDave May    Level: beginner
639d3a51819SDave May 
640d3a51819SDave May    Notes:
6418b8a3813SDave May    The textual name for each registered field must be unique.
642d3a51819SDave May 
643d3a51819SDave May .seealso: DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
644d3a51819SDave May @*/
6455f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmRegisterPetscDatatypeField(DM dm,const char fieldname[],PetscInt blocksize,PetscDataType type)
646b62e03f8SDave May {
6472eac95f8SDave May   PetscErrorCode ierr;
648b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
649b62e03f8SDave May   size_t size;
650b62e03f8SDave May 
651521f74f9SMatthew G. Knepley   PetscFunctionBegin;
6525f50eb2eSDave May   if (!swarm->field_registration_initialized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmInitializeFieldRegister() first");
6535f50eb2eSDave May   if (swarm->field_registration_finalized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Cannot register additional fields after calling DMSwarmFinalizeFieldRegister() first");
6545f50eb2eSDave May 
6555f50eb2eSDave May   if (type == PETSC_OBJECT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
6565f50eb2eSDave May   if (type == PETSC_FUNCTION) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
6575f50eb2eSDave May   if (type == PETSC_STRING) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
6585f50eb2eSDave May   if (type == PETSC_STRUCT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
6595f50eb2eSDave May   if (type == PETSC_DATATYPE_UNKNOWN) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
660b62e03f8SDave May 
6612ddcf43eSMatthew G. Knepley   ierr = PetscDataTypeGetSize(type, &size);CHKERRQ(ierr);
662b62e03f8SDave May   /* Load a specific data type into data bucket, specifying textual name and its size in bytes */
66352c3ed93SDave May   ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterPetscDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
66452c3ed93SDave May   {
66552c3ed93SDave May     DataField gfield;
66652c3ed93SDave May 
66752c3ed93SDave May     ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
66852c3ed93SDave May     ierr = DataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
66952c3ed93SDave May   }
670b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = type;
671b62e03f8SDave May   PetscFunctionReturn(0);
672b62e03f8SDave May }
673b62e03f8SDave May 
674d3a51819SDave May /*@C
675d3a51819SDave May    DMSwarmRegisterUserStructField - Register a user defined struct to a DMSwarm
676d3a51819SDave May 
677d3a51819SDave May    Collective on DM
678d3a51819SDave May 
679d3a51819SDave May    Input parameters:
68062741f57SDave May +  dm - a DMSwarm
681d3a51819SDave May .  fieldname - the textual name to identify this field
68262741f57SDave May -  size - the size in bytes of the user struct of each data type
683d3a51819SDave May 
684d3a51819SDave May    Level: beginner
685d3a51819SDave May 
686d3a51819SDave May    Notes:
6878b8a3813SDave May    The textual name for each registered field must be unique.
688d3a51819SDave May 
689d3a51819SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserDatatypeField()
690d3a51819SDave May @*/
6915f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmRegisterUserStructField(DM dm,const char fieldname[],size_t size)
692b62e03f8SDave May {
6932eac95f8SDave May   PetscErrorCode ierr;
694b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
695b62e03f8SDave May 
696521f74f9SMatthew G. Knepley   PetscFunctionBegin;
6972eac95f8SDave May   ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterUserStructField",fieldname,size,NULL);CHKERRQ(ierr);
698b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_STRUCT ;
699b62e03f8SDave May   PetscFunctionReturn(0);
700b62e03f8SDave May }
701b62e03f8SDave May 
702d3a51819SDave May /*@C
703d3a51819SDave May    DMSwarmRegisterUserDatatypeField - Register a user defined data type to a DMSwarm
704d3a51819SDave May 
705d3a51819SDave May    Collective on DM
706d3a51819SDave May 
707d3a51819SDave May    Input parameters:
70862741f57SDave May +  dm - a DMSwarm
709d3a51819SDave May .  fieldname - the textual name to identify this field
710d3a51819SDave May .  size - the size in bytes of the user data type
71162741f57SDave May -  blocksize - the number of each data type
712d3a51819SDave May 
713d3a51819SDave May    Level: beginner
714d3a51819SDave May 
715d3a51819SDave May    Notes:
7168b8a3813SDave May    The textual name for each registered field must be unique.
717d3a51819SDave May 
718d3a51819SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
719d3a51819SDave May @*/
720320740a0SDave May PETSC_EXTERN PetscErrorCode DMSwarmRegisterUserDatatypeField(DM dm,const char fieldname[],size_t size,PetscInt blocksize)
721b62e03f8SDave May {
722b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
7236845f8f5SDave May   PetscErrorCode ierr;
724b62e03f8SDave May 
725521f74f9SMatthew G. Knepley   PetscFunctionBegin;
726320740a0SDave May   ierr = DataBucketRegisterField(swarm->db,"DMSwarmRegisterUserDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
727320740a0SDave May   {
728320740a0SDave May     DataField gfield;
729320740a0SDave May 
730320740a0SDave May     ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
731320740a0SDave May     ierr = DataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
732320740a0SDave May   }
733b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_DATATYPE_UNKNOWN;
734b62e03f8SDave May   PetscFunctionReturn(0);
735b62e03f8SDave May }
736b62e03f8SDave May 
737d3a51819SDave May /*@C
738d3a51819SDave May    DMSwarmGetField - Get access to the underlying array storing all entries associated with a registered field
739d3a51819SDave May 
740d3a51819SDave May    Not collective
741d3a51819SDave May 
742d3a51819SDave May    Input parameters:
74362741f57SDave May +  dm - a DMSwarm
74462741f57SDave May -  fieldname - the textual name to identify this field
745d3a51819SDave May 
746d3a51819SDave May    Output parameters:
74762741f57SDave May +  blocksize - the number of each data type
748d3a51819SDave May .  type - the data type
74962741f57SDave May -  data - pointer to raw array
750d3a51819SDave May 
751d3a51819SDave May    Level: beginner
752d3a51819SDave May 
753d3a51819SDave May    Notes:
7548b8a3813SDave May    The array must be returned using a matching call to DMSwarmRestoreField().
755d3a51819SDave May 
756d3a51819SDave May .seealso: DMSwarmRestoreField()
757d3a51819SDave May @*/
7585f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmGetField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
759b62e03f8SDave May {
760b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
761b62e03f8SDave May   DataField gfield;
7622eac95f8SDave May   PetscErrorCode ierr;
763b62e03f8SDave May 
764521f74f9SMatthew G. Knepley   PetscFunctionBegin;
7653454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
7662eac95f8SDave May   ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
7676845f8f5SDave May   ierr = DataFieldGetAccess(gfield);CHKERRQ(ierr);
7686845f8f5SDave May   ierr = DataFieldGetEntries(gfield,data);CHKERRQ(ierr);
7691b1ea282SDave May   if (blocksize) {*blocksize = gfield->bs; }
770b5bcf523SDave May   if (type) { *type = gfield->petsc_type; }
771b62e03f8SDave May   PetscFunctionReturn(0);
772b62e03f8SDave May }
773b62e03f8SDave May 
774d3a51819SDave May /*@C
775d3a51819SDave May    DMSwarmRestoreField - Restore access to the underlying array storing all entries associated with a registered field
776d3a51819SDave May 
777d3a51819SDave May    Not collective
778d3a51819SDave May 
779d3a51819SDave May    Input parameters:
78062741f57SDave May +  dm - a DMSwarm
78162741f57SDave May -  fieldname - the textual name to identify this field
782d3a51819SDave May 
783d3a51819SDave May    Output parameters:
78462741f57SDave May +  blocksize - the number of each data type
785d3a51819SDave May .  type - the data type
78662741f57SDave May -  data - pointer to raw array
787d3a51819SDave May 
788d3a51819SDave May    Level: beginner
789d3a51819SDave May 
790d3a51819SDave May    Notes:
7918b8a3813SDave May    The user must call DMSwarmGetField() prior to calling DMSwarmRestoreField().
792d3a51819SDave May 
793d3a51819SDave May .seealso: DMSwarmGetField()
794d3a51819SDave May @*/
7955f50eb2eSDave May PETSC_EXTERN PetscErrorCode DMSwarmRestoreField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
796b62e03f8SDave May {
797b62e03f8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
798b62e03f8SDave May   DataField gfield;
7992eac95f8SDave May   PetscErrorCode ierr;
800b62e03f8SDave May 
801521f74f9SMatthew G. Knepley   PetscFunctionBegin;
8022eac95f8SDave May   ierr = DataBucketGetDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
8036845f8f5SDave May   ierr = DataFieldRestoreAccess(gfield);CHKERRQ(ierr);
804b62e03f8SDave May   if (data) *data = NULL;
805b62e03f8SDave May   PetscFunctionReturn(0);
806b62e03f8SDave May }
807b62e03f8SDave May 
808d3a51819SDave May /*@C
809d3a51819SDave May    DMSwarmAddPoint - Add space for one new point in the DMSwarm
810d3a51819SDave May 
811d3a51819SDave May    Not collective
812d3a51819SDave May 
813d3a51819SDave May    Input parameter:
814d3a51819SDave May .  dm - a DMSwarm
815d3a51819SDave May 
816d3a51819SDave May    Level: beginner
817d3a51819SDave May 
818d3a51819SDave May    Notes:
8198b8a3813SDave May    The new point will have all fields initialized to zero.
820d3a51819SDave May 
821d3a51819SDave May .seealso: DMSwarmAddNPoints()
822d3a51819SDave May @*/
823cb1d1399SDave May PETSC_EXTERN PetscErrorCode DMSwarmAddPoint(DM dm)
824cb1d1399SDave May {
825cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
826cb1d1399SDave May   PetscErrorCode ierr;
827cb1d1399SDave May 
828521f74f9SMatthew G. Knepley   PetscFunctionBegin;
8293454631fSDave May   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
830f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
831cb1d1399SDave May   ierr = DataBucketAddPoint(swarm->db);CHKERRQ(ierr);
832f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
833cb1d1399SDave May   PetscFunctionReturn(0);
834cb1d1399SDave May }
835cb1d1399SDave May 
836d3a51819SDave May /*@C
837d3a51819SDave May    DMSwarmAddNPoints - Add space for a number of new points in the DMSwarm
838d3a51819SDave May 
839d3a51819SDave May    Not collective
840d3a51819SDave May 
841d3a51819SDave May    Input parameters:
84262741f57SDave May +  dm - a DMSwarm
84362741f57SDave May -  npoints - the number of new points to add
844d3a51819SDave May 
845d3a51819SDave May    Level: beginner
846d3a51819SDave May 
847d3a51819SDave May    Notes:
8488b8a3813SDave May    The new point will have all fields initialized to zero.
849d3a51819SDave May 
850d3a51819SDave May .seealso: DMSwarmAddPoint()
851d3a51819SDave May @*/
852cb1d1399SDave May PETSC_EXTERN PetscErrorCode DMSwarmAddNPoints(DM dm,PetscInt npoints)
853cb1d1399SDave May {
854cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
855cb1d1399SDave May   PetscErrorCode ierr;
856cb1d1399SDave May   PetscInt nlocal;
857cb1d1399SDave May 
858521f74f9SMatthew G. Knepley   PetscFunctionBegin;
859f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
860cb1d1399SDave May   ierr = DataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
861cb1d1399SDave May   nlocal = nlocal + npoints;
86265141ba8SDave May   ierr = DataBucketSetSizes(swarm->db,nlocal,DATA_BUCKET_BUFFER_DEFAULT);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    DMSwarmRemovePoint - Remove the last point from the DMSwarm
869d3a51819SDave May 
870d3a51819SDave May    Not collective
871d3a51819SDave May 
872d3a51819SDave May    Input parameter:
873d3a51819SDave May .  dm - a DMSwarm
874d3a51819SDave May 
875d3a51819SDave May    Level: beginner
876d3a51819SDave May 
877d3a51819SDave May .seealso: DMSwarmRemovePointAtIndex()
878d3a51819SDave May @*/
879cb1d1399SDave May PETSC_EXTERN PetscErrorCode DMSwarmRemovePoint(DM dm)
880cb1d1399SDave May {
881cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
882cb1d1399SDave May   PetscErrorCode ierr;
883cb1d1399SDave May 
884521f74f9SMatthew G. Knepley   PetscFunctionBegin;
885f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
886cb1d1399SDave May   ierr = DataBucketRemovePoint(swarm->db);CHKERRQ(ierr);
887f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
888cb1d1399SDave May   PetscFunctionReturn(0);
889cb1d1399SDave May }
890cb1d1399SDave May 
891d3a51819SDave May /*@C
892d3a51819SDave May    DMSwarmRemovePointAtIndex - Removes a specific point from the DMSwarm
893d3a51819SDave May 
894d3a51819SDave May    Not collective
895d3a51819SDave May 
896d3a51819SDave May    Input parameters:
89762741f57SDave May +  dm - a DMSwarm
89862741f57SDave May -  idx - index of point to remove
899d3a51819SDave May 
900d3a51819SDave May    Level: beginner
901d3a51819SDave May 
902d3a51819SDave May .seealso: DMSwarmRemovePoint()
903d3a51819SDave May @*/
904cb1d1399SDave May PETSC_EXTERN PetscErrorCode DMSwarmRemovePointAtIndex(DM dm,PetscInt idx)
905cb1d1399SDave May {
906cb1d1399SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
907cb1d1399SDave May   PetscErrorCode ierr;
908cb1d1399SDave May 
909521f74f9SMatthew G. Knepley   PetscFunctionBegin;
910f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
911cb1d1399SDave May   ierr = DataBucketRemovePointAtIndex(swarm->db,idx);CHKERRQ(ierr);
912f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
913cb1d1399SDave May   PetscFunctionReturn(0);
914cb1d1399SDave May }
915b62e03f8SDave May 
916ba4fc9c6SDave May /*@C
917ba4fc9c6SDave May    DMSwarmCopyPoint - Copy point pj to point pi in the DMSwarm
918ba4fc9c6SDave May 
919ba4fc9c6SDave May    Not collective
920ba4fc9c6SDave May 
921ba4fc9c6SDave May    Input parameters:
922ba4fc9c6SDave May +  dm - a DMSwarm
923ba4fc9c6SDave May .  pi - the index of the point to copy
924ba4fc9c6SDave May -  pj - the point index where the copy should be located
925ba4fc9c6SDave May 
926ba4fc9c6SDave May  Level: beginner
927ba4fc9c6SDave May 
928ba4fc9c6SDave May .seealso: DMSwarmRemovePoint()
929ba4fc9c6SDave May @*/
930ba4fc9c6SDave May PETSC_EXTERN PetscErrorCode DMSwarmCopyPoint(DM dm,PetscInt pi,PetscInt pj)
931ba4fc9c6SDave May {
932ba4fc9c6SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
933ba4fc9c6SDave May   PetscErrorCode ierr;
934ba4fc9c6SDave May 
935ba4fc9c6SDave May   PetscFunctionBegin;
936ba4fc9c6SDave May   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
937ba4fc9c6SDave May   ierr = DataBucketCopyPoint(swarm->db,pi,swarm->db,pj);CHKERRQ(ierr);
938ba4fc9c6SDave May   PetscFunctionReturn(0);
939ba4fc9c6SDave May }
940ba4fc9c6SDave May 
941095059a4SDave May PetscErrorCode DMSwarmMigrate_Basic(DM dm,PetscBool remove_sent_points)
9423454631fSDave May {
943dcf43ee8SDave May   PetscErrorCode ierr;
944521f74f9SMatthew G. Knepley 
945521f74f9SMatthew G. Knepley   PetscFunctionBegin;
946dcf43ee8SDave May   ierr = DMSwarmMigrate_Push_Basic(dm,remove_sent_points);CHKERRQ(ierr);
9473454631fSDave May   PetscFunctionReturn(0);
9483454631fSDave May }
9493454631fSDave May 
950d3a51819SDave May /*@C
951d3a51819SDave May    DMSwarmMigrate - Relocates points defined in the DMSwarm to other MPI-ranks
952d3a51819SDave May 
953d3a51819SDave May    Collective on DM
954d3a51819SDave May 
955d3a51819SDave May    Input parameters:
95662741f57SDave May +  dm - the DMSwarm
95762741f57SDave May -  remove_sent_points - flag indicating if sent points should be removed from the current MPI-rank
958d3a51819SDave May 
959d3a51819SDave May    Notes:
9608b8a3813SDave May    The DM will be modified to accomodate received points.
9618b8a3813SDave May    If remove_sent_points = PETSC_TRUE, any points that were sent will be removed from the DM.
9628b8a3813SDave May    Different styles of migration are supported. See DMSwarmSetMigrateType().
963d3a51819SDave May 
964d3a51819SDave May    Level: advanced
965d3a51819SDave May 
966d3a51819SDave May .seealso: DMSwarmSetMigrateType()
967d3a51819SDave May @*/
968095059a4SDave May PETSC_EXTERN PetscErrorCode DMSwarmMigrate(DM dm,PetscBool remove_sent_points)
9693454631fSDave May {
970f0cdbbbaSDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
9713454631fSDave May   PetscErrorCode ierr;
972f0cdbbbaSDave May 
973521f74f9SMatthew G. Knepley   PetscFunctionBegin;
974ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
975f0cdbbbaSDave May   switch (swarm->migrate_type) {
976f0cdbbbaSDave May     case DMSWARM_MIGRATE_BASIC:
977095059a4SDave May       ierr = DMSwarmMigrate_Basic(dm,remove_sent_points);CHKERRQ(ierr);
978f0cdbbbaSDave May       break;
979f0cdbbbaSDave May     case DMSWARM_MIGRATE_DMCELLNSCATTER:
980f0cdbbbaSDave May       ierr = DMSwarmMigrate_CellDMScatter(dm,remove_sent_points);CHKERRQ(ierr);
981f0cdbbbaSDave May       break;
982f0cdbbbaSDave May     case DMSWARM_MIGRATE_DMCELLEXACT:
983f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_DMCELLEXACT not implemented");
984521f74f9SMatthew G. Knepley       /*ierr = DMSwarmMigrate_CellDMExact(dm,remove_sent_points);CHKERRQ(ierr);*/
985f0cdbbbaSDave May       break;
986f0cdbbbaSDave May     case DMSWARM_MIGRATE_USER:
987f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_USER not implemented");
988521f74f9SMatthew G. Knepley       /*ierr = swarm->migrate(dm,remove_sent_points);CHKERRQ(ierr);*/
989f0cdbbbaSDave May       break;
990f0cdbbbaSDave May     default:
991f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE type unknown");
992f0cdbbbaSDave May       break;
993f0cdbbbaSDave May   }
994ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
9953454631fSDave May   PetscFunctionReturn(0);
9963454631fSDave May }
9973454631fSDave May 
998f0cdbbbaSDave May PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm,PetscInt *globalsize);
999f0cdbbbaSDave May 
1000d3a51819SDave May /*
1001d3a51819SDave May  DMSwarmCollectViewCreate
1002d3a51819SDave May 
1003d3a51819SDave May  * Applies a collection method and gathers point neighbour points into dm
1004d3a51819SDave May 
1005d3a51819SDave May  Notes:
10068b8a3813SDave May  Users should call DMSwarmCollectViewDestroy() after
1007d3a51819SDave May  they have finished computations associated with the collected points
1008d3a51819SDave May */
1009d3a51819SDave May 
1010d3a51819SDave May /*@C
1011d3a51819SDave May    DMSwarmCollectViewCreate - Applies a collection method and gathers points
1012d3a51819SDave May    in neighbour MPI-ranks into the DMSwarm
1013d3a51819SDave May 
1014d3a51819SDave May    Collective on DM
1015d3a51819SDave May 
1016d3a51819SDave May    Input parameter:
1017d3a51819SDave May .  dm - the DMSwarm
1018d3a51819SDave May 
1019d3a51819SDave May    Notes:
1020d3a51819SDave May    Users should call DMSwarmCollectViewDestroy() after
1021d3a51819SDave May    they have finished computations associated with the collected points
10228b8a3813SDave May    Different collect methods are supported. See DMSwarmSetCollectType().
1023d3a51819SDave May 
1024d3a51819SDave May    Level: advanced
1025d3a51819SDave May 
1026d3a51819SDave May .seealso: DMSwarmCollectViewDestroy(), DMSwarmSetCollectType()
1027d3a51819SDave May @*/
1028fe39f135SDave May PETSC_EXTERN PetscErrorCode DMSwarmCollectViewCreate(DM dm)
10292712d1f2SDave May {
10302712d1f2SDave May   PetscErrorCode ierr;
10312712d1f2SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
10322712d1f2SDave May   PetscInt ng;
10332712d1f2SDave May 
1034521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1035480eef7bSDave May   if (swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView currently active");
1036480eef7bSDave May   ierr = DMSwarmGetLocalSize(dm,&ng);CHKERRQ(ierr);
1037480eef7bSDave May   switch (swarm->collect_type) {
1038f0cdbbbaSDave May 
1039480eef7bSDave May     case DMSWARM_COLLECT_BASIC:
10402712d1f2SDave May       ierr = DMSwarmMigrate_GlobalToLocal_Basic(dm,&ng);CHKERRQ(ierr);
1041480eef7bSDave May       break;
1042480eef7bSDave May     case DMSWARM_COLLECT_DMDABOUNDINGBOX:
1043f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_DMDABOUNDINGBOX not implemented");
1044521f74f9SMatthew G. Knepley       /*ierr = DMSwarmCollect_DMDABoundingBox(dm,&ng);CHKERRQ(ierr);*/
1045480eef7bSDave May       break;
1046480eef7bSDave May     case DMSWARM_COLLECT_GENERAL:
1047f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_GENERAL not implemented");
1048521f74f9SMatthew G. Knepley       /*ierr = DMSwarmCollect_General(dm,..,,..,&ng);CHKERRQ(ierr);*/
1049480eef7bSDave May       break;
1050480eef7bSDave May     default:
1051f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT type unknown");
1052480eef7bSDave May       break;
1053480eef7bSDave May   }
1054480eef7bSDave May   swarm->collect_view_active = PETSC_TRUE;
1055480eef7bSDave May   swarm->collect_view_reset_nlocal = ng;
10562712d1f2SDave May   PetscFunctionReturn(0);
10572712d1f2SDave May }
10582712d1f2SDave May 
1059d3a51819SDave May /*@C
1060d3a51819SDave May    DMSwarmCollectViewDestroy - Resets the DMSwarm to the size prior to calling DMSwarmCollectViewCreate()
1061d3a51819SDave May 
1062d3a51819SDave May    Collective on DM
1063d3a51819SDave May 
1064d3a51819SDave May    Input parameters:
1065d3a51819SDave May .  dm - the DMSwarm
1066d3a51819SDave May 
1067d3a51819SDave May    Notes:
1068d3a51819SDave May    Users should call DMSwarmCollectViewCreate() before this function is called.
1069d3a51819SDave May 
1070d3a51819SDave May    Level: advanced
1071d3a51819SDave May 
1072d3a51819SDave May .seealso: DMSwarmCollectViewCreate(), DMSwarmSetCollectType()
1073d3a51819SDave May @*/
1074fe39f135SDave May PETSC_EXTERN PetscErrorCode DMSwarmCollectViewDestroy(DM dm)
10752712d1f2SDave May {
10762712d1f2SDave May   PetscErrorCode ierr;
10772712d1f2SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
10782712d1f2SDave May 
1079521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1080480eef7bSDave May   if (!swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView is currently not active");
1081480eef7bSDave May   ierr = DMSwarmSetLocalSizes(dm,swarm->collect_view_reset_nlocal,-1);CHKERRQ(ierr);
1082480eef7bSDave May   swarm->collect_view_active = PETSC_FALSE;
10832712d1f2SDave May   PetscFunctionReturn(0);
10842712d1f2SDave May }
10853454631fSDave May 
1086f0cdbbbaSDave May PetscErrorCode DMSwarmSetUpPIC(DM dm)
1087f0cdbbbaSDave May {
1088f0cdbbbaSDave May   PetscInt dim;
1089f0cdbbbaSDave May   PetscErrorCode ierr;
1090f0cdbbbaSDave May 
1091521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1092f0cdbbbaSDave May   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
1093f0cdbbbaSDave May   if (dim < 1) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
1094f0cdbbbaSDave May   if (dim > 3) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
1095f0cdbbbaSDave May   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_coor,dim,PETSC_DOUBLE);CHKERRQ(ierr);
1096e2d107dbSDave May   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_cellid,1,PETSC_INT);CHKERRQ(ierr);
1097f0cdbbbaSDave May   PetscFunctionReturn(0);
1098f0cdbbbaSDave May }
1099f0cdbbbaSDave May 
1100d3a51819SDave May /*@C
1101d3a51819SDave May    DMSwarmSetType - Set particular flavor of DMSwarm
1102d3a51819SDave May 
1103d3a51819SDave May    Collective on DM
1104d3a51819SDave May 
1105d3a51819SDave May    Input parameters:
110662741f57SDave May +  dm - the DMSwarm
110762741f57SDave May -  stype - the DMSwarm type (e.g. DMSWARM_PIC)
1108d3a51819SDave May 
1109d3a51819SDave May    Level: advanced
1110d3a51819SDave May 
1111d3a51819SDave May .seealso: DMSwarmSetMigrateType(), DMSwarmSetCollectType()
1112d3a51819SDave May @*/
1113f0cdbbbaSDave May PETSC_EXTERN PetscErrorCode DMSwarmSetType(DM dm,DMSwarmType stype)
1114f0cdbbbaSDave May {
1115f0cdbbbaSDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
1116f0cdbbbaSDave May   PetscErrorCode ierr;
1117f0cdbbbaSDave May 
1118521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1119f0cdbbbaSDave May   swarm->swarm_type = stype;
1120f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
1121f0cdbbbaSDave May     ierr = DMSwarmSetUpPIC(dm);CHKERRQ(ierr);
1122f0cdbbbaSDave May   }
1123f0cdbbbaSDave May   PetscFunctionReturn(0);
1124f0cdbbbaSDave May }
1125f0cdbbbaSDave May 
11263454631fSDave May PetscErrorCode DMSetup_Swarm(DM dm)
11273454631fSDave May {
11283454631fSDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
11293454631fSDave May   PetscErrorCode ierr;
11303454631fSDave May   PetscMPIInt rank;
11313454631fSDave May   PetscInt p,npoints,*rankval;
11323454631fSDave May 
1133521f74f9SMatthew G. Knepley   PetscFunctionBegin;
11343454631fSDave May   if (swarm->issetup) PetscFunctionReturn(0);
11353454631fSDave May 
11363454631fSDave May   swarm->issetup = PETSC_TRUE;
11373454631fSDave May 
1138f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
1139f0cdbbbaSDave May     /* check dmcell exists */
1140f0cdbbbaSDave May     if (!swarm->dmcell) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires you call DMSwarmSetCellDM");
1141f0cdbbbaSDave May 
1142f0cdbbbaSDave May     if (swarm->dmcell->ops->locatepointssubdomain) {
1143f0cdbbbaSDave May       /* check methods exists for exact ownership identificiation */
1144521f74f9SMatthew G. Knepley       ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->ops->LocatePointsSubdomain\n");CHKERRQ(ierr);
1145f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLEXACT;
1146f0cdbbbaSDave May     } else {
1147f0cdbbbaSDave May       /* check methods exist for point location AND rank neighbor identification */
1148f0cdbbbaSDave May       if (swarm->dmcell->ops->locatepoints) {
1149521f74f9SMatthew G. Knepley         ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->LocatePoints\n");CHKERRQ(ierr);
1150f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->locatepoints be defined");
1151f0cdbbbaSDave May 
1152f0cdbbbaSDave May       if (swarm->dmcell->ops->getneighbors) {
1153521f74f9SMatthew G. Knepley         ierr = PetscPrintf(PetscObjectComm((PetscObject)dm),"  DMSWARM_PIC: Using method CellDM->GetNeigbors\n");CHKERRQ(ierr);
1154f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->getneighbors be defined");
1155f0cdbbbaSDave May 
1156f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLNSCATTER;
1157f0cdbbbaSDave May     }
1158f0cdbbbaSDave May   }
1159f0cdbbbaSDave May 
1160f0cdbbbaSDave May   ierr = DMSwarmFinalizeFieldRegister(dm);CHKERRQ(ierr);
1161f0cdbbbaSDave May 
11623454631fSDave May   /* check some fields were registered */
11633454631fSDave May   if (swarm->db->nfields <= 2) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"At least one field user must be registered via DMSwarmRegisterXXX()");
11643454631fSDave May 
11653454631fSDave May   /* check local sizes were set */
11663454631fSDave May   if (swarm->db->L == -1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Local sizes must be set via DMSwarmSetLocalSizes()");
11673454631fSDave May 
11683454631fSDave May   /* initialize values in pid and rank placeholders */
11693454631fSDave May   /* TODO: [pid - use MPI_Scan] */
11703454631fSDave May   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
11713454631fSDave May   ierr = DataBucketGetSizes(swarm->db,&npoints,NULL,NULL);CHKERRQ(ierr);
1172f0cdbbbaSDave May   ierr = DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
11733454631fSDave May   for (p=0; p<npoints; p++) {
11743454631fSDave May     rankval[p] = (PetscInt)rank;
11753454631fSDave May   }
1176f0cdbbbaSDave May   ierr = DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
11773454631fSDave May   PetscFunctionReturn(0);
11783454631fSDave May }
11793454631fSDave May 
1180dc5f5ce9SDave May extern PetscErrorCode DMSwarmSortDestroy(DMSwarmSort *_ctx);
1181dc5f5ce9SDave May 
118257795646SDave May PetscErrorCode DMDestroy_Swarm(DM dm)
118357795646SDave May {
118457795646SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
118557795646SDave May   PetscErrorCode ierr;
118657795646SDave May 
118757795646SDave May   PetscFunctionBegin;
11886845f8f5SDave May   ierr = DataBucketDestroy(&swarm->db);CHKERRQ(ierr);
1189dc5f5ce9SDave May   if (swarm->sort_context) {
1190dc5f5ce9SDave May     ierr = DMSwarmSortDestroy(&swarm->sort_context);CHKERRQ(ierr);
1191dc5f5ce9SDave May   }
119257795646SDave May   ierr = PetscFree(swarm);CHKERRQ(ierr);
119357795646SDave May   PetscFunctionReturn(0);
119457795646SDave May }
119557795646SDave May 
1196a9ee3421SMatthew G. Knepley PetscErrorCode DMSwarmView_Draw(DM dm, PetscViewer viewer)
1197a9ee3421SMatthew G. Knepley {
1198a9ee3421SMatthew G. Knepley   DM             cdm;
1199a9ee3421SMatthew G. Knepley   PetscDraw      draw;
1200a9ee3421SMatthew G. Knepley   PetscReal     *coords, oldPause;
1201a9ee3421SMatthew G. Knepley   PetscInt       Np, p, bs;
1202a9ee3421SMatthew G. Knepley   PetscErrorCode ierr;
1203a9ee3421SMatthew G. Knepley 
1204a9ee3421SMatthew G. Knepley   PetscFunctionBegin;
1205a9ee3421SMatthew G. Knepley   ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr);
1206a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetCellDM(dm, &cdm);CHKERRQ(ierr);
1207a9ee3421SMatthew G. Knepley   ierr = PetscDrawGetPause(draw, &oldPause);CHKERRQ(ierr);
1208a9ee3421SMatthew G. Knepley   ierr = PetscDrawSetPause(draw, 0.0);CHKERRQ(ierr);
1209a9ee3421SMatthew G. Knepley   ierr = DMView(cdm, viewer);CHKERRQ(ierr);
1210a9ee3421SMatthew G. Knepley   ierr = PetscDrawSetPause(draw, oldPause);CHKERRQ(ierr);
1211a9ee3421SMatthew G. Knepley 
1212a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetLocalSize(dm, &Np);CHKERRQ(ierr);
1213a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1214a9ee3421SMatthew G. Knepley   for (p = 0; p < Np; ++p) {
1215a9ee3421SMatthew G. Knepley     const PetscInt i = p*bs;
1216a9ee3421SMatthew G. Knepley 
1217a9ee3421SMatthew G. Knepley     ierr = PetscDrawEllipse(draw, coords[i], coords[i+1], 0.01, 0.01, PETSC_DRAW_BLUE);CHKERRQ(ierr);
1218a9ee3421SMatthew G. Knepley   }
1219a9ee3421SMatthew G. Knepley   ierr = DMSwarmRestoreField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1220a9ee3421SMatthew G. Knepley   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
1221a9ee3421SMatthew G. Knepley   ierr = PetscDrawPause(draw);CHKERRQ(ierr);
1222a9ee3421SMatthew G. Knepley   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
1223a9ee3421SMatthew G. Knepley   PetscFunctionReturn(0);
1224a9ee3421SMatthew G. Knepley }
1225a9ee3421SMatthew G. Knepley 
12265f50eb2eSDave May PetscErrorCode DMView_Swarm(DM dm, PetscViewer viewer)
12275f50eb2eSDave May {
12285f50eb2eSDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
1229a9ee3421SMatthew G. Knepley   PetscBool      iascii,ibinary,ishdf5,isvtk,isdraw;
12305f50eb2eSDave May   PetscErrorCode ierr;
12315f50eb2eSDave May 
12325f50eb2eSDave May   PetscFunctionBegin;
12335f50eb2eSDave May   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
12345f50eb2eSDave May   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
12355f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
12365f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY,&ibinary);CHKERRQ(ierr);
12375f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK,   &isvtk);CHKERRQ(ierr);
12385f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
1239a9ee3421SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW,  &isdraw);CHKERRQ(ierr);
12405f50eb2eSDave May   if (iascii) {
12416845f8f5SDave May     ierr = DataBucketView(PetscObjectComm((PetscObject)dm),swarm->db,NULL,DATABUCKET_VIEW_STDOUT);CHKERRQ(ierr);
12425f50eb2eSDave May   } else if (ibinary) {
1243a9ee3421SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO Binary support");
12445f50eb2eSDave May   } else if (ishdf5) {
12455f50eb2eSDave May #if defined(PETSC_HAVE_HDF5)
12465f50eb2eSDave May     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO HDF5 support");
12475f50eb2eSDave May #else
12485f50eb2eSDave May     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"HDF5 not supported. Please reconfigure using --download-hdf5");
12495f50eb2eSDave May #endif
12505f50eb2eSDave May   } else if (isvtk) {
12515f50eb2eSDave May     SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO VTK support");
1252a9ee3421SMatthew G. Knepley   } else if (isdraw) {
1253a9ee3421SMatthew G. Knepley     ierr = DMSwarmView_Draw(dm, viewer);CHKERRQ(ierr);
12545f50eb2eSDave May   }
12555f50eb2eSDave May   PetscFunctionReturn(0);
12565f50eb2eSDave May }
12575f50eb2eSDave May 
1258d3a51819SDave May /*MC
1259d3a51819SDave May 
1260d3a51819SDave May  DMSWARM = "swarm" - A DM object used to represent arrays of data (fields) of arbitrary data type.
126162741f57SDave May  This implementation was designed for particle methods in which the underlying
1262d3a51819SDave May  data required to be represented is both (i) dynamic in length, (ii) and of arbitrary data type.
1263d3a51819SDave May 
126462741f57SDave May  User data can be represented by DMSwarm through a registering "fields".
126562741f57SDave May  To register a field, the user must provide;
126662741f57SDave May  (a) a unique name;
126762741f57SDave May  (b) the data type (or size in bytes);
126862741f57SDave May  (c) the block size of the data.
1269d3a51819SDave May 
1270d3a51819SDave May  For example, suppose the application requires a unique id, energy, momentum and density to be stored
127162741f57SDave May  on a set of of particles. Then the following code could be used
1272d3a51819SDave May 
127362741f57SDave May $    DMSwarmInitializeFieldRegister(dm)
127462741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"uid",1,PETSC_LONG);
127562741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"energy",1,PETSC_REAL);
127662741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"momentum",3,PETSC_REAL);
127762741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"density",1,PETSC_FLOAT);
127862741f57SDave May $    DMSwarmFinalizeFieldRegister(dm)
1279d3a51819SDave May 
1280d3a51819SDave May  The fields represented by DMSwarm are dynamic and can be re-sized at any time.
128162741f57SDave May  The only restriction imposed by DMSwarm is that all fields contain the same number of points.
1282d3a51819SDave May 
1283d3a51819SDave May  To support particle methods, "migration" techniques are provided. These methods migrate data
1284d3a51819SDave May  between MPI-ranks.
1285d3a51819SDave May 
1286d3a51819SDave May  DMSwarm supports the methods DMCreateGlobalVector() and DMCreateLocalVector().
1287d3a51819SDave May  As a DMSwarm may internally define and store values of different data types,
128862741f57SDave May  before calling DMCreateGlobalVector() or DMCreateLocalVector(), the user must inform DMSwarm which
1289d3a51819SDave May  fields should be used to define a Vec object via
1290d3a51819SDave May    DMSwarmVectorDefineField()
1291d3a51819SDave May  The specified field can can changed be changed at any time - thereby permitting vectors
1292d3a51819SDave May  compatable with different fields to be created.
1293d3a51819SDave May 
129462741f57SDave May  A dual representation of fields in the DMSwarm and a Vec object is permitted via
1295d3a51819SDave May    DMSwarmCreateGlobalVectorFromField()
1296d3a51819SDave May  Here the data defining the field in the DMSwarm is shared with a Vec.
1297d3a51819SDave May  This is inherently unsafe if you alter the size of the field at any time between
1298d3a51819SDave May  calls to DMSwarmCreateGlobalVectorFromField() and DMSwarmDestroyGlobalVectorFromField().
1299cc651181SDave May  If the local size of the DMSwarm does not match the local size of the global vector
1300cc651181SDave May  when DMSwarmDestroyGlobalVectorFromField() is called, an error is thrown.
1301d3a51819SDave May 
130262741f57SDave May  Additional high-level support is provided for Particle-In-Cell methods.
130362741f57SDave May  Please refer to the man page for DMSwarmSetType().
130462741f57SDave May 
1305d3a51819SDave May  Level: beginner
1306d3a51819SDave May 
1307d3a51819SDave May .seealso: DMType, DMCreate(), DMSetType()
1308d3a51819SDave May M*/
130957795646SDave May PETSC_EXTERN PetscErrorCode DMCreate_Swarm(DM dm)
131057795646SDave May {
131157795646SDave May   DM_Swarm      *swarm;
131257795646SDave May   PetscErrorCode ierr;
131357795646SDave May 
131457795646SDave May   PetscFunctionBegin;
131557795646SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
131657795646SDave May   ierr     = PetscNewLog(dm,&swarm);CHKERRQ(ierr);
1317f0cdbbbaSDave May   dm->data = swarm;
131857795646SDave May 
13196845f8f5SDave May   ierr = DataBucketCreate(&swarm->db);CHKERRQ(ierr);
1320f0cdbbbaSDave May   ierr = DMSwarmInitializeFieldRegister(dm);CHKERRQ(ierr);
1321f0cdbbbaSDave May 
1322b5bcf523SDave May   swarm->vec_field_set = PETSC_FALSE;
13233454631fSDave May   swarm->issetup = PETSC_FALSE;
1324480eef7bSDave May   swarm->swarm_type = DMSWARM_BASIC;
1325480eef7bSDave May   swarm->migrate_type = DMSWARM_MIGRATE_BASIC;
1326480eef7bSDave May   swarm->collect_type = DMSWARM_COLLECT_BASIC;
132740c453e9SDave May   swarm->migrate_error_on_missing_point = PETSC_FALSE;
1328b62e03f8SDave May 
1329f0cdbbbaSDave May   swarm->dmcell = NULL;
1330f0cdbbbaSDave May   swarm->collect_view_active = PETSC_FALSE;
1331f0cdbbbaSDave May   swarm->collect_view_reset_nlocal = -1;
133257795646SDave May 
1333f0cdbbbaSDave May   dm->dim  = 0;
13345f50eb2eSDave May   dm->ops->view                            = DMView_Swarm;
133557795646SDave May   dm->ops->load                            = NULL;
133657795646SDave May   dm->ops->setfromoptions                  = NULL;
133757795646SDave May   dm->ops->clone                           = NULL;
13383454631fSDave May   dm->ops->setup                           = DMSetup_Swarm;
133957795646SDave May   dm->ops->createdefaultsection            = NULL;
134057795646SDave May   dm->ops->createdefaultconstraints        = NULL;
1341b5bcf523SDave May   dm->ops->createglobalvector              = DMCreateGlobalVector_Swarm;
1342b5bcf523SDave May   dm->ops->createlocalvector               = DMCreateLocalVector_Swarm;
134357795646SDave May   dm->ops->getlocaltoglobalmapping         = NULL;
134457795646SDave May   dm->ops->createfieldis                   = NULL;
134557795646SDave May   dm->ops->createcoordinatedm              = NULL;
134657795646SDave May   dm->ops->getcoloring                     = NULL;
134757795646SDave May   dm->ops->creatematrix                    = NULL;
134857795646SDave May   dm->ops->createinterpolation             = NULL;
134957795646SDave May   dm->ops->getaggregates                   = NULL;
135057795646SDave May   dm->ops->getinjection                    = NULL;
135183c47955SMatthew G. Knepley   dm->ops->createmassmatrix                = DMCreateMassMatrix_Swarm;
135257795646SDave May   dm->ops->refine                          = NULL;
135357795646SDave May   dm->ops->coarsen                         = NULL;
135457795646SDave May   dm->ops->refinehierarchy                 = NULL;
135557795646SDave May   dm->ops->coarsenhierarchy                = NULL;
135657795646SDave May   dm->ops->globaltolocalbegin              = NULL;
135757795646SDave May   dm->ops->globaltolocalend                = NULL;
135857795646SDave May   dm->ops->localtoglobalbegin              = NULL;
135957795646SDave May   dm->ops->localtoglobalend                = NULL;
136057795646SDave May   dm->ops->destroy                         = DMDestroy_Swarm;
136157795646SDave May   dm->ops->createsubdm                     = NULL;
136257795646SDave May   dm->ops->getdimpoints                    = NULL;
136357795646SDave May   dm->ops->locatepoints                    = NULL;
136457795646SDave May   PetscFunctionReturn(0);
136557795646SDave May }
1366