xref: /petsc/src/dm/impls/swarm/swarm.c (revision 4cc7f7b2dcd74fa57dff1352e067c8770f90eac0)
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>
8*4cc7f7b2SMatthew 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 
235e4fbd051SBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRQ(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 
428*4cc7f7b2SMatthew G. Knepley static PetscErrorCode DMSwarmComputeMassMatrixSquare_Private(DM dmc, DM dmf, Mat mass, PetscBool useDeltaFunction, void *ctx)
429*4cc7f7b2SMatthew G. Knepley {
430*4cc7f7b2SMatthew G. Knepley   const char    *name = "Mass Matrix Square";
431*4cc7f7b2SMatthew G. Knepley   MPI_Comm       comm;
432*4cc7f7b2SMatthew G. Knepley   PetscDS        prob;
433*4cc7f7b2SMatthew G. Knepley   PetscSection   fsection, globalFSection;
434*4cc7f7b2SMatthew G. Knepley   PetscHSetIJ    ht;
435*4cc7f7b2SMatthew G. Knepley   PetscLayout    rLayout, colLayout;
436*4cc7f7b2SMatthew G. Knepley   PetscInt      *dnz, *onz, *adj, depth, maxConeSize, maxSupportSize, maxAdjSize;
437*4cc7f7b2SMatthew G. Knepley   PetscInt       locRows, locCols, rStart, colStart, colEnd, *rowIDXs;
438*4cc7f7b2SMatthew G. Knepley   PetscReal     *xi, *v0, *J, *invJ, detJ = 1.0, v0ref[3] = {-1.0, -1.0, -1.0};
439*4cc7f7b2SMatthew G. Knepley   PetscScalar   *elemMat, *elemMatSq;
440*4cc7f7b2SMatthew G. Knepley   PetscInt       cdim, Nf, field, cStart, cEnd, cell, totDim, maxC = 0;
441*4cc7f7b2SMatthew G. Knepley   PetscErrorCode ierr;
442*4cc7f7b2SMatthew G. Knepley 
443*4cc7f7b2SMatthew G. Knepley   PetscFunctionBegin;
444*4cc7f7b2SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) mass, &comm);CHKERRQ(ierr);
445*4cc7f7b2SMatthew G. Knepley   ierr = DMGetCoordinateDim(dmf, &cdim);CHKERRQ(ierr);
446*4cc7f7b2SMatthew G. Knepley   ierr = DMGetDS(dmf, &prob);CHKERRQ(ierr);
447*4cc7f7b2SMatthew G. Knepley   ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr);
448*4cc7f7b2SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr);
449*4cc7f7b2SMatthew G. Knepley   ierr = PetscMalloc3(cdim, &v0, cdim*cdim, &J, cdim*cdim,&invJ);CHKERRQ(ierr);
450*4cc7f7b2SMatthew G. Knepley   ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);
451*4cc7f7b2SMatthew G. Knepley   ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);
452*4cc7f7b2SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd);CHKERRQ(ierr);
453*4cc7f7b2SMatthew G. Knepley   ierr = MatGetLocalSize(mass, &locRows, &locCols);CHKERRQ(ierr);
454*4cc7f7b2SMatthew G. Knepley 
455*4cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutCreate(comm, &colLayout);CHKERRQ(ierr);
456*4cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutSetLocalSize(colLayout, locCols);CHKERRQ(ierr);
457*4cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutSetBlockSize(colLayout, 1);CHKERRQ(ierr);
458*4cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutSetUp(colLayout);CHKERRQ(ierr);
459*4cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutGetRange(colLayout, &colStart, &colEnd);CHKERRQ(ierr);
460*4cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutDestroy(&colLayout);CHKERRQ(ierr);
461*4cc7f7b2SMatthew G. Knepley 
462*4cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutCreate(comm, &rLayout);CHKERRQ(ierr);
463*4cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr);
464*4cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr);
465*4cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr);
466*4cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutGetRange(rLayout, &rStart, NULL);CHKERRQ(ierr);
467*4cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr);
468*4cc7f7b2SMatthew G. Knepley 
469*4cc7f7b2SMatthew G. Knepley   ierr = DMPlexGetDepth(dmf, &depth);CHKERRQ(ierr);
470*4cc7f7b2SMatthew G. Knepley   ierr = DMPlexGetMaxSizes(dmf, &maxConeSize, &maxSupportSize);CHKERRQ(ierr);
471*4cc7f7b2SMatthew G. Knepley   maxAdjSize = PetscPowInt(maxConeSize*maxSupportSize, depth);
472*4cc7f7b2SMatthew G. Knepley   ierr = PetscMalloc1(maxAdjSize, &adj);CHKERRQ(ierr);
473*4cc7f7b2SMatthew G. Knepley 
474*4cc7f7b2SMatthew G. Knepley   ierr = PetscCalloc2(locRows, &dnz, locRows, &onz);CHKERRQ(ierr);
475*4cc7f7b2SMatthew G. Knepley   ierr = PetscHSetIJCreate(&ht);CHKERRQ(ierr);
476*4cc7f7b2SMatthew G. Knepley   /* Count nonzeros
477*4cc7f7b2SMatthew G. Knepley        This is just FVM++, but we cannot use the Plex P0 allocation since unknowns in a cell will not be contiguous
478*4cc7f7b2SMatthew G. Knepley   */
479*4cc7f7b2SMatthew G. Knepley   ierr = DMSwarmSortGetAccess(dmc);CHKERRQ(ierr);
480*4cc7f7b2SMatthew G. Knepley   for (cell = cStart; cell < cEnd; ++cell) {
481*4cc7f7b2SMatthew G. Knepley     PetscInt  i;
482*4cc7f7b2SMatthew G. Knepley     PetscInt *cindices;
483*4cc7f7b2SMatthew G. Knepley     PetscInt  numCIndices;
484*4cc7f7b2SMatthew G. Knepley   #if 0
485*4cc7f7b2SMatthew G. Knepley     PetscInt  adjSize = maxAdjSize, a, j;
486*4cc7f7b2SMatthew G. Knepley   #endif
487*4cc7f7b2SMatthew G. Knepley 
488*4cc7f7b2SMatthew G. Knepley     ierr = DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices);CHKERRQ(ierr);
489*4cc7f7b2SMatthew G. Knepley     maxC = PetscMax(maxC, numCIndices);
490*4cc7f7b2SMatthew G. Knepley     /* Diagonal block */
491*4cc7f7b2SMatthew G. Knepley     for (i = 0; i < numCIndices; ++i) {dnz[cindices[i]] += numCIndices;}
492*4cc7f7b2SMatthew G. Knepley #if 0
493*4cc7f7b2SMatthew G. Knepley     /* Off-diagonal blocks */
494*4cc7f7b2SMatthew G. Knepley     ierr = DMPlexGetAdjacency(dmf, cell, &adjSize, &adj);CHKERRQ(ierr);
495*4cc7f7b2SMatthew G. Knepley     for (a = 0; a < adjSize; ++a) {
496*4cc7f7b2SMatthew G. Knepley       if (adj[a] >= cStart && adj[a] < cEnd && adj[a] != cell) {
497*4cc7f7b2SMatthew G. Knepley         const PetscInt ncell = adj[a];
498*4cc7f7b2SMatthew G. Knepley         PetscInt      *ncindices;
499*4cc7f7b2SMatthew G. Knepley         PetscInt       numNCIndices;
500*4cc7f7b2SMatthew G. Knepley 
501*4cc7f7b2SMatthew G. Knepley         ierr = DMSwarmSortGetPointsPerCell(dmc, ncell, &numNCIndices, &ncindices);CHKERRQ(ierr);
502*4cc7f7b2SMatthew G. Knepley         {
503*4cc7f7b2SMatthew G. Knepley           PetscHashIJKey key;
504*4cc7f7b2SMatthew G. Knepley           PetscBool      missing;
505*4cc7f7b2SMatthew G. Knepley 
506*4cc7f7b2SMatthew G. Knepley           for (i = 0; i < numCIndices; ++i) {
507*4cc7f7b2SMatthew G. Knepley             key.i = cindices[i] + rStart; /* global rows (from Swarm) */
508*4cc7f7b2SMatthew G. Knepley             if (key.i < 0) continue;
509*4cc7f7b2SMatthew G. Knepley             for (j = 0; j < numNCIndices; ++j) {
510*4cc7f7b2SMatthew G. Knepley               key.j = ncindices[j] + rStart; /* global column (from Swarm) */
511*4cc7f7b2SMatthew G. Knepley               if (key.j < 0) continue;
512*4cc7f7b2SMatthew G. Knepley               ierr = PetscHSetIJQueryAdd(ht, key, &missing);CHKERRQ(ierr);
513*4cc7f7b2SMatthew G. Knepley               if (missing) {
514*4cc7f7b2SMatthew G. Knepley                 if ((key.j >= colStart) && (key.j < colEnd)) ++dnz[key.i - rStart];
515*4cc7f7b2SMatthew G. Knepley                 else                                         ++onz[key.i - rStart];
516*4cc7f7b2SMatthew G. Knepley               }
517*4cc7f7b2SMatthew G. Knepley             }
518*4cc7f7b2SMatthew G. Knepley           }
519*4cc7f7b2SMatthew G. Knepley         }
520*4cc7f7b2SMatthew G. Knepley         ierr = PetscFree(ncindices);CHKERRQ(ierr);
521*4cc7f7b2SMatthew G. Knepley       }
522*4cc7f7b2SMatthew G. Knepley     }
523*4cc7f7b2SMatthew G. Knepley #endif
524*4cc7f7b2SMatthew G. Knepley     ierr = PetscFree(cindices);CHKERRQ(ierr);
525*4cc7f7b2SMatthew G. Knepley   }
526*4cc7f7b2SMatthew G. Knepley   ierr = PetscHSetIJDestroy(&ht);CHKERRQ(ierr);
527*4cc7f7b2SMatthew G. Knepley   ierr = MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL);CHKERRQ(ierr);
528*4cc7f7b2SMatthew G. Knepley   ierr = MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE);CHKERRQ(ierr);
529*4cc7f7b2SMatthew G. Knepley   ierr = PetscFree2(dnz, onz);CHKERRQ(ierr);
530*4cc7f7b2SMatthew G. Knepley   ierr = PetscMalloc4(maxC*totDim, &elemMat, maxC*maxC, &elemMatSq, maxC, &rowIDXs, maxC*cdim, &xi);CHKERRQ(ierr);
531*4cc7f7b2SMatthew G. Knepley   /* Fill in values
532*4cc7f7b2SMatthew G. Knepley        Each entry is a sum of terms \phi_i(x_p) \phi_i(x_q)
533*4cc7f7b2SMatthew G. Knepley        Start just by producing block diagonal
534*4cc7f7b2SMatthew G. Knepley        Could loop over adjacent cells
535*4cc7f7b2SMatthew G. Knepley          Produce neighboring element matrix
536*4cc7f7b2SMatthew G. Knepley          TODO Determine which columns and rows correspond to shared dual vector
537*4cc7f7b2SMatthew G. Knepley          Do MatMatMult with rectangular matrices
538*4cc7f7b2SMatthew G. Knepley          Insert block
539*4cc7f7b2SMatthew G. Knepley   */
540*4cc7f7b2SMatthew G. Knepley   for (field = 0; field < Nf; ++field) {
541*4cc7f7b2SMatthew G. Knepley     PetscTabulation Tcoarse;
542*4cc7f7b2SMatthew G. Knepley     PetscObject       obj;
543*4cc7f7b2SMatthew G. Knepley     PetscReal        *coords;
544*4cc7f7b2SMatthew G. Knepley     PetscInt          Nc, i;
545*4cc7f7b2SMatthew G. Knepley 
546*4cc7f7b2SMatthew G. Knepley     ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr);
547*4cc7f7b2SMatthew G. Knepley     ierr = PetscFEGetNumComponents((PetscFE) obj, &Nc);CHKERRQ(ierr);
548*4cc7f7b2SMatthew G. Knepley     if (Nc != 1) SETERRQ1(PetscObjectComm((PetscObject) dmf), PETSC_ERR_SUP, "Can only interpolate a scalar field from particles, Nc = %D", Nc);
549*4cc7f7b2SMatthew G. Knepley     ierr = DMSwarmGetField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **) &coords);CHKERRQ(ierr);
550*4cc7f7b2SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
551*4cc7f7b2SMatthew G. Knepley       PetscInt *findices  , *cindices;
552*4cc7f7b2SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
553*4cc7f7b2SMatthew G. Knepley       PetscInt  p, c;
554*4cc7f7b2SMatthew G. Knepley 
555*4cc7f7b2SMatthew G. Knepley       /* TODO: Use DMField instead of assuming affine */
556*4cc7f7b2SMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr);
557*4cc7f7b2SMatthew G. Knepley       ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL);CHKERRQ(ierr);
558*4cc7f7b2SMatthew G. Knepley       ierr = DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices);CHKERRQ(ierr);
559*4cc7f7b2SMatthew G. Knepley       for (p = 0; p < numCIndices; ++p) {
560*4cc7f7b2SMatthew G. Knepley         CoordinatesRealToRef(cdim, cdim, v0ref, v0, invJ, &coords[cindices[p]*cdim], &xi[p*cdim]);
561*4cc7f7b2SMatthew G. Knepley       }
562*4cc7f7b2SMatthew G. Knepley       ierr = PetscFECreateTabulation((PetscFE) obj, 1, numCIndices, xi, 0, &Tcoarse);CHKERRQ(ierr);
563*4cc7f7b2SMatthew G. Knepley       /* Get elemMat entries by multiplying by weight */
564*4cc7f7b2SMatthew G. Knepley       ierr = PetscArrayzero(elemMat, numCIndices*totDim);CHKERRQ(ierr);
565*4cc7f7b2SMatthew G. Knepley       for (i = 0; i < numFIndices; ++i) {
566*4cc7f7b2SMatthew G. Knepley         for (p = 0; p < numCIndices; ++p) {
567*4cc7f7b2SMatthew G. Knepley           for (c = 0; c < Nc; ++c) {
568*4cc7f7b2SMatthew G. Knepley             /* B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c */
569*4cc7f7b2SMatthew G. Knepley             elemMat[p*numFIndices+i] += Tcoarse->T[0][(p*numFIndices + i)*Nc + c]*(useDeltaFunction ? 1.0 : detJ);
570*4cc7f7b2SMatthew G. Knepley           }
571*4cc7f7b2SMatthew G. Knepley         }
572*4cc7f7b2SMatthew G. Knepley       }
573*4cc7f7b2SMatthew G. Knepley       ierr = PetscTabulationDestroy(&Tcoarse);CHKERRQ(ierr);
574*4cc7f7b2SMatthew G. Knepley       for (p = 0; p < numCIndices; ++p) rowIDXs[p] = cindices[p] + rStart;
575*4cc7f7b2SMatthew G. Knepley       if (0) {ierr = DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat);CHKERRQ(ierr);}
576*4cc7f7b2SMatthew G. Knepley       /* Block diagonal */
577*4cc7f7b2SMatthew G. Knepley       {
578*4cc7f7b2SMatthew G. Knepley         PetscBLASInt blasn, blask;
579*4cc7f7b2SMatthew G. Knepley         PetscScalar  one = 1.0, zero = 0.0;
580*4cc7f7b2SMatthew G. Knepley 
581*4cc7f7b2SMatthew G. Knepley         ierr = PetscBLASIntCast(numCIndices, &blasn);CHKERRQ(ierr);
582*4cc7f7b2SMatthew G. Knepley         ierr = PetscBLASIntCast(numFIndices, &blask);CHKERRQ(ierr);
583*4cc7f7b2SMatthew G. Knepley         PetscStackCallBLAS("BLASgemm",BLASgemm_("T","N",&blasn,&blasn,&blask,&one,elemMat,&blask,elemMat,&blask,&zero,elemMatSq,&blasn));
584*4cc7f7b2SMatthew G. Knepley       }
585*4cc7f7b2SMatthew G. Knepley       ierr = MatSetValues(mass, numCIndices, rowIDXs, numCIndices, rowIDXs, elemMatSq, ADD_VALUES);CHKERRQ(ierr);
586*4cc7f7b2SMatthew G. Knepley       /* TODO Off-diagonal */
587*4cc7f7b2SMatthew G. Knepley       ierr = PetscFree(cindices);CHKERRQ(ierr);
588*4cc7f7b2SMatthew G. Knepley       ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL);CHKERRQ(ierr);
589*4cc7f7b2SMatthew G. Knepley     }
590*4cc7f7b2SMatthew G. Knepley     ierr = DMSwarmRestoreField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **) &coords);CHKERRQ(ierr);
591*4cc7f7b2SMatthew G. Knepley   }
592*4cc7f7b2SMatthew G. Knepley   ierr = PetscFree4(elemMat, elemMatSq, rowIDXs, xi);CHKERRQ(ierr);
593*4cc7f7b2SMatthew G. Knepley   ierr = PetscFree(adj);CHKERRQ(ierr);
594*4cc7f7b2SMatthew G. Knepley   ierr = DMSwarmSortRestoreAccess(dmc);CHKERRQ(ierr);
595*4cc7f7b2SMatthew G. Knepley   ierr = PetscFree3(v0, J, invJ);CHKERRQ(ierr);
596*4cc7f7b2SMatthew G. Knepley   ierr = MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
597*4cc7f7b2SMatthew G. Knepley   ierr = MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
598*4cc7f7b2SMatthew G. Knepley   PetscFunctionReturn(0);
599*4cc7f7b2SMatthew G. Knepley }
600*4cc7f7b2SMatthew G. Knepley 
601*4cc7f7b2SMatthew G. Knepley /*@C
602*4cc7f7b2SMatthew G. Knepley   DMSwarmCreateMassMatrixSquare - Creates the block-diagonal of the square, M^T_p M_p, of the particle mass matrix M_p
603*4cc7f7b2SMatthew G. Knepley 
604*4cc7f7b2SMatthew G. Knepley   Collective on dmCoarse
605*4cc7f7b2SMatthew G. Knepley 
606*4cc7f7b2SMatthew G. Knepley   Input parameters:
607*4cc7f7b2SMatthew G. Knepley + dmCoarse - a DMSwarm
608*4cc7f7b2SMatthew G. Knepley - dmFine   - a DMPlex
609*4cc7f7b2SMatthew G. Knepley 
610*4cc7f7b2SMatthew G. Knepley   Output parameter:
611*4cc7f7b2SMatthew G. Knepley . mass     - the square of the particle mass matrix
612*4cc7f7b2SMatthew G. Knepley 
613*4cc7f7b2SMatthew G. Knepley   Level: advanced
614*4cc7f7b2SMatthew G. Knepley 
615*4cc7f7b2SMatthew G. Knepley   Notes:
616*4cc7f7b2SMatthew G. Knepley   We only compute the block diagonal since this provides a good preconditioner and is completely local. It would be possible in the
617*4cc7f7b2SMatthew G. Knepley   future to compute the full normal equations.
618*4cc7f7b2SMatthew G. Knepley 
619*4cc7f7b2SMatthew G. Knepley .seealso: DMCreateMassMatrix()
620*4cc7f7b2SMatthew G. Knepley @*/
621*4cc7f7b2SMatthew G. Knepley PetscErrorCode DMSwarmCreateMassMatrixSquare(DM dmCoarse, DM dmFine, Mat *mass)
622*4cc7f7b2SMatthew G. Knepley {
623*4cc7f7b2SMatthew G. Knepley   PetscInt       n;
624*4cc7f7b2SMatthew G. Knepley   void          *ctx;
625*4cc7f7b2SMatthew G. Knepley   PetscErrorCode ierr;
626*4cc7f7b2SMatthew G. Knepley 
627*4cc7f7b2SMatthew G. Knepley   PetscFunctionBegin;
628*4cc7f7b2SMatthew G. Knepley   ierr = DMSwarmGetLocalSize(dmCoarse, &n);CHKERRQ(ierr);
629*4cc7f7b2SMatthew G. Knepley   ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr);
630*4cc7f7b2SMatthew G. Knepley   ierr = MatSetSizes(*mass, n, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
631*4cc7f7b2SMatthew G. Knepley   ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr);
632*4cc7f7b2SMatthew G. Knepley   ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr);
633*4cc7f7b2SMatthew G. Knepley 
634*4cc7f7b2SMatthew G. Knepley   ierr = DMSwarmComputeMassMatrixSquare_Private(dmCoarse, dmFine, *mass, PETSC_TRUE, ctx);CHKERRQ(ierr);
635*4cc7f7b2SMatthew G. Knepley   ierr = MatViewFromOptions(*mass, NULL, "-mass_sq_mat_view");CHKERRQ(ierr);
636*4cc7f7b2SMatthew G. Knepley   PetscFunctionReturn(0);
637*4cc7f7b2SMatthew G. Knepley }
638*4cc7f7b2SMatthew G. Knepley 
639*4cc7f7b2SMatthew 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);
946dcf43ee8SDave May   ierr = MPI_Allreduce(&nlocal,&ng,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRQ(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       break;
1309f0cdbbbaSDave May     case DMSWARM_MIGRATE_USER:
1310f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_USER not implemented");
1311f0cdbbbaSDave May       break;
1312f0cdbbbaSDave May     default:
1313f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE type unknown");
1314f0cdbbbaSDave May       break;
1315f0cdbbbaSDave May   }
1316ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
13173454631fSDave May   PetscFunctionReturn(0);
13183454631fSDave May }
13193454631fSDave May 
1320f0cdbbbaSDave May PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm,PetscInt *globalsize);
1321f0cdbbbaSDave May 
1322d3a51819SDave May /*
1323d3a51819SDave May  DMSwarmCollectViewCreate
1324d3a51819SDave May 
1325d3a51819SDave May  * Applies a collection method and gathers point neighbour points into dm
1326d3a51819SDave May 
1327d3a51819SDave May  Notes:
13288b8a3813SDave May  Users should call DMSwarmCollectViewDestroy() after
1329d3a51819SDave May  they have finished computations associated with the collected points
1330d3a51819SDave May */
1331d3a51819SDave May 
133274d0cae8SMatthew G. Knepley /*@
1333d3a51819SDave May    DMSwarmCollectViewCreate - Applies a collection method and gathers points
1334d3a51819SDave May    in neighbour MPI-ranks into the DMSwarm
1335d3a51819SDave May 
1336d083f849SBarry Smith    Collective on dm
1337d3a51819SDave May 
1338d3a51819SDave May    Input parameter:
1339d3a51819SDave May .  dm - the DMSwarm
1340d3a51819SDave May 
1341d3a51819SDave May    Notes:
1342d3a51819SDave May    Users should call DMSwarmCollectViewDestroy() after
1343d3a51819SDave May    they have finished computations associated with the collected points
13448b8a3813SDave May    Different collect methods are supported. See DMSwarmSetCollectType().
1345d3a51819SDave May 
1346d3a51819SDave May    Level: advanced
1347d3a51819SDave May 
1348d3a51819SDave May .seealso: DMSwarmCollectViewDestroy(), DMSwarmSetCollectType()
1349d3a51819SDave May @*/
135074d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmCollectViewCreate(DM dm)
13512712d1f2SDave May {
13522712d1f2SDave May   PetscErrorCode ierr;
13532712d1f2SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
13542712d1f2SDave May   PetscInt ng;
13552712d1f2SDave May 
1356521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1357480eef7bSDave May   if (swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView currently active");
1358480eef7bSDave May   ierr = DMSwarmGetLocalSize(dm,&ng);CHKERRQ(ierr);
1359480eef7bSDave May   switch (swarm->collect_type) {
1360f0cdbbbaSDave May 
1361480eef7bSDave May     case DMSWARM_COLLECT_BASIC:
13622712d1f2SDave May       ierr = DMSwarmMigrate_GlobalToLocal_Basic(dm,&ng);CHKERRQ(ierr);
1363480eef7bSDave May       break;
1364480eef7bSDave May     case DMSWARM_COLLECT_DMDABOUNDINGBOX:
1365f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_DMDABOUNDINGBOX not implemented");
1366480eef7bSDave May       break;
1367480eef7bSDave May     case DMSWARM_COLLECT_GENERAL:
1368f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_GENERAL not implemented");
1369480eef7bSDave May       break;
1370480eef7bSDave May     default:
1371f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT type unknown");
1372480eef7bSDave May       break;
1373480eef7bSDave May   }
1374480eef7bSDave May   swarm->collect_view_active = PETSC_TRUE;
1375480eef7bSDave May   swarm->collect_view_reset_nlocal = ng;
13762712d1f2SDave May   PetscFunctionReturn(0);
13772712d1f2SDave May }
13782712d1f2SDave May 
137974d0cae8SMatthew G. Knepley /*@
1380d3a51819SDave May    DMSwarmCollectViewDestroy - Resets the DMSwarm to the size prior to calling DMSwarmCollectViewCreate()
1381d3a51819SDave May 
1382d083f849SBarry Smith    Collective on dm
1383d3a51819SDave May 
1384d3a51819SDave May    Input parameters:
1385d3a51819SDave May .  dm - the DMSwarm
1386d3a51819SDave May 
1387d3a51819SDave May    Notes:
1388d3a51819SDave May    Users should call DMSwarmCollectViewCreate() before this function is called.
1389d3a51819SDave May 
1390d3a51819SDave May    Level: advanced
1391d3a51819SDave May 
1392d3a51819SDave May .seealso: DMSwarmCollectViewCreate(), DMSwarmSetCollectType()
1393d3a51819SDave May @*/
139474d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmCollectViewDestroy(DM dm)
13952712d1f2SDave May {
13962712d1f2SDave May   PetscErrorCode ierr;
13972712d1f2SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
13982712d1f2SDave May 
1399521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1400480eef7bSDave May   if (!swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView is currently not active");
1401480eef7bSDave May   ierr = DMSwarmSetLocalSizes(dm,swarm->collect_view_reset_nlocal,-1);CHKERRQ(ierr);
1402480eef7bSDave May   swarm->collect_view_active = PETSC_FALSE;
14032712d1f2SDave May   PetscFunctionReturn(0);
14042712d1f2SDave May }
14053454631fSDave May 
1406f0cdbbbaSDave May PetscErrorCode DMSwarmSetUpPIC(DM dm)
1407f0cdbbbaSDave May {
1408f0cdbbbaSDave May   PetscInt       dim;
1409f0cdbbbaSDave May   PetscErrorCode ierr;
1410f0cdbbbaSDave May 
1411521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1412f0cdbbbaSDave May   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
1413f0cdbbbaSDave May   if (dim < 1) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
1414f0cdbbbaSDave May   if (dim > 3) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
1415f0cdbbbaSDave May   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_coor,dim,PETSC_DOUBLE);CHKERRQ(ierr);
1416e2d107dbSDave May   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_cellid,1,PETSC_INT);CHKERRQ(ierr);
1417f0cdbbbaSDave May   PetscFunctionReturn(0);
1418f0cdbbbaSDave May }
1419f0cdbbbaSDave May 
142074d0cae8SMatthew G. Knepley /*@
1421d3a51819SDave May    DMSwarmSetType - Set particular flavor of DMSwarm
1422d3a51819SDave May 
1423d083f849SBarry Smith    Collective on dm
1424d3a51819SDave May 
1425d3a51819SDave May    Input parameters:
142662741f57SDave May +  dm - the DMSwarm
142762741f57SDave May -  stype - the DMSwarm type (e.g. DMSWARM_PIC)
1428d3a51819SDave May 
1429d3a51819SDave May    Level: advanced
1430d3a51819SDave May 
1431d3a51819SDave May .seealso: DMSwarmSetMigrateType(), DMSwarmSetCollectType()
1432d3a51819SDave May @*/
143374d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmSetType(DM dm,DMSwarmType stype)
1434f0cdbbbaSDave May {
1435f0cdbbbaSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1436f0cdbbbaSDave May   PetscErrorCode ierr;
1437f0cdbbbaSDave May 
1438521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1439f0cdbbbaSDave May   swarm->swarm_type = stype;
1440f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
1441f0cdbbbaSDave May     ierr = DMSwarmSetUpPIC(dm);CHKERRQ(ierr);
1442f0cdbbbaSDave May   }
1443f0cdbbbaSDave May   PetscFunctionReturn(0);
1444f0cdbbbaSDave May }
1445f0cdbbbaSDave May 
14463454631fSDave May PetscErrorCode DMSetup_Swarm(DM dm)
14473454631fSDave May {
14483454631fSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
14493454631fSDave May   PetscErrorCode ierr;
14503454631fSDave May   PetscMPIInt    rank;
14513454631fSDave May   PetscInt       p,npoints,*rankval;
14523454631fSDave May 
1453521f74f9SMatthew G. Knepley   PetscFunctionBegin;
14543454631fSDave May   if (swarm->issetup) PetscFunctionReturn(0);
14553454631fSDave May 
14563454631fSDave May   swarm->issetup = PETSC_TRUE;
14573454631fSDave May 
1458f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
1459f0cdbbbaSDave May     /* check dmcell exists */
1460f0cdbbbaSDave May     if (!swarm->dmcell) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires you call DMSwarmSetCellDM");
1461f0cdbbbaSDave May 
1462f0cdbbbaSDave May     if (swarm->dmcell->ops->locatepointssubdomain) {
1463f0cdbbbaSDave May       /* check methods exists for exact ownership identificiation */
146477b6ec44SMatthew G. Knepley       ierr = PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->ops->LocatePointsSubdomain\n");CHKERRQ(ierr);
1465f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLEXACT;
1466f0cdbbbaSDave May     } else {
1467f0cdbbbaSDave May       /* check methods exist for point location AND rank neighbor identification */
1468f0cdbbbaSDave May       if (swarm->dmcell->ops->locatepoints) {
146977b6ec44SMatthew G. Knepley         ierr = PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->LocatePoints\n");CHKERRQ(ierr);
1470f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->locatepoints be defined");
1471f0cdbbbaSDave May 
1472f0cdbbbaSDave May       if (swarm->dmcell->ops->getneighbors) {
147377b6ec44SMatthew G. Knepley         ierr = PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->GetNeigbors\n");CHKERRQ(ierr);
1474f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->getneighbors be defined");
1475f0cdbbbaSDave May 
1476f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLNSCATTER;
1477f0cdbbbaSDave May     }
1478f0cdbbbaSDave May   }
1479f0cdbbbaSDave May 
1480f0cdbbbaSDave May   ierr = DMSwarmFinalizeFieldRegister(dm);CHKERRQ(ierr);
1481f0cdbbbaSDave May 
14823454631fSDave May   /* check some fields were registered */
14833454631fSDave May   if (swarm->db->nfields <= 2) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"At least one field user must be registered via DMSwarmRegisterXXX()");
14843454631fSDave May 
14853454631fSDave May   /* check local sizes were set */
14863454631fSDave May   if (swarm->db->L == -1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Local sizes must be set via DMSwarmSetLocalSizes()");
14873454631fSDave May 
14883454631fSDave May   /* initialize values in pid and rank placeholders */
14893454631fSDave May   /* TODO: [pid - use MPI_Scan] */
14903454631fSDave May   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRQ(ierr);
149177048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db,&npoints,NULL,NULL);CHKERRQ(ierr);
1492f0cdbbbaSDave May   ierr = DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
14933454631fSDave May   for (p=0; p<npoints; p++) {
14943454631fSDave May     rankval[p] = (PetscInt)rank;
14953454631fSDave May   }
1496f0cdbbbaSDave May   ierr = DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
14973454631fSDave May   PetscFunctionReturn(0);
14983454631fSDave May }
14993454631fSDave May 
1500dc5f5ce9SDave May extern PetscErrorCode DMSwarmSortDestroy(DMSwarmSort *_ctx);
1501dc5f5ce9SDave May 
150257795646SDave May PetscErrorCode DMDestroy_Swarm(DM dm)
150357795646SDave May {
150457795646SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
150557795646SDave May   PetscErrorCode ierr;
150657795646SDave May 
150757795646SDave May   PetscFunctionBegin;
150877048351SPatrick Sanan   ierr = DMSwarmDataBucketDestroy(&swarm->db);CHKERRQ(ierr);
1509dc5f5ce9SDave May   if (swarm->sort_context) {
1510dc5f5ce9SDave May     ierr = DMSwarmSortDestroy(&swarm->sort_context);CHKERRQ(ierr);
1511dc5f5ce9SDave May   }
151257795646SDave May   ierr = PetscFree(swarm);CHKERRQ(ierr);
151357795646SDave May   PetscFunctionReturn(0);
151457795646SDave May }
151557795646SDave May 
1516a9ee3421SMatthew G. Knepley PetscErrorCode DMSwarmView_Draw(DM dm, PetscViewer viewer)
1517a9ee3421SMatthew G. Knepley {
1518a9ee3421SMatthew G. Knepley   DM             cdm;
1519a9ee3421SMatthew G. Knepley   PetscDraw      draw;
1520a9ee3421SMatthew G. Knepley   PetscReal     *coords, oldPause;
1521a9ee3421SMatthew G. Knepley   PetscInt       Np, p, bs;
1522a9ee3421SMatthew G. Knepley   PetscErrorCode ierr;
1523a9ee3421SMatthew G. Knepley 
1524a9ee3421SMatthew G. Knepley   PetscFunctionBegin;
1525a9ee3421SMatthew G. Knepley   ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr);
1526a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetCellDM(dm, &cdm);CHKERRQ(ierr);
1527a9ee3421SMatthew G. Knepley   ierr = PetscDrawGetPause(draw, &oldPause);CHKERRQ(ierr);
1528a9ee3421SMatthew G. Knepley   ierr = PetscDrawSetPause(draw, 0.0);CHKERRQ(ierr);
1529a9ee3421SMatthew G. Knepley   ierr = DMView(cdm, viewer);CHKERRQ(ierr);
1530a9ee3421SMatthew G. Knepley   ierr = PetscDrawSetPause(draw, oldPause);CHKERRQ(ierr);
1531a9ee3421SMatthew G. Knepley 
1532a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetLocalSize(dm, &Np);CHKERRQ(ierr);
1533a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1534a9ee3421SMatthew G. Knepley   for (p = 0; p < Np; ++p) {
1535a9ee3421SMatthew G. Knepley     const PetscInt i = p*bs;
1536a9ee3421SMatthew G. Knepley 
1537a9ee3421SMatthew G. Knepley     ierr = PetscDrawEllipse(draw, coords[i], coords[i+1], 0.01, 0.01, PETSC_DRAW_BLUE);CHKERRQ(ierr);
1538a9ee3421SMatthew G. Knepley   }
1539a9ee3421SMatthew G. Knepley   ierr = DMSwarmRestoreField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1540a9ee3421SMatthew G. Knepley   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
1541a9ee3421SMatthew G. Knepley   ierr = PetscDrawPause(draw);CHKERRQ(ierr);
1542a9ee3421SMatthew G. Knepley   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
1543a9ee3421SMatthew G. Knepley   PetscFunctionReturn(0);
1544a9ee3421SMatthew G. Knepley }
1545a9ee3421SMatthew G. Knepley 
15465f50eb2eSDave May PetscErrorCode DMView_Swarm(DM dm, PetscViewer viewer)
15475f50eb2eSDave May {
15485f50eb2eSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1549a9ee3421SMatthew G. Knepley   PetscBool      iascii,ibinary,ishdf5,isvtk,isdraw;
15505f50eb2eSDave May   PetscErrorCode ierr;
15515f50eb2eSDave May 
15525f50eb2eSDave May   PetscFunctionBegin;
15535f50eb2eSDave May   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
15545f50eb2eSDave May   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
15555f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
15565f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY,&ibinary);CHKERRQ(ierr);
15575f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK,   &isvtk);CHKERRQ(ierr);
15585f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
1559a9ee3421SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW,  &isdraw);CHKERRQ(ierr);
15605f50eb2eSDave May   if (iascii) {
156177048351SPatrick Sanan     ierr = DMSwarmDataBucketView(PetscObjectComm((PetscObject)dm),swarm->db,NULL,DATABUCKET_VIEW_STDOUT);CHKERRQ(ierr);
1562298827fbSBarry Smith   } else if (ibinary) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO Binary support");
15635f50eb2eSDave May #if defined(PETSC_HAVE_HDF5)
156474d0cae8SMatthew G. Knepley   else if (ishdf5) {
156574d0cae8SMatthew G. Knepley     ierr = DMSwarmView_HDF5(dm, viewer);CHKERRQ(ierr);
156674d0cae8SMatthew G. Knepley   }
15675f50eb2eSDave May #else
1568298827fbSBarry Smith   else if (ishdf5) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"HDF5 not supported. Please reconfigure using --download-hdf5");
15695f50eb2eSDave May #endif
1570298827fbSBarry Smith   else if (isvtk) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO VTK support");
1571298827fbSBarry Smith   else if (isdraw) {
1572a9ee3421SMatthew G. Knepley     ierr = DMSwarmView_Draw(dm, viewer);CHKERRQ(ierr);
15735f50eb2eSDave May   }
15745f50eb2eSDave May   PetscFunctionReturn(0);
15755f50eb2eSDave May }
15765f50eb2eSDave May 
1577d3a51819SDave May /*MC
1578d3a51819SDave May 
1579d3a51819SDave May  DMSWARM = "swarm" - A DM object used to represent arrays of data (fields) of arbitrary data type.
158062741f57SDave May  This implementation was designed for particle methods in which the underlying
1581d3a51819SDave May  data required to be represented is both (i) dynamic in length, (ii) and of arbitrary data type.
1582d3a51819SDave May 
158362741f57SDave May  User data can be represented by DMSwarm through a registering "fields".
158462741f57SDave May  To register a field, the user must provide;
158562741f57SDave May  (a) a unique name;
158662741f57SDave May  (b) the data type (or size in bytes);
158762741f57SDave May  (c) the block size of the data.
1588d3a51819SDave May 
1589d3a51819SDave May  For example, suppose the application requires a unique id, energy, momentum and density to be stored
1590c215a47eSMatthew Knepley  on a set of particles. Then the following code could be used
1591d3a51819SDave May 
159262741f57SDave May $    DMSwarmInitializeFieldRegister(dm)
159362741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"uid",1,PETSC_LONG);
159462741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"energy",1,PETSC_REAL);
159562741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"momentum",3,PETSC_REAL);
159662741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"density",1,PETSC_FLOAT);
159762741f57SDave May $    DMSwarmFinalizeFieldRegister(dm)
1598d3a51819SDave May 
1599d3a51819SDave May  The fields represented by DMSwarm are dynamic and can be re-sized at any time.
160062741f57SDave May  The only restriction imposed by DMSwarm is that all fields contain the same number of points.
1601d3a51819SDave May 
1602d3a51819SDave May  To support particle methods, "migration" techniques are provided. These methods migrate data
1603d3a51819SDave May  between MPI-ranks.
1604d3a51819SDave May 
1605d3a51819SDave May  DMSwarm supports the methods DMCreateGlobalVector() and DMCreateLocalVector().
1606d3a51819SDave May  As a DMSwarm may internally define and store values of different data types,
160762741f57SDave May  before calling DMCreateGlobalVector() or DMCreateLocalVector(), the user must inform DMSwarm which
1608d3a51819SDave May  fields should be used to define a Vec object via
1609d3a51819SDave May    DMSwarmVectorDefineField()
1610c215a47eSMatthew Knepley  The specified field can be changed at any time - thereby permitting vectors
1611c215a47eSMatthew Knepley  compatible with different fields to be created.
1612d3a51819SDave May 
161362741f57SDave May  A dual representation of fields in the DMSwarm and a Vec object is permitted via
1614d3a51819SDave May    DMSwarmCreateGlobalVectorFromField()
1615d3a51819SDave May  Here the data defining the field in the DMSwarm is shared with a Vec.
1616d3a51819SDave May  This is inherently unsafe if you alter the size of the field at any time between
1617d3a51819SDave May  calls to DMSwarmCreateGlobalVectorFromField() and DMSwarmDestroyGlobalVectorFromField().
1618cc651181SDave May  If the local size of the DMSwarm does not match the local size of the global vector
1619cc651181SDave May  when DMSwarmDestroyGlobalVectorFromField() is called, an error is thrown.
1620d3a51819SDave May 
162162741f57SDave May  Additional high-level support is provided for Particle-In-Cell methods.
162262741f57SDave May  Please refer to the man page for DMSwarmSetType().
162362741f57SDave May 
1624d3a51819SDave May  Level: beginner
1625d3a51819SDave May 
1626d3a51819SDave May .seealso: DMType, DMCreate(), DMSetType()
1627d3a51819SDave May M*/
162857795646SDave May PETSC_EXTERN PetscErrorCode DMCreate_Swarm(DM dm)
162957795646SDave May {
163057795646SDave May   DM_Swarm      *swarm;
163157795646SDave May   PetscErrorCode ierr;
163257795646SDave May 
163357795646SDave May   PetscFunctionBegin;
163457795646SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
163557795646SDave May   ierr     = PetscNewLog(dm,&swarm);CHKERRQ(ierr);
1636f0cdbbbaSDave May   dm->data = swarm;
163757795646SDave May 
163877048351SPatrick Sanan   ierr = DMSwarmDataBucketCreate(&swarm->db);CHKERRQ(ierr);
1639f0cdbbbaSDave May   ierr = DMSwarmInitializeFieldRegister(dm);CHKERRQ(ierr);
1640f0cdbbbaSDave May 
1641b5bcf523SDave May   swarm->vec_field_set = PETSC_FALSE;
16423454631fSDave May   swarm->issetup = PETSC_FALSE;
1643480eef7bSDave May   swarm->swarm_type = DMSWARM_BASIC;
1644480eef7bSDave May   swarm->migrate_type = DMSWARM_MIGRATE_BASIC;
1645480eef7bSDave May   swarm->collect_type = DMSWARM_COLLECT_BASIC;
164640c453e9SDave May   swarm->migrate_error_on_missing_point = PETSC_FALSE;
1647b62e03f8SDave May 
1648f0cdbbbaSDave May   swarm->dmcell = NULL;
1649f0cdbbbaSDave May   swarm->collect_view_active = PETSC_FALSE;
1650f0cdbbbaSDave May   swarm->collect_view_reset_nlocal = -1;
165157795646SDave May 
1652f0cdbbbaSDave May   dm->dim  = 0;
16535f50eb2eSDave May   dm->ops->view                            = DMView_Swarm;
165457795646SDave May   dm->ops->load                            = NULL;
165557795646SDave May   dm->ops->setfromoptions                  = NULL;
165657795646SDave May   dm->ops->clone                           = NULL;
16573454631fSDave May   dm->ops->setup                           = DMSetup_Swarm;
16581bb6d2a8SBarry Smith   dm->ops->createlocalsection              = NULL;
165957795646SDave May   dm->ops->createdefaultconstraints        = NULL;
1660b5bcf523SDave May   dm->ops->createglobalvector              = DMCreateGlobalVector_Swarm;
1661b5bcf523SDave May   dm->ops->createlocalvector               = DMCreateLocalVector_Swarm;
166257795646SDave May   dm->ops->getlocaltoglobalmapping         = NULL;
166357795646SDave May   dm->ops->createfieldis                   = NULL;
166457795646SDave May   dm->ops->createcoordinatedm              = NULL;
166557795646SDave May   dm->ops->getcoloring                     = NULL;
166657795646SDave May   dm->ops->creatematrix                    = NULL;
166757795646SDave May   dm->ops->createinterpolation             = NULL;
16685a84ad33SLisandro Dalcin   dm->ops->createinjection                 = NULL;
166983c47955SMatthew G. Knepley   dm->ops->createmassmatrix                = DMCreateMassMatrix_Swarm;
167057795646SDave May   dm->ops->refine                          = NULL;
167157795646SDave May   dm->ops->coarsen                         = NULL;
167257795646SDave May   dm->ops->refinehierarchy                 = NULL;
167357795646SDave May   dm->ops->coarsenhierarchy                = NULL;
167457795646SDave May   dm->ops->globaltolocalbegin              = NULL;
167557795646SDave May   dm->ops->globaltolocalend                = NULL;
167657795646SDave May   dm->ops->localtoglobalbegin              = NULL;
167757795646SDave May   dm->ops->localtoglobalend                = NULL;
167857795646SDave May   dm->ops->destroy                         = DMDestroy_Swarm;
167957795646SDave May   dm->ops->createsubdm                     = NULL;
168057795646SDave May   dm->ops->getdimpoints                    = NULL;
168157795646SDave May   dm->ops->locatepoints                    = NULL;
168257795646SDave May   PetscFunctionReturn(0);
168357795646SDave May }
1684