xref: /petsc/src/dm/impls/swarm/swarm.c (revision 5627991adfa0dae03dda7a34b1ec5f8d16d5e5f7)
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 #if defined(PETSC_HAVE_HDF5)
2874d0cae8SMatthew G. Knepley #include <petscviewerhdf5.h>
2974d0cae8SMatthew G. Knepley 
3074d0cae8SMatthew G. Knepley PetscErrorCode VecView_Swarm_HDF5_Internal(Vec v, PetscViewer viewer)
3174d0cae8SMatthew G. Knepley {
3274d0cae8SMatthew G. Knepley   DM             dm;
3374d0cae8SMatthew G. Knepley   PetscReal      seqval;
3474d0cae8SMatthew G. Knepley   PetscInt       seqnum, bs;
3574d0cae8SMatthew G. Knepley   PetscBool      isseq;
3674d0cae8SMatthew G. Knepley   PetscErrorCode ierr;
3774d0cae8SMatthew G. Knepley 
3874d0cae8SMatthew G. Knepley   PetscFunctionBegin;
3974d0cae8SMatthew G. Knepley   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
4074d0cae8SMatthew G. Knepley   ierr = VecGetBlockSize(v, &bs);CHKERRQ(ierr);
4174d0cae8SMatthew G. Knepley   ierr = PetscViewerHDF5PushGroup(viewer, "/particle_fields");CHKERRQ(ierr);
4274d0cae8SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr);
4374d0cae8SMatthew G. Knepley   ierr = DMGetOutputSequenceNumber(dm, &seqnum, &seqval);CHKERRQ(ierr);
4474d0cae8SMatthew G. Knepley   ierr = PetscViewerHDF5SetTimestep(viewer, seqnum);CHKERRQ(ierr);
4574d0cae8SMatthew G. Knepley   /* ierr = DMSequenceView_HDF5(dm, "time", seqnum, (PetscScalar) seqval, viewer);CHKERRQ(ierr); */
46f9558f5cSBarry Smith   ierr = VecViewNative(v, viewer);CHKERRQ(ierr);
4774d0cae8SMatthew G. Knepley   ierr = PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject) v, "Nc", PETSC_INT, (void *) &bs);CHKERRQ(ierr);
4874d0cae8SMatthew G. Knepley   ierr = PetscViewerHDF5PopGroup(viewer);CHKERRQ(ierr);
4974d0cae8SMatthew G. Knepley   PetscFunctionReturn(0);
5074d0cae8SMatthew G. Knepley }
5174d0cae8SMatthew G. Knepley 
5274d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmView_HDF5(DM dm, PetscViewer viewer)
5374d0cae8SMatthew G. Knepley {
5474d0cae8SMatthew G. Knepley   Vec            coordinates;
5574d0cae8SMatthew G. Knepley   PetscInt       Np;
5674d0cae8SMatthew G. Knepley   PetscBool      isseq;
5774d0cae8SMatthew G. Knepley   PetscErrorCode ierr;
5874d0cae8SMatthew G. Knepley 
5974d0cae8SMatthew G. Knepley   PetscFunctionBegin;
6074d0cae8SMatthew G. Knepley   ierr = DMSwarmGetSize(dm, &Np);CHKERRQ(ierr);
6174d0cae8SMatthew G. Knepley   ierr = DMSwarmCreateGlobalVectorFromField(dm, DMSwarmPICField_coor, &coordinates);CHKERRQ(ierr);
6274d0cae8SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) coordinates, "coordinates");CHKERRQ(ierr);
6374d0cae8SMatthew G. Knepley   ierr = PetscViewerHDF5PushGroup(viewer, "/particles");CHKERRQ(ierr);
6474d0cae8SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) coordinates, VECSEQ, &isseq);CHKERRQ(ierr);
65f9558f5cSBarry Smith   ierr = VecViewNative(coordinates, viewer);CHKERRQ(ierr);
6674d0cae8SMatthew G. Knepley   ierr = PetscViewerHDF5WriteObjectAttribute(viewer, (PetscObject) coordinates, "Np", PETSC_INT, (void *) &Np);CHKERRQ(ierr);
6774d0cae8SMatthew G. Knepley   ierr = PetscViewerHDF5PopGroup(viewer);CHKERRQ(ierr);
6874d0cae8SMatthew G. Knepley   ierr = DMSwarmDestroyGlobalVectorFromField(dm, DMSwarmPICField_coor, &coordinates);CHKERRQ(ierr);
6974d0cae8SMatthew G. Knepley   PetscFunctionReturn(0);
7074d0cae8SMatthew G. Knepley }
7174d0cae8SMatthew G. Knepley #endif
7274d0cae8SMatthew G. Knepley 
7374d0cae8SMatthew G. Knepley PetscErrorCode VecView_Swarm(Vec v, PetscViewer viewer)
7474d0cae8SMatthew G. Knepley {
7574d0cae8SMatthew G. Knepley   DM             dm;
76f9558f5cSBarry Smith #if defined(PETSC_HAVE_HDF5)
7774d0cae8SMatthew G. Knepley   PetscBool      ishdf5;
78f9558f5cSBarry Smith #endif
7974d0cae8SMatthew G. Knepley   PetscErrorCode ierr;
8074d0cae8SMatthew G. Knepley 
8174d0cae8SMatthew G. Knepley   PetscFunctionBegin;
8274d0cae8SMatthew G. Knepley   ierr = VecGetDM(v, &dm);CHKERRQ(ierr);
8374d0cae8SMatthew G. Knepley   if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM");
84f9558f5cSBarry Smith #if defined(PETSC_HAVE_HDF5)
8574d0cae8SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
8674d0cae8SMatthew G. Knepley   if (ishdf5) {
8774d0cae8SMatthew G. Knepley       ierr = VecView_Swarm_HDF5_Internal(v, viewer);CHKERRQ(ierr);
88f9558f5cSBarry Smith       PetscFunctionReturn(0);
8974d0cae8SMatthew G. Knepley   }
90f9558f5cSBarry Smith #endif
91f9558f5cSBarry Smith   ierr = VecViewNative(v, viewer);CHKERRQ(ierr);
9274d0cae8SMatthew G. Knepley   PetscFunctionReturn(0);
9374d0cae8SMatthew G. Knepley }
9474d0cae8SMatthew G. Knepley 
95d3a51819SDave May /*@C
9662741f57SDave May    DMSwarmVectorDefineField - Sets the field from which to define a Vec object
9762741f57SDave May                              when DMCreateLocalVector(), or DMCreateGlobalVector() is called
9857795646SDave May 
99d083f849SBarry Smith    Collective on dm
10057795646SDave May 
101d3a51819SDave May    Input parameters:
10262741f57SDave May +  dm - a DMSwarm
10362741f57SDave May -  fieldname - the textual name given to a registered field
10457795646SDave May 
105d3a51819SDave May    Level: beginner
10657795646SDave May 
107d3a51819SDave May    Notes:
108e7af74c8SDave May 
10962741f57SDave May    The field with name fieldname must be defined as having a data type of PetscScalar.
110e7af74c8SDave May 
111d3a51819SDave May    This function must be called prior to calling DMCreateLocalVector(), DMCreateGlobalVector().
112d3a51819SDave May    Mutiple calls to DMSwarmVectorDefineField() are permitted.
11357795646SDave May 
1148b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMCreateGlobalVector(), DMCreateLocalVector()
115d3a51819SDave May @*/
11674d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmVectorDefineField(DM dm,const char fieldname[])
117b5bcf523SDave May {
118b5bcf523SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
119b5bcf523SDave May   PetscErrorCode ierr;
120b5bcf523SDave May   PetscInt       bs,n;
121b5bcf523SDave May   PetscScalar    *array;
122b5bcf523SDave May   PetscDataType  type;
123b5bcf523SDave May 
124a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
1253454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
12677048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db,&n,NULL,NULL);CHKERRQ(ierr);
127b5bcf523SDave May   ierr = DMSwarmGetField(dm,fieldname,&bs,&type,(void**)&array);CHKERRQ(ierr);
128b5bcf523SDave May 
129b5bcf523SDave May   /* Check all fields are of type PETSC_REAL or PETSC_SCALAR */
130b5bcf523SDave May   if (type != PETSC_REAL) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Only valid for PETSC_REAL");
131521f74f9SMatthew G. Knepley   ierr = PetscSNPrintf(swarm->vec_field_name,PETSC_MAX_PATH_LEN-1,"%s",fieldname);CHKERRQ(ierr);
132b5bcf523SDave May   swarm->vec_field_set = PETSC_TRUE;
1331b1ea282SDave May   swarm->vec_field_bs = bs;
134b5bcf523SDave May   swarm->vec_field_nlocal = n;
135dcf43ee8SDave May   ierr = DMSwarmRestoreField(dm,fieldname,&bs,&type,(void**)&array);CHKERRQ(ierr);
136b5bcf523SDave May   PetscFunctionReturn(0);
137b5bcf523SDave May }
138b5bcf523SDave May 
139cc651181SDave May /* requires DMSwarmDefineFieldVector has been called */
140b5bcf523SDave May PetscErrorCode DMCreateGlobalVector_Swarm(DM dm,Vec *vec)
141b5bcf523SDave May {
142b5bcf523SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
143b5bcf523SDave May   PetscErrorCode ierr;
144b5bcf523SDave May   Vec            x;
145b5bcf523SDave May   char           name[PETSC_MAX_PATH_LEN];
146b5bcf523SDave May 
147a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
1483454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
149b5bcf523SDave May   if (!swarm->vec_field_set) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmVectorDefineField first");
150cc651181SDave 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 */
151cc651181SDave May 
152521f74f9SMatthew G. Knepley   ierr = PetscSNPrintf(name,PETSC_MAX_PATH_LEN-1,"DMSwarmField_%s",swarm->vec_field_name);CHKERRQ(ierr);
153b5bcf523SDave May   ierr = VecCreate(PetscObjectComm((PetscObject)dm),&x);CHKERRQ(ierr);
154b5bcf523SDave May   ierr = PetscObjectSetName((PetscObject)x,name);CHKERRQ(ierr);
1551b1ea282SDave May   ierr = VecSetSizes(x,swarm->db->L*swarm->vec_field_bs,PETSC_DETERMINE);CHKERRQ(ierr);
156b5bcf523SDave May   ierr = VecSetBlockSize(x,swarm->vec_field_bs);CHKERRQ(ierr);
157c6b011d8SStefano Zampini   ierr = VecSetDM(x,dm);CHKERRQ(ierr);
158b5bcf523SDave May   ierr = VecSetFromOptions(x);CHKERRQ(ierr);
15974d0cae8SMatthew G. Knepley   ierr = VecSetDM(x, dm);CHKERRQ(ierr);
16074d0cae8SMatthew G. Knepley   ierr = VecSetOperation(x, VECOP_VIEW, (void (*)(void)) VecView_Swarm);CHKERRQ(ierr);
161b5bcf523SDave May   *vec = x;
162b5bcf523SDave May   PetscFunctionReturn(0);
163b5bcf523SDave May }
164b5bcf523SDave May 
165b5bcf523SDave May /* requires DMSwarmDefineFieldVector has been called */
166b5bcf523SDave May PetscErrorCode DMCreateLocalVector_Swarm(DM dm,Vec *vec)
167b5bcf523SDave May {
168b5bcf523SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
169b5bcf523SDave May   PetscErrorCode ierr;
170b5bcf523SDave May   Vec            x;
171b5bcf523SDave May   char           name[PETSC_MAX_PATH_LEN];
172b5bcf523SDave May 
173a9cbaee5SMatthew G. Knepley   PetscFunctionBegin;
1743454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
175b5bcf523SDave May   if (!swarm->vec_field_set) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmVectorDefineField first");
176*5627991aSBarry Smith   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");
177cc651181SDave May 
178521f74f9SMatthew G. Knepley   ierr = PetscSNPrintf(name,PETSC_MAX_PATH_LEN-1,"DMSwarmField_%s",swarm->vec_field_name);CHKERRQ(ierr);
179b5bcf523SDave May   ierr = VecCreate(PETSC_COMM_SELF,&x);CHKERRQ(ierr);
180b5bcf523SDave May   ierr = PetscObjectSetName((PetscObject)x,name);CHKERRQ(ierr);
181071900c8SMatthew G. Knepley   ierr = VecSetSizes(x,swarm->db->L*swarm->vec_field_bs,PETSC_DETERMINE);CHKERRQ(ierr);
182b5bcf523SDave May   ierr = VecSetBlockSize(x,swarm->vec_field_bs);CHKERRQ(ierr);
183c6b011d8SStefano Zampini   ierr = VecSetDM(x,dm);CHKERRQ(ierr);
184b5bcf523SDave May   ierr = VecSetFromOptions(x);CHKERRQ(ierr);
185b5bcf523SDave May   *vec = x;
186b5bcf523SDave May   PetscFunctionReturn(0);
187b5bcf523SDave May }
188b5bcf523SDave May 
189fb1bcc12SMatthew G. Knepley static PetscErrorCode DMSwarmDestroyVectorFromField_Private(DM dm, const char fieldname[], Vec *vec)
190fb1bcc12SMatthew G. Knepley {
191fb1bcc12SMatthew G. Knepley   DM_Swarm         *swarm = (DM_Swarm *) dm->data;
19277048351SPatrick Sanan   DMSwarmDataField gfield;
193fb1bcc12SMatthew G. Knepley   void             (*fptr)(void);
194fb1bcc12SMatthew G. Knepley   PetscInt         bs, nlocal;
195fb1bcc12SMatthew G. Knepley   char             name[PETSC_MAX_PATH_LEN];
196fb1bcc12SMatthew G. Knepley   PetscErrorCode   ierr;
197d3a51819SDave May 
198fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
199fb1bcc12SMatthew G. Knepley   ierr = VecGetLocalSize(*vec, &nlocal);CHKERRQ(ierr);
200fb1bcc12SMatthew G. Knepley   ierr = VecGetBlockSize(*vec, &bs);CHKERRQ(ierr);
201*5627991aSBarry Smith   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");
20277048351SPatrick Sanan   ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db, fieldname, &gfield);CHKERRQ(ierr);
203fb1bcc12SMatthew G. Knepley   /* check vector is an inplace array */
204521f74f9SMatthew G. Knepley   ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarm_VecFieldInPlace_%s", fieldname);CHKERRQ(ierr);
205fb1bcc12SMatthew G. Knepley   ierr = PetscObjectQueryFunction((PetscObject) *vec, name, &fptr);CHKERRQ(ierr);
206fb1bcc12SMatthew G. Knepley   if (!fptr) SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_USER, "Vector being destroyed was not created from DMSwarm field(%s)", fieldname);
20777048351SPatrick Sanan   ierr = DMSwarmDataFieldRestoreAccess(gfield);CHKERRQ(ierr);
208fb1bcc12SMatthew G. Knepley   ierr = VecDestroy(vec);CHKERRQ(ierr);
209fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
210fb1bcc12SMatthew G. Knepley }
211fb1bcc12SMatthew G. Knepley 
212fb1bcc12SMatthew G. Knepley static PetscErrorCode DMSwarmCreateVectorFromField_Private(DM dm, const char fieldname[], MPI_Comm comm, Vec *vec)
213fb1bcc12SMatthew G. Knepley {
214fb1bcc12SMatthew G. Knepley   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
215fb1bcc12SMatthew G. Knepley   PetscDataType  type;
216fb1bcc12SMatthew G. Knepley   PetscScalar   *array;
217fb1bcc12SMatthew G. Knepley   PetscInt       bs, n;
218fb1bcc12SMatthew G. Knepley   char           name[PETSC_MAX_PATH_LEN];
219e4fbd051SBarry Smith   PetscMPIInt    size;
220fb1bcc12SMatthew G. Knepley   PetscErrorCode ierr;
221fb1bcc12SMatthew G. Knepley 
222fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
223fb1bcc12SMatthew G. Knepley   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
22477048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db, &n, NULL, NULL);CHKERRQ(ierr);
225fb1bcc12SMatthew G. Knepley   ierr = DMSwarmGetField(dm, fieldname, &bs, &type, (void **) &array);CHKERRQ(ierr);
226fb1bcc12SMatthew G. Knepley   if (type != PETSC_REAL) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Only valid for PETSC_REAL");
227fb1bcc12SMatthew G. Knepley 
228ffc4695bSBarry Smith   ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr);
229e4fbd051SBarry Smith   if (size == 1) {
230fb1bcc12SMatthew G. Knepley     ierr = VecCreateSeqWithArray(comm, bs, n*bs, array, vec);CHKERRQ(ierr);
231fb1bcc12SMatthew G. Knepley   } else {
232fb1bcc12SMatthew G. Knepley     ierr = VecCreateMPIWithArray(comm, bs, n*bs, PETSC_DETERMINE, array, vec);CHKERRQ(ierr);
233fb1bcc12SMatthew G. Knepley   }
234fb1bcc12SMatthew G. Knepley   ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarmSharedField_%s", fieldname);CHKERRQ(ierr);
235fb1bcc12SMatthew G. Knepley   ierr = PetscObjectSetName((PetscObject) *vec, name);CHKERRQ(ierr);
236fb1bcc12SMatthew G. Knepley 
237fb1bcc12SMatthew G. Knepley   /* Set guard */
238fb1bcc12SMatthew G. Knepley   ierr = PetscSNPrintf(name, PETSC_MAX_PATH_LEN-1, "DMSwarm_VecFieldInPlace_%s", fieldname);CHKERRQ(ierr);
239fb1bcc12SMatthew G. Knepley   ierr = PetscObjectComposeFunction((PetscObject) *vec, name, DMSwarmDestroyVectorFromField_Private);CHKERRQ(ierr);
24074d0cae8SMatthew G. Knepley 
24174d0cae8SMatthew G. Knepley   ierr = VecSetDM(*vec, dm);CHKERRQ(ierr);
24274d0cae8SMatthew G. Knepley   ierr = VecSetOperation(*vec, VECOP_VIEW, (void (*)(void)) VecView_Swarm);CHKERRQ(ierr);
243fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
244fb1bcc12SMatthew G. Knepley }
245fb1bcc12SMatthew G. Knepley 
2460643ed39SMatthew G. Knepley /* This creates a "mass matrix" between a finite element and particle space. If a finite element interpolant is given by
2470643ed39SMatthew G. Knepley 
2480643ed39SMatthew G. Knepley      \hat f = \sum_i f_i \phi_i
2490643ed39SMatthew G. Knepley 
2500643ed39SMatthew G. Knepley    and a particle function is given by
2510643ed39SMatthew G. Knepley 
2520643ed39SMatthew G. Knepley      f = \sum_i w_i \delta(x - x_i)
2530643ed39SMatthew G. Knepley 
2540643ed39SMatthew G. Knepley    then we want to require that
2550643ed39SMatthew G. Knepley 
2560643ed39SMatthew G. Knepley      M \hat f = M_p f
2570643ed39SMatthew G. Knepley 
2580643ed39SMatthew G. Knepley    where the particle mass matrix is given by
2590643ed39SMatthew G. Knepley 
2600643ed39SMatthew G. Knepley      (M_p)_{ij} = \int \phi_i \delta(x - x_j)
2610643ed39SMatthew G. Knepley 
2620643ed39SMatthew G. Knepley    The way Dave May does particles, they amount to quadratue weights rather than delta functions, so he has |J| is in
2630643ed39SMatthew G. Knepley    his integral. We allow this with the boolean flag.
2640643ed39SMatthew G. Knepley */
2650643ed39SMatthew G. Knepley static PetscErrorCode DMSwarmComputeMassMatrix_Private(DM dmc, DM dmf, Mat mass, PetscBool useDeltaFunction, void *ctx)
26683c47955SMatthew G. Knepley {
26783c47955SMatthew G. Knepley   const char    *name = "Mass Matrix";
2680643ed39SMatthew G. Knepley   MPI_Comm       comm;
26983c47955SMatthew G. Knepley   PetscDS        prob;
27083c47955SMatthew G. Knepley   PetscSection   fsection, globalFSection;
271e8f14785SLisandro Dalcin   PetscHSetIJ    ht;
2720643ed39SMatthew G. Knepley   PetscLayout    rLayout, colLayout;
27383c47955SMatthew G. Knepley   PetscInt      *dnz, *onz;
274adb2528bSMark Adams   PetscInt       locRows, locCols, rStart, colStart, colEnd, *rowIDXs;
2750643ed39SMatthew G. Knepley   PetscReal     *xi, *v0, *J, *invJ, detJ = 1.0, v0ref[3] = {-1.0, -1.0, -1.0};
27683c47955SMatthew G. Knepley   PetscScalar   *elemMat;
2770643ed39SMatthew G. Knepley   PetscInt       dim, Nf, field, cStart, cEnd, cell, totDim, maxC = 0;
27883c47955SMatthew G. Knepley   PetscErrorCode ierr;
27983c47955SMatthew G. Knepley 
28083c47955SMatthew G. Knepley   PetscFunctionBegin;
2810643ed39SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) mass, &comm);CHKERRQ(ierr);
28283c47955SMatthew G. Knepley   ierr = DMGetCoordinateDim(dmf, &dim);CHKERRQ(ierr);
28383c47955SMatthew G. Knepley   ierr = DMGetDS(dmf, &prob);CHKERRQ(ierr);
28483c47955SMatthew G. Knepley   ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr);
2850643ed39SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr);
28683c47955SMatthew G. Knepley   ierr = PetscMalloc3(dim, &v0, dim*dim, &J, dim*dim,&invJ);CHKERRQ(ierr);
28792fd8e1eSJed Brown   ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);
288e87a4003SBarry Smith   ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);
28983c47955SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd);CHKERRQ(ierr);
2900643ed39SMatthew G. Knepley   ierr = MatGetLocalSize(mass, &locRows, &locCols);CHKERRQ(ierr);
29183c47955SMatthew G. Knepley 
2920643ed39SMatthew G. Knepley   ierr = PetscLayoutCreate(comm, &colLayout);CHKERRQ(ierr);
2930643ed39SMatthew G. Knepley   ierr = PetscLayoutSetLocalSize(colLayout, locCols);CHKERRQ(ierr);
2940643ed39SMatthew G. Knepley   ierr = PetscLayoutSetBlockSize(colLayout, 1);CHKERRQ(ierr);
2950643ed39SMatthew G. Knepley   ierr = PetscLayoutSetUp(colLayout);CHKERRQ(ierr);
2960643ed39SMatthew G. Knepley   ierr = PetscLayoutGetRange(colLayout, &colStart, &colEnd);CHKERRQ(ierr);
2970643ed39SMatthew G. Knepley   ierr = PetscLayoutDestroy(&colLayout);CHKERRQ(ierr);
2980643ed39SMatthew G. Knepley 
2990643ed39SMatthew G. Knepley   ierr = PetscLayoutCreate(comm, &rLayout);CHKERRQ(ierr);
30083c47955SMatthew G. Knepley   ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr);
30183c47955SMatthew G. Knepley   ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr);
30283c47955SMatthew G. Knepley   ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr);
3030643ed39SMatthew G. Knepley   ierr = PetscLayoutGetRange(rLayout, &rStart, NULL);CHKERRQ(ierr);
30483c47955SMatthew G. Knepley   ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr);
3050643ed39SMatthew G. Knepley 
30683c47955SMatthew G. Knepley   ierr = PetscCalloc2(locRows, &dnz, locRows, &onz);CHKERRQ(ierr);
307e8f14785SLisandro Dalcin   ierr = PetscHSetIJCreate(&ht);CHKERRQ(ierr);
30853e60ab4SJoseph Pusztay 
3090643ed39SMatthew G. Knepley   ierr = PetscSynchronizedFlush(comm, NULL);CHKERRQ(ierr);
3100643ed39SMatthew G. Knepley   /* count non-zeros */
3110643ed39SMatthew G. Knepley   ierr = DMSwarmSortGetAccess(dmc);CHKERRQ(ierr);
31283c47955SMatthew G. Knepley   for (field = 0; field < Nf; ++field) {
31383c47955SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
3140643ed39SMatthew G. Knepley       PetscInt  c, i;
3150643ed39SMatthew G. Knepley       PetscInt *findices,   *cindices; /* fine is vertices, coarse is particles */
31683c47955SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
31783c47955SMatthew G. Knepley 
31871f0bbf9SMatthew G. Knepley       ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL);CHKERRQ(ierr);
319fc7c92abSMatthew G. Knepley       ierr = DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices);CHKERRQ(ierr);
320fc7c92abSMatthew G. Knepley       maxC = PetscMax(maxC, numCIndices);
32183c47955SMatthew G. Knepley       {
322e8f14785SLisandro Dalcin         PetscHashIJKey key;
323e8f14785SLisandro Dalcin         PetscBool      missing;
32483c47955SMatthew G. Knepley         for (i = 0; i < numFIndices; ++i) {
325adb2528bSMark Adams           key.j = findices[i]; /* global column (from Plex) */
326adb2528bSMark Adams           if (key.j >= 0) {
32783c47955SMatthew G. Knepley             /* Get indices for coarse elements */
32883c47955SMatthew G. Knepley             for (c = 0; c < numCIndices; ++c) {
329adb2528bSMark Adams               key.i = cindices[c] + rStart; /* global cols (from Swarm) */
330adb2528bSMark Adams               if (key.i < 0) continue;
331e8f14785SLisandro Dalcin               ierr = PetscHSetIJQueryAdd(ht, key, &missing);CHKERRQ(ierr);
33283c47955SMatthew G. Knepley               if (missing) {
3330643ed39SMatthew G. Knepley                 if ((key.j >= colStart) && (key.j < colEnd)) ++dnz[key.i - rStart];
334e8f14785SLisandro Dalcin                 else                                         ++onz[key.i - rStart];
3350643ed39SMatthew G. Knepley               } else SETERRQ2(PetscObjectComm((PetscObject) dmf), PETSC_ERR_SUP, "Set new value at %D,%D", key.i, key.j);
33683c47955SMatthew G. Knepley             }
337fc7c92abSMatthew G. Knepley           }
338fc7c92abSMatthew G. Knepley         }
33983c47955SMatthew G. Knepley         ierr = PetscFree(cindices);CHKERRQ(ierr);
34083c47955SMatthew G. Knepley       }
34171f0bbf9SMatthew G. Knepley       ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL);CHKERRQ(ierr);
34283c47955SMatthew G. Knepley     }
34383c47955SMatthew G. Knepley   }
344e8f14785SLisandro Dalcin   ierr = PetscHSetIJDestroy(&ht);CHKERRQ(ierr);
34583c47955SMatthew G. Knepley   ierr = MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL);CHKERRQ(ierr);
34683c47955SMatthew G. Knepley   ierr = MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE);CHKERRQ(ierr);
34783c47955SMatthew G. Knepley   ierr = PetscFree2(dnz, onz);CHKERRQ(ierr);
348adb2528bSMark Adams   ierr = PetscMalloc3(maxC*totDim, &elemMat, maxC, &rowIDXs, maxC*dim, &xi);CHKERRQ(ierr);
34983c47955SMatthew G. Knepley   for (field = 0; field < Nf; ++field) {
350ef0bb6c7SMatthew G. Knepley     PetscTabulation Tcoarse;
35183c47955SMatthew G. Knepley     PetscObject     obj;
352ef0bb6c7SMatthew G. Knepley     PetscReal       *coords;
3530643ed39SMatthew G. Knepley     PetscInt        Nc, i;
35483c47955SMatthew G. Knepley 
35583c47955SMatthew G. Knepley     ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr);
3560643ed39SMatthew G. Knepley     ierr = PetscFEGetNumComponents((PetscFE) obj, &Nc);CHKERRQ(ierr);
3570643ed39SMatthew G. Knepley     if (Nc != 1) SETERRQ1(PetscObjectComm((PetscObject) dmf), PETSC_ERR_SUP, "Can only interpolate a scalar field from particles, Nc = %D", Nc);
3580643ed39SMatthew G. Knepley     ierr = DMSwarmGetField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **) &coords);CHKERRQ(ierr);
35983c47955SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
36083c47955SMatthew G. Knepley       PetscInt *findices  , *cindices;
36183c47955SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
3620643ed39SMatthew G. Knepley       PetscInt  p, c;
36383c47955SMatthew G. Knepley 
3640643ed39SMatthew G. Knepley       /* TODO: Use DMField instead of assuming affine */
36583c47955SMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr);
36671f0bbf9SMatthew G. Knepley       ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL);CHKERRQ(ierr);
36783c47955SMatthew G. Knepley       ierr = DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices);CHKERRQ(ierr);
3680643ed39SMatthew G. Knepley       for (p = 0; p < numCIndices; ++p) {
3690643ed39SMatthew G. Knepley         CoordinatesRealToRef(dim, dim, v0ref, v0, invJ, &coords[cindices[p]*dim], &xi[p*dim]);
3700643ed39SMatthew G. Knepley       }
371ef0bb6c7SMatthew G. Knepley       ierr = PetscFECreateTabulation((PetscFE) obj, 1, numCIndices, xi, 0, &Tcoarse);CHKERRQ(ierr);
37283c47955SMatthew G. Knepley       /* Get elemMat entries by multiplying by weight */
373580bdb30SBarry Smith       ierr = PetscArrayzero(elemMat, numCIndices*totDim);CHKERRQ(ierr);
37483c47955SMatthew G. Knepley       for (i = 0; i < numFIndices; ++i) {
3750643ed39SMatthew G. Knepley         for (p = 0; p < numCIndices; ++p) {
3760643ed39SMatthew G. Knepley           for (c = 0; c < Nc; ++c) {
3770643ed39SMatthew G. Knepley             /* B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c */
378ef0bb6c7SMatthew G. Knepley             elemMat[p*numFIndices+i] += Tcoarse->T[0][(p*numFIndices + i)*Nc + c]*(useDeltaFunction ? 1.0 : detJ);
37983c47955SMatthew G. Knepley           }
3800643ed39SMatthew G. Knepley         }
3810643ed39SMatthew G. Knepley       }
382adb2528bSMark Adams       for (p = 0; p < numCIndices; ++p) rowIDXs[p] = cindices[p] + rStart;
38383c47955SMatthew G. Knepley       if (0) {ierr = DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat);CHKERRQ(ierr);}
384adb2528bSMark Adams       ierr = MatSetValues(mass, numCIndices, rowIDXs, numFIndices, findices, elemMat, ADD_VALUES);CHKERRQ(ierr);
38583c47955SMatthew G. Knepley       ierr = PetscFree(cindices);CHKERRQ(ierr);
38671f0bbf9SMatthew G. Knepley       ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL);CHKERRQ(ierr);
387ef0bb6c7SMatthew G. Knepley       ierr = PetscTabulationDestroy(&Tcoarse);CHKERRQ(ierr);
38883c47955SMatthew G. Knepley     }
3890643ed39SMatthew G. Knepley     ierr = DMSwarmRestoreField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **) &coords);CHKERRQ(ierr);
39083c47955SMatthew G. Knepley   }
391adb2528bSMark Adams   ierr = PetscFree3(elemMat, rowIDXs, xi);CHKERRQ(ierr);
39283c47955SMatthew G. Knepley   ierr = DMSwarmSortRestoreAccess(dmc);CHKERRQ(ierr);
39383c47955SMatthew G. Knepley   ierr = PetscFree3(v0, J, invJ);CHKERRQ(ierr);
39483c47955SMatthew G. Knepley   ierr = MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
39583c47955SMatthew G. Knepley   ierr = MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
39683c47955SMatthew G. Knepley   PetscFunctionReturn(0);
39783c47955SMatthew G. Knepley }
39883c47955SMatthew G. Knepley 
399d0c080abSJoseph Pusztay /* Returns empty matrix for use with SNES FD */
40070a7d78aSStefano Zampini static PetscErrorCode DMCreateMatrix_Swarm(DM sw, Mat* m)
40170a7d78aSStefano Zampini {
402d0c080abSJoseph Pusztay   Vec            field;
403d0c080abSJoseph Pusztay   PetscInt       size;
404d0c080abSJoseph Pusztay   PetscErrorCode ierr;
405d0c080abSJoseph Pusztay 
406d0c080abSJoseph Pusztay   PetscFunctionBegin;
407d0c080abSJoseph Pusztay   ierr = DMGetGlobalVector(sw, &field);CHKERRQ(ierr);
408d0c080abSJoseph Pusztay   ierr = VecGetLocalSize(field, &size);CHKERRQ(ierr);
409d0c080abSJoseph Pusztay   ierr = DMRestoreGlobalVector(sw, &field);CHKERRQ(ierr);
410d0c080abSJoseph Pusztay   ierr = MatCreate(PETSC_COMM_WORLD, m);CHKERRQ(ierr);
411d0c080abSJoseph Pusztay   ierr = MatSetFromOptions(*m);CHKERRQ(ierr);
4121e1ea65dSPierre Jolivet   ierr = MatSetSizes(*m, PETSC_DECIDE, PETSC_DECIDE, size, size);CHKERRQ(ierr);
413d0c080abSJoseph Pusztay   ierr = MatSeqAIJSetPreallocation(*m, 1, NULL);CHKERRQ(ierr);
414d0c080abSJoseph Pusztay   ierr = MatZeroEntries(*m);CHKERRQ(ierr);
415d0c080abSJoseph Pusztay   ierr = MatAssemblyBegin(*m, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
416d0c080abSJoseph Pusztay   ierr = MatAssemblyEnd(*m, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
417d0c080abSJoseph Pusztay   ierr = MatShift(*m, 1.0);CHKERRQ(ierr);
418d0c080abSJoseph Pusztay   ierr = MatSetDM(*m, sw);CHKERRQ(ierr);
419d0c080abSJoseph Pusztay   PetscFunctionReturn(0);
420d0c080abSJoseph Pusztay }
421d0c080abSJoseph Pusztay 
422adb2528bSMark Adams /* FEM cols, Particle rows */
42383c47955SMatthew G. Knepley static PetscErrorCode DMCreateMassMatrix_Swarm(DM dmCoarse, DM dmFine, Mat *mass)
42483c47955SMatthew G. Knepley {
425895a1698SMatthew G. Knepley   PetscSection   gsf;
42683c47955SMatthew G. Knepley   PetscInt       m, n;
42783c47955SMatthew G. Knepley   void          *ctx;
42883c47955SMatthew G. Knepley   PetscErrorCode ierr;
42983c47955SMatthew G. Knepley 
43083c47955SMatthew G. Knepley   PetscFunctionBegin;
431e87a4003SBarry Smith   ierr = DMGetGlobalSection(dmFine, &gsf);CHKERRQ(ierr);
43283c47955SMatthew G. Knepley   ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr);
433895a1698SMatthew G. Knepley   ierr = DMSwarmGetLocalSize(dmCoarse, &n);CHKERRQ(ierr);
43483c47955SMatthew G. Knepley   ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr);
435adb2528bSMark Adams   ierr = MatSetSizes(*mass, n, m, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
43683c47955SMatthew G. Knepley   ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr);
43783c47955SMatthew G. Knepley   ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr);
43883c47955SMatthew G. Knepley 
4390643ed39SMatthew G. Knepley   ierr = DMSwarmComputeMassMatrix_Private(dmCoarse, dmFine, *mass, PETSC_TRUE, ctx);CHKERRQ(ierr);
44083c47955SMatthew G. Knepley   ierr = MatViewFromOptions(*mass, NULL, "-mass_mat_view");CHKERRQ(ierr);
44183c47955SMatthew G. Knepley   PetscFunctionReturn(0);
44283c47955SMatthew G. Knepley }
44383c47955SMatthew G. Knepley 
4444cc7f7b2SMatthew G. Knepley static PetscErrorCode DMSwarmComputeMassMatrixSquare_Private(DM dmc, DM dmf, Mat mass, PetscBool useDeltaFunction, void *ctx)
4454cc7f7b2SMatthew G. Knepley {
4464cc7f7b2SMatthew G. Knepley   const char    *name = "Mass Matrix Square";
4474cc7f7b2SMatthew G. Knepley   MPI_Comm       comm;
4484cc7f7b2SMatthew G. Knepley   PetscDS        prob;
4494cc7f7b2SMatthew G. Knepley   PetscSection   fsection, globalFSection;
4504cc7f7b2SMatthew G. Knepley   PetscHSetIJ    ht;
4514cc7f7b2SMatthew G. Knepley   PetscLayout    rLayout, colLayout;
4524cc7f7b2SMatthew G. Knepley   PetscInt      *dnz, *onz, *adj, depth, maxConeSize, maxSupportSize, maxAdjSize;
4534cc7f7b2SMatthew G. Knepley   PetscInt       locRows, locCols, rStart, colStart, colEnd, *rowIDXs;
4544cc7f7b2SMatthew G. Knepley   PetscReal     *xi, *v0, *J, *invJ, detJ = 1.0, v0ref[3] = {-1.0, -1.0, -1.0};
4554cc7f7b2SMatthew G. Knepley   PetscScalar   *elemMat, *elemMatSq;
4564cc7f7b2SMatthew G. Knepley   PetscInt       cdim, Nf, field, cStart, cEnd, cell, totDim, maxC = 0;
4574cc7f7b2SMatthew G. Knepley   PetscErrorCode ierr;
4584cc7f7b2SMatthew G. Knepley 
4594cc7f7b2SMatthew G. Knepley   PetscFunctionBegin;
4604cc7f7b2SMatthew G. Knepley   ierr = PetscObjectGetComm((PetscObject) mass, &comm);CHKERRQ(ierr);
4614cc7f7b2SMatthew G. Knepley   ierr = DMGetCoordinateDim(dmf, &cdim);CHKERRQ(ierr);
4624cc7f7b2SMatthew G. Knepley   ierr = DMGetDS(dmf, &prob);CHKERRQ(ierr);
4634cc7f7b2SMatthew G. Knepley   ierr = PetscDSGetNumFields(prob, &Nf);CHKERRQ(ierr);
4644cc7f7b2SMatthew G. Knepley   ierr = PetscDSGetTotalDimension(prob, &totDim);CHKERRQ(ierr);
4654cc7f7b2SMatthew G. Knepley   ierr = PetscMalloc3(cdim, &v0, cdim*cdim, &J, cdim*cdim,&invJ);CHKERRQ(ierr);
4664cc7f7b2SMatthew G. Knepley   ierr = DMGetLocalSection(dmf, &fsection);CHKERRQ(ierr);
4674cc7f7b2SMatthew G. Knepley   ierr = DMGetGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);
4684cc7f7b2SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(dmf, 0, &cStart, &cEnd);CHKERRQ(ierr);
4694cc7f7b2SMatthew G. Knepley   ierr = MatGetLocalSize(mass, &locRows, &locCols);CHKERRQ(ierr);
4704cc7f7b2SMatthew G. Knepley 
4714cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutCreate(comm, &colLayout);CHKERRQ(ierr);
4724cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutSetLocalSize(colLayout, locCols);CHKERRQ(ierr);
4734cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutSetBlockSize(colLayout, 1);CHKERRQ(ierr);
4744cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutSetUp(colLayout);CHKERRQ(ierr);
4754cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutGetRange(colLayout, &colStart, &colEnd);CHKERRQ(ierr);
4764cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutDestroy(&colLayout);CHKERRQ(ierr);
4774cc7f7b2SMatthew G. Knepley 
4784cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutCreate(comm, &rLayout);CHKERRQ(ierr);
4794cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutSetLocalSize(rLayout, locRows);CHKERRQ(ierr);
4804cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutSetBlockSize(rLayout, 1);CHKERRQ(ierr);
4814cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutSetUp(rLayout);CHKERRQ(ierr);
4824cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutGetRange(rLayout, &rStart, NULL);CHKERRQ(ierr);
4834cc7f7b2SMatthew G. Knepley   ierr = PetscLayoutDestroy(&rLayout);CHKERRQ(ierr);
4844cc7f7b2SMatthew G. Knepley 
4854cc7f7b2SMatthew G. Knepley   ierr = DMPlexGetDepth(dmf, &depth);CHKERRQ(ierr);
4864cc7f7b2SMatthew G. Knepley   ierr = DMPlexGetMaxSizes(dmf, &maxConeSize, &maxSupportSize);CHKERRQ(ierr);
4874cc7f7b2SMatthew G. Knepley   maxAdjSize = PetscPowInt(maxConeSize*maxSupportSize, depth);
4884cc7f7b2SMatthew G. Knepley   ierr = PetscMalloc1(maxAdjSize, &adj);CHKERRQ(ierr);
4894cc7f7b2SMatthew G. Knepley 
4904cc7f7b2SMatthew G. Knepley   ierr = PetscCalloc2(locRows, &dnz, locRows, &onz);CHKERRQ(ierr);
4914cc7f7b2SMatthew G. Knepley   ierr = PetscHSetIJCreate(&ht);CHKERRQ(ierr);
4924cc7f7b2SMatthew G. Knepley   /* Count nonzeros
4934cc7f7b2SMatthew G. Knepley        This is just FVM++, but we cannot use the Plex P0 allocation since unknowns in a cell will not be contiguous
4944cc7f7b2SMatthew G. Knepley   */
4954cc7f7b2SMatthew G. Knepley   ierr = DMSwarmSortGetAccess(dmc);CHKERRQ(ierr);
4964cc7f7b2SMatthew G. Knepley   for (cell = cStart; cell < cEnd; ++cell) {
4974cc7f7b2SMatthew G. Knepley     PetscInt  i;
4984cc7f7b2SMatthew G. Knepley     PetscInt *cindices;
4994cc7f7b2SMatthew G. Knepley     PetscInt  numCIndices;
5004cc7f7b2SMatthew G. Knepley   #if 0
5014cc7f7b2SMatthew G. Knepley     PetscInt  adjSize = maxAdjSize, a, j;
5024cc7f7b2SMatthew G. Knepley   #endif
5034cc7f7b2SMatthew G. Knepley 
5044cc7f7b2SMatthew G. Knepley     ierr = DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices);CHKERRQ(ierr);
5054cc7f7b2SMatthew G. Knepley     maxC = PetscMax(maxC, numCIndices);
5064cc7f7b2SMatthew G. Knepley     /* Diagonal block */
5074cc7f7b2SMatthew G. Knepley     for (i = 0; i < numCIndices; ++i) {dnz[cindices[i]] += numCIndices;}
5084cc7f7b2SMatthew G. Knepley #if 0
5094cc7f7b2SMatthew G. Knepley     /* Off-diagonal blocks */
5104cc7f7b2SMatthew G. Knepley     ierr = DMPlexGetAdjacency(dmf, cell, &adjSize, &adj);CHKERRQ(ierr);
5114cc7f7b2SMatthew G. Knepley     for (a = 0; a < adjSize; ++a) {
5124cc7f7b2SMatthew G. Knepley       if (adj[a] >= cStart && adj[a] < cEnd && adj[a] != cell) {
5134cc7f7b2SMatthew G. Knepley         const PetscInt ncell = adj[a];
5144cc7f7b2SMatthew G. Knepley         PetscInt      *ncindices;
5154cc7f7b2SMatthew G. Knepley         PetscInt       numNCIndices;
5164cc7f7b2SMatthew G. Knepley 
5174cc7f7b2SMatthew G. Knepley         ierr = DMSwarmSortGetPointsPerCell(dmc, ncell, &numNCIndices, &ncindices);CHKERRQ(ierr);
5184cc7f7b2SMatthew G. Knepley         {
5194cc7f7b2SMatthew G. Knepley           PetscHashIJKey key;
5204cc7f7b2SMatthew G. Knepley           PetscBool      missing;
5214cc7f7b2SMatthew G. Knepley 
5224cc7f7b2SMatthew G. Knepley           for (i = 0; i < numCIndices; ++i) {
5234cc7f7b2SMatthew G. Knepley             key.i = cindices[i] + rStart; /* global rows (from Swarm) */
5244cc7f7b2SMatthew G. Knepley             if (key.i < 0) continue;
5254cc7f7b2SMatthew G. Knepley             for (j = 0; j < numNCIndices; ++j) {
5264cc7f7b2SMatthew G. Knepley               key.j = ncindices[j] + rStart; /* global column (from Swarm) */
5274cc7f7b2SMatthew G. Knepley               if (key.j < 0) continue;
5284cc7f7b2SMatthew G. Knepley               ierr = PetscHSetIJQueryAdd(ht, key, &missing);CHKERRQ(ierr);
5294cc7f7b2SMatthew G. Knepley               if (missing) {
5304cc7f7b2SMatthew G. Knepley                 if ((key.j >= colStart) && (key.j < colEnd)) ++dnz[key.i - rStart];
5314cc7f7b2SMatthew G. Knepley                 else                                         ++onz[key.i - rStart];
5324cc7f7b2SMatthew G. Knepley               }
5334cc7f7b2SMatthew G. Knepley             }
5344cc7f7b2SMatthew G. Knepley           }
5354cc7f7b2SMatthew G. Knepley         }
5364cc7f7b2SMatthew G. Knepley         ierr = PetscFree(ncindices);CHKERRQ(ierr);
5374cc7f7b2SMatthew G. Knepley       }
5384cc7f7b2SMatthew G. Knepley     }
5394cc7f7b2SMatthew G. Knepley #endif
5404cc7f7b2SMatthew G. Knepley     ierr = PetscFree(cindices);CHKERRQ(ierr);
5414cc7f7b2SMatthew G. Knepley   }
5424cc7f7b2SMatthew G. Knepley   ierr = PetscHSetIJDestroy(&ht);CHKERRQ(ierr);
5434cc7f7b2SMatthew G. Knepley   ierr = MatXAIJSetPreallocation(mass, 1, dnz, onz, NULL, NULL);CHKERRQ(ierr);
5444cc7f7b2SMatthew G. Knepley   ierr = MatSetOption(mass, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_TRUE);CHKERRQ(ierr);
5454cc7f7b2SMatthew G. Knepley   ierr = PetscFree2(dnz, onz);CHKERRQ(ierr);
5464cc7f7b2SMatthew G. Knepley   ierr = PetscMalloc4(maxC*totDim, &elemMat, maxC*maxC, &elemMatSq, maxC, &rowIDXs, maxC*cdim, &xi);CHKERRQ(ierr);
5474cc7f7b2SMatthew G. Knepley   /* Fill in values
5484cc7f7b2SMatthew G. Knepley        Each entry is a sum of terms \phi_i(x_p) \phi_i(x_q)
5494cc7f7b2SMatthew G. Knepley        Start just by producing block diagonal
5504cc7f7b2SMatthew G. Knepley        Could loop over adjacent cells
5514cc7f7b2SMatthew G. Knepley          Produce neighboring element matrix
5524cc7f7b2SMatthew G. Knepley          TODO Determine which columns and rows correspond to shared dual vector
5534cc7f7b2SMatthew G. Knepley          Do MatMatMult with rectangular matrices
5544cc7f7b2SMatthew G. Knepley          Insert block
5554cc7f7b2SMatthew G. Knepley   */
5564cc7f7b2SMatthew G. Knepley   for (field = 0; field < Nf; ++field) {
5574cc7f7b2SMatthew G. Knepley     PetscTabulation Tcoarse;
5584cc7f7b2SMatthew G. Knepley     PetscObject     obj;
5594cc7f7b2SMatthew G. Knepley     PetscReal       *coords;
5604cc7f7b2SMatthew G. Knepley     PetscInt        Nc, i;
5614cc7f7b2SMatthew G. Knepley 
5624cc7f7b2SMatthew G. Knepley     ierr = PetscDSGetDiscretization(prob, field, &obj);CHKERRQ(ierr);
5634cc7f7b2SMatthew G. Knepley     ierr = PetscFEGetNumComponents((PetscFE) obj, &Nc);CHKERRQ(ierr);
5644cc7f7b2SMatthew G. Knepley     if (Nc != 1) SETERRQ1(PetscObjectComm((PetscObject) dmf), PETSC_ERR_SUP, "Can only interpolate a scalar field from particles, Nc = %D", Nc);
5654cc7f7b2SMatthew G. Knepley     ierr = DMSwarmGetField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **) &coords);CHKERRQ(ierr);
5664cc7f7b2SMatthew G. Knepley     for (cell = cStart; cell < cEnd; ++cell) {
5674cc7f7b2SMatthew G. Knepley       PetscInt *findices  , *cindices;
5684cc7f7b2SMatthew G. Knepley       PetscInt  numFIndices, numCIndices;
5694cc7f7b2SMatthew G. Knepley       PetscInt  p, c;
5704cc7f7b2SMatthew G. Knepley 
5714cc7f7b2SMatthew G. Knepley       /* TODO: Use DMField instead of assuming affine */
5724cc7f7b2SMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFEM(dmf, cell, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr);
5734cc7f7b2SMatthew G. Knepley       ierr = DMPlexGetClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL);CHKERRQ(ierr);
5744cc7f7b2SMatthew G. Knepley       ierr = DMSwarmSortGetPointsPerCell(dmc, cell, &numCIndices, &cindices);CHKERRQ(ierr);
5754cc7f7b2SMatthew G. Knepley       for (p = 0; p < numCIndices; ++p) {
5764cc7f7b2SMatthew G. Knepley         CoordinatesRealToRef(cdim, cdim, v0ref, v0, invJ, &coords[cindices[p]*cdim], &xi[p*cdim]);
5774cc7f7b2SMatthew G. Knepley       }
5784cc7f7b2SMatthew G. Knepley       ierr = PetscFECreateTabulation((PetscFE) obj, 1, numCIndices, xi, 0, &Tcoarse);CHKERRQ(ierr);
5794cc7f7b2SMatthew G. Knepley       /* Get elemMat entries by multiplying by weight */
5804cc7f7b2SMatthew G. Knepley       ierr = PetscArrayzero(elemMat, numCIndices*totDim);CHKERRQ(ierr);
5814cc7f7b2SMatthew G. Knepley       for (i = 0; i < numFIndices; ++i) {
5824cc7f7b2SMatthew G. Knepley         for (p = 0; p < numCIndices; ++p) {
5834cc7f7b2SMatthew G. Knepley           for (c = 0; c < Nc; ++c) {
5844cc7f7b2SMatthew G. Knepley             /* B[(p*pdim + i)*Nc + c] is the value at point p for basis function i and component c */
5854cc7f7b2SMatthew G. Knepley             elemMat[p*numFIndices+i] += Tcoarse->T[0][(p*numFIndices + i)*Nc + c]*(useDeltaFunction ? 1.0 : detJ);
5864cc7f7b2SMatthew G. Knepley           }
5874cc7f7b2SMatthew G. Knepley         }
5884cc7f7b2SMatthew G. Knepley       }
5894cc7f7b2SMatthew G. Knepley       ierr = PetscTabulationDestroy(&Tcoarse);CHKERRQ(ierr);
5904cc7f7b2SMatthew G. Knepley       for (p = 0; p < numCIndices; ++p) rowIDXs[p] = cindices[p] + rStart;
5914cc7f7b2SMatthew G. Knepley       if (0) {ierr = DMPrintCellMatrix(cell, name, 1, numCIndices, elemMat);CHKERRQ(ierr);}
5924cc7f7b2SMatthew G. Knepley       /* Block diagonal */
59378884ca7SMatthew G. Knepley       if (numCIndices) {
5944cc7f7b2SMatthew G. Knepley         PetscBLASInt blasn, blask;
5954cc7f7b2SMatthew G. Knepley         PetscScalar  one = 1.0, zero = 0.0;
5964cc7f7b2SMatthew G. Knepley 
5974cc7f7b2SMatthew G. Knepley         ierr = PetscBLASIntCast(numCIndices, &blasn);CHKERRQ(ierr);
5984cc7f7b2SMatthew G. Knepley         ierr = PetscBLASIntCast(numFIndices, &blask);CHKERRQ(ierr);
5994cc7f7b2SMatthew G. Knepley         PetscStackCallBLAS("BLASgemm",BLASgemm_("T","N",&blasn,&blasn,&blask,&one,elemMat,&blask,elemMat,&blask,&zero,elemMatSq,&blasn));
6004cc7f7b2SMatthew G. Knepley       }
6014cc7f7b2SMatthew G. Knepley       ierr = MatSetValues(mass, numCIndices, rowIDXs, numCIndices, rowIDXs, elemMatSq, ADD_VALUES);CHKERRQ(ierr);
6024cc7f7b2SMatthew G. Knepley       /* TODO Off-diagonal */
6034cc7f7b2SMatthew G. Knepley       ierr = PetscFree(cindices);CHKERRQ(ierr);
6044cc7f7b2SMatthew G. Knepley       ierr = DMPlexRestoreClosureIndices(dmf, fsection, globalFSection, cell, PETSC_FALSE, &numFIndices, &findices, NULL, NULL);CHKERRQ(ierr);
6054cc7f7b2SMatthew G. Knepley     }
6064cc7f7b2SMatthew G. Knepley     ierr = DMSwarmRestoreField(dmc, DMSwarmPICField_coor, NULL, NULL, (void **) &coords);CHKERRQ(ierr);
6074cc7f7b2SMatthew G. Knepley   }
6084cc7f7b2SMatthew G. Knepley   ierr = PetscFree4(elemMat, elemMatSq, rowIDXs, xi);CHKERRQ(ierr);
6094cc7f7b2SMatthew G. Knepley   ierr = PetscFree(adj);CHKERRQ(ierr);
6104cc7f7b2SMatthew G. Knepley   ierr = DMSwarmSortRestoreAccess(dmc);CHKERRQ(ierr);
6114cc7f7b2SMatthew G. Knepley   ierr = PetscFree3(v0, J, invJ);CHKERRQ(ierr);
6124cc7f7b2SMatthew G. Knepley   ierr = MatAssemblyBegin(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6134cc7f7b2SMatthew G. Knepley   ierr = MatAssemblyEnd(mass, MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
6144cc7f7b2SMatthew G. Knepley   PetscFunctionReturn(0);
6154cc7f7b2SMatthew G. Knepley }
6164cc7f7b2SMatthew G. Knepley 
6174cc7f7b2SMatthew G. Knepley /*@C
6184cc7f7b2SMatthew G. Knepley   DMSwarmCreateMassMatrixSquare - Creates the block-diagonal of the square, M^T_p M_p, of the particle mass matrix M_p
6194cc7f7b2SMatthew G. Knepley 
6204cc7f7b2SMatthew G. Knepley   Collective on dmCoarse
6214cc7f7b2SMatthew G. Knepley 
6224cc7f7b2SMatthew G. Knepley   Input parameters:
6234cc7f7b2SMatthew G. Knepley + dmCoarse - a DMSwarm
6244cc7f7b2SMatthew G. Knepley - dmFine   - a DMPlex
6254cc7f7b2SMatthew G. Knepley 
6264cc7f7b2SMatthew G. Knepley   Output parameter:
6274cc7f7b2SMatthew G. Knepley . mass     - the square of the particle mass matrix
6284cc7f7b2SMatthew G. Knepley 
6294cc7f7b2SMatthew G. Knepley   Level: advanced
6304cc7f7b2SMatthew G. Knepley 
6314cc7f7b2SMatthew G. Knepley   Notes:
6324cc7f7b2SMatthew G. Knepley   We only compute the block diagonal since this provides a good preconditioner and is completely local. It would be possible in the
6334cc7f7b2SMatthew G. Knepley   future to compute the full normal equations.
6344cc7f7b2SMatthew G. Knepley 
6354cc7f7b2SMatthew G. Knepley .seealso: DMCreateMassMatrix()
6364cc7f7b2SMatthew G. Knepley @*/
6374cc7f7b2SMatthew G. Knepley PetscErrorCode DMSwarmCreateMassMatrixSquare(DM dmCoarse, DM dmFine, Mat *mass)
6384cc7f7b2SMatthew G. Knepley {
6394cc7f7b2SMatthew G. Knepley   PetscInt       n;
6404cc7f7b2SMatthew G. Knepley   void          *ctx;
6414cc7f7b2SMatthew G. Knepley   PetscErrorCode ierr;
6424cc7f7b2SMatthew G. Knepley 
6434cc7f7b2SMatthew G. Knepley   PetscFunctionBegin;
6444cc7f7b2SMatthew G. Knepley   ierr = DMSwarmGetLocalSize(dmCoarse, &n);CHKERRQ(ierr);
6454cc7f7b2SMatthew G. Knepley   ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), mass);CHKERRQ(ierr);
6464cc7f7b2SMatthew G. Knepley   ierr = MatSetSizes(*mass, n, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr);
6474cc7f7b2SMatthew G. Knepley   ierr = MatSetType(*mass, dmCoarse->mattype);CHKERRQ(ierr);
6484cc7f7b2SMatthew G. Knepley   ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr);
6494cc7f7b2SMatthew G. Knepley 
6504cc7f7b2SMatthew G. Knepley   ierr = DMSwarmComputeMassMatrixSquare_Private(dmCoarse, dmFine, *mass, PETSC_TRUE, ctx);CHKERRQ(ierr);
6514cc7f7b2SMatthew G. Knepley   ierr = MatViewFromOptions(*mass, NULL, "-mass_sq_mat_view");CHKERRQ(ierr);
6524cc7f7b2SMatthew G. Knepley   PetscFunctionReturn(0);
6534cc7f7b2SMatthew G. Knepley }
6544cc7f7b2SMatthew G. Knepley 
655fb1bcc12SMatthew G. Knepley /*@C
656d3a51819SDave May    DMSwarmCreateGlobalVectorFromField - Creates a Vec object sharing the array associated with a given field
657d3a51819SDave May 
658d083f849SBarry Smith    Collective on dm
659d3a51819SDave May 
660d3a51819SDave May    Input parameters:
66162741f57SDave May +  dm - a DMSwarm
66262741f57SDave May -  fieldname - the textual name given to a registered field
663d3a51819SDave May 
6648b8a3813SDave May    Output parameter:
665d3a51819SDave May .  vec - the vector
666d3a51819SDave May 
667d3a51819SDave May    Level: beginner
668d3a51819SDave May 
6698b8a3813SDave May    Notes:
6708b8a3813SDave May    The vector must be returned using a matching call to DMSwarmDestroyGlobalVectorFromField().
6718b8a3813SDave May 
6728b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmDestroyGlobalVectorFromField()
673d3a51819SDave May @*/
67474d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmCreateGlobalVectorFromField(DM dm,const char fieldname[],Vec *vec)
675b5bcf523SDave May {
676fb1bcc12SMatthew G. Knepley   MPI_Comm       comm = PetscObjectComm((PetscObject) dm);
677b5bcf523SDave May   PetscErrorCode ierr;
678b5bcf523SDave May 
679fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
680fb1bcc12SMatthew G. Knepley   ierr = DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec);CHKERRQ(ierr);
681b5bcf523SDave May   PetscFunctionReturn(0);
682b5bcf523SDave May }
683b5bcf523SDave May 
684d3a51819SDave May /*@C
685d3a51819SDave May    DMSwarmDestroyGlobalVectorFromField - Destroys the Vec object which share the array associated with a given field
686d3a51819SDave May 
687d083f849SBarry Smith    Collective on dm
688d3a51819SDave May 
689d3a51819SDave May    Input parameters:
69062741f57SDave May +  dm - a DMSwarm
69162741f57SDave May -  fieldname - the textual name given to a registered field
692d3a51819SDave May 
6938b8a3813SDave May    Output parameter:
694d3a51819SDave May .  vec - the vector
695d3a51819SDave May 
696d3a51819SDave May    Level: beginner
697d3a51819SDave May 
6988b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmCreateGlobalVectorFromField()
699d3a51819SDave May @*/
70074d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmDestroyGlobalVectorFromField(DM dm,const char fieldname[],Vec *vec)
701b5bcf523SDave May {
702b5bcf523SDave May   PetscErrorCode ierr;
703cc651181SDave May 
704fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
705fb1bcc12SMatthew G. Knepley   ierr = DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec);CHKERRQ(ierr);
706b5bcf523SDave May   PetscFunctionReturn(0);
707b5bcf523SDave May }
708b5bcf523SDave May 
709fb1bcc12SMatthew G. Knepley /*@C
710fb1bcc12SMatthew G. Knepley    DMSwarmCreateLocalVectorFromField - Creates a Vec object sharing the array associated with a given field
711fb1bcc12SMatthew G. Knepley 
712d083f849SBarry Smith    Collective on dm
713fb1bcc12SMatthew G. Knepley 
714fb1bcc12SMatthew G. Knepley    Input parameters:
71562741f57SDave May +  dm - a DMSwarm
71662741f57SDave May -  fieldname - the textual name given to a registered field
717fb1bcc12SMatthew G. Knepley 
7188b8a3813SDave May    Output parameter:
719fb1bcc12SMatthew G. Knepley .  vec - the vector
720fb1bcc12SMatthew G. Knepley 
721fb1bcc12SMatthew G. Knepley    Level: beginner
722fb1bcc12SMatthew G. Knepley 
7238b8a3813SDave May    Notes:
7248b8a3813SDave May    The vector must be returned using a matching call to DMSwarmDestroyLocalVectorFromField().
7258b8a3813SDave May 
7268b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmDestroyLocalVectorFromField()
727fb1bcc12SMatthew G. Knepley @*/
72874d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmCreateLocalVectorFromField(DM dm,const char fieldname[],Vec *vec)
729bbe8250bSMatthew G. Knepley {
730fb1bcc12SMatthew G. Knepley   MPI_Comm       comm = PETSC_COMM_SELF;
731bbe8250bSMatthew G. Knepley   PetscErrorCode ierr;
732bbe8250bSMatthew G. Knepley 
733fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
734fb1bcc12SMatthew G. Knepley   ierr = DMSwarmCreateVectorFromField_Private(dm, fieldname, comm, vec);CHKERRQ(ierr);
735fb1bcc12SMatthew G. Knepley   PetscFunctionReturn(0);
736bbe8250bSMatthew G. Knepley }
737fb1bcc12SMatthew G. Knepley 
738fb1bcc12SMatthew G. Knepley /*@C
739fb1bcc12SMatthew G. Knepley    DMSwarmDestroyLocalVectorFromField - Destroys the Vec object which share the array associated with a given field
740fb1bcc12SMatthew G. Knepley 
741d083f849SBarry Smith    Collective on dm
742fb1bcc12SMatthew G. Knepley 
743fb1bcc12SMatthew G. Knepley    Input parameters:
74462741f57SDave May +  dm - a DMSwarm
74562741f57SDave May -  fieldname - the textual name given to a registered field
746fb1bcc12SMatthew G. Knepley 
7478b8a3813SDave May    Output parameter:
748fb1bcc12SMatthew G. Knepley .  vec - the vector
749fb1bcc12SMatthew G. Knepley 
750fb1bcc12SMatthew G. Knepley    Level: beginner
751fb1bcc12SMatthew G. Knepley 
7528b8a3813SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmCreateLocalVectorFromField()
753fb1bcc12SMatthew G. Knepley @*/
75474d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmDestroyLocalVectorFromField(DM dm,const char fieldname[],Vec *vec)
755fb1bcc12SMatthew G. Knepley {
756fb1bcc12SMatthew G. Knepley   PetscErrorCode ierr;
757fb1bcc12SMatthew G. Knepley 
758fb1bcc12SMatthew G. Knepley   PetscFunctionBegin;
759fb1bcc12SMatthew G. Knepley   ierr = DMSwarmDestroyVectorFromField_Private(dm, fieldname, vec);CHKERRQ(ierr);
760bbe8250bSMatthew G. Knepley   PetscFunctionReturn(0);
761bbe8250bSMatthew G. Knepley }
762bbe8250bSMatthew G. Knepley 
763d3a51819SDave May /*@C
764d3a51819SDave May    DMSwarmInitializeFieldRegister - Initiates the registration of fields to a DMSwarm
765d3a51819SDave May 
766d083f849SBarry Smith    Collective on dm
767d3a51819SDave May 
768d3a51819SDave May    Input parameter:
769d3a51819SDave May .  dm - a DMSwarm
770d3a51819SDave May 
771d3a51819SDave May    Level: beginner
772d3a51819SDave May 
773d3a51819SDave May    Notes:
7748b8a3813SDave May    After all fields have been registered, you must call DMSwarmFinalizeFieldRegister().
775d3a51819SDave May 
776d3a51819SDave May .seealso: DMSwarmFinalizeFieldRegister(), DMSwarmRegisterPetscDatatypeField(),
777d3a51819SDave May           DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
778d3a51819SDave May @*/
77974d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmInitializeFieldRegister(DM dm)
7805f50eb2eSDave May {
7815f50eb2eSDave May   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
7823454631fSDave May   PetscErrorCode ierr;
7833454631fSDave May 
784521f74f9SMatthew G. Knepley   PetscFunctionBegin;
785cc651181SDave May   if (!swarm->field_registration_initialized) {
7865f50eb2eSDave May     swarm->field_registration_initialized = PETSC_TRUE;
78743f984edSMatthew G. Knepley     ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_pid,1,PETSC_INT64);CHKERRQ(ierr); /* unique identifer */
788f0cdbbbaSDave May     ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_rank,1,PETSC_INT);CHKERRQ(ierr); /* used for communication */
789cc651181SDave May   }
7905f50eb2eSDave May   PetscFunctionReturn(0);
7915f50eb2eSDave May }
7925f50eb2eSDave May 
79374d0cae8SMatthew G. Knepley /*@
794d3a51819SDave May    DMSwarmFinalizeFieldRegister - Finalizes the registration of fields to a DMSwarm
795d3a51819SDave May 
796d083f849SBarry Smith    Collective on dm
797d3a51819SDave May 
798d3a51819SDave May    Input parameter:
799d3a51819SDave May .  dm - a DMSwarm
800d3a51819SDave May 
801d3a51819SDave May    Level: beginner
802d3a51819SDave May 
803d3a51819SDave May    Notes:
80462741f57SDave May    After DMSwarmFinalizeFieldRegister() has been called, no new fields can be defined on the DMSwarm.
805d3a51819SDave May 
806d3a51819SDave May .seealso: DMSwarmInitializeFieldRegister(), DMSwarmRegisterPetscDatatypeField(),
807d3a51819SDave May           DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
808d3a51819SDave May @*/
80974d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmFinalizeFieldRegister(DM dm)
8105f50eb2eSDave May {
8115f50eb2eSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
8126845f8f5SDave May   PetscErrorCode ierr;
8136845f8f5SDave May 
814521f74f9SMatthew G. Knepley   PetscFunctionBegin;
815f0cdbbbaSDave May   if (!swarm->field_registration_finalized) {
81677048351SPatrick Sanan     ierr = DMSwarmDataBucketFinalize(swarm->db);CHKERRQ(ierr);
817f0cdbbbaSDave May   }
818f0cdbbbaSDave May   swarm->field_registration_finalized = PETSC_TRUE;
8195f50eb2eSDave May   PetscFunctionReturn(0);
8205f50eb2eSDave May }
8215f50eb2eSDave May 
82274d0cae8SMatthew G. Knepley /*@
823d3a51819SDave May    DMSwarmSetLocalSizes - Sets the length of all registered fields on the DMSwarm
824d3a51819SDave May 
825d3a51819SDave May    Not collective
826d3a51819SDave May 
827d3a51819SDave May    Input parameters:
82862741f57SDave May +  dm - a DMSwarm
829d3a51819SDave May .  nlocal - the length of each registered field
83062741f57SDave May -  buffer - the length of the buffer used to efficient dynamic re-sizing
831d3a51819SDave May 
832d3a51819SDave May    Level: beginner
833d3a51819SDave May 
834d3a51819SDave May .seealso: DMSwarmGetLocalSize()
835d3a51819SDave May @*/
83674d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmSetLocalSizes(DM dm,PetscInt nlocal,PetscInt buffer)
8375f50eb2eSDave May {
8385f50eb2eSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
8396845f8f5SDave May   PetscErrorCode ierr;
8405f50eb2eSDave May 
841521f74f9SMatthew G. Knepley   PetscFunctionBegin;
842f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_SetSizes,0,0,0,0);CHKERRQ(ierr);
84377048351SPatrick Sanan   ierr = DMSwarmDataBucketSetSizes(swarm->db,nlocal,buffer);CHKERRQ(ierr);
844f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_SetSizes,0,0,0,0);CHKERRQ(ierr);
8455f50eb2eSDave May   PetscFunctionReturn(0);
8465f50eb2eSDave May }
8475f50eb2eSDave May 
84874d0cae8SMatthew G. Knepley /*@
849d3a51819SDave May    DMSwarmSetCellDM - Attachs a DM to a DMSwarm
850d3a51819SDave May 
851d083f849SBarry Smith    Collective on dm
852d3a51819SDave May 
853d3a51819SDave May    Input parameters:
85462741f57SDave May +  dm - a DMSwarm
85562741f57SDave May -  dmcell - the DM to attach to the DMSwarm
856d3a51819SDave May 
857d3a51819SDave May    Level: beginner
858d3a51819SDave May 
859d3a51819SDave May    Notes:
860d3a51819SDave May    The attached DM (dmcell) will be queried for point location and
8618b8a3813SDave May    neighbor MPI-rank information if DMSwarmMigrate() is called.
862d3a51819SDave May 
8638b8a3813SDave May .seealso: DMSwarmSetType(), DMSwarmGetCellDM(), DMSwarmMigrate()
864d3a51819SDave May @*/
86574d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmSetCellDM(DM dm,DM dmcell)
866b16650c8SDave May {
867b16650c8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
868521f74f9SMatthew G. Knepley 
869521f74f9SMatthew G. Knepley   PetscFunctionBegin;
870b16650c8SDave May   swarm->dmcell = dmcell;
871b16650c8SDave May   PetscFunctionReturn(0);
872b16650c8SDave May }
873b16650c8SDave May 
87474d0cae8SMatthew G. Knepley /*@
875d3a51819SDave May    DMSwarmGetCellDM - Fetches the attached cell DM
876d3a51819SDave May 
877d083f849SBarry Smith    Collective on dm
878d3a51819SDave May 
879d3a51819SDave May    Input parameter:
880d3a51819SDave May .  dm - a DMSwarm
881d3a51819SDave May 
882d3a51819SDave May    Output parameter:
883d3a51819SDave May .  dmcell - the DM which was attached to the DMSwarm
884d3a51819SDave May 
885d3a51819SDave May    Level: beginner
886d3a51819SDave May 
887d3a51819SDave May .seealso: DMSwarmSetCellDM()
888d3a51819SDave May @*/
88974d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmGetCellDM(DM dm,DM *dmcell)
890fe39f135SDave May {
891fe39f135SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
892521f74f9SMatthew G. Knepley 
893521f74f9SMatthew G. Knepley   PetscFunctionBegin;
894fe39f135SDave May   *dmcell = swarm->dmcell;
895fe39f135SDave May   PetscFunctionReturn(0);
896fe39f135SDave May }
897fe39f135SDave May 
89874d0cae8SMatthew G. Knepley /*@
899d3a51819SDave May    DMSwarmGetLocalSize - Retrives the local length of fields registered
900d3a51819SDave May 
901d3a51819SDave May    Not collective
902d3a51819SDave May 
903d3a51819SDave May    Input parameter:
904d3a51819SDave May .  dm - a DMSwarm
905d3a51819SDave May 
906d3a51819SDave May    Output parameter:
907d3a51819SDave May .  nlocal - the length of each registered field
908d3a51819SDave May 
909d3a51819SDave May    Level: beginner
910d3a51819SDave May 
9118b8a3813SDave May .seealso: DMSwarmGetSize(), DMSwarmSetLocalSizes()
912d3a51819SDave May @*/
91374d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmGetLocalSize(DM dm,PetscInt *nlocal)
914dcf43ee8SDave May {
915dcf43ee8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
916dcf43ee8SDave May   PetscErrorCode ierr;
917dcf43ee8SDave May 
918521f74f9SMatthew G. Knepley   PetscFunctionBegin;
919*5627991aSBarry Smith   ierr = DMSwarmDataBucketGetSizes(swarm->db,nlocal,NULL,NULL);CHKERRQ(ierr);
920dcf43ee8SDave May   PetscFunctionReturn(0);
921dcf43ee8SDave May }
922dcf43ee8SDave May 
92374d0cae8SMatthew G. Knepley /*@
924d3a51819SDave May    DMSwarmGetSize - Retrives the total length of fields registered
925d3a51819SDave May 
926d083f849SBarry Smith    Collective on dm
927d3a51819SDave May 
928d3a51819SDave May    Input parameter:
929d3a51819SDave May .  dm - a DMSwarm
930d3a51819SDave May 
931d3a51819SDave May    Output parameter:
932d3a51819SDave May .  n - the total length of each registered field
933d3a51819SDave May 
934d3a51819SDave May    Level: beginner
935d3a51819SDave May 
936d3a51819SDave May    Note:
937d3a51819SDave May    This calls MPI_Allreduce upon each call (inefficient but safe)
938d3a51819SDave May 
9398b8a3813SDave May .seealso: DMSwarmGetLocalSize(), DMSwarmSetLocalSizes()
940d3a51819SDave May @*/
94174d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmGetSize(DM dm,PetscInt *n)
942dcf43ee8SDave May {
943dcf43ee8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
944dcf43ee8SDave May   PetscErrorCode ierr;
945*5627991aSBarry Smith   PetscInt       nlocal;
946dcf43ee8SDave May 
947521f74f9SMatthew G. Knepley   PetscFunctionBegin;
94877048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
949*5627991aSBarry Smith   ierr = MPI_Allreduce(&nlocal,n,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr);
950dcf43ee8SDave May   PetscFunctionReturn(0);
951dcf43ee8SDave May }
952dcf43ee8SDave May 
953d3a51819SDave May /*@C
9548b8a3813SDave May    DMSwarmRegisterPetscDatatypeField - Register a field to a DMSwarm with a native PETSc data type
955d3a51819SDave May 
956d083f849SBarry Smith    Collective on dm
957d3a51819SDave May 
958d3a51819SDave May    Input parameters:
95962741f57SDave May +  dm - a DMSwarm
960d3a51819SDave May .  fieldname - the textual name to identify this field
961d3a51819SDave May .  blocksize - the number of each data type
96262741f57SDave May -  type - a valid PETSc data type (PETSC_CHAR, PETSC_SHORT, PETSC_INT, PETSC_FLOAT, PETSC_REAL, PETSC_LONG)
963d3a51819SDave May 
964d3a51819SDave May    Level: beginner
965d3a51819SDave May 
966d3a51819SDave May    Notes:
9678b8a3813SDave May    The textual name for each registered field must be unique.
968d3a51819SDave May 
969d3a51819SDave May .seealso: DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
970d3a51819SDave May @*/
97174d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmRegisterPetscDatatypeField(DM dm,const char fieldname[],PetscInt blocksize,PetscDataType type)
972b62e03f8SDave May {
9732eac95f8SDave May   PetscErrorCode ierr;
974b62e03f8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
975b62e03f8SDave May   size_t         size;
976b62e03f8SDave May 
977521f74f9SMatthew G. Knepley   PetscFunctionBegin;
9785f50eb2eSDave May   if (!swarm->field_registration_initialized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmInitializeFieldRegister() first");
9795f50eb2eSDave May   if (swarm->field_registration_finalized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Cannot register additional fields after calling DMSwarmFinalizeFieldRegister() first");
9805f50eb2eSDave May 
9815f50eb2eSDave May   if (type == PETSC_OBJECT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
9825f50eb2eSDave May   if (type == PETSC_FUNCTION) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
9835f50eb2eSDave May   if (type == PETSC_STRING) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
9845f50eb2eSDave May   if (type == PETSC_STRUCT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
9855f50eb2eSDave May   if (type == PETSC_DATATYPE_UNKNOWN) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
986b62e03f8SDave May 
9872ddcf43eSMatthew G. Knepley   ierr = PetscDataTypeGetSize(type, &size);CHKERRQ(ierr);
988b62e03f8SDave May   /* Load a specific data type into data bucket, specifying textual name and its size in bytes */
98977048351SPatrick Sanan   ierr = DMSwarmDataBucketRegisterField(swarm->db,"DMSwarmRegisterPetscDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
99052c3ed93SDave May   {
99177048351SPatrick Sanan     DMSwarmDataField gfield;
99252c3ed93SDave May 
99377048351SPatrick Sanan     ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
99477048351SPatrick Sanan     ierr = DMSwarmDataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
99552c3ed93SDave May   }
996b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = type;
997b62e03f8SDave May   PetscFunctionReturn(0);
998b62e03f8SDave May }
999b62e03f8SDave May 
1000d3a51819SDave May /*@C
1001d3a51819SDave May    DMSwarmRegisterUserStructField - Register a user defined struct to a DMSwarm
1002d3a51819SDave May 
1003d083f849SBarry Smith    Collective on dm
1004d3a51819SDave May 
1005d3a51819SDave May    Input parameters:
100662741f57SDave May +  dm - a DMSwarm
1007d3a51819SDave May .  fieldname - the textual name to identify this field
100862741f57SDave May -  size - the size in bytes of the user struct of each data type
1009d3a51819SDave May 
1010d3a51819SDave May    Level: beginner
1011d3a51819SDave May 
1012d3a51819SDave May    Notes:
10138b8a3813SDave May    The textual name for each registered field must be unique.
1014d3a51819SDave May 
1015d3a51819SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserDatatypeField()
1016d3a51819SDave May @*/
101774d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmRegisterUserStructField(DM dm,const char fieldname[],size_t size)
1018b62e03f8SDave May {
10192eac95f8SDave May   PetscErrorCode ierr;
1020b62e03f8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1021b62e03f8SDave May 
1022521f74f9SMatthew G. Knepley   PetscFunctionBegin;
102377048351SPatrick Sanan   ierr = DMSwarmDataBucketRegisterField(swarm->db,"DMSwarmRegisterUserStructField",fieldname,size,NULL);CHKERRQ(ierr);
1024b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_STRUCT ;
1025b62e03f8SDave May   PetscFunctionReturn(0);
1026b62e03f8SDave May }
1027b62e03f8SDave May 
1028d3a51819SDave May /*@C
1029d3a51819SDave May    DMSwarmRegisterUserDatatypeField - Register a user defined data type to a DMSwarm
1030d3a51819SDave May 
1031d083f849SBarry Smith    Collective on dm
1032d3a51819SDave May 
1033d3a51819SDave May    Input parameters:
103462741f57SDave May +  dm - a DMSwarm
1035d3a51819SDave May .  fieldname - the textual name to identify this field
1036d3a51819SDave May .  size - the size in bytes of the user data type
103762741f57SDave May -  blocksize - the number of each data type
1038d3a51819SDave May 
1039d3a51819SDave May    Level: beginner
1040d3a51819SDave May 
1041d3a51819SDave May    Notes:
10428b8a3813SDave May    The textual name for each registered field must be unique.
1043d3a51819SDave May 
1044d3a51819SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
1045d3a51819SDave May @*/
104674d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmRegisterUserDatatypeField(DM dm,const char fieldname[],size_t size,PetscInt blocksize)
1047b62e03f8SDave May {
1048b62e03f8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
10496845f8f5SDave May   PetscErrorCode ierr;
1050b62e03f8SDave May 
1051521f74f9SMatthew G. Knepley   PetscFunctionBegin;
105277048351SPatrick Sanan   ierr = DMSwarmDataBucketRegisterField(swarm->db,"DMSwarmRegisterUserDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
1053320740a0SDave May   {
105477048351SPatrick Sanan     DMSwarmDataField gfield;
1055320740a0SDave May 
105677048351SPatrick Sanan     ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
105777048351SPatrick Sanan     ierr = DMSwarmDataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
1058320740a0SDave May   }
1059b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_DATATYPE_UNKNOWN;
1060b62e03f8SDave May   PetscFunctionReturn(0);
1061b62e03f8SDave May }
1062b62e03f8SDave May 
1063d3a51819SDave May /*@C
1064d3a51819SDave May    DMSwarmGetField - Get access to the underlying array storing all entries associated with a registered field
1065d3a51819SDave May 
1066d3a51819SDave May    Not collective
1067d3a51819SDave May 
1068d3a51819SDave May    Input parameters:
106962741f57SDave May +  dm - a DMSwarm
107062741f57SDave May -  fieldname - the textual name to identify this field
1071d3a51819SDave May 
1072d3a51819SDave May    Output parameters:
107362741f57SDave May +  blocksize - the number of each data type
1074d3a51819SDave May .  type - the data type
107562741f57SDave May -  data - pointer to raw array
1076d3a51819SDave May 
1077d3a51819SDave May    Level: beginner
1078d3a51819SDave May 
1079d3a51819SDave May    Notes:
10808b8a3813SDave May    The array must be returned using a matching call to DMSwarmRestoreField().
1081d3a51819SDave May 
1082d3a51819SDave May .seealso: DMSwarmRestoreField()
1083d3a51819SDave May @*/
108474d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmGetField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
1085b62e03f8SDave May {
1086b62e03f8SDave May   DM_Swarm         *swarm = (DM_Swarm*)dm->data;
108777048351SPatrick Sanan   DMSwarmDataField gfield;
10882eac95f8SDave May   PetscErrorCode   ierr;
1089b62e03f8SDave May 
1090521f74f9SMatthew G. Knepley   PetscFunctionBegin;
10913454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
109277048351SPatrick Sanan   ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
109377048351SPatrick Sanan   ierr = DMSwarmDataFieldGetAccess(gfield);CHKERRQ(ierr);
109477048351SPatrick Sanan   ierr = DMSwarmDataFieldGetEntries(gfield,data);CHKERRQ(ierr);
10951b1ea282SDave May   if (blocksize) {*blocksize = gfield->bs; }
1096b5bcf523SDave May   if (type) { *type = gfield->petsc_type; }
1097b62e03f8SDave May   PetscFunctionReturn(0);
1098b62e03f8SDave May }
1099b62e03f8SDave May 
1100d3a51819SDave May /*@C
1101d3a51819SDave May    DMSwarmRestoreField - Restore access to the underlying array storing all entries associated with a registered field
1102d3a51819SDave May 
1103d3a51819SDave May    Not collective
1104d3a51819SDave May 
1105d3a51819SDave May    Input parameters:
110662741f57SDave May +  dm - a DMSwarm
110762741f57SDave May -  fieldname - the textual name to identify this field
1108d3a51819SDave May 
1109d3a51819SDave May    Output parameters:
111062741f57SDave May +  blocksize - the number of each data type
1111d3a51819SDave May .  type - the data type
111262741f57SDave May -  data - pointer to raw array
1113d3a51819SDave May 
1114d3a51819SDave May    Level: beginner
1115d3a51819SDave May 
1116d3a51819SDave May    Notes:
11178b8a3813SDave May    The user must call DMSwarmGetField() prior to calling DMSwarmRestoreField().
1118d3a51819SDave May 
1119d3a51819SDave May .seealso: DMSwarmGetField()
1120d3a51819SDave May @*/
112174d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmRestoreField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
1122b62e03f8SDave May {
1123b62e03f8SDave May   DM_Swarm         *swarm = (DM_Swarm*)dm->data;
112477048351SPatrick Sanan   DMSwarmDataField gfield;
11252eac95f8SDave May   PetscErrorCode   ierr;
1126b62e03f8SDave May 
1127521f74f9SMatthew G. Knepley   PetscFunctionBegin;
112877048351SPatrick Sanan   ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
112977048351SPatrick Sanan   ierr = DMSwarmDataFieldRestoreAccess(gfield);CHKERRQ(ierr);
1130b62e03f8SDave May   if (data) *data = NULL;
1131b62e03f8SDave May   PetscFunctionReturn(0);
1132b62e03f8SDave May }
1133b62e03f8SDave May 
113474d0cae8SMatthew G. Knepley /*@
1135d3a51819SDave May    DMSwarmAddPoint - Add space for one new point in the DMSwarm
1136d3a51819SDave May 
1137d3a51819SDave May    Not collective
1138d3a51819SDave May 
1139d3a51819SDave May    Input parameter:
1140d3a51819SDave May .  dm - a DMSwarm
1141d3a51819SDave May 
1142d3a51819SDave May    Level: beginner
1143d3a51819SDave May 
1144d3a51819SDave May    Notes:
11458b8a3813SDave May    The new point will have all fields initialized to zero.
1146d3a51819SDave May 
1147d3a51819SDave May .seealso: DMSwarmAddNPoints()
1148d3a51819SDave May @*/
114974d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmAddPoint(DM dm)
1150cb1d1399SDave May {
1151cb1d1399SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1152cb1d1399SDave May   PetscErrorCode ierr;
1153cb1d1399SDave May 
1154521f74f9SMatthew G. Knepley   PetscFunctionBegin;
11553454631fSDave May   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
1156f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
115777048351SPatrick Sanan   ierr = DMSwarmDataBucketAddPoint(swarm->db);CHKERRQ(ierr);
1158f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
1159cb1d1399SDave May   PetscFunctionReturn(0);
1160cb1d1399SDave May }
1161cb1d1399SDave May 
116274d0cae8SMatthew G. Knepley /*@
1163d3a51819SDave May    DMSwarmAddNPoints - Add space for a number of new points in the DMSwarm
1164d3a51819SDave May 
1165d3a51819SDave May    Not collective
1166d3a51819SDave May 
1167d3a51819SDave May    Input parameters:
116862741f57SDave May +  dm - a DMSwarm
116962741f57SDave May -  npoints - the number of new points to add
1170d3a51819SDave May 
1171d3a51819SDave May    Level: beginner
1172d3a51819SDave May 
1173d3a51819SDave May    Notes:
11748b8a3813SDave May    The new point will have all fields initialized to zero.
1175d3a51819SDave May 
1176d3a51819SDave May .seealso: DMSwarmAddPoint()
1177d3a51819SDave May @*/
117874d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmAddNPoints(DM dm,PetscInt npoints)
1179cb1d1399SDave May {
1180cb1d1399SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1181cb1d1399SDave May   PetscErrorCode ierr;
1182cb1d1399SDave May   PetscInt       nlocal;
1183cb1d1399SDave May 
1184521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1185f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
118677048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
1187cb1d1399SDave May   nlocal = nlocal + npoints;
118877048351SPatrick Sanan   ierr = DMSwarmDataBucketSetSizes(swarm->db,nlocal,DMSWARM_DATA_BUCKET_BUFFER_DEFAULT);CHKERRQ(ierr);
1189f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
1190cb1d1399SDave May   PetscFunctionReturn(0);
1191cb1d1399SDave May }
1192cb1d1399SDave May 
119374d0cae8SMatthew G. Knepley /*@
1194d3a51819SDave May    DMSwarmRemovePoint - Remove the last point from the DMSwarm
1195d3a51819SDave May 
1196d3a51819SDave May    Not collective
1197d3a51819SDave May 
1198d3a51819SDave May    Input parameter:
1199d3a51819SDave May .  dm - a DMSwarm
1200d3a51819SDave May 
1201d3a51819SDave May    Level: beginner
1202d3a51819SDave May 
1203d3a51819SDave May .seealso: DMSwarmRemovePointAtIndex()
1204d3a51819SDave May @*/
120574d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmRemovePoint(DM dm)
1206cb1d1399SDave May {
1207cb1d1399SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1208cb1d1399SDave May   PetscErrorCode ierr;
1209cb1d1399SDave May 
1210521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1211f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
121277048351SPatrick Sanan   ierr = DMSwarmDataBucketRemovePoint(swarm->db);CHKERRQ(ierr);
1213f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
1214cb1d1399SDave May   PetscFunctionReturn(0);
1215cb1d1399SDave May }
1216cb1d1399SDave May 
121774d0cae8SMatthew G. Knepley /*@
1218d3a51819SDave May    DMSwarmRemovePointAtIndex - Removes a specific point from the DMSwarm
1219d3a51819SDave May 
1220d3a51819SDave May    Not collective
1221d3a51819SDave May 
1222d3a51819SDave May    Input parameters:
122362741f57SDave May +  dm - a DMSwarm
122462741f57SDave May -  idx - index of point to remove
1225d3a51819SDave May 
1226d3a51819SDave May    Level: beginner
1227d3a51819SDave May 
1228d3a51819SDave May .seealso: DMSwarmRemovePoint()
1229d3a51819SDave May @*/
123074d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmRemovePointAtIndex(DM dm,PetscInt idx)
1231cb1d1399SDave May {
1232cb1d1399SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1233cb1d1399SDave May   PetscErrorCode ierr;
1234cb1d1399SDave May 
1235521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1236f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
123777048351SPatrick Sanan   ierr = DMSwarmDataBucketRemovePointAtIndex(swarm->db,idx);CHKERRQ(ierr);
1238f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
1239cb1d1399SDave May   PetscFunctionReturn(0);
1240cb1d1399SDave May }
1241b62e03f8SDave May 
124274d0cae8SMatthew G. Knepley /*@
1243ba4fc9c6SDave May    DMSwarmCopyPoint - Copy point pj to point pi in the DMSwarm
1244ba4fc9c6SDave May 
1245ba4fc9c6SDave May    Not collective
1246ba4fc9c6SDave May 
1247ba4fc9c6SDave May    Input parameters:
1248ba4fc9c6SDave May +  dm - a DMSwarm
1249ba4fc9c6SDave May .  pi - the index of the point to copy
1250ba4fc9c6SDave May -  pj - the point index where the copy should be located
1251ba4fc9c6SDave May 
1252ba4fc9c6SDave May  Level: beginner
1253ba4fc9c6SDave May 
1254ba4fc9c6SDave May .seealso: DMSwarmRemovePoint()
1255ba4fc9c6SDave May @*/
125674d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmCopyPoint(DM dm,PetscInt pi,PetscInt pj)
1257ba4fc9c6SDave May {
1258ba4fc9c6SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1259ba4fc9c6SDave May   PetscErrorCode ierr;
1260ba4fc9c6SDave May 
1261ba4fc9c6SDave May   PetscFunctionBegin;
1262ba4fc9c6SDave May   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
126377048351SPatrick Sanan   ierr = DMSwarmDataBucketCopyPoint(swarm->db,pi,swarm->db,pj);CHKERRQ(ierr);
1264ba4fc9c6SDave May   PetscFunctionReturn(0);
1265ba4fc9c6SDave May }
1266ba4fc9c6SDave May 
1267095059a4SDave May PetscErrorCode DMSwarmMigrate_Basic(DM dm,PetscBool remove_sent_points)
12683454631fSDave May {
1269dcf43ee8SDave May   PetscErrorCode ierr;
1270521f74f9SMatthew G. Knepley 
1271521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1272dcf43ee8SDave May   ierr = DMSwarmMigrate_Push_Basic(dm,remove_sent_points);CHKERRQ(ierr);
12733454631fSDave May   PetscFunctionReturn(0);
12743454631fSDave May }
12753454631fSDave May 
127674d0cae8SMatthew G. Knepley /*@
1277d3a51819SDave May    DMSwarmMigrate - Relocates points defined in the DMSwarm to other MPI-ranks
1278d3a51819SDave May 
1279d083f849SBarry Smith    Collective on dm
1280d3a51819SDave May 
1281d3a51819SDave May    Input parameters:
128262741f57SDave May +  dm - the DMSwarm
128362741f57SDave May -  remove_sent_points - flag indicating if sent points should be removed from the current MPI-rank
1284d3a51819SDave May 
1285d3a51819SDave May    Notes:
1286a5b23f4aSJose E. Roman    The DM will be modified to accommodate received points.
12878b8a3813SDave May    If remove_sent_points = PETSC_TRUE, any points that were sent will be removed from the DM.
12888b8a3813SDave May    Different styles of migration are supported. See DMSwarmSetMigrateType().
1289d3a51819SDave May 
1290d3a51819SDave May    Level: advanced
1291d3a51819SDave May 
1292d3a51819SDave May .seealso: DMSwarmSetMigrateType()
1293d3a51819SDave May @*/
129474d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmMigrate(DM dm,PetscBool remove_sent_points)
12953454631fSDave May {
1296f0cdbbbaSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
12973454631fSDave May   PetscErrorCode ierr;
1298f0cdbbbaSDave May 
1299521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1300ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
1301f0cdbbbaSDave May   switch (swarm->migrate_type) {
1302f0cdbbbaSDave May     case DMSWARM_MIGRATE_BASIC:
1303095059a4SDave May       ierr = DMSwarmMigrate_Basic(dm,remove_sent_points);CHKERRQ(ierr);
1304f0cdbbbaSDave May       break;
1305f0cdbbbaSDave May     case DMSWARM_MIGRATE_DMCELLNSCATTER:
1306f0cdbbbaSDave May       ierr = DMSwarmMigrate_CellDMScatter(dm,remove_sent_points);CHKERRQ(ierr);
1307f0cdbbbaSDave May       break;
1308f0cdbbbaSDave May     case DMSWARM_MIGRATE_DMCELLEXACT:
1309f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_DMCELLEXACT not implemented");
1310f0cdbbbaSDave May     case DMSWARM_MIGRATE_USER:
1311f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_USER not implemented");
1312f0cdbbbaSDave May     default:
1313f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE type unknown");
1314f0cdbbbaSDave May   }
1315ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
1316183d2d45SMatthew G. Knepley   ierr = DMClearGlobalVectors(dm);CHKERRQ(ierr);
13173454631fSDave May   PetscFunctionReturn(0);
13183454631fSDave May }
13193454631fSDave May 
1320f0cdbbbaSDave May PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm,PetscInt *globalsize);
1321f0cdbbbaSDave May 
1322d3a51819SDave May /*
1323d3a51819SDave May  DMSwarmCollectViewCreate
1324d3a51819SDave May 
1325d3a51819SDave May  * Applies a collection method and gathers point neighbour points into dm
1326d3a51819SDave May 
1327d3a51819SDave May  Notes:
13288b8a3813SDave May  Users should call DMSwarmCollectViewDestroy() after
1329d3a51819SDave May  they have finished computations associated with the collected points
1330d3a51819SDave May */
1331d3a51819SDave May 
133274d0cae8SMatthew G. Knepley /*@
1333d3a51819SDave May    DMSwarmCollectViewCreate - Applies a collection method and gathers points
1334*5627991aSBarry Smith                               in neighbour ranks into the DMSwarm
1335d3a51819SDave May 
1336d083f849SBarry Smith    Collective on dm
1337d3a51819SDave May 
1338d3a51819SDave May    Input parameter:
1339d3a51819SDave May .  dm - the DMSwarm
1340d3a51819SDave May 
1341d3a51819SDave May    Notes:
1342d3a51819SDave May    Users should call DMSwarmCollectViewDestroy() after
1343d3a51819SDave May    they have finished computations associated with the collected points
13448b8a3813SDave May    Different collect methods are supported. See DMSwarmSetCollectType().
1345d3a51819SDave May 
1346d3a51819SDave May    Level: advanced
1347d3a51819SDave May 
1348d3a51819SDave May .seealso: DMSwarmCollectViewDestroy(), DMSwarmSetCollectType()
1349d3a51819SDave May @*/
135074d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmCollectViewCreate(DM dm)
13512712d1f2SDave May {
13522712d1f2SDave May   PetscErrorCode ierr;
13532712d1f2SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
13542712d1f2SDave May   PetscInt       ng;
13552712d1f2SDave May 
1356521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1357480eef7bSDave May   if (swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView currently active");
1358480eef7bSDave May   ierr = DMSwarmGetLocalSize(dm,&ng);CHKERRQ(ierr);
1359480eef7bSDave May   switch (swarm->collect_type) {
1360f0cdbbbaSDave May 
1361480eef7bSDave May     case DMSWARM_COLLECT_BASIC:
13622712d1f2SDave May       ierr = DMSwarmMigrate_GlobalToLocal_Basic(dm,&ng);CHKERRQ(ierr);
1363480eef7bSDave May       break;
1364480eef7bSDave May     case DMSWARM_COLLECT_DMDABOUNDINGBOX:
1365f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_DMDABOUNDINGBOX not implemented");
1366480eef7bSDave May     case DMSWARM_COLLECT_GENERAL:
1367f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_GENERAL not implemented");
1368480eef7bSDave May     default:
1369f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT type unknown");
1370480eef7bSDave May   }
1371480eef7bSDave May   swarm->collect_view_active = PETSC_TRUE;
1372480eef7bSDave May   swarm->collect_view_reset_nlocal = ng;
13732712d1f2SDave May   PetscFunctionReturn(0);
13742712d1f2SDave May }
13752712d1f2SDave May 
137674d0cae8SMatthew G. Knepley /*@
1377d3a51819SDave May    DMSwarmCollectViewDestroy - Resets the DMSwarm to the size prior to calling DMSwarmCollectViewCreate()
1378d3a51819SDave May 
1379d083f849SBarry Smith    Collective on dm
1380d3a51819SDave May 
1381d3a51819SDave May    Input parameters:
1382d3a51819SDave May .  dm - the DMSwarm
1383d3a51819SDave May 
1384d3a51819SDave May    Notes:
1385d3a51819SDave May    Users should call DMSwarmCollectViewCreate() before this function is called.
1386d3a51819SDave May 
1387d3a51819SDave May    Level: advanced
1388d3a51819SDave May 
1389d3a51819SDave May .seealso: DMSwarmCollectViewCreate(), DMSwarmSetCollectType()
1390d3a51819SDave May @*/
139174d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmCollectViewDestroy(DM dm)
13922712d1f2SDave May {
13932712d1f2SDave May   PetscErrorCode ierr;
13942712d1f2SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
13952712d1f2SDave May 
1396521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1397480eef7bSDave May   if (!swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView is currently not active");
1398480eef7bSDave May   ierr = DMSwarmSetLocalSizes(dm,swarm->collect_view_reset_nlocal,-1);CHKERRQ(ierr);
1399480eef7bSDave May   swarm->collect_view_active = PETSC_FALSE;
14002712d1f2SDave May   PetscFunctionReturn(0);
14012712d1f2SDave May }
14023454631fSDave May 
1403f0cdbbbaSDave May PetscErrorCode DMSwarmSetUpPIC(DM dm)
1404f0cdbbbaSDave May {
1405f0cdbbbaSDave May   PetscInt       dim;
1406f0cdbbbaSDave May   PetscErrorCode ierr;
1407f0cdbbbaSDave May 
1408521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1409f0cdbbbaSDave May   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
1410f0cdbbbaSDave May   if (dim < 1) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
1411f0cdbbbaSDave May   if (dim > 3) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
1412f0cdbbbaSDave May   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_coor,dim,PETSC_DOUBLE);CHKERRQ(ierr);
1413e2d107dbSDave May   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_cellid,1,PETSC_INT);CHKERRQ(ierr);
1414f0cdbbbaSDave May   PetscFunctionReturn(0);
1415f0cdbbbaSDave May }
1416f0cdbbbaSDave May 
141774d0cae8SMatthew G. Knepley /*@
141831403186SMatthew G. Knepley   DMSwarmSetPointCoordinatesRandom - Sets initial coordinates for particles in each cell
141931403186SMatthew G. Knepley 
142031403186SMatthew G. Knepley   Collective on dm
142131403186SMatthew G. Knepley 
142231403186SMatthew G. Knepley   Input parameters:
142331403186SMatthew G. Knepley + dm  - the DMSwarm
142431403186SMatthew G. Knepley - Npc - The number of particles per cell in the cell DM
142531403186SMatthew G. Knepley 
142631403186SMatthew G. Knepley   Notes:
142731403186SMatthew G. Knepley   The user must use DMSwarmSetCellDM() to set the cell DM first. The particles are placed randomly inside each cell. If only
142831403186SMatthew G. Knepley   one particle is in each cell, it is placed at the centroid.
142931403186SMatthew G. Knepley 
143031403186SMatthew G. Knepley   Level: intermediate
143131403186SMatthew G. Knepley 
143231403186SMatthew G. Knepley .seealso: DMSwarmSetCellDM()
143331403186SMatthew G. Knepley @*/
143431403186SMatthew G. Knepley PetscErrorCode DMSwarmSetPointCoordinatesRandom(DM dm, PetscInt Npc)
143531403186SMatthew G. Knepley {
143631403186SMatthew G. Knepley   DM             cdm;
143731403186SMatthew G. Knepley   PetscRandom    rnd;
143831403186SMatthew G. Knepley   DMPolytopeType ct;
143931403186SMatthew G. Knepley   PetscBool      simplex;
144031403186SMatthew G. Knepley   PetscReal     *centroid, *coords, *xi0, *v0, *J, *invJ, detJ;
144131403186SMatthew G. Knepley   PetscInt       dim, d, cStart, cEnd, c, p;
144231403186SMatthew G. Knepley   PetscErrorCode ierr;
144331403186SMatthew G. Knepley 
144431403186SMatthew G. Knepley   PetscFunctionBeginUser;
144531403186SMatthew G. Knepley   ierr = PetscRandomCreate(PetscObjectComm((PetscObject) dm), &rnd);CHKERRQ(ierr);
144631403186SMatthew G. Knepley   ierr = PetscRandomSetInterval(rnd, -1.0, 1.0);CHKERRQ(ierr);
144731403186SMatthew G. Knepley   ierr = PetscRandomSetType(rnd, PETSCRAND48);CHKERRQ(ierr);
144831403186SMatthew G. Knepley 
144931403186SMatthew G. Knepley   ierr = DMSwarmGetCellDM(dm, &cdm);CHKERRQ(ierr);
145031403186SMatthew G. Knepley   ierr = DMGetDimension(cdm, &dim);CHKERRQ(ierr);
145131403186SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr);
145231403186SMatthew G. Knepley   ierr = DMPlexGetCellType(cdm, cStart, &ct);CHKERRQ(ierr);
145331403186SMatthew G. Knepley   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE;
145431403186SMatthew G. Knepley 
145531403186SMatthew G. Knepley   ierr = PetscMalloc5(dim, &centroid, dim, &xi0, dim, &v0, dim*dim, &J, dim*dim, &invJ);CHKERRQ(ierr);
145631403186SMatthew G. Knepley   for (d = 0; d < dim; ++d) xi0[d] = -1.0;
145731403186SMatthew G. Knepley   ierr = DMSwarmGetField(dm, DMSwarmPICField_coor, NULL, NULL, (void **) &coords);CHKERRQ(ierr);
145831403186SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
145931403186SMatthew G. Knepley     if (Npc == 1) {
146031403186SMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFVM(cdm, c, NULL, centroid, NULL);CHKERRQ(ierr);
146131403186SMatthew G. Knepley       for (d = 0; d < dim; ++d) coords[c*dim+d] = centroid[d];
146231403186SMatthew G. Knepley     } else {
146331403186SMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFEM(cdm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); /* affine */
146431403186SMatthew G. Knepley       for (p = 0; p < Npc; ++p) {
146531403186SMatthew G. Knepley         const PetscInt n   = c*Npc + p;
146631403186SMatthew G. Knepley         PetscReal      sum = 0.0, refcoords[3];
146731403186SMatthew G. Knepley 
146831403186SMatthew G. Knepley         for (d = 0; d < dim; ++d) {
146931403186SMatthew G. Knepley           ierr = PetscRandomGetValueReal(rnd, &refcoords[d]);CHKERRQ(ierr);
147031403186SMatthew G. Knepley           sum += refcoords[d];
147131403186SMatthew G. Knepley         }
147231403186SMatthew G. Knepley         if (simplex && sum > 0.0) for (d = 0; d < dim; ++d) refcoords[d] -= PetscSqrtReal(dim)*sum;
147331403186SMatthew G. Knepley         CoordinatesRefToReal(dim, dim, xi0, v0, J, refcoords, &coords[n*dim]);
147431403186SMatthew G. Knepley       }
147531403186SMatthew G. Knepley     }
147631403186SMatthew G. Knepley   }
147731403186SMatthew G. Knepley   ierr = DMSwarmRestoreField(dm, DMSwarmPICField_coor, NULL, NULL, (void **) &coords);CHKERRQ(ierr);
147831403186SMatthew G. Knepley   ierr = PetscFree5(centroid, xi0, v0, J, invJ);CHKERRQ(ierr);
147931403186SMatthew G. Knepley   ierr = PetscRandomDestroy(&rnd);CHKERRQ(ierr);
148031403186SMatthew G. Knepley   PetscFunctionReturn(0);
148131403186SMatthew G. Knepley }
148231403186SMatthew G. Knepley 
148331403186SMatthew G. Knepley /*@
1484d3a51819SDave May    DMSwarmSetType - Set particular flavor of DMSwarm
1485d3a51819SDave May 
1486d083f849SBarry Smith    Collective on dm
1487d3a51819SDave May 
1488d3a51819SDave May    Input parameters:
148962741f57SDave May +  dm - the DMSwarm
149062741f57SDave May -  stype - the DMSwarm type (e.g. DMSWARM_PIC)
1491d3a51819SDave May 
1492d3a51819SDave May    Level: advanced
1493d3a51819SDave May 
1494*5627991aSBarry Smith .seealso: DMSwarmSetMigrateType(), DMSwarmSetCollectType(), DMSwarmType, DMSWARM_PIC, DMSWARM_BASIC
1495d3a51819SDave May @*/
149674d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmSetType(DM dm,DMSwarmType stype)
1497f0cdbbbaSDave May {
1498f0cdbbbaSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1499f0cdbbbaSDave May   PetscErrorCode ierr;
1500f0cdbbbaSDave May 
1501521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1502f0cdbbbaSDave May   swarm->swarm_type = stype;
1503f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
1504f0cdbbbaSDave May     ierr = DMSwarmSetUpPIC(dm);CHKERRQ(ierr);
1505f0cdbbbaSDave May   }
1506f0cdbbbaSDave May   PetscFunctionReturn(0);
1507f0cdbbbaSDave May }
1508f0cdbbbaSDave May 
15093454631fSDave May PetscErrorCode DMSetup_Swarm(DM dm)
15103454631fSDave May {
15113454631fSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
15123454631fSDave May   PetscErrorCode ierr;
15133454631fSDave May   PetscMPIInt    rank;
15143454631fSDave May   PetscInt       p,npoints,*rankval;
15153454631fSDave May 
1516521f74f9SMatthew G. Knepley   PetscFunctionBegin;
15173454631fSDave May   if (swarm->issetup) PetscFunctionReturn(0);
15183454631fSDave May   swarm->issetup = PETSC_TRUE;
15193454631fSDave May 
1520f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
1521f0cdbbbaSDave May     /* check dmcell exists */
1522f0cdbbbaSDave May     if (!swarm->dmcell) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires you call DMSwarmSetCellDM");
1523f0cdbbbaSDave May 
1524f0cdbbbaSDave May     if (swarm->dmcell->ops->locatepointssubdomain) {
1525f0cdbbbaSDave May       /* check methods exists for exact ownership identificiation */
152677b6ec44SMatthew G. Knepley       ierr = PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->ops->LocatePointsSubdomain\n");CHKERRQ(ierr);
1527f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLEXACT;
1528f0cdbbbaSDave May     } else {
1529f0cdbbbaSDave May       /* check methods exist for point location AND rank neighbor identification */
1530f0cdbbbaSDave May       if (swarm->dmcell->ops->locatepoints) {
153177b6ec44SMatthew G. Knepley         ierr = PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->LocatePoints\n");CHKERRQ(ierr);
1532f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->locatepoints be defined");
1533f0cdbbbaSDave May 
1534f0cdbbbaSDave May       if (swarm->dmcell->ops->getneighbors) {
153577b6ec44SMatthew G. Knepley         ierr = PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->GetNeigbors\n");CHKERRQ(ierr);
1536f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->getneighbors be defined");
1537f0cdbbbaSDave May 
1538f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLNSCATTER;
1539f0cdbbbaSDave May     }
1540f0cdbbbaSDave May   }
1541f0cdbbbaSDave May 
1542f0cdbbbaSDave May   ierr = DMSwarmFinalizeFieldRegister(dm);CHKERRQ(ierr);
1543f0cdbbbaSDave May 
15443454631fSDave May   /* check some fields were registered */
15453454631fSDave May   if (swarm->db->nfields <= 2) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"At least one field user must be registered via DMSwarmRegisterXXX()");
15463454631fSDave May 
15473454631fSDave May   /* check local sizes were set */
15483454631fSDave May   if (swarm->db->L == -1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Local sizes must be set via DMSwarmSetLocalSizes()");
15493454631fSDave May 
15503454631fSDave May   /* initialize values in pid and rank placeholders */
15513454631fSDave May   /* TODO: [pid - use MPI_Scan] */
1552ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRMPI(ierr);
155377048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db,&npoints,NULL,NULL);CHKERRQ(ierr);
1554f0cdbbbaSDave May   ierr = DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
15553454631fSDave May   for (p=0; p<npoints; p++) {
15563454631fSDave May     rankval[p] = (PetscInt)rank;
15573454631fSDave May   }
1558f0cdbbbaSDave May   ierr = DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
15593454631fSDave May   PetscFunctionReturn(0);
15603454631fSDave May }
15613454631fSDave May 
1562dc5f5ce9SDave May extern PetscErrorCode DMSwarmSortDestroy(DMSwarmSort *_ctx);
1563dc5f5ce9SDave May 
156457795646SDave May PetscErrorCode DMDestroy_Swarm(DM dm)
156557795646SDave May {
156657795646SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
156757795646SDave May   PetscErrorCode ierr;
156857795646SDave May 
156957795646SDave May   PetscFunctionBegin;
1570d0c080abSJoseph Pusztay   if (--swarm->refct > 0) PetscFunctionReturn(0);
157177048351SPatrick Sanan   ierr = DMSwarmDataBucketDestroy(&swarm->db);CHKERRQ(ierr);
1572dc5f5ce9SDave May   if (swarm->sort_context) {
1573dc5f5ce9SDave May     ierr = DMSwarmSortDestroy(&swarm->sort_context);CHKERRQ(ierr);
1574dc5f5ce9SDave May   }
157557795646SDave May   ierr = PetscFree(swarm);CHKERRQ(ierr);
157657795646SDave May   PetscFunctionReturn(0);
157757795646SDave May }
157857795646SDave May 
1579a9ee3421SMatthew G. Knepley PetscErrorCode DMSwarmView_Draw(DM dm, PetscViewer viewer)
1580a9ee3421SMatthew G. Knepley {
1581a9ee3421SMatthew G. Knepley   DM             cdm;
1582a9ee3421SMatthew G. Knepley   PetscDraw      draw;
158331403186SMatthew G. Knepley   PetscReal     *coords, oldPause, radius = 0.01;
1584a9ee3421SMatthew G. Knepley   PetscInt       Np, p, bs;
1585a9ee3421SMatthew G. Knepley   PetscErrorCode ierr;
1586a9ee3421SMatthew G. Knepley 
1587a9ee3421SMatthew G. Knepley   PetscFunctionBegin;
158831403186SMatthew G. Knepley   ierr = PetscOptionsGetReal(NULL, ((PetscObject) dm)->prefix, "-dm_view_swarm_radius", &radius, NULL);CHKERRQ(ierr);
1589a9ee3421SMatthew G. Knepley   ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr);
1590a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetCellDM(dm, &cdm);CHKERRQ(ierr);
1591a9ee3421SMatthew G. Knepley   ierr = PetscDrawGetPause(draw, &oldPause);CHKERRQ(ierr);
1592a9ee3421SMatthew G. Knepley   ierr = PetscDrawSetPause(draw, 0.0);CHKERRQ(ierr);
1593a9ee3421SMatthew G. Knepley   ierr = DMView(cdm, viewer);CHKERRQ(ierr);
1594a9ee3421SMatthew G. Knepley   ierr = PetscDrawSetPause(draw, oldPause);CHKERRQ(ierr);
1595a9ee3421SMatthew G. Knepley 
1596a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetLocalSize(dm, &Np);CHKERRQ(ierr);
1597a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1598a9ee3421SMatthew G. Knepley   for (p = 0; p < Np; ++p) {
1599a9ee3421SMatthew G. Knepley     const PetscInt i = p*bs;
1600a9ee3421SMatthew G. Knepley 
160131403186SMatthew G. Knepley     ierr = PetscDrawEllipse(draw, coords[i], coords[i+1], radius, radius, PETSC_DRAW_BLUE);CHKERRQ(ierr);
1602a9ee3421SMatthew G. Knepley   }
1603a9ee3421SMatthew G. Knepley   ierr = DMSwarmRestoreField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1604a9ee3421SMatthew G. Knepley   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
1605a9ee3421SMatthew G. Knepley   ierr = PetscDrawPause(draw);CHKERRQ(ierr);
1606a9ee3421SMatthew G. Knepley   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
1607a9ee3421SMatthew G. Knepley   PetscFunctionReturn(0);
1608a9ee3421SMatthew G. Knepley }
1609a9ee3421SMatthew G. Knepley 
16105f50eb2eSDave May PetscErrorCode DMView_Swarm(DM dm, PetscViewer viewer)
16115f50eb2eSDave May {
16125f50eb2eSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1613*5627991aSBarry Smith   PetscBool      iascii,ibinary,isvtk,isdraw;
1614*5627991aSBarry Smith #if defined(PETSC_HAVE_HDF5)
1615*5627991aSBarry Smith   PetscBool      ishdf5;
1616*5627991aSBarry Smith #endif
16175f50eb2eSDave May   PetscErrorCode ierr;
16185f50eb2eSDave May 
16195f50eb2eSDave May   PetscFunctionBegin;
16205f50eb2eSDave May   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
16215f50eb2eSDave May   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
16225f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
16235f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY,&ibinary);CHKERRQ(ierr);
16245f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK,   &isvtk);CHKERRQ(ierr);
1625*5627991aSBarry Smith #if defined(PETSC_HAVE_HDF5)
16265f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
1627*5627991aSBarry Smith #endif
1628a9ee3421SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW,  &isdraw);CHKERRQ(ierr);
16295f50eb2eSDave May   if (iascii) {
163077048351SPatrick Sanan     ierr = DMSwarmDataBucketView(PetscObjectComm((PetscObject)dm),swarm->db,NULL,DATABUCKET_VIEW_STDOUT);CHKERRQ(ierr);
1631298827fbSBarry Smith   } else if (ibinary) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO Binary support");
16325f50eb2eSDave May #if defined(PETSC_HAVE_HDF5)
163374d0cae8SMatthew G. Knepley   else if (ishdf5) {
163474d0cae8SMatthew G. Knepley     ierr = DMSwarmView_HDF5(dm, viewer);CHKERRQ(ierr);
163574d0cae8SMatthew G. Knepley   }
16365f50eb2eSDave May #endif
1637298827fbSBarry Smith   else if (isdraw) {
1638a9ee3421SMatthew G. Knepley     ierr = DMSwarmView_Draw(dm, viewer);CHKERRQ(ierr);
16395f50eb2eSDave May   }
16405f50eb2eSDave May   PetscFunctionReturn(0);
16415f50eb2eSDave May }
16425f50eb2eSDave May 
1643d0c080abSJoseph Pusztay /*@C
1644d0c080abSJoseph Pusztay    DMSwarmGetCellSwarm - Extracts a single cell from the DMSwarm object, returns it as a single cell DMSwarm.
1645d0c080abSJoseph 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.
1646d0c080abSJoseph Pusztay 
1647d0c080abSJoseph Pusztay    Important: Changes to this cell of the swarm will be lost if they are made prior to restoring this cell.
1648d0c080abSJoseph Pusztay 
1649d0c080abSJoseph Pusztay    Noncollective
1650d0c080abSJoseph Pusztay 
1651d0c080abSJoseph Pusztay    Input parameters:
1652d0c080abSJoseph Pusztay +  sw - the DMSwarm
1653*5627991aSBarry Smith .  cellID - the integer id of the cell to be extracted and filtered
1654*5627991aSBarry Smith -  cellswarm - The DMSwarm to receive the cell
1655d0c080abSJoseph Pusztay 
1656d0c080abSJoseph Pusztay    Level: beginner
1657d0c080abSJoseph Pusztay 
1658*5627991aSBarry Smith    Notes:
1659*5627991aSBarry Smith       This presently only supports DMSWARM_PIC type
1660*5627991aSBarry Smith 
1661*5627991aSBarry Smith       Should be restored with DMSwarmRestoreCellSwarm()
1662d0c080abSJoseph Pusztay 
1663d0c080abSJoseph Pusztay .seealso: DMSwarmRestoreCellSwarm()
1664d0c080abSJoseph Pusztay @*/
1665d0c080abSJoseph Pusztay PETSC_EXTERN PetscErrorCode DMSwarmGetCellSwarm(DM sw, PetscInt cellID, DM cellswarm)
1666d0c080abSJoseph Pusztay {
1667d0c080abSJoseph Pusztay   DM_Swarm      *original = (DM_Swarm*) sw->data;
1668d0c080abSJoseph Pusztay   DMLabel        label;
1669d0c080abSJoseph Pusztay   DM             dmc, subdmc;
1670d0c080abSJoseph Pusztay   PetscInt      *pids, particles, dim;
1671d0c080abSJoseph Pusztay   PetscErrorCode ierr;
1672d0c080abSJoseph Pusztay 
1673d0c080abSJoseph Pusztay   PetscFunctionBegin;
1674d0c080abSJoseph Pusztay   /* Configure new swarm */
1675d0c080abSJoseph Pusztay   ierr = DMSetType(cellswarm, DMSWARM);CHKERRQ(ierr);
1676d0c080abSJoseph Pusztay   ierr = DMGetDimension(sw, &dim);CHKERRQ(ierr);
1677d0c080abSJoseph Pusztay   ierr = DMSetDimension(cellswarm, dim);CHKERRQ(ierr);
1678d0c080abSJoseph Pusztay   ierr = DMSwarmSetType(cellswarm, DMSWARM_PIC);CHKERRQ(ierr);
1679d0c080abSJoseph Pusztay   /* Destroy the unused, unconfigured data bucket to prevent stragglers in memory */
16801e1ea65dSPierre Jolivet   ierr = DMSwarmDataBucketDestroy(&((DM_Swarm*)cellswarm->data)->db);CHKERRQ(ierr);
1681d0c080abSJoseph Pusztay   ierr = DMSwarmSortGetAccess(sw);CHKERRQ(ierr);
1682d0c080abSJoseph Pusztay   ierr = DMSwarmSortGetNumberOfPointsPerCell(sw, cellID, &particles);CHKERRQ(ierr);
1683d0c080abSJoseph Pusztay   ierr = DMSwarmSortGetPointsPerCell(sw, cellID, &particles, &pids);CHKERRQ(ierr);
16841e1ea65dSPierre Jolivet   ierr = DMSwarmDataBucketCreateFromSubset(original->db, particles, pids, &((DM_Swarm*)cellswarm->data)->db);CHKERRQ(ierr);
1685d0c080abSJoseph Pusztay   ierr = DMSwarmSortRestoreAccess(sw);CHKERRQ(ierr);
1686d0c080abSJoseph Pusztay   ierr = PetscFree(pids);CHKERRQ(ierr);
1687d0c080abSJoseph Pusztay   ierr = DMSwarmGetCellDM(sw, &dmc);CHKERRQ(ierr);
1688d0c080abSJoseph Pusztay   ierr = DMLabelCreate(PetscObjectComm((PetscObject)sw), "singlecell", &label);CHKERRQ(ierr);
1689d0c080abSJoseph Pusztay   ierr = DMAddLabel(dmc, label);CHKERRQ(ierr);
1690d0c080abSJoseph Pusztay   ierr = DMLabelSetValue(label, cellID, 1);CHKERRQ(ierr);
1691d0c080abSJoseph Pusztay   ierr = DMPlexFilter(dmc, label, 1, &subdmc);CHKERRQ(ierr);
16921e1ea65dSPierre Jolivet   ierr = DMSwarmSetCellDM(cellswarm, subdmc);CHKERRQ(ierr);
16931e1ea65dSPierre Jolivet   ierr = DMLabelDestroy(&label);CHKERRQ(ierr);
1694d0c080abSJoseph Pusztay   PetscFunctionReturn(0);
1695d0c080abSJoseph Pusztay }
1696d0c080abSJoseph Pusztay 
1697d0c080abSJoseph Pusztay /*@C
1698*5627991aSBarry Smith    DMSwarmRestoreCellSwarm - Restores a DMSwarm object obtained with DMSwarmGetCellSwarm(). All fields are copied back into the parent swarm.
1699d0c080abSJoseph Pusztay 
1700d0c080abSJoseph Pusztay    Noncollective
1701d0c080abSJoseph Pusztay 
1702d0c080abSJoseph Pusztay    Input parameters:
1703d0c080abSJoseph Pusztay +  sw - the parent DMSwarm
1704d0c080abSJoseph Pusztay .  cellID - the integer id of the cell to be copied back into the parent swarm
1705d0c080abSJoseph Pusztay -  cellswarm - the cell swarm object
1706d0c080abSJoseph Pusztay 
1707d0c080abSJoseph Pusztay    Level: beginner
1708d0c080abSJoseph Pusztay 
1709*5627991aSBarry Smith    Note:
1710*5627991aSBarry Smith     This only supports DMSWARM_PIC types of DMSwarms
1711d0c080abSJoseph Pusztay 
1712d0c080abSJoseph Pusztay .seealso: DMSwarmGetCellSwarm()
1713d0c080abSJoseph Pusztay @*/
1714d0c080abSJoseph Pusztay PETSC_EXTERN PetscErrorCode DMSwarmRestoreCellSwarm(DM sw, PetscInt cellID, DM cellswarm)
1715d0c080abSJoseph Pusztay {
1716d0c080abSJoseph Pusztay   DM             dmc;
1717d0c080abSJoseph Pusztay   PetscInt       *pids, particles, p;
1718d0c080abSJoseph Pusztay   PetscErrorCode ierr;
1719d0c080abSJoseph Pusztay 
1720d0c080abSJoseph Pusztay   PetscFunctionBegin;
1721d0c080abSJoseph Pusztay   ierr = DMSwarmSortGetAccess(sw);CHKERRQ(ierr);
1722d0c080abSJoseph Pusztay   ierr = DMSwarmSortGetPointsPerCell(sw, cellID, &particles, &pids);CHKERRQ(ierr);
1723d0c080abSJoseph Pusztay   ierr = DMSwarmSortRestoreAccess(sw);CHKERRQ(ierr);
1724d0c080abSJoseph Pusztay   /* Pointwise copy of each particle based on pid. The parent swarm may not be altered during this process. */
1725d0c080abSJoseph Pusztay   for (p=0; p<particles; ++p) {
1726d0c080abSJoseph Pusztay     ierr = DMSwarmDataBucketCopyPoint(((DM_Swarm*)cellswarm->data)->db,pids[p],((DM_Swarm*)sw->data)->db,pids[p]);CHKERRQ(ierr);
1727d0c080abSJoseph Pusztay   }
1728d0c080abSJoseph Pusztay   /* Free memory, destroy cell dm */
17291e1ea65dSPierre Jolivet   ierr = DMSwarmGetCellDM(cellswarm, &dmc);CHKERRQ(ierr);
17301e1ea65dSPierre Jolivet   ierr = DMDestroy(&dmc);CHKERRQ(ierr);
1731d0c080abSJoseph Pusztay   ierr = PetscFree(pids);CHKERRQ(ierr);
1732d0c080abSJoseph Pusztay   PetscFunctionReturn(0);
1733d0c080abSJoseph Pusztay }
1734d0c080abSJoseph Pusztay 
1735d0c080abSJoseph Pusztay PETSC_INTERN PetscErrorCode DMClone_Swarm(DM, DM *);
1736d0c080abSJoseph Pusztay 
1737d0c080abSJoseph Pusztay static PetscErrorCode DMInitialize_Swarm(DM sw)
1738d0c080abSJoseph Pusztay {
1739d0c080abSJoseph Pusztay   PetscFunctionBegin;
1740d0c080abSJoseph Pusztay   sw->dim  = 0;
1741d0c080abSJoseph Pusztay   sw->ops->view                            = DMView_Swarm;
1742d0c080abSJoseph Pusztay   sw->ops->load                            = NULL;
1743d0c080abSJoseph Pusztay   sw->ops->setfromoptions                  = NULL;
1744d0c080abSJoseph Pusztay   sw->ops->clone                           = DMClone_Swarm;
1745d0c080abSJoseph Pusztay   sw->ops->setup                           = DMSetup_Swarm;
1746d0c080abSJoseph Pusztay   sw->ops->createlocalsection              = NULL;
1747d0c080abSJoseph Pusztay   sw->ops->createdefaultconstraints        = NULL;
1748d0c080abSJoseph Pusztay   sw->ops->createglobalvector              = DMCreateGlobalVector_Swarm;
1749d0c080abSJoseph Pusztay   sw->ops->createlocalvector               = DMCreateLocalVector_Swarm;
1750d0c080abSJoseph Pusztay   sw->ops->getlocaltoglobalmapping         = NULL;
1751d0c080abSJoseph Pusztay   sw->ops->createfieldis                   = NULL;
1752d0c080abSJoseph Pusztay   sw->ops->createcoordinatedm              = NULL;
1753d0c080abSJoseph Pusztay   sw->ops->getcoloring                     = NULL;
1754d0c080abSJoseph Pusztay   sw->ops->creatematrix                    = DMCreateMatrix_Swarm;
1755d0c080abSJoseph Pusztay   sw->ops->createinterpolation             = NULL;
1756d0c080abSJoseph Pusztay   sw->ops->createinjection                 = NULL;
1757d0c080abSJoseph Pusztay   sw->ops->createmassmatrix                = DMCreateMassMatrix_Swarm;
1758d0c080abSJoseph Pusztay   sw->ops->refine                          = NULL;
1759d0c080abSJoseph Pusztay   sw->ops->coarsen                         = NULL;
1760d0c080abSJoseph Pusztay   sw->ops->refinehierarchy                 = NULL;
1761d0c080abSJoseph Pusztay   sw->ops->coarsenhierarchy                = NULL;
1762d0c080abSJoseph Pusztay   sw->ops->globaltolocalbegin              = NULL;
1763d0c080abSJoseph Pusztay   sw->ops->globaltolocalend                = NULL;
1764d0c080abSJoseph Pusztay   sw->ops->localtoglobalbegin              = NULL;
1765d0c080abSJoseph Pusztay   sw->ops->localtoglobalend                = NULL;
1766d0c080abSJoseph Pusztay   sw->ops->destroy                         = DMDestroy_Swarm;
1767d0c080abSJoseph Pusztay   sw->ops->createsubdm                     = NULL;
1768d0c080abSJoseph Pusztay   sw->ops->getdimpoints                    = NULL;
1769d0c080abSJoseph Pusztay   sw->ops->locatepoints                    = NULL;
1770d0c080abSJoseph Pusztay   PetscFunctionReturn(0);
1771d0c080abSJoseph Pusztay }
1772d0c080abSJoseph Pusztay 
1773d0c080abSJoseph Pusztay PETSC_INTERN PetscErrorCode DMClone_Swarm(DM dm, DM *newdm)
1774d0c080abSJoseph Pusztay {
1775d0c080abSJoseph Pusztay   DM_Swarm       *swarm = (DM_Swarm *) dm->data;
1776d0c080abSJoseph Pusztay   PetscErrorCode ierr;
1777d0c080abSJoseph Pusztay 
1778d0c080abSJoseph Pusztay   PetscFunctionBegin;
1779d0c080abSJoseph Pusztay   swarm->refct++;
1780d0c080abSJoseph Pusztay   (*newdm)->data = swarm;
1781d0c080abSJoseph Pusztay   ierr = PetscObjectChangeTypeName((PetscObject) *newdm, DMSWARM);CHKERRQ(ierr);
1782d0c080abSJoseph Pusztay   ierr = DMInitialize_Swarm(*newdm);CHKERRQ(ierr);
17832e56dffeSJoe Pusztay   (*newdm)->dim = dm->dim;
1784d0c080abSJoseph Pusztay   PetscFunctionReturn(0);
1785d0c080abSJoseph Pusztay }
1786d0c080abSJoseph Pusztay 
1787d3a51819SDave May /*MC
1788d3a51819SDave May 
1789d3a51819SDave May  DMSWARM = "swarm" - A DM object used to represent arrays of data (fields) of arbitrary data type.
179062741f57SDave May  This implementation was designed for particle methods in which the underlying
1791d3a51819SDave May  data required to be represented is both (i) dynamic in length, (ii) and of arbitrary data type.
1792d3a51819SDave May 
179362741f57SDave May  User data can be represented by DMSwarm through a registering "fields".
179462741f57SDave May  To register a field, the user must provide;
179562741f57SDave May  (a) a unique name;
179662741f57SDave May  (b) the data type (or size in bytes);
179762741f57SDave May  (c) the block size of the data.
1798d3a51819SDave May 
1799d3a51819SDave May  For example, suppose the application requires a unique id, energy, momentum and density to be stored
1800c215a47eSMatthew Knepley  on a set of particles. Then the following code could be used
1801d3a51819SDave May 
180262741f57SDave May $    DMSwarmInitializeFieldRegister(dm)
180362741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"uid",1,PETSC_LONG);
180462741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"energy",1,PETSC_REAL);
180562741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"momentum",3,PETSC_REAL);
180662741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"density",1,PETSC_FLOAT);
180762741f57SDave May $    DMSwarmFinalizeFieldRegister(dm)
1808d3a51819SDave May 
1809d3a51819SDave May  The fields represented by DMSwarm are dynamic and can be re-sized at any time.
181062741f57SDave May  The only restriction imposed by DMSwarm is that all fields contain the same number of points.
1811d3a51819SDave May 
1812d3a51819SDave May  To support particle methods, "migration" techniques are provided. These methods migrate data
1813*5627991aSBarry Smith  between ranks.
1814d3a51819SDave May 
1815d3a51819SDave May  DMSwarm supports the methods DMCreateGlobalVector() and DMCreateLocalVector().
1816d3a51819SDave May  As a DMSwarm may internally define and store values of different data types,
181762741f57SDave May  before calling DMCreateGlobalVector() or DMCreateLocalVector(), the user must inform DMSwarm which
1818d3a51819SDave May  fields should be used to define a Vec object via
1819d3a51819SDave May    DMSwarmVectorDefineField()
1820c215a47eSMatthew Knepley  The specified field can be changed at any time - thereby permitting vectors
1821c215a47eSMatthew Knepley  compatible with different fields to be created.
1822d3a51819SDave May 
182362741f57SDave May  A dual representation of fields in the DMSwarm and a Vec object is permitted via
1824d3a51819SDave May    DMSwarmCreateGlobalVectorFromField()
1825d3a51819SDave May  Here the data defining the field in the DMSwarm is shared with a Vec.
1826d3a51819SDave May  This is inherently unsafe if you alter the size of the field at any time between
1827d3a51819SDave May  calls to DMSwarmCreateGlobalVectorFromField() and DMSwarmDestroyGlobalVectorFromField().
1828cc651181SDave May  If the local size of the DMSwarm does not match the local size of the global vector
1829cc651181SDave May  when DMSwarmDestroyGlobalVectorFromField() is called, an error is thrown.
1830d3a51819SDave May 
183162741f57SDave May  Additional high-level support is provided for Particle-In-Cell methods.
183262741f57SDave May  Please refer to the man page for DMSwarmSetType().
183362741f57SDave May 
1834d3a51819SDave May  Level: beginner
1835d3a51819SDave May 
1836d3a51819SDave May .seealso: DMType, DMCreate(), DMSetType()
1837d3a51819SDave May M*/
183857795646SDave May PETSC_EXTERN PetscErrorCode DMCreate_Swarm(DM dm)
183957795646SDave May {
184057795646SDave May   DM_Swarm      *swarm;
184157795646SDave May   PetscErrorCode ierr;
184257795646SDave May 
184357795646SDave May   PetscFunctionBegin;
184457795646SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
184557795646SDave May   ierr     = PetscNewLog(dm,&swarm);CHKERRQ(ierr);
1846f0cdbbbaSDave May   dm->data = swarm;
184777048351SPatrick Sanan   ierr = DMSwarmDataBucketCreate(&swarm->db);CHKERRQ(ierr);
1848f0cdbbbaSDave May   ierr = DMSwarmInitializeFieldRegister(dm);CHKERRQ(ierr);
1849d0c080abSJoseph Pusztay   swarm->refct = 1;
1850b5bcf523SDave May   swarm->vec_field_set                  = PETSC_FALSE;
18513454631fSDave May   swarm->issetup                        = PETSC_FALSE;
1852480eef7bSDave May   swarm->swarm_type                     = DMSWARM_BASIC;
1853480eef7bSDave May   swarm->migrate_type                   = DMSWARM_MIGRATE_BASIC;
1854480eef7bSDave May   swarm->collect_type                   = DMSWARM_COLLECT_BASIC;
185540c453e9SDave May   swarm->migrate_error_on_missing_point = PETSC_FALSE;
1856f0cdbbbaSDave May   swarm->dmcell                         = NULL;
1857f0cdbbbaSDave May   swarm->collect_view_active            = PETSC_FALSE;
1858f0cdbbbaSDave May   swarm->collect_view_reset_nlocal      = -1;
1859d0c080abSJoseph Pusztay   ierr = DMInitialize_Swarm(dm);CHKERRQ(ierr);
186057795646SDave May   PetscFunctionReturn(0);
186157795646SDave May }
1862