xref: /petsc/src/ts/characteristic/interface/characteristic.c (revision 63a3b9bc7a1f24f247904ccba9383635fe6abade)
1af33a6ddSJed Brown 
2af0996ceSBarry Smith #include <petsc/private/characteristicimpl.h> /*I "petsccharacteristic.h" I*/
31e25c274SJed Brown #include <petscdmda.h>
4665c2dedSJed Brown #include <petscviewer.h>
5af33a6ddSJed Brown 
6af33a6ddSJed Brown PetscClassId  CHARACTERISTIC_CLASSID;
7af33a6ddSJed Brown PetscLogEvent CHARACTERISTIC_SetUp, CHARACTERISTIC_Solve, CHARACTERISTIC_QueueSetup, CHARACTERISTIC_DAUpdate;
8af33a6ddSJed Brown PetscLogEvent CHARACTERISTIC_HalfTimeLocal, CHARACTERISTIC_HalfTimeRemote, CHARACTERISTIC_HalfTimeExchange;
9af33a6ddSJed Brown PetscLogEvent CHARACTERISTIC_FullTimeLocal, CHARACTERISTIC_FullTimeRemote, CHARACTERISTIC_FullTimeExchange;
10af33a6ddSJed Brown /*
11af33a6ddSJed Brown    Contains the list of registered characteristic routines
12af33a6ddSJed Brown */
130298fd71SBarry Smith PetscFunctionList CharacteristicList              = NULL;
14140e18c1SBarry Smith PetscBool         CharacteristicRegisterAllCalled = PETSC_FALSE;
15af33a6ddSJed Brown 
16af33a6ddSJed Brown PetscErrorCode DMDAGetNeighborsRank(DM, PetscMPIInt []);
171cc8b206SBarry Smith PetscInt       DMDAGetNeighborRelative(DM, PetscReal, PetscReal);
18af33a6ddSJed Brown PetscErrorCode DMDAMapToPeriodicDomain(DM, PetscScalar []);
19af33a6ddSJed Brown 
200b8f38c8SBarry Smith PetscErrorCode CharacteristicHeapSort(Characteristic, Queue, PetscInt);
210b8f38c8SBarry Smith PetscErrorCode CharacteristicSiftDown(Characteristic, Queue, PetscInt, PetscInt);
22af33a6ddSJed Brown 
23af33a6ddSJed Brown PetscErrorCode CharacteristicView(Characteristic c, PetscViewer viewer)
24af33a6ddSJed Brown {
25af33a6ddSJed Brown   PetscBool      iascii;
26af33a6ddSJed Brown 
27af33a6ddSJed Brown   PetscFunctionBegin;
28af33a6ddSJed Brown   PetscValidHeaderSpecific(c, CHARACTERISTIC_CLASSID, 1);
29af33a6ddSJed Brown   if (!viewer) {
309566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)c),&viewer));
31af33a6ddSJed Brown   }
32af33a6ddSJed Brown   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
33af33a6ddSJed Brown   PetscCheckSameComm(c, 1, viewer, 2);
34af33a6ddSJed Brown 
359566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii));
36af33a6ddSJed Brown   if (!iascii) {
37af33a6ddSJed Brown     if (c->ops->view) {
389566063dSJacob Faibussowitsch       PetscCall((*c->ops->view)(c, viewer));
39af33a6ddSJed Brown     }
40af33a6ddSJed Brown   }
41af33a6ddSJed Brown   PetscFunctionReturn(0);
42af33a6ddSJed Brown }
43af33a6ddSJed Brown 
446bf464f9SBarry Smith PetscErrorCode CharacteristicDestroy(Characteristic *c)
45af33a6ddSJed Brown {
46af33a6ddSJed Brown   PetscFunctionBegin;
476bf464f9SBarry Smith   if (!*c) PetscFunctionReturn(0);
486bf464f9SBarry Smith   PetscValidHeaderSpecific(*c, CHARACTERISTIC_CLASSID, 1);
496bf464f9SBarry Smith   if (--((PetscObject)(*c))->refct > 0) PetscFunctionReturn(0);
50af33a6ddSJed Brown 
516bf464f9SBarry Smith   if ((*c)->ops->destroy) {
529566063dSJacob Faibussowitsch     PetscCall((*(*c)->ops->destroy)((*c)));
53af33a6ddSJed Brown   }
549566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Type_free(&(*c)->itemType));
559566063dSJacob Faibussowitsch   PetscCall(PetscFree((*c)->queue));
569566063dSJacob Faibussowitsch   PetscCall(PetscFree((*c)->queueLocal));
579566063dSJacob Faibussowitsch   PetscCall(PetscFree((*c)->queueRemote));
589566063dSJacob Faibussowitsch   PetscCall(PetscFree((*c)->neighbors));
599566063dSJacob Faibussowitsch   PetscCall(PetscFree((*c)->needCount));
609566063dSJacob Faibussowitsch   PetscCall(PetscFree((*c)->localOffsets));
619566063dSJacob Faibussowitsch   PetscCall(PetscFree((*c)->fillCount));
629566063dSJacob Faibussowitsch   PetscCall(PetscFree((*c)->remoteOffsets));
639566063dSJacob Faibussowitsch   PetscCall(PetscFree((*c)->request));
649566063dSJacob Faibussowitsch   PetscCall(PetscFree((*c)->status));
659566063dSJacob Faibussowitsch   PetscCall(PetscHeaderDestroy(c));
66af33a6ddSJed Brown   PetscFunctionReturn(0);
67af33a6ddSJed Brown }
68af33a6ddSJed Brown 
69af33a6ddSJed Brown PetscErrorCode CharacteristicCreate(MPI_Comm comm, Characteristic *c)
70af33a6ddSJed Brown {
71af33a6ddSJed Brown   Characteristic newC;
72af33a6ddSJed Brown 
73af33a6ddSJed Brown   PetscFunctionBegin;
74af33a6ddSJed Brown   PetscValidPointer(c, 2);
750298fd71SBarry Smith   *c = NULL;
769566063dSJacob Faibussowitsch   PetscCall(CharacteristicInitializePackage());
77af33a6ddSJed Brown 
789566063dSJacob Faibussowitsch   PetscCall(PetscHeaderCreate(newC, CHARACTERISTIC_CLASSID, "Characteristic", "Characteristic", "Characteristic", comm, CharacteristicDestroy, CharacteristicView));
79af33a6ddSJed Brown   *c   = newC;
80af33a6ddSJed Brown 
81af33a6ddSJed Brown   newC->structured          = PETSC_TRUE;
82af33a6ddSJed Brown   newC->numIds              = 0;
830298fd71SBarry Smith   newC->velocityDA          = NULL;
840298fd71SBarry Smith   newC->velocity            = NULL;
850298fd71SBarry Smith   newC->velocityOld         = NULL;
86af33a6ddSJed Brown   newC->numVelocityComp     = 0;
870298fd71SBarry Smith   newC->velocityComp        = NULL;
880298fd71SBarry Smith   newC->velocityInterp      = NULL;
890298fd71SBarry Smith   newC->velocityInterpLocal = NULL;
900298fd71SBarry Smith   newC->velocityCtx         = NULL;
910298fd71SBarry Smith   newC->fieldDA             = NULL;
920298fd71SBarry Smith   newC->field               = NULL;
93af33a6ddSJed Brown   newC->numFieldComp        = 0;
940298fd71SBarry Smith   newC->fieldComp           = NULL;
950298fd71SBarry Smith   newC->fieldInterp         = NULL;
960298fd71SBarry Smith   newC->fieldInterpLocal    = NULL;
970298fd71SBarry Smith   newC->fieldCtx            = NULL;
980298fd71SBarry Smith   newC->itemType            = 0;
990298fd71SBarry Smith   newC->queue               = NULL;
100af33a6ddSJed Brown   newC->queueSize           = 0;
101af33a6ddSJed Brown   newC->queueMax            = 0;
1020298fd71SBarry Smith   newC->queueLocal          = NULL;
103af33a6ddSJed Brown   newC->queueLocalSize      = 0;
104af33a6ddSJed Brown   newC->queueLocalMax       = 0;
1050298fd71SBarry Smith   newC->queueRemote         = NULL;
106af33a6ddSJed Brown   newC->queueRemoteSize     = 0;
107af33a6ddSJed Brown   newC->queueRemoteMax      = 0;
108af33a6ddSJed Brown   newC->numNeighbors        = 0;
1090298fd71SBarry Smith   newC->neighbors           = NULL;
1100298fd71SBarry Smith   newC->needCount           = NULL;
1110298fd71SBarry Smith   newC->localOffsets        = NULL;
1120298fd71SBarry Smith   newC->fillCount           = NULL;
1130298fd71SBarry Smith   newC->remoteOffsets       = NULL;
1140298fd71SBarry Smith   newC->request             = NULL;
1150298fd71SBarry Smith   newC->status              = NULL;
116af33a6ddSJed Brown   PetscFunctionReturn(0);
117af33a6ddSJed Brown }
118af33a6ddSJed Brown 
119af33a6ddSJed Brown /*@C
120af33a6ddSJed Brown    CharacteristicSetType - Builds Characteristic for a particular solver.
121af33a6ddSJed Brown 
122af33a6ddSJed Brown    Logically Collective on Characteristic
123af33a6ddSJed Brown 
124af33a6ddSJed Brown    Input Parameters:
125af33a6ddSJed Brown +  c    - the method of characteristics context
126af33a6ddSJed Brown -  type - a known method
127af33a6ddSJed Brown 
128af33a6ddSJed Brown    Options Database Key:
129af33a6ddSJed Brown .  -characteristic_type <method> - Sets the method; use -help for a list
130af33a6ddSJed Brown     of available methods
131af33a6ddSJed Brown 
132af33a6ddSJed Brown    Notes:
13330a76a96SBarry Smith    See "include/petsccharacteristic.h" for available methods
134af33a6ddSJed Brown 
135af33a6ddSJed Brown   Normally, it is best to use the CharacteristicSetFromOptions() command and
136af33a6ddSJed Brown   then set the Characteristic type from the options database rather than by using
137af33a6ddSJed Brown   this routine.  Using the options database provides the user with
138af33a6ddSJed Brown   maximum flexibility in evaluating the many different Krylov methods.
139af33a6ddSJed Brown   The CharacteristicSetType() routine is provided for those situations where it
140af33a6ddSJed Brown   is necessary to set the iterative solver independently of the command
141af33a6ddSJed Brown   line or options database.  This might be the case, for example, when
142af33a6ddSJed Brown   the choice of iterative solver changes during the execution of the
143af33a6ddSJed Brown   program, and the user's application is taking responsibility for
144af33a6ddSJed Brown   choosing the appropriate method.  In other words, this routine is
145af33a6ddSJed Brown   not for beginners.
146af33a6ddSJed Brown 
147af33a6ddSJed Brown   Level: intermediate
148af33a6ddSJed Brown 
149af33a6ddSJed Brown .seealso: CharacteristicType
150af33a6ddSJed Brown 
151af33a6ddSJed Brown @*/
15219fd82e9SBarry Smith PetscErrorCode CharacteristicSetType(Characteristic c, CharacteristicType type)
153af33a6ddSJed Brown {
154af33a6ddSJed Brown   PetscBool      match;
1555f80ce2aSJacob Faibussowitsch   PetscErrorCode (*r)(Characteristic);
156af33a6ddSJed Brown 
157af33a6ddSJed Brown   PetscFunctionBegin;
158af33a6ddSJed Brown   PetscValidHeaderSpecific(c, CHARACTERISTIC_CLASSID, 1);
159af33a6ddSJed Brown   PetscValidCharPointer(type, 2);
160af33a6ddSJed Brown 
1619566063dSJacob Faibussowitsch   PetscCall(PetscObjectTypeCompare((PetscObject) c, type, &match));
162af33a6ddSJed Brown   if (match) PetscFunctionReturn(0);
163af33a6ddSJed Brown 
164af33a6ddSJed Brown   if (c->data) {
165af33a6ddSJed Brown     /* destroy the old private Characteristic context */
1669566063dSJacob Faibussowitsch     PetscCall((*c->ops->destroy)(c));
1670298fd71SBarry Smith     c->ops->destroy = NULL;
1682120983fSLisandro Dalcin     c->data         = NULL;
169af33a6ddSJed Brown   }
170af33a6ddSJed Brown 
1719566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListFind(CharacteristicList,type,&r));
1723c633725SBarry Smith   PetscCheck(r,PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown Characteristic type given: %s", type);
173af33a6ddSJed Brown   c->setupcalled = 0;
1749566063dSJacob Faibussowitsch   PetscCall((*r)(c));
1759566063dSJacob Faibussowitsch   PetscCall(PetscObjectChangeTypeName((PetscObject) c, type));
176af33a6ddSJed Brown   PetscFunctionReturn(0);
177af33a6ddSJed Brown }
178af33a6ddSJed Brown 
179af33a6ddSJed Brown /*@
180af33a6ddSJed Brown    CharacteristicSetUp - Sets up the internal data structures for the
181af33a6ddSJed Brown    later use of an iterative solver.
182af33a6ddSJed Brown 
183af33a6ddSJed Brown    Collective on Characteristic
184af33a6ddSJed Brown 
185af33a6ddSJed Brown    Input Parameter:
186af33a6ddSJed Brown .  ksp   - iterative context obtained from CharacteristicCreate()
187af33a6ddSJed Brown 
188af33a6ddSJed Brown    Level: developer
189af33a6ddSJed Brown 
190af33a6ddSJed Brown .seealso: CharacteristicCreate(), CharacteristicSolve(), CharacteristicDestroy()
191af33a6ddSJed Brown @*/
192af33a6ddSJed Brown PetscErrorCode CharacteristicSetUp(Characteristic c)
193af33a6ddSJed Brown {
194af33a6ddSJed Brown   PetscFunctionBegin;
195af33a6ddSJed Brown   PetscValidHeaderSpecific(c, CHARACTERISTIC_CLASSID, 1);
196af33a6ddSJed Brown 
197af33a6ddSJed Brown   if (!((PetscObject)c)->type_name) {
1989566063dSJacob Faibussowitsch     PetscCall(CharacteristicSetType(c, CHARACTERISTICDA));
199af33a6ddSJed Brown   }
200af33a6ddSJed Brown 
201af33a6ddSJed Brown   if (c->setupcalled == 2) PetscFunctionReturn(0);
202af33a6ddSJed Brown 
2039566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(CHARACTERISTIC_SetUp,c,NULL,NULL,NULL));
204af33a6ddSJed Brown   if (!c->setupcalled) {
2059566063dSJacob Faibussowitsch     PetscCall((*c->ops->setup)(c));
206af33a6ddSJed Brown   }
2079566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(CHARACTERISTIC_SetUp,c,NULL,NULL,NULL));
208af33a6ddSJed Brown   c->setupcalled = 2;
209af33a6ddSJed Brown   PetscFunctionReturn(0);
210af33a6ddSJed Brown }
211af33a6ddSJed Brown 
212af33a6ddSJed Brown /*@C
2131c84c290SBarry Smith   CharacteristicRegister -  Adds a solver to the method of characteristics package.
2141c84c290SBarry Smith 
2151c84c290SBarry Smith    Not Collective
2161c84c290SBarry Smith 
2171c84c290SBarry Smith    Input Parameters:
2181c84c290SBarry Smith +  name_solver - name of a new user-defined solver
2191c84c290SBarry Smith -  routine_create - routine to create method context
2201c84c290SBarry Smith 
2211c84c290SBarry Smith   Sample usage:
2221c84c290SBarry Smith .vb
223bdf89e91SBarry Smith     CharacteristicRegister("my_char", MyCharCreate);
2241c84c290SBarry Smith .ve
2251c84c290SBarry Smith 
2261c84c290SBarry Smith   Then, your Characteristic type can be chosen with the procedural interface via
2271c84c290SBarry Smith .vb
2281c84c290SBarry Smith     CharacteristicCreate(MPI_Comm, Characteristic* &char);
2291c84c290SBarry Smith     CharacteristicSetType(char,"my_char");
2301c84c290SBarry Smith .ve
2311c84c290SBarry Smith    or at runtime via the option
2321c84c290SBarry Smith .vb
2331c84c290SBarry Smith     -characteristic_type my_char
2341c84c290SBarry Smith .ve
2351c84c290SBarry Smith 
2361c84c290SBarry Smith    Notes:
2371c84c290SBarry Smith    CharacteristicRegister() may be called multiple times to add several user-defined solvers.
2381c84c290SBarry Smith 
2391c84c290SBarry Smith .seealso: CharacteristicRegisterAll(), CharacteristicRegisterDestroy()
240af33a6ddSJed Brown 
241af33a6ddSJed Brown   Level: advanced
242af33a6ddSJed Brown @*/
243bdf89e91SBarry Smith PetscErrorCode CharacteristicRegister(const char sname[],PetscErrorCode (*function)(Characteristic))
244af33a6ddSJed Brown {
245af33a6ddSJed Brown   PetscFunctionBegin;
2469566063dSJacob Faibussowitsch   PetscCall(CharacteristicInitializePackage());
2479566063dSJacob Faibussowitsch   PetscCall(PetscFunctionListAdd(&CharacteristicList,sname,function));
248af33a6ddSJed Brown   PetscFunctionReturn(0);
249af33a6ddSJed Brown }
250af33a6ddSJed Brown 
251af33a6ddSJed Brown PetscErrorCode CharacteristicSetVelocityInterpolation(Characteristic c, DM da, Vec v, Vec vOld, PetscInt numComponents, PetscInt components[], PetscErrorCode (*interp)(Vec, PetscReal[], PetscInt, PetscInt[], PetscScalar[], void*), void *ctx)
252af33a6ddSJed Brown {
253af33a6ddSJed Brown   PetscFunctionBegin;
254af33a6ddSJed Brown   c->velocityDA      = da;
255af33a6ddSJed Brown   c->velocity        = v;
256af33a6ddSJed Brown   c->velocityOld     = vOld;
257af33a6ddSJed Brown   c->numVelocityComp = numComponents;
258af33a6ddSJed Brown   c->velocityComp    = components;
259af33a6ddSJed Brown   c->velocityInterp  = interp;
260af33a6ddSJed Brown   c->velocityCtx     = ctx;
261af33a6ddSJed Brown   PetscFunctionReturn(0);
262af33a6ddSJed Brown }
263af33a6ddSJed Brown 
264af33a6ddSJed Brown PetscErrorCode CharacteristicSetVelocityInterpolationLocal(Characteristic c, DM da, Vec v, Vec vOld, PetscInt numComponents, PetscInt components[], PetscErrorCode (*interp)(void*, PetscReal [], PetscInt, PetscInt[], PetscScalar[], void*), void *ctx)
265af33a6ddSJed Brown {
266af33a6ddSJed Brown   PetscFunctionBegin;
267af33a6ddSJed Brown   c->velocityDA          = da;
268af33a6ddSJed Brown   c->velocity            = v;
269af33a6ddSJed Brown   c->velocityOld         = vOld;
270af33a6ddSJed Brown   c->numVelocityComp     = numComponents;
271af33a6ddSJed Brown   c->velocityComp        = components;
272af33a6ddSJed Brown   c->velocityInterpLocal = interp;
273af33a6ddSJed Brown   c->velocityCtx         = ctx;
274af33a6ddSJed Brown   PetscFunctionReturn(0);
275af33a6ddSJed Brown }
276af33a6ddSJed Brown 
277af33a6ddSJed Brown PetscErrorCode CharacteristicSetFieldInterpolation(Characteristic c, DM da, Vec v, PetscInt numComponents, PetscInt components[], PetscErrorCode (*interp)(Vec, PetscReal[], PetscInt, PetscInt[], PetscScalar[], void*), void *ctx)
278af33a6ddSJed Brown {
279af33a6ddSJed Brown   PetscFunctionBegin;
280af33a6ddSJed Brown #if 0
2813c633725SBarry Smith   PetscCheck(numComponents <= 2,PETSC_COMM_SELF,PETSC_ERR_SUP, "Fields with more than 2 components are not supported. Send mail to petsc-maint@mcs.anl.gov.");
282af33a6ddSJed Brown #endif
283af33a6ddSJed Brown   c->fieldDA      = da;
284af33a6ddSJed Brown   c->field        = v;
285af33a6ddSJed Brown   c->numFieldComp = numComponents;
286af33a6ddSJed Brown   c->fieldComp    = components;
287af33a6ddSJed Brown   c->fieldInterp  = interp;
288af33a6ddSJed Brown   c->fieldCtx     = ctx;
289af33a6ddSJed Brown   PetscFunctionReturn(0);
290af33a6ddSJed Brown }
291af33a6ddSJed Brown 
292af33a6ddSJed Brown PetscErrorCode CharacteristicSetFieldInterpolationLocal(Characteristic c, DM da, Vec v, PetscInt numComponents, PetscInt components[], PetscErrorCode (*interp)(void*, PetscReal[], PetscInt, PetscInt[], PetscScalar [], void*), void *ctx)
293af33a6ddSJed Brown {
294af33a6ddSJed Brown   PetscFunctionBegin;
295af33a6ddSJed Brown #if 0
2963c633725SBarry Smith   PetscCheck(numComponents <= 2,PETSC_COMM_SELF,PETSC_ERR_SUP, "Fields with more than 2 components are not supported. Send mail to petsc-maint@mcs.anl.gov.");
297af33a6ddSJed Brown #endif
298af33a6ddSJed Brown   c->fieldDA          = da;
299af33a6ddSJed Brown   c->field            = v;
300af33a6ddSJed Brown   c->numFieldComp     = numComponents;
301af33a6ddSJed Brown   c->fieldComp        = components;
302af33a6ddSJed Brown   c->fieldInterpLocal = interp;
303af33a6ddSJed Brown   c->fieldCtx         = ctx;
304af33a6ddSJed Brown   PetscFunctionReturn(0);
305af33a6ddSJed Brown }
306af33a6ddSJed Brown 
307af33a6ddSJed Brown PetscErrorCode CharacteristicSolve(Characteristic c, PetscReal dt, Vec solution)
308af33a6ddSJed Brown {
309af33a6ddSJed Brown   CharacteristicPointDA2D Qi;
310af33a6ddSJed Brown   DM                      da = c->velocityDA;
311af33a6ddSJed Brown   Vec                     velocityLocal, velocityLocalOld;
312af33a6ddSJed Brown   Vec                     fieldLocal;
313af33a6ddSJed Brown   DMDALocalInfo           info;
314af33a6ddSJed Brown   PetscScalar             **solArray;
315af33a6ddSJed Brown   void                    *velocityArray;
316af33a6ddSJed Brown   void                    *velocityArrayOld;
317af33a6ddSJed Brown   void                    *fieldArray;
3181cc8b206SBarry Smith   PetscScalar             *interpIndices;
3191cc8b206SBarry Smith   PetscScalar             *velocityValues, *velocityValuesOld;
3201cc8b206SBarry Smith   PetscScalar             *fieldValues;
321af33a6ddSJed Brown   PetscMPIInt             rank;
322af33a6ddSJed Brown   PetscInt                dim;
323af33a6ddSJed Brown   PetscMPIInt             neighbors[9];
324af33a6ddSJed Brown   PetscInt                dof;
325af33a6ddSJed Brown   PetscInt                gx, gy;
326af33a6ddSJed Brown   PetscInt                n, is, ie, js, je, comp;
327af33a6ddSJed Brown 
328af33a6ddSJed Brown   PetscFunctionBegin;
329af33a6ddSJed Brown   c->queueSize = 0;
3309566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)c), &rank));
3319566063dSJacob Faibussowitsch   PetscCall(DMDAGetNeighborsRank(da, neighbors));
3329566063dSJacob Faibussowitsch   PetscCall(CharacteristicSetNeighbors(c, 9, neighbors));
3339566063dSJacob Faibussowitsch   PetscCall(CharacteristicSetUp(c));
334af33a6ddSJed Brown   /* global and local grid info */
3359566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, &dim, &gx, &gy, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL));
3369566063dSJacob Faibussowitsch   PetscCall(DMDAGetLocalInfo(da, &info));
337af33a6ddSJed Brown   is   = info.xs;          ie   = info.xs+info.xm;
338af33a6ddSJed Brown   js   = info.ys;          je   = info.ys+info.ym;
339af33a6ddSJed Brown   /* Allocation */
3409566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(dim,                &interpIndices));
3419566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(c->numVelocityComp, &velocityValues));
3429566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(c->numVelocityComp, &velocityValuesOld));
3439566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(c->numFieldComp,    &fieldValues));
3449566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(CHARACTERISTIC_Solve,NULL,NULL,NULL,NULL));
345af33a6ddSJed Brown 
346af33a6ddSJed Brown   /* -----------------------------------------------------------------------
347af33a6ddSJed Brown      PART 1, AT t-dt/2
348af33a6ddSJed Brown      -----------------------------------------------------------------------*/
3499566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(CHARACTERISTIC_QueueSetup,NULL,NULL,NULL,NULL));
350af33a6ddSJed Brown   /* GET POSITION AT HALF TIME IN THE PAST */
351af33a6ddSJed Brown   if (c->velocityInterpLocal) {
3529566063dSJacob Faibussowitsch     PetscCall(DMGetLocalVector(c->velocityDA, &velocityLocal));
3539566063dSJacob Faibussowitsch     PetscCall(DMGetLocalVector(c->velocityDA, &velocityLocalOld));
3549566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(c->velocityDA, c->velocity, INSERT_VALUES, velocityLocal));
3559566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(c->velocityDA, c->velocity, INSERT_VALUES, velocityLocal));
3569566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(c->velocityDA, c->velocityOld, INSERT_VALUES, velocityLocalOld));
3579566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(c->velocityDA, c->velocityOld, INSERT_VALUES, velocityLocalOld));
3589566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArray(c->velocityDA, velocityLocal,    &velocityArray));
3599566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArray(c->velocityDA, velocityLocalOld, &velocityArrayOld));
360af33a6ddSJed Brown   }
3619566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Calculating position at t_{n - 1/2}\n"));
362af33a6ddSJed Brown   for (Qi.j = js; Qi.j < je; Qi.j++) {
363af33a6ddSJed Brown     for (Qi.i = is; Qi.i < ie; Qi.i++) {
364af33a6ddSJed Brown       interpIndices[0] = Qi.i;
365af33a6ddSJed Brown       interpIndices[1] = Qi.j;
3669566063dSJacob Faibussowitsch       if (c->velocityInterpLocal) PetscCall(c->velocityInterpLocal(velocityArray, interpIndices, c->numVelocityComp, c->velocityComp, velocityValues, c->velocityCtx));
3679566063dSJacob Faibussowitsch       else PetscCall(c->velocityInterp(c->velocity, interpIndices, c->numVelocityComp, c->velocityComp, velocityValues, c->velocityCtx));
368af33a6ddSJed Brown       Qi.x = Qi.i - velocityValues[0]*dt/2.0;
369af33a6ddSJed Brown       Qi.y = Qi.j - velocityValues[1]*dt/2.0;
370af33a6ddSJed Brown 
371af33a6ddSJed Brown       /* Determine whether the position at t - dt/2 is local */
372af33a6ddSJed Brown       Qi.proc = DMDAGetNeighborRelative(da, Qi.x, Qi.y);
373af33a6ddSJed Brown 
374af33a6ddSJed Brown       /* Check for Periodic boundaries and move all periodic points back onto the domain */
3759566063dSJacob Faibussowitsch       PetscCall(DMDAMapCoordsToPeriodicDomain(da,&(Qi.x),&(Qi.y)));
3769566063dSJacob Faibussowitsch       PetscCall(CharacteristicAddPoint(c, &Qi));
377af33a6ddSJed Brown     }
378af33a6ddSJed Brown   }
3799566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(CHARACTERISTIC_QueueSetup,NULL,NULL,NULL,NULL));
380af33a6ddSJed Brown 
3819566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(CHARACTERISTIC_HalfTimeExchange,NULL,NULL,NULL,NULL));
3829566063dSJacob Faibussowitsch   PetscCall(CharacteristicSendCoordinatesBegin(c));
3839566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(CHARACTERISTIC_HalfTimeExchange,NULL,NULL,NULL,NULL));
384af33a6ddSJed Brown 
3859566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(CHARACTERISTIC_HalfTimeLocal,NULL,NULL,NULL,NULL));
386af33a6ddSJed Brown   /* Calculate velocity at t_n+1/2 (local values) */
3879566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Calculating local velocities at t_{n - 1/2}\n"));
388af33a6ddSJed Brown   for (n = 0; n < c->queueSize; n++) {
389af33a6ddSJed Brown     Qi = c->queue[n];
390af33a6ddSJed Brown     if (c->neighbors[Qi.proc] == rank) {
391af33a6ddSJed Brown       interpIndices[0] = Qi.x;
392af33a6ddSJed Brown       interpIndices[1] = Qi.y;
393af33a6ddSJed Brown       if (c->velocityInterpLocal) {
3949566063dSJacob Faibussowitsch         PetscCall(c->velocityInterpLocal(velocityArray,    interpIndices, c->numVelocityComp, c->velocityComp, velocityValues, c->velocityCtx));
3959566063dSJacob Faibussowitsch         PetscCall(c->velocityInterpLocal(velocityArrayOld, interpIndices, c->numVelocityComp, c->velocityComp, velocityValuesOld, c->velocityCtx));
396af33a6ddSJed Brown       } else {
3979566063dSJacob Faibussowitsch         PetscCall(c->velocityInterp(c->velocity,    interpIndices, c->numVelocityComp, c->velocityComp, velocityValues, c->velocityCtx));
3989566063dSJacob Faibussowitsch         PetscCall(c->velocityInterp(c->velocityOld, interpIndices, c->numVelocityComp, c->velocityComp, velocityValuesOld, c->velocityCtx));
399af33a6ddSJed Brown       }
400af33a6ddSJed Brown       Qi.x = 0.5*(velocityValues[0] + velocityValuesOld[0]);
401af33a6ddSJed Brown       Qi.y = 0.5*(velocityValues[1] + velocityValuesOld[1]);
402af33a6ddSJed Brown     }
403af33a6ddSJed Brown     c->queue[n] = Qi;
404af33a6ddSJed Brown   }
4059566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(CHARACTERISTIC_HalfTimeLocal,NULL,NULL,NULL,NULL));
406af33a6ddSJed Brown 
4079566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(CHARACTERISTIC_HalfTimeExchange,NULL,NULL,NULL,NULL));
4089566063dSJacob Faibussowitsch   PetscCall(CharacteristicSendCoordinatesEnd(c));
4099566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(CHARACTERISTIC_HalfTimeExchange,NULL,NULL,NULL,NULL));
410af33a6ddSJed Brown 
411af33a6ddSJed Brown   /* Calculate velocity at t_n+1/2 (fill remote requests) */
4129566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(CHARACTERISTIC_HalfTimeRemote,NULL,NULL,NULL,NULL));
413*63a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Calculating %" PetscInt_FMT " remote velocities at t_{n - 1/2}\n", c->queueRemoteSize));
414af33a6ddSJed Brown   for (n = 0; n < c->queueRemoteSize; n++) {
415af33a6ddSJed Brown     Qi = c->queueRemote[n];
416af33a6ddSJed Brown     interpIndices[0] = Qi.x;
417af33a6ddSJed Brown     interpIndices[1] = Qi.y;
418af33a6ddSJed Brown     if (c->velocityInterpLocal) {
4199566063dSJacob Faibussowitsch       PetscCall(c->velocityInterpLocal(velocityArray,    interpIndices, c->numVelocityComp, c->velocityComp, velocityValues,    c->velocityCtx));
4209566063dSJacob Faibussowitsch       PetscCall(c->velocityInterpLocal(velocityArrayOld, interpIndices, c->numVelocityComp, c->velocityComp, velocityValuesOld, c->velocityCtx));
421af33a6ddSJed Brown     } else {
4229566063dSJacob Faibussowitsch       PetscCall(c->velocityInterp(c->velocity,    interpIndices, c->numVelocityComp, c->velocityComp, velocityValues,    c->velocityCtx));
4239566063dSJacob Faibussowitsch       PetscCall(c->velocityInterp(c->velocityOld, interpIndices, c->numVelocityComp, c->velocityComp, velocityValuesOld, c->velocityCtx));
424af33a6ddSJed Brown     }
425af33a6ddSJed Brown     Qi.x = 0.5*(velocityValues[0] + velocityValuesOld[0]);
426af33a6ddSJed Brown     Qi.y = 0.5*(velocityValues[1] + velocityValuesOld[1]);
427af33a6ddSJed Brown     c->queueRemote[n] = Qi;
428af33a6ddSJed Brown   }
4299566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(CHARACTERISTIC_HalfTimeRemote,NULL,NULL,NULL,NULL));
4309566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(CHARACTERISTIC_HalfTimeExchange,NULL,NULL,NULL,NULL));
4319566063dSJacob Faibussowitsch   PetscCall(CharacteristicGetValuesBegin(c));
4329566063dSJacob Faibussowitsch   PetscCall(CharacteristicGetValuesEnd(c));
433af33a6ddSJed Brown   if (c->velocityInterpLocal) {
4349566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArray(c->velocityDA, velocityLocal,    &velocityArray));
4359566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArray(c->velocityDA, velocityLocalOld, &velocityArrayOld));
4369566063dSJacob Faibussowitsch     PetscCall(DMRestoreLocalVector(c->velocityDA, &velocityLocal));
4379566063dSJacob Faibussowitsch     PetscCall(DMRestoreLocalVector(c->velocityDA, &velocityLocalOld));
438af33a6ddSJed Brown   }
4399566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(CHARACTERISTIC_HalfTimeExchange,NULL,NULL,NULL,NULL));
440af33a6ddSJed Brown 
441af33a6ddSJed Brown   /* -----------------------------------------------------------------------
442af33a6ddSJed Brown      PART 2, AT t-dt
443af33a6ddSJed Brown      -----------------------------------------------------------------------*/
444af33a6ddSJed Brown 
445af33a6ddSJed Brown   /* GET POSITION AT t_n (local values) */
4469566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(CHARACTERISTIC_FullTimeLocal,NULL,NULL,NULL,NULL));
4479566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Calculating position at t_{n}\n"));
448af33a6ddSJed Brown   for (n = 0; n < c->queueSize; n++) {
449af33a6ddSJed Brown     Qi   = c->queue[n];
450af33a6ddSJed Brown     Qi.x = Qi.i - Qi.x*dt;
451af33a6ddSJed Brown     Qi.y = Qi.j - Qi.y*dt;
452af33a6ddSJed Brown 
453af33a6ddSJed Brown     /* Determine whether the position at t-dt is local */
454af33a6ddSJed Brown     Qi.proc = DMDAGetNeighborRelative(da, Qi.x, Qi.y);
455af33a6ddSJed Brown 
456af33a6ddSJed Brown     /* Check for Periodic boundaries and move all periodic points back onto the domain */
4579566063dSJacob Faibussowitsch     PetscCall(DMDAMapCoordsToPeriodicDomain(da,&(Qi.x),&(Qi.y)));
458af33a6ddSJed Brown 
459af33a6ddSJed Brown     c->queue[n] = Qi;
460af33a6ddSJed Brown   }
4619566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(CHARACTERISTIC_FullTimeLocal,NULL,NULL,NULL,NULL));
462af33a6ddSJed Brown 
4639566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(CHARACTERISTIC_FullTimeExchange,NULL,NULL,NULL,NULL));
4649566063dSJacob Faibussowitsch   PetscCall(CharacteristicSendCoordinatesBegin(c));
4659566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(CHARACTERISTIC_FullTimeExchange,NULL,NULL,NULL,NULL));
466af33a6ddSJed Brown 
467af33a6ddSJed Brown   /* GET VALUE AT FULL TIME IN THE PAST (LOCAL REQUESTS) */
4689566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(CHARACTERISTIC_FullTimeLocal,NULL,NULL,NULL,NULL));
469af33a6ddSJed Brown   if (c->fieldInterpLocal) {
4709566063dSJacob Faibussowitsch     PetscCall(DMGetLocalVector(c->fieldDA, &fieldLocal));
4719566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalBegin(c->fieldDA, c->field, INSERT_VALUES, fieldLocal));
4729566063dSJacob Faibussowitsch     PetscCall(DMGlobalToLocalEnd(c->fieldDA, c->field, INSERT_VALUES, fieldLocal));
4739566063dSJacob Faibussowitsch     PetscCall(DMDAVecGetArray(c->fieldDA, fieldLocal, &fieldArray));
474af33a6ddSJed Brown   }
4759566063dSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Calculating local field at t_{n}\n"));
476af33a6ddSJed Brown   for (n = 0; n < c->queueSize; n++) {
477af33a6ddSJed Brown     if (c->neighbors[c->queue[n].proc] == rank) {
478af33a6ddSJed Brown       interpIndices[0] = c->queue[n].x;
479af33a6ddSJed Brown       interpIndices[1] = c->queue[n].y;
4809566063dSJacob Faibussowitsch       if (c->fieldInterpLocal) PetscCall(c->fieldInterpLocal(fieldArray, interpIndices, c->numFieldComp, c->fieldComp, fieldValues, c->fieldCtx));
4819566063dSJacob Faibussowitsch       else PetscCall(c->fieldInterp(c->field, interpIndices, c->numFieldComp, c->fieldComp, fieldValues, c->fieldCtx));
482bbd56ea5SKarl Rupp       for (comp = 0; comp < c->numFieldComp; comp++) c->queue[n].field[comp] = fieldValues[comp];
483af33a6ddSJed Brown     }
484af33a6ddSJed Brown   }
4859566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(CHARACTERISTIC_FullTimeLocal,NULL,NULL,NULL,NULL));
486af33a6ddSJed Brown 
4879566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(CHARACTERISTIC_FullTimeExchange,NULL,NULL,NULL,NULL));
4889566063dSJacob Faibussowitsch   PetscCall(CharacteristicSendCoordinatesEnd(c));
4899566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(CHARACTERISTIC_FullTimeExchange,NULL,NULL,NULL,NULL));
490af33a6ddSJed Brown 
491af33a6ddSJed Brown   /* GET VALUE AT FULL TIME IN THE PAST (REMOTE REQUESTS) */
4929566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(CHARACTERISTIC_FullTimeRemote,NULL,NULL,NULL,NULL));
493*63a3b9bcSJacob Faibussowitsch   PetscCall(PetscInfo(NULL, "Calculating %" PetscInt_FMT " remote field points at t_{n}\n", c->queueRemoteSize));
494af33a6ddSJed Brown   for (n = 0; n < c->queueRemoteSize; n++) {
495af33a6ddSJed Brown     interpIndices[0] = c->queueRemote[n].x;
496af33a6ddSJed Brown     interpIndices[1] = c->queueRemote[n].y;
497af33a6ddSJed Brown 
498af33a6ddSJed Brown     /* for debugging purposes */
499af33a6ddSJed Brown     if (1) { /* hacked bounds test...let's do better */
500af33a6ddSJed Brown       PetscScalar im = interpIndices[0]; PetscScalar jm = interpIndices[1];
501af33a6ddSJed Brown 
502*63a3b9bcSJacob Faibussowitsch       PetscCheck((im >= (PetscScalar) is - 1.) && (im <= (PetscScalar) ie) && (jm >= (PetscScalar)  js - 1.) && (jm <= (PetscScalar) je),PETSC_COMM_SELF,PETSC_ERR_LIB, "Nonlocal point: (%g,%g)", (double)PetscAbsScalar(im), (double)PetscAbsScalar(jm));
503af33a6ddSJed Brown     }
504af33a6ddSJed Brown 
5059566063dSJacob Faibussowitsch     if (c->fieldInterpLocal) PetscCall(c->fieldInterpLocal(fieldArray, interpIndices, c->numFieldComp, c->fieldComp, fieldValues, c->fieldCtx));
5069566063dSJacob Faibussowitsch     else PetscCall(c->fieldInterp(c->field, interpIndices, c->numFieldComp, c->fieldComp, fieldValues, c->fieldCtx));
507bbd56ea5SKarl Rupp     for (comp = 0; comp < c->numFieldComp; comp++) c->queueRemote[n].field[comp] = fieldValues[comp];
508af33a6ddSJed Brown   }
5099566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(CHARACTERISTIC_FullTimeRemote,NULL,NULL,NULL,NULL));
510af33a6ddSJed Brown 
5119566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(CHARACTERISTIC_FullTimeExchange,NULL,NULL,NULL,NULL));
5129566063dSJacob Faibussowitsch   PetscCall(CharacteristicGetValuesBegin(c));
5139566063dSJacob Faibussowitsch   PetscCall(CharacteristicGetValuesEnd(c));
514af33a6ddSJed Brown   if (c->fieldInterpLocal) {
5159566063dSJacob Faibussowitsch     PetscCall(DMDAVecRestoreArray(c->fieldDA, fieldLocal, &fieldArray));
5169566063dSJacob Faibussowitsch     PetscCall(DMRestoreLocalVector(c->fieldDA, &fieldLocal));
517af33a6ddSJed Brown   }
5189566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(CHARACTERISTIC_FullTimeExchange,NULL,NULL,NULL,NULL));
519af33a6ddSJed Brown 
520af33a6ddSJed Brown   /* Return field of characteristics at t_n-1 */
5219566063dSJacob Faibussowitsch   PetscCall(PetscLogEventBegin(CHARACTERISTIC_DAUpdate,NULL,NULL,NULL,NULL));
5229566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(c->fieldDA,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL));
5239566063dSJacob Faibussowitsch   PetscCall(DMDAVecGetArray(c->fieldDA, solution, &solArray));
524af33a6ddSJed Brown   for (n = 0; n < c->queueSize; n++) {
525af33a6ddSJed Brown     Qi = c->queue[n];
526bbd56ea5SKarl Rupp     for (comp = 0; comp < c->numFieldComp; comp++) solArray[Qi.j][Qi.i*dof+c->fieldComp[comp]] = Qi.field[comp];
527af33a6ddSJed Brown   }
5289566063dSJacob Faibussowitsch   PetscCall(DMDAVecRestoreArray(c->fieldDA, solution, &solArray));
5299566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(CHARACTERISTIC_DAUpdate,NULL,NULL,NULL,NULL));
5309566063dSJacob Faibussowitsch   PetscCall(PetscLogEventEnd(CHARACTERISTIC_Solve,NULL,NULL,NULL,NULL));
531af33a6ddSJed Brown 
532af33a6ddSJed Brown   /* Cleanup */
5339566063dSJacob Faibussowitsch   PetscCall(PetscFree(interpIndices));
5349566063dSJacob Faibussowitsch   PetscCall(PetscFree(velocityValues));
5359566063dSJacob Faibussowitsch   PetscCall(PetscFree(velocityValuesOld));
5369566063dSJacob Faibussowitsch   PetscCall(PetscFree(fieldValues));
537af33a6ddSJed Brown   PetscFunctionReturn(0);
538af33a6ddSJed Brown }
539af33a6ddSJed Brown 
540af33a6ddSJed Brown PetscErrorCode CharacteristicSetNeighbors(Characteristic c, PetscInt numNeighbors, PetscMPIInt neighbors[])
541af33a6ddSJed Brown {
542af33a6ddSJed Brown   PetscFunctionBegin;
543af33a6ddSJed Brown   c->numNeighbors = numNeighbors;
5449566063dSJacob Faibussowitsch   PetscCall(PetscFree(c->neighbors));
5459566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(numNeighbors, &c->neighbors));
5469566063dSJacob Faibussowitsch   PetscCall(PetscArraycpy(c->neighbors, neighbors, numNeighbors));
547af33a6ddSJed Brown   PetscFunctionReturn(0);
548af33a6ddSJed Brown }
549af33a6ddSJed Brown 
550af33a6ddSJed Brown PetscErrorCode CharacteristicAddPoint(Characteristic c, CharacteristicPointDA2D *point)
551af33a6ddSJed Brown {
552af33a6ddSJed Brown   PetscFunctionBegin;
553*63a3b9bcSJacob Faibussowitsch   PetscCheck(c->queueSize < c->queueMax,PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Exceeded maximum queue size %" PetscInt_FMT, c->queueMax);
554af33a6ddSJed Brown   c->queue[c->queueSize++] = *point;
555af33a6ddSJed Brown   PetscFunctionReturn(0);
556af33a6ddSJed Brown }
557af33a6ddSJed Brown 
558af33a6ddSJed Brown int CharacteristicSendCoordinatesBegin(Characteristic c)
559af33a6ddSJed Brown {
560af33a6ddSJed Brown   PetscMPIInt    rank, tag = 121;
561af33a6ddSJed Brown   PetscInt       i, n;
562af33a6ddSJed Brown 
563af33a6ddSJed Brown   PetscFunctionBegin;
5649566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)c), &rank));
5659566063dSJacob Faibussowitsch   PetscCall(CharacteristicHeapSort(c, c->queue, c->queueSize));
5669566063dSJacob Faibussowitsch   PetscCall(PetscArrayzero(c->needCount, c->numNeighbors));
567bbd56ea5SKarl Rupp   for (i = 0;  i < c->queueSize; i++) c->needCount[c->queue[i].proc]++;
568af33a6ddSJed Brown   c->fillCount[0] = 0;
569af33a6ddSJed Brown   for (n = 1; n < c->numNeighbors; n++) {
5709566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Irecv(&(c->fillCount[n]), 1, MPIU_INT, c->neighbors[n], tag, PetscObjectComm((PetscObject)c), &(c->request[n-1])));
571af33a6ddSJed Brown   }
572af33a6ddSJed Brown   for (n = 1; n < c->numNeighbors; n++) {
5739566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Send(&(c->needCount[n]), 1, MPIU_INT, c->neighbors[n], tag, PetscObjectComm((PetscObject)c)));
574af33a6ddSJed Brown   }
5759566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Waitall(c->numNeighbors-1, c->request, c->status));
576af33a6ddSJed Brown   /* Initialize the remote queue */
577af33a6ddSJed Brown   c->queueLocalMax  = c->localOffsets[0]  = 0;
578af33a6ddSJed Brown   c->queueRemoteMax = c->remoteOffsets[0] = 0;
579af33a6ddSJed Brown   for (n = 1; n < c->numNeighbors; n++) {
580af33a6ddSJed Brown     c->remoteOffsets[n] = c->queueRemoteMax;
581af33a6ddSJed Brown     c->queueRemoteMax  += c->fillCount[n];
582af33a6ddSJed Brown     c->localOffsets[n]  = c->queueLocalMax;
583af33a6ddSJed Brown     c->queueLocalMax   += c->needCount[n];
584af33a6ddSJed Brown   }
585af33a6ddSJed Brown   /* HACK BEGIN */
586bbd56ea5SKarl Rupp   for (n = 1; n < c->numNeighbors; n++) c->localOffsets[n] += c->needCount[0];
587af33a6ddSJed Brown   c->needCount[0] = 0;
588af33a6ddSJed Brown   /* HACK END */
589af33a6ddSJed Brown   if (c->queueRemoteMax) {
5909566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(c->queueRemoteMax, &c->queueRemote));
5910298fd71SBarry Smith   } else c->queueRemote = NULL;
592af33a6ddSJed Brown   c->queueRemoteSize = c->queueRemoteMax;
593af33a6ddSJed Brown 
594af33a6ddSJed Brown   /* Send and Receive requests for values at t_n+1/2, giving the coordinates for interpolation */
595af33a6ddSJed Brown   for (n = 1; n < c->numNeighbors; n++) {
596*63a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(NULL, "Receiving %" PetscInt_FMT " requests for values from proc %d\n", c->fillCount[n], c->neighbors[n]));
5979566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Irecv(&(c->queueRemote[c->remoteOffsets[n]]), c->fillCount[n], c->itemType, c->neighbors[n], tag, PetscObjectComm((PetscObject)c), &(c->request[n-1])));
598af33a6ddSJed Brown   }
599af33a6ddSJed Brown   for (n = 1; n < c->numNeighbors; n++) {
600*63a3b9bcSJacob Faibussowitsch     PetscCall(PetscInfo(NULL, "Sending %" PetscInt_FMT " requests for values from proc %d\n", c->needCount[n], c->neighbors[n]));
6019566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Send(&(c->queue[c->localOffsets[n]]), c->needCount[n], c->itemType, c->neighbors[n], tag, PetscObjectComm((PetscObject)c)));
602af33a6ddSJed Brown   }
603af33a6ddSJed Brown   PetscFunctionReturn(0);
604af33a6ddSJed Brown }
605af33a6ddSJed Brown 
606af33a6ddSJed Brown PetscErrorCode CharacteristicSendCoordinatesEnd(Characteristic c)
607af33a6ddSJed Brown {
608af33a6ddSJed Brown #if 0
609af33a6ddSJed Brown   PetscMPIInt rank;
610af33a6ddSJed Brown   PetscInt    n;
611af33a6ddSJed Brown #endif
612af33a6ddSJed Brown 
613af33a6ddSJed Brown   PetscFunctionBegin;
6149566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Waitall(c->numNeighbors-1, c->request, c->status));
615af33a6ddSJed Brown #if 0
6169566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)c), &rank));
617af33a6ddSJed Brown   for (n = 0; n < c->queueRemoteSize; n++) {
6183c633725SBarry Smith     PetscCheck(c->neighbors[c->queueRemote[n].proc] != rank,PETSC_COMM_SELF,PETSC_ERR_PLIB, "This is messed up, n = %d proc = %d", n, c->queueRemote[n].proc);
619af33a6ddSJed Brown   }
620af33a6ddSJed Brown #endif
621af33a6ddSJed Brown   PetscFunctionReturn(0);
622af33a6ddSJed Brown }
623af33a6ddSJed Brown 
624af33a6ddSJed Brown PetscErrorCode CharacteristicGetValuesBegin(Characteristic c)
625af33a6ddSJed Brown {
626af33a6ddSJed Brown   PetscMPIInt    tag = 121;
627af33a6ddSJed Brown   PetscInt       n;
628af33a6ddSJed Brown 
629af33a6ddSJed Brown   PetscFunctionBegin;
630af33a6ddSJed Brown   /* SEND AND RECIEVE FILLED REQUESTS for velocities at t_n+1/2 */
631af33a6ddSJed Brown   for (n = 1; n < c->numNeighbors; n++) {
6329566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Irecv(&(c->queue[c->localOffsets[n]]), c->needCount[n], c->itemType, c->neighbors[n], tag, PetscObjectComm((PetscObject)c), &(c->request[n-1])));
633af33a6ddSJed Brown   }
634af33a6ddSJed Brown   for (n = 1; n < c->numNeighbors; n++) {
6359566063dSJacob Faibussowitsch     PetscCallMPI(MPI_Send(&(c->queueRemote[c->remoteOffsets[n]]), c->fillCount[n], c->itemType, c->neighbors[n], tag, PetscObjectComm((PetscObject)c)));
636af33a6ddSJed Brown   }
637af33a6ddSJed Brown   PetscFunctionReturn(0);
638af33a6ddSJed Brown }
639af33a6ddSJed Brown 
640af33a6ddSJed Brown PetscErrorCode CharacteristicGetValuesEnd(Characteristic c)
641af33a6ddSJed Brown {
642af33a6ddSJed Brown   PetscFunctionBegin;
6439566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Waitall(c->numNeighbors-1, c->request, c->status));
644af33a6ddSJed Brown   /* Free queue of requests from other procs */
6459566063dSJacob Faibussowitsch   PetscCall(PetscFree(c->queueRemote));
646af33a6ddSJed Brown   PetscFunctionReturn(0);
647af33a6ddSJed Brown }
648af33a6ddSJed Brown 
649af33a6ddSJed Brown /*---------------------------------------------------------------------*/
650af33a6ddSJed Brown /*
651af33a6ddSJed Brown   Based on code from http://linux.wku.edu/~lamonml/algor/sort/heap.html
652af33a6ddSJed Brown */
6530b8f38c8SBarry Smith PetscErrorCode CharacteristicHeapSort(Characteristic c, Queue queue, PetscInt size)
654af33a6ddSJed Brown /*---------------------------------------------------------------------*/
655af33a6ddSJed Brown {
656af33a6ddSJed Brown   CharacteristicPointDA2D temp;
6570b8f38c8SBarry Smith   PetscInt                n;
658af33a6ddSJed Brown 
6590b8f38c8SBarry Smith   PetscFunctionBegin;
660af33a6ddSJed Brown   if (0) { /* Check the order of the queue before sorting */
6619566063dSJacob Faibussowitsch     PetscCall(PetscInfo(NULL, "Before Heap sort\n"));
662af33a6ddSJed Brown     for (n=0; n<size; n++) {
663*63a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo(NULL,"%" PetscInt_FMT " %d\n",n,queue[n].proc));
664af33a6ddSJed Brown     }
665af33a6ddSJed Brown   }
666af33a6ddSJed Brown 
667af33a6ddSJed Brown   /* SORTING PHASE */
6680b8f38c8SBarry Smith   for (n = (size / 2)-1; n >= 0; n--) {
6699566063dSJacob Faibussowitsch     PetscCall(CharacteristicSiftDown(c, queue, n, size-1)); /* Rich had size-1 here, Matt had size*/
6700b8f38c8SBarry Smith   }
671af33a6ddSJed Brown   for (n = size-1; n >= 1; n--) {
672af33a6ddSJed Brown     temp     = queue[0];
673af33a6ddSJed Brown     queue[0] = queue[n];
674af33a6ddSJed Brown     queue[n] = temp;
6759566063dSJacob Faibussowitsch     PetscCall(CharacteristicSiftDown(c, queue, 0, n-1));
676af33a6ddSJed Brown   }
677af33a6ddSJed Brown   if (0) { /* Check the order of the queue after sorting */
6789566063dSJacob Faibussowitsch     PetscCall(PetscInfo(NULL, "Avter  Heap sort\n"));
679af33a6ddSJed Brown     for (n=0; n<size; n++) {
680*63a3b9bcSJacob Faibussowitsch       PetscCall(PetscInfo(NULL,"%" PetscInt_FMT " %d\n",n,queue[n].proc));
681af33a6ddSJed Brown     }
682af33a6ddSJed Brown   }
6830b8f38c8SBarry Smith   PetscFunctionReturn(0);
684af33a6ddSJed Brown }
685af33a6ddSJed Brown 
686af33a6ddSJed Brown /*---------------------------------------------------------------------*/
687af33a6ddSJed Brown /*
688af33a6ddSJed Brown   Based on code from http://linux.wku.edu/~lamonml/algor/sort/heap.html
689af33a6ddSJed Brown */
6900b8f38c8SBarry Smith PetscErrorCode CharacteristicSiftDown(Characteristic c, Queue queue, PetscInt root, PetscInt bottom)
691af33a6ddSJed Brown /*---------------------------------------------------------------------*/
692af33a6ddSJed Brown {
693af33a6ddSJed Brown   PetscBool               done = PETSC_FALSE;
694af33a6ddSJed Brown   PetscInt                maxChild;
695af33a6ddSJed Brown   CharacteristicPointDA2D temp;
696af33a6ddSJed Brown 
697af33a6ddSJed Brown   PetscFunctionBegin;
698af33a6ddSJed Brown   while ((root*2 <= bottom) && (!done)) {
699af33a6ddSJed Brown     if (root*2 == bottom) maxChild = root * 2;
700af33a6ddSJed Brown     else if (queue[root*2].proc > queue[root*2+1].proc) maxChild = root * 2;
701af33a6ddSJed Brown     else maxChild = root * 2 + 1;
702af33a6ddSJed Brown 
703af33a6ddSJed Brown     if (queue[root].proc < queue[maxChild].proc) {
704af33a6ddSJed Brown       temp            = queue[root];
705af33a6ddSJed Brown       queue[root]     = queue[maxChild];
706af33a6ddSJed Brown       queue[maxChild] = temp;
707af33a6ddSJed Brown       root            = maxChild;
708db4deed7SKarl Rupp     } else done = PETSC_TRUE;
709af33a6ddSJed Brown   }
710af33a6ddSJed Brown   PetscFunctionReturn(0);
711af33a6ddSJed Brown }
712af33a6ddSJed Brown 
713af33a6ddSJed Brown /* [center, left, top-left, top, top-right, right, bottom-right, bottom, bottom-left] */
714af33a6ddSJed Brown PetscErrorCode DMDAGetNeighborsRank(DM da, PetscMPIInt neighbors[])
715af33a6ddSJed Brown {
716bff4a2f0SMatthew G. Knepley   DMBoundaryType   bx, by;
717af33a6ddSJed Brown   PetscBool        IPeriodic = PETSC_FALSE, JPeriodic = PETSC_FALSE;
718af33a6ddSJed Brown   MPI_Comm         comm;
719af33a6ddSJed Brown   PetscMPIInt      rank;
720af33a6ddSJed Brown   PetscInt         **procs,pi,pj,pim,pip,pjm,pjp,PI,PJ;
721af33a6ddSJed Brown 
722af33a6ddSJed Brown   PetscFunctionBegin;
7239566063dSJacob Faibussowitsch   PetscCall(PetscObjectGetComm((PetscObject) da, &comm));
7249566063dSJacob Faibussowitsch   PetscCallMPI(MPI_Comm_rank(comm, &rank));
7259566063dSJacob Faibussowitsch   PetscCall(DMDAGetInfo(da, NULL, NULL, NULL, NULL, &PI,&PJ, NULL, NULL, NULL, &bx, &by,NULL, NULL));
726af33a6ddSJed Brown 
727bff4a2f0SMatthew G. Knepley   if (bx == DM_BOUNDARY_PERIODIC) IPeriodic = PETSC_TRUE;
728bff4a2f0SMatthew G. Knepley   if (by == DM_BOUNDARY_PERIODIC) JPeriodic = PETSC_TRUE;
729af33a6ddSJed Brown 
730af33a6ddSJed Brown   neighbors[0] = rank;
731af33a6ddSJed Brown   rank = 0;
7329566063dSJacob Faibussowitsch   PetscCall(PetscMalloc1(PJ,&procs));
733af33a6ddSJed Brown   for (pj=0; pj<PJ; pj++) {
7349566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(PI,&(procs[pj])));
735af33a6ddSJed Brown     for (pi=0; pi<PI; pi++) {
736af33a6ddSJed Brown       procs[pj][pi] = rank;
737af33a6ddSJed Brown       rank++;
738af33a6ddSJed Brown     }
739af33a6ddSJed Brown   }
740af33a6ddSJed Brown 
741af33a6ddSJed Brown   pi  = neighbors[0] % PI;
742af33a6ddSJed Brown   pj  = neighbors[0] / PI;
743af33a6ddSJed Brown   pim = pi-1;  if (pim<0) pim=PI-1;
744af33a6ddSJed Brown   pip = (pi+1)%PI;
745af33a6ddSJed Brown   pjm = pj-1;  if (pjm<0) pjm=PJ-1;
746af33a6ddSJed Brown   pjp = (pj+1)%PJ;
747af33a6ddSJed Brown 
748af33a6ddSJed Brown   neighbors[1] = procs[pj] [pim];
749af33a6ddSJed Brown   neighbors[2] = procs[pjp][pim];
750af33a6ddSJed Brown   neighbors[3] = procs[pjp][pi];
751af33a6ddSJed Brown   neighbors[4] = procs[pjp][pip];
752af33a6ddSJed Brown   neighbors[5] = procs[pj] [pip];
753af33a6ddSJed Brown   neighbors[6] = procs[pjm][pip];
754af33a6ddSJed Brown   neighbors[7] = procs[pjm][pi];
755af33a6ddSJed Brown   neighbors[8] = procs[pjm][pim];
756af33a6ddSJed Brown 
757af33a6ddSJed Brown   if (!IPeriodic) {
758af33a6ddSJed Brown     if (pi==0)    neighbors[1]=neighbors[2]=neighbors[8]=neighbors[0];
759af33a6ddSJed Brown     if (pi==PI-1) neighbors[4]=neighbors[5]=neighbors[6]=neighbors[0];
760af33a6ddSJed Brown   }
761af33a6ddSJed Brown 
762af33a6ddSJed Brown   if (!JPeriodic) {
763af33a6ddSJed Brown     if (pj==0)    neighbors[6]=neighbors[7]=neighbors[8]=neighbors[0];
764af33a6ddSJed Brown     if (pj==PJ-1) neighbors[2]=neighbors[3]=neighbors[4]=neighbors[0];
765af33a6ddSJed Brown   }
766af33a6ddSJed Brown 
767af33a6ddSJed Brown   for (pj = 0; pj < PJ; pj++) {
7689566063dSJacob Faibussowitsch     PetscCall(PetscFree(procs[pj]));
769af33a6ddSJed Brown   }
7709566063dSJacob Faibussowitsch   PetscCall(PetscFree(procs));
771af33a6ddSJed Brown   PetscFunctionReturn(0);
772af33a6ddSJed Brown }
773af33a6ddSJed Brown 
774af33a6ddSJed Brown /*
775af33a6ddSJed Brown   SUBDOMAIN NEIGHBORHOOD PROCESS MAP:
776af33a6ddSJed Brown     2 | 3 | 4
777af33a6ddSJed Brown     __|___|__
778af33a6ddSJed Brown     1 | 0 | 5
779af33a6ddSJed Brown     __|___|__
780af33a6ddSJed Brown     8 | 7 | 6
781af33a6ddSJed Brown       |   |
782af33a6ddSJed Brown */
7831cc8b206SBarry Smith PetscInt DMDAGetNeighborRelative(DM da, PetscReal ir, PetscReal jr)
784af33a6ddSJed Brown {
785af33a6ddSJed Brown   DMDALocalInfo  info;
7861cc8b206SBarry Smith   PetscReal      is,ie,js,je;
787af33a6ddSJed Brown 
7889566063dSJacob Faibussowitsch   PetscCall(DMDAGetLocalInfo(da, &info));
7891cc8b206SBarry Smith   is   = (PetscReal) info.xs - 0.5; ie = (PetscReal) info.xs + info.xm - 0.5;
7901cc8b206SBarry Smith   js   = (PetscReal) info.ys - 0.5; je = (PetscReal) info.ys + info.ym - 0.5;
791af33a6ddSJed Brown 
792af33a6ddSJed Brown   if (ir >= is && ir <= ie) { /* center column */
793bbd56ea5SKarl Rupp     if (jr >= js && jr <= je) return 0;
794bbd56ea5SKarl Rupp     else if (jr < js)         return 7;
795bbd56ea5SKarl Rupp     else                      return 3;
796af33a6ddSJed Brown   } else if (ir < is) {     /* left column */
797bbd56ea5SKarl Rupp     if (jr >= js && jr <= je) return 1;
798bbd56ea5SKarl Rupp     else if (jr < js)         return 8;
799bbd56ea5SKarl Rupp     else                      return 2;
800af33a6ddSJed Brown   } else {                  /* right column */
801bbd56ea5SKarl Rupp     if (jr >= js && jr <= je) return 5;
802bbd56ea5SKarl Rupp     else if (jr < js)         return 6;
803bbd56ea5SKarl Rupp     else                      return 4;
804af33a6ddSJed Brown   }
805af33a6ddSJed Brown }
806