xref: /petsc/src/dm/impls/swarm/swarm.c (revision 1e1ea65d8de51fde77ce8a787efbef25e407badc)
157795646SDave May #define PETSCDM_DLL
257795646SDave May #include <petsc/private/dmswarmimpl.h>    /*I   "petscdmswarm.h"   I*/
3e8f14785SLisandro Dalcin #include <petsc/private/hashsetij.h>
40643ed39SMatthew G. Knepley #include <petsc/private/petscfeimpl.h>
55917a6f0SStefano Zampini #include <petscviewer.h>
65917a6f0SStefano Zampini #include <petscdraw.h>
783c47955SMatthew G. Knepley #include <petscdmplex.h>
84cc7f7b2SMatthew G. Knepley #include <petscblaslapack.h>
9279f676cSBarry Smith #include "../src/dm/impls/swarm/data_bucket.h"
10d0c080abSJoseph Pusztay #include <petscdmlabel.h>
11d0c080abSJoseph Pusztay #include <petscsection.h>
1257795646SDave May 
13f2b2bee7SDave May PetscLogEvent DMSWARM_Migrate, DMSWARM_SetSizes, DMSWARM_AddPoints, DMSWARM_RemovePoints, DMSWARM_Sort;
14ed923d71SDave May PetscLogEvent DMSWARM_DataExchangerTopologySetup, DMSWARM_DataExchangerBegin, DMSWARM_DataExchangerEnd;
15ed923d71SDave May PetscLogEvent DMSWARM_DataExchangerSendCount, DMSWARM_DataExchangerPack;
16ed923d71SDave May 
17ea78f98cSLisandro Dalcin const char* DMSwarmTypeNames[] = { "basic", "pic", NULL };
18ea78f98cSLisandro Dalcin const char* DMSwarmMigrateTypeNames[] = { "basic", "dmcellnscatter", "dmcellexact", "user", NULL };
19ea78f98cSLisandro Dalcin const char* DMSwarmCollectTypeNames[] = { "basic", "boundingbox", "general", "user", NULL  };
20ea78f98cSLisandro Dalcin const char* DMSwarmPICLayoutTypeNames[] = { "regular", "gauss", "subdivision", NULL  };
21f0cdbbbaSDave May 
22f0cdbbbaSDave May const char DMSwarmField_pid[] = "DMSwarm_pid";
23f0cdbbbaSDave May const char DMSwarmField_rank[] = "DMSwarm_rank";
24f0cdbbbaSDave May const char DMSwarmPICField_coor[] = "DMSwarmPIC_coor";
25e2d107dbSDave May const char DMSwarmPICField_cellid[] = "DMSwarm_cellid";
26f0cdbbbaSDave May 
2774d0cae8SMatthew G. Knepley PETSC_EXTERN PetscErrorCode VecView_Seq(Vec, PetscViewer);
2874d0cae8SMatthew G. Knepley PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer);
2974d0cae8SMatthew G. Knepley 
3074d0cae8SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
3174d0cae8SMatthew G. Knepley #include <petscviewerhdf5.h>
3274d0cae8SMatthew G. Knepley 
3374d0cae8SMatthew G. Knepley PetscErrorCode VecView_Swarm_HDF5_Internal(Vec v, PetscViewer viewer)
3474d0cae8SMatthew G. Knepley {
3574d0cae8SMatthew G. Knepley   DM             dm;
3674d0cae8SMatthew G. Knepley   PetscReal      seqval;
3774d0cae8SMatthew G. Knepley   PetscInt       seqnum, bs;
3874d0cae8SMatthew G. Knepley   PetscBool      isseq;
3974d0cae8SMatthew G. Knepley   PetscErrorCode ierr;
4074d0cae8SMatthew G. Knepley 
4174d0cae8SMatthew G. Knepley   PetscFunctionBegin;
4274d0cae8SMatthew G. Knepley   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
4374d0cae8SMatthew G. Knepley   ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr);
4474d0cae8SMatthew G. Knepley   ierr = PetscViewerHDF5PushGroup(viewer, "/particle_fields");CHKERRQ(ierr);
4574d0cae8SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr);
4674d0cae8SMatthew G. Knepley   ierr = DMGetOutputSequenceNumber(dm, &seqnum, &seqval);CHKERRQ(ierr);
4774d0cae8SMatthew G. Knepley   ierr = PetscViewerHDF5SetTimestep(viewer, seqnum);CHKERRQ(ierr);
4874d0cae8SMatthew G. Knepley   /* ierr = DMSequenceView_HDF5(dm, "time", seqnum, (PetscScalar) seqval, viewer);CHKERRQ(ierr); */
4974d0cae8SMatthew G. Knepley   if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);}
5074d0cae8SMatthew G. Knepley   else       {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);}
5174d0cae8SMatthew G. Knepley   ierr = PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject) v, "Nc", PETSC_INT, (void *) &bs);CHKERRQ(ierr);
5274d0cae8SMatthew G. Knepley   ierr = PetscViewerHDF5PopGroup(viewer);CHKERRQ(ierr);
5374d0cae8SMatthew G. Knepley   PetscFunctionReturn(0);
5474d0cae8SMatthew G. Knepley }
5574d0cae8SMatthew G. Knepley 
5674d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmView_HDF5(DM dm, PetscViewer viewer)
5774d0cae8SMatthew G. Knepley {
5874d0cae8SMatthew G. Knepley   Vec            coordinates;
5974d0cae8SMatthew G. Knepley   PetscInt       Np;
6074d0cae8SMatthew G. Knepley   PetscBool      isseq;
6174d0cae8SMatthew G. Knepley   PetscErrorCode ierr;
6274d0cae8SMatthew G. Knepley 
6374d0cae8SMatthew G. Knepley   PetscFunctionBegin;
6474d0cae8SMatthew G. Knepley   ierr = DMSwarmGetSize(dm, &Np);CHKERRQ(ierr);
6574d0cae8SMatthew G. Knepley   ierr = DMSwarmCreateGlobalVectorFromField(dm, DMSwarmPICField_coor, &coordinates);CHKERRQ(ierr);
6674d0cae8SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr);
6774d0cae8SMatthew G. Knepley   ierr = PetscViewerHDF5PushGroup(viewer, "/particles");CHKERRQ(ierr);
6874d0cae8SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) coordinates, VECSEQ, &isseq);CHKERRQ(ierr);
6974d0cae8SMatthew G. Knepley   if (isseq) {ierr = VecView_Seq(coordinates, viewer);CHKERRQ(ierr);}
7074d0cae8SMatthew G. Knepley   else       {ierr = VecView_MPI(coordinates, viewer);CHKERRQ(ierr);}
7174d0cae8SMatthew G. Knepley   ierr = PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject) coordinates, "Np", PETSC_INT, (void *) &Np);CHKERRQ(ierr);
7274d0cae8SMatthew G. Knepley   ierr = PetscViewerHDF5PopGroup(viewer);CHKERRQ(ierr);
7374d0cae8SMatthew G. Knepley   ierr = DMSwarmDestroyGlobalVectorFromField(dm, DMSwarmPICField_coor, &coordinates);CHKERRQ(ierr);
7474d0cae8SMatthew G. Knepley   PetscFunctionReturn(0);
7574d0cae8SMatthew G. Knepley }
7674d0cae8SMatthew G. Knepley #endif
7774d0cae8SMatthew G. Knepley 
7874d0cae8SMatthew G. Knepley PetscErrorCode VecView_Swarm(Vec v, PetscViewer viewer)
7974d0cae8SMatthew G. Knepley {
8074d0cae8SMatthew G. Knepley   DM             dm;
8174d0cae8SMatthew G. Knepley   PetscBool      ishdf5;
8274d0cae8SMatthew G. Knepley   PetscErrorCode ierr;
8374d0cae8SMatthew G. Knepley 
8474d0cae8SMatthew G. Knepley   PetscFunctionBegin;
8574d0cae8SMatthew G. Knepley   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
8674d0cae8SMatthew G. Knepley   if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
8774d0cae8SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
8874d0cae8SMatthew G. Knepley   if (ishdf5) {
8974d0cae8SMatthew G. Knepley #if defined(PETSC_HAVE_HDF5)
9074d0cae8SMatthew G. Knepley     ierr = VecView_Swarm_HDF5_Internal(v, viewer);CHKERRQ(ierr);
9174d0cae8SMatthew G. Knepley #else
9274d0cae8SMatthew G. Knepley     SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5");
9374d0cae8SMatthew G. Knepley #endif
9474d0cae8SMatthew G. Knepley   } else {
9574d0cae8SMatthew G. Knepley     PetscBool isseq;
9674d0cae8SMatthew G. Knepley 
9774d0cae8SMatthew G. Knepley     ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr);
9874d0cae8SMatthew G. Knepley     if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);}
9974d0cae8SMatthew G. Knepley     else       {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);}
10074d0cae8SMatthew G. Knepley   }
10174d0cae8SMatthew G. Knepley   PetscFunctionReturn(0);
10274d0cae8SMatthew G. Knepley }
10374d0cae8SMatthew G. Knepley 
104d3a51819SDave May /*@C
10562741f57SDave May    DMSwarmVectorDefineField - Sets the field from which to define a Vec object
10662741f57SDave May                              when DMCreateLocalVector(), or DMCreateGlobalVector() is called
10757795646SDave May 
108d083f849SBarry Smith    Collective on dm
10957795646SDave May 
110d3a51819SDave May    Input parameters:
11162741f57SDave May +  dm - a DMSwarm
11262741f57SDave May -  fieldname - the textual name given to a registered field
11357795646SDave May 
114d3a51819SDave May    Level: beginner
11557795646SDave May 
116d3a51819SDave May    Notes:
117e7af74c8SDave May 
11862741f57SDave May    The field with name fieldname must be defined as having a data type of PetscScalar.
119e7af74c8SDave May 
120d3a51819SDave May    This function must be called prior to calling DMCreateLocalVector(), DMCreateGlobalVector().
121d3a51819SDave May    Mutiple calls to DMSwarmVectorDefineField() are permitted.
12257795646SDave May 
1238b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMCreateGlobalVector(), DMCreateLocalVector()
124d3a51819SDave May @*/
12574d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmVectorDefineField(DM dm,const char fieldname[])
126b5bcf523SDave May {
127b5bcf523SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
128b5bcf523SDave May   PetscErrorCode ierr;
129b5bcf523SDave May   PetscInt       bs,n;
130b5bcf523SDave May   PetscScalar    *array;
131b5bcf523SDave May   PetscDataType  type;
132b5bcf523SDave May 
133a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
1343454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
13577048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db,&n,NULL,NULL);CHKERRQ(ierr);
136b5bcf523SDave May   ierr = DMSwarmGetField(dm,fieldname,&bs,&type,(void**)&array);CHKERRQ(ierr);
137b5bcf523SDave May 
138b5bcf523SDave May   /* Check all fields are of type PETSC_REAL or PETSC_SCALAR */
139b5bcf523SDave May   if (type != PETSC_REAL) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only valid for PETSC_REAL");
140521f74f9SMatthew G. Knepley   ierr = PetscSNPrintf(swarm->vec_field_name,PETSC_MAX_PATH_LEN-1,"%s",fieldname);CHKERRQ(ierr);
141b5bcf523SDave May   swarm->vec_field_set = PETSC_TRUE;
1421b1ea282SDave May   swarm->vec_field_bs = bs;
143b5bcf523SDave May   swarm->vec_field_nlocal = n;
144dcf43ee8SDave May   ierr = DMSwarmRestoreField(dm,fieldname,&bs,&type,(void**)&array);CHKERRQ(ierr);
145b5bcf523SDave May   PetscFunctionReturn(0);
146b5bcf523SDave May }
147b5bcf523SDave May 
148cc651181SDave May /* requires DMSwarmDefineFieldVector has been called */
149b5bcf523SDave May PetscErrorCode DMCreateGlobalVector_Swarm(DM dm,Vec *vec)
150b5bcf523SDave May {
151b5bcf523SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
152b5bcf523SDave May   PetscErrorCode ierr;
153b5bcf523SDave May   Vec            x;
154b5bcf523SDave May   char           name[PETSC_MAX_PATH_LEN];
155b5bcf523SDave May 
156a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
1573454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
158b5bcf523SDave May   if (!swarm->vec_field_set) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmVectorDefineField first");
159cc651181SDave 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 */
160cc651181SDave May 
161521f74f9SMatthew G. Knepley   ierr = PetscSNPrintf(name,PETSC_MAX_PATH_LEN-1,"DMSwarmField_%s",swarm->vec_field_name);CHKERRQ(ierr);
162b5bcf523SDave May   ierr = VecCreate(PetscObjectComm((PetscObject)dm),&x);CHKERRQ(ierr);
163b5bcf523SDave May   ierr = PetscObjectSetName((PetscObject)x,name);CHKERRQ(ierr);
1641b1ea282SDave May   ierr = VecSetSizes(x,swarm->db->L*swarm->vec_field_bs,PETSC_DETERMINE);CHKERRQ(ierr);
165b5bcf523SDave May   ierr = VecSetBlockSize(x,swarm->vec_field_bs);CHKERRQ(ierr);
166c6b011d8SStefano Zampini   ierr = VecSetDM(x,dm);CHKERRQ(ierr);
167b5bcf523SDave May   ierr = VecSetFromOptions(x);CHKERRQ(ierr);
16874d0cae8SMatthew G. Knepley   ierr = VecSetDM(x, dm);CHKERRQ(ierr);
16974d0cae8SMatthew G. Knepley   ierr = VecSetOperation(x, VECOP_VIEW, (void (*)(void)) VecView_Swarm);CHKERRQ(ierr);
170b5bcf523SDave May   *vec = x;
171b5bcf523SDave May   PetscFunctionReturn(0);
172b5bcf523SDave May }
173b5bcf523SDave May 
174b5bcf523SDave May /* requires DMSwarmDefineFieldVector has been called */
175b5bcf523SDave May PetscErrorCode DMCreateLocalVector_Swarm(DM dm,Vec *vec)
176b5bcf523SDave May {
177b5bcf523SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
178b5bcf523SDave May   PetscErrorCode ierr;
179b5bcf523SDave May   Vec x;
180b5bcf523SDave May   char name[PETSC_MAX_PATH_LEN];
181b5bcf523SDave May 
182a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
1833454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
184b5bcf523SDave May   if (!swarm->vec_field_set) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmVectorDefineField first");
185cc651181SDave 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 */
186cc651181SDave May 
187521f74f9SMatthew G. Knepley   ierr = PetscSNPrintf(name,PETSC_MAX_PATH_LEN-1,"DMSwarmField_%s",swarm->vec_field_name);CHKERRQ(ierr);
188b5bcf523SDave May   ierr = VecCreate(PETSC_COMM_SELF,&x);CHKERRQ(ierr);
189b5bcf523SDave May   ierr = PetscObjectSetName((PetscObject)x,name);CHKERRQ(ierr);
190071900c8SMatthew G. Knepley   ierr = VecSetSizes(x,swarm->db->L*swarm->vec_field_bs,PETSC_DETERMINE);CHKERRQ(ierr);
191b5bcf523SDave May   ierr = VecSetBlockSize(x,swarm->vec_field_bs);CHKERRQ(ierr);
192c6b011d8SStefano Zampini   ierr = VecSetDM(x,dm);CHKERRQ(ierr);
193b5bcf523SDave May   ierr = VecSetFromOptions(x);CHKERRQ(ierr);
194b5bcf523SDave May   *vec = x;
195b5bcf523SDave May   PetscFunctionReturn(0);
196b5bcf523SDave May }
197b5bcf523SDave May 
198fb1bcc12SMatthew G. Knepley static PetscErrorCode DMSwarmDestroyVectorFromField_Private(DM dm, const char fieldname[], Vec *vec)
199fb1bcc12SMatthew G. Knepley {
200fb1bcc12SMatthew G. Knepley   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
20177048351SPatrick Sanan   DMSwarmDataField      gfield;
202fb1bcc12SMatthew G. Knepley   void         (*fptr)(void);
203fb1bcc12SMatthew G. Knepley   PetscInt       bs, nlocal;
204fb1bcc12SMatthew G. Knepley   char           name[PETSC_MAX_PATH_LEN];
205fb1bcc12SMatthew G. Knepley   PetscErrorCode ierr;
206d3a51819SDave May 
207fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
208fb1bcc12SMatthew G. Knepley   ierr = VecGetLocalSize(*vec, &nlocal);CHKERRQ(ierr);
209fb1bcc12SMatthew G. Knepley   ierr = VecGetBlockSize(*vec, &bs);CHKERRQ(ierr);
210fb1bcc12SMatthew 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 */
21177048351SPatrick Sanan   ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield);CHKERRQ(ierr);
212fb1bcc12SMatthew G. Knepley   /* check vector is an inplace array */
213521f74f9SMatthew G. Knepley   ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarm_VecFieldInPlace_%s", fieldname);CHKERRQ(ierr);
214fb1bcc12SMatthew G. Knepley   ierr = PetscObjectQueryFunction((PetscObject) *vec, name, &fptr);CHKERRQ(ierr);
215fb1bcc12SMatthew G. Knepley   if (!fptr) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_USER, "Vector being destroyed was not created from DMSwarm field(%s)", fieldname);
21677048351SPatrick Sanan   ierr = DMSwarmDataFieldRestoreAccess(gfield);CHKERRQ(ierr);
217fb1bcc12SMatthew G. Knepley   ierr = VecDestroy(vec);CHKERRQ(ierr);
218fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
219fb1bcc12SMatthew G. Knepley }
220fb1bcc12SMatthew G. Knepley 
221fb1bcc12SMatthew G. Knepley static PetscErrorCode DMSwarmCreateVectorFromField_Private(DM dm, const char fieldname[], MPI_Comm comm, Vec *vec)
222fb1bcc12SMatthew G. Knepley {
223fb1bcc12SMatthew G. Knepley   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
224fb1bcc12SMatthew G. Knepley   PetscDataType  type;
225fb1bcc12SMatthew G. Knepley   PetscScalar   *array;
226fb1bcc12SMatthew G. Knepley   PetscInt       bs, n;
227fb1bcc12SMatthew G. Knepley   char           name[PETSC_MAX_PATH_LEN];
228e4fbd051SBarry Smith   PetscMPIInt    size;
229fb1bcc12SMatthew G. Knepley   PetscErrorCode ierr;
230fb1bcc12SMatthew G. Knepley 
231fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
232fb1bcc12SMatthew G. Knepley   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
23377048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db, &n, NULL, NULL);CHKERRQ(ierr);
234fb1bcc12SMatthew G. Knepley   ierr = DMSwarmGetField(dm, fieldname, &bs, &type, (void **) &array);CHKERRQ(ierr);
235fb1bcc12SMatthew G. Knepley   if (type != PETSC_REAL) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Only valid for PETSC_REAL");
236fb1bcc12SMatthew G. Knepley 
237ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
238e4fbd051SBarry Smith   if (size == 1) {
239fb1bcc12SMatthew G. Knepley     ierr = VecCreateSeqWithArray(comm, bs, n*bs, array, vec);CHKERRQ(ierr);
240fb1bcc12SMatthew G. Knepley   } else {
241fb1bcc12SMatthew G. Knepley     ierr = VecCreateMPIWithArray(comm, bs, n*bs, PETSC_DETERMINE, array, vec);CHKERRQ(ierr);
242fb1bcc12SMatthew G. Knepley   }
243fb1bcc12SMatthew G. Knepley   ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarmSharedField_%s", fieldname);CHKERRQ(ierr);
244fb1bcc12SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) *vec, name);CHKERRQ(ierr);
245fb1bcc12SMatthew G. Knepley 
246fb1bcc12SMatthew G. Knepley   /* Set guard */
247fb1bcc12SMatthew G. Knepley   ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarm_VecFieldInPlace_%s", fieldname);CHKERRQ(ierr);
248fb1bcc12SMatthew G. Knepley   ierr = PetscObjectComposeFunction((PetscObject) *vec, name, DMSwarmDestroyVectorFromField_Private);CHKERRQ(ierr);
24974d0cae8SMatthew G. Knepley 
25074d0cae8SMatthew G. Knepley   ierr = VecSetDM(*vec, dm);CHKERRQ(ierr);
25174d0cae8SMatthew G. Knepley   ierr = VecSetOperation(*vec, VECOP_VIEW, (void (*)(void)) VecView_Swarm);CHKERRQ(ierr);
252fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
253fb1bcc12SMatthew G. Knepley }
254fb1bcc12SMatthew G. Knepley 
2550643ed39SMatthew G. Knepley /* This creates a "mass matrix" between a finite element and particle space. If a finite element interpolant is given by
2560643ed39SMatthew G. Knepley 
2570643ed39SMatthew G. Knepley      \hat f = \sum_i f_i \phi_i
2580643ed39SMatthew G. Knepley 
2590643ed39SMatthew G. Knepley    and a particle function is given by
2600643ed39SMatthew G. Knepley 
2610643ed39SMatthew G. Knepley      f = \sum_i w_i \delta(x - x_i)
2620643ed39SMatthew G. Knepley 
2630643ed39SMatthew G. Knepley    then we want to require that
2640643ed39SMatthew G. Knepley 
2650643ed39SMatthew G. Knepley      M \hat f = M_p f
2660643ed39SMatthew G. Knepley 
2670643ed39SMatthew G. Knepley    where the particle mass matrix is given by
2680643ed39SMatthew G. Knepley 
2690643ed39SMatthew G. Knepley      (M_p)_{ij} = \int \phi_i \delta(x - x_j)
2700643ed39SMatthew G. Knepley 
2710643ed39SMatthew G. Knepley    The way Dave May does particles, they amount to quadratue weights rather than delta functions, so he has |J| is in
2720643ed39SMatthew G. Knepley    his integral. We allow this with the boolean flag.
2730643ed39SMatthew G. Knepley */
2740643ed39SMatthew G. Knepley static PetscErrorCode DMSwarmComputeMassMatrix_Private(DM dmc, DM dmf, Mat mass, PetscBool useDeltaFunction, void *ctx)
27583c47955SMatthew G. Knepley {
27683c47955SMatthew G. Knepley   const char    *name = "Mass Matrix";
2770643ed39SMatthew G. Knepley   MPI_Comm       comm;
27883c47955SMatthew G. Knepley   PetscDS        prob;
27983c47955SMatthew G. Knepley   PetscSection   fsection, globalFSection;
280e8f14785SLisandro Dalcin   PetscHSetIJ    ht;
2810643ed39SMatthew G. Knepley   PetscLayout    rLayout, colLayout;
28283c47955SMatthew G. Knepley   PetscInt      *dnz, *onz;
283adb2528bSMark Adams   PetscInt       locRows, locCols, rStart, colStart, colEnd, *rowIDXs;
2840643ed39SMatthew G. Knepley   PetscReal     *xi, *v0, *J, *invJ, detJ = 1.0, v0ref[3] = {-1.0, -1.0, -1.0};
28583c47955SMatthew G. Knepley   PetscScalar   *elemMat;
2860643ed39SMatthew G. Knepley   PetscInt       dim, Nf, field, cStart, cEnd, cell, totDim, maxC = 0;
28783c47955SMatthew G. Knepley   PetscErrorCode ierr;
28883c47955SMatthew G. Knepley 
28983c47955SMatthew G. Knepley   PetscFunctionBegin;
2900643ed39SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) mass, &comm);CHKERRQ(ierr);
29183c47955SMatthew G. Knepley   ierr = DMGetCoordinateDim(dmf, &dim);CHKERRQ(ierr);
29283c47955SMatthew G. Knepley   ierr = DMGetDS(dmf, &prob);CHKERRQ(ierr);
29383c47955SMatthew G. Knepley   ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr);
2940643ed39SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr);
29583c47955SMatthew G. Knepley   ierr = PetscMalloc3(dim, &v0, dim*dim, &J, dim*dim,&invJ);CHKERRQ(ierr);
29692fd8e1eSJed Brown   ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);
297e87a4003SBarry Smith   ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);
29883c47955SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd);CHKERRQ(ierr);
2990643ed39SMatthew G. Knepley   ierr = MatGetLocalSize(mass, &locRows, &locCols);CHKERRQ(ierr);
30083c47955SMatthew G. Knepley 
3010643ed39SMatthew G. Knepley   ierr = PetscLayoutCreate(comm, &colLayout);CHKERRQ(ierr);
3020643ed39SMatthew G. Knepley   ierr = PetscLayoutSetLocalSize(colLayout, locCols);CHKERRQ(ierr);
3030643ed39SMatthew G. Knepley   ierr = PetscLayoutSetBlockSize(colLayout, 1);CHKERRQ(ierr);
3040643ed39SMatthew G. Knepley   ierr = PetscLayoutSetUp(colLayout);CHKERRQ(ierr);
3050643ed39SMatthew G. Knepley   ierr = PetscLayoutGetRange(colLayout, &colStart, &colEnd);CHKERRQ(ierr);
3060643ed39SMatthew G. Knepley   ierr = PetscLayoutDestroy(&colLayout);CHKERRQ(ierr);
3070643ed39SMatthew G. Knepley 
3080643ed39SMatthew G. Knepley   ierr = PetscLayoutCreate(comm, &rLayout);CHKERRQ(ierr);
30983c47955SMatthew G. Knepley   ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr);
31083c47955SMatthew G. Knepley   ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr);
31183c47955SMatthew G. Knepley   ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr);
3120643ed39SMatthew G. Knepley   ierr = PetscLayoutGetRange(rLayout, &rStart, NULL);CHKERRQ(ierr);
31383c47955SMatthew G. Knepley   ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr);
3140643ed39SMatthew G. Knepley 
31583c47955SMatthew G. Knepley   ierr = PetscCalloc2(locRows, &dnz, locRows, &onz);CHKERRQ(ierr);
316e8f14785SLisandro Dalcin   ierr = PetscHSetIJCreate(&ht);CHKERRQ(ierr);
31753e60ab4SJoseph Pusztay 
3180643ed39SMatthew G. Knepley   ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);
3190643ed39SMatthew G. Knepley   /* count non-zeros */
3200643ed39SMatthew G. Knepley   ierr = DMSwarmSortGetAccess(dmc);CHKERRQ(ierr);
32183c47955SMatthew G. Knepley   for (field = 0; field < Nf; ++field) {
32283c47955SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
3230643ed39SMatthew G. Knepley       PetscInt  c, i;
3240643ed39SMatthew G. Knepley       PetscInt *findices,   *cindices; /* fine is vertices, coarse is particles */
32583c47955SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
32683c47955SMatthew G. Knepley 
32771f0bbf9SMatthew G. Knepley       ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL);CHKERRQ(ierr);
328fc7c92abSMatthew G. Knepley       ierr = DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices);CHKERRQ(ierr);
329fc7c92abSMatthew G. Knepley       maxC = PetscMax(maxC, numCIndices);
33083c47955SMatthew G. Knepley       {
331e8f14785SLisandro Dalcin         PetscHashIJKey key;
332e8f14785SLisandro Dalcin         PetscBool      missing;
33383c47955SMatthew G. Knepley         for (i = 0; i < numFIndices; ++i) {
334adb2528bSMark Adams           key.j = findices[i]; /* global column (from Plex) */
335adb2528bSMark Adams           if (key.j >= 0) {
33683c47955SMatthew G. Knepley             /* Get indices for coarse elements */
33783c47955SMatthew G. Knepley             for (c = 0; c < numCIndices; ++c) {
338adb2528bSMark Adams               key.i = cindices[c] + rStart; /* global cols (from Swarm) */
339adb2528bSMark Adams               if (key.i < 0) continue;
340e8f14785SLisandro Dalcin               ierr = PetscHSetIJQueryAdd(ht, key, &missing);CHKERRQ(ierr);
34183c47955SMatthew G. Knepley               if (missing) {
3420643ed39SMatthew G. Knepley                 if ((key.j >= colStart) && (key.j < colEnd)) ++dnz[key.i - rStart];
343e8f14785SLisandro Dalcin                 else                                         ++onz[key.i - rStart];
3440643ed39SMatthew G. Knepley               } else SETERRQ2(PetscObjectComm((PetscObject) dmf), PETSC_ERR_SUP, "Set new value at %D,%D", key.i, key.j);
34583c47955SMatthew G. Knepley             }
346fc7c92abSMatthew G. Knepley           }
347fc7c92abSMatthew G. Knepley         }
34883c47955SMatthew G. Knepley         ierr = PetscFree(cindices);CHKERRQ(ierr);
34983c47955SMatthew G. Knepley       }
35071f0bbf9SMatthew G. Knepley       ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL);CHKERRQ(ierr);
35183c47955SMatthew G. Knepley     }
35283c47955SMatthew G. Knepley   }
353e8f14785SLisandro Dalcin   ierr = PetscHSetIJDestroy(&ht);CHKERRQ(ierr);
35483c47955SMatthew G. Knepley   ierr = MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL);CHKERRQ(ierr);
35583c47955SMatthew G. Knepley   ierr = MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE);CHKERRQ(ierr);
35683c47955SMatthew G. Knepley   ierr = PetscFree2(dnz, onz);CHKERRQ(ierr);
357adb2528bSMark Adams   ierr = PetscMalloc3(maxC*totDim, &elemMat, maxC, &rowIDXs, maxC*dim, &xi);CHKERRQ(ierr);
35883c47955SMatthew G. Knepley   for (field = 0; field < Nf; ++field) {
359ef0bb6c7SMatthew G. Knepley     PetscTabulation Tcoarse;
36083c47955SMatthew G. Knepley     PetscObject       obj;
361ef0bb6c7SMatthew G. Knepley     PetscReal        *coords;
3620643ed39SMatthew G. Knepley     PetscInt          Nc, i;
36383c47955SMatthew G. Knepley 
36483c47955SMatthew G. Knepley     ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr);
3650643ed39SMatthew G. Knepley     ierr = PetscFEGetNumComponents((PetscFE) obj, &Nc);CHKERRQ(ierr);
3660643ed39SMatthew G. Knepley     if (Nc != 1) SETERRQ1(PetscObjectComm((PetscObject) dmf), PETSC_ERR_SUP, "Can only interpolate a scalar field from particles, Nc = %D", Nc);
3670643ed39SMatthew G. Knepley     ierr = DMSwarmGetField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **) &coords);CHKERRQ(ierr);
36883c47955SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
36983c47955SMatthew G. Knepley       PetscInt *findices  , *cindices;
37083c47955SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
3710643ed39SMatthew G. Knepley       PetscInt  p, c;
37283c47955SMatthew G. Knepley 
3730643ed39SMatthew G. Knepley       /* TODO: Use DMField instead of assuming affine */
37483c47955SMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr);
37571f0bbf9SMatthew G. Knepley       ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL);CHKERRQ(ierr);
37683c47955SMatthew G. Knepley       ierr = DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices);CHKERRQ(ierr);
3770643ed39SMatthew G. Knepley       for (p = 0; p < numCIndices; ++p) {
3780643ed39SMatthew G. Knepley         CoordinatesRealToRef(dim, dim, v0ref, v0, invJ, &coords[cindices[p]*dim], &xi[p*dim]);
3790643ed39SMatthew G. Knepley       }
380ef0bb6c7SMatthew G. Knepley       ierr = PetscFECreateTabulation((PetscFE) obj, 1, numCIndices, xi, 0, &Tcoarse);CHKERRQ(ierr);
38183c47955SMatthew G. Knepley       /* Get elemMat entries by multiplying by weight */
382580bdb30SBarry Smith       ierr = PetscArrayzero(elemMat, numCIndices*totDim);CHKERRQ(ierr);
38383c47955SMatthew G. Knepley       for (i = 0; i < numFIndices; ++i) {
3840643ed39SMatthew G. Knepley         for (p = 0; p < numCIndices; ++p) {
3850643ed39SMatthew G. Knepley           for (c = 0; c < Nc; ++c) {
3860643ed39SMatthew G. Knepley             /* B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c */
387ef0bb6c7SMatthew G. Knepley             elemMat[p*numFIndices+i] += Tcoarse->T[0][(p*numFIndices + i)*Nc + c]*(useDeltaFunction ? 1.0 : detJ);
38883c47955SMatthew G. Knepley           }
3890643ed39SMatthew G. Knepley         }
3900643ed39SMatthew G. Knepley       }
391adb2528bSMark Adams       for (p = 0; p < numCIndices; ++p) rowIDXs[p] = cindices[p] + rStart;
39283c47955SMatthew G. Knepley       if (0) {ierr = DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat);CHKERRQ(ierr);}
393adb2528bSMark Adams       ierr = MatSetValues(mass, numCIndices, rowIDXs, numFIndices, findices, elemMat, ADD_VALUES);CHKERRQ(ierr);
39483c47955SMatthew G. Knepley       ierr = PetscFree(cindices);CHKERRQ(ierr);
39571f0bbf9SMatthew G. Knepley       ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL);CHKERRQ(ierr);
396ef0bb6c7SMatthew G. Knepley       ierr = PetscTabulationDestroy(&Tcoarse);CHKERRQ(ierr);
39783c47955SMatthew G. Knepley     }
3980643ed39SMatthew G. Knepley     ierr = DMSwarmRestoreField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **) &coords);CHKERRQ(ierr);
39983c47955SMatthew G. Knepley   }
400adb2528bSMark Adams   ierr = PetscFree3(elemMat, rowIDXs, xi);CHKERRQ(ierr);
40183c47955SMatthew G. Knepley   ierr = DMSwarmSortRestoreAccess(dmc);CHKERRQ(ierr);
40283c47955SMatthew G. Knepley   ierr = PetscFree3(v0, J, invJ);CHKERRQ(ierr);
40383c47955SMatthew G. Knepley   ierr = MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
40483c47955SMatthew G. Knepley   ierr = MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
40583c47955SMatthew G. Knepley   PetscFunctionReturn(0);
40683c47955SMatthew G. Knepley }
40783c47955SMatthew G. Knepley 
408d0c080abSJoseph Pusztay /* Returns empty matrix for use with SNES FD */
40970a7d78aSStefano Zampini static PetscErrorCode DMCreateMatrix_Swarm(DM sw, Mat* m)
41070a7d78aSStefano Zampini {
411d0c080abSJoseph Pusztay   Vec            field;
412d0c080abSJoseph Pusztay   PetscInt       size;
413d0c080abSJoseph Pusztay   PetscErrorCode ierr;
414d0c080abSJoseph Pusztay 
415d0c080abSJoseph Pusztay   PetscFunctionBegin;
416d0c080abSJoseph Pusztay   ierr = DMGetGlobalVector(sw, &field);CHKERRQ(ierr);
417d0c080abSJoseph Pusztay   ierr = VecGetLocalSize(field, &size);CHKERRQ(ierr);
418d0c080abSJoseph Pusztay   ierr = DMRestoreGlobalVector(sw, &field);CHKERRQ(ierr);
419d0c080abSJoseph Pusztay   ierr = MatCreate(PETSC_COMM_WORLD, m);CHKERRQ(ierr);
420d0c080abSJoseph Pusztay   ierr = MatSetFromOptions(*m);CHKERRQ(ierr);
421*1e1ea65dSPierre Jolivet   ierr = MatSetSizes(*m, PETSC_DECIDE, PETSC_DECIDE, size, size);CHKERRQ(ierr);
422d0c080abSJoseph Pusztay   ierr = MatSeqAIJSetPreallocation(*m, 1, NULL);CHKERRQ(ierr);
423d0c080abSJoseph Pusztay   ierr = MatZeroEntries(*m);CHKERRQ(ierr);
424d0c080abSJoseph Pusztay   ierr = MatAssemblyBegin(*m, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
425d0c080abSJoseph Pusztay   ierr = MatAssemblyEnd(*m, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
426d0c080abSJoseph Pusztay   ierr = MatShift(*m, 1.0);CHKERRQ(ierr);
427d0c080abSJoseph Pusztay   ierr = MatSetDM(*m, sw);CHKERRQ(ierr);
428d0c080abSJoseph Pusztay   PetscFunctionReturn(0);
429d0c080abSJoseph Pusztay }
430d0c080abSJoseph Pusztay 
431adb2528bSMark Adams /* FEM cols, Particle rows */
43283c47955SMatthew G. Knepley static PetscErrorCode DMCreateMassMatrix_Swarm(DM dmCoarse, DM dmFine, Mat *mass)
43383c47955SMatthew G. Knepley {
434895a1698SMatthew G. Knepley   PetscSection   gsf;
43583c47955SMatthew G. Knepley   PetscInt       m, n;
43683c47955SMatthew G. Knepley   void          *ctx;
43783c47955SMatthew G. Knepley   PetscErrorCode ierr;
43883c47955SMatthew G. Knepley 
43983c47955SMatthew G. Knepley   PetscFunctionBegin;
440e87a4003SBarry Smith   ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr);
44183c47955SMatthew G. Knepley   ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr);
442895a1698SMatthew G. Knepley   ierr = DMSwarmGetLocalSize(dmCoarse, &n);CHKERRQ(ierr);
44383c47955SMatthew G. Knepley   ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr);
444adb2528bSMark Adams   ierr = MatSetSizes(*mass, n, m, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
44583c47955SMatthew G. Knepley   ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr);
44683c47955SMatthew G. Knepley   ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr);
44783c47955SMatthew G. Knepley 
4480643ed39SMatthew G. Knepley   ierr = DMSwarmComputeMassMatrix_Private(dmCoarse, dmFine, *mass, PETSC_TRUE, ctx);CHKERRQ(ierr);
44983c47955SMatthew G. Knepley   ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr);
45083c47955SMatthew G. Knepley   PetscFunctionReturn(0);
45183c47955SMatthew G. Knepley }
45283c47955SMatthew G. Knepley 
4534cc7f7b2SMatthew G. Knepley static PetscErrorCode DMSwarmComputeMassMatrixSquare_Private(DM dmc, DM dmf, Mat mass, PetscBool useDeltaFunction, void *ctx)
4544cc7f7b2SMatthew G. Knepley {
4554cc7f7b2SMatthew G. Knepley   const char    *name = "Mass Matrix Square";
4564cc7f7b2SMatthew G. Knepley   MPI_Comm       comm;
4574cc7f7b2SMatthew G. Knepley   PetscDS        prob;
4584cc7f7b2SMatthew G. Knepley   PetscSection   fsection, globalFSection;
4594cc7f7b2SMatthew G. Knepley   PetscHSetIJ    ht;
4604cc7f7b2SMatthew G. Knepley   PetscLayout    rLayout, colLayout;
4614cc7f7b2SMatthew G. Knepley   PetscInt      *dnz, *onz, *adj, depth, maxConeSize, maxSupportSize, maxAdjSize;
4624cc7f7b2SMatthew G. Knepley   PetscInt       locRows, locCols, rStart, colStart, colEnd, *rowIDXs;
4634cc7f7b2SMatthew G. Knepley   PetscReal     *xi, *v0, *J, *invJ, detJ = 1.0, v0ref[3] = {-1.0, -1.0, -1.0};
4644cc7f7b2SMatthew G. Knepley   PetscScalar   *elemMat, *elemMatSq;
4654cc7f7b2SMatthew G. Knepley   PetscInt       cdim, Nf, field, cStart, cEnd, cell, totDim, maxC = 0;
4664cc7f7b2SMatthew G. Knepley   PetscErrorCode ierr;
4674cc7f7b2SMatthew G. Knepley 
4684cc7f7b2SMatthew G. Knepley   PetscFunctionBegin;
4694cc7f7b2SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) mass, &comm);CHKERRQ(ierr);
4704cc7f7b2SMatthew G. Knepley   ierr = DMGetCoordinateDim(dmf, &cdim);CHKERRQ(ierr);
4714cc7f7b2SMatthew G. Knepley   ierr = DMGetDS(dmf, &prob);CHKERRQ(ierr);
4724cc7f7b2SMatthew G. Knepley   ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr);
4734cc7f7b2SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr);
4744cc7f7b2SMatthew G. Knepley   ierr = PetscMalloc3(cdim, &v0, cdim*cdim, &J, cdim*cdim,&invJ);CHKERRQ(ierr);
4754cc7f7b2SMatthew G. Knepley   ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);
4764cc7f7b2SMatthew G. Knepley   ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);
4774cc7f7b2SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd);CHKERRQ(ierr);
4784cc7f7b2SMatthew G. Knepley   ierr = MatGetLocalSize(mass, &locRows, &locCols);CHKERRQ(ierr);
4794cc7f7b2SMatthew G. Knepley 
4804cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutCreate(comm, &colLayout);CHKERRQ(ierr);
4814cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutSetLocalSize(colLayout, locCols);CHKERRQ(ierr);
4824cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutSetBlockSize(colLayout, 1);CHKERRQ(ierr);
4834cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutSetUp(colLayout);CHKERRQ(ierr);
4844cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutGetRange(colLayout, &colStart, &colEnd);CHKERRQ(ierr);
4854cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutDestroy(&colLayout);CHKERRQ(ierr);
4864cc7f7b2SMatthew G. Knepley 
4874cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutCreate(comm, &rLayout);CHKERRQ(ierr);
4884cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr);
4894cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr);
4904cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr);
4914cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutGetRange(rLayout, &rStart, NULL);CHKERRQ(ierr);
4924cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr);
4934cc7f7b2SMatthew G. Knepley 
4944cc7f7b2SMatthew G. Knepley   ierr = DMPlexGetDepth(dmf, &depth);CHKERRQ(ierr);
4954cc7f7b2SMatthew G. Knepley   ierr = DMPlexGetMaxSizes(dmf, &maxConeSize, &maxSupportSize);CHKERRQ(ierr);
4964cc7f7b2SMatthew G. Knepley   maxAdjSize = PetscPowInt(maxConeSize*maxSupportSize, depth);
4974cc7f7b2SMatthew G. Knepley   ierr = PetscMalloc1(maxAdjSize, &adj);CHKERRQ(ierr);
4984cc7f7b2SMatthew G. Knepley 
4994cc7f7b2SMatthew G. Knepley   ierr = PetscCalloc2(locRows, &dnz, locRows, &onz);CHKERRQ(ierr);
5004cc7f7b2SMatthew G. Knepley   ierr = PetscHSetIJCreate(&ht);CHKERRQ(ierr);
5014cc7f7b2SMatthew G. Knepley   /* Count nonzeros
5024cc7f7b2SMatthew G. Knepley        This is just FVM++, but we cannot use the Plex P0 allocation since unknowns in a cell will not be contiguous
5034cc7f7b2SMatthew G. Knepley   */
5044cc7f7b2SMatthew G. Knepley   ierr = DMSwarmSortGetAccess(dmc);CHKERRQ(ierr);
5054cc7f7b2SMatthew G. Knepley   for (cell = cStart; cell < cEnd; ++cell) {
5064cc7f7b2SMatthew G. Knepley     PetscInt  i;
5074cc7f7b2SMatthew G. Knepley     PetscInt *cindices;
5084cc7f7b2SMatthew G. Knepley     PetscInt  numCIndices;
5094cc7f7b2SMatthew G. Knepley   #if 0
5104cc7f7b2SMatthew G. Knepley     PetscInt  adjSize = maxAdjSize, a, j;
5114cc7f7b2SMatthew G. Knepley   #endif
5124cc7f7b2SMatthew G. Knepley 
5134cc7f7b2SMatthew G. Knepley     ierr = DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices);CHKERRQ(ierr);
5144cc7f7b2SMatthew G. Knepley     maxC = PetscMax(maxC, numCIndices);
5154cc7f7b2SMatthew G. Knepley     /* Diagonal block */
5164cc7f7b2SMatthew G. Knepley     for (i = 0; i < numCIndices; ++i) {dnz[cindices[i]] += numCIndices;}
5174cc7f7b2SMatthew G. Knepley #if 0
5184cc7f7b2SMatthew G. Knepley     /* Off-diagonal blocks */
5194cc7f7b2SMatthew G. Knepley     ierr = DMPlexGetAdjacency(dmf, cell, &adjSize, &adj);CHKERRQ(ierr);
5204cc7f7b2SMatthew G. Knepley     for (a = 0; a < adjSize; ++a) {
5214cc7f7b2SMatthew G. Knepley       if (adj[a] >= cStart && adj[a] < cEnd && adj[a] != cell) {
5224cc7f7b2SMatthew G. Knepley         const PetscInt ncell = adj[a];
5234cc7f7b2SMatthew G. Knepley         PetscInt      *ncindices;
5244cc7f7b2SMatthew G. Knepley         PetscInt       numNCIndices;
5254cc7f7b2SMatthew G. Knepley 
5264cc7f7b2SMatthew G. Knepley         ierr = DMSwarmSortGetPointsPerCell(dmc, ncell, &numNCIndices, &ncindices);CHKERRQ(ierr);
5274cc7f7b2SMatthew G. Knepley         {
5284cc7f7b2SMatthew G. Knepley           PetscHashIJKey key;
5294cc7f7b2SMatthew G. Knepley           PetscBool      missing;
5304cc7f7b2SMatthew G. Knepley 
5314cc7f7b2SMatthew G. Knepley           for (i = 0; i < numCIndices; ++i) {
5324cc7f7b2SMatthew G. Knepley             key.i = cindices[i] + rStart; /* global rows (from Swarm) */
5334cc7f7b2SMatthew G. Knepley             if (key.i < 0) continue;
5344cc7f7b2SMatthew G. Knepley             for (j = 0; j < numNCIndices; ++j) {
5354cc7f7b2SMatthew G. Knepley               key.j = ncindices[j] + rStart; /* global column (from Swarm) */
5364cc7f7b2SMatthew G. Knepley               if (key.j < 0) continue;
5374cc7f7b2SMatthew G. Knepley               ierr = PetscHSetIJQueryAdd(ht, key, &missing);CHKERRQ(ierr);
5384cc7f7b2SMatthew G. Knepley               if (missing) {
5394cc7f7b2SMatthew G. Knepley                 if ((key.j >= colStart) && (key.j < colEnd)) ++dnz[key.i - rStart];
5404cc7f7b2SMatthew G. Knepley                 else                                         ++onz[key.i - rStart];
5414cc7f7b2SMatthew G. Knepley               }
5424cc7f7b2SMatthew G. Knepley             }
5434cc7f7b2SMatthew G. Knepley           }
5444cc7f7b2SMatthew G. Knepley         }
5454cc7f7b2SMatthew G. Knepley         ierr = PetscFree(ncindices);CHKERRQ(ierr);
5464cc7f7b2SMatthew G. Knepley       }
5474cc7f7b2SMatthew G. Knepley     }
5484cc7f7b2SMatthew G. Knepley #endif
5494cc7f7b2SMatthew G. Knepley     ierr = PetscFree(cindices);CHKERRQ(ierr);
5504cc7f7b2SMatthew G. Knepley   }
5514cc7f7b2SMatthew G. Knepley   ierr = PetscHSetIJDestroy(&ht);CHKERRQ(ierr);
5524cc7f7b2SMatthew G. Knepley   ierr = MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL);CHKERRQ(ierr);
5534cc7f7b2SMatthew G. Knepley   ierr = MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE);CHKERRQ(ierr);
5544cc7f7b2SMatthew G. Knepley   ierr = PetscFree2(dnz, onz);CHKERRQ(ierr);
5554cc7f7b2SMatthew G. Knepley   ierr = PetscMalloc4(maxC*totDim, &elemMat, maxC*maxC, &elemMatSq, maxC, &rowIDXs, maxC*cdim, &xi);CHKERRQ(ierr);
5564cc7f7b2SMatthew G. Knepley   /* Fill in values
5574cc7f7b2SMatthew G. Knepley        Each entry is a sum of terms \phi_i(x_p) \phi_i(x_q)
5584cc7f7b2SMatthew G. Knepley        Start just by producing block diagonal
5594cc7f7b2SMatthew G. Knepley        Could loop over adjacent cells
5604cc7f7b2SMatthew G. Knepley          Produce neighboring element matrix
5614cc7f7b2SMatthew G. Knepley          TODO Determine which columns and rows correspond to shared dual vector
5624cc7f7b2SMatthew G. Knepley          Do MatMatMult with rectangular matrices
5634cc7f7b2SMatthew G. Knepley          Insert block
5644cc7f7b2SMatthew G. Knepley   */
5654cc7f7b2SMatthew G. Knepley   for (field = 0; field < Nf; ++field) {
5664cc7f7b2SMatthew G. Knepley     PetscTabulation Tcoarse;
5674cc7f7b2SMatthew G. Knepley     PetscObject       obj;
5684cc7f7b2SMatthew G. Knepley     PetscReal        *coords;
5694cc7f7b2SMatthew G. Knepley     PetscInt          Nc, i;
5704cc7f7b2SMatthew G. Knepley 
5714cc7f7b2SMatthew G. Knepley     ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr);
5724cc7f7b2SMatthew G. Knepley     ierr = PetscFEGetNumComponents((PetscFE) obj, &Nc);CHKERRQ(ierr);
5734cc7f7b2SMatthew G. Knepley     if (Nc != 1) SETERRQ1(PetscObjectComm((PetscObject) dmf), PETSC_ERR_SUP, "Can only interpolate a scalar field from particles, Nc = %D", Nc);
5744cc7f7b2SMatthew G. Knepley     ierr = DMSwarmGetField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **) &coords);CHKERRQ(ierr);
5754cc7f7b2SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
5764cc7f7b2SMatthew G. Knepley       PetscInt *findices  , *cindices;
5774cc7f7b2SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
5784cc7f7b2SMatthew G. Knepley       PetscInt  p, c;
5794cc7f7b2SMatthew G. Knepley 
5804cc7f7b2SMatthew G. Knepley       /* TODO: Use DMField instead of assuming affine */
5814cc7f7b2SMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr);
5824cc7f7b2SMatthew G. Knepley       ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL);CHKERRQ(ierr);
5834cc7f7b2SMatthew G. Knepley       ierr = DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices);CHKERRQ(ierr);
5844cc7f7b2SMatthew G. Knepley       for (p = 0; p < numCIndices; ++p) {
5854cc7f7b2SMatthew G. Knepley         CoordinatesRealToRef(cdim, cdim, v0ref, v0, invJ, &coords[cindices[p]*cdim], &xi[p*cdim]);
5864cc7f7b2SMatthew G. Knepley       }
5874cc7f7b2SMatthew G. Knepley       ierr = PetscFECreateTabulation((PetscFE) obj, 1, numCIndices, xi, 0, &Tcoarse);CHKERRQ(ierr);
5884cc7f7b2SMatthew G. Knepley       /* Get elemMat entries by multiplying by weight */
5894cc7f7b2SMatthew G. Knepley       ierr = PetscArrayzero(elemMat, numCIndices*totDim);CHKERRQ(ierr);
5904cc7f7b2SMatthew G. Knepley       for (i = 0; i < numFIndices; ++i) {
5914cc7f7b2SMatthew G. Knepley         for (p = 0; p < numCIndices; ++p) {
5924cc7f7b2SMatthew G. Knepley           for (c = 0; c < Nc; ++c) {
5934cc7f7b2SMatthew G. Knepley             /* B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c */
5944cc7f7b2SMatthew G. Knepley             elemMat[p*numFIndices+i] += Tcoarse->T[0][(p*numFIndices + i)*Nc + c]*(useDeltaFunction ? 1.0 : detJ);
5954cc7f7b2SMatthew G. Knepley           }
5964cc7f7b2SMatthew G. Knepley         }
5974cc7f7b2SMatthew G. Knepley       }
5984cc7f7b2SMatthew G. Knepley       ierr = PetscTabulationDestroy(&Tcoarse);CHKERRQ(ierr);
5994cc7f7b2SMatthew G. Knepley       for (p = 0; p < numCIndices; ++p) rowIDXs[p] = cindices[p] + rStart;
6004cc7f7b2SMatthew G. Knepley       if (0) {ierr = DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat);CHKERRQ(ierr);}
6014cc7f7b2SMatthew G. Knepley       /* Block diagonal */
6024cc7f7b2SMatthew G. Knepley       {
6034cc7f7b2SMatthew G. Knepley         PetscBLASInt blasn, blask;
6044cc7f7b2SMatthew G. Knepley         PetscScalar  one = 1.0, zero = 0.0;
6054cc7f7b2SMatthew G. Knepley 
6064cc7f7b2SMatthew G. Knepley         ierr = PetscBLASIntCast(numCIndices, &blasn);CHKERRQ(ierr);
6074cc7f7b2SMatthew G. Knepley         ierr = PetscBLASIntCast(numFIndices, &blask);CHKERRQ(ierr);
6084cc7f7b2SMatthew G. Knepley         PetscStackCallBLAS("BLASgemm",BLASgemm_("T","N",&blasn,&blasn,&blask,&one,elemMat,&blask,elemMat,&blask,&zero,elemMatSq,&blasn));
6094cc7f7b2SMatthew G. Knepley       }
6104cc7f7b2SMatthew G. Knepley       ierr = MatSetValues(mass, numCIndices, rowIDXs, numCIndices, rowIDXs, elemMatSq, ADD_VALUES);CHKERRQ(ierr);
6114cc7f7b2SMatthew G. Knepley       /* TODO Off-diagonal */
6124cc7f7b2SMatthew G. Knepley       ierr = PetscFree(cindices);CHKERRQ(ierr);
6134cc7f7b2SMatthew G. Knepley       ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL);CHKERRQ(ierr);
6144cc7f7b2SMatthew G. Knepley     }
6154cc7f7b2SMatthew G. Knepley     ierr = DMSwarmRestoreField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **) &coords);CHKERRQ(ierr);
6164cc7f7b2SMatthew G. Knepley   }
6174cc7f7b2SMatthew G. Knepley   ierr = PetscFree4(elemMat, elemMatSq, rowIDXs, xi);CHKERRQ(ierr);
6184cc7f7b2SMatthew G. Knepley   ierr = PetscFree(adj);CHKERRQ(ierr);
6194cc7f7b2SMatthew G. Knepley   ierr = DMSwarmSortRestoreAccess(dmc);CHKERRQ(ierr);
6204cc7f7b2SMatthew G. Knepley   ierr = PetscFree3(v0, J, invJ);CHKERRQ(ierr);
6214cc7f7b2SMatthew G. Knepley   ierr = MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6224cc7f7b2SMatthew G. Knepley   ierr = MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6234cc7f7b2SMatthew G. Knepley   PetscFunctionReturn(0);
6244cc7f7b2SMatthew G. Knepley }
6254cc7f7b2SMatthew G. Knepley 
6264cc7f7b2SMatthew G. Knepley /*@C
6274cc7f7b2SMatthew G. Knepley   DMSwarmCreateMassMatrixSquare - Creates the block-diagonal of the square, M^T_p M_p, of the particle mass matrix M_p
6284cc7f7b2SMatthew G. Knepley 
6294cc7f7b2SMatthew G. Knepley   Collective on dmCoarse
6304cc7f7b2SMatthew G. Knepley 
6314cc7f7b2SMatthew G. Knepley   Input parameters:
6324cc7f7b2SMatthew G. Knepley + dmCoarse - a DMSwarm
6334cc7f7b2SMatthew G. Knepley - dmFine   - a DMPlex
6344cc7f7b2SMatthew G. Knepley 
6354cc7f7b2SMatthew G. Knepley   Output parameter:
6364cc7f7b2SMatthew G. Knepley . mass     - the square of the particle mass matrix
6374cc7f7b2SMatthew G. Knepley 
6384cc7f7b2SMatthew G. Knepley   Level: advanced
6394cc7f7b2SMatthew G. Knepley 
6404cc7f7b2SMatthew G. Knepley   Notes:
6414cc7f7b2SMatthew G. Knepley   We only compute the block diagonal since this provides a good preconditioner and is completely local. It would be possible in the
6424cc7f7b2SMatthew G. Knepley   future to compute the full normal equations.
6434cc7f7b2SMatthew G. Knepley 
6444cc7f7b2SMatthew G. Knepley .seealso: DMCreateMassMatrix()
6454cc7f7b2SMatthew G. Knepley @*/
6464cc7f7b2SMatthew G. Knepley PetscErrorCode DMSwarmCreateMassMatrixSquare(DM dmCoarse, DM dmFine, Mat *mass)
6474cc7f7b2SMatthew G. Knepley {
6484cc7f7b2SMatthew G. Knepley   PetscInt       n;
6494cc7f7b2SMatthew G. Knepley   void          *ctx;
6504cc7f7b2SMatthew G. Knepley   PetscErrorCode ierr;
6514cc7f7b2SMatthew G. Knepley 
6524cc7f7b2SMatthew G. Knepley   PetscFunctionBegin;
6534cc7f7b2SMatthew G. Knepley   ierr = DMSwarmGetLocalSize(dmCoarse, &n);CHKERRQ(ierr);
6544cc7f7b2SMatthew G. Knepley   ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr);
6554cc7f7b2SMatthew G. Knepley   ierr = MatSetSizes(*mass, n, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
6564cc7f7b2SMatthew G. Knepley   ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr);
6574cc7f7b2SMatthew G. Knepley   ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr);
6584cc7f7b2SMatthew G. Knepley 
6594cc7f7b2SMatthew G. Knepley   ierr = DMSwarmComputeMassMatrixSquare_Private(dmCoarse, dmFine, *mass, PETSC_TRUE, ctx);CHKERRQ(ierr);
6604cc7f7b2SMatthew G. Knepley   ierr = MatViewFromOptions(*mass, NULL, "-mass_sq_mat_view");CHKERRQ(ierr);
6614cc7f7b2SMatthew G. Knepley   PetscFunctionReturn(0);
6624cc7f7b2SMatthew G. Knepley }
6634cc7f7b2SMatthew G. Knepley 
664fb1bcc12SMatthew G. Knepley /*@C
665d3a51819SDave May    DMSwarmCreateGlobalVectorFromField - Creates a Vec object sharing the array associated with a given field
666d3a51819SDave May 
667d083f849SBarry Smith    Collective on dm
668d3a51819SDave May 
669d3a51819SDave May    Input parameters:
67062741f57SDave May +  dm - a DMSwarm
67162741f57SDave May -  fieldname - the textual name given to a registered field
672d3a51819SDave May 
6738b8a3813SDave May    Output parameter:
674d3a51819SDave May .  vec - the vector
675d3a51819SDave May 
676d3a51819SDave May    Level: beginner
677d3a51819SDave May 
6788b8a3813SDave May    Notes:
6798b8a3813SDave May    The vector must be returned using a matching call to DMSwarmDestroyGlobalVectorFromField().
6808b8a3813SDave May 
6818b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmDestroyGlobalVectorFromField()
682d3a51819SDave May @*/
68374d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmCreateGlobalVectorFromField(DM dm,const char fieldname[],Vec *vec)
684b5bcf523SDave May {
685fb1bcc12SMatthew G. Knepley   MPI_Comm       comm = PetscObjectComm((PetscObject) dm);
686b5bcf523SDave May   PetscErrorCode ierr;
687b5bcf523SDave May 
688fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
689fb1bcc12SMatthew G. Knepley   ierr = DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec);CHKERRQ(ierr);
690b5bcf523SDave May   PetscFunctionReturn(0);
691b5bcf523SDave May }
692b5bcf523SDave May 
693d3a51819SDave May /*@C
694d3a51819SDave May    DMSwarmDestroyGlobalVectorFromField - Destroys the Vec object which share the array associated with a given field
695d3a51819SDave May 
696d083f849SBarry Smith    Collective on dm
697d3a51819SDave May 
698d3a51819SDave May    Input parameters:
69962741f57SDave May +  dm - a DMSwarm
70062741f57SDave May -  fieldname - the textual name given to a registered field
701d3a51819SDave May 
7028b8a3813SDave May    Output parameter:
703d3a51819SDave May .  vec - the vector
704d3a51819SDave May 
705d3a51819SDave May    Level: beginner
706d3a51819SDave May 
7078b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmCreateGlobalVectorFromField()
708d3a51819SDave May @*/
70974d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmDestroyGlobalVectorFromField(DM dm,const char fieldname[],Vec *vec)
710b5bcf523SDave May {
711b5bcf523SDave May   PetscErrorCode ierr;
712cc651181SDave May 
713fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
714fb1bcc12SMatthew G. Knepley   ierr = DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec);CHKERRQ(ierr);
715b5bcf523SDave May   PetscFunctionReturn(0);
716b5bcf523SDave May }
717b5bcf523SDave May 
718fb1bcc12SMatthew G. Knepley /*@C
719fb1bcc12SMatthew G. Knepley    DMSwarmCreateLocalVectorFromField - Creates a Vec object sharing the array associated with a given field
720fb1bcc12SMatthew G. Knepley 
721d083f849SBarry Smith    Collective on dm
722fb1bcc12SMatthew G. Knepley 
723fb1bcc12SMatthew G. Knepley    Input parameters:
72462741f57SDave May +  dm - a DMSwarm
72562741f57SDave May -  fieldname - the textual name given to a registered field
726fb1bcc12SMatthew G. Knepley 
7278b8a3813SDave May    Output parameter:
728fb1bcc12SMatthew G. Knepley .  vec - the vector
729fb1bcc12SMatthew G. Knepley 
730fb1bcc12SMatthew G. Knepley    Level: beginner
731fb1bcc12SMatthew G. Knepley 
7328b8a3813SDave May    Notes:
7338b8a3813SDave May    The vector must be returned using a matching call to DMSwarmDestroyLocalVectorFromField().
7348b8a3813SDave May 
7358b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmDestroyLocalVectorFromField()
736fb1bcc12SMatthew G. Knepley @*/
73774d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmCreateLocalVectorFromField(DM dm,const char fieldname[],Vec *vec)
738bbe8250bSMatthew G. Knepley {
739fb1bcc12SMatthew G. Knepley   MPI_Comm       comm = PETSC_COMM_SELF;
740bbe8250bSMatthew G. Knepley   PetscErrorCode ierr;
741bbe8250bSMatthew G. Knepley 
742fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
743fb1bcc12SMatthew G. Knepley   ierr = DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec);CHKERRQ(ierr);
744fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
745bbe8250bSMatthew G. Knepley }
746fb1bcc12SMatthew G. Knepley 
747fb1bcc12SMatthew G. Knepley /*@C
748fb1bcc12SMatthew G. Knepley    DMSwarmDestroyLocalVectorFromField - Destroys the Vec object which share the array associated with a given field
749fb1bcc12SMatthew G. Knepley 
750d083f849SBarry Smith    Collective on dm
751fb1bcc12SMatthew G. Knepley 
752fb1bcc12SMatthew G. Knepley    Input parameters:
75362741f57SDave May +  dm - a DMSwarm
75462741f57SDave May -  fieldname - the textual name given to a registered field
755fb1bcc12SMatthew G. Knepley 
7568b8a3813SDave May    Output parameter:
757fb1bcc12SMatthew G. Knepley .  vec - the vector
758fb1bcc12SMatthew G. Knepley 
759fb1bcc12SMatthew G. Knepley    Level: beginner
760fb1bcc12SMatthew G. Knepley 
7618b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmCreateLocalVectorFromField()
762fb1bcc12SMatthew G. Knepley @*/
76374d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmDestroyLocalVectorFromField(DM dm,const char fieldname[],Vec *vec)
764fb1bcc12SMatthew G. Knepley {
765fb1bcc12SMatthew G. Knepley   PetscErrorCode ierr;
766fb1bcc12SMatthew G. Knepley 
767fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
768fb1bcc12SMatthew G. Knepley   ierr = DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec);CHKERRQ(ierr);
769bbe8250bSMatthew G. Knepley   PetscFunctionReturn(0);
770bbe8250bSMatthew G. Knepley }
771bbe8250bSMatthew G. Knepley 
772b5bcf523SDave May /*
77374d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmCreateGlobalVectorFromFields(DM dm,const PetscInt nf,const char *fieldnames[],Vec *vec)
774b5bcf523SDave May {
775b5bcf523SDave May   PetscFunctionReturn(0);
776b5bcf523SDave May }
777b5bcf523SDave May 
77874d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmRestoreGlobalVectorFromFields(DM dm,Vec *vec)
779b5bcf523SDave May {
780b5bcf523SDave May   PetscFunctionReturn(0);
781b5bcf523SDave May }
782b5bcf523SDave May */
783b5bcf523SDave May 
784d3a51819SDave May /*@C
785d3a51819SDave May    DMSwarmInitializeFieldRegister - Initiates the registration of fields to a DMSwarm
786d3a51819SDave May 
787d083f849SBarry Smith    Collective on dm
788d3a51819SDave May 
789d3a51819SDave May    Input parameter:
790d3a51819SDave May .  dm - a DMSwarm
791d3a51819SDave May 
792d3a51819SDave May    Level: beginner
793d3a51819SDave May 
794d3a51819SDave May    Notes:
7958b8a3813SDave May    After all fields have been registered, you must call DMSwarmFinalizeFieldRegister().
796d3a51819SDave May 
797d3a51819SDave May .seealso: DMSwarmFinalizeFieldRegister(), DMSwarmRegisterPetscDatatypeField(),
798d3a51819SDave May  DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
799d3a51819SDave May @*/
80074d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmInitializeFieldRegister(DM dm)
8015f50eb2eSDave May {
8025f50eb2eSDave May   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
8033454631fSDave May   PetscErrorCode ierr;
8043454631fSDave May 
805521f74f9SMatthew G. Knepley   PetscFunctionBegin;
806cc651181SDave May   if (!swarm->field_registration_initialized) {
8075f50eb2eSDave May     swarm->field_registration_initialized = PETSC_TRUE;
80843f984edSMatthew G. Knepley     ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_pid,1,PETSC_INT64);CHKERRQ(ierr); /* unique identifer */
809f0cdbbbaSDave May     ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_rank,1,PETSC_INT);CHKERRQ(ierr); /* used for communication */
810cc651181SDave May   }
8115f50eb2eSDave May   PetscFunctionReturn(0);
8125f50eb2eSDave May }
8135f50eb2eSDave May 
81474d0cae8SMatthew G. Knepley /*@
815d3a51819SDave May    DMSwarmFinalizeFieldRegister - Finalizes the registration of fields to a DMSwarm
816d3a51819SDave May 
817d083f849SBarry Smith    Collective on dm
818d3a51819SDave May 
819d3a51819SDave May    Input parameter:
820d3a51819SDave May .  dm - a DMSwarm
821d3a51819SDave May 
822d3a51819SDave May    Level: beginner
823d3a51819SDave May 
824d3a51819SDave May    Notes:
82562741f57SDave May    After DMSwarmFinalizeFieldRegister() has been called, no new fields can be defined on the DMSwarm.
826d3a51819SDave May 
827d3a51819SDave May .seealso: DMSwarmInitializeFieldRegister(), DMSwarmRegisterPetscDatatypeField(),
828d3a51819SDave May  DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
829d3a51819SDave May @*/
83074d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmFinalizeFieldRegister(DM dm)
8315f50eb2eSDave May {
8325f50eb2eSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
8336845f8f5SDave May   PetscErrorCode ierr;
8346845f8f5SDave May 
835521f74f9SMatthew G. Knepley   PetscFunctionBegin;
836f0cdbbbaSDave May   if (!swarm->field_registration_finalized) {
83777048351SPatrick Sanan     ierr = DMSwarmDataBucketFinalize(swarm->db);CHKERRQ(ierr);
838f0cdbbbaSDave May   }
839f0cdbbbaSDave May   swarm->field_registration_finalized = PETSC_TRUE;
8405f50eb2eSDave May   PetscFunctionReturn(0);
8415f50eb2eSDave May }
8425f50eb2eSDave May 
84374d0cae8SMatthew G. Knepley /*@
844d3a51819SDave May    DMSwarmSetLocalSizes - Sets the length of all registered fields on the DMSwarm
845d3a51819SDave May 
846d3a51819SDave May    Not collective
847d3a51819SDave May 
848d3a51819SDave May    Input parameters:
84962741f57SDave May +  dm - a DMSwarm
850d3a51819SDave May .  nlocal - the length of each registered field
85162741f57SDave May -  buffer - the length of the buffer used to efficient dynamic re-sizing
852d3a51819SDave May 
853d3a51819SDave May    Level: beginner
854d3a51819SDave May 
855d3a51819SDave May .seealso: DMSwarmGetLocalSize()
856d3a51819SDave May @*/
85774d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmSetLocalSizes(DM dm,PetscInt nlocal,PetscInt buffer)
8585f50eb2eSDave May {
8595f50eb2eSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
8606845f8f5SDave May   PetscErrorCode ierr;
8615f50eb2eSDave May 
862521f74f9SMatthew G. Knepley   PetscFunctionBegin;
863f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_SetSizes,0,0,0,0);CHKERRQ(ierr);
86477048351SPatrick Sanan   ierr = DMSwarmDataBucketSetSizes(swarm->db,nlocal,buffer);CHKERRQ(ierr);
865f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_SetSizes,0,0,0,0);CHKERRQ(ierr);
8665f50eb2eSDave May   PetscFunctionReturn(0);
8675f50eb2eSDave May }
8685f50eb2eSDave May 
86974d0cae8SMatthew G. Knepley /*@
870d3a51819SDave May    DMSwarmSetCellDM - Attachs a DM to a DMSwarm
871d3a51819SDave May 
872d083f849SBarry Smith    Collective on dm
873d3a51819SDave May 
874d3a51819SDave May    Input parameters:
87562741f57SDave May +  dm - a DMSwarm
87662741f57SDave May -  dmcell - the DM to attach to the DMSwarm
877d3a51819SDave May 
878d3a51819SDave May    Level: beginner
879d3a51819SDave May 
880d3a51819SDave May    Notes:
881d3a51819SDave May    The attached DM (dmcell) will be queried for point location and
8828b8a3813SDave May    neighbor MPI-rank information if DMSwarmMigrate() is called.
883d3a51819SDave May 
8848b8a3813SDave May .seealso: DMSwarmSetType(), DMSwarmGetCellDM(), DMSwarmMigrate()
885d3a51819SDave May @*/
88674d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmSetCellDM(DM dm,DM dmcell)
887b16650c8SDave May {
888b16650c8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
889521f74f9SMatthew G. Knepley 
890521f74f9SMatthew G. Knepley   PetscFunctionBegin;
891b16650c8SDave May   swarm->dmcell = dmcell;
892b16650c8SDave May   PetscFunctionReturn(0);
893b16650c8SDave May }
894b16650c8SDave May 
89574d0cae8SMatthew G. Knepley /*@
896d3a51819SDave May    DMSwarmGetCellDM - Fetches the attached cell DM
897d3a51819SDave May 
898d083f849SBarry Smith    Collective on dm
899d3a51819SDave May 
900d3a51819SDave May    Input parameter:
901d3a51819SDave May .  dm - a DMSwarm
902d3a51819SDave May 
903d3a51819SDave May    Output parameter:
904d3a51819SDave May .  dmcell - the DM which was attached to the DMSwarm
905d3a51819SDave May 
906d3a51819SDave May    Level: beginner
907d3a51819SDave May 
908d3a51819SDave May .seealso: DMSwarmSetCellDM()
909d3a51819SDave May @*/
91074d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmGetCellDM(DM dm,DM *dmcell)
911fe39f135SDave May {
912fe39f135SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
913521f74f9SMatthew G. Knepley 
914521f74f9SMatthew G. Knepley   PetscFunctionBegin;
915fe39f135SDave May   *dmcell = swarm->dmcell;
916fe39f135SDave May   PetscFunctionReturn(0);
917fe39f135SDave May }
918fe39f135SDave May 
91974d0cae8SMatthew G. Knepley /*@
920d3a51819SDave May    DMSwarmGetLocalSize - Retrives the local length of fields registered
921d3a51819SDave May 
922d3a51819SDave May    Not collective
923d3a51819SDave May 
924d3a51819SDave May    Input parameter:
925d3a51819SDave May .  dm - a DMSwarm
926d3a51819SDave May 
927d3a51819SDave May    Output parameter:
928d3a51819SDave May .  nlocal - the length of each registered field
929d3a51819SDave May 
930d3a51819SDave May    Level: beginner
931d3a51819SDave May 
9328b8a3813SDave May .seealso: DMSwarmGetSize(), DMSwarmSetLocalSizes()
933d3a51819SDave May @*/
93474d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmGetLocalSize(DM dm,PetscInt *nlocal)
935dcf43ee8SDave May {
936dcf43ee8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
937dcf43ee8SDave May   PetscErrorCode ierr;
938dcf43ee8SDave May 
939521f74f9SMatthew G. Knepley   PetscFunctionBegin;
94077048351SPatrick Sanan   if (nlocal) {ierr = DMSwarmDataBucketGetSizes(swarm->db,nlocal,NULL,NULL);CHKERRQ(ierr);}
941dcf43ee8SDave May   PetscFunctionReturn(0);
942dcf43ee8SDave May }
943dcf43ee8SDave May 
94474d0cae8SMatthew G. Knepley /*@
945d3a51819SDave May    DMSwarmGetSize - Retrives the total length of fields registered
946d3a51819SDave May 
947d083f849SBarry Smith    Collective on dm
948d3a51819SDave May 
949d3a51819SDave May    Input parameter:
950d3a51819SDave May .  dm - a DMSwarm
951d3a51819SDave May 
952d3a51819SDave May    Output parameter:
953d3a51819SDave May .  n - the total length of each registered field
954d3a51819SDave May 
955d3a51819SDave May    Level: beginner
956d3a51819SDave May 
957d3a51819SDave May    Note:
958d3a51819SDave May    This calls MPI_Allreduce upon each call (inefficient but safe)
959d3a51819SDave May 
9608b8a3813SDave May .seealso: DMSwarmGetLocalSize(), DMSwarmSetLocalSizes()
961d3a51819SDave May @*/
96274d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmGetSize(DM dm,PetscInt *n)
963dcf43ee8SDave May {
964dcf43ee8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
965dcf43ee8SDave May   PetscErrorCode ierr;
966dcf43ee8SDave May   PetscInt       nlocal,ng;
967dcf43ee8SDave May 
968521f74f9SMatthew G. Knepley   PetscFunctionBegin;
96977048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
970ffc4695bSBarry Smith   ierr = MPI_Allreduce(&nlocal,&ng,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr);
971dcf43ee8SDave May   if (n) { *n = ng; }
972dcf43ee8SDave May   PetscFunctionReturn(0);
973dcf43ee8SDave May }
974dcf43ee8SDave May 
975d3a51819SDave May /*@C
9768b8a3813SDave May    DMSwarmRegisterPetscDatatypeField - Register a field to a DMSwarm with a native PETSc data type
977d3a51819SDave May 
978d083f849SBarry Smith    Collective on dm
979d3a51819SDave May 
980d3a51819SDave May    Input parameters:
98162741f57SDave May +  dm - a DMSwarm
982d3a51819SDave May .  fieldname - the textual name to identify this field
983d3a51819SDave May .  blocksize - the number of each data type
98462741f57SDave May -  type - a valid PETSc data type (PETSC_CHAR, PETSC_SHORT, PETSC_INT, PETSC_FLOAT, PETSC_REAL, PETSC_LONG)
985d3a51819SDave May 
986d3a51819SDave May    Level: beginner
987d3a51819SDave May 
988d3a51819SDave May    Notes:
9898b8a3813SDave May    The textual name for each registered field must be unique.
990d3a51819SDave May 
991d3a51819SDave May .seealso: DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
992d3a51819SDave May @*/
99374d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmRegisterPetscDatatypeField(DM dm,const char fieldname[],PetscInt blocksize,PetscDataType type)
994b62e03f8SDave May {
9952eac95f8SDave May   PetscErrorCode ierr;
996b62e03f8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
997b62e03f8SDave May   size_t         size;
998b62e03f8SDave May 
999521f74f9SMatthew G. Knepley   PetscFunctionBegin;
10005f50eb2eSDave May   if (!swarm->field_registration_initialized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmInitializeFieldRegister() first");
10015f50eb2eSDave May   if (swarm->field_registration_finalized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Cannot register additional fields after calling DMSwarmFinalizeFieldRegister() first");
10025f50eb2eSDave May 
10035f50eb2eSDave May   if (type == PETSC_OBJECT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
10045f50eb2eSDave May   if (type == PETSC_FUNCTION) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
10055f50eb2eSDave May   if (type == PETSC_STRING) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
10065f50eb2eSDave May   if (type == PETSC_STRUCT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
10075f50eb2eSDave May   if (type == PETSC_DATATYPE_UNKNOWN) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
1008b62e03f8SDave May 
10092ddcf43eSMatthew G. Knepley   ierr = PetscDataTypeGetSize(type, &size);CHKERRQ(ierr);
1010b62e03f8SDave May   /* Load a specific data type into data bucket, specifying textual name and its size in bytes */
101177048351SPatrick Sanan   ierr = DMSwarmDataBucketRegisterField(swarm->db,"DMSwarmRegisterPetscDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
101252c3ed93SDave May   {
101377048351SPatrick Sanan     DMSwarmDataField gfield;
101452c3ed93SDave May 
101577048351SPatrick Sanan     ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
101677048351SPatrick Sanan     ierr = DMSwarmDataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
101752c3ed93SDave May   }
1018b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = type;
1019b62e03f8SDave May   PetscFunctionReturn(0);
1020b62e03f8SDave May }
1021b62e03f8SDave May 
1022d3a51819SDave May /*@C
1023d3a51819SDave May    DMSwarmRegisterUserStructField - Register a user defined struct to a DMSwarm
1024d3a51819SDave May 
1025d083f849SBarry Smith    Collective on dm
1026d3a51819SDave May 
1027d3a51819SDave May    Input parameters:
102862741f57SDave May +  dm - a DMSwarm
1029d3a51819SDave May .  fieldname - the textual name to identify this field
103062741f57SDave May -  size - the size in bytes of the user struct of each data type
1031d3a51819SDave May 
1032d3a51819SDave May    Level: beginner
1033d3a51819SDave May 
1034d3a51819SDave May    Notes:
10358b8a3813SDave May    The textual name for each registered field must be unique.
1036d3a51819SDave May 
1037d3a51819SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserDatatypeField()
1038d3a51819SDave May @*/
103974d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmRegisterUserStructField(DM dm,const char fieldname[],size_t size)
1040b62e03f8SDave May {
10412eac95f8SDave May   PetscErrorCode ierr;
1042b62e03f8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1043b62e03f8SDave May 
1044521f74f9SMatthew G. Knepley   PetscFunctionBegin;
104577048351SPatrick Sanan   ierr = DMSwarmDataBucketRegisterField(swarm->db,"DMSwarmRegisterUserStructField",fieldname,size,NULL);CHKERRQ(ierr);
1046b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_STRUCT ;
1047b62e03f8SDave May   PetscFunctionReturn(0);
1048b62e03f8SDave May }
1049b62e03f8SDave May 
1050d3a51819SDave May /*@C
1051d3a51819SDave May    DMSwarmRegisterUserDatatypeField - Register a user defined data type to a DMSwarm
1052d3a51819SDave May 
1053d083f849SBarry Smith    Collective on dm
1054d3a51819SDave May 
1055d3a51819SDave May    Input parameters:
105662741f57SDave May +  dm - a DMSwarm
1057d3a51819SDave May .  fieldname - the textual name to identify this field
1058d3a51819SDave May .  size - the size in bytes of the user data type
105962741f57SDave May -  blocksize - the number of each data type
1060d3a51819SDave May 
1061d3a51819SDave May    Level: beginner
1062d3a51819SDave May 
1063d3a51819SDave May    Notes:
10648b8a3813SDave May    The textual name for each registered field must be unique.
1065d3a51819SDave May 
1066d3a51819SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
1067d3a51819SDave May @*/
106874d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmRegisterUserDatatypeField(DM dm,const char fieldname[],size_t size,PetscInt blocksize)
1069b62e03f8SDave May {
1070b62e03f8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
10716845f8f5SDave May   PetscErrorCode ierr;
1072b62e03f8SDave May 
1073521f74f9SMatthew G. Knepley   PetscFunctionBegin;
107477048351SPatrick Sanan   ierr = DMSwarmDataBucketRegisterField(swarm->db,"DMSwarmRegisterUserDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
1075320740a0SDave May   {
107677048351SPatrick Sanan     DMSwarmDataField gfield;
1077320740a0SDave May 
107877048351SPatrick Sanan     ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
107977048351SPatrick Sanan     ierr = DMSwarmDataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
1080320740a0SDave May   }
1081b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_DATATYPE_UNKNOWN;
1082b62e03f8SDave May   PetscFunctionReturn(0);
1083b62e03f8SDave May }
1084b62e03f8SDave May 
1085d3a51819SDave May /*@C
1086d3a51819SDave May    DMSwarmGetField - Get access to the underlying array storing all entries associated with a registered field
1087d3a51819SDave May 
1088d3a51819SDave May    Not collective
1089d3a51819SDave May 
1090d3a51819SDave May    Input parameters:
109162741f57SDave May +  dm - a DMSwarm
109262741f57SDave May -  fieldname - the textual name to identify this field
1093d3a51819SDave May 
1094d3a51819SDave May    Output parameters:
109562741f57SDave May +  blocksize - the number of each data type
1096d3a51819SDave May .  type - the data type
109762741f57SDave May -  data - pointer to raw array
1098d3a51819SDave May 
1099d3a51819SDave May    Level: beginner
1100d3a51819SDave May 
1101d3a51819SDave May    Notes:
11028b8a3813SDave May    The array must be returned using a matching call to DMSwarmRestoreField().
1103d3a51819SDave May 
1104d3a51819SDave May .seealso: DMSwarmRestoreField()
1105d3a51819SDave May @*/
110674d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmGetField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
1107b62e03f8SDave May {
1108b62e03f8SDave May   DM_Swarm         *swarm = (DM_Swarm*)dm->data;
110977048351SPatrick Sanan   DMSwarmDataField gfield;
11102eac95f8SDave May   PetscErrorCode ierr;
1111b62e03f8SDave May 
1112521f74f9SMatthew G. Knepley   PetscFunctionBegin;
11133454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
111477048351SPatrick Sanan   ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
111577048351SPatrick Sanan   ierr = DMSwarmDataFieldGetAccess(gfield);CHKERRQ(ierr);
111677048351SPatrick Sanan   ierr = DMSwarmDataFieldGetEntries(gfield,data);CHKERRQ(ierr);
11171b1ea282SDave May   if (blocksize) {*blocksize = gfield->bs; }
1118b5bcf523SDave May   if (type) { *type = gfield->petsc_type; }
1119b62e03f8SDave May   PetscFunctionReturn(0);
1120b62e03f8SDave May }
1121b62e03f8SDave May 
1122d3a51819SDave May /*@C
1123d3a51819SDave May    DMSwarmRestoreField - Restore access to the underlying array storing all entries associated with a registered field
1124d3a51819SDave May 
1125d3a51819SDave May    Not collective
1126d3a51819SDave May 
1127d3a51819SDave May    Input parameters:
112862741f57SDave May +  dm - a DMSwarm
112962741f57SDave May -  fieldname - the textual name to identify this field
1130d3a51819SDave May 
1131d3a51819SDave May    Output parameters:
113262741f57SDave May +  blocksize - the number of each data type
1133d3a51819SDave May .  type - the data type
113462741f57SDave May -  data - pointer to raw array
1135d3a51819SDave May 
1136d3a51819SDave May    Level: beginner
1137d3a51819SDave May 
1138d3a51819SDave May    Notes:
11398b8a3813SDave May    The user must call DMSwarmGetField() prior to calling DMSwarmRestoreField().
1140d3a51819SDave May 
1141d3a51819SDave May .seealso: DMSwarmGetField()
1142d3a51819SDave May @*/
114374d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmRestoreField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
1144b62e03f8SDave May {
1145b62e03f8SDave May   DM_Swarm         *swarm = (DM_Swarm*)dm->data;
114677048351SPatrick Sanan   DMSwarmDataField gfield;
11472eac95f8SDave May   PetscErrorCode ierr;
1148b62e03f8SDave May 
1149521f74f9SMatthew G. Knepley   PetscFunctionBegin;
115077048351SPatrick Sanan   ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
115177048351SPatrick Sanan   ierr = DMSwarmDataFieldRestoreAccess(gfield);CHKERRQ(ierr);
1152b62e03f8SDave May   if (data) *data = NULL;
1153b62e03f8SDave May   PetscFunctionReturn(0);
1154b62e03f8SDave May }
1155b62e03f8SDave May 
115674d0cae8SMatthew G. Knepley /*@
1157d3a51819SDave May    DMSwarmAddPoint - Add space for one new point in the DMSwarm
1158d3a51819SDave May 
1159d3a51819SDave May    Not collective
1160d3a51819SDave May 
1161d3a51819SDave May    Input parameter:
1162d3a51819SDave May .  dm - a DMSwarm
1163d3a51819SDave May 
1164d3a51819SDave May    Level: beginner
1165d3a51819SDave May 
1166d3a51819SDave May    Notes:
11678b8a3813SDave May    The new point will have all fields initialized to zero.
1168d3a51819SDave May 
1169d3a51819SDave May .seealso: DMSwarmAddNPoints()
1170d3a51819SDave May @*/
117174d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmAddPoint(DM dm)
1172cb1d1399SDave May {
1173cb1d1399SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1174cb1d1399SDave May   PetscErrorCode ierr;
1175cb1d1399SDave May 
1176521f74f9SMatthew G. Knepley   PetscFunctionBegin;
11773454631fSDave May   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
1178f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
117977048351SPatrick Sanan   ierr = DMSwarmDataBucketAddPoint(swarm->db);CHKERRQ(ierr);
1180f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
1181cb1d1399SDave May   PetscFunctionReturn(0);
1182cb1d1399SDave May }
1183cb1d1399SDave May 
118474d0cae8SMatthew G. Knepley /*@
1185d3a51819SDave May    DMSwarmAddNPoints - Add space for a number of new points in the DMSwarm
1186d3a51819SDave May 
1187d3a51819SDave May    Not collective
1188d3a51819SDave May 
1189d3a51819SDave May    Input parameters:
119062741f57SDave May +  dm - a DMSwarm
119162741f57SDave May -  npoints - the number of new points to add
1192d3a51819SDave May 
1193d3a51819SDave May    Level: beginner
1194d3a51819SDave May 
1195d3a51819SDave May    Notes:
11968b8a3813SDave May    The new point will have all fields initialized to zero.
1197d3a51819SDave May 
1198d3a51819SDave May .seealso: DMSwarmAddPoint()
1199d3a51819SDave May @*/
120074d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmAddNPoints(DM dm,PetscInt npoints)
1201cb1d1399SDave May {
1202cb1d1399SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1203cb1d1399SDave May   PetscErrorCode ierr;
1204cb1d1399SDave May   PetscInt       nlocal;
1205cb1d1399SDave May 
1206521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1207f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
120877048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
1209cb1d1399SDave May   nlocal = nlocal + npoints;
121077048351SPatrick Sanan   ierr = DMSwarmDataBucketSetSizes(swarm->db,nlocal,DMSWARM_DATA_BUCKET_BUFFER_DEFAULT);CHKERRQ(ierr);
1211f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
1212cb1d1399SDave May   PetscFunctionReturn(0);
1213cb1d1399SDave May }
1214cb1d1399SDave May 
121574d0cae8SMatthew G. Knepley /*@
1216d3a51819SDave May    DMSwarmRemovePoint - Remove the last point from the DMSwarm
1217d3a51819SDave May 
1218d3a51819SDave May    Not collective
1219d3a51819SDave May 
1220d3a51819SDave May    Input parameter:
1221d3a51819SDave May .  dm - a DMSwarm
1222d3a51819SDave May 
1223d3a51819SDave May    Level: beginner
1224d3a51819SDave May 
1225d3a51819SDave May .seealso: DMSwarmRemovePointAtIndex()
1226d3a51819SDave May @*/
122774d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmRemovePoint(DM dm)
1228cb1d1399SDave May {
1229cb1d1399SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1230cb1d1399SDave May   PetscErrorCode ierr;
1231cb1d1399SDave May 
1232521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1233f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
123477048351SPatrick Sanan   ierr = DMSwarmDataBucketRemovePoint(swarm->db);CHKERRQ(ierr);
1235f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
1236cb1d1399SDave May   PetscFunctionReturn(0);
1237cb1d1399SDave May }
1238cb1d1399SDave May 
123974d0cae8SMatthew G. Knepley /*@
1240d3a51819SDave May    DMSwarmRemovePointAtIndex - Removes a specific point from the DMSwarm
1241d3a51819SDave May 
1242d3a51819SDave May    Not collective
1243d3a51819SDave May 
1244d3a51819SDave May    Input parameters:
124562741f57SDave May +  dm - a DMSwarm
124662741f57SDave May -  idx - index of point to remove
1247d3a51819SDave May 
1248d3a51819SDave May    Level: beginner
1249d3a51819SDave May 
1250d3a51819SDave May .seealso: DMSwarmRemovePoint()
1251d3a51819SDave May @*/
125274d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmRemovePointAtIndex(DM dm,PetscInt idx)
1253cb1d1399SDave May {
1254cb1d1399SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1255cb1d1399SDave May   PetscErrorCode ierr;
1256cb1d1399SDave May 
1257521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1258f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
125977048351SPatrick Sanan   ierr = DMSwarmDataBucketRemovePointAtIndex(swarm->db,idx);CHKERRQ(ierr);
1260f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
1261cb1d1399SDave May   PetscFunctionReturn(0);
1262cb1d1399SDave May }
1263b62e03f8SDave May 
126474d0cae8SMatthew G. Knepley /*@
1265ba4fc9c6SDave May    DMSwarmCopyPoint - Copy point pj to point pi in the DMSwarm
1266ba4fc9c6SDave May 
1267ba4fc9c6SDave May    Not collective
1268ba4fc9c6SDave May 
1269ba4fc9c6SDave May    Input parameters:
1270ba4fc9c6SDave May +  dm - a DMSwarm
1271ba4fc9c6SDave May .  pi - the index of the point to copy
1272ba4fc9c6SDave May -  pj - the point index where the copy should be located
1273ba4fc9c6SDave May 
1274ba4fc9c6SDave May  Level: beginner
1275ba4fc9c6SDave May 
1276ba4fc9c6SDave May .seealso: DMSwarmRemovePoint()
1277ba4fc9c6SDave May @*/
127874d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmCopyPoint(DM dm,PetscInt pi,PetscInt pj)
1279ba4fc9c6SDave May {
1280ba4fc9c6SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1281ba4fc9c6SDave May   PetscErrorCode ierr;
1282ba4fc9c6SDave May 
1283ba4fc9c6SDave May   PetscFunctionBegin;
1284ba4fc9c6SDave May   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
128577048351SPatrick Sanan   ierr = DMSwarmDataBucketCopyPoint(swarm->db,pi,swarm->db,pj);CHKERRQ(ierr);
1286ba4fc9c6SDave May   PetscFunctionReturn(0);
1287ba4fc9c6SDave May }
1288ba4fc9c6SDave May 
1289095059a4SDave May PetscErrorCode DMSwarmMigrate_Basic(DM dm,PetscBool remove_sent_points)
12903454631fSDave May {
1291dcf43ee8SDave May   PetscErrorCode ierr;
1292521f74f9SMatthew G. Knepley 
1293521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1294dcf43ee8SDave May   ierr = DMSwarmMigrate_Push_Basic(dm,remove_sent_points);CHKERRQ(ierr);
12953454631fSDave May   PetscFunctionReturn(0);
12963454631fSDave May }
12973454631fSDave May 
129874d0cae8SMatthew G. Knepley /*@
1299d3a51819SDave May    DMSwarmMigrate - Relocates points defined in the DMSwarm to other MPI-ranks
1300d3a51819SDave May 
1301d083f849SBarry Smith    Collective on dm
1302d3a51819SDave May 
1303d3a51819SDave May    Input parameters:
130462741f57SDave May +  dm - the DMSwarm
130562741f57SDave May -  remove_sent_points - flag indicating if sent points should be removed from the current MPI-rank
1306d3a51819SDave May 
1307d3a51819SDave May    Notes:
13088b8a3813SDave May    The DM will be modified to accomodate received points.
13098b8a3813SDave May    If remove_sent_points = PETSC_TRUE, any points that were sent will be removed from the DM.
13108b8a3813SDave May    Different styles of migration are supported. See DMSwarmSetMigrateType().
1311d3a51819SDave May 
1312d3a51819SDave May    Level: advanced
1313d3a51819SDave May 
1314d3a51819SDave May .seealso: DMSwarmSetMigrateType()
1315d3a51819SDave May @*/
131674d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmMigrate(DM dm,PetscBool remove_sent_points)
13173454631fSDave May {
1318f0cdbbbaSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
13193454631fSDave May   PetscErrorCode ierr;
1320f0cdbbbaSDave May 
1321521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1322ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
1323f0cdbbbaSDave May   switch (swarm->migrate_type) {
1324f0cdbbbaSDave May     case DMSWARM_MIGRATE_BASIC:
1325095059a4SDave May       ierr = DMSwarmMigrate_Basic(dm,remove_sent_points);CHKERRQ(ierr);
1326f0cdbbbaSDave May       break;
1327f0cdbbbaSDave May     case DMSWARM_MIGRATE_DMCELLNSCATTER:
1328f0cdbbbaSDave May       ierr = DMSwarmMigrate_CellDMScatter(dm,remove_sent_points);CHKERRQ(ierr);
1329f0cdbbbaSDave May       break;
1330f0cdbbbaSDave May     case DMSWARM_MIGRATE_DMCELLEXACT:
1331f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_DMCELLEXACT not implemented");
1332f0cdbbbaSDave May     case DMSWARM_MIGRATE_USER:
1333f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_USER not implemented");
1334f0cdbbbaSDave May     default:
1335f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE type unknown");
1336f0cdbbbaSDave May   }
1337ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
1338183d2d45SMatthew G. Knepley   ierr = DMClearGlobalVectors(dm);CHKERRQ(ierr);
13393454631fSDave May   PetscFunctionReturn(0);
13403454631fSDave May }
13413454631fSDave May 
1342f0cdbbbaSDave May PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm,PetscInt *globalsize);
1343f0cdbbbaSDave May 
1344d3a51819SDave May /*
1345d3a51819SDave May  DMSwarmCollectViewCreate
1346d3a51819SDave May 
1347d3a51819SDave May  * Applies a collection method and gathers point neighbour points into dm
1348d3a51819SDave May 
1349d3a51819SDave May  Notes:
13508b8a3813SDave May  Users should call DMSwarmCollectViewDestroy() after
1351d3a51819SDave May  they have finished computations associated with the collected points
1352d3a51819SDave May */
1353d3a51819SDave May 
135474d0cae8SMatthew G. Knepley /*@
1355d3a51819SDave May    DMSwarmCollectViewCreate - Applies a collection method and gathers points
1356d3a51819SDave May    in neighbour MPI-ranks into the DMSwarm
1357d3a51819SDave May 
1358d083f849SBarry Smith    Collective on dm
1359d3a51819SDave May 
1360d3a51819SDave May    Input parameter:
1361d3a51819SDave May .  dm - the DMSwarm
1362d3a51819SDave May 
1363d3a51819SDave May    Notes:
1364d3a51819SDave May    Users should call DMSwarmCollectViewDestroy() after
1365d3a51819SDave May    they have finished computations associated with the collected points
13668b8a3813SDave May    Different collect methods are supported. See DMSwarmSetCollectType().
1367d3a51819SDave May 
1368d3a51819SDave May    Level: advanced
1369d3a51819SDave May 
1370d3a51819SDave May .seealso: DMSwarmCollectViewDestroy(), DMSwarmSetCollectType()
1371d3a51819SDave May @*/
137274d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmCollectViewCreate(DM dm)
13732712d1f2SDave May {
13742712d1f2SDave May   PetscErrorCode ierr;
13752712d1f2SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
13762712d1f2SDave May   PetscInt ng;
13772712d1f2SDave May 
1378521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1379480eef7bSDave May   if (swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView currently active");
1380480eef7bSDave May   ierr = DMSwarmGetLocalSize(dm,&ng);CHKERRQ(ierr);
1381480eef7bSDave May   switch (swarm->collect_type) {
1382f0cdbbbaSDave May 
1383480eef7bSDave May     case DMSWARM_COLLECT_BASIC:
13842712d1f2SDave May       ierr = DMSwarmMigrate_GlobalToLocal_Basic(dm,&ng);CHKERRQ(ierr);
1385480eef7bSDave May       break;
1386480eef7bSDave May     case DMSWARM_COLLECT_DMDABOUNDINGBOX:
1387f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_DMDABOUNDINGBOX not implemented");
1388480eef7bSDave May     case DMSWARM_COLLECT_GENERAL:
1389f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_GENERAL not implemented");
1390480eef7bSDave May     default:
1391f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT type unknown");
1392480eef7bSDave May   }
1393480eef7bSDave May   swarm->collect_view_active = PETSC_TRUE;
1394480eef7bSDave May   swarm->collect_view_reset_nlocal = ng;
13952712d1f2SDave May   PetscFunctionReturn(0);
13962712d1f2SDave May }
13972712d1f2SDave May 
139874d0cae8SMatthew G. Knepley /*@
1399d3a51819SDave May    DMSwarmCollectViewDestroy - Resets the DMSwarm to the size prior to calling DMSwarmCollectViewCreate()
1400d3a51819SDave May 
1401d083f849SBarry Smith    Collective on dm
1402d3a51819SDave May 
1403d3a51819SDave May    Input parameters:
1404d3a51819SDave May .  dm - the DMSwarm
1405d3a51819SDave May 
1406d3a51819SDave May    Notes:
1407d3a51819SDave May    Users should call DMSwarmCollectViewCreate() before this function is called.
1408d3a51819SDave May 
1409d3a51819SDave May    Level: advanced
1410d3a51819SDave May 
1411d3a51819SDave May .seealso: DMSwarmCollectViewCreate(), DMSwarmSetCollectType()
1412d3a51819SDave May @*/
141374d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmCollectViewDestroy(DM dm)
14142712d1f2SDave May {
14152712d1f2SDave May   PetscErrorCode ierr;
14162712d1f2SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
14172712d1f2SDave May 
1418521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1419480eef7bSDave May   if (!swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView is currently not active");
1420480eef7bSDave May   ierr = DMSwarmSetLocalSizes(dm,swarm->collect_view_reset_nlocal,-1);CHKERRQ(ierr);
1421480eef7bSDave May   swarm->collect_view_active = PETSC_FALSE;
14222712d1f2SDave May   PetscFunctionReturn(0);
14232712d1f2SDave May }
14243454631fSDave May 
1425f0cdbbbaSDave May PetscErrorCode DMSwarmSetUpPIC(DM dm)
1426f0cdbbbaSDave May {
1427f0cdbbbaSDave May   PetscInt       dim;
1428f0cdbbbaSDave May   PetscErrorCode ierr;
1429f0cdbbbaSDave May 
1430521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1431f0cdbbbaSDave May   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
1432f0cdbbbaSDave May   if (dim < 1) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
1433f0cdbbbaSDave May   if (dim > 3) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
1434f0cdbbbaSDave May   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_coor,dim,PETSC_DOUBLE);CHKERRQ(ierr);
1435e2d107dbSDave May   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_cellid,1,PETSC_INT);CHKERRQ(ierr);
1436f0cdbbbaSDave May   PetscFunctionReturn(0);
1437f0cdbbbaSDave May }
1438f0cdbbbaSDave May 
143974d0cae8SMatthew G. Knepley /*@
144031403186SMatthew G. Knepley   DMSwarmSetPointCoordinatesRandom - Sets initial coordinates for particles in each cell
144131403186SMatthew G. Knepley 
144231403186SMatthew G. Knepley   Collective on dm
144331403186SMatthew G. Knepley 
144431403186SMatthew G. Knepley   Input parameters:
144531403186SMatthew G. Knepley + dm  - the DMSwarm
144631403186SMatthew G. Knepley - Npc - The number of particles per cell in the cell DM
144731403186SMatthew G. Knepley 
144831403186SMatthew G. Knepley   Notes:
144931403186SMatthew G. Knepley   The user must use DMSwarmSetCellDM() to set the cell DM first. The particles are placed randomly inside each cell. If only
145031403186SMatthew G. Knepley   one particle is in each cell, it is placed at the centroid.
145131403186SMatthew G. Knepley 
145231403186SMatthew G. Knepley   Level: intermediate
145331403186SMatthew G. Knepley 
145431403186SMatthew G. Knepley .seealso: DMSwarmSetCellDM()
145531403186SMatthew G. Knepley @*/
145631403186SMatthew G. Knepley PetscErrorCode DMSwarmSetPointCoordinatesRandom(DM dm, PetscInt Npc)
145731403186SMatthew G. Knepley {
145831403186SMatthew G. Knepley   DM             cdm;
145931403186SMatthew G. Knepley   PetscRandom    rnd;
146031403186SMatthew G. Knepley   DMPolytopeType ct;
146131403186SMatthew G. Knepley   PetscBool      simplex;
146231403186SMatthew G. Knepley   PetscReal     *centroid, *coords, *xi0, *v0, *J, *invJ, detJ;
146331403186SMatthew G. Knepley   PetscInt       dim, d, cStart, cEnd, c, p;
146431403186SMatthew G. Knepley   PetscErrorCode ierr;
146531403186SMatthew G. Knepley 
146631403186SMatthew G. Knepley   PetscFunctionBeginUser;
146731403186SMatthew G. Knepley   ierr = PetscRandomCreate(PetscObjectComm((PetscObject) dm), &rnd);CHKERRQ(ierr);
146831403186SMatthew G. Knepley   ierr = PetscRandomSetInterval(rnd, -1.0, 1.0);CHKERRQ(ierr);
146931403186SMatthew G. Knepley   ierr = PetscRandomSetType(rnd, PETSCRAND48);CHKERRQ(ierr);
147031403186SMatthew G. Knepley 
147131403186SMatthew G. Knepley   ierr = DMSwarmGetCellDM(dm, &cdm);CHKERRQ(ierr);
147231403186SMatthew G. Knepley   ierr = DMGetDimension(cdm, &dim);CHKERRQ(ierr);
147331403186SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr);
147431403186SMatthew G. Knepley   ierr = DMPlexGetCellType(cdm, cStart, &ct);CHKERRQ(ierr);
147531403186SMatthew G. Knepley   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE;
147631403186SMatthew G. Knepley 
147731403186SMatthew G. Knepley   ierr = PetscMalloc5(dim, &centroid, dim, &xi0, dim, &v0, dim*dim, &J, dim*dim, &invJ);CHKERRQ(ierr);
147831403186SMatthew G. Knepley   for (d = 0; d < dim; ++d) xi0[d] = -1.0;
147931403186SMatthew G. Knepley   ierr = DMSwarmGetField(dm, DMSwarmPICField_coor, NULL, NULL, (void **) &coords);CHKERRQ(ierr);
148031403186SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
148131403186SMatthew G. Knepley     if (Npc == 1) {
148231403186SMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFVM(cdm, c, NULL, centroid, NULL);CHKERRQ(ierr);
148331403186SMatthew G. Knepley       for (d = 0; d < dim; ++d) coords[c*dim+d] = centroid[d];
148431403186SMatthew G. Knepley     } else {
148531403186SMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFEM(cdm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); /* affine */
148631403186SMatthew G. Knepley       for (p = 0; p < Npc; ++p) {
148731403186SMatthew G. Knepley         const PetscInt n   = c*Npc + p;
148831403186SMatthew G. Knepley         PetscReal      sum = 0.0, refcoords[3];
148931403186SMatthew G. Knepley 
149031403186SMatthew G. Knepley         for (d = 0; d < dim; ++d) {
149131403186SMatthew G. Knepley           ierr = PetscRandomGetValueReal(rnd, &refcoords[d]);CHKERRQ(ierr);
149231403186SMatthew G. Knepley           sum += refcoords[d];
149331403186SMatthew G. Knepley         }
149431403186SMatthew G. Knepley         if (simplex && sum > 0.0) for (d = 0; d < dim; ++d) refcoords[d] -= PetscSqrtReal(dim)*sum;
149531403186SMatthew G. Knepley         CoordinatesRefToReal(dim, dim, xi0, v0, J, refcoords, &coords[n*dim]);
149631403186SMatthew G. Knepley       }
149731403186SMatthew G. Knepley     }
149831403186SMatthew G. Knepley   }
149931403186SMatthew G. Knepley   ierr = DMSwarmRestoreField(dm, DMSwarmPICField_coor, NULL, NULL, (void **) &coords);CHKERRQ(ierr);
150031403186SMatthew G. Knepley   ierr = PetscFree5(centroid, xi0, v0, J, invJ);CHKERRQ(ierr);
150131403186SMatthew G. Knepley   ierr = PetscRandomDestroy(&rnd);CHKERRQ(ierr);
150231403186SMatthew G. Knepley   PetscFunctionReturn(0);
150331403186SMatthew G. Knepley }
150431403186SMatthew G. Knepley 
150531403186SMatthew G. Knepley /*@
1506d3a51819SDave May    DMSwarmSetType - Set particular flavor of DMSwarm
1507d3a51819SDave May 
1508d083f849SBarry Smith    Collective on dm
1509d3a51819SDave May 
1510d3a51819SDave May    Input parameters:
151162741f57SDave May +  dm - the DMSwarm
151262741f57SDave May -  stype - the DMSwarm type (e.g. DMSWARM_PIC)
1513d3a51819SDave May 
1514d3a51819SDave May    Level: advanced
1515d3a51819SDave May 
1516d3a51819SDave May .seealso: DMSwarmSetMigrateType(), DMSwarmSetCollectType()
1517d3a51819SDave May @*/
151874d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmSetType(DM dm,DMSwarmType stype)
1519f0cdbbbaSDave May {
1520f0cdbbbaSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1521f0cdbbbaSDave May   PetscErrorCode ierr;
1522f0cdbbbaSDave May 
1523521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1524f0cdbbbaSDave May   swarm->swarm_type = stype;
1525f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
1526f0cdbbbaSDave May     ierr = DMSwarmSetUpPIC(dm);CHKERRQ(ierr);
1527f0cdbbbaSDave May   }
1528f0cdbbbaSDave May   PetscFunctionReturn(0);
1529f0cdbbbaSDave May }
1530f0cdbbbaSDave May 
15313454631fSDave May PetscErrorCode DMSetup_Swarm(DM dm)
15323454631fSDave May {
15333454631fSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
15343454631fSDave May   PetscErrorCode ierr;
15353454631fSDave May   PetscMPIInt    rank;
15363454631fSDave May   PetscInt       p,npoints,*rankval;
15373454631fSDave May 
1538521f74f9SMatthew G. Knepley   PetscFunctionBegin;
15393454631fSDave May   if (swarm->issetup) PetscFunctionReturn(0);
15403454631fSDave May 
15413454631fSDave May   swarm->issetup = PETSC_TRUE;
15423454631fSDave May 
1543f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
1544f0cdbbbaSDave May     /* check dmcell exists */
1545f0cdbbbaSDave May     if (!swarm->dmcell) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires you call DMSwarmSetCellDM");
1546f0cdbbbaSDave May 
1547f0cdbbbaSDave May     if (swarm->dmcell->ops->locatepointssubdomain) {
1548f0cdbbbaSDave May       /* check methods exists for exact ownership identificiation */
154977b6ec44SMatthew G. Knepley       ierr = PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->ops->LocatePointsSubdomain\n");CHKERRQ(ierr);
1550f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLEXACT;
1551f0cdbbbaSDave May     } else {
1552f0cdbbbaSDave May       /* check methods exist for point location AND rank neighbor identification */
1553f0cdbbbaSDave May       if (swarm->dmcell->ops->locatepoints) {
155477b6ec44SMatthew G. Knepley         ierr = PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->LocatePoints\n");CHKERRQ(ierr);
1555f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->locatepoints be defined");
1556f0cdbbbaSDave May 
1557f0cdbbbaSDave May       if (swarm->dmcell->ops->getneighbors) {
155877b6ec44SMatthew G. Knepley         ierr = PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->GetNeigbors\n");CHKERRQ(ierr);
1559f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->getneighbors be defined");
1560f0cdbbbaSDave May 
1561f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLNSCATTER;
1562f0cdbbbaSDave May     }
1563f0cdbbbaSDave May   }
1564f0cdbbbaSDave May 
1565f0cdbbbaSDave May   ierr = DMSwarmFinalizeFieldRegister(dm);CHKERRQ(ierr);
1566f0cdbbbaSDave May 
15673454631fSDave May   /* check some fields were registered */
15683454631fSDave May   if (swarm->db->nfields <= 2) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"At least one field user must be registered via DMSwarmRegisterXXX()");
15693454631fSDave May 
15703454631fSDave May   /* check local sizes were set */
15713454631fSDave May   if (swarm->db->L == -1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Local sizes must be set via DMSwarmSetLocalSizes()");
15723454631fSDave May 
15733454631fSDave May   /* initialize values in pid and rank placeholders */
15743454631fSDave May   /* TODO: [pid - use MPI_Scan] */
1575ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRMPI(ierr);
157677048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db,&npoints,NULL,NULL);CHKERRQ(ierr);
1577f0cdbbbaSDave May   ierr = DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
15783454631fSDave May   for (p=0; p<npoints; p++) {
15793454631fSDave May     rankval[p] = (PetscInt)rank;
15803454631fSDave May   }
1581f0cdbbbaSDave May   ierr = DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
15823454631fSDave May   PetscFunctionReturn(0);
15833454631fSDave May }
15843454631fSDave May 
1585dc5f5ce9SDave May extern PetscErrorCode DMSwarmSortDestroy(DMSwarmSort *_ctx);
1586dc5f5ce9SDave May 
158757795646SDave May PetscErrorCode DMDestroy_Swarm(DM dm)
158857795646SDave May {
158957795646SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
159057795646SDave May   PetscErrorCode ierr;
159157795646SDave May 
159257795646SDave May   PetscFunctionBegin;
1593d0c080abSJoseph Pusztay   if (--swarm->refct > 0) PetscFunctionReturn(0);
159477048351SPatrick Sanan   ierr = DMSwarmDataBucketDestroy(&swarm->db);CHKERRQ(ierr);
1595dc5f5ce9SDave May   if (swarm->sort_context) {
1596dc5f5ce9SDave May     ierr = DMSwarmSortDestroy(&swarm->sort_context);CHKERRQ(ierr);
1597dc5f5ce9SDave May   }
159857795646SDave May   ierr = PetscFree(swarm);CHKERRQ(ierr);
159957795646SDave May   PetscFunctionReturn(0);
160057795646SDave May }
160157795646SDave May 
1602a9ee3421SMatthew G. Knepley PetscErrorCode DMSwarmView_Draw(DM dm, PetscViewer viewer)
1603a9ee3421SMatthew G. Knepley {
1604a9ee3421SMatthew G. Knepley   DM             cdm;
1605a9ee3421SMatthew G. Knepley   PetscDraw      draw;
160631403186SMatthew G. Knepley   PetscReal     *coords, oldPause, radius = 0.01;
1607a9ee3421SMatthew G. Knepley   PetscInt       Np, p, bs;
1608a9ee3421SMatthew G. Knepley   PetscErrorCode ierr;
1609a9ee3421SMatthew G. Knepley 
1610a9ee3421SMatthew G. Knepley   PetscFunctionBegin;
161131403186SMatthew G. Knepley   ierr = PetscOptionsGetReal(NULL, ((PetscObject) dm)->prefix, "-dm_view_swarm_radius", &radius, NULL);CHKERRQ(ierr);
1612a9ee3421SMatthew G. Knepley   ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr);
1613a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetCellDM(dm, &cdm);CHKERRQ(ierr);
1614a9ee3421SMatthew G. Knepley   ierr = PetscDrawGetPause(draw, &oldPause);CHKERRQ(ierr);
1615a9ee3421SMatthew G. Knepley   ierr = PetscDrawSetPause(draw, 0.0);CHKERRQ(ierr);
1616a9ee3421SMatthew G. Knepley   ierr = DMView(cdm, viewer);CHKERRQ(ierr);
1617a9ee3421SMatthew G. Knepley   ierr = PetscDrawSetPause(draw, oldPause);CHKERRQ(ierr);
1618a9ee3421SMatthew G. Knepley 
1619a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetLocalSize(dm, &Np);CHKERRQ(ierr);
1620a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1621a9ee3421SMatthew G. Knepley   for (p = 0; p < Np; ++p) {
1622a9ee3421SMatthew G. Knepley     const PetscInt i = p*bs;
1623a9ee3421SMatthew G. Knepley 
162431403186SMatthew G. Knepley     ierr = PetscDrawEllipse(draw, coords[i], coords[i+1], radius, radius, PETSC_DRAW_BLUE);CHKERRQ(ierr);
1625a9ee3421SMatthew G. Knepley   }
1626a9ee3421SMatthew G. Knepley   ierr = DMSwarmRestoreField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1627a9ee3421SMatthew G. Knepley   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
1628a9ee3421SMatthew G. Knepley   ierr = PetscDrawPause(draw);CHKERRQ(ierr);
1629a9ee3421SMatthew G. Knepley   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
1630a9ee3421SMatthew G. Knepley   PetscFunctionReturn(0);
1631a9ee3421SMatthew G. Knepley }
1632a9ee3421SMatthew G. Knepley 
16335f50eb2eSDave May PetscErrorCode DMView_Swarm(DM dm, PetscViewer viewer)
16345f50eb2eSDave May {
16355f50eb2eSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1636a9ee3421SMatthew G. Knepley   PetscBool      iascii,ibinary,ishdf5,isvtk,isdraw;
16375f50eb2eSDave May   PetscErrorCode ierr;
16385f50eb2eSDave May 
16395f50eb2eSDave May   PetscFunctionBegin;
16405f50eb2eSDave May   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
16415f50eb2eSDave May   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
16425f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
16435f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY,&ibinary);CHKERRQ(ierr);
16445f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK,   &isvtk);CHKERRQ(ierr);
16455f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
1646a9ee3421SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW,  &isdraw);CHKERRQ(ierr);
16475f50eb2eSDave May   if (iascii) {
164877048351SPatrick Sanan     ierr = DMSwarmDataBucketView(PetscObjectComm((PetscObject)dm),swarm->db,NULL,DATABUCKET_VIEW_STDOUT);CHKERRQ(ierr);
1649298827fbSBarry Smith   } else if (ibinary) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO Binary support");
16505f50eb2eSDave May #if defined(PETSC_HAVE_HDF5)
165174d0cae8SMatthew G. Knepley   else if (ishdf5) {
165274d0cae8SMatthew G. Knepley     ierr = DMSwarmView_HDF5(dm, viewer);CHKERRQ(ierr);
165374d0cae8SMatthew G. Knepley   }
16545f50eb2eSDave May #else
1655298827fbSBarry Smith   else if (ishdf5) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"HDF5 not supported. Please reconfigure using --download-hdf5");
16565f50eb2eSDave May #endif
1657298827fbSBarry Smith   else if (isvtk) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO VTK support");
1658298827fbSBarry Smith   else if (isdraw) {
1659a9ee3421SMatthew G. Knepley     ierr = DMSwarmView_Draw(dm, viewer);CHKERRQ(ierr);
16605f50eb2eSDave May   }
16615f50eb2eSDave May   PetscFunctionReturn(0);
16625f50eb2eSDave May }
16635f50eb2eSDave May 
1664d0c080abSJoseph Pusztay /*@C
1665d0c080abSJoseph Pusztay    DMSwarmGetCellSwarm - Extracts a single cell from the DMSwarm object, returns it as a single cell DMSwarm.
1666d0c080abSJoseph Pusztay    The cell DM is filtered for fields of that cell, and the filtered DM is used as the cell DM of the new swarm object.
1667d0c080abSJoseph Pusztay 
1668d0c080abSJoseph Pusztay    Important: Changes to this cell of the swarm will be lost if they are made prior to restoring this cell.
1669d0c080abSJoseph Pusztay 
1670d0c080abSJoseph Pusztay    Noncollective
1671d0c080abSJoseph Pusztay 
1672d0c080abSJoseph Pusztay    Input parameters:
1673d0c080abSJoseph Pusztay +  sw - the DMSwarm
1674d0c080abSJoseph Pusztay -  cellID - the integer id of the cell to be extracted and filtered
1675d0c080abSJoseph Pusztay 
1676d0c080abSJoseph Pusztay    Output parameters:
1677d0c080abSJoseph Pusztay .  cellswarm - The new DMSwarm
1678d0c080abSJoseph Pusztay 
1679d0c080abSJoseph Pusztay    Level: beginner
1680d0c080abSJoseph Pusztay 
1681d0c080abSJoseph Pusztay    Note: This presently only supports DMSWARM_PIC type
1682d0c080abSJoseph Pusztay 
1683d0c080abSJoseph Pusztay .seealso: DMSwarmRestoreCellSwarm()
1684d0c080abSJoseph Pusztay @*/
1685d0c080abSJoseph Pusztay PETSC_EXTERN PetscErrorCode DMSwarmGetCellSwarm(DM sw, PetscInt cellID, DM cellswarm)
1686d0c080abSJoseph Pusztay {
1687d0c080abSJoseph Pusztay   DM_Swarm      *original = (DM_Swarm*) sw->data;
1688d0c080abSJoseph Pusztay   DMLabel        label;
1689d0c080abSJoseph Pusztay   DM             dmc, subdmc;
1690d0c080abSJoseph Pusztay   PetscInt      *pids, particles, dim;
1691d0c080abSJoseph Pusztay   PetscErrorCode ierr;
1692d0c080abSJoseph Pusztay 
1693d0c080abSJoseph Pusztay   PetscFunctionBegin;
1694d0c080abSJoseph Pusztay   /* Configure new swarm */
1695d0c080abSJoseph Pusztay   ierr = DMSetType(cellswarm, DMSWARM);CHKERRQ(ierr);
1696d0c080abSJoseph Pusztay   ierr = DMGetDimension(sw, &dim);CHKERRQ(ierr);
1697d0c080abSJoseph Pusztay   ierr = DMSetDimension(cellswarm, dim);CHKERRQ(ierr);
1698d0c080abSJoseph Pusztay   ierr = DMSwarmSetType(cellswarm, DMSWARM_PIC);CHKERRQ(ierr);
1699d0c080abSJoseph Pusztay   /* Destroy the unused, unconfigured data bucket to prevent stragglers in memory */
1700*1e1ea65dSPierre Jolivet   ierr = DMSwarmDataBucketDestroy(&((DM_Swarm*)cellswarm->data)->db);CHKERRQ(ierr);
1701d0c080abSJoseph Pusztay   ierr = DMSwarmSortGetAccess(sw);CHKERRQ(ierr);
1702d0c080abSJoseph Pusztay   ierr = DMSwarmSortGetNumberOfPointsPerCell(sw, cellID, &particles);CHKERRQ(ierr);
1703d0c080abSJoseph Pusztay   ierr = DMSwarmSortGetPointsPerCell(sw, cellID, &particles, &pids);CHKERRQ(ierr);
1704*1e1ea65dSPierre Jolivet   ierr = DMSwarmDataBucketCreateFromSubset(original->db, particles, pids, &((DM_Swarm*)cellswarm->data)->db);CHKERRQ(ierr);
1705d0c080abSJoseph Pusztay   ierr = DMSwarmSortRestoreAccess(sw);CHKERRQ(ierr);
1706d0c080abSJoseph Pusztay   ierr = PetscFree(pids);CHKERRQ(ierr);
1707d0c080abSJoseph Pusztay   ierr = DMSwarmGetCellDM(sw, &dmc);CHKERRQ(ierr);
1708d0c080abSJoseph Pusztay   ierr = DMLabelCreate(PetscObjectComm((PetscObject)sw), "singlecell", &label);CHKERRQ(ierr);
1709d0c080abSJoseph Pusztay   ierr = DMAddLabel(dmc, label);CHKERRQ(ierr);
1710d0c080abSJoseph Pusztay   ierr = DMLabelSetValue(label, cellID, 1);CHKERRQ(ierr);
1711d0c080abSJoseph Pusztay   ierr = DMPlexFilter(dmc, label, 1, &subdmc);CHKERRQ(ierr);
1712*1e1ea65dSPierre Jolivet   ierr = DMSwarmSetCellDM(cellswarm, subdmc);CHKERRQ(ierr);
1713*1e1ea65dSPierre Jolivet   ierr = DMLabelDestroy(&label);CHKERRQ(ierr);
1714d0c080abSJoseph Pusztay   PetscFunctionReturn(0);
1715d0c080abSJoseph Pusztay }
1716d0c080abSJoseph Pusztay 
1717d0c080abSJoseph Pusztay /*@C
1718d0c080abSJoseph Pusztay    DMSwarmRestoreCellSwarm - Restores a DMSwarm object obtained with DMSwarmGetCellSwarm. All fields are copied back into the parent swarm.
1719d0c080abSJoseph Pusztay 
1720d0c080abSJoseph Pusztay    Noncollective
1721d0c080abSJoseph Pusztay 
1722d0c080abSJoseph Pusztay    Input parameters:
1723d0c080abSJoseph Pusztay +  sw - the parent DMSwarm
1724d0c080abSJoseph Pusztay .  cellID - the integer id of the cell to be copied back into the parent swarm
1725d0c080abSJoseph Pusztay -  cellswarm - the cell swarm object
1726d0c080abSJoseph Pusztay 
1727d0c080abSJoseph Pusztay    Level: beginner
1728d0c080abSJoseph Pusztay 
1729d0c080abSJoseph Pusztay    Note: This only supports DMSWARM_PIC types of DMSwarms
1730d0c080abSJoseph Pusztay 
1731d0c080abSJoseph Pusztay .seealso: DMSwarmGetCellSwarm()
1732d0c080abSJoseph Pusztay @*/
1733d0c080abSJoseph Pusztay PETSC_EXTERN PetscErrorCode DMSwarmRestoreCellSwarm(DM sw, PetscInt cellID, DM cellswarm)
1734d0c080abSJoseph Pusztay {
1735d0c080abSJoseph Pusztay   DM                dmc;
1736d0c080abSJoseph Pusztay   PetscInt         *pids, particles, p;
1737d0c080abSJoseph Pusztay   PetscErrorCode    ierr;
1738d0c080abSJoseph Pusztay 
1739d0c080abSJoseph Pusztay   PetscFunctionBegin;
1740d0c080abSJoseph Pusztay   ierr = DMSwarmSortGetAccess(sw);CHKERRQ(ierr);
1741d0c080abSJoseph Pusztay   ierr = DMSwarmSortGetPointsPerCell(sw, cellID, &particles, &pids);CHKERRQ(ierr);
1742d0c080abSJoseph Pusztay   ierr = DMSwarmSortRestoreAccess(sw);CHKERRQ(ierr);
1743d0c080abSJoseph Pusztay   /* Pointwise copy of each particle based on pid. The parent swarm may not be altered during this process. */
1744d0c080abSJoseph Pusztay   for (p=0; p<particles; ++p) {
1745d0c080abSJoseph Pusztay     ierr = DMSwarmDataBucketCopyPoint(((DM_Swarm*)cellswarm->data)->db,pids[p],((DM_Swarm*)sw->data)->db,pids[p]);CHKERRQ(ierr);
1746d0c080abSJoseph Pusztay   }
1747d0c080abSJoseph Pusztay   /* Free memory, destroy cell dm */
1748*1e1ea65dSPierre Jolivet   ierr = DMSwarmGetCellDM(cellswarm, &dmc);CHKERRQ(ierr);
1749*1e1ea65dSPierre Jolivet   ierr = DMDestroy(&dmc);CHKERRQ(ierr);
1750d0c080abSJoseph Pusztay   ierr = PetscFree(pids);CHKERRQ(ierr);
1751d0c080abSJoseph Pusztay   PetscFunctionReturn(0);
1752d0c080abSJoseph Pusztay }
1753d0c080abSJoseph Pusztay 
1754d0c080abSJoseph Pusztay PETSC_INTERN PetscErrorCode DMClone_Swarm(DM, DM *);
1755d0c080abSJoseph Pusztay 
1756d0c080abSJoseph Pusztay static PetscErrorCode DMInitialize_Swarm(DM sw)
1757d0c080abSJoseph Pusztay {
1758d0c080abSJoseph Pusztay   PetscFunctionBegin;
1759d0c080abSJoseph Pusztay   sw->dim  = 0;
1760d0c080abSJoseph Pusztay   sw->ops->view                            = DMView_Swarm;
1761d0c080abSJoseph Pusztay   sw->ops->load                            = NULL;
1762d0c080abSJoseph Pusztay   sw->ops->setfromoptions                  = NULL;
1763d0c080abSJoseph Pusztay   sw->ops->clone                           = DMClone_Swarm;
1764d0c080abSJoseph Pusztay   sw->ops->setup                           = DMSetup_Swarm;
1765d0c080abSJoseph Pusztay   sw->ops->createlocalsection              = NULL;
1766d0c080abSJoseph Pusztay   sw->ops->createdefaultconstraints        = NULL;
1767d0c080abSJoseph Pusztay   sw->ops->createglobalvector              = DMCreateGlobalVector_Swarm;
1768d0c080abSJoseph Pusztay   sw->ops->createlocalvector               = DMCreateLocalVector_Swarm;
1769d0c080abSJoseph Pusztay   sw->ops->getlocaltoglobalmapping         = NULL;
1770d0c080abSJoseph Pusztay   sw->ops->createfieldis                   = NULL;
1771d0c080abSJoseph Pusztay   sw->ops->createcoordinatedm              = NULL;
1772d0c080abSJoseph Pusztay   sw->ops->getcoloring                     = NULL;
1773d0c080abSJoseph Pusztay   sw->ops->creatematrix                    = DMCreateMatrix_Swarm;
1774d0c080abSJoseph Pusztay   sw->ops->createinterpolation             = NULL;
1775d0c080abSJoseph Pusztay   sw->ops->createinjection                 = NULL;
1776d0c080abSJoseph Pusztay   sw->ops->createmassmatrix                = DMCreateMassMatrix_Swarm;
1777d0c080abSJoseph Pusztay   sw->ops->refine                          = NULL;
1778d0c080abSJoseph Pusztay   sw->ops->coarsen                         = NULL;
1779d0c080abSJoseph Pusztay   sw->ops->refinehierarchy                 = NULL;
1780d0c080abSJoseph Pusztay   sw->ops->coarsenhierarchy                = NULL;
1781d0c080abSJoseph Pusztay   sw->ops->globaltolocalbegin              = NULL;
1782d0c080abSJoseph Pusztay   sw->ops->globaltolocalend                = NULL;
1783d0c080abSJoseph Pusztay   sw->ops->localtoglobalbegin              = NULL;
1784d0c080abSJoseph Pusztay   sw->ops->localtoglobalend                = NULL;
1785d0c080abSJoseph Pusztay   sw->ops->destroy                         = DMDestroy_Swarm;
1786d0c080abSJoseph Pusztay   sw->ops->createsubdm                     = NULL;
1787d0c080abSJoseph Pusztay   sw->ops->getdimpoints                    = NULL;
1788d0c080abSJoseph Pusztay   sw->ops->locatepoints                    = NULL;
1789d0c080abSJoseph Pusztay   PetscFunctionReturn(0);
1790d0c080abSJoseph Pusztay }
1791d0c080abSJoseph Pusztay 
1792d0c080abSJoseph Pusztay PETSC_INTERN PetscErrorCode DMClone_Swarm(DM dm, DM *newdm)
1793d0c080abSJoseph Pusztay {
1794d0c080abSJoseph Pusztay   DM_Swarm       *swarm = (DM_Swarm *) dm->data;
1795d0c080abSJoseph Pusztay   PetscErrorCode ierr;
1796d0c080abSJoseph Pusztay 
1797d0c080abSJoseph Pusztay   PetscFunctionBegin;
1798d0c080abSJoseph Pusztay   swarm->refct++;
1799d0c080abSJoseph Pusztay   (*newdm)->data = swarm;
1800d0c080abSJoseph Pusztay   ierr = PetscObjectChangeTypeName((PetscObject) *newdm, DMSWARM);CHKERRQ(ierr);
1801d0c080abSJoseph Pusztay   ierr = DMInitialize_Swarm(*newdm);CHKERRQ(ierr);
1802d0c080abSJoseph Pusztay   PetscFunctionReturn(0);
1803d0c080abSJoseph Pusztay }
1804d0c080abSJoseph Pusztay 
1805d3a51819SDave May /*MC
1806d3a51819SDave May 
1807d3a51819SDave May  DMSWARM = "swarm" - A DM object used to represent arrays of data (fields) of arbitrary data type.
180862741f57SDave May  This implementation was designed for particle methods in which the underlying
1809d3a51819SDave May  data required to be represented is both (i) dynamic in length, (ii) and of arbitrary data type.
1810d3a51819SDave May 
181162741f57SDave May  User data can be represented by DMSwarm through a registering "fields".
181262741f57SDave May  To register a field, the user must provide;
181362741f57SDave May  (a) a unique name;
181462741f57SDave May  (b) the data type (or size in bytes);
181562741f57SDave May  (c) the block size of the data.
1816d3a51819SDave May 
1817d3a51819SDave May  For example, suppose the application requires a unique id, energy, momentum and density to be stored
1818c215a47eSMatthew Knepley  on a set of particles. Then the following code could be used
1819d3a51819SDave May 
182062741f57SDave May $    DMSwarmInitializeFieldRegister(dm)
182162741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"uid",1,PETSC_LONG);
182262741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"energy",1,PETSC_REAL);
182362741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"momentum",3,PETSC_REAL);
182462741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"density",1,PETSC_FLOAT);
182562741f57SDave May $    DMSwarmFinalizeFieldRegister(dm)
1826d3a51819SDave May 
1827d3a51819SDave May  The fields represented by DMSwarm are dynamic and can be re-sized at any time.
182862741f57SDave May  The only restriction imposed by DMSwarm is that all fields contain the same number of points.
1829d3a51819SDave May 
1830d3a51819SDave May  To support particle methods, "migration" techniques are provided. These methods migrate data
1831d3a51819SDave May  between MPI-ranks.
1832d3a51819SDave May 
1833d3a51819SDave May  DMSwarm supports the methods DMCreateGlobalVector() and DMCreateLocalVector().
1834d3a51819SDave May  As a DMSwarm may internally define and store values of different data types,
183562741f57SDave May  before calling DMCreateGlobalVector() or DMCreateLocalVector(), the user must inform DMSwarm which
1836d3a51819SDave May  fields should be used to define a Vec object via
1837d3a51819SDave May    DMSwarmVectorDefineField()
1838c215a47eSMatthew Knepley  The specified field can be changed at any time - thereby permitting vectors
1839c215a47eSMatthew Knepley  compatible with different fields to be created.
1840d3a51819SDave May 
184162741f57SDave May  A dual representation of fields in the DMSwarm and a Vec object is permitted via
1842d3a51819SDave May    DMSwarmCreateGlobalVectorFromField()
1843d3a51819SDave May  Here the data defining the field in the DMSwarm is shared with a Vec.
1844d3a51819SDave May  This is inherently unsafe if you alter the size of the field at any time between
1845d3a51819SDave May  calls to DMSwarmCreateGlobalVectorFromField() and DMSwarmDestroyGlobalVectorFromField().
1846cc651181SDave May  If the local size of the DMSwarm does not match the local size of the global vector
1847cc651181SDave May  when DMSwarmDestroyGlobalVectorFromField() is called, an error is thrown.
1848d3a51819SDave May 
184962741f57SDave May  Additional high-level support is provided for Particle-In-Cell methods.
185062741f57SDave May  Please refer to the man page for DMSwarmSetType().
185162741f57SDave May 
1852d3a51819SDave May  Level: beginner
1853d3a51819SDave May 
1854d3a51819SDave May .seealso: DMType, DMCreate(), DMSetType()
1855d3a51819SDave May M*/
185657795646SDave May PETSC_EXTERN PetscErrorCode DMCreate_Swarm(DM dm)
185757795646SDave May {
185857795646SDave May   DM_Swarm      *swarm;
185957795646SDave May   PetscErrorCode ierr;
186057795646SDave May 
186157795646SDave May   PetscFunctionBegin;
186257795646SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
186357795646SDave May   ierr     = PetscNewLog(dm,&swarm);CHKERRQ(ierr);
1864f0cdbbbaSDave May   dm->data = swarm;
186577048351SPatrick Sanan   ierr = DMSwarmDataBucketCreate(&swarm->db);CHKERRQ(ierr);
1866f0cdbbbaSDave May   ierr = DMSwarmInitializeFieldRegister(dm);CHKERRQ(ierr);
1867d0c080abSJoseph Pusztay   swarm->refct = 1;
1868b5bcf523SDave May   swarm->vec_field_set = PETSC_FALSE;
18693454631fSDave May   swarm->issetup = PETSC_FALSE;
1870480eef7bSDave May   swarm->swarm_type = DMSWARM_BASIC;
1871480eef7bSDave May   swarm->migrate_type = DMSWARM_MIGRATE_BASIC;
1872480eef7bSDave May   swarm->collect_type = DMSWARM_COLLECT_BASIC;
187340c453e9SDave May   swarm->migrate_error_on_missing_point = PETSC_FALSE;
1874f0cdbbbaSDave May   swarm->dmcell = NULL;
1875f0cdbbbaSDave May   swarm->collect_view_active = PETSC_FALSE;
1876f0cdbbbaSDave May   swarm->collect_view_reset_nlocal = -1;
1877d0c080abSJoseph Pusztay   ierr = DMInitialize_Swarm(dm);CHKERRQ(ierr);
187857795646SDave May   PetscFunctionReturn(0);
187957795646SDave May }
1880