xref: /petsc/src/dm/impls/swarm/swarm.c (revision f9558f5cfdb2a0bba47ae047cb39a904cf6f17eb)
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); */
46*f9558f5cSBarry 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);
65*f9558f5cSBarry 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;
76*f9558f5cSBarry Smith #if defined(PETSC_HAVE_HDF5)
7774d0cae8SMatthew G. Knepley   PetscBool      ishdf5;
78*f9558f5cSBarry 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");
84*f9558f5cSBarry 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);
88*f9558f5cSBarry Smith       PetscFunctionReturn(0);
8974d0cae8SMatthew G. Knepley   }
90*f9558f5cSBarry Smith #endif
91*f9558f5cSBarry 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");
176cc651181SDave 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 */
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);
201fb1bcc12SMatthew G. Knepley   if (nlocal/bs != swarm->db->L) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSwarm sizes have changed since vector was created - cannot ensure pointers are valid"); /* Stale data */
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 
763b5bcf523SDave May /*
76474d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmCreateGlobalVectorFromFields(DM dm,const PetscInt nf,const char *fieldnames[],Vec *vec)
765b5bcf523SDave May {
766b5bcf523SDave May   PetscFunctionReturn(0);
767b5bcf523SDave May }
768b5bcf523SDave May 
76974d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmRestoreGlobalVectorFromFields(DM dm,Vec *vec)
770b5bcf523SDave May {
771b5bcf523SDave May   PetscFunctionReturn(0);
772b5bcf523SDave May }
773b5bcf523SDave May */
774b5bcf523SDave May 
775d3a51819SDave May /*@C
776d3a51819SDave May    DMSwarmInitializeFieldRegister - Initiates the registration of fields to a DMSwarm
777d3a51819SDave May 
778d083f849SBarry Smith    Collective on dm
779d3a51819SDave May 
780d3a51819SDave May    Input parameter:
781d3a51819SDave May .  dm - a DMSwarm
782d3a51819SDave May 
783d3a51819SDave May    Level: beginner
784d3a51819SDave May 
785d3a51819SDave May    Notes:
7868b8a3813SDave May    After all fields have been registered, you must call DMSwarmFinalizeFieldRegister().
787d3a51819SDave May 
788d3a51819SDave May .seealso: DMSwarmFinalizeFieldRegister(), DMSwarmRegisterPetscDatatypeField(),
789d3a51819SDave May  DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
790d3a51819SDave May @*/
79174d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmInitializeFieldRegister(DM dm)
7925f50eb2eSDave May {
7935f50eb2eSDave May   DM_Swarm      *swarm = (DM_Swarm *) dm->data;
7943454631fSDave May   PetscErrorCode ierr;
7953454631fSDave May 
796521f74f9SMatthew G. Knepley   PetscFunctionBegin;
797cc651181SDave May   if (!swarm->field_registration_initialized) {
7985f50eb2eSDave May     swarm->field_registration_initialized = PETSC_TRUE;
79943f984edSMatthew G. Knepley     ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_pid,1,PETSC_INT64);CHKERRQ(ierr); /* unique identifer */
800f0cdbbbaSDave May     ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmField_rank,1,PETSC_INT);CHKERRQ(ierr); /* used for communication */
801cc651181SDave May   }
8025f50eb2eSDave May   PetscFunctionReturn(0);
8035f50eb2eSDave May }
8045f50eb2eSDave May 
80574d0cae8SMatthew G. Knepley /*@
806d3a51819SDave May    DMSwarmFinalizeFieldRegister - Finalizes the registration of fields to a DMSwarm
807d3a51819SDave May 
808d083f849SBarry Smith    Collective on dm
809d3a51819SDave May 
810d3a51819SDave May    Input parameter:
811d3a51819SDave May .  dm - a DMSwarm
812d3a51819SDave May 
813d3a51819SDave May    Level: beginner
814d3a51819SDave May 
815d3a51819SDave May    Notes:
81662741f57SDave May    After DMSwarmFinalizeFieldRegister() has been called, no new fields can be defined on the DMSwarm.
817d3a51819SDave May 
818d3a51819SDave May .seealso: DMSwarmInitializeFieldRegister(), DMSwarmRegisterPetscDatatypeField(),
819d3a51819SDave May  DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
820d3a51819SDave May @*/
82174d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmFinalizeFieldRegister(DM dm)
8225f50eb2eSDave May {
8235f50eb2eSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
8246845f8f5SDave May   PetscErrorCode ierr;
8256845f8f5SDave May 
826521f74f9SMatthew G. Knepley   PetscFunctionBegin;
827f0cdbbbaSDave May   if (!swarm->field_registration_finalized) {
82877048351SPatrick Sanan     ierr = DMSwarmDataBucketFinalize(swarm->db);CHKERRQ(ierr);
829f0cdbbbaSDave May   }
830f0cdbbbaSDave May   swarm->field_registration_finalized = PETSC_TRUE;
8315f50eb2eSDave May   PetscFunctionReturn(0);
8325f50eb2eSDave May }
8335f50eb2eSDave May 
83474d0cae8SMatthew G. Knepley /*@
835d3a51819SDave May    DMSwarmSetLocalSizes - Sets the length of all registered fields on the DMSwarm
836d3a51819SDave May 
837d3a51819SDave May    Not collective
838d3a51819SDave May 
839d3a51819SDave May    Input parameters:
84062741f57SDave May +  dm - a DMSwarm
841d3a51819SDave May .  nlocal - the length of each registered field
84262741f57SDave May -  buffer - the length of the buffer used to efficient dynamic re-sizing
843d3a51819SDave May 
844d3a51819SDave May    Level: beginner
845d3a51819SDave May 
846d3a51819SDave May .seealso: DMSwarmGetLocalSize()
847d3a51819SDave May @*/
84874d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmSetLocalSizes(DM dm,PetscInt nlocal,PetscInt buffer)
8495f50eb2eSDave May {
8505f50eb2eSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
8516845f8f5SDave May   PetscErrorCode ierr;
8525f50eb2eSDave May 
853521f74f9SMatthew G. Knepley   PetscFunctionBegin;
854f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_SetSizes,0,0,0,0);CHKERRQ(ierr);
85577048351SPatrick Sanan   ierr = DMSwarmDataBucketSetSizes(swarm->db,nlocal,buffer);CHKERRQ(ierr);
856f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_SetSizes,0,0,0,0);CHKERRQ(ierr);
8575f50eb2eSDave May   PetscFunctionReturn(0);
8585f50eb2eSDave May }
8595f50eb2eSDave May 
86074d0cae8SMatthew G. Knepley /*@
861d3a51819SDave May    DMSwarmSetCellDM - Attachs a DM to a DMSwarm
862d3a51819SDave May 
863d083f849SBarry Smith    Collective on dm
864d3a51819SDave May 
865d3a51819SDave May    Input parameters:
86662741f57SDave May +  dm - a DMSwarm
86762741f57SDave May -  dmcell - the DM to attach to the DMSwarm
868d3a51819SDave May 
869d3a51819SDave May    Level: beginner
870d3a51819SDave May 
871d3a51819SDave May    Notes:
872d3a51819SDave May    The attached DM (dmcell) will be queried for point location and
8738b8a3813SDave May    neighbor MPI-rank information if DMSwarmMigrate() is called.
874d3a51819SDave May 
8758b8a3813SDave May .seealso: DMSwarmSetType(), DMSwarmGetCellDM(), DMSwarmMigrate()
876d3a51819SDave May @*/
87774d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmSetCellDM(DM dm,DM dmcell)
878b16650c8SDave May {
879b16650c8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
880521f74f9SMatthew G. Knepley 
881521f74f9SMatthew G. Knepley   PetscFunctionBegin;
882b16650c8SDave May   swarm->dmcell = dmcell;
883b16650c8SDave May   PetscFunctionReturn(0);
884b16650c8SDave May }
885b16650c8SDave May 
88674d0cae8SMatthew G. Knepley /*@
887d3a51819SDave May    DMSwarmGetCellDM - Fetches the attached cell DM
888d3a51819SDave May 
889d083f849SBarry Smith    Collective on dm
890d3a51819SDave May 
891d3a51819SDave May    Input parameter:
892d3a51819SDave May .  dm - a DMSwarm
893d3a51819SDave May 
894d3a51819SDave May    Output parameter:
895d3a51819SDave May .  dmcell - the DM which was attached to the DMSwarm
896d3a51819SDave May 
897d3a51819SDave May    Level: beginner
898d3a51819SDave May 
899d3a51819SDave May .seealso: DMSwarmSetCellDM()
900d3a51819SDave May @*/
90174d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmGetCellDM(DM dm,DM *dmcell)
902fe39f135SDave May {
903fe39f135SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
904521f74f9SMatthew G. Knepley 
905521f74f9SMatthew G. Knepley   PetscFunctionBegin;
906fe39f135SDave May   *dmcell = swarm->dmcell;
907fe39f135SDave May   PetscFunctionReturn(0);
908fe39f135SDave May }
909fe39f135SDave May 
91074d0cae8SMatthew G. Knepley /*@
911d3a51819SDave May    DMSwarmGetLocalSize - Retrives the local length of fields registered
912d3a51819SDave May 
913d3a51819SDave May    Not collective
914d3a51819SDave May 
915d3a51819SDave May    Input parameter:
916d3a51819SDave May .  dm - a DMSwarm
917d3a51819SDave May 
918d3a51819SDave May    Output parameter:
919d3a51819SDave May .  nlocal - the length of each registered field
920d3a51819SDave May 
921d3a51819SDave May    Level: beginner
922d3a51819SDave May 
9238b8a3813SDave May .seealso: DMSwarmGetSize(), DMSwarmSetLocalSizes()
924d3a51819SDave May @*/
92574d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmGetLocalSize(DM dm,PetscInt *nlocal)
926dcf43ee8SDave May {
927dcf43ee8SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
928dcf43ee8SDave May   PetscErrorCode ierr;
929dcf43ee8SDave May 
930521f74f9SMatthew G. Knepley   PetscFunctionBegin;
93177048351SPatrick Sanan   if (nlocal) {ierr = DMSwarmDataBucketGetSizes(swarm->db,nlocal,NULL,NULL);CHKERRQ(ierr);}
932dcf43ee8SDave May   PetscFunctionReturn(0);
933dcf43ee8SDave May }
934dcf43ee8SDave May 
93574d0cae8SMatthew G. Knepley /*@
936d3a51819SDave May    DMSwarmGetSize - Retrives the total length of fields registered
937d3a51819SDave May 
938d083f849SBarry Smith    Collective on dm
939d3a51819SDave May 
940d3a51819SDave May    Input parameter:
941d3a51819SDave May .  dm - a DMSwarm
942d3a51819SDave May 
943d3a51819SDave May    Output parameter:
944d3a51819SDave May .  n - the total length of each registered field
945d3a51819SDave May 
946d3a51819SDave May    Level: beginner
947d3a51819SDave May 
948d3a51819SDave May    Note:
949d3a51819SDave May    This calls MPI_Allreduce upon each call (inefficient but safe)
950d3a51819SDave May 
9518b8a3813SDave May .seealso: DMSwarmGetLocalSize(), DMSwarmSetLocalSizes()
952d3a51819SDave May @*/
95374d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmGetSize(DM dm,PetscInt *n)
954dcf43ee8SDave May {
955dcf43ee8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
956dcf43ee8SDave May   PetscErrorCode ierr;
957dcf43ee8SDave May   PetscInt       nlocal,ng;
958dcf43ee8SDave May 
959521f74f9SMatthew G. Knepley   PetscFunctionBegin;
96077048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
961ffc4695bSBarry Smith   ierr = MPI_Allreduce(&nlocal,&ng,1,MPIU_INT,MPI_SUM,PetscObjectComm((PetscObject)dm));CHKERRMPI(ierr);
962dcf43ee8SDave May   if (n) { *n = ng; }
963dcf43ee8SDave May   PetscFunctionReturn(0);
964dcf43ee8SDave May }
965dcf43ee8SDave May 
966d3a51819SDave May /*@C
9678b8a3813SDave May    DMSwarmRegisterPetscDatatypeField - Register a field to a DMSwarm with a native PETSc data type
968d3a51819SDave May 
969d083f849SBarry Smith    Collective on dm
970d3a51819SDave May 
971d3a51819SDave May    Input parameters:
97262741f57SDave May +  dm - a DMSwarm
973d3a51819SDave May .  fieldname - the textual name to identify this field
974d3a51819SDave May .  blocksize - the number of each data type
97562741f57SDave May -  type - a valid PETSc data type (PETSC_CHAR, PETSC_SHORT, PETSC_INT, PETSC_FLOAT, PETSC_REAL, PETSC_LONG)
976d3a51819SDave May 
977d3a51819SDave May    Level: beginner
978d3a51819SDave May 
979d3a51819SDave May    Notes:
9808b8a3813SDave May    The textual name for each registered field must be unique.
981d3a51819SDave May 
982d3a51819SDave May .seealso: DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
983d3a51819SDave May @*/
98474d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmRegisterPetscDatatypeField(DM dm,const char fieldname[],PetscInt blocksize,PetscDataType type)
985b62e03f8SDave May {
9862eac95f8SDave May   PetscErrorCode ierr;
987b62e03f8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
988b62e03f8SDave May   size_t         size;
989b62e03f8SDave May 
990521f74f9SMatthew G. Knepley   PetscFunctionBegin;
9915f50eb2eSDave May   if (!swarm->field_registration_initialized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Must call DMSwarmInitializeFieldRegister() first");
9925f50eb2eSDave May   if (swarm->field_registration_finalized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Cannot register additional fields after calling DMSwarmFinalizeFieldRegister() first");
9935f50eb2eSDave May 
9945f50eb2eSDave May   if (type == PETSC_OBJECT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
9955f50eb2eSDave May   if (type == PETSC_FUNCTION) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
9965f50eb2eSDave May   if (type == PETSC_STRING) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
9975f50eb2eSDave May   if (type == PETSC_STRUCT) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
9985f50eb2eSDave May   if (type == PETSC_DATATYPE_UNKNOWN) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"Valid for {char,short,int,long,float,double}");
999b62e03f8SDave May 
10002ddcf43eSMatthew G. Knepley   ierr = PetscDataTypeGetSize(type, &size);CHKERRQ(ierr);
1001b62e03f8SDave May   /* Load a specific data type into data bucket, specifying textual name and its size in bytes */
100277048351SPatrick Sanan   ierr = DMSwarmDataBucketRegisterField(swarm->db,"DMSwarmRegisterPetscDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
100352c3ed93SDave May   {
100477048351SPatrick Sanan     DMSwarmDataField gfield;
100552c3ed93SDave May 
100677048351SPatrick Sanan     ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
100777048351SPatrick Sanan     ierr = DMSwarmDataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
100852c3ed93SDave May   }
1009b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = type;
1010b62e03f8SDave May   PetscFunctionReturn(0);
1011b62e03f8SDave May }
1012b62e03f8SDave May 
1013d3a51819SDave May /*@C
1014d3a51819SDave May    DMSwarmRegisterUserStructField - Register a user defined struct to a DMSwarm
1015d3a51819SDave May 
1016d083f849SBarry Smith    Collective on dm
1017d3a51819SDave May 
1018d3a51819SDave May    Input parameters:
101962741f57SDave May +  dm - a DMSwarm
1020d3a51819SDave May .  fieldname - the textual name to identify this field
102162741f57SDave May -  size - the size in bytes of the user struct of each data type
1022d3a51819SDave May 
1023d3a51819SDave May    Level: beginner
1024d3a51819SDave May 
1025d3a51819SDave May    Notes:
10268b8a3813SDave May    The textual name for each registered field must be unique.
1027d3a51819SDave May 
1028d3a51819SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserDatatypeField()
1029d3a51819SDave May @*/
103074d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmRegisterUserStructField(DM dm,const char fieldname[],size_t size)
1031b62e03f8SDave May {
10322eac95f8SDave May   PetscErrorCode ierr;
1033b62e03f8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1034b62e03f8SDave May 
1035521f74f9SMatthew G. Knepley   PetscFunctionBegin;
103677048351SPatrick Sanan   ierr = DMSwarmDataBucketRegisterField(swarm->db,"DMSwarmRegisterUserStructField",fieldname,size,NULL);CHKERRQ(ierr);
1037b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_STRUCT ;
1038b62e03f8SDave May   PetscFunctionReturn(0);
1039b62e03f8SDave May }
1040b62e03f8SDave May 
1041d3a51819SDave May /*@C
1042d3a51819SDave May    DMSwarmRegisterUserDatatypeField - Register a user defined data type to a DMSwarm
1043d3a51819SDave May 
1044d083f849SBarry Smith    Collective on dm
1045d3a51819SDave May 
1046d3a51819SDave May    Input parameters:
104762741f57SDave May +  dm - a DMSwarm
1048d3a51819SDave May .  fieldname - the textual name to identify this field
1049d3a51819SDave May .  size - the size in bytes of the user data type
105062741f57SDave May -  blocksize - the number of each data type
1051d3a51819SDave May 
1052d3a51819SDave May    Level: beginner
1053d3a51819SDave May 
1054d3a51819SDave May    Notes:
10558b8a3813SDave May    The textual name for each registered field must be unique.
1056d3a51819SDave May 
1057d3a51819SDave May .seealso: DMSwarmRegisterPetscDatatypeField(), DMSwarmRegisterUserStructField(), DMSwarmRegisterUserDatatypeField()
1058d3a51819SDave May @*/
105974d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmRegisterUserDatatypeField(DM dm,const char fieldname[],size_t size,PetscInt blocksize)
1060b62e03f8SDave May {
1061b62e03f8SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
10626845f8f5SDave May   PetscErrorCode ierr;
1063b62e03f8SDave May 
1064521f74f9SMatthew G. Knepley   PetscFunctionBegin;
106577048351SPatrick Sanan   ierr = DMSwarmDataBucketRegisterField(swarm->db,"DMSwarmRegisterUserDatatypeField",fieldname,blocksize*size,NULL);CHKERRQ(ierr);
1066320740a0SDave May   {
106777048351SPatrick Sanan     DMSwarmDataField gfield;
1068320740a0SDave May 
106977048351SPatrick Sanan     ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
107077048351SPatrick Sanan     ierr = DMSwarmDataFieldSetBlockSize(gfield,blocksize);CHKERRQ(ierr);
1071320740a0SDave May   }
1072b62e03f8SDave May   swarm->db->field[swarm->db->nfields-1]->petsc_type = PETSC_DATATYPE_UNKNOWN;
1073b62e03f8SDave May   PetscFunctionReturn(0);
1074b62e03f8SDave May }
1075b62e03f8SDave May 
1076d3a51819SDave May /*@C
1077d3a51819SDave May    DMSwarmGetField - Get access to the underlying array storing all entries associated with a registered field
1078d3a51819SDave May 
1079d3a51819SDave May    Not collective
1080d3a51819SDave May 
1081d3a51819SDave May    Input parameters:
108262741f57SDave May +  dm - a DMSwarm
108362741f57SDave May -  fieldname - the textual name to identify this field
1084d3a51819SDave May 
1085d3a51819SDave May    Output parameters:
108662741f57SDave May +  blocksize - the number of each data type
1087d3a51819SDave May .  type - the data type
108862741f57SDave May -  data - pointer to raw array
1089d3a51819SDave May 
1090d3a51819SDave May    Level: beginner
1091d3a51819SDave May 
1092d3a51819SDave May    Notes:
10938b8a3813SDave May    The array must be returned using a matching call to DMSwarmRestoreField().
1094d3a51819SDave May 
1095d3a51819SDave May .seealso: DMSwarmRestoreField()
1096d3a51819SDave May @*/
109774d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmGetField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
1098b62e03f8SDave May {
1099b62e03f8SDave May   DM_Swarm         *swarm = (DM_Swarm*)dm->data;
110077048351SPatrick Sanan   DMSwarmDataField gfield;
11012eac95f8SDave May   PetscErrorCode ierr;
1102b62e03f8SDave May 
1103521f74f9SMatthew G. Knepley   PetscFunctionBegin;
11043454631fSDave May   if (!swarm->issetup) { ierr = DMSetUp(dm);CHKERRQ(ierr); }
110577048351SPatrick Sanan   ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
110677048351SPatrick Sanan   ierr = DMSwarmDataFieldGetAccess(gfield);CHKERRQ(ierr);
110777048351SPatrick Sanan   ierr = DMSwarmDataFieldGetEntries(gfield,data);CHKERRQ(ierr);
11081b1ea282SDave May   if (blocksize) {*blocksize = gfield->bs; }
1109b5bcf523SDave May   if (type) { *type = gfield->petsc_type; }
1110b62e03f8SDave May   PetscFunctionReturn(0);
1111b62e03f8SDave May }
1112b62e03f8SDave May 
1113d3a51819SDave May /*@C
1114d3a51819SDave May    DMSwarmRestoreField - Restore access to the underlying array storing all entries associated with a registered field
1115d3a51819SDave May 
1116d3a51819SDave May    Not collective
1117d3a51819SDave May 
1118d3a51819SDave May    Input parameters:
111962741f57SDave May +  dm - a DMSwarm
112062741f57SDave May -  fieldname - the textual name to identify this field
1121d3a51819SDave May 
1122d3a51819SDave May    Output parameters:
112362741f57SDave May +  blocksize - the number of each data type
1124d3a51819SDave May .  type - the data type
112562741f57SDave May -  data - pointer to raw array
1126d3a51819SDave May 
1127d3a51819SDave May    Level: beginner
1128d3a51819SDave May 
1129d3a51819SDave May    Notes:
11308b8a3813SDave May    The user must call DMSwarmGetField() prior to calling DMSwarmRestoreField().
1131d3a51819SDave May 
1132d3a51819SDave May .seealso: DMSwarmGetField()
1133d3a51819SDave May @*/
113474d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmRestoreField(DM dm,const char fieldname[],PetscInt *blocksize,PetscDataType *type,void **data)
1135b62e03f8SDave May {
1136b62e03f8SDave May   DM_Swarm         *swarm = (DM_Swarm*)dm->data;
113777048351SPatrick Sanan   DMSwarmDataField gfield;
11382eac95f8SDave May   PetscErrorCode ierr;
1139b62e03f8SDave May 
1140521f74f9SMatthew G. Knepley   PetscFunctionBegin;
114177048351SPatrick Sanan   ierr = DMSwarmDataBucketGetDMSwarmDataFieldByName(swarm->db,fieldname,&gfield);CHKERRQ(ierr);
114277048351SPatrick Sanan   ierr = DMSwarmDataFieldRestoreAccess(gfield);CHKERRQ(ierr);
1143b62e03f8SDave May   if (data) *data = NULL;
1144b62e03f8SDave May   PetscFunctionReturn(0);
1145b62e03f8SDave May }
1146b62e03f8SDave May 
114774d0cae8SMatthew G. Knepley /*@
1148d3a51819SDave May    DMSwarmAddPoint - Add space for one new point in the DMSwarm
1149d3a51819SDave May 
1150d3a51819SDave May    Not collective
1151d3a51819SDave May 
1152d3a51819SDave May    Input parameter:
1153d3a51819SDave May .  dm - a DMSwarm
1154d3a51819SDave May 
1155d3a51819SDave May    Level: beginner
1156d3a51819SDave May 
1157d3a51819SDave May    Notes:
11588b8a3813SDave May    The new point will have all fields initialized to zero.
1159d3a51819SDave May 
1160d3a51819SDave May .seealso: DMSwarmAddNPoints()
1161d3a51819SDave May @*/
116274d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmAddPoint(DM dm)
1163cb1d1399SDave May {
1164cb1d1399SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1165cb1d1399SDave May   PetscErrorCode ierr;
1166cb1d1399SDave May 
1167521f74f9SMatthew G. Knepley   PetscFunctionBegin;
11683454631fSDave May   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
1169f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
117077048351SPatrick Sanan   ierr = DMSwarmDataBucketAddPoint(swarm->db);CHKERRQ(ierr);
1171f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
1172cb1d1399SDave May   PetscFunctionReturn(0);
1173cb1d1399SDave May }
1174cb1d1399SDave May 
117574d0cae8SMatthew G. Knepley /*@
1176d3a51819SDave May    DMSwarmAddNPoints - Add space for a number of new points in the DMSwarm
1177d3a51819SDave May 
1178d3a51819SDave May    Not collective
1179d3a51819SDave May 
1180d3a51819SDave May    Input parameters:
118162741f57SDave May +  dm - a DMSwarm
118262741f57SDave May -  npoints - the number of new points to add
1183d3a51819SDave May 
1184d3a51819SDave May    Level: beginner
1185d3a51819SDave May 
1186d3a51819SDave May    Notes:
11878b8a3813SDave May    The new point will have all fields initialized to zero.
1188d3a51819SDave May 
1189d3a51819SDave May .seealso: DMSwarmAddPoint()
1190d3a51819SDave May @*/
119174d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmAddNPoints(DM dm,PetscInt npoints)
1192cb1d1399SDave May {
1193cb1d1399SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1194cb1d1399SDave May   PetscErrorCode ierr;
1195cb1d1399SDave May   PetscInt       nlocal;
1196cb1d1399SDave May 
1197521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1198f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
119977048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db,&nlocal,NULL,NULL);CHKERRQ(ierr);
1200cb1d1399SDave May   nlocal = nlocal + npoints;
120177048351SPatrick Sanan   ierr = DMSwarmDataBucketSetSizes(swarm->db,nlocal,DMSWARM_DATA_BUCKET_BUFFER_DEFAULT);CHKERRQ(ierr);
1202f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_AddPoints,0,0,0,0);CHKERRQ(ierr);
1203cb1d1399SDave May   PetscFunctionReturn(0);
1204cb1d1399SDave May }
1205cb1d1399SDave May 
120674d0cae8SMatthew G. Knepley /*@
1207d3a51819SDave May    DMSwarmRemovePoint - Remove the last point from the DMSwarm
1208d3a51819SDave May 
1209d3a51819SDave May    Not collective
1210d3a51819SDave May 
1211d3a51819SDave May    Input parameter:
1212d3a51819SDave May .  dm - a DMSwarm
1213d3a51819SDave May 
1214d3a51819SDave May    Level: beginner
1215d3a51819SDave May 
1216d3a51819SDave May .seealso: DMSwarmRemovePointAtIndex()
1217d3a51819SDave May @*/
121874d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmRemovePoint(DM dm)
1219cb1d1399SDave May {
1220cb1d1399SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1221cb1d1399SDave May   PetscErrorCode ierr;
1222cb1d1399SDave May 
1223521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1224f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
122577048351SPatrick Sanan   ierr = DMSwarmDataBucketRemovePoint(swarm->db);CHKERRQ(ierr);
1226f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
1227cb1d1399SDave May   PetscFunctionReturn(0);
1228cb1d1399SDave May }
1229cb1d1399SDave May 
123074d0cae8SMatthew G. Knepley /*@
1231d3a51819SDave May    DMSwarmRemovePointAtIndex - Removes a specific point from the DMSwarm
1232d3a51819SDave May 
1233d3a51819SDave May    Not collective
1234d3a51819SDave May 
1235d3a51819SDave May    Input parameters:
123662741f57SDave May +  dm - a DMSwarm
123762741f57SDave May -  idx - index of point to remove
1238d3a51819SDave May 
1239d3a51819SDave May    Level: beginner
1240d3a51819SDave May 
1241d3a51819SDave May .seealso: DMSwarmRemovePoint()
1242d3a51819SDave May @*/
124374d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmRemovePointAtIndex(DM dm,PetscInt idx)
1244cb1d1399SDave May {
1245cb1d1399SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1246cb1d1399SDave May   PetscErrorCode ierr;
1247cb1d1399SDave May 
1248521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1249f2b2bee7SDave May   ierr = PetscLogEventBegin(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
125077048351SPatrick Sanan   ierr = DMSwarmDataBucketRemovePointAtIndex(swarm->db,idx);CHKERRQ(ierr);
1251f2b2bee7SDave May   ierr = PetscLogEventEnd(DMSWARM_RemovePoints,0,0,0,0);CHKERRQ(ierr);
1252cb1d1399SDave May   PetscFunctionReturn(0);
1253cb1d1399SDave May }
1254b62e03f8SDave May 
125574d0cae8SMatthew G. Knepley /*@
1256ba4fc9c6SDave May    DMSwarmCopyPoint - Copy point pj to point pi in the DMSwarm
1257ba4fc9c6SDave May 
1258ba4fc9c6SDave May    Not collective
1259ba4fc9c6SDave May 
1260ba4fc9c6SDave May    Input parameters:
1261ba4fc9c6SDave May +  dm - a DMSwarm
1262ba4fc9c6SDave May .  pi - the index of the point to copy
1263ba4fc9c6SDave May -  pj - the point index where the copy should be located
1264ba4fc9c6SDave May 
1265ba4fc9c6SDave May  Level: beginner
1266ba4fc9c6SDave May 
1267ba4fc9c6SDave May .seealso: DMSwarmRemovePoint()
1268ba4fc9c6SDave May @*/
126974d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmCopyPoint(DM dm,PetscInt pi,PetscInt pj)
1270ba4fc9c6SDave May {
1271ba4fc9c6SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1272ba4fc9c6SDave May   PetscErrorCode ierr;
1273ba4fc9c6SDave May 
1274ba4fc9c6SDave May   PetscFunctionBegin;
1275ba4fc9c6SDave May   if (!swarm->issetup) {ierr = DMSetUp(dm);CHKERRQ(ierr);}
127677048351SPatrick Sanan   ierr = DMSwarmDataBucketCopyPoint(swarm->db,pi,swarm->db,pj);CHKERRQ(ierr);
1277ba4fc9c6SDave May   PetscFunctionReturn(0);
1278ba4fc9c6SDave May }
1279ba4fc9c6SDave May 
1280095059a4SDave May PetscErrorCode DMSwarmMigrate_Basic(DM dm,PetscBool remove_sent_points)
12813454631fSDave May {
1282dcf43ee8SDave May   PetscErrorCode ierr;
1283521f74f9SMatthew G. Knepley 
1284521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1285dcf43ee8SDave May   ierr = DMSwarmMigrate_Push_Basic(dm,remove_sent_points);CHKERRQ(ierr);
12863454631fSDave May   PetscFunctionReturn(0);
12873454631fSDave May }
12883454631fSDave May 
128974d0cae8SMatthew G. Knepley /*@
1290d3a51819SDave May    DMSwarmMigrate - Relocates points defined in the DMSwarm to other MPI-ranks
1291d3a51819SDave May 
1292d083f849SBarry Smith    Collective on dm
1293d3a51819SDave May 
1294d3a51819SDave May    Input parameters:
129562741f57SDave May +  dm - the DMSwarm
129662741f57SDave May -  remove_sent_points - flag indicating if sent points should be removed from the current MPI-rank
1297d3a51819SDave May 
1298d3a51819SDave May    Notes:
1299a5b23f4aSJose E. Roman    The DM will be modified to accommodate received points.
13008b8a3813SDave May    If remove_sent_points = PETSC_TRUE, any points that were sent will be removed from the DM.
13018b8a3813SDave May    Different styles of migration are supported. See DMSwarmSetMigrateType().
1302d3a51819SDave May 
1303d3a51819SDave May    Level: advanced
1304d3a51819SDave May 
1305d3a51819SDave May .seealso: DMSwarmSetMigrateType()
1306d3a51819SDave May @*/
130774d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmMigrate(DM dm,PetscBool remove_sent_points)
13083454631fSDave May {
1309f0cdbbbaSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
13103454631fSDave May   PetscErrorCode ierr;
1311f0cdbbbaSDave May 
1312521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1313ed923d71SDave May   ierr = PetscLogEventBegin(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
1314f0cdbbbaSDave May   switch (swarm->migrate_type) {
1315f0cdbbbaSDave May     case DMSWARM_MIGRATE_BASIC:
1316095059a4SDave May       ierr = DMSwarmMigrate_Basic(dm,remove_sent_points);CHKERRQ(ierr);
1317f0cdbbbaSDave May       break;
1318f0cdbbbaSDave May     case DMSWARM_MIGRATE_DMCELLNSCATTER:
1319f0cdbbbaSDave May       ierr = DMSwarmMigrate_CellDMScatter(dm,remove_sent_points);CHKERRQ(ierr);
1320f0cdbbbaSDave May       break;
1321f0cdbbbaSDave May     case DMSWARM_MIGRATE_DMCELLEXACT:
1322f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_DMCELLEXACT not implemented");
1323f0cdbbbaSDave May     case DMSWARM_MIGRATE_USER:
1324f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE_USER not implemented");
1325f0cdbbbaSDave May     default:
1326f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_MIGRATE type unknown");
1327f0cdbbbaSDave May   }
1328ed923d71SDave May   ierr = PetscLogEventEnd(DMSWARM_Migrate,0,0,0,0);CHKERRQ(ierr);
1329183d2d45SMatthew G. Knepley   ierr = DMClearGlobalVectors(dm);CHKERRQ(ierr);
13303454631fSDave May   PetscFunctionReturn(0);
13313454631fSDave May }
13323454631fSDave May 
1333f0cdbbbaSDave May PetscErrorCode DMSwarmMigrate_GlobalToLocal_Basic(DM dm,PetscInt *globalsize);
1334f0cdbbbaSDave May 
1335d3a51819SDave May /*
1336d3a51819SDave May  DMSwarmCollectViewCreate
1337d3a51819SDave May 
1338d3a51819SDave May  * Applies a collection method and gathers point neighbour points into dm
1339d3a51819SDave May 
1340d3a51819SDave May  Notes:
13418b8a3813SDave May  Users should call DMSwarmCollectViewDestroy() after
1342d3a51819SDave May  they have finished computations associated with the collected points
1343d3a51819SDave May */
1344d3a51819SDave May 
134574d0cae8SMatthew G. Knepley /*@
1346d3a51819SDave May    DMSwarmCollectViewCreate - Applies a collection method and gathers points
1347d3a51819SDave May    in neighbour MPI-ranks into the DMSwarm
1348d3a51819SDave May 
1349d083f849SBarry Smith    Collective on dm
1350d3a51819SDave May 
1351d3a51819SDave May    Input parameter:
1352d3a51819SDave May .  dm - the DMSwarm
1353d3a51819SDave May 
1354d3a51819SDave May    Notes:
1355d3a51819SDave May    Users should call DMSwarmCollectViewDestroy() after
1356d3a51819SDave May    they have finished computations associated with the collected points
13578b8a3813SDave May    Different collect methods are supported. See DMSwarmSetCollectType().
1358d3a51819SDave May 
1359d3a51819SDave May    Level: advanced
1360d3a51819SDave May 
1361d3a51819SDave May .seealso: DMSwarmCollectViewDestroy(), DMSwarmSetCollectType()
1362d3a51819SDave May @*/
136374d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmCollectViewCreate(DM dm)
13642712d1f2SDave May {
13652712d1f2SDave May   PetscErrorCode ierr;
13662712d1f2SDave May   DM_Swarm *swarm = (DM_Swarm*)dm->data;
13672712d1f2SDave May   PetscInt ng;
13682712d1f2SDave May 
1369521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1370480eef7bSDave May   if (swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView currently active");
1371480eef7bSDave May   ierr = DMSwarmGetLocalSize(dm,&ng);CHKERRQ(ierr);
1372480eef7bSDave May   switch (swarm->collect_type) {
1373f0cdbbbaSDave May 
1374480eef7bSDave May     case DMSWARM_COLLECT_BASIC:
13752712d1f2SDave May       ierr = DMSwarmMigrate_GlobalToLocal_Basic(dm,&ng);CHKERRQ(ierr);
1376480eef7bSDave May       break;
1377480eef7bSDave May     case DMSWARM_COLLECT_DMDABOUNDINGBOX:
1378f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_DMDABOUNDINGBOX not implemented");
1379480eef7bSDave May     case DMSWARM_COLLECT_GENERAL:
1380f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT_GENERAL not implemented");
1381480eef7bSDave May     default:
1382f0cdbbbaSDave May       SETERRQ(PETSC_COMM_WORLD,PETSC_ERR_SUP,"DMSWARM_COLLECT type unknown");
1383480eef7bSDave May   }
1384480eef7bSDave May   swarm->collect_view_active = PETSC_TRUE;
1385480eef7bSDave May   swarm->collect_view_reset_nlocal = ng;
13862712d1f2SDave May   PetscFunctionReturn(0);
13872712d1f2SDave May }
13882712d1f2SDave May 
138974d0cae8SMatthew G. Knepley /*@
1390d3a51819SDave May    DMSwarmCollectViewDestroy - Resets the DMSwarm to the size prior to calling DMSwarmCollectViewCreate()
1391d3a51819SDave May 
1392d083f849SBarry Smith    Collective on dm
1393d3a51819SDave May 
1394d3a51819SDave May    Input parameters:
1395d3a51819SDave May .  dm - the DMSwarm
1396d3a51819SDave May 
1397d3a51819SDave May    Notes:
1398d3a51819SDave May    Users should call DMSwarmCollectViewCreate() before this function is called.
1399d3a51819SDave May 
1400d3a51819SDave May    Level: advanced
1401d3a51819SDave May 
1402d3a51819SDave May .seealso: DMSwarmCollectViewCreate(), DMSwarmSetCollectType()
1403d3a51819SDave May @*/
140474d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmCollectViewDestroy(DM dm)
14052712d1f2SDave May {
14062712d1f2SDave May   PetscErrorCode ierr;
14072712d1f2SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
14082712d1f2SDave May 
1409521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1410480eef7bSDave May   if (!swarm->collect_view_active) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"CollectView is currently not active");
1411480eef7bSDave May   ierr = DMSwarmSetLocalSizes(dm,swarm->collect_view_reset_nlocal,-1);CHKERRQ(ierr);
1412480eef7bSDave May   swarm->collect_view_active = PETSC_FALSE;
14132712d1f2SDave May   PetscFunctionReturn(0);
14142712d1f2SDave May }
14153454631fSDave May 
1416f0cdbbbaSDave May PetscErrorCode DMSwarmSetUpPIC(DM dm)
1417f0cdbbbaSDave May {
1418f0cdbbbaSDave May   PetscInt       dim;
1419f0cdbbbaSDave May   PetscErrorCode ierr;
1420f0cdbbbaSDave May 
1421521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1422f0cdbbbaSDave May   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
1423f0cdbbbaSDave May   if (dim < 1) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
1424f0cdbbbaSDave May   if (dim > 3) SETERRQ1(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Dimension must be 1,2,3 - found %D",dim);
1425f0cdbbbaSDave May   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_coor,dim,PETSC_DOUBLE);CHKERRQ(ierr);
1426e2d107dbSDave May   ierr = DMSwarmRegisterPetscDatatypeField(dm,DMSwarmPICField_cellid,1,PETSC_INT);CHKERRQ(ierr);
1427f0cdbbbaSDave May   PetscFunctionReturn(0);
1428f0cdbbbaSDave May }
1429f0cdbbbaSDave May 
143074d0cae8SMatthew G. Knepley /*@
143131403186SMatthew G. Knepley   DMSwarmSetPointCoordinatesRandom - Sets initial coordinates for particles in each cell
143231403186SMatthew G. Knepley 
143331403186SMatthew G. Knepley   Collective on dm
143431403186SMatthew G. Knepley 
143531403186SMatthew G. Knepley   Input parameters:
143631403186SMatthew G. Knepley + dm  - the DMSwarm
143731403186SMatthew G. Knepley - Npc - The number of particles per cell in the cell DM
143831403186SMatthew G. Knepley 
143931403186SMatthew G. Knepley   Notes:
144031403186SMatthew G. Knepley   The user must use DMSwarmSetCellDM() to set the cell DM first. The particles are placed randomly inside each cell. If only
144131403186SMatthew G. Knepley   one particle is in each cell, it is placed at the centroid.
144231403186SMatthew G. Knepley 
144331403186SMatthew G. Knepley   Level: intermediate
144431403186SMatthew G. Knepley 
144531403186SMatthew G. Knepley .seealso: DMSwarmSetCellDM()
144631403186SMatthew G. Knepley @*/
144731403186SMatthew G. Knepley PetscErrorCode DMSwarmSetPointCoordinatesRandom(DM dm, PetscInt Npc)
144831403186SMatthew G. Knepley {
144931403186SMatthew G. Knepley   DM             cdm;
145031403186SMatthew G. Knepley   PetscRandom    rnd;
145131403186SMatthew G. Knepley   DMPolytopeType ct;
145231403186SMatthew G. Knepley   PetscBool      simplex;
145331403186SMatthew G. Knepley   PetscReal     *centroid, *coords, *xi0, *v0, *J, *invJ, detJ;
145431403186SMatthew G. Knepley   PetscInt       dim, d, cStart, cEnd, c, p;
145531403186SMatthew G. Knepley   PetscErrorCode ierr;
145631403186SMatthew G. Knepley 
145731403186SMatthew G. Knepley   PetscFunctionBeginUser;
145831403186SMatthew G. Knepley   ierr = PetscRandomCreate(PetscObjectComm((PetscObject) dm), &rnd);CHKERRQ(ierr);
145931403186SMatthew G. Knepley   ierr = PetscRandomSetInterval(rnd, -1.0, 1.0);CHKERRQ(ierr);
146031403186SMatthew G. Knepley   ierr = PetscRandomSetType(rnd, PETSCRAND48);CHKERRQ(ierr);
146131403186SMatthew G. Knepley 
146231403186SMatthew G. Knepley   ierr = DMSwarmGetCellDM(dm, &cdm);CHKERRQ(ierr);
146331403186SMatthew G. Knepley   ierr = DMGetDimension(cdm, &dim);CHKERRQ(ierr);
146431403186SMatthew G. Knepley   ierr = DMPlexGetHeightStratum(cdm, 0, &cStart, &cEnd);CHKERRQ(ierr);
146531403186SMatthew G. Knepley   ierr = DMPlexGetCellType(cdm, cStart, &ct);CHKERRQ(ierr);
146631403186SMatthew G. Knepley   simplex = DMPolytopeTypeGetNumVertices(ct) == DMPolytopeTypeGetDim(ct)+1 ? PETSC_TRUE : PETSC_FALSE;
146731403186SMatthew G. Knepley 
146831403186SMatthew G. Knepley   ierr = PetscMalloc5(dim, &centroid, dim, &xi0, dim, &v0, dim*dim, &J, dim*dim, &invJ);CHKERRQ(ierr);
146931403186SMatthew G. Knepley   for (d = 0; d < dim; ++d) xi0[d] = -1.0;
147031403186SMatthew G. Knepley   ierr = DMSwarmGetField(dm, DMSwarmPICField_coor, NULL, NULL, (void **) &coords);CHKERRQ(ierr);
147131403186SMatthew G. Knepley   for (c = cStart; c < cEnd; ++c) {
147231403186SMatthew G. Knepley     if (Npc == 1) {
147331403186SMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFVM(cdm, c, NULL, centroid, NULL);CHKERRQ(ierr);
147431403186SMatthew G. Knepley       for (d = 0; d < dim; ++d) coords[c*dim+d] = centroid[d];
147531403186SMatthew G. Knepley     } else {
147631403186SMatthew G. Knepley       ierr = DMPlexComputeCellGeometryFEM(cdm, c, NULL, v0, J, invJ, &detJ);CHKERRQ(ierr); /* affine */
147731403186SMatthew G. Knepley       for (p = 0; p < Npc; ++p) {
147831403186SMatthew G. Knepley         const PetscInt n   = c*Npc + p;
147931403186SMatthew G. Knepley         PetscReal      sum = 0.0, refcoords[3];
148031403186SMatthew G. Knepley 
148131403186SMatthew G. Knepley         for (d = 0; d < dim; ++d) {
148231403186SMatthew G. Knepley           ierr = PetscRandomGetValueReal(rnd, &refcoords[d]);CHKERRQ(ierr);
148331403186SMatthew G. Knepley           sum += refcoords[d];
148431403186SMatthew G. Knepley         }
148531403186SMatthew G. Knepley         if (simplex && sum > 0.0) for (d = 0; d < dim; ++d) refcoords[d] -= PetscSqrtReal(dim)*sum;
148631403186SMatthew G. Knepley         CoordinatesRefToReal(dim, dim, xi0, v0, J, refcoords, &coords[n*dim]);
148731403186SMatthew G. Knepley       }
148831403186SMatthew G. Knepley     }
148931403186SMatthew G. Knepley   }
149031403186SMatthew G. Knepley   ierr = DMSwarmRestoreField(dm, DMSwarmPICField_coor, NULL, NULL, (void **) &coords);CHKERRQ(ierr);
149131403186SMatthew G. Knepley   ierr = PetscFree5(centroid, xi0, v0, J, invJ);CHKERRQ(ierr);
149231403186SMatthew G. Knepley   ierr = PetscRandomDestroy(&rnd);CHKERRQ(ierr);
149331403186SMatthew G. Knepley   PetscFunctionReturn(0);
149431403186SMatthew G. Knepley }
149531403186SMatthew G. Knepley 
149631403186SMatthew G. Knepley /*@
1497d3a51819SDave May    DMSwarmSetType - Set particular flavor of DMSwarm
1498d3a51819SDave May 
1499d083f849SBarry Smith    Collective on dm
1500d3a51819SDave May 
1501d3a51819SDave May    Input parameters:
150262741f57SDave May +  dm - the DMSwarm
150362741f57SDave May -  stype - the DMSwarm type (e.g. DMSWARM_PIC)
1504d3a51819SDave May 
1505d3a51819SDave May    Level: advanced
1506d3a51819SDave May 
1507d3a51819SDave May .seealso: DMSwarmSetMigrateType(), DMSwarmSetCollectType()
1508d3a51819SDave May @*/
150974d0cae8SMatthew G. Knepley PetscErrorCode DMSwarmSetType(DM dm,DMSwarmType stype)
1510f0cdbbbaSDave May {
1511f0cdbbbaSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1512f0cdbbbaSDave May   PetscErrorCode ierr;
1513f0cdbbbaSDave May 
1514521f74f9SMatthew G. Knepley   PetscFunctionBegin;
1515f0cdbbbaSDave May   swarm->swarm_type = stype;
1516f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
1517f0cdbbbaSDave May     ierr = DMSwarmSetUpPIC(dm);CHKERRQ(ierr);
1518f0cdbbbaSDave May   }
1519f0cdbbbaSDave May   PetscFunctionReturn(0);
1520f0cdbbbaSDave May }
1521f0cdbbbaSDave May 
15223454631fSDave May PetscErrorCode DMSetup_Swarm(DM dm)
15233454631fSDave May {
15243454631fSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
15253454631fSDave May   PetscErrorCode ierr;
15263454631fSDave May   PetscMPIInt    rank;
15273454631fSDave May   PetscInt       p,npoints,*rankval;
15283454631fSDave May 
1529521f74f9SMatthew G. Knepley   PetscFunctionBegin;
15303454631fSDave May   if (swarm->issetup) PetscFunctionReturn(0);
15313454631fSDave May 
15323454631fSDave May   swarm->issetup = PETSC_TRUE;
15333454631fSDave May 
1534f0cdbbbaSDave May   if (swarm->swarm_type == DMSWARM_PIC) {
1535f0cdbbbaSDave May     /* check dmcell exists */
1536f0cdbbbaSDave May     if (!swarm->dmcell) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires you call DMSwarmSetCellDM");
1537f0cdbbbaSDave May 
1538f0cdbbbaSDave May     if (swarm->dmcell->ops->locatepointssubdomain) {
1539f0cdbbbaSDave May       /* check methods exists for exact ownership identificiation */
154077b6ec44SMatthew G. Knepley       ierr = PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->ops->LocatePointsSubdomain\n");CHKERRQ(ierr);
1541f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLEXACT;
1542f0cdbbbaSDave May     } else {
1543f0cdbbbaSDave May       /* check methods exist for point location AND rank neighbor identification */
1544f0cdbbbaSDave May       if (swarm->dmcell->ops->locatepoints) {
154577b6ec44SMatthew G. Knepley         ierr = PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->LocatePoints\n");CHKERRQ(ierr);
1546f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->locatepoints be defined");
1547f0cdbbbaSDave May 
1548f0cdbbbaSDave May       if (swarm->dmcell->ops->getneighbors) {
154977b6ec44SMatthew G. Knepley         ierr = PetscInfo(dm, "DMSWARM_PIC: Using method CellDM->GetNeigbors\n");CHKERRQ(ierr);
1550f0cdbbbaSDave May       } else SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"DMSWARM_PIC requires the method CellDM->ops->getneighbors be defined");
1551f0cdbbbaSDave May 
1552f0cdbbbaSDave May       swarm->migrate_type = DMSWARM_MIGRATE_DMCELLNSCATTER;
1553f0cdbbbaSDave May     }
1554f0cdbbbaSDave May   }
1555f0cdbbbaSDave May 
1556f0cdbbbaSDave May   ierr = DMSwarmFinalizeFieldRegister(dm);CHKERRQ(ierr);
1557f0cdbbbaSDave May 
15583454631fSDave May   /* check some fields were registered */
15593454631fSDave May   if (swarm->db->nfields <= 2) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"At least one field user must be registered via DMSwarmRegisterXXX()");
15603454631fSDave May 
15613454631fSDave May   /* check local sizes were set */
15623454631fSDave May   if (swarm->db->L == -1) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_USER,"Local sizes must be set via DMSwarmSetLocalSizes()");
15633454631fSDave May 
15643454631fSDave May   /* initialize values in pid and rank placeholders */
15653454631fSDave May   /* TODO: [pid - use MPI_Scan] */
1566ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRMPI(ierr);
156777048351SPatrick Sanan   ierr = DMSwarmDataBucketGetSizes(swarm->db,&npoints,NULL,NULL);CHKERRQ(ierr);
1568f0cdbbbaSDave May   ierr = DMSwarmGetField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
15693454631fSDave May   for (p=0; p<npoints; p++) {
15703454631fSDave May     rankval[p] = (PetscInt)rank;
15713454631fSDave May   }
1572f0cdbbbaSDave May   ierr = DMSwarmRestoreField(dm,DMSwarmField_rank,NULL,NULL,(void**)&rankval);CHKERRQ(ierr);
15733454631fSDave May   PetscFunctionReturn(0);
15743454631fSDave May }
15753454631fSDave May 
1576dc5f5ce9SDave May extern PetscErrorCode DMSwarmSortDestroy(DMSwarmSort *_ctx);
1577dc5f5ce9SDave May 
157857795646SDave May PetscErrorCode DMDestroy_Swarm(DM dm)
157957795646SDave May {
158057795646SDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
158157795646SDave May   PetscErrorCode ierr;
158257795646SDave May 
158357795646SDave May   PetscFunctionBegin;
1584d0c080abSJoseph Pusztay   if (--swarm->refct > 0) PetscFunctionReturn(0);
158577048351SPatrick Sanan   ierr = DMSwarmDataBucketDestroy(&swarm->db);CHKERRQ(ierr);
1586dc5f5ce9SDave May   if (swarm->sort_context) {
1587dc5f5ce9SDave May     ierr = DMSwarmSortDestroy(&swarm->sort_context);CHKERRQ(ierr);
1588dc5f5ce9SDave May   }
158957795646SDave May   ierr = PetscFree(swarm);CHKERRQ(ierr);
159057795646SDave May   PetscFunctionReturn(0);
159157795646SDave May }
159257795646SDave May 
1593a9ee3421SMatthew G. Knepley PetscErrorCode DMSwarmView_Draw(DM dm, PetscViewer viewer)
1594a9ee3421SMatthew G. Knepley {
1595a9ee3421SMatthew G. Knepley   DM             cdm;
1596a9ee3421SMatthew G. Knepley   PetscDraw      draw;
159731403186SMatthew G. Knepley   PetscReal     *coords, oldPause, radius = 0.01;
1598a9ee3421SMatthew G. Knepley   PetscInt       Np, p, bs;
1599a9ee3421SMatthew G. Knepley   PetscErrorCode ierr;
1600a9ee3421SMatthew G. Knepley 
1601a9ee3421SMatthew G. Knepley   PetscFunctionBegin;
160231403186SMatthew G. Knepley   ierr = PetscOptionsGetReal(NULL, ((PetscObject) dm)->prefix, "-dm_view_swarm_radius", &radius, NULL);CHKERRQ(ierr);
1603a9ee3421SMatthew G. Knepley   ierr = PetscViewerDrawGetDraw(viewer, 0, &draw);CHKERRQ(ierr);
1604a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetCellDM(dm, &cdm);CHKERRQ(ierr);
1605a9ee3421SMatthew G. Knepley   ierr = PetscDrawGetPause(draw, &oldPause);CHKERRQ(ierr);
1606a9ee3421SMatthew G. Knepley   ierr = PetscDrawSetPause(draw, 0.0);CHKERRQ(ierr);
1607a9ee3421SMatthew G. Knepley   ierr = DMView(cdm, viewer);CHKERRQ(ierr);
1608a9ee3421SMatthew G. Knepley   ierr = PetscDrawSetPause(draw, oldPause);CHKERRQ(ierr);
1609a9ee3421SMatthew G. Knepley 
1610a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetLocalSize(dm, &Np);CHKERRQ(ierr);
1611a9ee3421SMatthew G. Knepley   ierr = DMSwarmGetField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1612a9ee3421SMatthew G. Knepley   for (p = 0; p < Np; ++p) {
1613a9ee3421SMatthew G. Knepley     const PetscInt i = p*bs;
1614a9ee3421SMatthew G. Knepley 
161531403186SMatthew G. Knepley     ierr = PetscDrawEllipse(draw, coords[i], coords[i+1], radius, radius, PETSC_DRAW_BLUE);CHKERRQ(ierr);
1616a9ee3421SMatthew G. Knepley   }
1617a9ee3421SMatthew G. Knepley   ierr = DMSwarmRestoreField(dm, DMSwarmPICField_coor, &bs, NULL, (void **) &coords);CHKERRQ(ierr);
1618a9ee3421SMatthew G. Knepley   ierr = PetscDrawFlush(draw);CHKERRQ(ierr);
1619a9ee3421SMatthew G. Knepley   ierr = PetscDrawPause(draw);CHKERRQ(ierr);
1620a9ee3421SMatthew G. Knepley   ierr = PetscDrawSave(draw);CHKERRQ(ierr);
1621a9ee3421SMatthew G. Knepley   PetscFunctionReturn(0);
1622a9ee3421SMatthew G. Knepley }
1623a9ee3421SMatthew G. Knepley 
16245f50eb2eSDave May PetscErrorCode DMView_Swarm(DM dm, PetscViewer viewer)
16255f50eb2eSDave May {
16265f50eb2eSDave May   DM_Swarm       *swarm = (DM_Swarm*)dm->data;
1627a9ee3421SMatthew G. Knepley   PetscBool      iascii,ibinary,ishdf5,isvtk,isdraw;
16285f50eb2eSDave May   PetscErrorCode ierr;
16295f50eb2eSDave May 
16305f50eb2eSDave May   PetscFunctionBegin;
16315f50eb2eSDave May   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
16325f50eb2eSDave May   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,2);
16335f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
16345f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERBINARY,&ibinary);CHKERRQ(ierr);
16355f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERVTK,   &isvtk);CHKERRQ(ierr);
16365f50eb2eSDave May   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERHDF5,  &ishdf5);CHKERRQ(ierr);
1637a9ee3421SMatthew G. Knepley   ierr = PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW,  &isdraw);CHKERRQ(ierr);
16385f50eb2eSDave May   if (iascii) {
163977048351SPatrick Sanan     ierr = DMSwarmDataBucketView(PetscObjectComm((PetscObject)dm),swarm->db,NULL,DATABUCKET_VIEW_STDOUT);CHKERRQ(ierr);
1640298827fbSBarry Smith   } else if (ibinary) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO Binary support");
16415f50eb2eSDave May #if defined(PETSC_HAVE_HDF5)
164274d0cae8SMatthew G. Knepley   else if (ishdf5) {
164374d0cae8SMatthew G. Knepley     ierr = DMSwarmView_HDF5(dm, viewer);CHKERRQ(ierr);
164474d0cae8SMatthew G. Knepley   }
16455f50eb2eSDave May #else
1646298827fbSBarry Smith   else if (ishdf5) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"HDF5 not supported. Please reconfigure using --download-hdf5");
16475f50eb2eSDave May #endif
1648298827fbSBarry Smith   else if (isvtk) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"NO VTK support");
1649298827fbSBarry Smith   else if (isdraw) {
1650a9ee3421SMatthew G. Knepley     ierr = DMSwarmView_Draw(dm, viewer);CHKERRQ(ierr);
16515f50eb2eSDave May   }
16525f50eb2eSDave May   PetscFunctionReturn(0);
16535f50eb2eSDave May }
16545f50eb2eSDave May 
1655d0c080abSJoseph Pusztay /*@C
1656d0c080abSJoseph Pusztay    DMSwarmGetCellSwarm - Extracts a single cell from the DMSwarm object, returns it as a single cell DMSwarm.
1657d0c080abSJoseph 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.
1658d0c080abSJoseph Pusztay 
1659d0c080abSJoseph Pusztay    Important: Changes to this cell of the swarm will be lost if they are made prior to restoring this cell.
1660d0c080abSJoseph Pusztay 
1661d0c080abSJoseph Pusztay    Noncollective
1662d0c080abSJoseph Pusztay 
1663d0c080abSJoseph Pusztay    Input parameters:
1664d0c080abSJoseph Pusztay +  sw - the DMSwarm
1665d0c080abSJoseph Pusztay -  cellID - the integer id of the cell to be extracted and filtered
1666d0c080abSJoseph Pusztay 
1667d0c080abSJoseph Pusztay    Output parameters:
1668d0c080abSJoseph Pusztay .  cellswarm - The new DMSwarm
1669d0c080abSJoseph Pusztay 
1670d0c080abSJoseph Pusztay    Level: beginner
1671d0c080abSJoseph Pusztay 
1672d0c080abSJoseph Pusztay    Note: This presently only supports DMSWARM_PIC type
1673d0c080abSJoseph Pusztay 
1674d0c080abSJoseph Pusztay .seealso: DMSwarmRestoreCellSwarm()
1675d0c080abSJoseph Pusztay @*/
1676d0c080abSJoseph Pusztay PETSC_EXTERN PetscErrorCode DMSwarmGetCellSwarm(DM sw, PetscInt cellID, DM cellswarm)
1677d0c080abSJoseph Pusztay {
1678d0c080abSJoseph Pusztay   DM_Swarm      *original = (DM_Swarm*) sw->data;
1679d0c080abSJoseph Pusztay   DMLabel        label;
1680d0c080abSJoseph Pusztay   DM             dmc, subdmc;
1681d0c080abSJoseph Pusztay   PetscInt      *pids, particles, dim;
1682d0c080abSJoseph Pusztay   PetscErrorCode ierr;
1683d0c080abSJoseph Pusztay 
1684d0c080abSJoseph Pusztay   PetscFunctionBegin;
1685d0c080abSJoseph Pusztay   /* Configure new swarm */
1686d0c080abSJoseph Pusztay   ierr = DMSetType(cellswarm, DMSWARM);CHKERRQ(ierr);
1687d0c080abSJoseph Pusztay   ierr = DMGetDimension(sw, &dim);CHKERRQ(ierr);
1688d0c080abSJoseph Pusztay   ierr = DMSetDimension(cellswarm, dim);CHKERRQ(ierr);
1689d0c080abSJoseph Pusztay   ierr = DMSwarmSetType(cellswarm, DMSWARM_PIC);CHKERRQ(ierr);
1690d0c080abSJoseph Pusztay   /* Destroy the unused, unconfigured data bucket to prevent stragglers in memory */
16911e1ea65dSPierre Jolivet   ierr = DMSwarmDataBucketDestroy(&((DM_Swarm*)cellswarm->data)->db);CHKERRQ(ierr);
1692d0c080abSJoseph Pusztay   ierr = DMSwarmSortGetAccess(sw);CHKERRQ(ierr);
1693d0c080abSJoseph Pusztay   ierr = DMSwarmSortGetNumberOfPointsPerCell(sw, cellID, &particles);CHKERRQ(ierr);
1694d0c080abSJoseph Pusztay   ierr = DMSwarmSortGetPointsPerCell(sw, cellID, &particles, &pids);CHKERRQ(ierr);
16951e1ea65dSPierre Jolivet   ierr = DMSwarmDataBucketCreateFromSubset(original->db, particles, pids, &((DM_Swarm*)cellswarm->data)->db);CHKERRQ(ierr);
1696d0c080abSJoseph Pusztay   ierr = DMSwarmSortRestoreAccess(sw);CHKERRQ(ierr);
1697d0c080abSJoseph Pusztay   ierr = PetscFree(pids);CHKERRQ(ierr);
1698d0c080abSJoseph Pusztay   ierr = DMSwarmGetCellDM(sw, &dmc);CHKERRQ(ierr);
1699d0c080abSJoseph Pusztay   ierr = DMLabelCreate(PetscObjectComm((PetscObject)sw), "singlecell", &label);CHKERRQ(ierr);
1700d0c080abSJoseph Pusztay   ierr = DMAddLabel(dmc, label);CHKERRQ(ierr);
1701d0c080abSJoseph Pusztay   ierr = DMLabelSetValue(label, cellID, 1);CHKERRQ(ierr);
1702d0c080abSJoseph Pusztay   ierr = DMPlexFilter(dmc, label, 1, &subdmc);CHKERRQ(ierr);
17031e1ea65dSPierre Jolivet   ierr = DMSwarmSetCellDM(cellswarm, subdmc);CHKERRQ(ierr);
17041e1ea65dSPierre Jolivet   ierr = DMLabelDestroy(&label);CHKERRQ(ierr);
1705d0c080abSJoseph Pusztay   PetscFunctionReturn(0);
1706d0c080abSJoseph Pusztay }
1707d0c080abSJoseph Pusztay 
1708d0c080abSJoseph Pusztay /*@C
1709d0c080abSJoseph Pusztay    DMSwarmRestoreCellSwarm - Restores a DMSwarm object obtained with DMSwarmGetCellSwarm. All fields are copied back into the parent swarm.
1710d0c080abSJoseph Pusztay 
1711d0c080abSJoseph Pusztay    Noncollective
1712d0c080abSJoseph Pusztay 
1713d0c080abSJoseph Pusztay    Input parameters:
1714d0c080abSJoseph Pusztay +  sw - the parent DMSwarm
1715d0c080abSJoseph Pusztay .  cellID - the integer id of the cell to be copied back into the parent swarm
1716d0c080abSJoseph Pusztay -  cellswarm - the cell swarm object
1717d0c080abSJoseph Pusztay 
1718d0c080abSJoseph Pusztay    Level: beginner
1719d0c080abSJoseph Pusztay 
1720d0c080abSJoseph Pusztay    Note: This only supports DMSWARM_PIC types of DMSwarms
1721d0c080abSJoseph Pusztay 
1722d0c080abSJoseph Pusztay .seealso: DMSwarmGetCellSwarm()
1723d0c080abSJoseph Pusztay @*/
1724d0c080abSJoseph Pusztay PETSC_EXTERN PetscErrorCode DMSwarmRestoreCellSwarm(DM sw, PetscInt cellID, DM cellswarm)
1725d0c080abSJoseph Pusztay {
1726d0c080abSJoseph Pusztay   DM                dmc;
1727d0c080abSJoseph Pusztay   PetscInt         *pids, particles, p;
1728d0c080abSJoseph Pusztay   PetscErrorCode    ierr;
1729d0c080abSJoseph Pusztay 
1730d0c080abSJoseph Pusztay   PetscFunctionBegin;
1731d0c080abSJoseph Pusztay   ierr = DMSwarmSortGetAccess(sw);CHKERRQ(ierr);
1732d0c080abSJoseph Pusztay   ierr = DMSwarmSortGetPointsPerCell(sw, cellID, &particles, &pids);CHKERRQ(ierr);
1733d0c080abSJoseph Pusztay   ierr = DMSwarmSortRestoreAccess(sw);CHKERRQ(ierr);
1734d0c080abSJoseph Pusztay   /* Pointwise copy of each particle based on pid. The parent swarm may not be altered during this process. */
1735d0c080abSJoseph Pusztay   for (p=0; p<particles; ++p) {
1736d0c080abSJoseph Pusztay     ierr = DMSwarmDataBucketCopyPoint(((DM_Swarm*)cellswarm->data)->db,pids[p],((DM_Swarm*)sw->data)->db,pids[p]);CHKERRQ(ierr);
1737d0c080abSJoseph Pusztay   }
1738d0c080abSJoseph Pusztay   /* Free memory, destroy cell dm */
17391e1ea65dSPierre Jolivet   ierr = DMSwarmGetCellDM(cellswarm, &dmc);CHKERRQ(ierr);
17401e1ea65dSPierre Jolivet   ierr = DMDestroy(&dmc);CHKERRQ(ierr);
1741d0c080abSJoseph Pusztay   ierr = PetscFree(pids);CHKERRQ(ierr);
1742d0c080abSJoseph Pusztay   PetscFunctionReturn(0);
1743d0c080abSJoseph Pusztay }
1744d0c080abSJoseph Pusztay 
1745d0c080abSJoseph Pusztay PETSC_INTERN PetscErrorCode DMClone_Swarm(DM, DM *);
1746d0c080abSJoseph Pusztay 
1747d0c080abSJoseph Pusztay static PetscErrorCode DMInitialize_Swarm(DM sw)
1748d0c080abSJoseph Pusztay {
1749d0c080abSJoseph Pusztay   PetscFunctionBegin;
1750d0c080abSJoseph Pusztay   sw->dim  = 0;
1751d0c080abSJoseph Pusztay   sw->ops->view                            = DMView_Swarm;
1752d0c080abSJoseph Pusztay   sw->ops->load                            = NULL;
1753d0c080abSJoseph Pusztay   sw->ops->setfromoptions                  = NULL;
1754d0c080abSJoseph Pusztay   sw->ops->clone                           = DMClone_Swarm;
1755d0c080abSJoseph Pusztay   sw->ops->setup                           = DMSetup_Swarm;
1756d0c080abSJoseph Pusztay   sw->ops->createlocalsection              = NULL;
1757d0c080abSJoseph Pusztay   sw->ops->createdefaultconstraints        = NULL;
1758d0c080abSJoseph Pusztay   sw->ops->createglobalvector              = DMCreateGlobalVector_Swarm;
1759d0c080abSJoseph Pusztay   sw->ops->createlocalvector               = DMCreateLocalVector_Swarm;
1760d0c080abSJoseph Pusztay   sw->ops->getlocaltoglobalmapping         = NULL;
1761d0c080abSJoseph Pusztay   sw->ops->createfieldis                   = NULL;
1762d0c080abSJoseph Pusztay   sw->ops->createcoordinatedm              = NULL;
1763d0c080abSJoseph Pusztay   sw->ops->getcoloring                     = NULL;
1764d0c080abSJoseph Pusztay   sw->ops->creatematrix                    = DMCreateMatrix_Swarm;
1765d0c080abSJoseph Pusztay   sw->ops->createinterpolation             = NULL;
1766d0c080abSJoseph Pusztay   sw->ops->createinjection                 = NULL;
1767d0c080abSJoseph Pusztay   sw->ops->createmassmatrix                = DMCreateMassMatrix_Swarm;
1768d0c080abSJoseph Pusztay   sw->ops->refine                          = NULL;
1769d0c080abSJoseph Pusztay   sw->ops->coarsen                         = NULL;
1770d0c080abSJoseph Pusztay   sw->ops->refinehierarchy                 = NULL;
1771d0c080abSJoseph Pusztay   sw->ops->coarsenhierarchy                = NULL;
1772d0c080abSJoseph Pusztay   sw->ops->globaltolocalbegin              = NULL;
1773d0c080abSJoseph Pusztay   sw->ops->globaltolocalend                = NULL;
1774d0c080abSJoseph Pusztay   sw->ops->localtoglobalbegin              = NULL;
1775d0c080abSJoseph Pusztay   sw->ops->localtoglobalend                = NULL;
1776d0c080abSJoseph Pusztay   sw->ops->destroy                         = DMDestroy_Swarm;
1777d0c080abSJoseph Pusztay   sw->ops->createsubdm                     = NULL;
1778d0c080abSJoseph Pusztay   sw->ops->getdimpoints                    = NULL;
1779d0c080abSJoseph Pusztay   sw->ops->locatepoints                    = NULL;
1780d0c080abSJoseph Pusztay   PetscFunctionReturn(0);
1781d0c080abSJoseph Pusztay }
1782d0c080abSJoseph Pusztay 
1783d0c080abSJoseph Pusztay PETSC_INTERN PetscErrorCode DMClone_Swarm(DM dm, DM *newdm)
1784d0c080abSJoseph Pusztay {
1785d0c080abSJoseph Pusztay   DM_Swarm       *swarm = (DM_Swarm *) dm->data;
1786d0c080abSJoseph Pusztay   PetscErrorCode ierr;
1787d0c080abSJoseph Pusztay 
1788d0c080abSJoseph Pusztay   PetscFunctionBegin;
1789d0c080abSJoseph Pusztay   swarm->refct++;
1790d0c080abSJoseph Pusztay   (*newdm)->data = swarm;
1791d0c080abSJoseph Pusztay   ierr = PetscObjectChangeTypeName((PetscObject) *newdm, DMSWARM);CHKERRQ(ierr);
1792d0c080abSJoseph Pusztay   ierr = DMInitialize_Swarm(*newdm);CHKERRQ(ierr);
17932e56dffeSJoe Pusztay   (*newdm)->dim = dm->dim;
1794d0c080abSJoseph Pusztay   PetscFunctionReturn(0);
1795d0c080abSJoseph Pusztay }
1796d0c080abSJoseph Pusztay 
1797d3a51819SDave May /*MC
1798d3a51819SDave May 
1799d3a51819SDave May  DMSWARM = "swarm" - A DM object used to represent arrays of data (fields) of arbitrary data type.
180062741f57SDave May  This implementation was designed for particle methods in which the underlying
1801d3a51819SDave May  data required to be represented is both (i) dynamic in length, (ii) and of arbitrary data type.
1802d3a51819SDave May 
180362741f57SDave May  User data can be represented by DMSwarm through a registering "fields".
180462741f57SDave May  To register a field, the user must provide;
180562741f57SDave May  (a) a unique name;
180662741f57SDave May  (b) the data type (or size in bytes);
180762741f57SDave May  (c) the block size of the data.
1808d3a51819SDave May 
1809d3a51819SDave May  For example, suppose the application requires a unique id, energy, momentum and density to be stored
1810c215a47eSMatthew Knepley  on a set of particles. Then the following code could be used
1811d3a51819SDave May 
181262741f57SDave May $    DMSwarmInitializeFieldRegister(dm)
181362741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"uid",1,PETSC_LONG);
181462741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"energy",1,PETSC_REAL);
181562741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"momentum",3,PETSC_REAL);
181662741f57SDave May $    DMSwarmRegisterPetscDatatypeField(dm,"density",1,PETSC_FLOAT);
181762741f57SDave May $    DMSwarmFinalizeFieldRegister(dm)
1818d3a51819SDave May 
1819d3a51819SDave May  The fields represented by DMSwarm are dynamic and can be re-sized at any time.
182062741f57SDave May  The only restriction imposed by DMSwarm is that all fields contain the same number of points.
1821d3a51819SDave May 
1822d3a51819SDave May  To support particle methods, "migration" techniques are provided. These methods migrate data
1823d3a51819SDave May  between MPI-ranks.
1824d3a51819SDave May 
1825d3a51819SDave May  DMSwarm supports the methods DMCreateGlobalVector() and DMCreateLocalVector().
1826d3a51819SDave May  As a DMSwarm may internally define and store values of different data types,
182762741f57SDave May  before calling DMCreateGlobalVector() or DMCreateLocalVector(), the user must inform DMSwarm which
1828d3a51819SDave May  fields should be used to define a Vec object via
1829d3a51819SDave May    DMSwarmVectorDefineField()
1830c215a47eSMatthew Knepley  The specified field can be changed at any time - thereby permitting vectors
1831c215a47eSMatthew Knepley  compatible with different fields to be created.
1832d3a51819SDave May 
183362741f57SDave May  A dual representation of fields in the DMSwarm and a Vec object is permitted via
1834d3a51819SDave May    DMSwarmCreateGlobalVectorFromField()
1835d3a51819SDave May  Here the data defining the field in the DMSwarm is shared with a Vec.
1836d3a51819SDave May  This is inherently unsafe if you alter the size of the field at any time between
1837d3a51819SDave May  calls to DMSwarmCreateGlobalVectorFromField() and DMSwarmDestroyGlobalVectorFromField().
1838cc651181SDave May  If the local size of the DMSwarm does not match the local size of the global vector
1839cc651181SDave May  when DMSwarmDestroyGlobalVectorFromField() is called, an error is thrown.
1840d3a51819SDave May 
184162741f57SDave May  Additional high-level support is provided for Particle-In-Cell methods.
184262741f57SDave May  Please refer to the man page for DMSwarmSetType().
184362741f57SDave May 
1844d3a51819SDave May  Level: beginner
1845d3a51819SDave May 
1846d3a51819SDave May .seealso: DMType, DMCreate(), DMSetType()
1847d3a51819SDave May M*/
184857795646SDave May PETSC_EXTERN PetscErrorCode DMCreate_Swarm(DM dm)
184957795646SDave May {
185057795646SDave May   DM_Swarm      *swarm;
185157795646SDave May   PetscErrorCode ierr;
185257795646SDave May 
185357795646SDave May   PetscFunctionBegin;
185457795646SDave May   PetscValidHeaderSpecific(dm, DM_CLASSID, 1);
185557795646SDave May   ierr     = PetscNewLog(dm,&swarm);CHKERRQ(ierr);
1856f0cdbbbaSDave May   dm->data = swarm;
185777048351SPatrick Sanan   ierr = DMSwarmDataBucketCreate(&swarm->db);CHKERRQ(ierr);
1858f0cdbbbaSDave May   ierr = DMSwarmInitializeFieldRegister(dm);CHKERRQ(ierr);
1859d0c080abSJoseph Pusztay   swarm->refct = 1;
1860b5bcf523SDave May   swarm->vec_field_set = PETSC_FALSE;
18613454631fSDave May   swarm->issetup = PETSC_FALSE;
1862480eef7bSDave May   swarm->swarm_type = DMSWARM_BASIC;
1863480eef7bSDave May   swarm->migrate_type = DMSWARM_MIGRATE_BASIC;
1864480eef7bSDave May   swarm->collect_type = DMSWARM_COLLECT_BASIC;
186540c453e9SDave May   swarm->migrate_error_on_missing_point = PETSC_FALSE;
1866f0cdbbbaSDave May   swarm->dmcell = NULL;
1867f0cdbbbaSDave May   swarm->collect_view_active = PETSC_FALSE;
1868f0cdbbbaSDave May   swarm->collect_view_reset_nlocal = -1;
1869d0c080abSJoseph Pusztay   ierr = DMInitialize_Swarm(dm);CHKERRQ(ierr);
187057795646SDave May   PetscFunctionReturn(0);
187157795646SDave May }
1872