xref: /petsc/src/ts/characteristic/interface/characteristic.c (revision 98921bda46e76d7aaed9e0138c5ff9d0ce93f355)
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   PetscErrorCode ierr;
27af33a6ddSJed Brown 
28af33a6ddSJed Brown   PetscFunctionBegin;
29af33a6ddSJed Brown   PetscValidHeaderSpecific(c, CHARACTERISTIC_CLASSID, 1);
30af33a6ddSJed Brown   if (!viewer) {
31ce94432eSBarry Smith     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)c),&viewer);CHKERRQ(ierr);
32af33a6ddSJed Brown   }
33af33a6ddSJed Brown   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
34af33a6ddSJed Brown   PetscCheckSameComm(c, 1, viewer, 2);
35af33a6ddSJed Brown 
36251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
37af33a6ddSJed Brown   if (!iascii) {
38af33a6ddSJed Brown     if (c->ops->view) {
39af33a6ddSJed Brown       ierr = (*c->ops->view)(c, viewer);CHKERRQ(ierr);
40af33a6ddSJed Brown     }
41af33a6ddSJed Brown   }
42af33a6ddSJed Brown   PetscFunctionReturn(0);
43af33a6ddSJed Brown }
44af33a6ddSJed Brown 
456bf464f9SBarry Smith PetscErrorCode CharacteristicDestroy(Characteristic *c)
46af33a6ddSJed Brown {
47af33a6ddSJed Brown   PetscErrorCode ierr;
48af33a6ddSJed Brown 
49af33a6ddSJed Brown   PetscFunctionBegin;
506bf464f9SBarry Smith   if (!*c) PetscFunctionReturn(0);
516bf464f9SBarry Smith   PetscValidHeaderSpecific(*c, CHARACTERISTIC_CLASSID, 1);
526bf464f9SBarry Smith   if (--((PetscObject)(*c))->refct > 0) PetscFunctionReturn(0);
53af33a6ddSJed Brown 
546bf464f9SBarry Smith   if ((*c)->ops->destroy) {
556bf464f9SBarry Smith     ierr = (*(*c)->ops->destroy)((*c));CHKERRQ(ierr);
56af33a6ddSJed Brown   }
57ffc4695bSBarry Smith   ierr = MPI_Type_free(&(*c)->itemType);CHKERRMPI(ierr);
586bf464f9SBarry Smith   ierr = PetscFree((*c)->queue);CHKERRQ(ierr);
596bf464f9SBarry Smith   ierr = PetscFree((*c)->queueLocal);CHKERRQ(ierr);
606bf464f9SBarry Smith   ierr = PetscFree((*c)->queueRemote);CHKERRQ(ierr);
616bf464f9SBarry Smith   ierr = PetscFree((*c)->neighbors);CHKERRQ(ierr);
626bf464f9SBarry Smith   ierr = PetscFree((*c)->needCount);CHKERRQ(ierr);
636bf464f9SBarry Smith   ierr = PetscFree((*c)->localOffsets);CHKERRQ(ierr);
646bf464f9SBarry Smith   ierr = PetscFree((*c)->fillCount);CHKERRQ(ierr);
656bf464f9SBarry Smith   ierr = PetscFree((*c)->remoteOffsets);CHKERRQ(ierr);
666bf464f9SBarry Smith   ierr = PetscFree((*c)->request);CHKERRQ(ierr);
676bf464f9SBarry Smith   ierr = PetscFree((*c)->status);CHKERRQ(ierr);
68af33a6ddSJed Brown   ierr = PetscHeaderDestroy(c);CHKERRQ(ierr);
69af33a6ddSJed Brown   PetscFunctionReturn(0);
70af33a6ddSJed Brown }
71af33a6ddSJed Brown 
72af33a6ddSJed Brown PetscErrorCode CharacteristicCreate(MPI_Comm comm, Characteristic *c)
73af33a6ddSJed Brown {
74af33a6ddSJed Brown   Characteristic newC;
75af33a6ddSJed Brown   PetscErrorCode ierr;
76af33a6ddSJed Brown 
77af33a6ddSJed Brown   PetscFunctionBegin;
78af33a6ddSJed Brown   PetscValidPointer(c, 2);
790298fd71SBarry Smith   *c = NULL;
80607a6623SBarry Smith   ierr = CharacteristicInitializePackage();CHKERRQ(ierr);
81af33a6ddSJed Brown 
821b266c99SBarry Smith   ierr = PetscHeaderCreate(newC, CHARACTERISTIC_CLASSID, "Characteristic", "Characteristic", "Characteristic", comm, CharacteristicDestroy, CharacteristicView);CHKERRQ(ierr);
83af33a6ddSJed Brown   *c   = newC;
84af33a6ddSJed Brown 
85af33a6ddSJed Brown   newC->structured          = PETSC_TRUE;
86af33a6ddSJed Brown   newC->numIds              = 0;
870298fd71SBarry Smith   newC->velocityDA          = NULL;
880298fd71SBarry Smith   newC->velocity            = NULL;
890298fd71SBarry Smith   newC->velocityOld         = NULL;
90af33a6ddSJed Brown   newC->numVelocityComp     = 0;
910298fd71SBarry Smith   newC->velocityComp        = NULL;
920298fd71SBarry Smith   newC->velocityInterp      = NULL;
930298fd71SBarry Smith   newC->velocityInterpLocal = NULL;
940298fd71SBarry Smith   newC->velocityCtx         = NULL;
950298fd71SBarry Smith   newC->fieldDA             = NULL;
960298fd71SBarry Smith   newC->field               = NULL;
97af33a6ddSJed Brown   newC->numFieldComp        = 0;
980298fd71SBarry Smith   newC->fieldComp           = NULL;
990298fd71SBarry Smith   newC->fieldInterp         = NULL;
1000298fd71SBarry Smith   newC->fieldInterpLocal    = NULL;
1010298fd71SBarry Smith   newC->fieldCtx            = NULL;
1020298fd71SBarry Smith   newC->itemType            = 0;
1030298fd71SBarry Smith   newC->queue               = NULL;
104af33a6ddSJed Brown   newC->queueSize           = 0;
105af33a6ddSJed Brown   newC->queueMax            = 0;
1060298fd71SBarry Smith   newC->queueLocal          = NULL;
107af33a6ddSJed Brown   newC->queueLocalSize      = 0;
108af33a6ddSJed Brown   newC->queueLocalMax       = 0;
1090298fd71SBarry Smith   newC->queueRemote         = NULL;
110af33a6ddSJed Brown   newC->queueRemoteSize     = 0;
111af33a6ddSJed Brown   newC->queueRemoteMax      = 0;
112af33a6ddSJed Brown   newC->numNeighbors        = 0;
1130298fd71SBarry Smith   newC->neighbors           = NULL;
1140298fd71SBarry Smith   newC->needCount           = NULL;
1150298fd71SBarry Smith   newC->localOffsets        = NULL;
1160298fd71SBarry Smith   newC->fillCount           = NULL;
1170298fd71SBarry Smith   newC->remoteOffsets       = NULL;
1180298fd71SBarry Smith   newC->request             = NULL;
1190298fd71SBarry Smith   newC->status              = NULL;
120af33a6ddSJed Brown   PetscFunctionReturn(0);
121af33a6ddSJed Brown }
122af33a6ddSJed Brown 
123af33a6ddSJed Brown /*@C
124af33a6ddSJed Brown    CharacteristicSetType - Builds Characteristic for a particular solver.
125af33a6ddSJed Brown 
126af33a6ddSJed Brown    Logically Collective on Characteristic
127af33a6ddSJed Brown 
128af33a6ddSJed Brown    Input Parameters:
129af33a6ddSJed Brown +  c    - the method of characteristics context
130af33a6ddSJed Brown -  type - a known method
131af33a6ddSJed Brown 
132af33a6ddSJed Brown    Options Database Key:
133af33a6ddSJed Brown .  -characteristic_type <method> - Sets the method; use -help for a list
134af33a6ddSJed Brown     of available methods
135af33a6ddSJed Brown 
136af33a6ddSJed Brown    Notes:
13730a76a96SBarry Smith    See "include/petsccharacteristic.h" for available methods
138af33a6ddSJed Brown 
139af33a6ddSJed Brown   Normally, it is best to use the CharacteristicSetFromOptions() command and
140af33a6ddSJed Brown   then set the Characteristic type from the options database rather than by using
141af33a6ddSJed Brown   this routine.  Using the options database provides the user with
142af33a6ddSJed Brown   maximum flexibility in evaluating the many different Krylov methods.
143af33a6ddSJed Brown   The CharacteristicSetType() routine is provided for those situations where it
144af33a6ddSJed Brown   is necessary to set the iterative solver independently of the command
145af33a6ddSJed Brown   line or options database.  This might be the case, for example, when
146af33a6ddSJed Brown   the choice of iterative solver changes during the execution of the
147af33a6ddSJed Brown   program, and the user's application is taking responsibility for
148af33a6ddSJed Brown   choosing the appropriate method.  In other words, this routine is
149af33a6ddSJed Brown   not for beginners.
150af33a6ddSJed Brown 
151af33a6ddSJed Brown   Level: intermediate
152af33a6ddSJed Brown 
153af33a6ddSJed Brown .seealso: CharacteristicType
154af33a6ddSJed Brown 
155af33a6ddSJed Brown @*/
15619fd82e9SBarry Smith PetscErrorCode CharacteristicSetType(Characteristic c, CharacteristicType type)
157af33a6ddSJed Brown {
158af33a6ddSJed Brown   PetscErrorCode ierr, (*r)(Characteristic);
159af33a6ddSJed Brown   PetscBool      match;
160af33a6ddSJed Brown 
161af33a6ddSJed Brown   PetscFunctionBegin;
162af33a6ddSJed Brown   PetscValidHeaderSpecific(c, CHARACTERISTIC_CLASSID, 1);
163af33a6ddSJed Brown   PetscValidCharPointer(type, 2);
164af33a6ddSJed Brown 
165251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject) c, type, &match);CHKERRQ(ierr);
166af33a6ddSJed Brown   if (match) PetscFunctionReturn(0);
167af33a6ddSJed Brown 
168af33a6ddSJed Brown   if (c->data) {
169af33a6ddSJed Brown     /* destroy the old private Characteristic context */
170af33a6ddSJed Brown     ierr = (*c->ops->destroy)(c);CHKERRQ(ierr);
1710298fd71SBarry Smith     c->ops->destroy = NULL;
1722120983fSLisandro Dalcin     c->data         = NULL;
173af33a6ddSJed Brown   }
174af33a6ddSJed Brown 
1751c9cd337SJed Brown   ierr =  PetscFunctionListFind(CharacteristicList,type,&r);CHKERRQ(ierr);
176*98921bdaSJacob Faibussowitsch   if (!r) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown Characteristic type given: %s", type);
177af33a6ddSJed Brown   c->setupcalled = 0;
178af33a6ddSJed Brown   ierr = (*r)(c);CHKERRQ(ierr);
179af33a6ddSJed Brown   ierr = PetscObjectChangeTypeName((PetscObject) c, type);CHKERRQ(ierr);
180af33a6ddSJed Brown   PetscFunctionReturn(0);
181af33a6ddSJed Brown }
182af33a6ddSJed Brown 
183af33a6ddSJed Brown /*@
184af33a6ddSJed Brown    CharacteristicSetUp - Sets up the internal data structures for the
185af33a6ddSJed Brown    later use of an iterative solver.
186af33a6ddSJed Brown 
187af33a6ddSJed Brown    Collective on Characteristic
188af33a6ddSJed Brown 
189af33a6ddSJed Brown    Input Parameter:
190af33a6ddSJed Brown .  ksp   - iterative context obtained from CharacteristicCreate()
191af33a6ddSJed Brown 
192af33a6ddSJed Brown    Level: developer
193af33a6ddSJed Brown 
194af33a6ddSJed Brown .seealso: CharacteristicCreate(), CharacteristicSolve(), CharacteristicDestroy()
195af33a6ddSJed Brown @*/
196af33a6ddSJed Brown PetscErrorCode CharacteristicSetUp(Characteristic c)
197af33a6ddSJed Brown {
198af33a6ddSJed Brown   PetscErrorCode ierr;
199af33a6ddSJed Brown 
200af33a6ddSJed Brown   PetscFunctionBegin;
201af33a6ddSJed Brown   PetscValidHeaderSpecific(c, CHARACTERISTIC_CLASSID, 1);
202af33a6ddSJed Brown 
203af33a6ddSJed Brown   if (!((PetscObject)c)->type_name) {
204af33a6ddSJed Brown     ierr = CharacteristicSetType(c, CHARACTERISTICDA);CHKERRQ(ierr);
205af33a6ddSJed Brown   }
206af33a6ddSJed Brown 
207af33a6ddSJed Brown   if (c->setupcalled == 2) PetscFunctionReturn(0);
208af33a6ddSJed Brown 
2092120983fSLisandro Dalcin   ierr = PetscLogEventBegin(CHARACTERISTIC_SetUp,c,NULL,NULL,NULL);CHKERRQ(ierr);
210af33a6ddSJed Brown   if (!c->setupcalled) {
211af33a6ddSJed Brown     ierr = (*c->ops->setup)(c);CHKERRQ(ierr);
212af33a6ddSJed Brown   }
2132120983fSLisandro Dalcin   ierr = PetscLogEventEnd(CHARACTERISTIC_SetUp,c,NULL,NULL,NULL);CHKERRQ(ierr);
214af33a6ddSJed Brown   c->setupcalled = 2;
215af33a6ddSJed Brown   PetscFunctionReturn(0);
216af33a6ddSJed Brown }
217af33a6ddSJed Brown 
218af33a6ddSJed Brown /*@C
2191c84c290SBarry Smith   CharacteristicRegister -  Adds a solver to the method of characteristics package.
2201c84c290SBarry Smith 
2211c84c290SBarry Smith    Not Collective
2221c84c290SBarry Smith 
2231c84c290SBarry Smith    Input Parameters:
2241c84c290SBarry Smith +  name_solver - name of a new user-defined solver
2251c84c290SBarry Smith -  routine_create - routine to create method context
2261c84c290SBarry Smith 
2271c84c290SBarry Smith   Sample usage:
2281c84c290SBarry Smith .vb
229bdf89e91SBarry Smith     CharacteristicRegister("my_char", MyCharCreate);
2301c84c290SBarry Smith .ve
2311c84c290SBarry Smith 
2321c84c290SBarry Smith   Then, your Characteristic type can be chosen with the procedural interface via
2331c84c290SBarry Smith .vb
2341c84c290SBarry Smith     CharacteristicCreate(MPI_Comm, Characteristic* &char);
2351c84c290SBarry Smith     CharacteristicSetType(char,"my_char");
2361c84c290SBarry Smith .ve
2371c84c290SBarry Smith    or at runtime via the option
2381c84c290SBarry Smith .vb
2391c84c290SBarry Smith     -characteristic_type my_char
2401c84c290SBarry Smith .ve
2411c84c290SBarry Smith 
2421c84c290SBarry Smith    Notes:
2431c84c290SBarry Smith    CharacteristicRegister() may be called multiple times to add several user-defined solvers.
2441c84c290SBarry Smith 
2451c84c290SBarry Smith .seealso: CharacteristicRegisterAll(), CharacteristicRegisterDestroy()
246af33a6ddSJed Brown 
247af33a6ddSJed Brown   Level: advanced
248af33a6ddSJed Brown @*/
249bdf89e91SBarry Smith PetscErrorCode CharacteristicRegister(const char sname[],PetscErrorCode (*function)(Characteristic))
250af33a6ddSJed Brown {
251af33a6ddSJed Brown   PetscErrorCode ierr;
252af33a6ddSJed Brown 
253af33a6ddSJed Brown   PetscFunctionBegin;
2541d36bdfdSBarry Smith   ierr = CharacteristicInitializePackage();CHKERRQ(ierr);
255a240a19fSJed Brown   ierr = PetscFunctionListAdd(&CharacteristicList,sname,function);CHKERRQ(ierr);
256af33a6ddSJed Brown   PetscFunctionReturn(0);
257af33a6ddSJed Brown }
258af33a6ddSJed Brown 
259af33a6ddSJed 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)
260af33a6ddSJed Brown {
261af33a6ddSJed Brown   PetscFunctionBegin;
262af33a6ddSJed Brown   c->velocityDA      = da;
263af33a6ddSJed Brown   c->velocity        = v;
264af33a6ddSJed Brown   c->velocityOld     = vOld;
265af33a6ddSJed Brown   c->numVelocityComp = numComponents;
266af33a6ddSJed Brown   c->velocityComp    = components;
267af33a6ddSJed Brown   c->velocityInterp  = interp;
268af33a6ddSJed Brown   c->velocityCtx     = ctx;
269af33a6ddSJed Brown   PetscFunctionReturn(0);
270af33a6ddSJed Brown }
271af33a6ddSJed Brown 
272af33a6ddSJed 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)
273af33a6ddSJed Brown {
274af33a6ddSJed Brown   PetscFunctionBegin;
275af33a6ddSJed Brown   c->velocityDA          = da;
276af33a6ddSJed Brown   c->velocity            = v;
277af33a6ddSJed Brown   c->velocityOld         = vOld;
278af33a6ddSJed Brown   c->numVelocityComp     = numComponents;
279af33a6ddSJed Brown   c->velocityComp        = components;
280af33a6ddSJed Brown   c->velocityInterpLocal = interp;
281af33a6ddSJed Brown   c->velocityCtx         = ctx;
282af33a6ddSJed Brown   PetscFunctionReturn(0);
283af33a6ddSJed Brown }
284af33a6ddSJed Brown 
285af33a6ddSJed Brown PetscErrorCode CharacteristicSetFieldInterpolation(Characteristic c, DM da, Vec v, PetscInt numComponents, PetscInt components[], PetscErrorCode (*interp)(Vec, PetscReal[], PetscInt, PetscInt[], PetscScalar[], void*), void *ctx)
286af33a6ddSJed Brown {
287af33a6ddSJed Brown   PetscFunctionBegin;
288af33a6ddSJed Brown #if 0
289af33a6ddSJed Brown   if (numComponents > 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP, "Fields with more than 2 components are not supported. Send mail to petsc-maint@mcs.anl.gov.");
290af33a6ddSJed Brown #endif
291af33a6ddSJed Brown   c->fieldDA      = da;
292af33a6ddSJed Brown   c->field        = v;
293af33a6ddSJed Brown   c->numFieldComp = numComponents;
294af33a6ddSJed Brown   c->fieldComp    = components;
295af33a6ddSJed Brown   c->fieldInterp  = interp;
296af33a6ddSJed Brown   c->fieldCtx     = ctx;
297af33a6ddSJed Brown   PetscFunctionReturn(0);
298af33a6ddSJed Brown }
299af33a6ddSJed Brown 
300af33a6ddSJed Brown PetscErrorCode CharacteristicSetFieldInterpolationLocal(Characteristic c, DM da, Vec v, PetscInt numComponents, PetscInt components[], PetscErrorCode (*interp)(void*, PetscReal[], PetscInt, PetscInt[], PetscScalar [], void*), void *ctx)
301af33a6ddSJed Brown {
302af33a6ddSJed Brown   PetscFunctionBegin;
303af33a6ddSJed Brown #if 0
304af33a6ddSJed Brown   if (numComponents > 2) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP, "Fields with more than 2 components are not supported. Send mail to petsc-maint@mcs.anl.gov.");
305af33a6ddSJed Brown #endif
306af33a6ddSJed Brown   c->fieldDA          = da;
307af33a6ddSJed Brown   c->field            = v;
308af33a6ddSJed Brown   c->numFieldComp     = numComponents;
309af33a6ddSJed Brown   c->fieldComp        = components;
310af33a6ddSJed Brown   c->fieldInterpLocal = interp;
311af33a6ddSJed Brown   c->fieldCtx         = ctx;
312af33a6ddSJed Brown   PetscFunctionReturn(0);
313af33a6ddSJed Brown }
314af33a6ddSJed Brown 
315af33a6ddSJed Brown PetscErrorCode CharacteristicSolve(Characteristic c, PetscReal dt, Vec solution)
316af33a6ddSJed Brown {
317af33a6ddSJed Brown   CharacteristicPointDA2D Qi;
318af33a6ddSJed Brown   DM                      da = c->velocityDA;
319af33a6ddSJed Brown   Vec                     velocityLocal, velocityLocalOld;
320af33a6ddSJed Brown   Vec                     fieldLocal;
321af33a6ddSJed Brown   DMDALocalInfo           info;
322af33a6ddSJed Brown   PetscScalar             **solArray;
323af33a6ddSJed Brown   void                    *velocityArray;
324af33a6ddSJed Brown   void                    *velocityArrayOld;
325af33a6ddSJed Brown   void                    *fieldArray;
3261cc8b206SBarry Smith   PetscScalar             *interpIndices;
3271cc8b206SBarry Smith   PetscScalar             *velocityValues, *velocityValuesOld;
3281cc8b206SBarry Smith   PetscScalar             *fieldValues;
329af33a6ddSJed Brown   PetscMPIInt             rank;
330af33a6ddSJed Brown   PetscInt                dim;
331af33a6ddSJed Brown   PetscMPIInt             neighbors[9];
332af33a6ddSJed Brown   PetscInt                dof;
333af33a6ddSJed Brown   PetscInt                gx, gy;
334af33a6ddSJed Brown   PetscInt                n, is, ie, js, je, comp;
335af33a6ddSJed Brown   PetscErrorCode          ierr;
336af33a6ddSJed Brown 
337af33a6ddSJed Brown   PetscFunctionBegin;
338af33a6ddSJed Brown   c->queueSize = 0;
339ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)c), &rank);CHKERRMPI(ierr);
340af33a6ddSJed Brown   ierr = DMDAGetNeighborsRank(da, neighbors);CHKERRQ(ierr);
341af33a6ddSJed Brown   ierr = CharacteristicSetNeighbors(c, 9, neighbors);CHKERRQ(ierr);
342af33a6ddSJed Brown   ierr = CharacteristicSetUp(c);CHKERRQ(ierr);
343af33a6ddSJed Brown   /* global and local grid info */
3442120983fSLisandro Dalcin   ierr = DMDAGetInfo(da, &dim, &gx, &gy, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr);
345af33a6ddSJed Brown   ierr = DMDAGetLocalInfo(da, &info);CHKERRQ(ierr);
346af33a6ddSJed Brown   is   = info.xs;          ie   = info.xs+info.xm;
347af33a6ddSJed Brown   js   = info.ys;          je   = info.ys+info.ym;
348af33a6ddSJed Brown   /* Allocation */
349785e854fSJed Brown   ierr = PetscMalloc1(dim,                &interpIndices);CHKERRQ(ierr);
350785e854fSJed Brown   ierr = PetscMalloc1(c->numVelocityComp, &velocityValues);CHKERRQ(ierr);
351785e854fSJed Brown   ierr = PetscMalloc1(c->numVelocityComp, &velocityValuesOld);CHKERRQ(ierr);
352785e854fSJed Brown   ierr = PetscMalloc1(c->numFieldComp,    &fieldValues);CHKERRQ(ierr);
3532120983fSLisandro Dalcin   ierr = PetscLogEventBegin(CHARACTERISTIC_Solve,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
354af33a6ddSJed Brown 
355af33a6ddSJed Brown   /* -----------------------------------------------------------------------
356af33a6ddSJed Brown      PART 1, AT t-dt/2
357af33a6ddSJed Brown      -----------------------------------------------------------------------*/
3582120983fSLisandro Dalcin   ierr = PetscLogEventBegin(CHARACTERISTIC_QueueSetup,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
359af33a6ddSJed Brown   /* GET POSITION AT HALF TIME IN THE PAST */
360af33a6ddSJed Brown   if (c->velocityInterpLocal) {
361af33a6ddSJed Brown     ierr = DMGetLocalVector(c->velocityDA, &velocityLocal);CHKERRQ(ierr);
362af33a6ddSJed Brown     ierr = DMGetLocalVector(c->velocityDA, &velocityLocalOld);CHKERRQ(ierr);
363af33a6ddSJed Brown     ierr = DMGlobalToLocalBegin(c->velocityDA, c->velocity, INSERT_VALUES, velocityLocal);CHKERRQ(ierr);
364af33a6ddSJed Brown     ierr = DMGlobalToLocalEnd(c->velocityDA, c->velocity, INSERT_VALUES, velocityLocal);CHKERRQ(ierr);
365af33a6ddSJed Brown     ierr = DMGlobalToLocalBegin(c->velocityDA, c->velocityOld, INSERT_VALUES, velocityLocalOld);CHKERRQ(ierr);
366af33a6ddSJed Brown     ierr = DMGlobalToLocalEnd(c->velocityDA, c->velocityOld, INSERT_VALUES, velocityLocalOld);CHKERRQ(ierr);
367af33a6ddSJed Brown     ierr = DMDAVecGetArray(c->velocityDA, velocityLocal,    &velocityArray);CHKERRQ(ierr);
368af33a6ddSJed Brown     ierr = DMDAVecGetArray(c->velocityDA, velocityLocalOld, &velocityArrayOld);CHKERRQ(ierr);
369af33a6ddSJed Brown   }
3700298fd71SBarry Smith   ierr = PetscInfo(NULL, "Calculating position at t_{n - 1/2}\n");CHKERRQ(ierr);
371af33a6ddSJed Brown   for (Qi.j = js; Qi.j < je; Qi.j++) {
372af33a6ddSJed Brown     for (Qi.i = is; Qi.i < ie; Qi.i++) {
373af33a6ddSJed Brown       interpIndices[0] = Qi.i;
374af33a6ddSJed Brown       interpIndices[1] = Qi.j;
37561ba4676SBarry Smith       if (c->velocityInterpLocal) {ierr = c->velocityInterpLocal(velocityArray, interpIndices, c->numVelocityComp, c->velocityComp, velocityValues, c->velocityCtx);CHKERRQ(ierr);}
37661ba4676SBarry Smith       else {ierr = c->velocityInterp(c->velocity, interpIndices, c->numVelocityComp, c->velocityComp, velocityValues, c->velocityCtx);CHKERRQ(ierr);}
377af33a6ddSJed Brown       Qi.x = Qi.i - velocityValues[0]*dt/2.0;
378af33a6ddSJed Brown       Qi.y = Qi.j - velocityValues[1]*dt/2.0;
379af33a6ddSJed Brown 
380af33a6ddSJed Brown       /* Determine whether the position at t - dt/2 is local */
381af33a6ddSJed Brown       Qi.proc = DMDAGetNeighborRelative(da, Qi.x, Qi.y);
382af33a6ddSJed Brown 
383af33a6ddSJed Brown       /* Check for Periodic boundaries and move all periodic points back onto the domain */
384af33a6ddSJed Brown       ierr = DMDAMapCoordsToPeriodicDomain(da,&(Qi.x),&(Qi.y));CHKERRQ(ierr);
385af33a6ddSJed Brown       ierr = CharacteristicAddPoint(c, &Qi);CHKERRQ(ierr);
386af33a6ddSJed Brown     }
387af33a6ddSJed Brown   }
3882120983fSLisandro Dalcin   ierr = PetscLogEventEnd(CHARACTERISTIC_QueueSetup,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
389af33a6ddSJed Brown 
3902120983fSLisandro Dalcin   ierr = PetscLogEventBegin(CHARACTERISTIC_HalfTimeExchange,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
391af33a6ddSJed Brown   ierr = CharacteristicSendCoordinatesBegin(c);CHKERRQ(ierr);
3922120983fSLisandro Dalcin   ierr = PetscLogEventEnd(CHARACTERISTIC_HalfTimeExchange,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
393af33a6ddSJed Brown 
3942120983fSLisandro Dalcin   ierr = PetscLogEventBegin(CHARACTERISTIC_HalfTimeLocal,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
395af33a6ddSJed Brown   /* Calculate velocity at t_n+1/2 (local values) */
3960298fd71SBarry Smith   ierr = PetscInfo(NULL, "Calculating local velocities at t_{n - 1/2}\n");CHKERRQ(ierr);
397af33a6ddSJed Brown   for (n = 0; n < c->queueSize; n++) {
398af33a6ddSJed Brown     Qi = c->queue[n];
399af33a6ddSJed Brown     if (c->neighbors[Qi.proc] == rank) {
400af33a6ddSJed Brown       interpIndices[0] = Qi.x;
401af33a6ddSJed Brown       interpIndices[1] = Qi.y;
402af33a6ddSJed Brown       if (c->velocityInterpLocal) {
40361ba4676SBarry Smith         ierr = c->velocityInterpLocal(velocityArray,    interpIndices, c->numVelocityComp, c->velocityComp, velocityValues, c->velocityCtx);CHKERRQ(ierr);
40461ba4676SBarry Smith         ierr = c->velocityInterpLocal(velocityArrayOld, interpIndices, c->numVelocityComp, c->velocityComp, velocityValuesOld, c->velocityCtx);CHKERRQ(ierr);
405af33a6ddSJed Brown       } else {
40661ba4676SBarry Smith         ierr = c->velocityInterp(c->velocity,    interpIndices, c->numVelocityComp, c->velocityComp, velocityValues, c->velocityCtx);CHKERRQ(ierr);
40761528463SBarry Smith         ierr = c->velocityInterp(c->velocityOld, interpIndices, c->numVelocityComp, c->velocityComp, velocityValuesOld, c->velocityCtx);CHKERRQ(ierr);
408af33a6ddSJed Brown       }
409af33a6ddSJed Brown       Qi.x = 0.5*(velocityValues[0] + velocityValuesOld[0]);
410af33a6ddSJed Brown       Qi.y = 0.5*(velocityValues[1] + velocityValuesOld[1]);
411af33a6ddSJed Brown     }
412af33a6ddSJed Brown     c->queue[n] = Qi;
413af33a6ddSJed Brown   }
4142120983fSLisandro Dalcin   ierr = PetscLogEventEnd(CHARACTERISTIC_HalfTimeLocal,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
415af33a6ddSJed Brown 
4162120983fSLisandro Dalcin   ierr = PetscLogEventBegin(CHARACTERISTIC_HalfTimeExchange,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
417af33a6ddSJed Brown   ierr = CharacteristicSendCoordinatesEnd(c);CHKERRQ(ierr);
4182120983fSLisandro Dalcin   ierr = PetscLogEventEnd(CHARACTERISTIC_HalfTimeExchange,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
419af33a6ddSJed Brown 
420af33a6ddSJed Brown   /* Calculate velocity at t_n+1/2 (fill remote requests) */
4212120983fSLisandro Dalcin   ierr = PetscLogEventBegin(CHARACTERISTIC_HalfTimeRemote,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
4220298fd71SBarry Smith   ierr = PetscInfo1(NULL, "Calculating %d remote velocities at t_{n - 1/2}\n", c->queueRemoteSize);CHKERRQ(ierr);
423af33a6ddSJed Brown   for (n = 0; n < c->queueRemoteSize; n++) {
424af33a6ddSJed Brown     Qi = c->queueRemote[n];
425af33a6ddSJed Brown     interpIndices[0] = Qi.x;
426af33a6ddSJed Brown     interpIndices[1] = Qi.y;
427af33a6ddSJed Brown     if (c->velocityInterpLocal) {
42861ba4676SBarry Smith       ierr = c->velocityInterpLocal(velocityArray,    interpIndices, c->numVelocityComp, c->velocityComp, velocityValues,    c->velocityCtx);CHKERRQ(ierr);
42961ba4676SBarry Smith       ierr = c->velocityInterpLocal(velocityArrayOld, interpIndices, c->numVelocityComp, c->velocityComp, velocityValuesOld, c->velocityCtx);CHKERRQ(ierr);
430af33a6ddSJed Brown     } else {
43161ba4676SBarry Smith       ierr = c->velocityInterp(c->velocity,    interpIndices, c->numVelocityComp, c->velocityComp, velocityValues,    c->velocityCtx);CHKERRQ(ierr);
43261ba4676SBarry Smith       ierr = c->velocityInterp(c->velocityOld, interpIndices, c->numVelocityComp, c->velocityComp, velocityValuesOld, c->velocityCtx);CHKERRQ(ierr);
433af33a6ddSJed Brown     }
434af33a6ddSJed Brown     Qi.x = 0.5*(velocityValues[0] + velocityValuesOld[0]);
435af33a6ddSJed Brown     Qi.y = 0.5*(velocityValues[1] + velocityValuesOld[1]);
436af33a6ddSJed Brown     c->queueRemote[n] = Qi;
437af33a6ddSJed Brown   }
4382120983fSLisandro Dalcin   ierr = PetscLogEventEnd(CHARACTERISTIC_HalfTimeRemote,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
4392120983fSLisandro Dalcin   ierr = PetscLogEventBegin(CHARACTERISTIC_HalfTimeExchange,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
440af33a6ddSJed Brown   ierr = CharacteristicGetValuesBegin(c);CHKERRQ(ierr);
441af33a6ddSJed Brown   ierr = CharacteristicGetValuesEnd(c);CHKERRQ(ierr);
442af33a6ddSJed Brown   if (c->velocityInterpLocal) {
443af33a6ddSJed Brown     ierr = DMDAVecRestoreArray(c->velocityDA, velocityLocal,    &velocityArray);CHKERRQ(ierr);
444af33a6ddSJed Brown     ierr = DMDAVecRestoreArray(c->velocityDA, velocityLocalOld, &velocityArrayOld);CHKERRQ(ierr);
445af33a6ddSJed Brown     ierr = DMRestoreLocalVector(c->velocityDA, &velocityLocal);CHKERRQ(ierr);
446af33a6ddSJed Brown     ierr = DMRestoreLocalVector(c->velocityDA, &velocityLocalOld);CHKERRQ(ierr);
447af33a6ddSJed Brown   }
4482120983fSLisandro Dalcin   ierr = PetscLogEventEnd(CHARACTERISTIC_HalfTimeExchange,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
449af33a6ddSJed Brown 
450af33a6ddSJed Brown   /* -----------------------------------------------------------------------
451af33a6ddSJed Brown      PART 2, AT t-dt
452af33a6ddSJed Brown      -----------------------------------------------------------------------*/
453af33a6ddSJed Brown 
454af33a6ddSJed Brown   /* GET POSITION AT t_n (local values) */
4552120983fSLisandro Dalcin   ierr = PetscLogEventBegin(CHARACTERISTIC_FullTimeLocal,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
4560298fd71SBarry Smith   ierr = PetscInfo(NULL, "Calculating position at t_{n}\n");CHKERRQ(ierr);
457af33a6ddSJed Brown   for (n = 0; n < c->queueSize; n++) {
458af33a6ddSJed Brown     Qi   = c->queue[n];
459af33a6ddSJed Brown     Qi.x = Qi.i - Qi.x*dt;
460af33a6ddSJed Brown     Qi.y = Qi.j - Qi.y*dt;
461af33a6ddSJed Brown 
462af33a6ddSJed Brown     /* Determine whether the position at t-dt is local */
463af33a6ddSJed Brown     Qi.proc = DMDAGetNeighborRelative(da, Qi.x, Qi.y);
464af33a6ddSJed Brown 
465af33a6ddSJed Brown     /* Check for Periodic boundaries and move all periodic points back onto the domain */
466af33a6ddSJed Brown     ierr = DMDAMapCoordsToPeriodicDomain(da,&(Qi.x),&(Qi.y));CHKERRQ(ierr);
467af33a6ddSJed Brown 
468af33a6ddSJed Brown     c->queue[n] = Qi;
469af33a6ddSJed Brown   }
4702120983fSLisandro Dalcin   ierr = PetscLogEventEnd(CHARACTERISTIC_FullTimeLocal,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
471af33a6ddSJed Brown 
4722120983fSLisandro Dalcin   ierr = PetscLogEventBegin(CHARACTERISTIC_FullTimeExchange,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
473af33a6ddSJed Brown   ierr = CharacteristicSendCoordinatesBegin(c);CHKERRQ(ierr);
4742120983fSLisandro Dalcin   ierr = PetscLogEventEnd(CHARACTERISTIC_FullTimeExchange,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
475af33a6ddSJed Brown 
476af33a6ddSJed Brown   /* GET VALUE AT FULL TIME IN THE PAST (LOCAL REQUESTS) */
4772120983fSLisandro Dalcin   ierr = PetscLogEventBegin(CHARACTERISTIC_FullTimeLocal,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
478af33a6ddSJed Brown   if (c->fieldInterpLocal) {
479af33a6ddSJed Brown     ierr = DMGetLocalVector(c->fieldDA, &fieldLocal);CHKERRQ(ierr);
480af33a6ddSJed Brown     ierr = DMGlobalToLocalBegin(c->fieldDA, c->field, INSERT_VALUES, fieldLocal);CHKERRQ(ierr);
481af33a6ddSJed Brown     ierr = DMGlobalToLocalEnd(c->fieldDA, c->field, INSERT_VALUES, fieldLocal);CHKERRQ(ierr);
482af33a6ddSJed Brown     ierr = DMDAVecGetArray(c->fieldDA, fieldLocal, &fieldArray);CHKERRQ(ierr);
483af33a6ddSJed Brown   }
4840298fd71SBarry Smith   ierr = PetscInfo(NULL, "Calculating local field at t_{n}\n");CHKERRQ(ierr);
485af33a6ddSJed Brown   for (n = 0; n < c->queueSize; n++) {
486af33a6ddSJed Brown     if (c->neighbors[c->queue[n].proc] == rank) {
487af33a6ddSJed Brown       interpIndices[0] = c->queue[n].x;
488af33a6ddSJed Brown       interpIndices[1] = c->queue[n].y;
48961ba4676SBarry Smith       if (c->fieldInterpLocal) {ierr = c->fieldInterpLocal(fieldArray, interpIndices, c->numFieldComp, c->fieldComp, fieldValues, c->fieldCtx);CHKERRQ(ierr);}
49061ba4676SBarry Smith       else {ierr = c->fieldInterp(c->field, interpIndices, c->numFieldComp, c->fieldComp, fieldValues, c->fieldCtx);CHKERRQ(ierr);}
491bbd56ea5SKarl Rupp       for (comp = 0; comp < c->numFieldComp; comp++) c->queue[n].field[comp] = fieldValues[comp];
492af33a6ddSJed Brown     }
493af33a6ddSJed Brown   }
4942120983fSLisandro Dalcin   ierr = PetscLogEventEnd(CHARACTERISTIC_FullTimeLocal,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
495af33a6ddSJed Brown 
4962120983fSLisandro Dalcin   ierr = PetscLogEventBegin(CHARACTERISTIC_FullTimeExchange,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
497af33a6ddSJed Brown   ierr = CharacteristicSendCoordinatesEnd(c);CHKERRQ(ierr);
4982120983fSLisandro Dalcin   ierr = PetscLogEventEnd(CHARACTERISTIC_FullTimeExchange,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
499af33a6ddSJed Brown 
500af33a6ddSJed Brown   /* GET VALUE AT FULL TIME IN THE PAST (REMOTE REQUESTS) */
5012120983fSLisandro Dalcin   ierr = PetscLogEventBegin(CHARACTERISTIC_FullTimeRemote,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
5020298fd71SBarry Smith   ierr = PetscInfo1(NULL, "Calculating %d remote field points at t_{n}\n", c->queueRemoteSize);CHKERRQ(ierr);
503af33a6ddSJed Brown   for (n = 0; n < c->queueRemoteSize; n++) {
504af33a6ddSJed Brown     interpIndices[0] = c->queueRemote[n].x;
505af33a6ddSJed Brown     interpIndices[1] = c->queueRemote[n].y;
506af33a6ddSJed Brown 
507af33a6ddSJed Brown     /* for debugging purposes */
508af33a6ddSJed Brown     if (1) { /* hacked bounds test...let's do better */
509af33a6ddSJed Brown       PetscScalar im = interpIndices[0]; PetscScalar jm = interpIndices[1];
510af33a6ddSJed Brown 
511*98921bdaSJacob Faibussowitsch       if ((im < (PetscScalar) is - 1.) || (im > (PetscScalar) ie) || (jm < (PetscScalar)  js - 1.) || (jm > (PetscScalar) je)) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_LIB, "Nonlocal point: (%g,%g)", im, jm);
512af33a6ddSJed Brown     }
513af33a6ddSJed Brown 
51461ba4676SBarry Smith     if (c->fieldInterpLocal) {ierr = c->fieldInterpLocal(fieldArray, interpIndices, c->numFieldComp, c->fieldComp, fieldValues, c->fieldCtx);CHKERRQ(ierr);}
51561528463SBarry Smith     else {ierr = c->fieldInterp(c->field, interpIndices, c->numFieldComp, c->fieldComp, fieldValues, c->fieldCtx);CHKERRQ(ierr);}
516bbd56ea5SKarl Rupp     for (comp = 0; comp < c->numFieldComp; comp++) c->queueRemote[n].field[comp] = fieldValues[comp];
517af33a6ddSJed Brown   }
5182120983fSLisandro Dalcin   ierr = PetscLogEventEnd(CHARACTERISTIC_FullTimeRemote,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
519af33a6ddSJed Brown 
5202120983fSLisandro Dalcin   ierr = PetscLogEventBegin(CHARACTERISTIC_FullTimeExchange,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
521af33a6ddSJed Brown   ierr = CharacteristicGetValuesBegin(c);CHKERRQ(ierr);
522af33a6ddSJed Brown   ierr = CharacteristicGetValuesEnd(c);CHKERRQ(ierr);
523af33a6ddSJed Brown   if (c->fieldInterpLocal) {
524af33a6ddSJed Brown     ierr = DMDAVecRestoreArray(c->fieldDA, fieldLocal, &fieldArray);CHKERRQ(ierr);
525af33a6ddSJed Brown     ierr = DMRestoreLocalVector(c->fieldDA, &fieldLocal);CHKERRQ(ierr);
526af33a6ddSJed Brown   }
5272120983fSLisandro Dalcin   ierr = PetscLogEventEnd(CHARACTERISTIC_FullTimeExchange,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
528af33a6ddSJed Brown 
529af33a6ddSJed Brown   /* Return field of characteristics at t_n-1 */
5302120983fSLisandro Dalcin   ierr = PetscLogEventBegin(CHARACTERISTIC_DAUpdate,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
5312120983fSLisandro Dalcin   ierr = DMDAGetInfo(c->fieldDA,NULL,NULL,NULL,NULL,NULL,NULL,NULL,&dof,NULL,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
532af33a6ddSJed Brown   ierr = DMDAVecGetArray(c->fieldDA, solution, &solArray);CHKERRQ(ierr);
533af33a6ddSJed Brown   for (n = 0; n < c->queueSize; n++) {
534af33a6ddSJed Brown     Qi = c->queue[n];
535bbd56ea5SKarl Rupp     for (comp = 0; comp < c->numFieldComp; comp++) solArray[Qi.j][Qi.i*dof+c->fieldComp[comp]] = Qi.field[comp];
536af33a6ddSJed Brown   }
537af33a6ddSJed Brown   ierr = DMDAVecRestoreArray(c->fieldDA, solution, &solArray);CHKERRQ(ierr);
5382120983fSLisandro Dalcin   ierr = PetscLogEventEnd(CHARACTERISTIC_DAUpdate,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
5392120983fSLisandro Dalcin   ierr = PetscLogEventEnd(CHARACTERISTIC_Solve,NULL,NULL,NULL,NULL);CHKERRQ(ierr);
540af33a6ddSJed Brown 
541af33a6ddSJed Brown   /* Cleanup */
542af33a6ddSJed Brown   ierr = PetscFree(interpIndices);CHKERRQ(ierr);
543af33a6ddSJed Brown   ierr = PetscFree(velocityValues);CHKERRQ(ierr);
544af33a6ddSJed Brown   ierr = PetscFree(velocityValuesOld);CHKERRQ(ierr);
545af33a6ddSJed Brown   ierr = PetscFree(fieldValues);CHKERRQ(ierr);
546af33a6ddSJed Brown   PetscFunctionReturn(0);
547af33a6ddSJed Brown }
548af33a6ddSJed Brown 
549af33a6ddSJed Brown PetscErrorCode CharacteristicSetNeighbors(Characteristic c, PetscInt numNeighbors, PetscMPIInt neighbors[])
550af33a6ddSJed Brown {
551af33a6ddSJed Brown   PetscErrorCode ierr;
552af33a6ddSJed Brown 
553af33a6ddSJed Brown   PetscFunctionBegin;
554af33a6ddSJed Brown   c->numNeighbors = numNeighbors;
5556eaa7dc8SBarry Smith   ierr = PetscFree(c->neighbors);CHKERRQ(ierr);
556785e854fSJed Brown   ierr = PetscMalloc1(numNeighbors, &c->neighbors);CHKERRQ(ierr);
557580bdb30SBarry Smith   ierr = PetscArraycpy(c->neighbors, neighbors, numNeighbors);CHKERRQ(ierr);
558af33a6ddSJed Brown   PetscFunctionReturn(0);
559af33a6ddSJed Brown }
560af33a6ddSJed Brown 
561af33a6ddSJed Brown PetscErrorCode CharacteristicAddPoint(Characteristic c, CharacteristicPointDA2D *point)
562af33a6ddSJed Brown {
563af33a6ddSJed Brown   PetscFunctionBegin;
564*98921bdaSJacob Faibussowitsch   if (c->queueSize >= c->queueMax) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Exceeded maximum queue size %d", c->queueMax);
565af33a6ddSJed Brown   c->queue[c->queueSize++] = *point;
566af33a6ddSJed Brown   PetscFunctionReturn(0);
567af33a6ddSJed Brown }
568af33a6ddSJed Brown 
569af33a6ddSJed Brown int CharacteristicSendCoordinatesBegin(Characteristic c)
570af33a6ddSJed Brown {
571af33a6ddSJed Brown   PetscMPIInt    rank, tag = 121;
572af33a6ddSJed Brown   PetscInt       i, n;
573af33a6ddSJed Brown   PetscErrorCode ierr;
574af33a6ddSJed Brown 
575af33a6ddSJed Brown   PetscFunctionBegin;
576ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)c), &rank);CHKERRMPI(ierr);
5770b8f38c8SBarry Smith   ierr = CharacteristicHeapSort(c, c->queue, c->queueSize);CHKERRQ(ierr);
578580bdb30SBarry Smith   ierr = PetscArrayzero(c->needCount, c->numNeighbors);CHKERRQ(ierr);
579bbd56ea5SKarl Rupp   for (i = 0;  i < c->queueSize; i++) c->needCount[c->queue[i].proc]++;
580af33a6ddSJed Brown   c->fillCount[0] = 0;
581af33a6ddSJed Brown   for (n = 1; n < c->numNeighbors; n++) {
582ffc4695bSBarry Smith     ierr = MPI_Irecv(&(c->fillCount[n]), 1, MPIU_INT, c->neighbors[n], tag, PetscObjectComm((PetscObject)c), &(c->request[n-1]));CHKERRMPI(ierr);
583af33a6ddSJed Brown   }
584af33a6ddSJed Brown   for (n = 1; n < c->numNeighbors; n++) {
585ffc4695bSBarry Smith     ierr = MPI_Send(&(c->needCount[n]), 1, MPIU_INT, c->neighbors[n], tag, PetscObjectComm((PetscObject)c));CHKERRMPI(ierr);
586af33a6ddSJed Brown   }
587ffc4695bSBarry Smith   ierr = MPI_Waitall(c->numNeighbors-1, c->request, c->status);CHKERRMPI(ierr);
588af33a6ddSJed Brown   /* Initialize the remote queue */
589af33a6ddSJed Brown   c->queueLocalMax  = c->localOffsets[0]  = 0;
590af33a6ddSJed Brown   c->queueRemoteMax = c->remoteOffsets[0] = 0;
591af33a6ddSJed Brown   for (n = 1; n < c->numNeighbors; n++) {
592af33a6ddSJed Brown     c->remoteOffsets[n] = c->queueRemoteMax;
593af33a6ddSJed Brown     c->queueRemoteMax  += c->fillCount[n];
594af33a6ddSJed Brown     c->localOffsets[n]  = c->queueLocalMax;
595af33a6ddSJed Brown     c->queueLocalMax   += c->needCount[n];
596af33a6ddSJed Brown   }
597af33a6ddSJed Brown   /* HACK BEGIN */
598bbd56ea5SKarl Rupp   for (n = 1; n < c->numNeighbors; n++) c->localOffsets[n] += c->needCount[0];
599af33a6ddSJed Brown   c->needCount[0] = 0;
600af33a6ddSJed Brown   /* HACK END */
601af33a6ddSJed Brown   if (c->queueRemoteMax) {
60295dccacaSBarry Smith     ierr = PetscMalloc1(c->queueRemoteMax, &c->queueRemote);CHKERRQ(ierr);
6030298fd71SBarry Smith   } else c->queueRemote = NULL;
604af33a6ddSJed Brown   c->queueRemoteSize = c->queueRemoteMax;
605af33a6ddSJed Brown 
606af33a6ddSJed Brown   /* Send and Receive requests for values at t_n+1/2, giving the coordinates for interpolation */
607af33a6ddSJed Brown   for (n = 1; n < c->numNeighbors; n++) {
6080298fd71SBarry Smith     ierr = PetscInfo2(NULL, "Receiving %d requests for values from proc %d\n", c->fillCount[n], c->neighbors[n]);CHKERRQ(ierr);
609ffc4695bSBarry Smith     ierr = MPI_Irecv(&(c->queueRemote[c->remoteOffsets[n]]), c->fillCount[n], c->itemType, c->neighbors[n], tag, PetscObjectComm((PetscObject)c), &(c->request[n-1]));CHKERRMPI(ierr);
610af33a6ddSJed Brown   }
611af33a6ddSJed Brown   for (n = 1; n < c->numNeighbors; n++) {
6120298fd71SBarry Smith     ierr = PetscInfo2(NULL, "Sending %d requests for values from proc %d\n", c->needCount[n], c->neighbors[n]);CHKERRQ(ierr);
613ffc4695bSBarry Smith     ierr = MPI_Send(&(c->queue[c->localOffsets[n]]), c->needCount[n], c->itemType, c->neighbors[n], tag, PetscObjectComm((PetscObject)c));CHKERRMPI(ierr);
614af33a6ddSJed Brown   }
615af33a6ddSJed Brown   PetscFunctionReturn(0);
616af33a6ddSJed Brown }
617af33a6ddSJed Brown 
618af33a6ddSJed Brown PetscErrorCode CharacteristicSendCoordinatesEnd(Characteristic c)
619af33a6ddSJed Brown {
620af33a6ddSJed Brown #if 0
621af33a6ddSJed Brown   PetscMPIInt rank;
622af33a6ddSJed Brown   PetscInt    n;
623af33a6ddSJed Brown #endif
624af33a6ddSJed Brown   PetscErrorCode ierr;
625af33a6ddSJed Brown 
626af33a6ddSJed Brown   PetscFunctionBegin;
627ffc4695bSBarry Smith   ierr = MPI_Waitall(c->numNeighbors-1, c->request, c->status);CHKERRMPI(ierr);
628af33a6ddSJed Brown #if 0
629ffc4695bSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)c), &rank);CHKERRMPI(ierr);
630af33a6ddSJed Brown   for (n = 0; n < c->queueRemoteSize; n++) {
631*98921bdaSJacob Faibussowitsch     if (c->neighbors[c->queueRemote[n].proc] == rank) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB, "This is messed up, n = %d proc = %d", n, c->queueRemote[n].proc);
632af33a6ddSJed Brown   }
633af33a6ddSJed Brown #endif
634af33a6ddSJed Brown   PetscFunctionReturn(0);
635af33a6ddSJed Brown }
636af33a6ddSJed Brown 
637af33a6ddSJed Brown PetscErrorCode CharacteristicGetValuesBegin(Characteristic c)
638af33a6ddSJed Brown {
639af33a6ddSJed Brown   PetscMPIInt    tag = 121;
640af33a6ddSJed Brown   PetscInt       n;
641af33a6ddSJed Brown   PetscErrorCode ierr;
642af33a6ddSJed Brown 
643af33a6ddSJed Brown   PetscFunctionBegin;
644af33a6ddSJed Brown   /* SEND AND RECIEVE FILLED REQUESTS for velocities at t_n+1/2 */
645af33a6ddSJed Brown   for (n = 1; n < c->numNeighbors; n++) {
646ffc4695bSBarry Smith     ierr = MPI_Irecv(&(c->queue[c->localOffsets[n]]), c->needCount[n], c->itemType, c->neighbors[n], tag, PetscObjectComm((PetscObject)c), &(c->request[n-1]));CHKERRMPI(ierr);
647af33a6ddSJed Brown   }
648af33a6ddSJed Brown   for (n = 1; n < c->numNeighbors; n++) {
649ffc4695bSBarry Smith     ierr = MPI_Send(&(c->queueRemote[c->remoteOffsets[n]]), c->fillCount[n], c->itemType, c->neighbors[n], tag, PetscObjectComm((PetscObject)c));CHKERRMPI(ierr);
650af33a6ddSJed Brown   }
651af33a6ddSJed Brown   PetscFunctionReturn(0);
652af33a6ddSJed Brown }
653af33a6ddSJed Brown 
654af33a6ddSJed Brown PetscErrorCode CharacteristicGetValuesEnd(Characteristic c)
655af33a6ddSJed Brown {
656af33a6ddSJed Brown   PetscErrorCode ierr;
657af33a6ddSJed Brown 
658af33a6ddSJed Brown   PetscFunctionBegin;
659ffc4695bSBarry Smith   ierr = MPI_Waitall(c->numNeighbors-1, c->request, c->status);CHKERRMPI(ierr);
660af33a6ddSJed Brown   /* Free queue of requests from other procs */
661af33a6ddSJed Brown   ierr = PetscFree(c->queueRemote);CHKERRQ(ierr);
662af33a6ddSJed Brown   PetscFunctionReturn(0);
663af33a6ddSJed Brown }
664af33a6ddSJed Brown 
665af33a6ddSJed Brown /*---------------------------------------------------------------------*/
666af33a6ddSJed Brown /*
667af33a6ddSJed Brown   Based on code from http://linux.wku.edu/~lamonml/algor/sort/heap.html
668af33a6ddSJed Brown */
6690b8f38c8SBarry Smith PetscErrorCode CharacteristicHeapSort(Characteristic c, Queue queue, PetscInt size)
670af33a6ddSJed Brown /*---------------------------------------------------------------------*/
671af33a6ddSJed Brown {
6720b8f38c8SBarry Smith   PetscErrorCode          ierr;
673af33a6ddSJed Brown   CharacteristicPointDA2D temp;
6740b8f38c8SBarry Smith   PetscInt                n;
675af33a6ddSJed Brown 
6760b8f38c8SBarry Smith   PetscFunctionBegin;
677af33a6ddSJed Brown   if (0) { /* Check the order of the queue before sorting */
678994fe344SLisandro Dalcin     ierr = PetscInfo(NULL, "Before Heap sort\n");CHKERRQ(ierr);
679af33a6ddSJed Brown     for (n=0; n<size; n++) {
6800298fd71SBarry Smith       ierr = PetscInfo2(NULL,"%d %d\n",n,queue[n].proc);CHKERRQ(ierr);
681af33a6ddSJed Brown     }
682af33a6ddSJed Brown   }
683af33a6ddSJed Brown 
684af33a6ddSJed Brown   /* SORTING PHASE */
6850b8f38c8SBarry Smith   for (n = (size / 2)-1; n >= 0; n--) {
6860b8f38c8SBarry Smith     ierr = CharacteristicSiftDown(c, queue, n, size-1);CHKERRQ(ierr); /* Rich had size-1 here, Matt had size*/
6870b8f38c8SBarry Smith   }
688af33a6ddSJed Brown   for (n = size-1; n >= 1; n--) {
689af33a6ddSJed Brown     temp     = queue[0];
690af33a6ddSJed Brown     queue[0] = queue[n];
691af33a6ddSJed Brown     queue[n] = temp;
6920b8f38c8SBarry Smith     ierr     = CharacteristicSiftDown(c, queue, 0, n-1);CHKERRQ(ierr);
693af33a6ddSJed Brown   }
694af33a6ddSJed Brown   if (0) { /* Check the order of the queue after sorting */
6950298fd71SBarry Smith     ierr = PetscInfo(NULL, "Avter  Heap sort\n");CHKERRQ(ierr);
696af33a6ddSJed Brown     for (n=0; n<size; n++) {
6970298fd71SBarry Smith       ierr = PetscInfo2(NULL,"%d %d\n",n,queue[n].proc);CHKERRQ(ierr);
698af33a6ddSJed Brown     }
699af33a6ddSJed Brown   }
7000b8f38c8SBarry Smith   PetscFunctionReturn(0);
701af33a6ddSJed Brown }
702af33a6ddSJed Brown 
703af33a6ddSJed Brown /*---------------------------------------------------------------------*/
704af33a6ddSJed Brown /*
705af33a6ddSJed Brown   Based on code from http://linux.wku.edu/~lamonml/algor/sort/heap.html
706af33a6ddSJed Brown */
7070b8f38c8SBarry Smith PetscErrorCode CharacteristicSiftDown(Characteristic c, Queue queue, PetscInt root, PetscInt bottom)
708af33a6ddSJed Brown /*---------------------------------------------------------------------*/
709af33a6ddSJed Brown {
710af33a6ddSJed Brown   PetscBool               done = PETSC_FALSE;
711af33a6ddSJed Brown   PetscInt                maxChild;
712af33a6ddSJed Brown   CharacteristicPointDA2D temp;
713af33a6ddSJed Brown 
714af33a6ddSJed Brown   PetscFunctionBegin;
715af33a6ddSJed Brown   while ((root*2 <= bottom) && (!done)) {
716af33a6ddSJed Brown     if (root*2 == bottom) maxChild = root * 2;
717af33a6ddSJed Brown     else if (queue[root*2].proc > queue[root*2+1].proc) maxChild = root * 2;
718af33a6ddSJed Brown     else maxChild = root * 2 + 1;
719af33a6ddSJed Brown 
720af33a6ddSJed Brown     if (queue[root].proc < queue[maxChild].proc) {
721af33a6ddSJed Brown       temp            = queue[root];
722af33a6ddSJed Brown       queue[root]     = queue[maxChild];
723af33a6ddSJed Brown       queue[maxChild] = temp;
724af33a6ddSJed Brown       root            = maxChild;
725db4deed7SKarl Rupp     } else done = PETSC_TRUE;
726af33a6ddSJed Brown   }
727af33a6ddSJed Brown   PetscFunctionReturn(0);
728af33a6ddSJed Brown }
729af33a6ddSJed Brown 
730af33a6ddSJed Brown /* [center, left, top-left, top, top-right, right, bottom-right, bottom, bottom-left] */
731af33a6ddSJed Brown PetscErrorCode DMDAGetNeighborsRank(DM da, PetscMPIInt neighbors[])
732af33a6ddSJed Brown {
733bff4a2f0SMatthew G. Knepley   DMBoundaryType   bx, by;
734af33a6ddSJed Brown   PetscBool        IPeriodic = PETSC_FALSE, JPeriodic = PETSC_FALSE;
735af33a6ddSJed Brown   MPI_Comm         comm;
736af33a6ddSJed Brown   PetscMPIInt      rank;
737af33a6ddSJed Brown   PetscInt         **procs,pi,pj,pim,pip,pjm,pjp,PI,PJ;
738af33a6ddSJed Brown   PetscErrorCode   ierr;
739af33a6ddSJed Brown 
740af33a6ddSJed Brown   PetscFunctionBegin;
741af33a6ddSJed Brown   ierr = PetscObjectGetComm((PetscObject) da, &comm);CHKERRQ(ierr);
742ffc4695bSBarry Smith   ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr);
7432120983fSLisandro Dalcin   ierr = DMDAGetInfo(da, NULL, NULL, NULL, NULL, &PI,&PJ, NULL, NULL, NULL, &bx, &by,NULL, NULL);CHKERRQ(ierr);
744af33a6ddSJed Brown 
745bff4a2f0SMatthew G. Knepley   if (bx == DM_BOUNDARY_PERIODIC) IPeriodic = PETSC_TRUE;
746bff4a2f0SMatthew G. Knepley   if (by == DM_BOUNDARY_PERIODIC) JPeriodic = PETSC_TRUE;
747af33a6ddSJed Brown 
748af33a6ddSJed Brown   neighbors[0] = rank;
749af33a6ddSJed Brown   rank = 0;
750854ce69bSBarry Smith   ierr = PetscMalloc1(PJ,&procs);CHKERRQ(ierr);
751af33a6ddSJed Brown   for (pj=0; pj<PJ; pj++) {
752854ce69bSBarry Smith     ierr = PetscMalloc1(PI,&(procs[pj]));CHKERRQ(ierr);
753af33a6ddSJed Brown     for (pi=0; pi<PI; pi++) {
754af33a6ddSJed Brown       procs[pj][pi] = rank;
755af33a6ddSJed Brown       rank++;
756af33a6ddSJed Brown     }
757af33a6ddSJed Brown   }
758af33a6ddSJed Brown 
759af33a6ddSJed Brown   pi  = neighbors[0] % PI;
760af33a6ddSJed Brown   pj  = neighbors[0] / PI;
761af33a6ddSJed Brown   pim = pi-1;  if (pim<0) pim=PI-1;
762af33a6ddSJed Brown   pip = (pi+1)%PI;
763af33a6ddSJed Brown   pjm = pj-1;  if (pjm<0) pjm=PJ-1;
764af33a6ddSJed Brown   pjp = (pj+1)%PJ;
765af33a6ddSJed Brown 
766af33a6ddSJed Brown   neighbors[1] = procs[pj] [pim];
767af33a6ddSJed Brown   neighbors[2] = procs[pjp][pim];
768af33a6ddSJed Brown   neighbors[3] = procs[pjp][pi];
769af33a6ddSJed Brown   neighbors[4] = procs[pjp][pip];
770af33a6ddSJed Brown   neighbors[5] = procs[pj] [pip];
771af33a6ddSJed Brown   neighbors[6] = procs[pjm][pip];
772af33a6ddSJed Brown   neighbors[7] = procs[pjm][pi];
773af33a6ddSJed Brown   neighbors[8] = procs[pjm][pim];
774af33a6ddSJed Brown 
775af33a6ddSJed Brown   if (!IPeriodic) {
776af33a6ddSJed Brown     if (pi==0)    neighbors[1]=neighbors[2]=neighbors[8]=neighbors[0];
777af33a6ddSJed Brown     if (pi==PI-1) neighbors[4]=neighbors[5]=neighbors[6]=neighbors[0];
778af33a6ddSJed Brown   }
779af33a6ddSJed Brown 
780af33a6ddSJed Brown   if (!JPeriodic) {
781af33a6ddSJed Brown     if (pj==0)    neighbors[6]=neighbors[7]=neighbors[8]=neighbors[0];
782af33a6ddSJed Brown     if (pj==PJ-1) neighbors[2]=neighbors[3]=neighbors[4]=neighbors[0];
783af33a6ddSJed Brown   }
784af33a6ddSJed Brown 
785af33a6ddSJed Brown   for (pj = 0; pj < PJ; pj++) {
786af33a6ddSJed Brown     ierr = PetscFree(procs[pj]);CHKERRQ(ierr);
787af33a6ddSJed Brown   }
788af33a6ddSJed Brown   ierr = PetscFree(procs);CHKERRQ(ierr);
789af33a6ddSJed Brown   PetscFunctionReturn(0);
790af33a6ddSJed Brown }
791af33a6ddSJed Brown 
792af33a6ddSJed Brown /*
793af33a6ddSJed Brown   SUBDOMAIN NEIGHBORHOOD PROCESS MAP:
794af33a6ddSJed Brown     2 | 3 | 4
795af33a6ddSJed Brown     __|___|__
796af33a6ddSJed Brown     1 | 0 | 5
797af33a6ddSJed Brown     __|___|__
798af33a6ddSJed Brown     8 | 7 | 6
799af33a6ddSJed Brown       |   |
800af33a6ddSJed Brown */
8011cc8b206SBarry Smith PetscInt DMDAGetNeighborRelative(DM da, PetscReal ir, PetscReal jr)
802af33a6ddSJed Brown {
803af33a6ddSJed Brown   DMDALocalInfo  info;
8041cc8b206SBarry Smith   PetscReal      is,ie,js,je;
805af33a6ddSJed Brown   PetscErrorCode ierr;
806af33a6ddSJed Brown 
807af33a6ddSJed Brown   ierr = DMDAGetLocalInfo(da, &info);CHKERRQ(ierr);
8081cc8b206SBarry Smith   is   = (PetscReal) info.xs - 0.5; ie = (PetscReal) info.xs + info.xm - 0.5;
8091cc8b206SBarry Smith   js   = (PetscReal) info.ys - 0.5; je = (PetscReal) info.ys + info.ym - 0.5;
810af33a6ddSJed Brown 
811af33a6ddSJed Brown   if (ir >= is && ir <= ie) { /* center column */
812bbd56ea5SKarl Rupp     if (jr >= js && jr <= je) return 0;
813bbd56ea5SKarl Rupp     else if (jr < js)         return 7;
814bbd56ea5SKarl Rupp     else                      return 3;
815af33a6ddSJed Brown   } else if (ir < is) {     /* left column */
816bbd56ea5SKarl Rupp     if (jr >= js && jr <= je) return 1;
817bbd56ea5SKarl Rupp     else if (jr < js)         return 8;
818bbd56ea5SKarl Rupp     else                      return 2;
819af33a6ddSJed Brown   } else {                  /* right column */
820bbd56ea5SKarl Rupp     if (jr >= js && jr <= je) return 5;
821bbd56ea5SKarl Rupp     else if (jr < js)         return 6;
822bbd56ea5SKarl Rupp     else                      return 4;
823af33a6ddSJed Brown   }
824af33a6ddSJed Brown }
825