xref: /petsc/src/ts/characteristic/interface/characteristic.c (revision ce94432eddcd14845bc7e8083b7f8ea723b9bf7d)
1af33a6ddSJed Brown 
2b45d2f2cSJed Brown #include <petsc-private/characteristicimpl.h> /*I "petsccharacteristic.h" I*/
3af33a6ddSJed Brown 
4af33a6ddSJed Brown PetscClassId  CHARACTERISTIC_CLASSID;
5af33a6ddSJed Brown PetscLogEvent CHARACTERISTIC_SetUp, CHARACTERISTIC_Solve, CHARACTERISTIC_QueueSetup, CHARACTERISTIC_DAUpdate;
6af33a6ddSJed Brown PetscLogEvent CHARACTERISTIC_HalfTimeLocal, CHARACTERISTIC_HalfTimeRemote, CHARACTERISTIC_HalfTimeExchange;
7af33a6ddSJed Brown PetscLogEvent CHARACTERISTIC_FullTimeLocal, CHARACTERISTIC_FullTimeRemote, CHARACTERISTIC_FullTimeExchange;
8af33a6ddSJed Brown /*
9af33a6ddSJed Brown    Contains the list of registered characteristic routines
10af33a6ddSJed Brown */
110298fd71SBarry Smith PetscFunctionList CharacteristicList              = NULL;
12140e18c1SBarry Smith PetscBool         CharacteristicRegisterAllCalled = PETSC_FALSE;
13af33a6ddSJed Brown 
14af33a6ddSJed Brown PetscErrorCode DMDAGetNeighborsRank(DM, PetscMPIInt []);
15af33a6ddSJed Brown PetscInt       DMDAGetNeighborRelative(DM, PassiveReal, PassiveReal);
16af33a6ddSJed Brown PetscErrorCode DMDAMapToPeriodicDomain(DM, PetscScalar []);
17af33a6ddSJed Brown 
180b8f38c8SBarry Smith PetscErrorCode CharacteristicHeapSort(Characteristic, Queue, PetscInt);
190b8f38c8SBarry Smith PetscErrorCode CharacteristicSiftDown(Characteristic, Queue, PetscInt, PetscInt);
20af33a6ddSJed Brown 
21af33a6ddSJed Brown #undef __FUNCT__
22af33a6ddSJed Brown #define __FUNCT__ "CharacteristicView"
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) {
31*ce94432eSBarry 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 
45af33a6ddSJed Brown #undef __FUNCT__
46af33a6ddSJed Brown #define __FUNCT__ "CharacteristicDestroy"
476bf464f9SBarry Smith PetscErrorCode CharacteristicDestroy(Characteristic *c)
48af33a6ddSJed Brown {
49af33a6ddSJed Brown   PetscErrorCode ierr;
50af33a6ddSJed Brown 
51af33a6ddSJed Brown   PetscFunctionBegin;
526bf464f9SBarry Smith   if (!*c) PetscFunctionReturn(0);
536bf464f9SBarry Smith   PetscValidHeaderSpecific(*c, CHARACTERISTIC_CLASSID, 1);
546bf464f9SBarry Smith   if (--((PetscObject)(*c))->refct > 0) PetscFunctionReturn(0);
55af33a6ddSJed Brown 
566bf464f9SBarry Smith   if ((*c)->ops->destroy) {
576bf464f9SBarry Smith     ierr = (*(*c)->ops->destroy)((*c));CHKERRQ(ierr);
58af33a6ddSJed Brown   }
596bf464f9SBarry Smith   ierr = MPI_Type_free(&(*c)->itemType);CHKERRQ(ierr);
606bf464f9SBarry Smith   ierr = PetscFree((*c)->queue);CHKERRQ(ierr);
616bf464f9SBarry Smith   ierr = PetscFree((*c)->queueLocal);CHKERRQ(ierr);
626bf464f9SBarry Smith   ierr = PetscFree((*c)->queueRemote);CHKERRQ(ierr);
636bf464f9SBarry Smith   ierr = PetscFree((*c)->neighbors);CHKERRQ(ierr);
646bf464f9SBarry Smith   ierr = PetscFree((*c)->needCount);CHKERRQ(ierr);
656bf464f9SBarry Smith   ierr = PetscFree((*c)->localOffsets);CHKERRQ(ierr);
666bf464f9SBarry Smith   ierr = PetscFree((*c)->fillCount);CHKERRQ(ierr);
676bf464f9SBarry Smith   ierr = PetscFree((*c)->remoteOffsets);CHKERRQ(ierr);
686bf464f9SBarry Smith   ierr = PetscFree((*c)->request);CHKERRQ(ierr);
696bf464f9SBarry Smith   ierr = PetscFree((*c)->status);CHKERRQ(ierr);
70af33a6ddSJed Brown   ierr = PetscHeaderDestroy(c);CHKERRQ(ierr);
71af33a6ddSJed Brown   PetscFunctionReturn(0);
72af33a6ddSJed Brown }
73af33a6ddSJed Brown 
74af33a6ddSJed Brown #undef __FUNCT__
75af33a6ddSJed Brown #define __FUNCT__ "CharacteristicCreate"
76af33a6ddSJed Brown PetscErrorCode CharacteristicCreate(MPI_Comm comm, Characteristic *c)
77af33a6ddSJed Brown {
78af33a6ddSJed Brown   Characteristic newC;
79af33a6ddSJed Brown   PetscErrorCode ierr;
80af33a6ddSJed Brown 
81af33a6ddSJed Brown   PetscFunctionBegin;
82af33a6ddSJed Brown   PetscValidPointer(c, 2);
830298fd71SBarry Smith   *c = NULL;
84519f805aSKarl Rupp #if !defined(PETSC_USE_DYNAMIC_LIBRARIES)
850298fd71SBarry Smith   ierr = CharacteristicInitializePackage(NULL);CHKERRQ(ierr);
86af33a6ddSJed Brown #endif
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 
186*ce94432eSBarry Smith   ierr =  PetscFunctionListFind(PetscObjectComm((PetscObject)c),CharacteristicList, type,PETSC_TRUE, (void (**)(void)) &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
236af33a6ddSJed Brown   CharacteristicRegister - See CharacteristicRegisterDynamic()
237af33a6ddSJed Brown 
238af33a6ddSJed Brown   Level: advanced
239af33a6ddSJed Brown @*/
240af33a6ddSJed Brown PetscErrorCode CharacteristicRegister(const char sname[],const char path[],const char name[],PetscErrorCode (*function)(Characteristic))
241af33a6ddSJed Brown {
242af33a6ddSJed Brown   PetscErrorCode ierr;
243af33a6ddSJed Brown   char           fullname[PETSC_MAX_PATH_LEN];
244af33a6ddSJed Brown 
245af33a6ddSJed Brown   PetscFunctionBegin;
246140e18c1SBarry Smith   ierr = PetscFunctionListConcat(path,name,fullname);CHKERRQ(ierr);
247140e18c1SBarry Smith   ierr = PetscFunctionListAdd(PETSC_COMM_WORLD,&CharacteristicList,sname,fullname,(void (*)(void))function);CHKERRQ(ierr);
248af33a6ddSJed Brown   PetscFunctionReturn(0);
249af33a6ddSJed Brown }
250af33a6ddSJed Brown 
251af33a6ddSJed Brown #undef __FUNCT__
252af33a6ddSJed Brown #define __FUNCT__ "CharacteristicSetVelocityInterpolation"
253af33a6ddSJed 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)
254af33a6ddSJed Brown {
255af33a6ddSJed Brown   PetscFunctionBegin;
256af33a6ddSJed Brown   c->velocityDA      = da;
257af33a6ddSJed Brown   c->velocity        = v;
258af33a6ddSJed Brown   c->velocityOld     = vOld;
259af33a6ddSJed Brown   c->numVelocityComp = numComponents;
260af33a6ddSJed Brown   c->velocityComp    = components;
261af33a6ddSJed Brown   c->velocityInterp  = interp;
262af33a6ddSJed Brown   c->velocityCtx     = ctx;
263af33a6ddSJed Brown   PetscFunctionReturn(0);
264af33a6ddSJed Brown }
265af33a6ddSJed Brown 
266af33a6ddSJed Brown #undef __FUNCT__
267af33a6ddSJed Brown #define __FUNCT__ "CharacteristicSetVelocityInterpolationLocal"
268af33a6ddSJed 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)
269af33a6ddSJed Brown {
270af33a6ddSJed Brown   PetscFunctionBegin;
271af33a6ddSJed Brown   c->velocityDA          = da;
272af33a6ddSJed Brown   c->velocity            = v;
273af33a6ddSJed Brown   c->velocityOld         = vOld;
274af33a6ddSJed Brown   c->numVelocityComp     = numComponents;
275af33a6ddSJed Brown   c->velocityComp        = components;
276af33a6ddSJed Brown   c->velocityInterpLocal = interp;
277af33a6ddSJed Brown   c->velocityCtx         = ctx;
278af33a6ddSJed Brown   PetscFunctionReturn(0);
279af33a6ddSJed Brown }
280af33a6ddSJed Brown 
281af33a6ddSJed Brown #undef __FUNCT__
282af33a6ddSJed Brown #define __FUNCT__ "CharacteristicSetFieldInterpolation"
283af33a6ddSJed Brown PetscErrorCode CharacteristicSetFieldInterpolation(Characteristic c, DM da, Vec v, PetscInt numComponents, PetscInt components[], PetscErrorCode (*interp)(Vec, PetscReal[], PetscInt, PetscInt[], PetscScalar[], void*), void *ctx)
284af33a6ddSJed Brown {
285af33a6ddSJed Brown   PetscFunctionBegin;
286af33a6ddSJed Brown #if 0
287af33a6ddSJed 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.");
288af33a6ddSJed Brown #endif
289af33a6ddSJed Brown   c->fieldDA      = da;
290af33a6ddSJed Brown   c->field        = v;
291af33a6ddSJed Brown   c->numFieldComp = numComponents;
292af33a6ddSJed Brown   c->fieldComp    = components;
293af33a6ddSJed Brown   c->fieldInterp  = interp;
294af33a6ddSJed Brown   c->fieldCtx     = ctx;
295af33a6ddSJed Brown   PetscFunctionReturn(0);
296af33a6ddSJed Brown }
297af33a6ddSJed Brown 
298af33a6ddSJed Brown #undef __FUNCT__
299af33a6ddSJed Brown #define __FUNCT__ "CharacteristicSetFieldInterpolationLocal"
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 #undef __FUNCT__
316af33a6ddSJed Brown #define __FUNCT__ "CharacteristicSolve"
317af33a6ddSJed Brown PetscErrorCode CharacteristicSolve(Characteristic c, PetscReal dt, Vec solution)
318af33a6ddSJed Brown {
319af33a6ddSJed Brown   CharacteristicPointDA2D Qi;
320af33a6ddSJed Brown   DM                      da = c->velocityDA;
321af33a6ddSJed Brown   Vec                     velocityLocal, velocityLocalOld;
322af33a6ddSJed Brown   Vec                     fieldLocal;
323af33a6ddSJed Brown   DMDALocalInfo           info;
324af33a6ddSJed Brown   PetscScalar             **solArray;
325af33a6ddSJed Brown   void                    *velocityArray;
326af33a6ddSJed Brown   void                    *velocityArrayOld;
327af33a6ddSJed Brown   void                    *fieldArray;
328af33a6ddSJed Brown   PassiveScalar           *interpIndices;
329af33a6ddSJed Brown   PassiveScalar           *velocityValues, *velocityValuesOld;
330af33a6ddSJed Brown   PassiveScalar           *fieldValues;
331af33a6ddSJed Brown   PetscMPIInt             rank;
332af33a6ddSJed Brown   PetscInt                dim;
333af33a6ddSJed Brown   PetscMPIInt             neighbors[9];
334af33a6ddSJed Brown   PetscInt                dof;
335af33a6ddSJed Brown   PetscInt                gx, gy;
336af33a6ddSJed Brown   PetscInt                n, is, ie, js, je, comp;
337af33a6ddSJed Brown   PetscErrorCode          ierr;
338af33a6ddSJed Brown 
339af33a6ddSJed Brown   PetscFunctionBegin;
340af33a6ddSJed Brown   c->queueSize = 0;
341*ce94432eSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)c), &rank);CHKERRQ(ierr);
342af33a6ddSJed Brown   ierr = DMDAGetNeighborsRank(da, neighbors);CHKERRQ(ierr);
343af33a6ddSJed Brown   ierr = CharacteristicSetNeighbors(c, 9, neighbors);CHKERRQ(ierr);
344af33a6ddSJed Brown   ierr = CharacteristicSetUp(c);CHKERRQ(ierr);
345af33a6ddSJed Brown   /* global and local grid info */
346af33a6ddSJed Brown   ierr = DMDAGetInfo(da, &dim, &gx, &gy, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);CHKERRQ(ierr);
347af33a6ddSJed Brown   ierr = DMDAGetLocalInfo(da, &info);CHKERRQ(ierr);
348af33a6ddSJed Brown   is   = info.xs;          ie   = info.xs+info.xm;
349af33a6ddSJed Brown   js   = info.ys;          je   = info.ys+info.ym;
350af33a6ddSJed Brown   /* Allocation */
351af33a6ddSJed Brown   ierr = PetscMalloc(dim*sizeof(PetscScalar),                &interpIndices);CHKERRQ(ierr);
352af33a6ddSJed Brown   ierr = PetscMalloc(c->numVelocityComp*sizeof(PetscScalar), &velocityValues);CHKERRQ(ierr);
353af33a6ddSJed Brown   ierr = PetscMalloc(c->numVelocityComp*sizeof(PetscScalar), &velocityValuesOld);CHKERRQ(ierr);
354af33a6ddSJed Brown   ierr = PetscMalloc(c->numFieldComp*sizeof(PetscScalar),    &fieldValues);CHKERRQ(ierr);
355af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_Solve,0,0,0,0);CHKERRQ(ierr);
356af33a6ddSJed Brown 
357af33a6ddSJed Brown   /* -----------------------------------------------------------------------
358af33a6ddSJed Brown      PART 1, AT t-dt/2
359af33a6ddSJed Brown      -----------------------------------------------------------------------*/
360af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_QueueSetup,0,0,0,0);CHKERRQ(ierr);
361af33a6ddSJed Brown   /* GET POSITION AT HALF TIME IN THE PAST */
362af33a6ddSJed Brown   if (c->velocityInterpLocal) {
363af33a6ddSJed Brown     ierr = DMGetLocalVector(c->velocityDA, &velocityLocal);CHKERRQ(ierr);
364af33a6ddSJed Brown     ierr = DMGetLocalVector(c->velocityDA, &velocityLocalOld);CHKERRQ(ierr);
365af33a6ddSJed Brown     ierr = DMGlobalToLocalBegin(c->velocityDA, c->velocity, INSERT_VALUES, velocityLocal);CHKERRQ(ierr);
366af33a6ddSJed Brown     ierr = DMGlobalToLocalEnd(c->velocityDA, c->velocity, INSERT_VALUES, velocityLocal);CHKERRQ(ierr);
367af33a6ddSJed Brown     ierr = DMGlobalToLocalBegin(c->velocityDA, c->velocityOld, INSERT_VALUES, velocityLocalOld);CHKERRQ(ierr);
368af33a6ddSJed Brown     ierr = DMGlobalToLocalEnd(c->velocityDA, c->velocityOld, INSERT_VALUES, velocityLocalOld);CHKERRQ(ierr);
369af33a6ddSJed Brown     ierr = DMDAVecGetArray(c->velocityDA, velocityLocal,    &velocityArray);CHKERRQ(ierr);
370af33a6ddSJed Brown     ierr = DMDAVecGetArray(c->velocityDA, velocityLocalOld, &velocityArrayOld);CHKERRQ(ierr);
371af33a6ddSJed Brown   }
3720298fd71SBarry Smith   ierr = PetscInfo(NULL, "Calculating position at t_{n - 1/2}\n");CHKERRQ(ierr);
373af33a6ddSJed Brown   for (Qi.j = js; Qi.j < je; Qi.j++) {
374af33a6ddSJed Brown     for (Qi.i = is; Qi.i < ie; Qi.i++) {
375af33a6ddSJed Brown       interpIndices[0] = Qi.i;
376af33a6ddSJed Brown       interpIndices[1] = Qi.j;
377bbd56ea5SKarl Rupp       if (c->velocityInterpLocal) c->velocityInterpLocal(velocityArray, interpIndices, c->numVelocityComp, c->velocityComp, velocityValues, c->velocityCtx);
378bbd56ea5SKarl Rupp       else c->velocityInterp(c->velocity, interpIndices, c->numVelocityComp, c->velocityComp, velocityValues, c->velocityCtx);
379af33a6ddSJed Brown       Qi.x = Qi.i - velocityValues[0]*dt/2.0;
380af33a6ddSJed Brown       Qi.y = Qi.j - velocityValues[1]*dt/2.0;
381af33a6ddSJed Brown 
382af33a6ddSJed Brown       /* Determine whether the position at t - dt/2 is local */
383af33a6ddSJed Brown       Qi.proc = DMDAGetNeighborRelative(da, Qi.x, Qi.y);
384af33a6ddSJed Brown 
385af33a6ddSJed Brown       /* Check for Periodic boundaries and move all periodic points back onto the domain */
386af33a6ddSJed Brown       ierr = DMDAMapCoordsToPeriodicDomain(da,&(Qi.x),&(Qi.y));CHKERRQ(ierr);
387af33a6ddSJed Brown       ierr = CharacteristicAddPoint(c, &Qi);CHKERRQ(ierr);
388af33a6ddSJed Brown     }
389af33a6ddSJed Brown   }
390af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_QueueSetup,0,0,0,0);CHKERRQ(ierr);
391af33a6ddSJed Brown 
392af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_HalfTimeExchange,0,0,0,0);CHKERRQ(ierr);
393af33a6ddSJed Brown   ierr = CharacteristicSendCoordinatesBegin(c);CHKERRQ(ierr);
394af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_HalfTimeExchange,0,0,0,0);CHKERRQ(ierr);
395af33a6ddSJed Brown 
396af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_HalfTimeLocal,0,0,0,0);CHKERRQ(ierr);
397af33a6ddSJed Brown   /* Calculate velocity at t_n+1/2 (local values) */
3980298fd71SBarry Smith   ierr = PetscInfo(NULL, "Calculating local velocities at t_{n - 1/2}\n");CHKERRQ(ierr);
399af33a6ddSJed Brown   for (n = 0; n < c->queueSize; n++) {
400af33a6ddSJed Brown     Qi = c->queue[n];
401af33a6ddSJed Brown     if (c->neighbors[Qi.proc] == rank) {
402af33a6ddSJed Brown       interpIndices[0] = Qi.x;
403af33a6ddSJed Brown       interpIndices[1] = Qi.y;
404af33a6ddSJed Brown       if (c->velocityInterpLocal) {
405af33a6ddSJed Brown         c->velocityInterpLocal(velocityArray,    interpIndices, c->numVelocityComp, c->velocityComp, velocityValues,    c->velocityCtx);
406af33a6ddSJed Brown         c->velocityInterpLocal(velocityArrayOld, interpIndices, c->numVelocityComp, c->velocityComp, velocityValuesOld, c->velocityCtx);
407af33a6ddSJed Brown       } else {
408af33a6ddSJed Brown         c->velocityInterp(c->velocity,    interpIndices, c->numVelocityComp, c->velocityComp, velocityValues,    c->velocityCtx);
409af33a6ddSJed Brown         c->velocityInterp(c->velocityOld, interpIndices, c->numVelocityComp, c->velocityComp, velocityValuesOld, c->velocityCtx);
410af33a6ddSJed Brown       }
411af33a6ddSJed Brown       Qi.x = 0.5*(velocityValues[0] + velocityValuesOld[0]);
412af33a6ddSJed Brown       Qi.y = 0.5*(velocityValues[1] + velocityValuesOld[1]);
413af33a6ddSJed Brown     }
414af33a6ddSJed Brown     c->queue[n] = Qi;
415af33a6ddSJed Brown   }
416af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_HalfTimeLocal,0,0,0,0);CHKERRQ(ierr);
417af33a6ddSJed Brown 
418af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_HalfTimeExchange,0,0,0,0);CHKERRQ(ierr);
419af33a6ddSJed Brown   ierr = CharacteristicSendCoordinatesEnd(c);CHKERRQ(ierr);
420af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_HalfTimeExchange,0,0,0,0);CHKERRQ(ierr);
421af33a6ddSJed Brown 
422af33a6ddSJed Brown 
423af33a6ddSJed Brown   /* Calculate velocity at t_n+1/2 (fill remote requests) */
424af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_HalfTimeRemote,0,0,0,0);CHKERRQ(ierr);
4250298fd71SBarry Smith   ierr = PetscInfo1(NULL, "Calculating %d remote velocities at t_{n - 1/2}\n", c->queueRemoteSize);CHKERRQ(ierr);
426af33a6ddSJed Brown   for (n = 0; n < c->queueRemoteSize; n++) {
427af33a6ddSJed Brown     Qi = c->queueRemote[n];
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     c->queueRemote[n] = Qi;
440af33a6ddSJed Brown   }
441af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_HalfTimeRemote,0,0,0,0);CHKERRQ(ierr);
442af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_HalfTimeExchange,0,0,0,0);CHKERRQ(ierr);
443af33a6ddSJed Brown   ierr = CharacteristicGetValuesBegin(c);CHKERRQ(ierr);
444af33a6ddSJed Brown   ierr = CharacteristicGetValuesEnd(c);CHKERRQ(ierr);
445af33a6ddSJed Brown   if (c->velocityInterpLocal) {
446af33a6ddSJed Brown     ierr = DMDAVecRestoreArray(c->velocityDA, velocityLocal,    &velocityArray);CHKERRQ(ierr);
447af33a6ddSJed Brown     ierr = DMDAVecRestoreArray(c->velocityDA, velocityLocalOld, &velocityArrayOld);CHKERRQ(ierr);
448af33a6ddSJed Brown     ierr = DMRestoreLocalVector(c->velocityDA, &velocityLocal);CHKERRQ(ierr);
449af33a6ddSJed Brown     ierr = DMRestoreLocalVector(c->velocityDA, &velocityLocalOld);CHKERRQ(ierr);
450af33a6ddSJed Brown   }
451af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_HalfTimeExchange,0,0,0,0);CHKERRQ(ierr);
452af33a6ddSJed Brown 
453af33a6ddSJed Brown   /* -----------------------------------------------------------------------
454af33a6ddSJed Brown      PART 2, AT t-dt
455af33a6ddSJed Brown      -----------------------------------------------------------------------*/
456af33a6ddSJed Brown 
457af33a6ddSJed Brown   /* GET POSITION AT t_n (local values) */
458af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_FullTimeLocal,0,0,0,0);CHKERRQ(ierr);
4590298fd71SBarry Smith   ierr = PetscInfo(NULL, "Calculating position at t_{n}\n");CHKERRQ(ierr);
460af33a6ddSJed Brown   for (n = 0; n < c->queueSize; n++) {
461af33a6ddSJed Brown     Qi   = c->queue[n];
462af33a6ddSJed Brown     Qi.x = Qi.i - Qi.x*dt;
463af33a6ddSJed Brown     Qi.y = Qi.j - Qi.y*dt;
464af33a6ddSJed Brown 
465af33a6ddSJed Brown     /* Determine whether the position at t-dt is local */
466af33a6ddSJed Brown     Qi.proc = DMDAGetNeighborRelative(da, Qi.x, Qi.y);
467af33a6ddSJed Brown 
468af33a6ddSJed Brown     /* Check for Periodic boundaries and move all periodic points back onto the domain */
469af33a6ddSJed Brown     ierr = DMDAMapCoordsToPeriodicDomain(da,&(Qi.x),&(Qi.y));CHKERRQ(ierr);
470af33a6ddSJed Brown 
471af33a6ddSJed Brown     c->queue[n] = Qi;
472af33a6ddSJed Brown   }
473af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_FullTimeLocal,0,0,0,0);CHKERRQ(ierr);
474af33a6ddSJed Brown 
475af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_FullTimeExchange,0,0,0,0);CHKERRQ(ierr);
476af33a6ddSJed Brown   ierr = CharacteristicSendCoordinatesBegin(c);CHKERRQ(ierr);
477af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_FullTimeExchange,0,0,0,0);CHKERRQ(ierr);
478af33a6ddSJed Brown 
479af33a6ddSJed Brown   /* GET VALUE AT FULL TIME IN THE PAST (LOCAL REQUESTS) */
480af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_FullTimeLocal,0,0,0,0);CHKERRQ(ierr);
481af33a6ddSJed Brown   if (c->fieldInterpLocal) {
482af33a6ddSJed Brown     ierr = DMGetLocalVector(c->fieldDA, &fieldLocal);CHKERRQ(ierr);
483af33a6ddSJed Brown     ierr = DMGlobalToLocalBegin(c->fieldDA, c->field, INSERT_VALUES, fieldLocal);CHKERRQ(ierr);
484af33a6ddSJed Brown     ierr = DMGlobalToLocalEnd(c->fieldDA, c->field, INSERT_VALUES, fieldLocal);CHKERRQ(ierr);
485af33a6ddSJed Brown     ierr = DMDAVecGetArray(c->fieldDA, fieldLocal, &fieldArray);CHKERRQ(ierr);
486af33a6ddSJed Brown   }
4870298fd71SBarry Smith   ierr = PetscInfo(NULL, "Calculating local field at t_{n}\n");CHKERRQ(ierr);
488af33a6ddSJed Brown   for (n = 0; n < c->queueSize; n++) {
489af33a6ddSJed Brown     if (c->neighbors[c->queue[n].proc] == rank) {
490af33a6ddSJed Brown       interpIndices[0] = c->queue[n].x;
491af33a6ddSJed Brown       interpIndices[1] = c->queue[n].y;
492bbd56ea5SKarl Rupp       if (c->fieldInterpLocal) c->fieldInterpLocal(fieldArray, interpIndices, c->numFieldComp, c->fieldComp, fieldValues, c->fieldCtx);
493bbd56ea5SKarl Rupp       else c->fieldInterp(c->field, interpIndices, c->numFieldComp, c->fieldComp, fieldValues, c->fieldCtx);
494bbd56ea5SKarl Rupp       for (comp = 0; comp < c->numFieldComp; comp++) c->queue[n].field[comp] = fieldValues[comp];
495af33a6ddSJed Brown     }
496af33a6ddSJed Brown   }
497af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_FullTimeLocal,0,0,0,0);CHKERRQ(ierr);
498af33a6ddSJed Brown 
499af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_FullTimeExchange,0,0,0,0);CHKERRQ(ierr);
500af33a6ddSJed Brown   ierr = CharacteristicSendCoordinatesEnd(c);CHKERRQ(ierr);
501af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_FullTimeExchange,0,0,0,0);CHKERRQ(ierr);
502af33a6ddSJed Brown 
503af33a6ddSJed Brown   /* GET VALUE AT FULL TIME IN THE PAST (REMOTE REQUESTS) */
504af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_FullTimeRemote,0,0,0,0);CHKERRQ(ierr);
5050298fd71SBarry Smith   ierr = PetscInfo1(NULL, "Calculating %d remote field points at t_{n}\n", c->queueRemoteSize);CHKERRQ(ierr);
506af33a6ddSJed Brown   for (n = 0; n < c->queueRemoteSize; n++) {
507af33a6ddSJed Brown     interpIndices[0] = c->queueRemote[n].x;
508af33a6ddSJed Brown     interpIndices[1] = c->queueRemote[n].y;
509af33a6ddSJed Brown 
510af33a6ddSJed Brown     /* for debugging purposes */
511af33a6ddSJed Brown     if (1) { /* hacked bounds test...let's do better */
512af33a6ddSJed Brown       PetscScalar im = interpIndices[0]; PetscScalar jm = interpIndices[1];
513af33a6ddSJed Brown 
514bbd56ea5SKarl 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);
515af33a6ddSJed Brown     }
516af33a6ddSJed Brown 
517bbd56ea5SKarl Rupp     if (c->fieldInterpLocal) c->fieldInterpLocal(fieldArray, interpIndices, c->numFieldComp, c->fieldComp, fieldValues, c->fieldCtx);
518bbd56ea5SKarl Rupp     else c->fieldInterp(c->field, interpIndices, c->numFieldComp, c->fieldComp, fieldValues, c->fieldCtx);
519bbd56ea5SKarl Rupp     for (comp = 0; comp < c->numFieldComp; comp++) c->queueRemote[n].field[comp] = fieldValues[comp];
520af33a6ddSJed Brown   }
521af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_FullTimeRemote,0,0,0,0);CHKERRQ(ierr);
522af33a6ddSJed Brown 
523af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_FullTimeExchange,0,0,0,0);CHKERRQ(ierr);
524af33a6ddSJed Brown   ierr = CharacteristicGetValuesBegin(c);CHKERRQ(ierr);
525af33a6ddSJed Brown   ierr = CharacteristicGetValuesEnd(c);CHKERRQ(ierr);
526af33a6ddSJed Brown   if (c->fieldInterpLocal) {
527af33a6ddSJed Brown     ierr = DMDAVecRestoreArray(c->fieldDA, fieldLocal, &fieldArray);CHKERRQ(ierr);
528af33a6ddSJed Brown     ierr = DMRestoreLocalVector(c->fieldDA, &fieldLocal);CHKERRQ(ierr);
529af33a6ddSJed Brown   }
530af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_FullTimeExchange,0,0,0,0);CHKERRQ(ierr);
531af33a6ddSJed Brown 
532af33a6ddSJed Brown   /* Return field of characteristics at t_n-1 */
533af33a6ddSJed Brown   ierr = PetscLogEventBegin(CHARACTERISTIC_DAUpdate,0,0,0,0);CHKERRQ(ierr);
534af33a6ddSJed Brown   ierr = DMDAGetInfo(c->fieldDA,0,0,0,0,0,0,0,&dof,0,0,0,0,0);CHKERRQ(ierr);
535af33a6ddSJed Brown   ierr = DMDAVecGetArray(c->fieldDA, solution, &solArray);CHKERRQ(ierr);
536af33a6ddSJed Brown   for (n = 0; n < c->queueSize; n++) {
537af33a6ddSJed Brown     Qi = c->queue[n];
538bbd56ea5SKarl Rupp     for (comp = 0; comp < c->numFieldComp; comp++) solArray[Qi.j][Qi.i*dof+c->fieldComp[comp]] = Qi.field[comp];
539af33a6ddSJed Brown   }
540af33a6ddSJed Brown   ierr = DMDAVecRestoreArray(c->fieldDA, solution, &solArray);CHKERRQ(ierr);
541af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_DAUpdate,0,0,0,0);CHKERRQ(ierr);
542af33a6ddSJed Brown   ierr = PetscLogEventEnd(CHARACTERISTIC_Solve,0,0,0,0);CHKERRQ(ierr);
543af33a6ddSJed Brown 
544af33a6ddSJed Brown   /* Cleanup */
545af33a6ddSJed Brown   ierr = PetscFree(interpIndices);CHKERRQ(ierr);
546af33a6ddSJed Brown   ierr = PetscFree(velocityValues);CHKERRQ(ierr);
547af33a6ddSJed Brown   ierr = PetscFree(velocityValuesOld);CHKERRQ(ierr);
548af33a6ddSJed Brown   ierr = PetscFree(fieldValues);CHKERRQ(ierr);
549af33a6ddSJed Brown   PetscFunctionReturn(0);
550af33a6ddSJed Brown }
551af33a6ddSJed Brown 
552af33a6ddSJed Brown #undef __FUNCT__
553af33a6ddSJed Brown #define __FUNCT__ "CharacteristicSetNeighbors"
554af33a6ddSJed Brown PetscErrorCode CharacteristicSetNeighbors(Characteristic c, PetscInt numNeighbors, PetscMPIInt neighbors[])
555af33a6ddSJed Brown {
556af33a6ddSJed Brown   PetscErrorCode ierr;
557af33a6ddSJed Brown 
558af33a6ddSJed Brown   PetscFunctionBegin;
559af33a6ddSJed Brown   c->numNeighbors = numNeighbors;
5606eaa7dc8SBarry Smith   ierr = PetscFree(c->neighbors);CHKERRQ(ierr);
561af33a6ddSJed Brown   ierr = PetscMalloc(numNeighbors * sizeof(PetscMPIInt), &c->neighbors);CHKERRQ(ierr);
562af33a6ddSJed Brown   ierr = PetscMemcpy(c->neighbors, neighbors, numNeighbors * sizeof(PetscMPIInt));CHKERRQ(ierr);
563af33a6ddSJed Brown   PetscFunctionReturn(0);
564af33a6ddSJed Brown }
565af33a6ddSJed Brown 
566af33a6ddSJed Brown #undef __FUNCT__
567af33a6ddSJed Brown #define __FUNCT__ "CharacteristicAddPoint"
568af33a6ddSJed Brown PetscErrorCode CharacteristicAddPoint(Characteristic c, CharacteristicPointDA2D *point)
569af33a6ddSJed Brown {
570af33a6ddSJed Brown   PetscFunctionBegin;
571f23aa3ddSBarry Smith   if (c->queueSize >= c->queueMax) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE, "Exceeeded maximum queue size %d", c->queueMax);
572af33a6ddSJed Brown   c->queue[c->queueSize++] = *point;
573af33a6ddSJed Brown   PetscFunctionReturn(0);
574af33a6ddSJed Brown }
575af33a6ddSJed Brown 
576af33a6ddSJed Brown #undef __FUNCT__
577af33a6ddSJed Brown #define __FUNCT__ "CharacteristicSendCoordinatesBegin"
578af33a6ddSJed Brown int CharacteristicSendCoordinatesBegin(Characteristic c)
579af33a6ddSJed Brown {
580af33a6ddSJed Brown   PetscMPIInt    rank, tag = 121;
581af33a6ddSJed Brown   PetscInt       i, n;
582af33a6ddSJed Brown   PetscErrorCode ierr;
583af33a6ddSJed Brown 
584af33a6ddSJed Brown   PetscFunctionBegin;
585*ce94432eSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)c), &rank);CHKERRQ(ierr);
5860b8f38c8SBarry Smith   ierr = CharacteristicHeapSort(c, c->queue, c->queueSize);CHKERRQ(ierr);
587af33a6ddSJed Brown   ierr = PetscMemzero(c->needCount, c->numNeighbors * sizeof(PetscInt));CHKERRQ(ierr);
588bbd56ea5SKarl Rupp   for (i = 0;  i < c->queueSize; i++) c->needCount[c->queue[i].proc]++;
589af33a6ddSJed Brown   c->fillCount[0] = 0;
590af33a6ddSJed Brown   for (n = 1; n < c->numNeighbors; n++) {
591*ce94432eSBarry Smith     ierr = MPI_Irecv(&(c->fillCount[n]), 1, MPIU_INT, c->neighbors[n], tag, PetscObjectComm((PetscObject)c), &(c->request[n-1]));CHKERRQ(ierr);
592af33a6ddSJed Brown   }
593af33a6ddSJed Brown   for (n = 1; n < c->numNeighbors; n++) {
594*ce94432eSBarry Smith     ierr = MPI_Send(&(c->needCount[n]), 1, MPIU_INT, c->neighbors[n], tag, PetscObjectComm((PetscObject)c));CHKERRQ(ierr);
595af33a6ddSJed Brown   }
596af33a6ddSJed Brown   ierr = MPI_Waitall(c->numNeighbors-1, c->request, c->status);CHKERRQ(ierr);
597af33a6ddSJed Brown   /* Initialize the remote queue */
598af33a6ddSJed Brown   c->queueLocalMax  = c->localOffsets[0]  = 0;
599af33a6ddSJed Brown   c->queueRemoteMax = c->remoteOffsets[0] = 0;
600af33a6ddSJed Brown   for (n = 1; n < c->numNeighbors; n++) {
601af33a6ddSJed Brown     c->remoteOffsets[n] = c->queueRemoteMax;
602af33a6ddSJed Brown     c->queueRemoteMax  += c->fillCount[n];
603af33a6ddSJed Brown     c->localOffsets[n]  = c->queueLocalMax;
604af33a6ddSJed Brown     c->queueLocalMax   += c->needCount[n];
605af33a6ddSJed Brown   }
606af33a6ddSJed Brown   /* HACK BEGIN */
607bbd56ea5SKarl Rupp   for (n = 1; n < c->numNeighbors; n++) c->localOffsets[n] += c->needCount[0];
608af33a6ddSJed Brown   c->needCount[0] = 0;
609af33a6ddSJed Brown   /* HACK END */
610af33a6ddSJed Brown   if (c->queueRemoteMax) {
611af33a6ddSJed Brown     ierr = PetscMalloc(sizeof(CharacteristicPointDA2D) * c->queueRemoteMax, &c->queueRemote);CHKERRQ(ierr);
6120298fd71SBarry Smith   } else c->queueRemote = NULL;
613af33a6ddSJed Brown   c->queueRemoteSize = c->queueRemoteMax;
614af33a6ddSJed Brown 
615af33a6ddSJed Brown   /* Send and Receive requests for values at t_n+1/2, giving the coordinates for interpolation */
616af33a6ddSJed Brown   for (n = 1; n < c->numNeighbors; n++) {
6170298fd71SBarry Smith     ierr = PetscInfo2(NULL, "Receiving %d requests for values from proc %d\n", c->fillCount[n], c->neighbors[n]);CHKERRQ(ierr);
618*ce94432eSBarry 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);
619af33a6ddSJed Brown   }
620af33a6ddSJed Brown   for (n = 1; n < c->numNeighbors; n++) {
6210298fd71SBarry Smith     ierr = PetscInfo2(NULL, "Sending %d requests for values from proc %d\n", c->needCount[n], c->neighbors[n]);CHKERRQ(ierr);
622*ce94432eSBarry Smith     ierr = MPI_Send(&(c->queue[c->localOffsets[n]]), c->needCount[n], c->itemType, c->neighbors[n], tag, PetscObjectComm((PetscObject)c));CHKERRQ(ierr);
623af33a6ddSJed Brown   }
624af33a6ddSJed Brown   PetscFunctionReturn(0);
625af33a6ddSJed Brown }
626af33a6ddSJed Brown 
627af33a6ddSJed Brown #undef __FUNCT__
628af33a6ddSJed Brown #define __FUNCT__ "CharacteristicSendCoordinatesEnd"
629af33a6ddSJed Brown PetscErrorCode CharacteristicSendCoordinatesEnd(Characteristic c)
630af33a6ddSJed Brown {
631af33a6ddSJed Brown #if 0
632af33a6ddSJed Brown   PetscMPIInt rank;
633af33a6ddSJed Brown   PetscInt    n;
634af33a6ddSJed Brown #endif
635af33a6ddSJed Brown   PetscErrorCode ierr;
636af33a6ddSJed Brown 
637af33a6ddSJed Brown   PetscFunctionBegin;
638af33a6ddSJed Brown   ierr = MPI_Waitall(c->numNeighbors-1, c->request, c->status);CHKERRQ(ierr);
639af33a6ddSJed Brown #if 0
640*ce94432eSBarry Smith   ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)c), &rank);CHKERRQ(ierr);
641af33a6ddSJed Brown   for (n = 0; n < c->queueRemoteSize; n++) {
642f23aa3ddSBarry 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);
643af33a6ddSJed Brown   }
644af33a6ddSJed Brown #endif
645af33a6ddSJed Brown   PetscFunctionReturn(0);
646af33a6ddSJed Brown }
647af33a6ddSJed Brown 
648af33a6ddSJed Brown #undef __FUNCT__
649af33a6ddSJed Brown #define __FUNCT__ "CharacteristicGetValuesBegin"
650af33a6ddSJed Brown PetscErrorCode CharacteristicGetValuesBegin(Characteristic c)
651af33a6ddSJed Brown {
652af33a6ddSJed Brown   PetscMPIInt    tag = 121;
653af33a6ddSJed Brown   PetscInt       n;
654af33a6ddSJed Brown   PetscErrorCode ierr;
655af33a6ddSJed Brown 
656af33a6ddSJed Brown   PetscFunctionBegin;
657af33a6ddSJed Brown   /* SEND AND RECIEVE FILLED REQUESTS for velocities at t_n+1/2 */
658af33a6ddSJed Brown   for (n = 1; n < c->numNeighbors; n++) {
659*ce94432eSBarry 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);
660af33a6ddSJed Brown   }
661af33a6ddSJed Brown   for (n = 1; n < c->numNeighbors; n++) {
662*ce94432eSBarry Smith     ierr = MPI_Send(&(c->queueRemote[c->remoteOffsets[n]]), c->fillCount[n], c->itemType, c->neighbors[n], tag, PetscObjectComm((PetscObject)c));CHKERRQ(ierr);
663af33a6ddSJed Brown   }
664af33a6ddSJed Brown   PetscFunctionReturn(0);
665af33a6ddSJed Brown }
666af33a6ddSJed Brown 
667af33a6ddSJed Brown #undef __FUNCT__
668af33a6ddSJed Brown #define __FUNCT__ "CharacteristicGetValuesEnd"
669af33a6ddSJed Brown PetscErrorCode CharacteristicGetValuesEnd(Characteristic c)
670af33a6ddSJed Brown {
671af33a6ddSJed Brown   PetscErrorCode ierr;
672af33a6ddSJed Brown 
673af33a6ddSJed Brown   PetscFunctionBegin;
674af33a6ddSJed Brown   ierr = MPI_Waitall(c->numNeighbors-1, c->request, c->status);CHKERRQ(ierr);
675af33a6ddSJed Brown   /* Free queue of requests from other procs */
676af33a6ddSJed Brown   ierr = PetscFree(c->queueRemote);CHKERRQ(ierr);
677af33a6ddSJed Brown   PetscFunctionReturn(0);
678af33a6ddSJed Brown }
679af33a6ddSJed Brown 
680af33a6ddSJed Brown /*---------------------------------------------------------------------*/
681af33a6ddSJed Brown #undef __FUNCT__
6820b8f38c8SBarry Smith #define __FUNCT__ "CharacteristicHeapSort"
683af33a6ddSJed Brown /*
684af33a6ddSJed Brown   Based on code from http://linux.wku.edu/~lamonml/algor/sort/heap.html
685af33a6ddSJed Brown */
6860b8f38c8SBarry Smith PetscErrorCode CharacteristicHeapSort(Characteristic c, Queue queue, PetscInt size)
687af33a6ddSJed Brown /*---------------------------------------------------------------------*/
688af33a6ddSJed Brown {
6890b8f38c8SBarry Smith   PetscErrorCode          ierr;
690af33a6ddSJed Brown   CharacteristicPointDA2D temp;
6910b8f38c8SBarry Smith   PetscInt                n;
692af33a6ddSJed Brown 
6930b8f38c8SBarry Smith   PetscFunctionBegin;
694af33a6ddSJed Brown   if (0) { /* Check the order of the queue before sorting */
6950298fd71SBarry Smith     PetscInfo(NULL, "Before Heap sort\n");
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   }
700af33a6ddSJed Brown 
701af33a6ddSJed Brown   /* SORTING PHASE */
7020b8f38c8SBarry Smith   for (n = (size / 2)-1; n >= 0; n--) {
7030b8f38c8SBarry Smith     ierr = CharacteristicSiftDown(c, queue, n, size-1);CHKERRQ(ierr); /* Rich had size-1 here, Matt had size*/
7040b8f38c8SBarry Smith   }
705af33a6ddSJed Brown   for (n = size-1; n >= 1; n--) {
706af33a6ddSJed Brown     temp     = queue[0];
707af33a6ddSJed Brown     queue[0] = queue[n];
708af33a6ddSJed Brown     queue[n] = temp;
7090b8f38c8SBarry Smith     ierr     = CharacteristicSiftDown(c, queue, 0, n-1);CHKERRQ(ierr);
710af33a6ddSJed Brown   }
711af33a6ddSJed Brown   if (0) { /* Check the order of the queue after sorting */
7120298fd71SBarry Smith     ierr = PetscInfo(NULL, "Avter  Heap sort\n");CHKERRQ(ierr);
713af33a6ddSJed Brown     for (n=0; n<size; n++) {
7140298fd71SBarry Smith       ierr = PetscInfo2(NULL,"%d %d\n",n,queue[n].proc);CHKERRQ(ierr);
715af33a6ddSJed Brown     }
716af33a6ddSJed Brown   }
7170b8f38c8SBarry Smith   PetscFunctionReturn(0);
718af33a6ddSJed Brown }
719af33a6ddSJed Brown 
720af33a6ddSJed Brown /*---------------------------------------------------------------------*/
721af33a6ddSJed Brown #undef __FUNCT__
7220b8f38c8SBarry Smith #define __FUNCT__ "CharacteristicSiftDown"
723af33a6ddSJed Brown /*
724af33a6ddSJed Brown   Based on code from http://linux.wku.edu/~lamonml/algor/sort/heap.html
725af33a6ddSJed Brown */
7260b8f38c8SBarry Smith PetscErrorCode CharacteristicSiftDown(Characteristic c, Queue queue, PetscInt root, PetscInt bottom)
727af33a6ddSJed Brown /*---------------------------------------------------------------------*/
728af33a6ddSJed Brown {
729af33a6ddSJed Brown   PetscBool               done = PETSC_FALSE;
730af33a6ddSJed Brown   PetscInt                maxChild;
731af33a6ddSJed Brown   CharacteristicPointDA2D temp;
732af33a6ddSJed Brown 
733af33a6ddSJed Brown   PetscFunctionBegin;
734af33a6ddSJed Brown   while ((root*2 <= bottom) && (!done)) {
735af33a6ddSJed Brown     if (root*2 == bottom) maxChild = root * 2;
736af33a6ddSJed Brown     else if (queue[root*2].proc > queue[root*2+1].proc) maxChild = root * 2;
737af33a6ddSJed Brown     else maxChild = root * 2 + 1;
738af33a6ddSJed Brown 
739af33a6ddSJed Brown     if (queue[root].proc < queue[maxChild].proc) {
740af33a6ddSJed Brown       temp            = queue[root];
741af33a6ddSJed Brown       queue[root]     = queue[maxChild];
742af33a6ddSJed Brown       queue[maxChild] = temp;
743af33a6ddSJed Brown       root            = maxChild;
744db4deed7SKarl Rupp     } else done = PETSC_TRUE;
745af33a6ddSJed Brown   }
746af33a6ddSJed Brown   PetscFunctionReturn(0);
747af33a6ddSJed Brown }
748af33a6ddSJed Brown 
749af33a6ddSJed Brown #undef __FUNCT__
750af33a6ddSJed Brown #define __FUNCT__ "DMDAGetNeighborsRank"
751af33a6ddSJed Brown /* [center, left, top-left, top, top-right, right, bottom-right, bottom, bottom-left] */
752af33a6ddSJed Brown PetscErrorCode DMDAGetNeighborsRank(DM da, PetscMPIInt neighbors[])
753af33a6ddSJed Brown {
754af33a6ddSJed Brown   DMDABoundaryType bx, by;
755af33a6ddSJed Brown   PetscBool        IPeriodic = PETSC_FALSE, JPeriodic = PETSC_FALSE;
756af33a6ddSJed Brown   MPI_Comm         comm;
757af33a6ddSJed Brown   PetscMPIInt      rank;
758af33a6ddSJed Brown   PetscInt         **procs,pi,pj,pim,pip,pjm,pjp,PI,PJ;
759af33a6ddSJed Brown   PetscErrorCode   ierr;
760af33a6ddSJed Brown 
761af33a6ddSJed Brown   PetscFunctionBegin;
762af33a6ddSJed Brown   ierr = PetscObjectGetComm((PetscObject) da, &comm);CHKERRQ(ierr);
763af33a6ddSJed Brown   ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr);
76422d28d08SBarry Smith   ierr = DMDAGetInfo(da, 0, 0, 0, 0, &PI,&PJ, 0, 0, 0, &bx, &by,0, 0);CHKERRQ(ierr);
765af33a6ddSJed Brown 
766bbd56ea5SKarl Rupp   if (bx == DMDA_BOUNDARY_PERIODIC) IPeriodic = PETSC_TRUE;
767bbd56ea5SKarl Rupp   if (by == DMDA_BOUNDARY_PERIODIC) JPeriodic = PETSC_TRUE;
768af33a6ddSJed Brown 
769af33a6ddSJed Brown   neighbors[0] = rank;
770af33a6ddSJed Brown   rank = 0;
771af33a6ddSJed Brown   ierr = PetscMalloc(sizeof(PetscInt*)*PJ,&procs);CHKERRQ(ierr);
772af33a6ddSJed Brown   for (pj=0; pj<PJ; pj++) {
773af33a6ddSJed Brown     ierr = PetscMalloc(sizeof(PetscInt)*PI,&(procs[pj]));CHKERRQ(ierr);
774af33a6ddSJed Brown     for (pi=0; pi<PI; pi++) {
775af33a6ddSJed Brown       procs[pj][pi] = rank;
776af33a6ddSJed Brown       rank++;
777af33a6ddSJed Brown     }
778af33a6ddSJed Brown   }
779af33a6ddSJed Brown 
780af33a6ddSJed Brown   pi  = neighbors[0] % PI;
781af33a6ddSJed Brown   pj  = neighbors[0] / PI;
782af33a6ddSJed Brown   pim = pi-1;  if (pim<0) pim=PI-1;
783af33a6ddSJed Brown   pip = (pi+1)%PI;
784af33a6ddSJed Brown   pjm = pj-1;  if (pjm<0) pjm=PJ-1;
785af33a6ddSJed Brown   pjp = (pj+1)%PJ;
786af33a6ddSJed Brown 
787af33a6ddSJed Brown   neighbors[1] = procs[pj] [pim];
788af33a6ddSJed Brown   neighbors[2] = procs[pjp][pim];
789af33a6ddSJed Brown   neighbors[3] = procs[pjp][pi];
790af33a6ddSJed Brown   neighbors[4] = procs[pjp][pip];
791af33a6ddSJed Brown   neighbors[5] = procs[pj] [pip];
792af33a6ddSJed Brown   neighbors[6] = procs[pjm][pip];
793af33a6ddSJed Brown   neighbors[7] = procs[pjm][pi];
794af33a6ddSJed Brown   neighbors[8] = procs[pjm][pim];
795af33a6ddSJed Brown 
796af33a6ddSJed Brown   if (!IPeriodic) {
797af33a6ddSJed Brown     if (pi==0)    neighbors[1]=neighbors[2]=neighbors[8]=neighbors[0];
798af33a6ddSJed Brown     if (pi==PI-1) neighbors[4]=neighbors[5]=neighbors[6]=neighbors[0];
799af33a6ddSJed Brown   }
800af33a6ddSJed Brown 
801af33a6ddSJed Brown   if (!JPeriodic) {
802af33a6ddSJed Brown     if (pj==0)    neighbors[6]=neighbors[7]=neighbors[8]=neighbors[0];
803af33a6ddSJed Brown     if (pj==PJ-1) neighbors[2]=neighbors[3]=neighbors[4]=neighbors[0];
804af33a6ddSJed Brown   }
805af33a6ddSJed Brown 
806af33a6ddSJed Brown   for (pj = 0; pj < PJ; pj++) {
807af33a6ddSJed Brown     ierr = PetscFree(procs[pj]);CHKERRQ(ierr);
808af33a6ddSJed Brown   }
809af33a6ddSJed Brown   ierr = PetscFree(procs);CHKERRQ(ierr);
810af33a6ddSJed Brown   PetscFunctionReturn(0);
811af33a6ddSJed Brown }
812af33a6ddSJed Brown 
813af33a6ddSJed Brown #undef __FUNCT__
814af33a6ddSJed Brown #define __FUNCT__ "DMDAGetNeighborRelative"
815af33a6ddSJed Brown /*
816af33a6ddSJed Brown   SUBDOMAIN NEIGHBORHOOD PROCESS MAP:
817af33a6ddSJed Brown     2 | 3 | 4
818af33a6ddSJed Brown     __|___|__
819af33a6ddSJed Brown     1 | 0 | 5
820af33a6ddSJed Brown     __|___|__
821af33a6ddSJed Brown     8 | 7 | 6
822af33a6ddSJed Brown       |   |
823af33a6ddSJed Brown */
824af33a6ddSJed Brown PetscInt DMDAGetNeighborRelative(DM da, PassiveReal ir, PassiveReal jr)
825af33a6ddSJed Brown {
826af33a6ddSJed Brown   DMDALocalInfo  info;
827af33a6ddSJed Brown   PassiveReal    is,ie,js,je;
828af33a6ddSJed Brown   PetscErrorCode ierr;
829af33a6ddSJed Brown 
830af33a6ddSJed Brown   ierr = DMDAGetLocalInfo(da, &info);CHKERRQ(ierr);
831af33a6ddSJed Brown   is   = (PassiveReal) info.xs - 0.5; ie = (PassiveReal) info.xs + info.xm - 0.5;
832af33a6ddSJed Brown   js   = (PassiveReal) info.ys - 0.5; je = (PassiveReal) info.ys + info.ym - 0.5;
833af33a6ddSJed Brown 
834af33a6ddSJed Brown   if (ir >= is && ir <= ie) { /* center column */
835bbd56ea5SKarl Rupp     if (jr >= js && jr <= je) return 0;
836bbd56ea5SKarl Rupp     else if (jr < js)         return 7;
837bbd56ea5SKarl Rupp     else                      return 3;
838af33a6ddSJed Brown   } else if (ir < is) {     /* left column */
839bbd56ea5SKarl Rupp     if (jr >= js && jr <= je) return 1;
840bbd56ea5SKarl Rupp     else if (jr < js)         return 8;
841bbd56ea5SKarl Rupp     else                      return 2;
842af33a6ddSJed Brown   } else {                  /* right column */
843bbd56ea5SKarl Rupp     if (jr >= js && jr <= je) return 5;
844bbd56ea5SKarl Rupp     else if (jr < js)         return 6;
845bbd56ea5SKarl Rupp     else                      return 4;
846af33a6ddSJed Brown   }
847af33a6ddSJed Brown }
848