xref: /petsc/src/ts/characteristic/interface/characteristic.c (revision 785e854f82a3c614b452fca2cf5ad4f2afe8bdde)
1af33a6ddSJed Brown 
2b45d2f2cSJed Brown #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 []);
17af33a6ddSJed Brown PetscInt       DMDAGetNeighborRelative(DM, PassiveReal, PassiveReal);
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 #undef __FUNCT__
24af33a6ddSJed Brown #define __FUNCT__ "CharacteristicView"
25af33a6ddSJed Brown PetscErrorCode CharacteristicView(Characteristic c, PetscViewer viewer)
26af33a6ddSJed Brown {
27af33a6ddSJed Brown   PetscBool      iascii;
28af33a6ddSJed Brown   PetscErrorCode ierr;
29af33a6ddSJed Brown 
30af33a6ddSJed Brown   PetscFunctionBegin;
31af33a6ddSJed Brown   PetscValidHeaderSpecific(c, CHARACTERISTIC_CLASSID, 1);
32af33a6ddSJed Brown   if (!viewer) {
33ce94432eSBarry Smith     ierr = PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject)c),&viewer);CHKERRQ(ierr);
34af33a6ddSJed Brown   }
35af33a6ddSJed Brown   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2);
36af33a6ddSJed Brown   PetscCheckSameComm(c, 1, viewer, 2);
37af33a6ddSJed Brown 
38251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr);
39af33a6ddSJed Brown   if (!iascii) {
40af33a6ddSJed Brown     if (c->ops->view) {
41af33a6ddSJed Brown       ierr = (*c->ops->view)(c, viewer);CHKERRQ(ierr);
42af33a6ddSJed Brown     }
43af33a6ddSJed Brown   }
44af33a6ddSJed Brown   PetscFunctionReturn(0);
45af33a6ddSJed Brown }
46af33a6ddSJed Brown 
47af33a6ddSJed Brown #undef __FUNCT__
48af33a6ddSJed Brown #define __FUNCT__ "CharacteristicDestroy"
496bf464f9SBarry Smith PetscErrorCode CharacteristicDestroy(Characteristic *c)
50af33a6ddSJed Brown {
51af33a6ddSJed Brown   PetscErrorCode ierr;
52af33a6ddSJed Brown 
53af33a6ddSJed Brown   PetscFunctionBegin;
546bf464f9SBarry Smith   if (!*c) PetscFunctionReturn(0);
556bf464f9SBarry Smith   PetscValidHeaderSpecific(*c, CHARACTERISTIC_CLASSID, 1);
566bf464f9SBarry Smith   if (--((PetscObject)(*c))->refct > 0) PetscFunctionReturn(0);
57af33a6ddSJed Brown 
586bf464f9SBarry Smith   if ((*c)->ops->destroy) {
596bf464f9SBarry Smith     ierr = (*(*c)->ops->destroy)((*c));CHKERRQ(ierr);
60af33a6ddSJed Brown   }
616bf464f9SBarry Smith   ierr = MPI_Type_free(&(*c)->itemType);CHKERRQ(ierr);
626bf464f9SBarry Smith   ierr = PetscFree((*c)->queue);CHKERRQ(ierr);
636bf464f9SBarry Smith   ierr = PetscFree((*c)->queueLocal);CHKERRQ(ierr);
646bf464f9SBarry Smith   ierr = PetscFree((*c)->queueRemote);CHKERRQ(ierr);
656bf464f9SBarry Smith   ierr = PetscFree((*c)->neighbors);CHKERRQ(ierr);
666bf464f9SBarry Smith   ierr = PetscFree((*c)->needCount);CHKERRQ(ierr);
676bf464f9SBarry Smith   ierr = PetscFree((*c)->localOffsets);CHKERRQ(ierr);
686bf464f9SBarry Smith   ierr = PetscFree((*c)->fillCount);CHKERRQ(ierr);
696bf464f9SBarry Smith   ierr = PetscFree((*c)->remoteOffsets);CHKERRQ(ierr);
706bf464f9SBarry Smith   ierr = PetscFree((*c)->request);CHKERRQ(ierr);
716bf464f9SBarry Smith   ierr = PetscFree((*c)->status);CHKERRQ(ierr);
72af33a6ddSJed Brown   ierr = PetscHeaderDestroy(c);CHKERRQ(ierr);
73af33a6ddSJed Brown   PetscFunctionReturn(0);
74af33a6ddSJed Brown }
75af33a6ddSJed Brown 
76af33a6ddSJed Brown #undef __FUNCT__
77af33a6ddSJed Brown #define __FUNCT__ "CharacteristicCreate"
78af33a6ddSJed Brown PetscErrorCode CharacteristicCreate(MPI_Comm comm, Characteristic *c)
79af33a6ddSJed Brown {
80af33a6ddSJed Brown   Characteristic newC;
81af33a6ddSJed Brown   PetscErrorCode ierr;
82af33a6ddSJed Brown 
83af33a6ddSJed Brown   PetscFunctionBegin;
84af33a6ddSJed Brown   PetscValidPointer(c, 2);
850298fd71SBarry Smith   *c = NULL;
86607a6623SBarry Smith   ierr = CharacteristicInitializePackage();CHKERRQ(ierr);
87af33a6ddSJed Brown 
8867c2884eSBarry Smith   ierr = PetscHeaderCreate(newC, _p_Characteristic, struct _CharacteristicOps, CHARACTERISTIC_CLASSID, "Characteristic", "Characteristic", "SemiLagrange", comm, CharacteristicDestroy, CharacteristicView);CHKERRQ(ierr);
89af33a6ddSJed Brown   ierr = PetscLogObjectCreate(newC);CHKERRQ(ierr);
90af33a6ddSJed Brown   *c   = newC;
91af33a6ddSJed Brown 
92af33a6ddSJed Brown   newC->structured          = PETSC_TRUE;
93af33a6ddSJed Brown   newC->numIds              = 0;
940298fd71SBarry Smith   newC->velocityDA          = NULL;
950298fd71SBarry Smith   newC->velocity            = NULL;
960298fd71SBarry Smith   newC->velocityOld         = NULL;
97af33a6ddSJed Brown   newC->numVelocityComp     = 0;
980298fd71SBarry Smith   newC->velocityComp        = NULL;
990298fd71SBarry Smith   newC->velocityInterp      = NULL;
1000298fd71SBarry Smith   newC->velocityInterpLocal = NULL;
1010298fd71SBarry Smith   newC->velocityCtx         = NULL;
1020298fd71SBarry Smith   newC->fieldDA             = NULL;
1030298fd71SBarry Smith   newC->field               = NULL;
104af33a6ddSJed Brown   newC->numFieldComp        = 0;
1050298fd71SBarry Smith   newC->fieldComp           = NULL;
1060298fd71SBarry Smith   newC->fieldInterp         = NULL;
1070298fd71SBarry Smith   newC->fieldInterpLocal    = NULL;
1080298fd71SBarry Smith   newC->fieldCtx            = NULL;
1090298fd71SBarry Smith   newC->itemType            = 0;
1100298fd71SBarry Smith   newC->queue               = NULL;
111af33a6ddSJed Brown   newC->queueSize           = 0;
112af33a6ddSJed Brown   newC->queueMax            = 0;
1130298fd71SBarry Smith   newC->queueLocal          = NULL;
114af33a6ddSJed Brown   newC->queueLocalSize      = 0;
115af33a6ddSJed Brown   newC->queueLocalMax       = 0;
1160298fd71SBarry Smith   newC->queueRemote         = NULL;
117af33a6ddSJed Brown   newC->queueRemoteSize     = 0;
118af33a6ddSJed Brown   newC->queueRemoteMax      = 0;
119af33a6ddSJed Brown   newC->numNeighbors        = 0;
1200298fd71SBarry Smith   newC->neighbors           = NULL;
1210298fd71SBarry Smith   newC->needCount           = NULL;
1220298fd71SBarry Smith   newC->localOffsets        = NULL;
1230298fd71SBarry Smith   newC->fillCount           = NULL;
1240298fd71SBarry Smith   newC->remoteOffsets       = NULL;
1250298fd71SBarry Smith   newC->request             = NULL;
1260298fd71SBarry Smith   newC->status              = NULL;
127af33a6ddSJed Brown   PetscFunctionReturn(0);
128af33a6ddSJed Brown }
129af33a6ddSJed Brown 
130af33a6ddSJed Brown #undef __FUNCT__
131af33a6ddSJed Brown #define __FUNCT__ "CharacteristicSetType"
132af33a6ddSJed Brown /*@C
133af33a6ddSJed Brown    CharacteristicSetType - Builds Characteristic for a particular solver.
134af33a6ddSJed Brown 
135af33a6ddSJed Brown    Logically Collective on Characteristic
136af33a6ddSJed Brown 
137af33a6ddSJed Brown    Input Parameters:
138af33a6ddSJed Brown +  c    - the method of characteristics context
139af33a6ddSJed Brown -  type - a known method
140af33a6ddSJed Brown 
141af33a6ddSJed Brown    Options Database Key:
142af33a6ddSJed Brown .  -characteristic_type <method> - Sets the method; use -help for a list
143af33a6ddSJed Brown     of available methods
144af33a6ddSJed Brown 
145af33a6ddSJed Brown    Notes:
14630a76a96SBarry Smith    See "include/petsccharacteristic.h" for available methods
147af33a6ddSJed Brown 
148af33a6ddSJed Brown   Normally, it is best to use the CharacteristicSetFromOptions() command and
149af33a6ddSJed Brown   then set the Characteristic type from the options database rather than by using
150af33a6ddSJed Brown   this routine.  Using the options database provides the user with
151af33a6ddSJed Brown   maximum flexibility in evaluating the many different Krylov methods.
152af33a6ddSJed Brown   The CharacteristicSetType() routine is provided for those situations where it
153af33a6ddSJed Brown   is necessary to set the iterative solver independently of the command
154af33a6ddSJed Brown   line or options database.  This might be the case, for example, when
155af33a6ddSJed Brown   the choice of iterative solver changes during the execution of the
156af33a6ddSJed Brown   program, and the user's application is taking responsibility for
157af33a6ddSJed Brown   choosing the appropriate method.  In other words, this routine is
158af33a6ddSJed Brown   not for beginners.
159af33a6ddSJed Brown 
160af33a6ddSJed Brown   Level: intermediate
161af33a6ddSJed Brown 
162af33a6ddSJed Brown .keywords: Characteristic, set, method
163af33a6ddSJed Brown 
164af33a6ddSJed Brown .seealso: CharacteristicType
165af33a6ddSJed Brown 
166af33a6ddSJed Brown @*/
16719fd82e9SBarry Smith PetscErrorCode CharacteristicSetType(Characteristic c, CharacteristicType type)
168af33a6ddSJed Brown {
169af33a6ddSJed Brown   PetscErrorCode ierr, (*r)(Characteristic);
170af33a6ddSJed Brown   PetscBool      match;
171af33a6ddSJed Brown 
172af33a6ddSJed Brown   PetscFunctionBegin;
173af33a6ddSJed Brown   PetscValidHeaderSpecific(c, CHARACTERISTIC_CLASSID, 1);
174af33a6ddSJed Brown   PetscValidCharPointer(type, 2);
175af33a6ddSJed Brown 
176251f4c67SDmitry Karpeev   ierr = PetscObjectTypeCompare((PetscObject) c, type, &match);CHKERRQ(ierr);
177af33a6ddSJed Brown   if (match) PetscFunctionReturn(0);
178af33a6ddSJed Brown 
179af33a6ddSJed Brown   if (c->data) {
180af33a6ddSJed Brown     /* destroy the old private Characteristic context */
181af33a6ddSJed Brown     ierr = (*c->ops->destroy)(c);CHKERRQ(ierr);
1820298fd71SBarry Smith     c->ops->destroy = NULL;
183af33a6ddSJed Brown     c->data         = 0;
184af33a6ddSJed Brown   }
185af33a6ddSJed Brown 
1861c9cd337SJed Brown   ierr =  PetscFunctionListFind(CharacteristicList,type,&r);CHKERRQ(ierr);
187af33a6ddSJed Brown   if (!r) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown Characteristic type given: %s", type);
188af33a6ddSJed Brown   c->setupcalled = 0;
189af33a6ddSJed Brown   ierr = (*r)(c);CHKERRQ(ierr);
190af33a6ddSJed Brown   ierr = PetscObjectChangeTypeName((PetscObject) c, type);CHKERRQ(ierr);
191af33a6ddSJed Brown   PetscFunctionReturn(0);
192af33a6ddSJed Brown }
193af33a6ddSJed Brown 
194af33a6ddSJed Brown #undef __FUNCT__
195af33a6ddSJed Brown #define __FUNCT__ "CharacteristicSetUp"
196af33a6ddSJed Brown /*@
197af33a6ddSJed Brown    CharacteristicSetUp - Sets up the internal data structures for the
198af33a6ddSJed Brown    later use of an iterative solver.
199af33a6ddSJed Brown 
200af33a6ddSJed Brown    Collective on Characteristic
201af33a6ddSJed Brown 
202af33a6ddSJed Brown    Input Parameter:
203af33a6ddSJed Brown .  ksp   - iterative context obtained from CharacteristicCreate()
204af33a6ddSJed Brown 
205af33a6ddSJed Brown    Level: developer
206af33a6ddSJed Brown 
207af33a6ddSJed Brown .keywords: Characteristic, setup
208af33a6ddSJed Brown 
209af33a6ddSJed Brown .seealso: CharacteristicCreate(), CharacteristicSolve(), CharacteristicDestroy()
210af33a6ddSJed Brown @*/
211af33a6ddSJed Brown PetscErrorCode CharacteristicSetUp(Characteristic c)
212af33a6ddSJed Brown {
213af33a6ddSJed Brown   PetscErrorCode ierr;
214af33a6ddSJed Brown 
215af33a6ddSJed Brown   PetscFunctionBegin;
216af33a6ddSJed Brown   PetscValidHeaderSpecific(c, CHARACTERISTIC_CLASSID, 1);
217af33a6ddSJed Brown 
218af33a6ddSJed Brown   if (!((PetscObject)c)->type_name) {
219af33a6ddSJed Brown     ierr = CharacteristicSetType(c, CHARACTERISTICDA);CHKERRQ(ierr);
220af33a6ddSJed Brown   }
221af33a6ddSJed Brown 
222af33a6ddSJed Brown   if (c->setupcalled == 2) PetscFunctionReturn(0);
223af33a6ddSJed Brown 
224af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_SetUp,c,0,0,0);CHKERRQ(ierr);
225af33a6ddSJed Brown   if (!c->setupcalled) {
226af33a6ddSJed Brown     ierr = (*c->ops->setup)(c);CHKERRQ(ierr);
227af33a6ddSJed Brown   }
228af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_SetUp,c,0,0,0);CHKERRQ(ierr);
229af33a6ddSJed Brown   c->setupcalled = 2;
230af33a6ddSJed Brown   PetscFunctionReturn(0);
231af33a6ddSJed Brown }
232af33a6ddSJed Brown 
233af33a6ddSJed Brown #undef __FUNCT__
234af33a6ddSJed Brown #define __FUNCT__ "CharacteristicRegister"
235af33a6ddSJed Brown /*@C
2361c84c290SBarry Smith   CharacteristicRegister -  Adds a solver to the method of characteristics package.
2371c84c290SBarry Smith 
2381c84c290SBarry Smith    Not Collective
2391c84c290SBarry Smith 
2401c84c290SBarry Smith    Input Parameters:
2411c84c290SBarry Smith +  name_solver - name of a new user-defined solver
2421c84c290SBarry Smith -  routine_create - routine to create method context
2431c84c290SBarry Smith 
2441c84c290SBarry Smith   Sample usage:
2451c84c290SBarry Smith .vb
246bdf89e91SBarry Smith     CharacteristicRegister("my_char", MyCharCreate);
2471c84c290SBarry Smith .ve
2481c84c290SBarry Smith 
2491c84c290SBarry Smith   Then, your Characteristic type can be chosen with the procedural interface via
2501c84c290SBarry Smith .vb
2511c84c290SBarry Smith     CharacteristicCreate(MPI_Comm, Characteristic* &char);
2521c84c290SBarry Smith     CharacteristicSetType(char,"my_char");
2531c84c290SBarry Smith .ve
2541c84c290SBarry Smith    or at runtime via the option
2551c84c290SBarry Smith .vb
2561c84c290SBarry Smith     -characteristic_type my_char
2571c84c290SBarry Smith .ve
2581c84c290SBarry Smith 
2591c84c290SBarry Smith    Notes:
2601c84c290SBarry Smith    CharacteristicRegister() may be called multiple times to add several user-defined solvers.
2611c84c290SBarry Smith 
2621c84c290SBarry Smith .keywords: Characteristic, register
2631c84c290SBarry Smith 
2641c84c290SBarry Smith .seealso: CharacteristicRegisterAll(), CharacteristicRegisterDestroy()
265af33a6ddSJed Brown 
266af33a6ddSJed Brown   Level: advanced
267af33a6ddSJed Brown @*/
268bdf89e91SBarry Smith PetscErrorCode CharacteristicRegister(const char sname[],PetscErrorCode (*function)(Characteristic))
269af33a6ddSJed Brown {
270af33a6ddSJed Brown   PetscErrorCode ierr;
271af33a6ddSJed Brown 
272af33a6ddSJed Brown   PetscFunctionBegin;
273a240a19fSJed Brown   ierr = PetscFunctionListAdd(&CharacteristicList,sname,function);CHKERRQ(ierr);
274af33a6ddSJed Brown   PetscFunctionReturn(0);
275af33a6ddSJed Brown }
276af33a6ddSJed Brown 
277af33a6ddSJed Brown #undef __FUNCT__
278af33a6ddSJed Brown #define __FUNCT__ "CharacteristicSetVelocityInterpolation"
279af33a6ddSJed 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)
280af33a6ddSJed Brown {
281af33a6ddSJed Brown   PetscFunctionBegin;
282af33a6ddSJed Brown   c->velocityDA      = da;
283af33a6ddSJed Brown   c->velocity        = v;
284af33a6ddSJed Brown   c->velocityOld     = vOld;
285af33a6ddSJed Brown   c->numVelocityComp = numComponents;
286af33a6ddSJed Brown   c->velocityComp    = components;
287af33a6ddSJed Brown   c->velocityInterp  = interp;
288af33a6ddSJed Brown   c->velocityCtx     = ctx;
289af33a6ddSJed Brown   PetscFunctionReturn(0);
290af33a6ddSJed Brown }
291af33a6ddSJed Brown 
292af33a6ddSJed Brown #undef __FUNCT__
293af33a6ddSJed Brown #define __FUNCT__ "CharacteristicSetVelocityInterpolationLocal"
294af33a6ddSJed 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)
295af33a6ddSJed Brown {
296af33a6ddSJed Brown   PetscFunctionBegin;
297af33a6ddSJed Brown   c->velocityDA          = da;
298af33a6ddSJed Brown   c->velocity            = v;
299af33a6ddSJed Brown   c->velocityOld         = vOld;
300af33a6ddSJed Brown   c->numVelocityComp     = numComponents;
301af33a6ddSJed Brown   c->velocityComp        = components;
302af33a6ddSJed Brown   c->velocityInterpLocal = interp;
303af33a6ddSJed Brown   c->velocityCtx         = ctx;
304af33a6ddSJed Brown   PetscFunctionReturn(0);
305af33a6ddSJed Brown }
306af33a6ddSJed Brown 
307af33a6ddSJed Brown #undef __FUNCT__
308af33a6ddSJed Brown #define __FUNCT__ "CharacteristicSetFieldInterpolation"
309af33a6ddSJed Brown PetscErrorCode CharacteristicSetFieldInterpolation(Characteristic c, DM da, Vec v, PetscInt numComponents, PetscInt components[], PetscErrorCode (*interp)(Vec, PetscReal[], PetscInt, PetscInt[], PetscScalar[], void*), void *ctx)
310af33a6ddSJed Brown {
311af33a6ddSJed Brown   PetscFunctionBegin;
312af33a6ddSJed Brown #if 0
313af33a6ddSJed 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.");
314af33a6ddSJed Brown #endif
315af33a6ddSJed Brown   c->fieldDA      = da;
316af33a6ddSJed Brown   c->field        = v;
317af33a6ddSJed Brown   c->numFieldComp = numComponents;
318af33a6ddSJed Brown   c->fieldComp    = components;
319af33a6ddSJed Brown   c->fieldInterp  = interp;
320af33a6ddSJed Brown   c->fieldCtx     = ctx;
321af33a6ddSJed Brown   PetscFunctionReturn(0);
322af33a6ddSJed Brown }
323af33a6ddSJed Brown 
324af33a6ddSJed Brown #undef __FUNCT__
325af33a6ddSJed Brown #define __FUNCT__ "CharacteristicSetFieldInterpolationLocal"
326af33a6ddSJed Brown PetscErrorCode CharacteristicSetFieldInterpolationLocal(Characteristic c, DM da, Vec v, PetscInt numComponents, PetscInt components[], PetscErrorCode (*interp)(void*, PetscReal[], PetscInt, PetscInt[], PetscScalar [], void*), void *ctx)
327af33a6ddSJed Brown {
328af33a6ddSJed Brown   PetscFunctionBegin;
329af33a6ddSJed Brown #if 0
330af33a6ddSJed 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.");
331af33a6ddSJed Brown #endif
332af33a6ddSJed Brown   c->fieldDA          = da;
333af33a6ddSJed Brown   c->field            = v;
334af33a6ddSJed Brown   c->numFieldComp     = numComponents;
335af33a6ddSJed Brown   c->fieldComp        = components;
336af33a6ddSJed Brown   c->fieldInterpLocal = interp;
337af33a6ddSJed Brown   c->fieldCtx         = ctx;
338af33a6ddSJed Brown   PetscFunctionReturn(0);
339af33a6ddSJed Brown }
340af33a6ddSJed Brown 
341af33a6ddSJed Brown #undef __FUNCT__
342af33a6ddSJed Brown #define __FUNCT__ "CharacteristicSolve"
343af33a6ddSJed Brown PetscErrorCode CharacteristicSolve(Characteristic c, PetscReal dt, Vec solution)
344af33a6ddSJed Brown {
345af33a6ddSJed Brown   CharacteristicPointDA2D Qi;
346af33a6ddSJed Brown   DM                      da = c->velocityDA;
347af33a6ddSJed Brown   Vec                     velocityLocal, velocityLocalOld;
348af33a6ddSJed Brown   Vec                     fieldLocal;
349af33a6ddSJed Brown   DMDALocalInfo           info;
350af33a6ddSJed Brown   PetscScalar             **solArray;
351af33a6ddSJed Brown   void                    *velocityArray;
352af33a6ddSJed Brown   void                    *velocityArrayOld;
353af33a6ddSJed Brown   void                    *fieldArray;
354af33a6ddSJed Brown   PassiveScalar           *interpIndices;
355af33a6ddSJed Brown   PassiveScalar           *velocityValues, *velocityValuesOld;
356af33a6ddSJed Brown   PassiveScalar           *fieldValues;
357af33a6ddSJed Brown   PetscMPIInt             rank;
358af33a6ddSJed Brown   PetscInt                dim;
359af33a6ddSJed Brown   PetscMPIInt             neighbors[9];
360af33a6ddSJed Brown   PetscInt                dof;
361af33a6ddSJed Brown   PetscInt                gx, gy;
362af33a6ddSJed Brown   PetscInt                n, is, ie, js, je, comp;
363af33a6ddSJed Brown   PetscErrorCode          ierr;
364af33a6ddSJed Brown 
365af33a6ddSJed Brown   PetscFunctionBegin;
366af33a6ddSJed Brown   c->queueSize = 0;
367ce94432eSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)c), &rank);CHKERRQ(ierr);
368af33a6ddSJed Brown   ierr = DMDAGetNeighborsRank(da, neighbors);CHKERRQ(ierr);
369af33a6ddSJed Brown   ierr = CharacteristicSetNeighbors(c, 9, neighbors);CHKERRQ(ierr);
370af33a6ddSJed Brown   ierr = CharacteristicSetUp(c);CHKERRQ(ierr);
371af33a6ddSJed Brown   /* global and local grid info */
372af33a6ddSJed Brown   ierr = DMDAGetInfo(da, &dim, &gx, &gy, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);CHKERRQ(ierr);
373af33a6ddSJed Brown   ierr = DMDAGetLocalInfo(da, &info);CHKERRQ(ierr);
374af33a6ddSJed Brown   is   = info.xs;          ie   = info.xs+info.xm;
375af33a6ddSJed Brown   js   = info.ys;          je   = info.ys+info.ym;
376af33a6ddSJed Brown   /* Allocation */
377*785e854fSJed Brown   ierr = PetscMalloc1(dim,                &interpIndices);CHKERRQ(ierr);
378*785e854fSJed Brown   ierr = PetscMalloc1(c->numVelocityComp, &velocityValues);CHKERRQ(ierr);
379*785e854fSJed Brown   ierr = PetscMalloc1(c->numVelocityComp, &velocityValuesOld);CHKERRQ(ierr);
380*785e854fSJed Brown   ierr = PetscMalloc1(c->numFieldComp,    &fieldValues);CHKERRQ(ierr);
381af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_Solve,0,0,0,0);CHKERRQ(ierr);
382af33a6ddSJed Brown 
383af33a6ddSJed Brown   /* -----------------------------------------------------------------------
384af33a6ddSJed Brown      PART 1, AT t-dt/2
385af33a6ddSJed Brown      -----------------------------------------------------------------------*/
386af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_QueueSetup,0,0,0,0);CHKERRQ(ierr);
387af33a6ddSJed Brown   /* GET POSITION AT HALF TIME IN THE PAST */
388af33a6ddSJed Brown   if (c->velocityInterpLocal) {
389af33a6ddSJed Brown     ierr = DMGetLocalVector(c->velocityDA, &velocityLocal);CHKERRQ(ierr);
390af33a6ddSJed Brown     ierr = DMGetLocalVector(c->velocityDA, &velocityLocalOld);CHKERRQ(ierr);
391af33a6ddSJed Brown     ierr = DMGlobalToLocalBegin(c->velocityDA, c->velocity, INSERT_VALUES, velocityLocal);CHKERRQ(ierr);
392af33a6ddSJed Brown     ierr = DMGlobalToLocalEnd(c->velocityDA, c->velocity, INSERT_VALUES, velocityLocal);CHKERRQ(ierr);
393af33a6ddSJed Brown     ierr = DMGlobalToLocalBegin(c->velocityDA, c->velocityOld, INSERT_VALUES, velocityLocalOld);CHKERRQ(ierr);
394af33a6ddSJed Brown     ierr = DMGlobalToLocalEnd(c->velocityDA, c->velocityOld, INSERT_VALUES, velocityLocalOld);CHKERRQ(ierr);
395af33a6ddSJed Brown     ierr = DMDAVecGetArray(c->velocityDA, velocityLocal,    &velocityArray);CHKERRQ(ierr);
396af33a6ddSJed Brown     ierr = DMDAVecGetArray(c->velocityDA, velocityLocalOld, &velocityArrayOld);CHKERRQ(ierr);
397af33a6ddSJed Brown   }
3980298fd71SBarry Smith   ierr = PetscInfo(NULL, "Calculating position at t_{n - 1/2}\n");CHKERRQ(ierr);
399af33a6ddSJed Brown   for (Qi.j = js; Qi.j < je; Qi.j++) {
400af33a6ddSJed Brown     for (Qi.i = is; Qi.i < ie; Qi.i++) {
401af33a6ddSJed Brown       interpIndices[0] = Qi.i;
402af33a6ddSJed Brown       interpIndices[1] = Qi.j;
403bbd56ea5SKarl Rupp       if (c->velocityInterpLocal) c->velocityInterpLocal(velocityArray, interpIndices, c->numVelocityComp, c->velocityComp, velocityValues, c->velocityCtx);
404bbd56ea5SKarl Rupp       else c->velocityInterp(c->velocity, interpIndices, c->numVelocityComp, c->velocityComp, velocityValues, c->velocityCtx);
405af33a6ddSJed Brown       Qi.x = Qi.i - velocityValues[0]*dt/2.0;
406af33a6ddSJed Brown       Qi.y = Qi.j - velocityValues[1]*dt/2.0;
407af33a6ddSJed Brown 
408af33a6ddSJed Brown       /* Determine whether the position at t - dt/2 is local */
409af33a6ddSJed Brown       Qi.proc = DMDAGetNeighborRelative(da, Qi.x, Qi.y);
410af33a6ddSJed Brown 
411af33a6ddSJed Brown       /* Check for Periodic boundaries and move all periodic points back onto the domain */
412af33a6ddSJed Brown       ierr = DMDAMapCoordsToPeriodicDomain(da,&(Qi.x),&(Qi.y));CHKERRQ(ierr);
413af33a6ddSJed Brown       ierr = CharacteristicAddPoint(c, &Qi);CHKERRQ(ierr);
414af33a6ddSJed Brown     }
415af33a6ddSJed Brown   }
416af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_QueueSetup,0,0,0,0);CHKERRQ(ierr);
417af33a6ddSJed Brown 
418af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_HalfTimeExchange,0,0,0,0);CHKERRQ(ierr);
419af33a6ddSJed Brown   ierr = CharacteristicSendCoordinatesBegin(c);CHKERRQ(ierr);
420af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_HalfTimeExchange,0,0,0,0);CHKERRQ(ierr);
421af33a6ddSJed Brown 
422af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_HalfTimeLocal,0,0,0,0);CHKERRQ(ierr);
423af33a6ddSJed Brown   /* Calculate velocity at t_n+1/2 (local values) */
4240298fd71SBarry Smith   ierr = PetscInfo(NULL, "Calculating local velocities at t_{n - 1/2}\n");CHKERRQ(ierr);
425af33a6ddSJed Brown   for (n = 0; n < c->queueSize; n++) {
426af33a6ddSJed Brown     Qi = c->queue[n];
427af33a6ddSJed Brown     if (c->neighbors[Qi.proc] == rank) {
428af33a6ddSJed Brown       interpIndices[0] = Qi.x;
429af33a6ddSJed Brown       interpIndices[1] = Qi.y;
430af33a6ddSJed Brown       if (c->velocityInterpLocal) {
431af33a6ddSJed Brown         c->velocityInterpLocal(velocityArray,    interpIndices, c->numVelocityComp, c->velocityComp, velocityValues,    c->velocityCtx);
432af33a6ddSJed Brown         c->velocityInterpLocal(velocityArrayOld, interpIndices, c->numVelocityComp, c->velocityComp, velocityValuesOld, c->velocityCtx);
433af33a6ddSJed Brown       } else {
434af33a6ddSJed Brown         c->velocityInterp(c->velocity,    interpIndices, c->numVelocityComp, c->velocityComp, velocityValues,    c->velocityCtx);
435af33a6ddSJed Brown         c->velocityInterp(c->velocityOld, interpIndices, c->numVelocityComp, c->velocityComp, velocityValuesOld, c->velocityCtx);
436af33a6ddSJed Brown       }
437af33a6ddSJed Brown       Qi.x = 0.5*(velocityValues[0] + velocityValuesOld[0]);
438af33a6ddSJed Brown       Qi.y = 0.5*(velocityValues[1] + velocityValuesOld[1]);
439af33a6ddSJed Brown     }
440af33a6ddSJed Brown     c->queue[n] = Qi;
441af33a6ddSJed Brown   }
442af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_HalfTimeLocal,0,0,0,0);CHKERRQ(ierr);
443af33a6ddSJed Brown 
444af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_HalfTimeExchange,0,0,0,0);CHKERRQ(ierr);
445af33a6ddSJed Brown   ierr = CharacteristicSendCoordinatesEnd(c);CHKERRQ(ierr);
446af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_HalfTimeExchange,0,0,0,0);CHKERRQ(ierr);
447af33a6ddSJed Brown 
448af33a6ddSJed Brown 
449af33a6ddSJed Brown   /* Calculate velocity at t_n+1/2 (fill remote requests) */
450af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_HalfTimeRemote,0,0,0,0);CHKERRQ(ierr);
4510298fd71SBarry Smith   ierr = PetscInfo1(NULL, "Calculating %d remote velocities at t_{n - 1/2}\n", c->queueRemoteSize);CHKERRQ(ierr);
452af33a6ddSJed Brown   for (n = 0; n < c->queueRemoteSize; n++) {
453af33a6ddSJed Brown     Qi = c->queueRemote[n];
454af33a6ddSJed Brown     interpIndices[0] = Qi.x;
455af33a6ddSJed Brown     interpIndices[1] = Qi.y;
456af33a6ddSJed Brown     if (c->velocityInterpLocal) {
457af33a6ddSJed Brown       c->velocityInterpLocal(velocityArray,    interpIndices, c->numVelocityComp, c->velocityComp, velocityValues,    c->velocityCtx);
458af33a6ddSJed Brown       c->velocityInterpLocal(velocityArrayOld, interpIndices, c->numVelocityComp, c->velocityComp, velocityValuesOld, c->velocityCtx);
459af33a6ddSJed Brown     } else {
460af33a6ddSJed Brown       c->velocityInterp(c->velocity,    interpIndices, c->numVelocityComp, c->velocityComp, velocityValues,    c->velocityCtx);
461af33a6ddSJed Brown       c->velocityInterp(c->velocityOld, interpIndices, c->numVelocityComp, c->velocityComp, velocityValuesOld, c->velocityCtx);
462af33a6ddSJed Brown     }
463af33a6ddSJed Brown     Qi.x = 0.5*(velocityValues[0] + velocityValuesOld[0]);
464af33a6ddSJed Brown     Qi.y = 0.5*(velocityValues[1] + velocityValuesOld[1]);
465af33a6ddSJed Brown     c->queueRemote[n] = Qi;
466af33a6ddSJed Brown   }
467af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_HalfTimeRemote,0,0,0,0);CHKERRQ(ierr);
468af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_HalfTimeExchange,0,0,0,0);CHKERRQ(ierr);
469af33a6ddSJed Brown   ierr = CharacteristicGetValuesBegin(c);CHKERRQ(ierr);
470af33a6ddSJed Brown   ierr = CharacteristicGetValuesEnd(c);CHKERRQ(ierr);
471af33a6ddSJed Brown   if (c->velocityInterpLocal) {
472af33a6ddSJed Brown     ierr = DMDAVecRestoreArray(c->velocityDA, velocityLocal,    &velocityArray);CHKERRQ(ierr);
473af33a6ddSJed Brown     ierr = DMDAVecRestoreArray(c->velocityDA, velocityLocalOld, &velocityArrayOld);CHKERRQ(ierr);
474af33a6ddSJed Brown     ierr = DMRestoreLocalVector(c->velocityDA, &velocityLocal);CHKERRQ(ierr);
475af33a6ddSJed Brown     ierr = DMRestoreLocalVector(c->velocityDA, &velocityLocalOld);CHKERRQ(ierr);
476af33a6ddSJed Brown   }
477af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_HalfTimeExchange,0,0,0,0);CHKERRQ(ierr);
478af33a6ddSJed Brown 
479af33a6ddSJed Brown   /* -----------------------------------------------------------------------
480af33a6ddSJed Brown      PART 2, AT t-dt
481af33a6ddSJed Brown      -----------------------------------------------------------------------*/
482af33a6ddSJed Brown 
483af33a6ddSJed Brown   /* GET POSITION AT t_n (local values) */
484af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_FullTimeLocal,0,0,0,0);CHKERRQ(ierr);
4850298fd71SBarry Smith   ierr = PetscInfo(NULL, "Calculating position at t_{n}\n");CHKERRQ(ierr);
486af33a6ddSJed Brown   for (n = 0; n < c->queueSize; n++) {
487af33a6ddSJed Brown     Qi   = c->queue[n];
488af33a6ddSJed Brown     Qi.x = Qi.i - Qi.x*dt;
489af33a6ddSJed Brown     Qi.y = Qi.j - Qi.y*dt;
490af33a6ddSJed Brown 
491af33a6ddSJed Brown     /* Determine whether the position at t-dt is local */
492af33a6ddSJed Brown     Qi.proc = DMDAGetNeighborRelative(da, Qi.x, Qi.y);
493af33a6ddSJed Brown 
494af33a6ddSJed Brown     /* Check for Periodic boundaries and move all periodic points back onto the domain */
495af33a6ddSJed Brown     ierr = DMDAMapCoordsToPeriodicDomain(da,&(Qi.x),&(Qi.y));CHKERRQ(ierr);
496af33a6ddSJed Brown 
497af33a6ddSJed Brown     c->queue[n] = Qi;
498af33a6ddSJed Brown   }
499af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_FullTimeLocal,0,0,0,0);CHKERRQ(ierr);
500af33a6ddSJed Brown 
501af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_FullTimeExchange,0,0,0,0);CHKERRQ(ierr);
502af33a6ddSJed Brown   ierr = CharacteristicSendCoordinatesBegin(c);CHKERRQ(ierr);
503af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_FullTimeExchange,0,0,0,0);CHKERRQ(ierr);
504af33a6ddSJed Brown 
505af33a6ddSJed Brown   /* GET VALUE AT FULL TIME IN THE PAST (LOCAL REQUESTS) */
506af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_FullTimeLocal,0,0,0,0);CHKERRQ(ierr);
507af33a6ddSJed Brown   if (c->fieldInterpLocal) {
508af33a6ddSJed Brown     ierr = DMGetLocalVector(c->fieldDA, &fieldLocal);CHKERRQ(ierr);
509af33a6ddSJed Brown     ierr = DMGlobalToLocalBegin(c->fieldDA, c->field, INSERT_VALUES, fieldLocal);CHKERRQ(ierr);
510af33a6ddSJed Brown     ierr = DMGlobalToLocalEnd(c->fieldDA, c->field, INSERT_VALUES, fieldLocal);CHKERRQ(ierr);
511af33a6ddSJed Brown     ierr = DMDAVecGetArray(c->fieldDA, fieldLocal, &fieldArray);CHKERRQ(ierr);
512af33a6ddSJed Brown   }
5130298fd71SBarry Smith   ierr = PetscInfo(NULL, "Calculating local field at t_{n}\n");CHKERRQ(ierr);
514af33a6ddSJed Brown   for (n = 0; n < c->queueSize; n++) {
515af33a6ddSJed Brown     if (c->neighbors[c->queue[n].proc] == rank) {
516af33a6ddSJed Brown       interpIndices[0] = c->queue[n].x;
517af33a6ddSJed Brown       interpIndices[1] = c->queue[n].y;
518bbd56ea5SKarl Rupp       if (c->fieldInterpLocal) c->fieldInterpLocal(fieldArray, interpIndices, c->numFieldComp, c->fieldComp, fieldValues, c->fieldCtx);
519bbd56ea5SKarl Rupp       else c->fieldInterp(c->field, interpIndices, c->numFieldComp, c->fieldComp, fieldValues, c->fieldCtx);
520bbd56ea5SKarl Rupp       for (comp = 0; comp < c->numFieldComp; comp++) c->queue[n].field[comp] = fieldValues[comp];
521af33a6ddSJed Brown     }
522af33a6ddSJed Brown   }
523af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_FullTimeLocal,0,0,0,0);CHKERRQ(ierr);
524af33a6ddSJed Brown 
525af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_FullTimeExchange,0,0,0,0);CHKERRQ(ierr);
526af33a6ddSJed Brown   ierr = CharacteristicSendCoordinatesEnd(c);CHKERRQ(ierr);
527af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_FullTimeExchange,0,0,0,0);CHKERRQ(ierr);
528af33a6ddSJed Brown 
529af33a6ddSJed Brown   /* GET VALUE AT FULL TIME IN THE PAST (REMOTE REQUESTS) */
530af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_FullTimeRemote,0,0,0,0);CHKERRQ(ierr);
5310298fd71SBarry Smith   ierr = PetscInfo1(NULL, "Calculating %d remote field points at t_{n}\n", c->queueRemoteSize);CHKERRQ(ierr);
532af33a6ddSJed Brown   for (n = 0; n < c->queueRemoteSize; n++) {
533af33a6ddSJed Brown     interpIndices[0] = c->queueRemote[n].x;
534af33a6ddSJed Brown     interpIndices[1] = c->queueRemote[n].y;
535af33a6ddSJed Brown 
536af33a6ddSJed Brown     /* for debugging purposes */
537af33a6ddSJed Brown     if (1) { /* hacked bounds test...let's do better */
538af33a6ddSJed Brown       PetscScalar im = interpIndices[0]; PetscScalar jm = interpIndices[1];
539af33a6ddSJed Brown 
540bbd56ea5SKarl Rupp       if ((im < (PetscScalar) is - 1.) || (im > (PetscScalar) ie) || (jm < (PetscScalar)  js - 1.) || (jm > (PetscScalar) je)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_LIB, "Nonlocal point: (%g,%g)", im, jm);
541af33a6ddSJed Brown     }
542af33a6ddSJed Brown 
543bbd56ea5SKarl Rupp     if (c->fieldInterpLocal) c->fieldInterpLocal(fieldArray, interpIndices, c->numFieldComp, c->fieldComp, fieldValues, c->fieldCtx);
544bbd56ea5SKarl Rupp     else c->fieldInterp(c->field, interpIndices, c->numFieldComp, c->fieldComp, fieldValues, c->fieldCtx);
545bbd56ea5SKarl Rupp     for (comp = 0; comp < c->numFieldComp; comp++) c->queueRemote[n].field[comp] = fieldValues[comp];
546af33a6ddSJed Brown   }
547af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_FullTimeRemote,0,0,0,0);CHKERRQ(ierr);
548af33a6ddSJed Brown 
549af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_FullTimeExchange,0,0,0,0);CHKERRQ(ierr);
550af33a6ddSJed Brown   ierr = CharacteristicGetValuesBegin(c);CHKERRQ(ierr);
551af33a6ddSJed Brown   ierr = CharacteristicGetValuesEnd(c);CHKERRQ(ierr);
552af33a6ddSJed Brown   if (c->fieldInterpLocal) {
553af33a6ddSJed Brown     ierr = DMDAVecRestoreArray(c->fieldDA, fieldLocal, &fieldArray);CHKERRQ(ierr);
554af33a6ddSJed Brown     ierr = DMRestoreLocalVector(c->fieldDA, &fieldLocal);CHKERRQ(ierr);
555af33a6ddSJed Brown   }
556af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_FullTimeExchange,0,0,0,0);CHKERRQ(ierr);
557af33a6ddSJed Brown 
558af33a6ddSJed Brown   /* Return field of characteristics at t_n-1 */
559af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_DAUpdate,0,0,0,0);CHKERRQ(ierr);
560af33a6ddSJed Brown   ierr = DMDAGetInfo(c->fieldDA,0,0,0,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
561af33a6ddSJed Brown   ierr = DMDAVecGetArray(c->fieldDA, solution, &solArray);CHKERRQ(ierr);
562af33a6ddSJed Brown   for (n = 0; n < c->queueSize; n++) {
563af33a6ddSJed Brown     Qi = c->queue[n];
564bbd56ea5SKarl Rupp     for (comp = 0; comp < c->numFieldComp; comp++) solArray[Qi.j][Qi.i*dof+c->fieldComp[comp]] = Qi.field[comp];
565af33a6ddSJed Brown   }
566af33a6ddSJed Brown   ierr = DMDAVecRestoreArray(c->fieldDA, solution, &solArray);CHKERRQ(ierr);
567af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_DAUpdate,0,0,0,0);CHKERRQ(ierr);
568af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_Solve,0,0,0,0);CHKERRQ(ierr);
569af33a6ddSJed Brown 
570af33a6ddSJed Brown   /* Cleanup */
571af33a6ddSJed Brown   ierr = PetscFree(interpIndices);CHKERRQ(ierr);
572af33a6ddSJed Brown   ierr = PetscFree(velocityValues);CHKERRQ(ierr);
573af33a6ddSJed Brown   ierr = PetscFree(velocityValuesOld);CHKERRQ(ierr);
574af33a6ddSJed Brown   ierr = PetscFree(fieldValues);CHKERRQ(ierr);
575af33a6ddSJed Brown   PetscFunctionReturn(0);
576af33a6ddSJed Brown }
577af33a6ddSJed Brown 
578af33a6ddSJed Brown #undef __FUNCT__
579af33a6ddSJed Brown #define __FUNCT__ "CharacteristicSetNeighbors"
580af33a6ddSJed Brown PetscErrorCode CharacteristicSetNeighbors(Characteristic c, PetscInt numNeighbors, PetscMPIInt neighbors[])
581af33a6ddSJed Brown {
582af33a6ddSJed Brown   PetscErrorCode ierr;
583af33a6ddSJed Brown 
584af33a6ddSJed Brown   PetscFunctionBegin;
585af33a6ddSJed Brown   c->numNeighbors = numNeighbors;
5866eaa7dc8SBarry Smith   ierr = PetscFree(c->neighbors);CHKERRQ(ierr);
587*785e854fSJed Brown   ierr = PetscMalloc1(numNeighbors, &c->neighbors);CHKERRQ(ierr);
588af33a6ddSJed Brown   ierr = PetscMemcpy(c->neighbors, neighbors, numNeighbors * sizeof(PetscMPIInt));CHKERRQ(ierr);
589af33a6ddSJed Brown   PetscFunctionReturn(0);
590af33a6ddSJed Brown }
591af33a6ddSJed Brown 
592af33a6ddSJed Brown #undef __FUNCT__
593af33a6ddSJed Brown #define __FUNCT__ "CharacteristicAddPoint"
594af33a6ddSJed Brown PetscErrorCode CharacteristicAddPoint(Characteristic c, CharacteristicPointDA2D *point)
595af33a6ddSJed Brown {
596af33a6ddSJed Brown   PetscFunctionBegin;
597f23aa3ddSBarry Smith   if (c->queueSize >= c->queueMax) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Exceeeded maximum queue size %d", c->queueMax);
598af33a6ddSJed Brown   c->queue[c->queueSize++] = *point;
599af33a6ddSJed Brown   PetscFunctionReturn(0);
600af33a6ddSJed Brown }
601af33a6ddSJed Brown 
602af33a6ddSJed Brown #undef __FUNCT__
603af33a6ddSJed Brown #define __FUNCT__ "CharacteristicSendCoordinatesBegin"
604af33a6ddSJed Brown int CharacteristicSendCoordinatesBegin(Characteristic c)
605af33a6ddSJed Brown {
606af33a6ddSJed Brown   PetscMPIInt    rank, tag = 121;
607af33a6ddSJed Brown   PetscInt       i, n;
608af33a6ddSJed Brown   PetscErrorCode ierr;
609af33a6ddSJed Brown 
610af33a6ddSJed Brown   PetscFunctionBegin;
611ce94432eSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)c), &rank);CHKERRQ(ierr);
6120b8f38c8SBarry Smith   ierr = CharacteristicHeapSort(c, c->queue, c->queueSize);CHKERRQ(ierr);
613af33a6ddSJed Brown   ierr = PetscMemzero(c->needCount, c->numNeighbors * sizeof(PetscInt));CHKERRQ(ierr);
614bbd56ea5SKarl Rupp   for (i = 0;  i < c->queueSize; i++) c->needCount[c->queue[i].proc]++;
615af33a6ddSJed Brown   c->fillCount[0] = 0;
616af33a6ddSJed Brown   for (n = 1; n < c->numNeighbors; n++) {
617ce94432eSBarry Smith     ierr = MPI_Irecv(&(c->fillCount[n]), 1, MPIU_INT, c->neighbors[n], tag, PetscObjectComm((PetscObject)c), &(c->request[n-1]));CHKERRQ(ierr);
618af33a6ddSJed Brown   }
619af33a6ddSJed Brown   for (n = 1; n < c->numNeighbors; n++) {
620ce94432eSBarry Smith     ierr = MPI_Send(&(c->needCount[n]), 1, MPIU_INT, c->neighbors[n], tag, PetscObjectComm((PetscObject)c));CHKERRQ(ierr);
621af33a6ddSJed Brown   }
622af33a6ddSJed Brown   ierr = MPI_Waitall(c->numNeighbors-1, c->request, c->status);CHKERRQ(ierr);
623af33a6ddSJed Brown   /* Initialize the remote queue */
624af33a6ddSJed Brown   c->queueLocalMax  = c->localOffsets[0]  = 0;
625af33a6ddSJed Brown   c->queueRemoteMax = c->remoteOffsets[0] = 0;
626af33a6ddSJed Brown   for (n = 1; n < c->numNeighbors; n++) {
627af33a6ddSJed Brown     c->remoteOffsets[n] = c->queueRemoteMax;
628af33a6ddSJed Brown     c->queueRemoteMax  += c->fillCount[n];
629af33a6ddSJed Brown     c->localOffsets[n]  = c->queueLocalMax;
630af33a6ddSJed Brown     c->queueLocalMax   += c->needCount[n];
631af33a6ddSJed Brown   }
632af33a6ddSJed Brown   /* HACK BEGIN */
633bbd56ea5SKarl Rupp   for (n = 1; n < c->numNeighbors; n++) c->localOffsets[n] += c->needCount[0];
634af33a6ddSJed Brown   c->needCount[0] = 0;
635af33a6ddSJed Brown   /* HACK END */
636af33a6ddSJed Brown   if (c->queueRemoteMax) {
637af33a6ddSJed Brown     ierr = PetscMalloc(sizeof(CharacteristicPointDA2D) * c->queueRemoteMax, &c->queueRemote);CHKERRQ(ierr);
6380298fd71SBarry Smith   } else c->queueRemote = NULL;
639af33a6ddSJed Brown   c->queueRemoteSize = c->queueRemoteMax;
640af33a6ddSJed Brown 
641af33a6ddSJed Brown   /* Send and Receive requests for values at t_n+1/2, giving the coordinates for interpolation */
642af33a6ddSJed Brown   for (n = 1; n < c->numNeighbors; n++) {
6430298fd71SBarry Smith     ierr = PetscInfo2(NULL, "Receiving %d requests for values from proc %d\n", c->fillCount[n], c->neighbors[n]);CHKERRQ(ierr);
644ce94432eSBarry 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]));CHKERRQ(ierr);
645af33a6ddSJed Brown   }
646af33a6ddSJed Brown   for (n = 1; n < c->numNeighbors; n++) {
6470298fd71SBarry Smith     ierr = PetscInfo2(NULL, "Sending %d requests for values from proc %d\n", c->needCount[n], c->neighbors[n]);CHKERRQ(ierr);
648ce94432eSBarry Smith     ierr = MPI_Send(&(c->queue[c->localOffsets[n]]), c->needCount[n], c->itemType, c->neighbors[n], tag, PetscObjectComm((PetscObject)c));CHKERRQ(ierr);
649af33a6ddSJed Brown   }
650af33a6ddSJed Brown   PetscFunctionReturn(0);
651af33a6ddSJed Brown }
652af33a6ddSJed Brown 
653af33a6ddSJed Brown #undef __FUNCT__
654af33a6ddSJed Brown #define __FUNCT__ "CharacteristicSendCoordinatesEnd"
655af33a6ddSJed Brown PetscErrorCode CharacteristicSendCoordinatesEnd(Characteristic c)
656af33a6ddSJed Brown {
657af33a6ddSJed Brown #if 0
658af33a6ddSJed Brown   PetscMPIInt rank;
659af33a6ddSJed Brown   PetscInt    n;
660af33a6ddSJed Brown #endif
661af33a6ddSJed Brown   PetscErrorCode ierr;
662af33a6ddSJed Brown 
663af33a6ddSJed Brown   PetscFunctionBegin;
664af33a6ddSJed Brown   ierr = MPI_Waitall(c->numNeighbors-1, c->request, c->status);CHKERRQ(ierr);
665af33a6ddSJed Brown #if 0
666ce94432eSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)c), &rank);CHKERRQ(ierr);
667af33a6ddSJed Brown   for (n = 0; n < c->queueRemoteSize; n++) {
668f23aa3ddSBarry Smith     if (c->neighbors[c->queueRemote[n].proc] == rank) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB, "This is messed up, n = %d proc = %d", n, c->queueRemote[n].proc);
669af33a6ddSJed Brown   }
670af33a6ddSJed Brown #endif
671af33a6ddSJed Brown   PetscFunctionReturn(0);
672af33a6ddSJed Brown }
673af33a6ddSJed Brown 
674af33a6ddSJed Brown #undef __FUNCT__
675af33a6ddSJed Brown #define __FUNCT__ "CharacteristicGetValuesBegin"
676af33a6ddSJed Brown PetscErrorCode CharacteristicGetValuesBegin(Characteristic c)
677af33a6ddSJed Brown {
678af33a6ddSJed Brown   PetscMPIInt    tag = 121;
679af33a6ddSJed Brown   PetscInt       n;
680af33a6ddSJed Brown   PetscErrorCode ierr;
681af33a6ddSJed Brown 
682af33a6ddSJed Brown   PetscFunctionBegin;
683af33a6ddSJed Brown   /* SEND AND RECIEVE FILLED REQUESTS for velocities at t_n+1/2 */
684af33a6ddSJed Brown   for (n = 1; n < c->numNeighbors; n++) {
685ce94432eSBarry 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]));CHKERRQ(ierr);
686af33a6ddSJed Brown   }
687af33a6ddSJed Brown   for (n = 1; n < c->numNeighbors; n++) {
688ce94432eSBarry Smith     ierr = MPI_Send(&(c->queueRemote[c->remoteOffsets[n]]), c->fillCount[n], c->itemType, c->neighbors[n], tag, PetscObjectComm((PetscObject)c));CHKERRQ(ierr);
689af33a6ddSJed Brown   }
690af33a6ddSJed Brown   PetscFunctionReturn(0);
691af33a6ddSJed Brown }
692af33a6ddSJed Brown 
693af33a6ddSJed Brown #undef __FUNCT__
694af33a6ddSJed Brown #define __FUNCT__ "CharacteristicGetValuesEnd"
695af33a6ddSJed Brown PetscErrorCode CharacteristicGetValuesEnd(Characteristic c)
696af33a6ddSJed Brown {
697af33a6ddSJed Brown   PetscErrorCode ierr;
698af33a6ddSJed Brown 
699af33a6ddSJed Brown   PetscFunctionBegin;
700af33a6ddSJed Brown   ierr = MPI_Waitall(c->numNeighbors-1, c->request, c->status);CHKERRQ(ierr);
701af33a6ddSJed Brown   /* Free queue of requests from other procs */
702af33a6ddSJed Brown   ierr = PetscFree(c->queueRemote);CHKERRQ(ierr);
703af33a6ddSJed Brown   PetscFunctionReturn(0);
704af33a6ddSJed Brown }
705af33a6ddSJed Brown 
706af33a6ddSJed Brown /*---------------------------------------------------------------------*/
707af33a6ddSJed Brown #undef __FUNCT__
7080b8f38c8SBarry Smith #define __FUNCT__ "CharacteristicHeapSort"
709af33a6ddSJed Brown /*
710af33a6ddSJed Brown   Based on code from http://linux.wku.edu/~lamonml/algor/sort/heap.html
711af33a6ddSJed Brown */
7120b8f38c8SBarry Smith PetscErrorCode CharacteristicHeapSort(Characteristic c, Queue queue, PetscInt size)
713af33a6ddSJed Brown /*---------------------------------------------------------------------*/
714af33a6ddSJed Brown {
7150b8f38c8SBarry Smith   PetscErrorCode          ierr;
716af33a6ddSJed Brown   CharacteristicPointDA2D temp;
7170b8f38c8SBarry Smith   PetscInt                n;
718af33a6ddSJed Brown 
7190b8f38c8SBarry Smith   PetscFunctionBegin;
720af33a6ddSJed Brown   if (0) { /* Check the order of the queue before sorting */
7210298fd71SBarry Smith     PetscInfo(NULL, "Before Heap sort\n");
722af33a6ddSJed Brown     for (n=0; n<size; n++) {
7230298fd71SBarry Smith       ierr = PetscInfo2(NULL,"%d %d\n",n,queue[n].proc);CHKERRQ(ierr);
724af33a6ddSJed Brown     }
725af33a6ddSJed Brown   }
726af33a6ddSJed Brown 
727af33a6ddSJed Brown   /* SORTING PHASE */
7280b8f38c8SBarry Smith   for (n = (size / 2)-1; n >= 0; n--) {
7290b8f38c8SBarry Smith     ierr = CharacteristicSiftDown(c, queue, n, size-1);CHKERRQ(ierr); /* Rich had size-1 here, Matt had size*/
7300b8f38c8SBarry Smith   }
731af33a6ddSJed Brown   for (n = size-1; n >= 1; n--) {
732af33a6ddSJed Brown     temp     = queue[0];
733af33a6ddSJed Brown     queue[0] = queue[n];
734af33a6ddSJed Brown     queue[n] = temp;
7350b8f38c8SBarry Smith     ierr     = CharacteristicSiftDown(c, queue, 0, n-1);CHKERRQ(ierr);
736af33a6ddSJed Brown   }
737af33a6ddSJed Brown   if (0) { /* Check the order of the queue after sorting */
7380298fd71SBarry Smith     ierr = PetscInfo(NULL, "Avter  Heap sort\n");CHKERRQ(ierr);
739af33a6ddSJed Brown     for (n=0; n<size; n++) {
7400298fd71SBarry Smith       ierr = PetscInfo2(NULL,"%d %d\n",n,queue[n].proc);CHKERRQ(ierr);
741af33a6ddSJed Brown     }
742af33a6ddSJed Brown   }
7430b8f38c8SBarry Smith   PetscFunctionReturn(0);
744af33a6ddSJed Brown }
745af33a6ddSJed Brown 
746af33a6ddSJed Brown /*---------------------------------------------------------------------*/
747af33a6ddSJed Brown #undef __FUNCT__
7480b8f38c8SBarry Smith #define __FUNCT__ "CharacteristicSiftDown"
749af33a6ddSJed Brown /*
750af33a6ddSJed Brown   Based on code from http://linux.wku.edu/~lamonml/algor/sort/heap.html
751af33a6ddSJed Brown */
7520b8f38c8SBarry Smith PetscErrorCode CharacteristicSiftDown(Characteristic c, Queue queue, PetscInt root, PetscInt bottom)
753af33a6ddSJed Brown /*---------------------------------------------------------------------*/
754af33a6ddSJed Brown {
755af33a6ddSJed Brown   PetscBool               done = PETSC_FALSE;
756af33a6ddSJed Brown   PetscInt                maxChild;
757af33a6ddSJed Brown   CharacteristicPointDA2D temp;
758af33a6ddSJed Brown 
759af33a6ddSJed Brown   PetscFunctionBegin;
760af33a6ddSJed Brown   while ((root*2 <= bottom) && (!done)) {
761af33a6ddSJed Brown     if (root*2 == bottom) maxChild = root * 2;
762af33a6ddSJed Brown     else if (queue[root*2].proc > queue[root*2+1].proc) maxChild = root * 2;
763af33a6ddSJed Brown     else maxChild = root * 2 + 1;
764af33a6ddSJed Brown 
765af33a6ddSJed Brown     if (queue[root].proc < queue[maxChild].proc) {
766af33a6ddSJed Brown       temp            = queue[root];
767af33a6ddSJed Brown       queue[root]     = queue[maxChild];
768af33a6ddSJed Brown       queue[maxChild] = temp;
769af33a6ddSJed Brown       root            = maxChild;
770db4deed7SKarl Rupp     } else done = PETSC_TRUE;
771af33a6ddSJed Brown   }
772af33a6ddSJed Brown   PetscFunctionReturn(0);
773af33a6ddSJed Brown }
774af33a6ddSJed Brown 
775af33a6ddSJed Brown #undef __FUNCT__
776af33a6ddSJed Brown #define __FUNCT__ "DMDAGetNeighborsRank"
777af33a6ddSJed Brown /* [center, left, top-left, top, top-right, right, bottom-right, bottom, bottom-left] */
778af33a6ddSJed Brown PetscErrorCode DMDAGetNeighborsRank(DM da, PetscMPIInt neighbors[])
779af33a6ddSJed Brown {
780af33a6ddSJed Brown   DMDABoundaryType bx, by;
781af33a6ddSJed Brown   PetscBool        IPeriodic = PETSC_FALSE, JPeriodic = PETSC_FALSE;
782af33a6ddSJed Brown   MPI_Comm         comm;
783af33a6ddSJed Brown   PetscMPIInt      rank;
784af33a6ddSJed Brown   PetscInt         **procs,pi,pj,pim,pip,pjm,pjp,PI,PJ;
785af33a6ddSJed Brown   PetscErrorCode   ierr;
786af33a6ddSJed Brown 
787af33a6ddSJed Brown   PetscFunctionBegin;
788af33a6ddSJed Brown   ierr = PetscObjectGetComm((PetscObject) da, &comm);CHKERRQ(ierr);
789af33a6ddSJed Brown   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
79022d28d08SBarry Smith   ierr = DMDAGetInfo(da, 0, 0, 0, 0, &PI,&PJ, 0, 0, 0, &bx, &by,0, 0);CHKERRQ(ierr);
791af33a6ddSJed Brown 
792bbd56ea5SKarl Rupp   if (bx == DMDA_BOUNDARY_PERIODIC) IPeriodic = PETSC_TRUE;
793bbd56ea5SKarl Rupp   if (by == DMDA_BOUNDARY_PERIODIC) JPeriodic = PETSC_TRUE;
794af33a6ddSJed Brown 
795af33a6ddSJed Brown   neighbors[0] = rank;
796af33a6ddSJed Brown   rank = 0;
797af33a6ddSJed Brown   ierr = PetscMalloc(sizeof(PetscInt*)*PJ,&procs);CHKERRQ(ierr);
798af33a6ddSJed Brown   for (pj=0; pj<PJ; pj++) {
799af33a6ddSJed Brown     ierr = PetscMalloc(sizeof(PetscInt)*PI,&(procs[pj]));CHKERRQ(ierr);
800af33a6ddSJed Brown     for (pi=0; pi<PI; pi++) {
801af33a6ddSJed Brown       procs[pj][pi] = rank;
802af33a6ddSJed Brown       rank++;
803af33a6ddSJed Brown     }
804af33a6ddSJed Brown   }
805af33a6ddSJed Brown 
806af33a6ddSJed Brown   pi  = neighbors[0] % PI;
807af33a6ddSJed Brown   pj  = neighbors[0] / PI;
808af33a6ddSJed Brown   pim = pi-1;  if (pim<0) pim=PI-1;
809af33a6ddSJed Brown   pip = (pi+1)%PI;
810af33a6ddSJed Brown   pjm = pj-1;  if (pjm<0) pjm=PJ-1;
811af33a6ddSJed Brown   pjp = (pj+1)%PJ;
812af33a6ddSJed Brown 
813af33a6ddSJed Brown   neighbors[1] = procs[pj] [pim];
814af33a6ddSJed Brown   neighbors[2] = procs[pjp][pim];
815af33a6ddSJed Brown   neighbors[3] = procs[pjp][pi];
816af33a6ddSJed Brown   neighbors[4] = procs[pjp][pip];
817af33a6ddSJed Brown   neighbors[5] = procs[pj] [pip];
818af33a6ddSJed Brown   neighbors[6] = procs[pjm][pip];
819af33a6ddSJed Brown   neighbors[7] = procs[pjm][pi];
820af33a6ddSJed Brown   neighbors[8] = procs[pjm][pim];
821af33a6ddSJed Brown 
822af33a6ddSJed Brown   if (!IPeriodic) {
823af33a6ddSJed Brown     if (pi==0)    neighbors[1]=neighbors[2]=neighbors[8]=neighbors[0];
824af33a6ddSJed Brown     if (pi==PI-1) neighbors[4]=neighbors[5]=neighbors[6]=neighbors[0];
825af33a6ddSJed Brown   }
826af33a6ddSJed Brown 
827af33a6ddSJed Brown   if (!JPeriodic) {
828af33a6ddSJed Brown     if (pj==0)    neighbors[6]=neighbors[7]=neighbors[8]=neighbors[0];
829af33a6ddSJed Brown     if (pj==PJ-1) neighbors[2]=neighbors[3]=neighbors[4]=neighbors[0];
830af33a6ddSJed Brown   }
831af33a6ddSJed Brown 
832af33a6ddSJed Brown   for (pj = 0; pj < PJ; pj++) {
833af33a6ddSJed Brown     ierr = PetscFree(procs[pj]);CHKERRQ(ierr);
834af33a6ddSJed Brown   }
835af33a6ddSJed Brown   ierr = PetscFree(procs);CHKERRQ(ierr);
836af33a6ddSJed Brown   PetscFunctionReturn(0);
837af33a6ddSJed Brown }
838af33a6ddSJed Brown 
839af33a6ddSJed Brown #undef __FUNCT__
840af33a6ddSJed Brown #define __FUNCT__ "DMDAGetNeighborRelative"
841af33a6ddSJed Brown /*
842af33a6ddSJed Brown   SUBDOMAIN NEIGHBORHOOD PROCESS MAP:
843af33a6ddSJed Brown     2 | 3 | 4
844af33a6ddSJed Brown     __|___|__
845af33a6ddSJed Brown     1 | 0 | 5
846af33a6ddSJed Brown     __|___|__
847af33a6ddSJed Brown     8 | 7 | 6
848af33a6ddSJed Brown       |   |
849af33a6ddSJed Brown */
850af33a6ddSJed Brown PetscInt DMDAGetNeighborRelative(DM da, PassiveReal ir, PassiveReal jr)
851af33a6ddSJed Brown {
852af33a6ddSJed Brown   DMDALocalInfo  info;
853af33a6ddSJed Brown   PassiveReal    is,ie,js,je;
854af33a6ddSJed Brown   PetscErrorCode ierr;
855af33a6ddSJed Brown 
856af33a6ddSJed Brown   ierr = DMDAGetLocalInfo(da, &info);CHKERRQ(ierr);
857af33a6ddSJed Brown   is   = (PassiveReal) info.xs - 0.5; ie = (PassiveReal) info.xs + info.xm - 0.5;
858af33a6ddSJed Brown   js   = (PassiveReal) info.ys - 0.5; je = (PassiveReal) info.ys + info.ym - 0.5;
859af33a6ddSJed Brown 
860af33a6ddSJed Brown   if (ir >= is && ir <= ie) { /* center column */
861bbd56ea5SKarl Rupp     if (jr >= js && jr <= je) return 0;
862bbd56ea5SKarl Rupp     else if (jr < js)         return 7;
863bbd56ea5SKarl Rupp     else                      return 3;
864af33a6ddSJed Brown   } else if (ir < is) {     /* left column */
865bbd56ea5SKarl Rupp     if (jr >= js && jr <= je) return 1;
866bbd56ea5SKarl Rupp     else if (jr < js)         return 8;
867bbd56ea5SKarl Rupp     else                      return 2;
868af33a6ddSJed Brown   } else {                  /* right column */
869bbd56ea5SKarl Rupp     if (jr >= js && jr <= je) return 5;
870bbd56ea5SKarl Rupp     else if (jr < js)         return 6;
871bbd56ea5SKarl Rupp     else                      return 4;
872af33a6ddSJed Brown   }
873af33a6ddSJed Brown }
874