xref: /petsc/src/dm/impls/swarm/swarm.c (revision 31403186891f3d2c32002533fd243194e0ca18bb)
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>
84cc7f7b2SMatthew G. Knepley #include <petscblaslapack.h>
9279f676cSBarry Smith #include "../src/dm/impls/swarm/data_bucket.h"
1057795646SDave May 
11f2b2bee7SDave May PetscLogEvent DMSWARM_Migrate, DMSWARM_SetSizes, DMSWARM_AddPoints, DMSWARM_RemovePoints, DMSWARM_Sort;
12ed923d71SDave May PetscLogEvent DMSWARM_DataExchangerTopologySetup, DMSWARM_DataExchangerBegin, DMSWARM_DataExchangerEnd;
13ed923d71SDave May PetscLogEvent DMSWARM_DataExchangerSendCount, DMSWARM_DataExchangerPack;
14ed923d71SDave May 
15ea78f98cSLisandro Dalcin const char* DMSwarmTypeNames[] = { "basic", "pic", NULL };
16ea78f98cSLisandro Dalcin const char* DMSwarmMigrateTypeNames[] = { "basic", "dmcellnscatter", "dmcellexact", "user", NULL };
17ea78f98cSLisandro Dalcin const char* DMSwarmCollectTypeNames[] = { "basic", "boundingbox", "general", "user", NULL  };
18ea78f98cSLisandro Dalcin const char* DMSwarmPICLayoutTypeNames[] = { "regular", "gauss", "subdivision", NULL  };
19f0cdbbbaSDave May 
20f0cdbbbaSDave May const char DMSwarmField_pid[] = "DMSwarm_pid";
21f0cdbbbaSDave May const char DMSwarmField_rank[] = "DMSwarm_rank";
22f0cdbbbaSDave May const char DMSwarmPICField_coor[] = "DMSwarmPIC_coor";
23e2d107dbSDave May const char DMSwarmPICField_cellid[] = "DMSwarm_cellid";
24f0cdbbbaSDave May 
2574d0cae8SMatthew G. Knepley PETSC_EXTERN PetscErrorCode VecView_Seq(Vec, PetscViewer);
2674d0cae8SMatthew G. Knepley PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer);
2774d0cae8SMatthew G. Knepley 
2874d0cae8SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
2974d0cae8SMatthew G. Knepley #include <petscviewerhdf5.h>
3074d0cae8SMatthew G. Knepley 
3174d0cae8SMatthew G. Knepley PetscErrorCode VecView_Swarm_HDF5_Internal(Vec v, PetscViewer viewer)
3274d0cae8SMatthew G. Knepley {
3374d0cae8SMatthew G. Knepley   DM             dm;
3474d0cae8SMatthew G. Knepley   PetscReal      seqval;
3574d0cae8SMatthew G. Knepley   PetscInt       seqnum, bs;
3674d0cae8SMatthew G. Knepley   PetscBool      isseq;
3774d0cae8SMatthew G. Knepley   PetscErrorCode ierr;
3874d0cae8SMatthew G. Knepley 
3974d0cae8SMatthew G. Knepley   PetscFunctionBegin;
4074d0cae8SMatthew G. Knepley   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
4174d0cae8SMatthew G. Knepley   ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr);
4274d0cae8SMatthew G. Knepley   ierr = PetscViewerHDF5PushGroup(viewer, "/particle_fields");CHKERRQ(ierr);
4374d0cae8SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr);
4474d0cae8SMatthew G. Knepley   ierr = DMGetOutputSequenceNumber(dm, &seqnum, &seqval);CHKERRQ(ierr);
4574d0cae8SMatthew G. Knepley   ierr = PetscViewerHDF5SetTimestep(viewer, seqnum);CHKERRQ(ierr);
4674d0cae8SMatthew G. Knepley   /* ierr = DMSequenceView_HDF5(dm, "time", seqnum, (PetscScalar) seqval, viewer);CHKERRQ(ierr); */
4774d0cae8SMatthew G. Knepley   if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);}
4874d0cae8SMatthew G. Knepley   else       {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);}
4974d0cae8SMatthew G. Knepley   ierr = PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject) v, "Nc", PETSC_INT, (void *) &bs);CHKERRQ(ierr);
5074d0cae8SMatthew G. Knepley   ierr = PetscViewerHDF5PopGroup(viewer);CHKERRQ(ierr);
5174d0cae8SMatthew G. Knepley   PetscFunctionReturn(0);
5274d0cae8SMatthew G. Knepley }
5374d0cae8SMatthew G. Knepley 
5474d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmView_HDF5(DM dm, PetscViewer viewer)
5574d0cae8SMatthew G. Knepley {
5674d0cae8SMatthew G. Knepley   Vec            coordinates;
5774d0cae8SMatthew G. Knepley   PetscInt       Np;
5874d0cae8SMatthew G. Knepley   PetscBool      isseq;
5974d0cae8SMatthew G. Knepley   PetscErrorCode ierr;
6074d0cae8SMatthew G. Knepley 
6174d0cae8SMatthew G. Knepley   PetscFunctionBegin;
6274d0cae8SMatthew G. Knepley   ierr = DMSwarmGetSize(dm, &Np);CHKERRQ(ierr);
6374d0cae8SMatthew G. Knepley   ierr = DMSwarmCreateGlobalVectorFromField(dm, DMSwarmPICField_coor, &coordinates);CHKERRQ(ierr);
6474d0cae8SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr);
6574d0cae8SMatthew G. Knepley   ierr = PetscViewerHDF5PushGroup(viewer, "/particles");CHKERRQ(ierr);
6674d0cae8SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) coordinates, VECSEQ, &isseq);CHKERRQ(ierr);
6774d0cae8SMatthew G. Knepley   if (isseq) {ierr = VecView_Seq(coordinates, viewer);CHKERRQ(ierr);}
6874d0cae8SMatthew G. Knepley   else       {ierr = VecView_MPI(coordinates, viewer);CHKERRQ(ierr);}
6974d0cae8SMatthew G. Knepley   ierr = PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject) coordinates, "Np", PETSC_INT, (void *) &Np);CHKERRQ(ierr);
7074d0cae8SMatthew G. Knepley   ierr = PetscViewerHDF5PopGroup(viewer);CHKERRQ(ierr);
7174d0cae8SMatthew G. Knepley   ierr = DMSwarmDestroyGlobalVectorFromField(dm, DMSwarmPICField_coor, &coordinates);CHKERRQ(ierr);
7274d0cae8SMatthew G. Knepley   PetscFunctionReturn(0);
7374d0cae8SMatthew G. Knepley }
7474d0cae8SMatthew G. Knepley #endif
7574d0cae8SMatthew G. Knepley 
7674d0cae8SMatthew G. Knepley PetscErrorCode VecView_Swarm(Vec v, PetscViewer viewer)
7774d0cae8SMatthew G. Knepley {
7874d0cae8SMatthew G. Knepley   DM             dm;
7974d0cae8SMatthew G. Knepley   PetscBool      ishdf5;
8074d0cae8SMatthew G. Knepley   PetscErrorCode ierr;
8174d0cae8SMatthew G. Knepley 
8274d0cae8SMatthew G. Knepley   PetscFunctionBegin;
8374d0cae8SMatthew G. Knepley   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
8474d0cae8SMatthew G. Knepley   if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
8574d0cae8SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
8674d0cae8SMatthew G. Knepley   if (ishdf5) {
8774d0cae8SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
8874d0cae8SMatthew G. Knepley     ierr = VecView_Swarm_HDF5_Internal(v, viewer);CHKERRQ(ierr);
8974d0cae8SMatthew G. Knepley #else
9074d0cae8SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
9174d0cae8SMatthew G. Knepley #endif
9274d0cae8SMatthew G. Knepley   } else {
9374d0cae8SMatthew G. Knepley     PetscBool isseq;
9474d0cae8SMatthew G. Knepley 
9574d0cae8SMatthew G. Knepley     ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr);
9674d0cae8SMatthew G. Knepley     if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);}
9774d0cae8SMatthew G. Knepley     else       {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);}
9874d0cae8SMatthew G. Knepley   }
9974d0cae8SMatthew G. Knepley   PetscFunctionReturn(0);
10074d0cae8SMatthew G. Knepley }
10174d0cae8SMatthew G. Knepley 
102d3a51819SDave May /*@C
10362741f57SDave May    DMSwarmVectorDefineField - Sets the field from which to define a Vec object
10462741f57SDave May                              when DMCreateLocalVector(), or DMCreateGlobalVector() is called
10557795646SDave May 
106d083f849SBarry Smith    Collective on dm
10757795646SDave May 
108d3a51819SDave May    Input parameters:
10962741f57SDave May +  dm - a DMSwarm
11062741f57SDave May -  fieldname - the textual name given to a registered field
11157795646SDave May 
112d3a51819SDave May    Level: beginner
11357795646SDave May 
114d3a51819SDave May    Notes:
115e7af74c8SDave May 
11662741f57SDave May    The field with name fieldname must be defined as having a data type of PetscScalar.
117e7af74c8SDave May 
118d3a51819SDave May    This function must be called prior to calling DMCreateLocalVector(), DMCreateGlobalVector().
119d3a51819SDave May    Mutiple calls to DMSwarmVectorDefineField() are permitted.
12057795646SDave May 
1218b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMCreateGlobalVector(), DMCreateLocalVector()
122d3a51819SDave May @*/
12374d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmVectorDefineField(DM dm,const char fieldname[])
124b5bcf523SDave May {
125b5bcf523SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
126b5bcf523SDave May   PetscErrorCode ierr;
127b5bcf523SDave May   PetscInt       bs,n;
128b5bcf523SDave May   PetscScalar    *array;
129b5bcf523SDave May   PetscDataType  type;
130b5bcf523SDave May 
131a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
1323454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
13377048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db,&n,NULL,NULL);CHKERRQ(ierr);
134b5bcf523SDave May   ierr = DMSwarmGetField(dm,fieldname,&bs,&type,(void**)&array);CHKERRQ(ierr);
135b5bcf523SDave May 
136b5bcf523SDave May   /* Check all fields are of type PETSC_REAL or PETSC_SCALAR */
137b5bcf523SDave May   if (type != PETSC_REAL) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only valid for PETSC_REAL");
138521f74f9SMatthew G. Knepley   ierr = PetscSNPrintf(swarm->vec_field_name,PETSC_MAX_PATH_LEN-1,"%s",fieldname);CHKERRQ(ierr);
139b5bcf523SDave May   swarm->vec_field_set = PETSC_TRUE;
1401b1ea282SDave May   swarm->vec_field_bs = bs;
141b5bcf523SDave May   swarm->vec_field_nlocal = n;
142dcf43ee8SDave May   ierr = DMSwarmRestoreField(dm,fieldname,&bs,&type,(void**)&array);CHKERRQ(ierr);
143b5bcf523SDave May   PetscFunctionReturn(0);
144b5bcf523SDave May }
145b5bcf523SDave May 
146cc651181SDave May /* requires DMSwarmDefineFieldVector has been called */
147b5bcf523SDave May PetscErrorCode DMCreateGlobalVector_Swarm(DM dm,Vec *vec)
148b5bcf523SDave May {
149b5bcf523SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
150b5bcf523SDave May   PetscErrorCode ierr;
151b5bcf523SDave May   Vec            x;
152b5bcf523SDave May   char           name[PETSC_MAX_PATH_LEN];
153b5bcf523SDave May 
154a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
1553454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
156b5bcf523SDave May   if (!swarm->vec_field_set) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmVectorDefineField first");
157cc651181SDave 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 */
158cc651181SDave May 
159521f74f9SMatthew G. Knepley   ierr = PetscSNPrintf(name,PETSC_MAX_PATH_LEN-1,"DMSwarmField_%s",swarm->vec_field_name);CHKERRQ(ierr);
160b5bcf523SDave May   ierr = VecCreate(PetscObjectComm((PetscObject)dm),&x);CHKERRQ(ierr);
161b5bcf523SDave May   ierr = PetscObjectSetName((PetscObject)x,name);CHKERRQ(ierr);
1621b1ea282SDave May   ierr = VecSetSizes(x,swarm->db->L*swarm->vec_field_bs,PETSC_DETERMINE);CHKERRQ(ierr);
163b5bcf523SDave May   ierr = VecSetBlockSize(x,swarm->vec_field_bs);CHKERRQ(ierr);
164c6b011d8SStefano Zampini   ierr = VecSetDM(x,dm);CHKERRQ(ierr);
165b5bcf523SDave May   ierr = VecSetFromOptions(x);CHKERRQ(ierr);
16674d0cae8SMatthew G. Knepley   ierr = VecSetDM(x, dm);CHKERRQ(ierr);
16774d0cae8SMatthew G. Knepley   ierr = VecSetOperation(x, VECOP_VIEW, (void (*)(void)) VecView_Swarm);CHKERRQ(ierr);
168b5bcf523SDave May   *vec = x;
169b5bcf523SDave May   PetscFunctionReturn(0);
170b5bcf523SDave May }
171b5bcf523SDave May 
172b5bcf523SDave May /* requires DMSwarmDefineFieldVector has been called */
173b5bcf523SDave May PetscErrorCode DMCreateLocalVector_Swarm(DM dm,Vec *vec)
174b5bcf523SDave May {
175b5bcf523SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
176b5bcf523SDave May   PetscErrorCode ierr;
177b5bcf523SDave May   Vec x;
178b5bcf523SDave May   char name[PETSC_MAX_PATH_LEN];
179b5bcf523SDave May 
180a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
1813454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
182b5bcf523SDave May   if (!swarm->vec_field_set) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmVectorDefineField first");
183cc651181SDave 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 */
184cc651181SDave May 
185521f74f9SMatthew G. Knepley   ierr = PetscSNPrintf(name,PETSC_MAX_PATH_LEN-1,"DMSwarmField_%s",swarm->vec_field_name);CHKERRQ(ierr);
186b5bcf523SDave May   ierr = VecCreate(PETSC_COMM_SELF,&x);CHKERRQ(ierr);
187b5bcf523SDave May   ierr = PetscObjectSetName((PetscObject)x,name);CHKERRQ(ierr);
188071900c8SMatthew G. Knepley   ierr = VecSetSizes(x,swarm->db->L*swarm->vec_field_bs,PETSC_DETERMINE);CHKERRQ(ierr);
189b5bcf523SDave May   ierr = VecSetBlockSize(x,swarm->vec_field_bs);CHKERRQ(ierr);
190c6b011d8SStefano Zampini   ierr = VecSetDM(x,dm);CHKERRQ(ierr);
191b5bcf523SDave May   ierr = VecSetFromOptions(x);CHKERRQ(ierr);
192b5bcf523SDave May   *vec = x;
193b5bcf523SDave May   PetscFunctionReturn(0);
194b5bcf523SDave May }
195b5bcf523SDave May 
196fb1bcc12SMatthew G. Knepley static PetscErrorCode DMSwarmDestroyVectorFromField_Private(DM dm, const char fieldname[], Vec *vec)
197fb1bcc12SMatthew G. Knepley {
198fb1bcc12SMatthew G. Knepley   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
19977048351SPatrick Sanan   DMSwarmDataField      gfield;
200fb1bcc12SMatthew G. Knepley   void         (*fptr)(void);
201fb1bcc12SMatthew G. Knepley   PetscInt       bs, nlocal;
202fb1bcc12SMatthew G. Knepley   char           name[PETSC_MAX_PATH_LEN];
203fb1bcc12SMatthew G. Knepley   PetscErrorCode ierr;
204d3a51819SDave May 
205fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
206fb1bcc12SMatthew G. Knepley   ierr = VecGetLocalSize(*vec, &nlocal);CHKERRQ(ierr);
207fb1bcc12SMatthew G. Knepley   ierr = VecGetBlockSize(*vec, &bs);CHKERRQ(ierr);
208fb1bcc12SMatthew 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 */
20977048351SPatrick Sanan   ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield);CHKERRQ(ierr);
210fb1bcc12SMatthew G. Knepley   /* check vector is an inplace array */
211521f74f9SMatthew G. Knepley   ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarm_VecFieldInPlace_%s", fieldname);CHKERRQ(ierr);
212fb1bcc12SMatthew G. Knepley   ierr = PetscObjectQueryFunction((PetscObject) *vec, name, &fptr);CHKERRQ(ierr);
213fb1bcc12SMatthew G. Knepley   if (!fptr) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_USER, "Vector being destroyed was not created from DMSwarm field(%s)", fieldname);
21477048351SPatrick Sanan   ierr = DMSwarmDataFieldRestoreAccess(gfield);CHKERRQ(ierr);
215fb1bcc12SMatthew G. Knepley   ierr = VecDestroy(vec);CHKERRQ(ierr);
216fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
217fb1bcc12SMatthew G. Knepley }
218fb1bcc12SMatthew G. Knepley 
219fb1bcc12SMatthew G. Knepley static PetscErrorCode DMSwarmCreateVectorFromField_Private(DM dm, const char fieldname[], MPI_Comm comm, Vec *vec)
220fb1bcc12SMatthew G. Knepley {
221fb1bcc12SMatthew G. Knepley   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
222fb1bcc12SMatthew G. Knepley   PetscDataType  type;
223fb1bcc12SMatthew G. Knepley   PetscScalar   *array;
224fb1bcc12SMatthew G. Knepley   PetscInt       bs, n;
225fb1bcc12SMatthew G. Knepley   char           name[PETSC_MAX_PATH_LEN];
226e4fbd051SBarry Smith   PetscMPIInt    size;
227fb1bcc12SMatthew G. Knepley   PetscErrorCode ierr;
228fb1bcc12SMatthew G. Knepley 
229fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
230fb1bcc12SMatthew G. Knepley   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
23177048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db, &n, NULL, NULL);CHKERRQ(ierr);
232fb1bcc12SMatthew G. Knepley   ierr = DMSwarmGetField(dm, fieldname, &bs, &type, (void **) &array);CHKERRQ(ierr);
233fb1bcc12SMatthew G. Knepley   if (type != PETSC_REAL) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Only valid for PETSC_REAL");
234fb1bcc12SMatthew G. Knepley 
235ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
236e4fbd051SBarry Smith   if (size == 1) {
237fb1bcc12SMatthew G. Knepley     ierr = VecCreateSeqWithArray(comm, bs, n*bs, array, vec);CHKERRQ(ierr);
238fb1bcc12SMatthew G. Knepley   } else {
239fb1bcc12SMatthew G. Knepley     ierr = VecCreateMPIWithArray(comm, bs, n*bs, PETSC_DETERMINE, array, vec);CHKERRQ(ierr);
240fb1bcc12SMatthew G. Knepley   }
241fb1bcc12SMatthew G. Knepley   ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarmSharedField_%s", fieldname);CHKERRQ(ierr);
242fb1bcc12SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) *vec, name);CHKERRQ(ierr);
243fb1bcc12SMatthew G. Knepley 
244fb1bcc12SMatthew G. Knepley   /* Set guard */
245fb1bcc12SMatthew G. Knepley   ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarm_VecFieldInPlace_%s", fieldname);CHKERRQ(ierr);
246fb1bcc12SMatthew G. Knepley   ierr = PetscObjectComposeFunction((PetscObject) *vec, name, DMSwarmDestroyVectorFromField_Private);CHKERRQ(ierr);
24774d0cae8SMatthew G. Knepley 
24874d0cae8SMatthew G. Knepley   ierr = VecSetDM(*vec, dm);CHKERRQ(ierr);
24974d0cae8SMatthew G. Knepley   ierr = VecSetOperation(*vec, VECOP_VIEW, (void (*)(void)) VecView_Swarm);CHKERRQ(ierr);
250fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
251fb1bcc12SMatthew G. Knepley }
252fb1bcc12SMatthew G. Knepley 
2530643ed39SMatthew G. Knepley /* This creates a "mass matrix" between a finite element and particle space. If a finite element interpolant is given by
2540643ed39SMatthew G. Knepley 
2550643ed39SMatthew G. Knepley      \hat f = \sum_i f_i \phi_i
2560643ed39SMatthew G. Knepley 
2570643ed39SMatthew G. Knepley    and a particle function is given by
2580643ed39SMatthew G. Knepley 
2590643ed39SMatthew G. Knepley      f = \sum_i w_i \delta(x - x_i)
2600643ed39SMatthew G. Knepley 
2610643ed39SMatthew G. Knepley    then we want to require that
2620643ed39SMatthew G. Knepley 
2630643ed39SMatthew G. Knepley      M \hat f = M_p f
2640643ed39SMatthew G. Knepley 
2650643ed39SMatthew G. Knepley    where the particle mass matrix is given by
2660643ed39SMatthew G. Knepley 
2670643ed39SMatthew G. Knepley      (M_p)_{ij} = \int \phi_i \delta(x - x_j)
2680643ed39SMatthew G. Knepley 
2690643ed39SMatthew G. Knepley    The way Dave May does particles, they amount to quadratue weights rather than delta functions, so he has |J| is in
2700643ed39SMatthew G. Knepley    his integral. We allow this with the boolean flag.
2710643ed39SMatthew G. Knepley */
2720643ed39SMatthew G. Knepley static PetscErrorCode DMSwarmComputeMassMatrix_Private(DM dmc, DM dmf, Mat mass, PetscBool useDeltaFunction, void *ctx)
27383c47955SMatthew G. Knepley {
27483c47955SMatthew G. Knepley   const char    *name = "Mass Matrix";
2750643ed39SMatthew G. Knepley   MPI_Comm       comm;
27683c47955SMatthew G. Knepley   PetscDS        prob;
27783c47955SMatthew G. Knepley   PetscSection   fsection, globalFSection;
278e8f14785SLisandro Dalcin   PetscHSetIJ    ht;
2790643ed39SMatthew G. Knepley   PetscLayout    rLayout, colLayout;
28083c47955SMatthew G. Knepley   PetscInt      *dnz, *onz;
281adb2528bSMark Adams   PetscInt       locRows, locCols, rStart, colStart, colEnd, *rowIDXs;
2820643ed39SMatthew G. Knepley   PetscReal     *xi, *v0, *J, *invJ, detJ = 1.0, v0ref[3] = {-1.0, -1.0, -1.0};
28383c47955SMatthew G. Knepley   PetscScalar   *elemMat;
2840643ed39SMatthew G. Knepley   PetscInt       dim, Nf, field, cStart, cEnd, cell, totDim, maxC = 0;
28583c47955SMatthew G. Knepley   PetscErrorCode ierr;
28683c47955SMatthew G. Knepley 
28783c47955SMatthew G. Knepley   PetscFunctionBegin;
2880643ed39SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) mass, &comm);CHKERRQ(ierr);
28983c47955SMatthew G. Knepley   ierr = DMGetCoordinateDim(dmf, &dim);CHKERRQ(ierr);
29083c47955SMatthew G. Knepley   ierr = DMGetDS(dmf, &prob);CHKERRQ(ierr);
29183c47955SMatthew G. Knepley   ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr);
2920643ed39SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr);
29383c47955SMatthew G. Knepley   ierr = PetscMalloc3(dim, &v0, dim*dim, &J, dim*dim,&invJ);CHKERRQ(ierr);
29492fd8e1eSJed Brown   ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);
295e87a4003SBarry Smith   ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);
29683c47955SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd);CHKERRQ(ierr);
2970643ed39SMatthew G. Knepley   ierr = MatGetLocalSize(mass, &locRows, &locCols);CHKERRQ(ierr);
29883c47955SMatthew G. Knepley 
2990643ed39SMatthew G. Knepley   ierr = PetscLayoutCreate(comm, &colLayout);CHKERRQ(ierr);
3000643ed39SMatthew G. Knepley   ierr = PetscLayoutSetLocalSize(colLayout, locCols);CHKERRQ(ierr);
3010643ed39SMatthew G. Knepley   ierr = PetscLayoutSetBlockSize(colLayout, 1);CHKERRQ(ierr);
3020643ed39SMatthew G. Knepley   ierr = PetscLayoutSetUp(colLayout);CHKERRQ(ierr);
3030643ed39SMatthew G. Knepley   ierr = PetscLayoutGetRange(colLayout, &colStart, &colEnd);CHKERRQ(ierr);
3040643ed39SMatthew G. Knepley   ierr = PetscLayoutDestroy(&colLayout);CHKERRQ(ierr);
3050643ed39SMatthew G. Knepley 
3060643ed39SMatthew G. Knepley   ierr = PetscLayoutCreate(comm, &rLayout);CHKERRQ(ierr);
30783c47955SMatthew G. Knepley   ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr);
30883c47955SMatthew G. Knepley   ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr);
30983c47955SMatthew G. Knepley   ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr);
3100643ed39SMatthew G. Knepley   ierr = PetscLayoutGetRange(rLayout, &rStart, NULL);CHKERRQ(ierr);
31183c47955SMatthew G. Knepley   ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr);
3120643ed39SMatthew G. Knepley 
31383c47955SMatthew G. Knepley   ierr = PetscCalloc2(locRows, &dnz, locRows, &onz);CHKERRQ(ierr);
314e8f14785SLisandro Dalcin   ierr = PetscHSetIJCreate(&ht);CHKERRQ(ierr);
31553e60ab4SJoseph Pusztay 
3160643ed39SMatthew G. Knepley   ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);
3170643ed39SMatthew G. Knepley   /* count non-zeros */
3180643ed39SMatthew G. Knepley   ierr = DMSwarmSortGetAccess(dmc);CHKERRQ(ierr);
31983c47955SMatthew G. Knepley   for (field = 0; field < Nf; ++field) {
32083c47955SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
3210643ed39SMatthew G. Knepley       PetscInt  c, i;
3220643ed39SMatthew G. Knepley       PetscInt *findices,   *cindices; /* fine is vertices, coarse is particles */
32383c47955SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
32483c47955SMatthew G. Knepley 
32571f0bbf9SMatthew G. Knepley       ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL);CHKERRQ(ierr);
326fc7c92abSMatthew G. Knepley       ierr = DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices);CHKERRQ(ierr);
327fc7c92abSMatthew G. Knepley       maxC = PetscMax(maxC, numCIndices);
32883c47955SMatthew G. Knepley       {
329e8f14785SLisandro Dalcin         PetscHashIJKey key;
330e8f14785SLisandro Dalcin         PetscBool      missing;
33183c47955SMatthew G. Knepley         for (i = 0; i < numFIndices; ++i) {
332adb2528bSMark Adams           key.j = findices[i]; /* global column (from Plex) */
333adb2528bSMark Adams           if (key.j >= 0) {
33483c47955SMatthew G. Knepley             /* Get indices for coarse elements */
33583c47955SMatthew G. Knepley             for (c = 0; c < numCIndices; ++c) {
336adb2528bSMark Adams               key.i = cindices[c] + rStart; /* global cols (from Swarm) */
337adb2528bSMark Adams               if (key.i < 0) continue;
338e8f14785SLisandro Dalcin               ierr = PetscHSetIJQueryAdd(ht, key, &missing);CHKERRQ(ierr);
33983c47955SMatthew G. Knepley               if (missing) {
3400643ed39SMatthew G. Knepley                 if ((key.j >= colStart) && (key.j < colEnd)) ++dnz[key.i - rStart];
341e8f14785SLisandro Dalcin                 else                                         ++onz[key.i - rStart];
3420643ed39SMatthew G. Knepley               } else SETERRQ2(PetscObjectComm((PetscObject) dmf), PETSC_ERR_SUP, "Set new value at %D,%D", key.i, key.j);
34383c47955SMatthew G. Knepley             }
344fc7c92abSMatthew G. Knepley           }
345fc7c92abSMatthew G. Knepley         }
34683c47955SMatthew G. Knepley         ierr = PetscFree(cindices);CHKERRQ(ierr);
34783c47955SMatthew G. Knepley       }
34871f0bbf9SMatthew G. Knepley       ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL);CHKERRQ(ierr);
34983c47955SMatthew G. Knepley     }
35083c47955SMatthew G. Knepley   }
351e8f14785SLisandro Dalcin   ierr = PetscHSetIJDestroy(&ht);CHKERRQ(ierr);
35283c47955SMatthew G. Knepley   ierr = MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL);CHKERRQ(ierr);
35383c47955SMatthew G. Knepley   ierr = MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE);CHKERRQ(ierr);
35483c47955SMatthew G. Knepley   ierr = PetscFree2(dnz, onz);CHKERRQ(ierr);
355adb2528bSMark Adams   ierr = PetscMalloc3(maxC*totDim, &elemMat, maxC, &rowIDXs, maxC*dim, &xi);CHKERRQ(ierr);
35683c47955SMatthew G. Knepley   for (field = 0; field < Nf; ++field) {
357ef0bb6c7SMatthew G. Knepley     PetscTabulation Tcoarse;
35883c47955SMatthew G. Knepley     PetscObject       obj;
359ef0bb6c7SMatthew G. Knepley     PetscReal        *coords;
3600643ed39SMatthew G. Knepley     PetscInt          Nc, i;
36183c47955SMatthew G. Knepley 
36283c47955SMatthew G. Knepley     ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr);
3630643ed39SMatthew G. Knepley     ierr = PetscFEGetNumComponents((PetscFE) obj, &Nc);CHKERRQ(ierr);
3640643ed39SMatthew G. Knepley     if (Nc != 1) SETERRQ1(PetscObjectComm((PetscObject) dmf), PETSC_ERR_SUP, "Can only interpolate a scalar field from particles, Nc = %D", Nc);
3650643ed39SMatthew G. Knepley     ierr = DMSwarmGetField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **) &coords);CHKERRQ(ierr);
36683c47955SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
36783c47955SMatthew G. Knepley       PetscInt *findices  , *cindices;
36883c47955SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
3690643ed39SMatthew G. Knepley       PetscInt  p, c;
37083c47955SMatthew G. Knepley 
3710643ed39SMatthew G. Knepley       /* TODO: Use DMField instead of assuming affine */
37283c47955SMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr);
37371f0bbf9SMatthew G. Knepley       ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL);CHKERRQ(ierr);
37483c47955SMatthew G. Knepley       ierr = DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices);CHKERRQ(ierr);
3750643ed39SMatthew G. Knepley       for (p = 0; p < numCIndices; ++p) {
3760643ed39SMatthew G. Knepley         CoordinatesRealToRef(dim, dim, v0ref, v0, invJ, &coords[cindices[p]*dim], &xi[p*dim]);
3770643ed39SMatthew G. Knepley       }
378ef0bb6c7SMatthew G. Knepley       ierr = PetscFECreateTabulation((PetscFE) obj, 1, numCIndices, xi, 0, &Tcoarse);CHKERRQ(ierr);
37983c47955SMatthew G. Knepley       /* Get elemMat entries by multiplying by weight */
380580bdb30SBarry Smith       ierr = PetscArrayzero(elemMat, numCIndices*totDim);CHKERRQ(ierr);
38183c47955SMatthew G. Knepley       for (i = 0; i < numFIndices; ++i) {
3820643ed39SMatthew G. Knepley         for (p = 0; p < numCIndices; ++p) {
3830643ed39SMatthew G. Knepley           for (c = 0; c < Nc; ++c) {
3840643ed39SMatthew G. Knepley             /* B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c */
385ef0bb6c7SMatthew G. Knepley             elemMat[p*numFIndices+i] += Tcoarse->T[0][(p*numFIndices + i)*Nc + c]*(useDeltaFunction ? 1.0 : detJ);
38683c47955SMatthew G. Knepley           }
3870643ed39SMatthew G. Knepley         }
3880643ed39SMatthew G. Knepley       }
389adb2528bSMark Adams       for (p = 0; p < numCIndices; ++p) rowIDXs[p] = cindices[p] + rStart;
39083c47955SMatthew G. Knepley       if (0) {ierr = DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat);CHKERRQ(ierr);}
391adb2528bSMark Adams       ierr = MatSetValues(mass, numCIndices, rowIDXs, numFIndices, findices, elemMat, ADD_VALUES);CHKERRQ(ierr);
39283c47955SMatthew G. Knepley       ierr = PetscFree(cindices);CHKERRQ(ierr);
39371f0bbf9SMatthew G. Knepley       ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL);CHKERRQ(ierr);
394ef0bb6c7SMatthew G. Knepley       ierr = PetscTabulationDestroy(&Tcoarse);CHKERRQ(ierr);
39583c47955SMatthew G. Knepley     }
3960643ed39SMatthew G. Knepley     ierr = DMSwarmRestoreField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **) &coords);CHKERRQ(ierr);
39783c47955SMatthew G. Knepley   }
398adb2528bSMark Adams   ierr = PetscFree3(elemMat, rowIDXs, xi);CHKERRQ(ierr);
39983c47955SMatthew G. Knepley   ierr = DMSwarmSortRestoreAccess(dmc);CHKERRQ(ierr);
40083c47955SMatthew G. Knepley   ierr = PetscFree3(v0, J, invJ);CHKERRQ(ierr);
40183c47955SMatthew G. Knepley   ierr = MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
40283c47955SMatthew G. Knepley   ierr = MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
40383c47955SMatthew G. Knepley   PetscFunctionReturn(0);
40483c47955SMatthew G. Knepley }
40583c47955SMatthew G. Knepley 
406adb2528bSMark Adams /* FEM cols, Particle rows */
40783c47955SMatthew G. Knepley static PetscErrorCode DMCreateMassMatrix_Swarm(DM dmCoarse, DM dmFine, Mat *mass)
40883c47955SMatthew G. Knepley {
409895a1698SMatthew G. Knepley   PetscSection   gsf;
41083c47955SMatthew G. Knepley   PetscInt       m, n;
41183c47955SMatthew G. Knepley   void          *ctx;
41283c47955SMatthew G. Knepley   PetscErrorCode ierr;
41383c47955SMatthew G. Knepley 
41483c47955SMatthew G. Knepley   PetscFunctionBegin;
415e87a4003SBarry Smith   ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr);
41683c47955SMatthew G. Knepley   ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr);
417895a1698SMatthew G. Knepley   ierr = DMSwarmGetLocalSize(dmCoarse, &n);CHKERRQ(ierr);
41883c47955SMatthew G. Knepley   ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr);
419adb2528bSMark Adams   ierr = MatSetSizes(*mass, n, m, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
42083c47955SMatthew G. Knepley   ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr);
42183c47955SMatthew G. Knepley   ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr);
42283c47955SMatthew G. Knepley 
4230643ed39SMatthew G. Knepley   ierr = DMSwarmComputeMassMatrix_Private(dmCoarse, dmFine, *mass, PETSC_TRUE, ctx);CHKERRQ(ierr);
42483c47955SMatthew G. Knepley   ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr);
42583c47955SMatthew G. Knepley   PetscFunctionReturn(0);
42683c47955SMatthew G. Knepley }
42783c47955SMatthew G. Knepley 
4284cc7f7b2SMatthew G. Knepley static PetscErrorCode DMSwarmComputeMassMatrixSquare_Private(DM dmc, DM dmf, Mat mass, PetscBool useDeltaFunction, void *ctx)
4294cc7f7b2SMatthew G. Knepley {
4304cc7f7b2SMatthew G. Knepley   const char    *name = "Mass Matrix Square";
4314cc7f7b2SMatthew G. Knepley   MPI_Comm       comm;
4324cc7f7b2SMatthew G. Knepley   PetscDS        prob;
4334cc7f7b2SMatthew G. Knepley   PetscSection   fsection, globalFSection;
4344cc7f7b2SMatthew G. Knepley   PetscHSetIJ    ht;
4354cc7f7b2SMatthew G. Knepley   PetscLayout    rLayout, colLayout;
4364cc7f7b2SMatthew G. Knepley   PetscInt      *dnz, *onz, *adj, depth, maxConeSize, maxSupportSize, maxAdjSize;
4374cc7f7b2SMatthew G. Knepley   PetscInt       locRows, locCols, rStart, colStart, colEnd, *rowIDXs;
4384cc7f7b2SMatthew G. Knepley   PetscReal     *xi, *v0, *J, *invJ, detJ = 1.0, v0ref[3] = {-1.0, -1.0, -1.0};
4394cc7f7b2SMatthew G. Knepley   PetscScalar   *elemMat, *elemMatSq;
4404cc7f7b2SMatthew G. Knepley   PetscInt       cdim, Nf, field, cStart, cEnd, cell, totDim, maxC = 0;
4414cc7f7b2SMatthew G. Knepley   PetscErrorCode ierr;
4424cc7f7b2SMatthew G. Knepley 
4434cc7f7b2SMatthew G. Knepley   PetscFunctionBegin;
4444cc7f7b2SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) mass, &comm);CHKERRQ(ierr);
4454cc7f7b2SMatthew G. Knepley   ierr = DMGetCoordinateDim(dmf, &cdim);CHKERRQ(ierr);
4464cc7f7b2SMatthew G. Knepley   ierr = DMGetDS(dmf, &prob);CHKERRQ(ierr);
4474cc7f7b2SMatthew G. Knepley   ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr);
4484cc7f7b2SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr);
4494cc7f7b2SMatthew G. Knepley   ierr = PetscMalloc3(cdim, &v0, cdim*cdim, &J, cdim*cdim,&invJ);CHKERRQ(ierr);
4504cc7f7b2SMatthew G. Knepley   ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);
4514cc7f7b2SMatthew G. Knepley   ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);
4524cc7f7b2SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd);CHKERRQ(ierr);
4534cc7f7b2SMatthew G. Knepley   ierr = MatGetLocalSize(mass, &locRows, &locCols);CHKERRQ(ierr);
4544cc7f7b2SMatthew G. Knepley 
4554cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutCreate(comm, &colLayout);CHKERRQ(ierr);
4564cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutSetLocalSize(colLayout, locCols);CHKERRQ(ierr);
4574cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutSetBlockSize(colLayout, 1);CHKERRQ(ierr);
4584cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutSetUp(colLayout);CHKERRQ(ierr);
4594cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutGetRange(colLayout, &colStart, &colEnd);CHKERRQ(ierr);
4604cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutDestroy(&colLayout);CHKERRQ(ierr);
4614cc7f7b2SMatthew G. Knepley 
4624cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutCreate(comm, &rLayout);CHKERRQ(ierr);
4634cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr);
4644cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr);
4654cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr);
4664cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutGetRange(rLayout, &rStart, NULL);CHKERRQ(ierr);
4674cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr);
4684cc7f7b2SMatthew G. Knepley 
4694cc7f7b2SMatthew G. Knepley   ierr = DMPlexGetDepth(dmf, &depth);CHKERRQ(ierr);
4704cc7f7b2SMatthew G. Knepley   ierr = DMPlexGetMaxSizes(dmf, &maxConeSize, &maxSupportSize);CHKERRQ(ierr);
4714cc7f7b2SMatthew G. Knepley   maxAdjSize = PetscPowInt(maxConeSize*maxSupportSize, depth);
4724cc7f7b2SMatthew G. Knepley   ierr = PetscMalloc1(maxAdjSize, &adj);CHKERRQ(ierr);
4734cc7f7b2SMatthew G. Knepley 
4744cc7f7b2SMatthew G. Knepley   ierr = PetscCalloc2(locRows, &dnz, locRows, &onz);CHKERRQ(ierr);
4754cc7f7b2SMatthew G. Knepley   ierr = PetscHSetIJCreate(&ht);CHKERRQ(ierr);
4764cc7f7b2SMatthew G. Knepley   /* Count nonzeros
4774cc7f7b2SMatthew G. Knepley        This is just FVM++, but we cannot use the Plex P0 allocation since unknowns in a cell will not be contiguous
4784cc7f7b2SMatthew G. Knepley   */
4794cc7f7b2SMatthew G. Knepley   ierr = DMSwarmSortGetAccess(dmc);CHKERRQ(ierr);
4804cc7f7b2SMatthew G. Knepley   for (cell = cStart; cell < cEnd; ++cell) {
4814cc7f7b2SMatthew G. Knepley     PetscInt  i;
4824cc7f7b2SMatthew G. Knepley     PetscInt *cindices;
4834cc7f7b2SMatthew G. Knepley     PetscInt  numCIndices;
4844cc7f7b2SMatthew G. Knepley   #if 0
4854cc7f7b2SMatthew G. Knepley     PetscInt  adjSize = maxAdjSize, a, j;
4864cc7f7b2SMatthew G. Knepley   #endif
4874cc7f7b2SMatthew G. Knepley 
4884cc7f7b2SMatthew G. Knepley     ierr = DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices);CHKERRQ(ierr);
4894cc7f7b2SMatthew G. Knepley     maxC = PetscMax(maxC, numCIndices);
4904cc7f7b2SMatthew G. Knepley     /* Diagonal block */
4914cc7f7b2SMatthew G. Knepley     for (i = 0; i < numCIndices; ++i) {dnz[cindices[i]] += numCIndices;}
4924cc7f7b2SMatthew G. Knepley #if 0
4934cc7f7b2SMatthew G. Knepley     /* Off-diagonal blocks */
4944cc7f7b2SMatthew G. Knepley     ierr = DMPlexGetAdjacency(dmf, cell, &adjSize, &adj);CHKERRQ(ierr);
4954cc7f7b2SMatthew G. Knepley     for (a = 0; a < adjSize; ++a) {
4964cc7f7b2SMatthew G. Knepley       if (adj[a] >= cStart && adj[a] < cEnd && adj[a] != cell) {
4974cc7f7b2SMatthew G. Knepley         const PetscInt ncell = adj[a];
4984cc7f7b2SMatthew G. Knepley         PetscInt      *ncindices;
4994cc7f7b2SMatthew G. Knepley         PetscInt       numNCIndices;
5004cc7f7b2SMatthew G. Knepley 
5014cc7f7b2SMatthew G. Knepley         ierr = DMSwarmSortGetPointsPerCell(dmc, ncell, &numNCIndices, &ncindices);CHKERRQ(ierr);
5024cc7f7b2SMatthew G. Knepley         {
5034cc7f7b2SMatthew G. Knepley           PetscHashIJKey key;
5044cc7f7b2SMatthew G. Knepley           PetscBool      missing;
5054cc7f7b2SMatthew G. Knepley 
5064cc7f7b2SMatthew G. Knepley           for (i = 0; i < numCIndices; ++i) {
5074cc7f7b2SMatthew G. Knepley             key.i = cindices[i] + rStart; /* global rows (from Swarm) */
5084cc7f7b2SMatthew G. Knepley             if (key.i < 0) continue;
5094cc7f7b2SMatthew G. Knepley             for (j = 0; j < numNCIndices; ++j) {
5104cc7f7b2SMatthew G. Knepley               key.j = ncindices[j] + rStart; /* global column (from Swarm) */
5114cc7f7b2SMatthew G. Knepley               if (key.j < 0) continue;
5124cc7f7b2SMatthew G. Knepley               ierr = PetscHSetIJQueryAdd(ht, key, &missing);CHKERRQ(ierr);
5134cc7f7b2SMatthew G. Knepley               if (missing) {
5144cc7f7b2SMatthew G. Knepley                 if ((key.j >= colStart) && (key.j < colEnd)) ++dnz[key.i - rStart];
5154cc7f7b2SMatthew G. Knepley                 else                                         ++onz[key.i - rStart];
5164cc7f7b2SMatthew G. Knepley               }
5174cc7f7b2SMatthew G. Knepley             }
5184cc7f7b2SMatthew G. Knepley           }
5194cc7f7b2SMatthew G. Knepley         }
5204cc7f7b2SMatthew G. Knepley         ierr = PetscFree(ncindices);CHKERRQ(ierr);
5214cc7f7b2SMatthew G. Knepley       }
5224cc7f7b2SMatthew G. Knepley     }
5234cc7f7b2SMatthew G. Knepley #endif
5244cc7f7b2SMatthew G. Knepley     ierr = PetscFree(cindices);CHKERRQ(ierr);
5254cc7f7b2SMatthew G. Knepley   }
5264cc7f7b2SMatthew G. Knepley   ierr = PetscHSetIJDestroy(&ht);CHKERRQ(ierr);
5274cc7f7b2SMatthew G. Knepley   ierr = MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL);CHKERRQ(ierr);
5284cc7f7b2SMatthew G. Knepley   ierr = MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE);CHKERRQ(ierr);
5294cc7f7b2SMatthew G. Knepley   ierr = PetscFree2(dnz, onz);CHKERRQ(ierr);
5304cc7f7b2SMatthew G. Knepley   ierr = PetscMalloc4(maxC*totDim, &elemMat, maxC*maxC, &elemMatSq, maxC, &rowIDXs, maxC*cdim, &xi);CHKERRQ(ierr);
5314cc7f7b2SMatthew G. Knepley   /* Fill in values
5324cc7f7b2SMatthew G. Knepley        Each entry is a sum of terms \phi_i(x_p) \phi_i(x_q)
5334cc7f7b2SMatthew G. Knepley        Start just by producing block diagonal
5344cc7f7b2SMatthew G. Knepley        Could loop over adjacent cells
5354cc7f7b2SMatthew G. Knepley          Produce neighboring element matrix
5364cc7f7b2SMatthew G. Knepley          TODO Determine which columns and rows correspond to shared dual vector
5374cc7f7b2SMatthew G. Knepley          Do MatMatMult with rectangular matrices
5384cc7f7b2SMatthew G. Knepley          Insert block
5394cc7f7b2SMatthew G. Knepley   */
5404cc7f7b2SMatthew G. Knepley   for (field = 0; field < Nf; ++field) {
5414cc7f7b2SMatthew G. Knepley     PetscTabulation Tcoarse;
5424cc7f7b2SMatthew G. Knepley     PetscObject       obj;
5434cc7f7b2SMatthew G. Knepley     PetscReal        *coords;
5444cc7f7b2SMatthew G. Knepley     PetscInt          Nc, i;
5454cc7f7b2SMatthew G. Knepley 
5464cc7f7b2SMatthew G. Knepley     ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr);
5474cc7f7b2SMatthew G. Knepley     ierr = PetscFEGetNumComponents((PetscFE) obj, &Nc);CHKERRQ(ierr);
5484cc7f7b2SMatthew G. Knepley     if (Nc != 1) SETERRQ1(PetscObjectComm((PetscObject) dmf), PETSC_ERR_SUP, "Can only interpolate a scalar field from particles, Nc = %D", Nc);
5494cc7f7b2SMatthew G. Knepley     ierr = DMSwarmGetField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **) &coords);CHKERRQ(ierr);
5504cc7f7b2SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
5514cc7f7b2SMatthew G. Knepley       PetscInt *findices  , *cindices;
5524cc7f7b2SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
5534cc7f7b2SMatthew G. Knepley       PetscInt  p, c;
5544cc7f7b2SMatthew G. Knepley 
5554cc7f7b2SMatthew G. Knepley       /* TODO: Use DMField instead of assuming affine */
5564cc7f7b2SMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr);
5574cc7f7b2SMatthew G. Knepley       ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL);CHKERRQ(ierr);
5584cc7f7b2SMatthew G. Knepley       ierr = DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices);CHKERRQ(ierr);
5594cc7f7b2SMatthew G. Knepley       for (p = 0; p < numCIndices; ++p) {
5604cc7f7b2SMatthew G. Knepley         CoordinatesRealToRef(cdim, cdim, v0ref, v0, invJ, &coords[cindices[p]*cdim], &xi[p*cdim]);
5614cc7f7b2SMatthew G. Knepley       }
5624cc7f7b2SMatthew G. Knepley       ierr = PetscFECreateTabulation((PetscFE) obj, 1, numCIndices, xi, 0, &Tcoarse);CHKERRQ(ierr);
5634cc7f7b2SMatthew G. Knepley       /* Get elemMat entries by multiplying by weight */
5644cc7f7b2SMatthew G. Knepley       ierr = PetscArrayzero(elemMat, numCIndices*totDim);CHKERRQ(ierr);
5654cc7f7b2SMatthew G. Knepley       for (i = 0; i < numFIndices; ++i) {
5664cc7f7b2SMatthew G. Knepley         for (p = 0; p < numCIndices; ++p) {
5674cc7f7b2SMatthew G. Knepley           for (c = 0; c < Nc; ++c) {
5684cc7f7b2SMatthew G. Knepley             /* B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c */
5694cc7f7b2SMatthew G. Knepley             elemMat[p*numFIndices+i] += Tcoarse->T[0][(p*numFIndices + i)*Nc + c]*(useDeltaFunction ? 1.0 : detJ);
5704cc7f7b2SMatthew G. Knepley           }
5714cc7f7b2SMatthew G. Knepley         }
5724cc7f7b2SMatthew G. Knepley       }
5734cc7f7b2SMatthew G. Knepley       ierr = PetscTabulationDestroy(&Tcoarse);CHKERRQ(ierr);
5744cc7f7b2SMatthew G. Knepley       for (p = 0; p < numCIndices; ++p) rowIDXs[p] = cindices[p] + rStart;
5754cc7f7b2SMatthew G. Knepley       if (0) {ierr = DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat);CHKERRQ(ierr);}
5764cc7f7b2SMatthew G. Knepley       /* Block diagonal */
5774cc7f7b2SMatthew G. Knepley       {
5784cc7f7b2SMatthew G. Knepley         PetscBLASInt blasn, blask;
5794cc7f7b2SMatthew G. Knepley         PetscScalar  one = 1.0, zero = 0.0;
5804cc7f7b2SMatthew G. Knepley 
5814cc7f7b2SMatthew G. Knepley         ierr = PetscBLASIntCast(numCIndices, &blasn);CHKERRQ(ierr);
5824cc7f7b2SMatthew G. Knepley         ierr = PetscBLASIntCast(numFIndices, &blask);CHKERRQ(ierr);
5834cc7f7b2SMatthew G. Knepley         PetscStackCallBLAS("BLASgemm",BLASgemm_("T","N",&blasn,&blasn,&blask,&one,elemMat,&blask,elemMat,&blask,&zero,elemMatSq,&blasn));
5844cc7f7b2SMatthew G. Knepley       }
5854cc7f7b2SMatthew G. Knepley       ierr = MatSetValues(mass, numCIndices, rowIDXs, numCIndices, rowIDXs, elemMatSq, ADD_VALUES);CHKERRQ(ierr);
5864cc7f7b2SMatthew G. Knepley       /* TODO Off-diagonal */
5874cc7f7b2SMatthew G. Knepley       ierr = PetscFree(cindices);CHKERRQ(ierr);
5884cc7f7b2SMatthew G. Knepley       ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL);CHKERRQ(ierr);
5894cc7f7b2SMatthew G. Knepley     }
5904cc7f7b2SMatthew G. Knepley     ierr = DMSwarmRestoreField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **) &coords);CHKERRQ(ierr);
5914cc7f7b2SMatthew G. Knepley   }
5924cc7f7b2SMatthew G. Knepley   ierr = PetscFree4(elemMat, elemMatSq, rowIDXs, xi);CHKERRQ(ierr);
5934cc7f7b2SMatthew G. Knepley   ierr = PetscFree(adj);CHKERRQ(ierr);
5944cc7f7b2SMatthew G. Knepley   ierr = DMSwarmSortRestoreAccess(dmc);CHKERRQ(ierr);
5954cc7f7b2SMatthew G. Knepley   ierr = PetscFree3(v0, J, invJ);CHKERRQ(ierr);
5964cc7f7b2SMatthew G. Knepley   ierr = MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5974cc7f7b2SMatthew G. Knepley   ierr = MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
5984cc7f7b2SMatthew G. Knepley   PetscFunctionReturn(0);
5994cc7f7b2SMatthew G. Knepley }
6004cc7f7b2SMatthew G. Knepley 
6014cc7f7b2SMatthew G. Knepley /*@C
6024cc7f7b2SMatthew G. Knepley   DMSwarmCreateMassMatrixSquare - Creates the block-diagonal of the square, M^T_p M_p, of the particle mass matrix M_p
6034cc7f7b2SMatthew G. Knepley 
6044cc7f7b2SMatthew G. Knepley   Collective on dmCoarse
6054cc7f7b2SMatthew G. Knepley 
6064cc7f7b2SMatthew G. Knepley   Input parameters:
6074cc7f7b2SMatthew G. Knepley + dmCoarse - a DMSwarm
6084cc7f7b2SMatthew G. Knepley - dmFine   - a DMPlex
6094cc7f7b2SMatthew G. Knepley 
6104cc7f7b2SMatthew G. Knepley   Output parameter:
6114cc7f7b2SMatthew G. Knepley . mass     - the square of the particle mass matrix
6124cc7f7b2SMatthew G. Knepley 
6134cc7f7b2SMatthew G. Knepley   Level: advanced
6144cc7f7b2SMatthew G. Knepley 
6154cc7f7b2SMatthew G. Knepley   Notes:
6164cc7f7b2SMatthew G. Knepley   We only compute the block diagonal since this provides a good preconditioner and is completely local. It would be possible in the
6174cc7f7b2SMatthew G. Knepley   future to compute the full normal equations.
6184cc7f7b2SMatthew G. Knepley 
6194cc7f7b2SMatthew G. Knepley .seealso: DMCreateMassMatrix()
6204cc7f7b2SMatthew G. Knepley @*/
6214cc7f7b2SMatthew G. Knepley PetscErrorCode DMSwarmCreateMassMatrixSquare(DM dmCoarse, DM dmFine, Mat *mass)
6224cc7f7b2SMatthew G. Knepley {
6234cc7f7b2SMatthew G. Knepley   PetscInt       n;
6244cc7f7b2SMatthew G. Knepley   void          *ctx;
6254cc7f7b2SMatthew G. Knepley   PetscErrorCode ierr;
6264cc7f7b2SMatthew G. Knepley 
6274cc7f7b2SMatthew G. Knepley   PetscFunctionBegin;
6284cc7f7b2SMatthew G. Knepley   ierr = DMSwarmGetLocalSize(dmCoarse, &n);CHKERRQ(ierr);
6294cc7f7b2SMatthew G. Knepley   ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr);
6304cc7f7b2SMatthew G. Knepley   ierr = MatSetSizes(*mass, n, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
6314cc7f7b2SMatthew G. Knepley   ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr);
6324cc7f7b2SMatthew G. Knepley   ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr);
6334cc7f7b2SMatthew G. Knepley 
6344cc7f7b2SMatthew G. Knepley   ierr = DMSwarmComputeMassMatrixSquare_Private(dmCoarse, dmFine, *mass, PETSC_TRUE, ctx);CHKERRQ(ierr);
6354cc7f7b2SMatthew G. Knepley   ierr = MatViewFromOptions(*mass, NULL, "-mass_sq_mat_view");CHKERRQ(ierr);
6364cc7f7b2SMatthew G. Knepley   PetscFunctionReturn(0);
6374cc7f7b2SMatthew G. Knepley }
6384cc7f7b2SMatthew G. Knepley 
6394cc7f7b2SMatthew G. Knepley 
640fb1bcc12SMatthew G. Knepley /*@C
641d3a51819SDave May    DMSwarmCreateGlobalVectorFromField - Creates a Vec object sharing the array associated with a given field
642d3a51819SDave May 
643d083f849SBarry Smith    Collective on dm
644d3a51819SDave May 
645d3a51819SDave May    Input parameters:
64662741f57SDave May +  dm - a DMSwarm
64762741f57SDave May -  fieldname - the textual name given to a registered field
648d3a51819SDave May 
6498b8a3813SDave May    Output parameter:
650d3a51819SDave May .  vec - the vector
651d3a51819SDave May 
652d3a51819SDave May    Level: beginner
653d3a51819SDave May 
6548b8a3813SDave May    Notes:
6558b8a3813SDave May    The vector must be returned using a matching call to DMSwarmDestroyGlobalVectorFromField().
6568b8a3813SDave May 
6578b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmDestroyGlobalVectorFromField()
658d3a51819SDave May @*/
65974d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmCreateGlobalVectorFromField(DM dm,const char fieldname[],Vec *vec)
660b5bcf523SDave May {
661fb1bcc12SMatthew G. Knepley   MPI_Comm       comm = PetscObjectComm((PetscObject) dm);
662b5bcf523SDave May   PetscErrorCode ierr;
663b5bcf523SDave May 
664fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
665fb1bcc12SMatthew G. Knepley   ierr = DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec);CHKERRQ(ierr);
666b5bcf523SDave May   PetscFunctionReturn(0);
667b5bcf523SDave May }
668b5bcf523SDave May 
669d3a51819SDave May /*@C
670d3a51819SDave May    DMSwarmDestroyGlobalVectorFromField - Destroys the Vec object which share the array associated with a given field
671d3a51819SDave May 
672d083f849SBarry Smith    Collective on dm
673d3a51819SDave May 
674d3a51819SDave May    Input parameters:
67562741f57SDave May +  dm - a DMSwarm
67662741f57SDave May -  fieldname - the textual name given to a registered field
677d3a51819SDave May 
6788b8a3813SDave May    Output parameter:
679d3a51819SDave May .  vec - the vector
680d3a51819SDave May 
681d3a51819SDave May    Level: beginner
682d3a51819SDave May 
6838b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmCreateGlobalVectorFromField()
684d3a51819SDave May @*/
68574d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmDestroyGlobalVectorFromField(DM dm,const char fieldname[],Vec *vec)
686b5bcf523SDave May {
687b5bcf523SDave May   PetscErrorCode ierr;
688cc651181SDave May 
689fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
690fb1bcc12SMatthew G. Knepley   ierr = DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec);CHKERRQ(ierr);
691b5bcf523SDave May   PetscFunctionReturn(0);
692b5bcf523SDave May }
693b5bcf523SDave May 
694fb1bcc12SMatthew G. Knepley /*@C
695fb1bcc12SMatthew G. Knepley    DMSwarmCreateLocalVectorFromField - Creates a Vec object sharing the array associated with a given field
696fb1bcc12SMatthew G. Knepley 
697d083f849SBarry Smith    Collective on dm
698fb1bcc12SMatthew G. Knepley 
699fb1bcc12SMatthew G. Knepley    Input parameters:
70062741f57SDave May +  dm - a DMSwarm
70162741f57SDave May -  fieldname - the textual name given to a registered field
702fb1bcc12SMatthew G. Knepley 
7038b8a3813SDave May    Output parameter:
704fb1bcc12SMatthew G. Knepley .  vec - the vector
705fb1bcc12SMatthew G. Knepley 
706fb1bcc12SMatthew G. Knepley    Level: beginner
707fb1bcc12SMatthew G. Knepley 
7088b8a3813SDave May    Notes:
7098b8a3813SDave May    The vector must be returned using a matching call to DMSwarmDestroyLocalVectorFromField().
7108b8a3813SDave May 
7118b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmDestroyLocalVectorFromField()
712fb1bcc12SMatthew G. Knepley @*/
71374d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmCreateLocalVectorFromField(DM dm,const char fieldname[],Vec *vec)
714bbe8250bSMatthew G. Knepley {
715fb1bcc12SMatthew G. Knepley   MPI_Comm       comm = PETSC_COMM_SELF;
716bbe8250bSMatthew G. Knepley   PetscErrorCode ierr;
717bbe8250bSMatthew G. Knepley 
718fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
719fb1bcc12SMatthew G. Knepley   ierr = DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec);CHKERRQ(ierr);
720fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
721bbe8250bSMatthew G. Knepley }
722fb1bcc12SMatthew G. Knepley 
723fb1bcc12SMatthew G. Knepley /*@C
724fb1bcc12SMatthew G. Knepley    DMSwarmDestroyLocalVectorFromField - Destroys the Vec object which share the array associated with a given field
725fb1bcc12SMatthew G. Knepley 
726d083f849SBarry Smith    Collective on dm
727fb1bcc12SMatthew G. Knepley 
728fb1bcc12SMatthew G. Knepley    Input parameters:
72962741f57SDave May +  dm - a DMSwarm
73062741f57SDave May -  fieldname - the textual name given to a registered field
731fb1bcc12SMatthew G. Knepley 
7328b8a3813SDave May    Output parameter:
733fb1bcc12SMatthew G. Knepley .  vec - the vector
734fb1bcc12SMatthew G. Knepley 
735fb1bcc12SMatthew G. Knepley    Level: beginner
736fb1bcc12SMatthew G. Knepley 
7378b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmCreateLocalVectorFromField()
738fb1bcc12SMatthew G. Knepley @*/
73974d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmDestroyLocalVectorFromField(DM dm,const char fieldname[],Vec *vec)
740fb1bcc12SMatthew G. Knepley {
741fb1bcc12SMatthew G. Knepley   PetscErrorCode ierr;
742fb1bcc12SMatthew G. Knepley 
743fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
744fb1bcc12SMatthew G. Knepley   ierr = DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec);CHKERRQ(ierr);
745bbe8250bSMatthew G. Knepley   PetscFunctionReturn(0);
746bbe8250bSMatthew G. Knepley }
747bbe8250bSMatthew G. Knepley 
748b5bcf523SDave May /*
74974d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmCreateGlobalVectorFromFields(DM dm,const PetscInt nf,const char *fieldnames[],Vec *vec)
750b5bcf523SDave May {
751b5bcf523SDave May   PetscFunctionReturn(0);
752b5bcf523SDave May }
753b5bcf523SDave May 
75474d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmRestoreGlobalVectorFromFields(DM dm,Vec *vec)
755b5bcf523SDave May {
756b5bcf523SDave May   PetscFunctionReturn(0);
757b5bcf523SDave May }
758b5bcf523SDave May */
759b5bcf523SDave May 
760d3a51819SDave May /*@C
761d3a51819SDave May    DMSwarmInitializeFieldRegister - Initiates the registration of fields to a DMSwarm
762d3a51819SDave May 
763d083f849SBarry Smith    Collective on dm
764d3a51819SDave May 
765d3a51819SDave May    Input parameter:
766d3a51819SDave May .  dm - a DMSwarm
767d3a51819SDave May 
768d3a51819SDave May    Level: beginner
769d3a51819SDave May 
770d3a51819SDave May    Notes:
7718b8a3813SDave May    After all fields have been registered, you must call DMSwarmFinalizeFieldRegister().
772d3a51819SDave May 
773d3a51819SDave May .seealso: DMSwarmFinalizeFieldRegister(), DMSwarmRegisterPetscDatatypeField(),
774d3a51819SDave May  DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
775d3a51819SDave May @*/
77674d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmInitializeFieldRegister(DM dm)
7775f50eb2eSDave May {
7785f50eb2eSDave May   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
7793454631fSDave May   PetscErrorCode ierr;
7803454631fSDave May 
781521f74f9SMatthew G. Knepley   PetscFunctionBegin;
782cc651181SDave May   if (!swarm->field_registration_initialized) {
7835f50eb2eSDave May     swarm->field_registration_initialized = PETSC_TRUE;
78443f984edSMatthew G. Knepley     ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_pid,1,PETSC_INT64);CHKERRQ(ierr); /* unique identifer */
785f0cdbbbaSDave May     ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_rank,1,PETSC_INT);CHKERRQ(ierr); /* used for communication */
786cc651181SDave May   }
7875f50eb2eSDave May   PetscFunctionReturn(0);
7885f50eb2eSDave May }
7895f50eb2eSDave May 
79074d0cae8SMatthew G. Knepley /*@
791d3a51819SDave May    DMSwarmFinalizeFieldRegister - Finalizes the registration of fields to a DMSwarm
792d3a51819SDave May 
793d083f849SBarry Smith    Collective on dm
794d3a51819SDave May 
795d3a51819SDave May    Input parameter:
796d3a51819SDave May .  dm - a DMSwarm
797d3a51819SDave May 
798d3a51819SDave May    Level: beginner
799d3a51819SDave May 
800d3a51819SDave May    Notes:
80162741f57SDave May    After DMSwarmFinalizeFieldRegister() has been called, no new fields can be defined on the DMSwarm.
802d3a51819SDave May 
803d3a51819SDave May .seealso: DMSwarmInitializeFieldRegister(), DMSwarmRegisterPetscDatatypeField(),
804d3a51819SDave May  DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
805d3a51819SDave May @*/
80674d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmFinalizeFieldRegister(DM dm)
8075f50eb2eSDave May {
8085f50eb2eSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
8096845f8f5SDave May   PetscErrorCode ierr;
8106845f8f5SDave May 
811521f74f9SMatthew G. Knepley   PetscFunctionBegin;
812f0cdbbbaSDave May   if (!swarm->field_registration_finalized) {
81377048351SPatrick Sanan     ierr = DMSwarmDataBucketFinalize(swarm->db);CHKERRQ(ierr);
814f0cdbbbaSDave May   }
815f0cdbbbaSDave May   swarm->field_registration_finalized = PETSC_TRUE;
8165f50eb2eSDave May   PetscFunctionReturn(0);
8175f50eb2eSDave May }
8185f50eb2eSDave May 
81974d0cae8SMatthew G. Knepley /*@
820d3a51819SDave May    DMSwarmSetLocalSizes - Sets the length of all registered fields on the DMSwarm
821d3a51819SDave May 
822d3a51819SDave May    Not collective
823d3a51819SDave May 
824d3a51819SDave May    Input parameters:
82562741f57SDave May +  dm - a DMSwarm
826d3a51819SDave May .  nlocal - the length of each registered field
82762741f57SDave May -  buffer - the length of the buffer used to efficient dynamic re-sizing
828d3a51819SDave May 
829d3a51819SDave May    Level: beginner
830d3a51819SDave May 
831d3a51819SDave May .seealso: DMSwarmGetLocalSize()
832d3a51819SDave May @*/
83374d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmSetLocalSizes(DM dm,PetscInt nlocal,PetscInt buffer)
8345f50eb2eSDave May {
8355f50eb2eSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
8366845f8f5SDave May   PetscErrorCode ierr;
8375f50eb2eSDave May 
838521f74f9SMatthew G. Knepley   PetscFunctionBegin;
839f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_SetSizes,0,0,0,0);CHKERRQ(ierr);
84077048351SPatrick Sanan   ierr = DMSwarmDataBucketSetSizes(swarm->db,nlocal,buffer);CHKERRQ(ierr);
841f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_SetSizes,0,0,0,0);CHKERRQ(ierr);
8425f50eb2eSDave May   PetscFunctionReturn(0);
8435f50eb2eSDave May }
8445f50eb2eSDave May 
84574d0cae8SMatthew G. Knepley /*@
846d3a51819SDave May    DMSwarmSetCellDM - Attachs a DM to a DMSwarm
847d3a51819SDave May 
848d083f849SBarry Smith    Collective on dm
849d3a51819SDave May 
850d3a51819SDave May    Input parameters:
85162741f57SDave May +  dm - a DMSwarm
85262741f57SDave May -  dmcell - the DM to attach to the DMSwarm
853d3a51819SDave May 
854d3a51819SDave May    Level: beginner
855d3a51819SDave May 
856d3a51819SDave May    Notes:
857d3a51819SDave May    The attached DM (dmcell) will be queried for point location and
8588b8a3813SDave May    neighbor MPI-rank information if DMSwarmMigrate() is called.
859d3a51819SDave May 
8608b8a3813SDave May .seealso: DMSwarmSetType(), DMSwarmGetCellDM(), DMSwarmMigrate()
861d3a51819SDave May @*/
86274d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmSetCellDM(DM dm,DM dmcell)
863b16650c8SDave May {
864b16650c8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
865521f74f9SMatthew G. Knepley 
866521f74f9SMatthew G. Knepley   PetscFunctionBegin;
867b16650c8SDave May   swarm->dmcell = dmcell;
868b16650c8SDave May   PetscFunctionReturn(0);
869b16650c8SDave May }
870b16650c8SDave May 
87174d0cae8SMatthew G. Knepley /*@
872d3a51819SDave May    DMSwarmGetCellDM - Fetches the attached cell DM
873d3a51819SDave May 
874d083f849SBarry Smith    Collective on dm
875d3a51819SDave May 
876d3a51819SDave May    Input parameter:
877d3a51819SDave May .  dm - a DMSwarm
878d3a51819SDave May 
879d3a51819SDave May    Output parameter:
880d3a51819SDave May .  dmcell - the DM which was attached to the DMSwarm
881d3a51819SDave May 
882d3a51819SDave May    Level: beginner
883d3a51819SDave May 
884d3a51819SDave May .seealso: DMSwarmSetCellDM()
885d3a51819SDave May @*/
88674d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmGetCellDM(DM dm,DM *dmcell)
887fe39f135SDave May {
888fe39f135SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
889521f74f9SMatthew G. Knepley 
890521f74f9SMatthew G. Knepley   PetscFunctionBegin;
891fe39f135SDave May   *dmcell = swarm->dmcell;
892fe39f135SDave May   PetscFunctionReturn(0);
893fe39f135SDave May }
894fe39f135SDave May 
89574d0cae8SMatthew G. Knepley /*@
896d3a51819SDave May    DMSwarmGetLocalSize - Retrives the local length of fields registered
897d3a51819SDave May 
898d3a51819SDave May    Not collective
899d3a51819SDave May 
900d3a51819SDave May    Input parameter:
901d3a51819SDave May .  dm - a DMSwarm
902d3a51819SDave May 
903d3a51819SDave May    Output parameter:
904d3a51819SDave May .  nlocal - the length of each registered field
905d3a51819SDave May 
906d3a51819SDave May    Level: beginner
907d3a51819SDave May 
9088b8a3813SDave May .seealso: DMSwarmGetSize(), DMSwarmSetLocalSizes()
909d3a51819SDave May @*/
91074d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmGetLocalSize(DM dm,PetscInt *nlocal)
911dcf43ee8SDave May {
912dcf43ee8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
913dcf43ee8SDave May   PetscErrorCode ierr;
914dcf43ee8SDave May 
915521f74f9SMatthew G. Knepley   PetscFunctionBegin;
91677048351SPatrick Sanan   if (nlocal) {ierr = DMSwarmDataBucketGetSizes(swarm->db,nlocal,NULL,NULL);CHKERRQ(ierr);}
917dcf43ee8SDave May   PetscFunctionReturn(0);
918dcf43ee8SDave May }
919dcf43ee8SDave May 
92074d0cae8SMatthew G. Knepley /*@
921d3a51819SDave May    DMSwarmGetSize - Retrives the total length of fields registered
922d3a51819SDave May 
923d083f849SBarry Smith    Collective on dm
924d3a51819SDave May 
925d3a51819SDave May    Input parameter:
926d3a51819SDave May .  dm - a DMSwarm
927d3a51819SDave May 
928d3a51819SDave May    Output parameter:
929d3a51819SDave May .  n - the total length of each registered field
930d3a51819SDave May 
931d3a51819SDave May    Level: beginner
932d3a51819SDave May 
933d3a51819SDave May    Note:
934d3a51819SDave May    This calls MPI_Allreduce upon each call (inefficient but safe)
935d3a51819SDave May 
9368b8a3813SDave May .seealso: DMSwarmGetLocalSize(), DMSwarmSetLocalSizes()
937d3a51819SDave May @*/
93874d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmGetSize(DM dm,PetscInt *n)
939dcf43ee8SDave May {
940dcf43ee8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
941dcf43ee8SDave May   PetscErrorCode ierr;
942dcf43ee8SDave May   PetscInt       nlocal,ng;
943dcf43ee8SDave May 
944521f74f9SMatthew G. Knepley   PetscFunctionBegin;
94577048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
946ffc4695bSBarry Smith   ierr = MPI_Allreduce(&nlocal,&ng,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr);
947dcf43ee8SDave May   if (n) { *n = ng; }
948dcf43ee8SDave May   PetscFunctionReturn(0);
949dcf43ee8SDave May }
950dcf43ee8SDave May 
951d3a51819SDave May /*@C
9528b8a3813SDave May    DMSwarmRegisterPetscDatatypeField - Register a field to a DMSwarm with a native PETSc data type
953d3a51819SDave May 
954d083f849SBarry Smith    Collective on dm
955d3a51819SDave May 
956d3a51819SDave May    Input parameters:
95762741f57SDave May +  dm - a DMSwarm
958d3a51819SDave May .  fieldname - the textual name to identify this field
959d3a51819SDave May .  blocksize - the number of each data type
96062741f57SDave May -  type - a valid PETSc data type (PETSC_CHAR, PETSC_SHORT, PETSC_INT, PETSC_FLOAT, PETSC_REAL, PETSC_LONG)
961d3a51819SDave May 
962d3a51819SDave May    Level: beginner
963d3a51819SDave May 
964d3a51819SDave May    Notes:
9658b8a3813SDave May    The textual name for each registered field must be unique.
966d3a51819SDave May 
967d3a51819SDave May .seealso: DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
968d3a51819SDave May @*/
96974d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmRegisterPetscDatatypeField(DM dm,const char fieldname[],PetscInt blocksize,PetscDataType type)
970b62e03f8SDave May {
9712eac95f8SDave May   PetscErrorCode ierr;
972b62e03f8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
973b62e03f8SDave May   size_t         size;
974b62e03f8SDave May 
975521f74f9SMatthew G. Knepley   PetscFunctionBegin;
9765f50eb2eSDave May   if (!swarm->field_registration_initialized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmInitializeFieldRegister() first");
9775f50eb2eSDave May   if (swarm->field_registration_finalized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Cannot register additional fields after calling DMSwarmFinalizeFieldRegister() first");
9785f50eb2eSDave May 
9795f50eb2eSDave May   if (type == PETSC_OBJECT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
9805f50eb2eSDave May   if (type == PETSC_FUNCTION) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
9815f50eb2eSDave May   if (type == PETSC_STRING) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
9825f50eb2eSDave May   if (type == PETSC_STRUCT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
9835f50eb2eSDave May   if (type == PETSC_DATATYPE_UNKNOWN) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
984b62e03f8SDave May 
9852ddcf43eSMatthew G. Knepley   ierr = PetscDataTypeGetSize(type, &size);CHKERRQ(ierr);
986b62e03f8SDave May   /* Load a specific data type into data bucket, specifying textual name and its size in bytes */
98777048351SPatrick Sanan   ierr = DMSwarmDataBucketRegisterField(swarm->db,"DMSwarmRegisterPetscDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
98852c3ed93SDave May   {
98977048351SPatrick Sanan     DMSwarmDataField gfield;
99052c3ed93SDave May 
99177048351SPatrick Sanan     ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
99277048351SPatrick Sanan     ierr = DMSwarmDataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
99352c3ed93SDave May   }
994b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = type;
995b62e03f8SDave May   PetscFunctionReturn(0);
996b62e03f8SDave May }
997b62e03f8SDave May 
998d3a51819SDave May /*@C
999d3a51819SDave May    DMSwarmRegisterUserStructField - Register a user defined struct to a DMSwarm
1000d3a51819SDave May 
1001d083f849SBarry Smith    Collective on dm
1002d3a51819SDave May 
1003d3a51819SDave May    Input parameters:
100462741f57SDave May +  dm - a DMSwarm
1005d3a51819SDave May .  fieldname - the textual name to identify this field
100662741f57SDave May -  size - the size in bytes of the user struct of each data type
1007d3a51819SDave May 
1008d3a51819SDave May    Level: beginner
1009d3a51819SDave May 
1010d3a51819SDave May    Notes:
10118b8a3813SDave May    The textual name for each registered field must be unique.
1012d3a51819SDave May 
1013d3a51819SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserDatatypeField()
1014d3a51819SDave May @*/
101574d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmRegisterUserStructField(DM dm,const char fieldname[],size_t size)
1016b62e03f8SDave May {
10172eac95f8SDave May   PetscErrorCode ierr;
1018b62e03f8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1019b62e03f8SDave May 
1020521f74f9SMatthew G. Knepley   PetscFunctionBegin;
102177048351SPatrick Sanan   ierr = DMSwarmDataBucketRegisterField(swarm->db,"DMSwarmRegisterUserStructField",fieldname,size,NULL);CHKERRQ(ierr);
1022b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_STRUCT ;
1023b62e03f8SDave May   PetscFunctionReturn(0);
1024b62e03f8SDave May }
1025b62e03f8SDave May 
1026d3a51819SDave May /*@C
1027d3a51819SDave May    DMSwarmRegisterUserDatatypeField - Register a user defined data type to a DMSwarm
1028d3a51819SDave May 
1029d083f849SBarry Smith    Collective on dm
1030d3a51819SDave May 
1031d3a51819SDave May    Input parameters:
103262741f57SDave May +  dm - a DMSwarm
1033d3a51819SDave May .  fieldname - the textual name to identify this field
1034d3a51819SDave May .  size - the size in bytes of the user data type
103562741f57SDave May -  blocksize - the number of each data type
1036d3a51819SDave May 
1037d3a51819SDave May    Level: beginner
1038d3a51819SDave May 
1039d3a51819SDave May    Notes:
10408b8a3813SDave May    The textual name for each registered field must be unique.
1041d3a51819SDave May 
1042d3a51819SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
1043d3a51819SDave May @*/
104474d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmRegisterUserDatatypeField(DM dm,const char fieldname[],size_t size,PetscInt blocksize)
1045b62e03f8SDave May {
1046b62e03f8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
10476845f8f5SDave May   PetscErrorCode ierr;
1048b62e03f8SDave May 
1049521f74f9SMatthew G. Knepley   PetscFunctionBegin;
105077048351SPatrick Sanan   ierr = DMSwarmDataBucketRegisterField(swarm->db,"DMSwarmRegisterUserDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
1051320740a0SDave May   {
105277048351SPatrick Sanan     DMSwarmDataField gfield;
1053320740a0SDave May 
105477048351SPatrick Sanan     ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
105577048351SPatrick Sanan     ierr = DMSwarmDataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
1056320740a0SDave May   }
1057b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_DATATYPE_UNKNOWN;
1058b62e03f8SDave May   PetscFunctionReturn(0);
1059b62e03f8SDave May }
1060b62e03f8SDave May 
1061d3a51819SDave May /*@C
1062d3a51819SDave May    DMSwarmGetField - Get access to the underlying array storing all entries associated with a registered field
1063d3a51819SDave May 
1064d3a51819SDave May    Not collective
1065d3a51819SDave May 
1066d3a51819SDave May    Input parameters:
106762741f57SDave May +  dm - a DMSwarm
106862741f57SDave May -  fieldname - the textual name to identify this field
1069d3a51819SDave May 
1070d3a51819SDave May    Output parameters:
107162741f57SDave May +  blocksize - the number of each data type
1072d3a51819SDave May .  type - the data type
107362741f57SDave May -  data - pointer to raw array
1074d3a51819SDave May 
1075d3a51819SDave May    Level: beginner
1076d3a51819SDave May 
1077d3a51819SDave May    Notes:
10788b8a3813SDave May    The array must be returned using a matching call to DMSwarmRestoreField().
1079d3a51819SDave May 
1080d3a51819SDave May .seealso: DMSwarmRestoreField()
1081d3a51819SDave May @*/
108274d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmGetField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
1083b62e03f8SDave May {
1084b62e03f8SDave May   DM_Swarm         *swarm = (DM_Swarm*)dm->data;
108577048351SPatrick Sanan   DMSwarmDataField gfield;
10862eac95f8SDave May   PetscErrorCode ierr;
1087b62e03f8SDave May 
1088521f74f9SMatthew G. Knepley   PetscFunctionBegin;
10893454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
109077048351SPatrick Sanan   ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
109177048351SPatrick Sanan   ierr = DMSwarmDataFieldGetAccess(gfield);CHKERRQ(ierr);
109277048351SPatrick Sanan   ierr = DMSwarmDataFieldGetEntries(gfield,data);CHKERRQ(ierr);
10931b1ea282SDave May   if (blocksize) {*blocksize = gfield->bs; }
1094b5bcf523SDave May   if (type) { *type = gfield->petsc_type; }
1095b62e03f8SDave May   PetscFunctionReturn(0);
1096b62e03f8SDave May }
1097b62e03f8SDave May 
1098d3a51819SDave May /*@C
1099d3a51819SDave May    DMSwarmRestoreField - Restore access to the underlying array storing all entries associated with a registered field
1100d3a51819SDave May 
1101d3a51819SDave May    Not collective
1102d3a51819SDave May 
1103d3a51819SDave May    Input parameters:
110462741f57SDave May +  dm - a DMSwarm
110562741f57SDave May -  fieldname - the textual name to identify this field
1106d3a51819SDave May 
1107d3a51819SDave May    Output parameters:
110862741f57SDave May +  blocksize - the number of each data type
1109d3a51819SDave May .  type - the data type
111062741f57SDave May -  data - pointer to raw array
1111d3a51819SDave May 
1112d3a51819SDave May    Level: beginner
1113d3a51819SDave May 
1114d3a51819SDave May    Notes:
11158b8a3813SDave May    The user must call DMSwarmGetField() prior to calling DMSwarmRestoreField().
1116d3a51819SDave May 
1117d3a51819SDave May .seealso: DMSwarmGetField()
1118d3a51819SDave May @*/
111974d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmRestoreField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
1120b62e03f8SDave May {
1121b62e03f8SDave May   DM_Swarm         *swarm = (DM_Swarm*)dm->data;
112277048351SPatrick Sanan   DMSwarmDataField gfield;
11232eac95f8SDave May   PetscErrorCode ierr;
1124b62e03f8SDave May 
1125521f74f9SMatthew G. Knepley   PetscFunctionBegin;
112677048351SPatrick Sanan   ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
112777048351SPatrick Sanan   ierr = DMSwarmDataFieldRestoreAccess(gfield);CHKERRQ(ierr);
1128b62e03f8SDave May   if (data) *data = NULL;
1129b62e03f8SDave May   PetscFunctionReturn(0);
1130b62e03f8SDave May }
1131b62e03f8SDave May 
113274d0cae8SMatthew G. Knepley /*@
1133d3a51819SDave May    DMSwarmAddPoint - Add space for one new point in the DMSwarm
1134d3a51819SDave May 
1135d3a51819SDave May    Not collective
1136d3a51819SDave May 
1137d3a51819SDave May    Input parameter:
1138d3a51819SDave May .  dm - a DMSwarm
1139d3a51819SDave May 
1140d3a51819SDave May    Level: beginner
1141d3a51819SDave May 
1142d3a51819SDave May    Notes:
11438b8a3813SDave May    The new point will have all fields initialized to zero.
1144d3a51819SDave May 
1145d3a51819SDave May .seealso: DMSwarmAddNPoints()
1146d3a51819SDave May @*/
114774d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmAddPoint(DM dm)
1148cb1d1399SDave May {
1149cb1d1399SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1150cb1d1399SDave May   PetscErrorCode ierr;
1151cb1d1399SDave May 
1152521f74f9SMatthew G. Knepley   PetscFunctionBegin;
11533454631fSDave May   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
1154f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
115577048351SPatrick Sanan   ierr = DMSwarmDataBucketAddPoint(swarm->db);CHKERRQ(ierr);
1156f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
1157cb1d1399SDave May   PetscFunctionReturn(0);
1158cb1d1399SDave May }
1159cb1d1399SDave May 
116074d0cae8SMatthew G. Knepley /*@
1161d3a51819SDave May    DMSwarmAddNPoints - Add space for a number of new points in the DMSwarm
1162d3a51819SDave May 
1163d3a51819SDave May    Not collective
1164d3a51819SDave May 
1165d3a51819SDave May    Input parameters:
116662741f57SDave May +  dm - a DMSwarm
116762741f57SDave May -  npoints - the number of new points to add
1168d3a51819SDave May 
1169d3a51819SDave May    Level: beginner
1170d3a51819SDave May 
1171d3a51819SDave May    Notes:
11728b8a3813SDave May    The new point will have all fields initialized to zero.
1173d3a51819SDave May 
1174d3a51819SDave May .seealso: DMSwarmAddPoint()
1175d3a51819SDave May @*/
117674d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmAddNPoints(DM dm,PetscInt npoints)
1177cb1d1399SDave May {
1178cb1d1399SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1179cb1d1399SDave May   PetscErrorCode ierr;
1180cb1d1399SDave May   PetscInt       nlocal;
1181cb1d1399SDave May 
1182521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1183f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
118477048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
1185cb1d1399SDave May   nlocal = nlocal + npoints;
118677048351SPatrick Sanan   ierr = DMSwarmDataBucketSetSizes(swarm->db,nlocal,DMSWARM_DATA_BUCKET_BUFFER_DEFAULT);CHKERRQ(ierr);
1187f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
1188cb1d1399SDave May   PetscFunctionReturn(0);
1189cb1d1399SDave May }
1190cb1d1399SDave May 
119174d0cae8SMatthew G. Knepley /*@
1192d3a51819SDave May    DMSwarmRemovePoint - Remove the last point from the DMSwarm
1193d3a51819SDave May 
1194d3a51819SDave May    Not collective
1195d3a51819SDave May 
1196d3a51819SDave May    Input parameter:
1197d3a51819SDave May .  dm - a DMSwarm
1198d3a51819SDave May 
1199d3a51819SDave May    Level: beginner
1200d3a51819SDave May 
1201d3a51819SDave May .seealso: DMSwarmRemovePointAtIndex()
1202d3a51819SDave May @*/
120374d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmRemovePoint(DM dm)
1204cb1d1399SDave May {
1205cb1d1399SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1206cb1d1399SDave May   PetscErrorCode ierr;
1207cb1d1399SDave May 
1208521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1209f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
121077048351SPatrick Sanan   ierr = DMSwarmDataBucketRemovePoint(swarm->db);CHKERRQ(ierr);
1211f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
1212cb1d1399SDave May   PetscFunctionReturn(0);
1213cb1d1399SDave May }
1214cb1d1399SDave May 
121574d0cae8SMatthew G. Knepley /*@
1216d3a51819SDave May    DMSwarmRemovePointAtIndex - Removes a specific point from the DMSwarm
1217d3a51819SDave May 
1218d3a51819SDave May    Not collective
1219d3a51819SDave May 
1220d3a51819SDave May    Input parameters:
122162741f57SDave May +  dm - a DMSwarm
122262741f57SDave May -  idx - index of point to remove
1223d3a51819SDave May 
1224d3a51819SDave May    Level: beginner
1225d3a51819SDave May 
1226d3a51819SDave May .seealso: DMSwarmRemovePoint()
1227d3a51819SDave May @*/
122874d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmRemovePointAtIndex(DM dm,PetscInt idx)
1229cb1d1399SDave May {
1230cb1d1399SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1231cb1d1399SDave May   PetscErrorCode ierr;
1232cb1d1399SDave May 
1233521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1234f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
123577048351SPatrick Sanan   ierr = DMSwarmDataBucketRemovePointAtIndex(swarm->db,idx);CHKERRQ(ierr);
1236f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
1237cb1d1399SDave May   PetscFunctionReturn(0);
1238cb1d1399SDave May }
1239b62e03f8SDave May 
124074d0cae8SMatthew G. Knepley /*@
1241ba4fc9c6SDave May    DMSwarmCopyPoint - Copy point pj to point pi in the DMSwarm
1242ba4fc9c6SDave May 
1243ba4fc9c6SDave May    Not collective
1244ba4fc9c6SDave May 
1245ba4fc9c6SDave May    Input parameters:
1246ba4fc9c6SDave May +  dm - a DMSwarm
1247ba4fc9c6SDave May .  pi - the index of the point to copy
1248ba4fc9c6SDave May -  pj - the point index where the copy should be located
1249ba4fc9c6SDave May 
1250ba4fc9c6SDave May  Level: beginner
1251ba4fc9c6SDave May 
1252ba4fc9c6SDave May .seealso: DMSwarmRemovePoint()
1253ba4fc9c6SDave May @*/
125474d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmCopyPoint(DM dm,PetscInt pi,PetscInt pj)
1255ba4fc9c6SDave May {
1256ba4fc9c6SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1257ba4fc9c6SDave May   PetscErrorCode ierr;
1258ba4fc9c6SDave May 
1259ba4fc9c6SDave May   PetscFunctionBegin;
1260ba4fc9c6SDave May   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
126177048351SPatrick Sanan   ierr = DMSwarmDataBucketCopyPoint(swarm->db,pi,swarm->db,pj);CHKERRQ(ierr);
1262ba4fc9c6SDave May   PetscFunctionReturn(0);
1263ba4fc9c6SDave May }
1264ba4fc9c6SDave May 
1265095059a4SDave May PetscErrorCode DMSwarmMigrate_Basic(DM dm,PetscBool remove_sent_points)
12663454631fSDave May {
1267dcf43ee8SDave May   PetscErrorCode ierr;
1268521f74f9SMatthew G. Knepley 
1269521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1270dcf43ee8SDave May   ierr = DMSwarmMigrate_Push_Basic(dm,remove_sent_points);CHKERRQ(ierr);
12713454631fSDave May   PetscFunctionReturn(0);
12723454631fSDave May }
12733454631fSDave May 
127474d0cae8SMatthew G. Knepley /*@
1275d3a51819SDave May    DMSwarmMigrate - Relocates points defined in the DMSwarm to other MPI-ranks
1276d3a51819SDave May 
1277d083f849SBarry Smith    Collective on dm
1278d3a51819SDave May 
1279d3a51819SDave May    Input parameters:
128062741f57SDave May +  dm - the DMSwarm
128162741f57SDave May -  remove_sent_points - flag indicating if sent points should be removed from the current MPI-rank
1282d3a51819SDave May 
1283d3a51819SDave May    Notes:
12848b8a3813SDave May    The DM will be modified to accomodate received points.
12858b8a3813SDave May    If remove_sent_points = PETSC_TRUE, any points that were sent will be removed from the DM.
12868b8a3813SDave May    Different styles of migration are supported. See DMSwarmSetMigrateType().
1287d3a51819SDave May 
1288d3a51819SDave May    Level: advanced
1289d3a51819SDave May 
1290d3a51819SDave May .seealso: DMSwarmSetMigrateType()
1291d3a51819SDave May @*/
129274d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmMigrate(DM dm,PetscBool remove_sent_points)
12933454631fSDave May {
1294f0cdbbbaSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
12953454631fSDave May   PetscErrorCode ierr;
1296f0cdbbbaSDave May 
1297521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1298ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
1299f0cdbbbaSDave May   switch (swarm->migrate_type) {
1300f0cdbbbaSDave May     case DMSWARM_MIGRATE_BASIC:
1301095059a4SDave May       ierr = DMSwarmMigrate_Basic(dm,remove_sent_points);CHKERRQ(ierr);
1302f0cdbbbaSDave May       break;
1303f0cdbbbaSDave May     case DMSWARM_MIGRATE_DMCELLNSCATTER:
1304f0cdbbbaSDave May       ierr = DMSwarmMigrate_CellDMScatter(dm,remove_sent_points);CHKERRQ(ierr);
1305f0cdbbbaSDave May       break;
1306f0cdbbbaSDave May     case DMSWARM_MIGRATE_DMCELLEXACT:
1307f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_DMCELLEXACT not implemented");
1308f0cdbbbaSDave May     case DMSWARM_MIGRATE_USER:
1309f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_USER not implemented");
1310f0cdbbbaSDave May     default:
1311f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE type unknown");
1312f0cdbbbaSDave May   }
1313ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
13143454631fSDave May   PetscFunctionReturn(0);
13153454631fSDave May }
13163454631fSDave May 
1317f0cdbbbaSDave May PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm,PetscInt *globalsize);
1318f0cdbbbaSDave May 
1319d3a51819SDave May /*
1320d3a51819SDave May  DMSwarmCollectViewCreate
1321d3a51819SDave May 
1322d3a51819SDave May  * Applies a collection method and gathers point neighbour points into dm
1323d3a51819SDave May 
1324d3a51819SDave May  Notes:
13258b8a3813SDave May  Users should call DMSwarmCollectViewDestroy() after
1326d3a51819SDave May  they have finished computations associated with the collected points
1327d3a51819SDave May */
1328d3a51819SDave May 
132974d0cae8SMatthew G. Knepley /*@
1330d3a51819SDave May    DMSwarmCollectViewCreate - Applies a collection method and gathers points
1331d3a51819SDave May    in neighbour MPI-ranks into the DMSwarm
1332d3a51819SDave May 
1333d083f849SBarry Smith    Collective on dm
1334d3a51819SDave May 
1335d3a51819SDave May    Input parameter:
1336d3a51819SDave May .  dm - the DMSwarm
1337d3a51819SDave May 
1338d3a51819SDave May    Notes:
1339d3a51819SDave May    Users should call DMSwarmCollectViewDestroy() after
1340d3a51819SDave May    they have finished computations associated with the collected points
13418b8a3813SDave May    Different collect methods are supported. See DMSwarmSetCollectType().
1342d3a51819SDave May 
1343d3a51819SDave May    Level: advanced
1344d3a51819SDave May 
1345d3a51819SDave May .seealso: DMSwarmCollectViewDestroy(), DMSwarmSetCollectType()
1346d3a51819SDave May @*/
134774d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmCollectViewCreate(DM dm)
13482712d1f2SDave May {
13492712d1f2SDave May   PetscErrorCode ierr;
13502712d1f2SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
13512712d1f2SDave May   PetscInt ng;
13522712d1f2SDave May 
1353521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1354480eef7bSDave May   if (swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView currently active");
1355480eef7bSDave May   ierr = DMSwarmGetLocalSize(dm,&ng);CHKERRQ(ierr);
1356480eef7bSDave May   switch (swarm->collect_type) {
1357f0cdbbbaSDave May 
1358480eef7bSDave May     case DMSWARM_COLLECT_BASIC:
13592712d1f2SDave May       ierr = DMSwarmMigrate_GlobalToLocal_Basic(dm,&ng);CHKERRQ(ierr);
1360480eef7bSDave May       break;
1361480eef7bSDave May     case DMSWARM_COLLECT_DMDABOUNDINGBOX:
1362f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_DMDABOUNDINGBOX not implemented");
1363480eef7bSDave May     case DMSWARM_COLLECT_GENERAL:
1364f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_GENERAL not implemented");
1365480eef7bSDave May     default:
1366f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT type unknown");
1367480eef7bSDave May   }
1368480eef7bSDave May   swarm->collect_view_active = PETSC_TRUE;
1369480eef7bSDave May   swarm->collect_view_reset_nlocal = ng;
13702712d1f2SDave May   PetscFunctionReturn(0);
13712712d1f2SDave May }
13722712d1f2SDave May 
137374d0cae8SMatthew G. Knepley /*@
1374d3a51819SDave May    DMSwarmCollectViewDestroy - Resets the DMSwarm to the size prior to calling DMSwarmCollectViewCreate()
1375d3a51819SDave May 
1376d083f849SBarry Smith    Collective on dm
1377d3a51819SDave May 
1378d3a51819SDave May    Input parameters:
1379d3a51819SDave May .  dm - the DMSwarm
1380d3a51819SDave May 
1381d3a51819SDave May    Notes:
1382d3a51819SDave May    Users should call DMSwarmCollectViewCreate() before this function is called.
1383d3a51819SDave May 
1384d3a51819SDave May    Level: advanced
1385d3a51819SDave May 
1386d3a51819SDave May .seealso: DMSwarmCollectViewCreate(), DMSwarmSetCollectType()
1387d3a51819SDave May @*/
138874d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmCollectViewDestroy(DM dm)
13892712d1f2SDave May {
13902712d1f2SDave May   PetscErrorCode ierr;
13912712d1f2SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
13922712d1f2SDave May 
1393521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1394480eef7bSDave May   if (!swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView is currently not active");
1395480eef7bSDave May   ierr = DMSwarmSetLocalSizes(dm,swarm->collect_view_reset_nlocal,-1);CHKERRQ(ierr);
1396480eef7bSDave May   swarm->collect_view_active = PETSC_FALSE;
13972712d1f2SDave May   PetscFunctionReturn(0);
13982712d1f2SDave May }
13993454631fSDave May 
1400f0cdbbbaSDave May PetscErrorCode DMSwarmSetUpPIC(DM dm)
1401f0cdbbbaSDave May {
1402f0cdbbbaSDave May   PetscInt       dim;
1403f0cdbbbaSDave May   PetscErrorCode ierr;
1404f0cdbbbaSDave May 
1405521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1406f0cdbbbaSDave May   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
1407f0cdbbbaSDave May   if (dim < 1) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
1408f0cdbbbaSDave May   if (dim > 3) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
1409f0cdbbbaSDave May   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_coor,dim,PETSC_DOUBLE);CHKERRQ(ierr);
1410e2d107dbSDave May   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_cellid,1,PETSC_INT);CHKERRQ(ierr);
1411f0cdbbbaSDave May   PetscFunctionReturn(0);
1412f0cdbbbaSDave May }
1413f0cdbbbaSDave May 
141474d0cae8SMatthew G. Knepley /*@
1415*31403186SMatthew G. Knepley   DMSwarmSetPointCoordinatesRandom - Sets initial coordinates for particles in each cell
1416*31403186SMatthew G. Knepley 
1417*31403186SMatthew G. Knepley   Collective on dm
1418*31403186SMatthew G. Knepley 
1419*31403186SMatthew G. Knepley   Input parameters:
1420*31403186SMatthew G. Knepley + dm  - the DMSwarm
1421*31403186SMatthew G. Knepley - Npc - The number of particles per cell in the cell DM
1422*31403186SMatthew G. Knepley 
1423*31403186SMatthew G. Knepley   Notes:
1424*31403186SMatthew G. Knepley   The user must use DMSwarmSetCellDM() to set the cell DM first. The particles are placed randomly inside each cell. If only
1425*31403186SMatthew G. Knepley   one particle is in each cell, it is placed at the centroid.
1426*31403186SMatthew G. Knepley 
1427*31403186SMatthew G. Knepley   Level: intermediate
1428*31403186SMatthew G. Knepley 
1429*31403186SMatthew G. Knepley .seealso: DMSwarmSetCellDM()
1430*31403186SMatthew G. Knepley @*/
1431*31403186SMatthew G. Knepley PetscErrorCode DMSwarmSetPointCoordinatesRandom(DM dm, PetscInt Npc)
1432*31403186SMatthew G. Knepley {
1433*31403186SMatthew G. Knepley   DM             cdm;
1434*31403186SMatthew G. Knepley   PetscRandom    rnd;
1435*31403186SMatthew G. Knepley   DMPolytopeType ct;
1436*31403186SMatthew G. Knepley   PetscBool      simplex;
1437*31403186SMatthew G. Knepley   PetscReal     *centroid, *coords, *xi0, *v0, *J, *invJ, detJ;
1438*31403186SMatthew G. Knepley   PetscInt       dim, d, cStart, cEnd, c, p;
1439*31403186SMatthew G. Knepley   PetscErrorCode ierr;
1440*31403186SMatthew G. Knepley 
1441*31403186SMatthew G. Knepley   PetscFunctionBeginUser;
1442*31403186SMatthew G. Knepley   ierr = PetscRandomCreate(PetscObjectComm((PetscObject) dm), &rnd);CHKERRQ(ierr);
1443*31403186SMatthew G. Knepley   ierr = PetscRandomSetInterval(rnd, -1.0, 1.0);CHKERRQ(ierr);
1444*31403186SMatthew G. Knepley   ierr = PetscRandomSetType(rnd, PETSCRAND48);CHKERRQ(ierr);
1445*31403186SMatthew G. Knepley 
1446*31403186SMatthew G. Knepley   ierr = DMSwarmGetCellDM(dm, &cdm);CHKERRQ(ierr);
1447*31403186SMatthew G. Knepley   ierr = DMGetDimension(cdm, &dim);CHKERRQ(ierr);
1448*31403186SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr);
1449*31403186SMatthew G. Knepley   ierr = DMPlexGetCellType(cdm, cStart, &ct);CHKERRQ(ierr);
1450*31403186SMatthew G. Knepley   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE;
1451*31403186SMatthew G. Knepley 
1452*31403186SMatthew G. Knepley   ierr = PetscMalloc5(dim, &centroid, dim, &xi0, dim, &v0, dim*dim, &J, dim*dim, &invJ);CHKERRQ(ierr);
1453*31403186SMatthew G. Knepley   for (d = 0; d < dim; ++d) xi0[d] = -1.0;
1454*31403186SMatthew G. Knepley   ierr = DMSwarmGetField(dm, DMSwarmPICField_coor, NULL, NULL, (void **) &coords);CHKERRQ(ierr);
1455*31403186SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
1456*31403186SMatthew G. Knepley     if (Npc == 1) {
1457*31403186SMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFVM(cdm, c, NULL, centroid, NULL);CHKERRQ(ierr);
1458*31403186SMatthew G. Knepley       for (d = 0; d < dim; ++d) coords[c*dim+d] = centroid[d];
1459*31403186SMatthew G. Knepley     } else {
1460*31403186SMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFEM(cdm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); /* affine */
1461*31403186SMatthew G. Knepley       for (p = 0; p < Npc; ++p) {
1462*31403186SMatthew G. Knepley         const PetscInt n   = c*Npc + p;
1463*31403186SMatthew G. Knepley         PetscReal      sum = 0.0, refcoords[3];
1464*31403186SMatthew G. Knepley 
1465*31403186SMatthew G. Knepley         for (d = 0; d < dim; ++d) {
1466*31403186SMatthew G. Knepley           ierr = PetscRandomGetValueReal(rnd, &refcoords[d]);CHKERRQ(ierr);
1467*31403186SMatthew G. Knepley           sum += refcoords[d];
1468*31403186SMatthew G. Knepley         }
1469*31403186SMatthew G. Knepley         if (simplex && sum > 0.0) for (d = 0; d < dim; ++d) refcoords[d] -= PetscSqrtReal(dim)*sum;
1470*31403186SMatthew G. Knepley         CoordinatesRefToReal(dim, dim, xi0, v0, J, refcoords, &coords[n*dim]);
1471*31403186SMatthew G. Knepley       }
1472*31403186SMatthew G. Knepley     }
1473*31403186SMatthew G. Knepley   }
1474*31403186SMatthew G. Knepley   ierr = DMSwarmRestoreField(dm, DMSwarmPICField_coor, NULL, NULL, (void **) &coords);CHKERRQ(ierr);
1475*31403186SMatthew G. Knepley   ierr = PetscFree5(centroid, xi0, v0, J, invJ);CHKERRQ(ierr);
1476*31403186SMatthew G. Knepley   ierr = PetscRandomDestroy(&rnd);CHKERRQ(ierr);
1477*31403186SMatthew G. Knepley   PetscFunctionReturn(0);
1478*31403186SMatthew G. Knepley }
1479*31403186SMatthew G. Knepley 
1480*31403186SMatthew G. Knepley /*@
1481d3a51819SDave May    DMSwarmSetType - Set particular flavor of DMSwarm
1482d3a51819SDave May 
1483d083f849SBarry Smith    Collective on dm
1484d3a51819SDave May 
1485d3a51819SDave May    Input parameters:
148662741f57SDave May +  dm - the DMSwarm
148762741f57SDave May -  stype - the DMSwarm type (e.g. DMSWARM_PIC)
1488d3a51819SDave May 
1489d3a51819SDave May    Level: advanced
1490d3a51819SDave May 
1491d3a51819SDave May .seealso: DMSwarmSetMigrateType(), DMSwarmSetCollectType()
1492d3a51819SDave May @*/
149374d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmSetType(DM dm,DMSwarmType stype)
1494f0cdbbbaSDave May {
1495f0cdbbbaSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1496f0cdbbbaSDave May   PetscErrorCode ierr;
1497f0cdbbbaSDave May 
1498521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1499f0cdbbbaSDave May   swarm->swarm_type = stype;
1500f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
1501f0cdbbbaSDave May     ierr = DMSwarmSetUpPIC(dm);CHKERRQ(ierr);
1502f0cdbbbaSDave May   }
1503f0cdbbbaSDave May   PetscFunctionReturn(0);
1504f0cdbbbaSDave May }
1505f0cdbbbaSDave May 
15063454631fSDave May PetscErrorCode DMSetup_Swarm(DM dm)
15073454631fSDave May {
15083454631fSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
15093454631fSDave May   PetscErrorCode ierr;
15103454631fSDave May   PetscMPIInt    rank;
15113454631fSDave May   PetscInt       p,npoints,*rankval;
15123454631fSDave May 
1513521f74f9SMatthew G. Knepley   PetscFunctionBegin;
15143454631fSDave May   if (swarm->issetup) PetscFunctionReturn(0);
15153454631fSDave May 
15163454631fSDave May   swarm->issetup = PETSC_TRUE;
15173454631fSDave May 
1518f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
1519f0cdbbbaSDave May     /* check dmcell exists */
1520f0cdbbbaSDave May     if (!swarm->dmcell) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires you call DMSwarmSetCellDM");
1521f0cdbbbaSDave May 
1522f0cdbbbaSDave May     if (swarm->dmcell->ops->locatepointssubdomain) {
1523f0cdbbbaSDave May       /* check methods exists for exact ownership identificiation */
152477b6ec44SMatthew G. Knepley       ierr = PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->ops->LocatePointsSubdomain\n");CHKERRQ(ierr);
1525f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLEXACT;
1526f0cdbbbaSDave May     } else {
1527f0cdbbbaSDave May       /* check methods exist for point location AND rank neighbor identification */
1528f0cdbbbaSDave May       if (swarm->dmcell->ops->locatepoints) {
152977b6ec44SMatthew G. Knepley         ierr = PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->LocatePoints\n");CHKERRQ(ierr);
1530f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->locatepoints be defined");
1531f0cdbbbaSDave May 
1532f0cdbbbaSDave May       if (swarm->dmcell->ops->getneighbors) {
153377b6ec44SMatthew G. Knepley         ierr = PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->GetNeigbors\n");CHKERRQ(ierr);
1534f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->getneighbors be defined");
1535f0cdbbbaSDave May 
1536f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLNSCATTER;
1537f0cdbbbaSDave May     }
1538f0cdbbbaSDave May   }
1539f0cdbbbaSDave May 
1540f0cdbbbaSDave May   ierr = DMSwarmFinalizeFieldRegister(dm);CHKERRQ(ierr);
1541f0cdbbbaSDave May 
15423454631fSDave May   /* check some fields were registered */
15433454631fSDave May   if (swarm->db->nfields <= 2) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"At least one field user must be registered via DMSwarmRegisterXXX()");
15443454631fSDave May 
15453454631fSDave May   /* check local sizes were set */
15463454631fSDave May   if (swarm->db->L == -1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Local sizes must be set via DMSwarmSetLocalSizes()");
15473454631fSDave May 
15483454631fSDave May   /* initialize values in pid and rank placeholders */
15493454631fSDave May   /* TODO: [pid - use MPI_Scan] */
1550ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRMPI(ierr);
155177048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db,&npoints,NULL,NULL);CHKERRQ(ierr);
1552f0cdbbbaSDave May   ierr = DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
15533454631fSDave May   for (p=0; p<npoints; p++) {
15543454631fSDave May     rankval[p] = (PetscInt)rank;
15553454631fSDave May   }
1556f0cdbbbaSDave May   ierr = DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
15573454631fSDave May   PetscFunctionReturn(0);
15583454631fSDave May }
15593454631fSDave May 
1560dc5f5ce9SDave May extern PetscErrorCode DMSwarmSortDestroy(DMSwarmSort *_ctx);
1561dc5f5ce9SDave May 
156257795646SDave May PetscErrorCode DMDestroy_Swarm(DM dm)
156357795646SDave May {
156457795646SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
156557795646SDave May   PetscErrorCode ierr;
156657795646SDave May 
156757795646SDave May   PetscFunctionBegin;
156877048351SPatrick Sanan   ierr = DMSwarmDataBucketDestroy(&swarm->db);CHKERRQ(ierr);
1569dc5f5ce9SDave May   if (swarm->sort_context) {
1570dc5f5ce9SDave May     ierr = DMSwarmSortDestroy(&swarm->sort_context);CHKERRQ(ierr);
1571dc5f5ce9SDave May   }
157257795646SDave May   ierr = PetscFree(swarm);CHKERRQ(ierr);
157357795646SDave May   PetscFunctionReturn(0);
157457795646SDave May }
157557795646SDave May 
1576a9ee3421SMatthew G. Knepley PetscErrorCode DMSwarmView_Draw(DM dm, PetscViewer viewer)
1577a9ee3421SMatthew G. Knepley {
1578a9ee3421SMatthew G. Knepley   DM             cdm;
1579a9ee3421SMatthew G. Knepley   PetscDraw      draw;
1580*31403186SMatthew G. Knepley   PetscReal     *coords, oldPause, radius = 0.01;
1581a9ee3421SMatthew G. Knepley   PetscInt       Np, p, bs;
1582a9ee3421SMatthew G. Knepley   PetscErrorCode ierr;
1583a9ee3421SMatthew G. Knepley 
1584a9ee3421SMatthew G. Knepley   PetscFunctionBegin;
1585*31403186SMatthew G. Knepley   ierr = PetscOptionsGetReal(NULL, ((PetscObject) dm)->prefix, "-dm_view_swarm_radius", &radius, NULL);CHKERRQ(ierr);
1586a9ee3421SMatthew G. Knepley   ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr);
1587a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetCellDM(dm, &cdm);CHKERRQ(ierr);
1588a9ee3421SMatthew G. Knepley   ierr = PetscDrawGetPause(draw, &oldPause);CHKERRQ(ierr);
1589a9ee3421SMatthew G. Knepley   ierr = PetscDrawSetPause(draw, 0.0);CHKERRQ(ierr);
1590a9ee3421SMatthew G. Knepley   ierr = DMView(cdm, viewer);CHKERRQ(ierr);
1591a9ee3421SMatthew G. Knepley   ierr = PetscDrawSetPause(draw, oldPause);CHKERRQ(ierr);
1592a9ee3421SMatthew G. Knepley 
1593a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetLocalSize(dm, &Np);CHKERRQ(ierr);
1594a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1595a9ee3421SMatthew G. Knepley   for (p = 0; p < Np; ++p) {
1596a9ee3421SMatthew G. Knepley     const PetscInt i = p*bs;
1597a9ee3421SMatthew G. Knepley 
1598*31403186SMatthew G. Knepley     ierr = PetscDrawEllipse(draw, coords[i], coords[i+1], radius, radius, PETSC_DRAW_BLUE);CHKERRQ(ierr);
1599a9ee3421SMatthew G. Knepley   }
1600a9ee3421SMatthew G. Knepley   ierr = DMSwarmRestoreField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1601a9ee3421SMatthew G. Knepley   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
1602a9ee3421SMatthew G. Knepley   ierr = PetscDrawPause(draw);CHKERRQ(ierr);
1603a9ee3421SMatthew G. Knepley   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
1604a9ee3421SMatthew G. Knepley   PetscFunctionReturn(0);
1605a9ee3421SMatthew G. Knepley }
1606a9ee3421SMatthew G. Knepley 
16075f50eb2eSDave May PetscErrorCode DMView_Swarm(DM dm, PetscViewer viewer)
16085f50eb2eSDave May {
16095f50eb2eSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1610a9ee3421SMatthew G. Knepley   PetscBool      iascii,ibinary,ishdf5,isvtk,isdraw;
16115f50eb2eSDave May   PetscErrorCode ierr;
16125f50eb2eSDave May 
16135f50eb2eSDave May   PetscFunctionBegin;
16145f50eb2eSDave May   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
16155f50eb2eSDave May   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
16165f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
16175f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY,&ibinary);CHKERRQ(ierr);
16185f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK,   &isvtk);CHKERRQ(ierr);
16195f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
1620a9ee3421SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW,  &isdraw);CHKERRQ(ierr);
16215f50eb2eSDave May   if (iascii) {
162277048351SPatrick Sanan     ierr = DMSwarmDataBucketView(PetscObjectComm((PetscObject)dm),swarm->db,NULL,DATABUCKET_VIEW_STDOUT);CHKERRQ(ierr);
1623298827fbSBarry Smith   } else if (ibinary) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO Binary support");
16245f50eb2eSDave May #if defined(PETSC_HAVE_HDF5)
162574d0cae8SMatthew G. Knepley   else if (ishdf5) {
162674d0cae8SMatthew G. Knepley     ierr = DMSwarmView_HDF5(dm, viewer);CHKERRQ(ierr);
162774d0cae8SMatthew G. Knepley   }
16285f50eb2eSDave May #else
1629298827fbSBarry Smith   else if (ishdf5) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"HDF5 not supported. Please reconfigure using --download-hdf5");
16305f50eb2eSDave May #endif
1631298827fbSBarry Smith   else if (isvtk) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO VTK support");
1632298827fbSBarry Smith   else if (isdraw) {
1633a9ee3421SMatthew G. Knepley     ierr = DMSwarmView_Draw(dm, viewer);CHKERRQ(ierr);
16345f50eb2eSDave May   }
16355f50eb2eSDave May   PetscFunctionReturn(0);
16365f50eb2eSDave May }
16375f50eb2eSDave May 
1638d3a51819SDave May /*MC
1639d3a51819SDave May 
1640d3a51819SDave May  DMSWARM = "swarm" - A DM object used to represent arrays of data (fields) of arbitrary data type.
164162741f57SDave May  This implementation was designed for particle methods in which the underlying
1642d3a51819SDave May  data required to be represented is both (i) dynamic in length, (ii) and of arbitrary data type.
1643d3a51819SDave May 
164462741f57SDave May  User data can be represented by DMSwarm through a registering "fields".
164562741f57SDave May  To register a field, the user must provide;
164662741f57SDave May  (a) a unique name;
164762741f57SDave May  (b) the data type (or size in bytes);
164862741f57SDave May  (c) the block size of the data.
1649d3a51819SDave May 
1650d3a51819SDave May  For example, suppose the application requires a unique id, energy, momentum and density to be stored
1651c215a47eSMatthew Knepley  on a set of particles. Then the following code could be used
1652d3a51819SDave May 
165362741f57SDave May $    DMSwarmInitializeFieldRegister(dm)
165462741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"uid",1,PETSC_LONG);
165562741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"energy",1,PETSC_REAL);
165662741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"momentum",3,PETSC_REAL);
165762741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"density",1,PETSC_FLOAT);
165862741f57SDave May $    DMSwarmFinalizeFieldRegister(dm)
1659d3a51819SDave May 
1660d3a51819SDave May  The fields represented by DMSwarm are dynamic and can be re-sized at any time.
166162741f57SDave May  The only restriction imposed by DMSwarm is that all fields contain the same number of points.
1662d3a51819SDave May 
1663d3a51819SDave May  To support particle methods, "migration" techniques are provided. These methods migrate data
1664d3a51819SDave May  between MPI-ranks.
1665d3a51819SDave May 
1666d3a51819SDave May  DMSwarm supports the methods DMCreateGlobalVector() and DMCreateLocalVector().
1667d3a51819SDave May  As a DMSwarm may internally define and store values of different data types,
166862741f57SDave May  before calling DMCreateGlobalVector() or DMCreateLocalVector(), the user must inform DMSwarm which
1669d3a51819SDave May  fields should be used to define a Vec object via
1670d3a51819SDave May    DMSwarmVectorDefineField()
1671c215a47eSMatthew Knepley  The specified field can be changed at any time - thereby permitting vectors
1672c215a47eSMatthew Knepley  compatible with different fields to be created.
1673d3a51819SDave May 
167462741f57SDave May  A dual representation of fields in the DMSwarm and a Vec object is permitted via
1675d3a51819SDave May    DMSwarmCreateGlobalVectorFromField()
1676d3a51819SDave May  Here the data defining the field in the DMSwarm is shared with a Vec.
1677d3a51819SDave May  This is inherently unsafe if you alter the size of the field at any time between
1678d3a51819SDave May  calls to DMSwarmCreateGlobalVectorFromField() and DMSwarmDestroyGlobalVectorFromField().
1679cc651181SDave May  If the local size of the DMSwarm does not match the local size of the global vector
1680cc651181SDave May  when DMSwarmDestroyGlobalVectorFromField() is called, an error is thrown.
1681d3a51819SDave May 
168262741f57SDave May  Additional high-level support is provided for Particle-In-Cell methods.
168362741f57SDave May  Please refer to the man page for DMSwarmSetType().
168462741f57SDave May 
1685d3a51819SDave May  Level: beginner
1686d3a51819SDave May 
1687d3a51819SDave May .seealso: DMType, DMCreate(), DMSetType()
1688d3a51819SDave May M*/
168957795646SDave May PETSC_EXTERN PetscErrorCode DMCreate_Swarm(DM dm)
169057795646SDave May {
169157795646SDave May   DM_Swarm      *swarm;
169257795646SDave May   PetscErrorCode ierr;
169357795646SDave May 
169457795646SDave May   PetscFunctionBegin;
169557795646SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
169657795646SDave May   ierr     = PetscNewLog(dm,&swarm);CHKERRQ(ierr);
1697f0cdbbbaSDave May   dm->data = swarm;
169857795646SDave May 
169977048351SPatrick Sanan   ierr = DMSwarmDataBucketCreate(&swarm->db);CHKERRQ(ierr);
1700f0cdbbbaSDave May   ierr = DMSwarmInitializeFieldRegister(dm);CHKERRQ(ierr);
1701f0cdbbbaSDave May 
1702b5bcf523SDave May   swarm->vec_field_set = PETSC_FALSE;
17033454631fSDave May   swarm->issetup = PETSC_FALSE;
1704480eef7bSDave May   swarm->swarm_type = DMSWARM_BASIC;
1705480eef7bSDave May   swarm->migrate_type = DMSWARM_MIGRATE_BASIC;
1706480eef7bSDave May   swarm->collect_type = DMSWARM_COLLECT_BASIC;
170740c453e9SDave May   swarm->migrate_error_on_missing_point = PETSC_FALSE;
1708b62e03f8SDave May 
1709f0cdbbbaSDave May   swarm->dmcell = NULL;
1710f0cdbbbaSDave May   swarm->collect_view_active = PETSC_FALSE;
1711f0cdbbbaSDave May   swarm->collect_view_reset_nlocal = -1;
171257795646SDave May 
1713f0cdbbbaSDave May   dm->dim  = 0;
17145f50eb2eSDave May   dm->ops->view                            = DMView_Swarm;
171557795646SDave May   dm->ops->load                            = NULL;
171657795646SDave May   dm->ops->setfromoptions                  = NULL;
171757795646SDave May   dm->ops->clone                           = NULL;
17183454631fSDave May   dm->ops->setup                           = DMSetup_Swarm;
17191bb6d2a8SBarry Smith   dm->ops->createlocalsection              = NULL;
172057795646SDave May   dm->ops->createdefaultconstraints        = NULL;
1721b5bcf523SDave May   dm->ops->createglobalvector              = DMCreateGlobalVector_Swarm;
1722b5bcf523SDave May   dm->ops->createlocalvector               = DMCreateLocalVector_Swarm;
172357795646SDave May   dm->ops->getlocaltoglobalmapping         = NULL;
172457795646SDave May   dm->ops->createfieldis                   = NULL;
172557795646SDave May   dm->ops->createcoordinatedm              = NULL;
172657795646SDave May   dm->ops->getcoloring                     = NULL;
172757795646SDave May   dm->ops->creatematrix                    = NULL;
172857795646SDave May   dm->ops->createinterpolation             = NULL;
17295a84ad33SLisandro Dalcin   dm->ops->createinjection                 = NULL;
173083c47955SMatthew G. Knepley   dm->ops->createmassmatrix                = DMCreateMassMatrix_Swarm;
173157795646SDave May   dm->ops->refine                          = NULL;
173257795646SDave May   dm->ops->coarsen                         = NULL;
173357795646SDave May   dm->ops->refinehierarchy                 = NULL;
173457795646SDave May   dm->ops->coarsenhierarchy                = NULL;
173557795646SDave May   dm->ops->globaltolocalbegin              = NULL;
173657795646SDave May   dm->ops->globaltolocalend                = NULL;
173757795646SDave May   dm->ops->localtoglobalbegin              = NULL;
173857795646SDave May   dm->ops->localtoglobalend                = NULL;
173957795646SDave May   dm->ops->destroy                         = DMDestroy_Swarm;
174057795646SDave May   dm->ops->createsubdm                     = NULL;
174157795646SDave May   dm->ops->getdimpoints                    = NULL;
174257795646SDave May   dm->ops->locatepoints                    = NULL;
174357795646SDave May   PetscFunctionReturn(0);
174457795646SDave May }
1745