DAIndex.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2 
3  DAFoam : Discrete Adjoint with OpenFOAM
4  Version : v3
5 
6 \*---------------------------------------------------------------------------*/
7 
8 #include "DAIndex.H"
9 
10 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
11 
12 namespace Foam
13 {
14 
15 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
16 
17 DAIndex::DAIndex(
18  const fvMesh& mesh,
19  const DAOption& daOption,
20  const DAModel& daModel)
21  : mesh_(mesh),
22  daOption_(daOption),
23  daModel_(daModel),
24  pointProcAddressing(
25  IOobject(
26  "pointProcAddressing",
27  mesh_.facesInstance(),
28  mesh_.meshSubDir,
29  mesh_,
30  IOobject::READ_IF_PRESENT,
31  IOobject::NO_WRITE),
32  {})
33 {
34  // Calculate the sizes
35  // local denotes the current MPI process
36  // global denotes all the MPI processes
37 
38  // initialize stateInfo_
39  word solverName = daOption.getOption<word>("solverName");
40  autoPtr<DAStateInfo> daStateInfo(DAStateInfo::New(solverName, mesh, daOption, daModel));
41  stateInfo_ = daStateInfo->getStateInfo();
42 
43  // Setup the adjoint state name and type lists.
44  forAll(stateInfo_["volVectorStates"], idxI)
45  {
46  adjStateNames.append(stateInfo_["volVectorStates"][idxI]);
47  adjStateType.set(stateInfo_["volVectorStates"][idxI], "volVectorState");
48  }
49  forAll(stateInfo_["volScalarStates"], idxI)
50  {
51  adjStateNames.append(stateInfo_["volScalarStates"][idxI]);
52  adjStateType.set(stateInfo_["volScalarStates"][idxI], "volScalarState");
53  }
54  forAll(stateInfo_["modelStates"], idxI)
55  {
56  adjStateNames.append(stateInfo_["modelStates"][idxI]);
57  adjStateType.set(stateInfo_["modelStates"][idxI], "modelState");
58  }
59  forAll(stateInfo_["surfaceScalarStates"], idxI)
60  {
61  adjStateNames.append(stateInfo_["surfaceScalarStates"][idxI]);
62  adjStateType.set(stateInfo_["surfaceScalarStates"][idxI], "surfaceScalarState");
63  }
64 
65  // Local mesh related sizes
66  nLocalCells = mesh.nCells();
67  nLocalFaces = mesh.nFaces();
68  nLocalPoints = mesh.nPoints();
69  nLocalXv = nLocalPoints * 3;
70  nLocalInternalFaces = mesh.nInternalFaces();
71  nLocalBoundaryFaces = nLocalFaces - nLocalInternalFaces;
72  nLocalBoundaryPatches = mesh.boundaryMesh().size();
73 
74  // get bFacePatchI and bFaceFaceI
75  // these two lists store the patchI and faceI for a given boundary mesh face index
76  // the index of these lists starts from the first boundary face of the first boundary patch.
77  // they will be used to quickly get the patchI and faceI from a given boundary face index
78  bFacePatchI.setSize(nLocalBoundaryFaces);
79  bFaceFaceI.setSize(nLocalBoundaryFaces);
80  label tmpCounter = 0;
81  forAll(mesh_.boundaryMesh(), patchI)
82  {
83  forAll(mesh_.boundaryMesh()[patchI], faceI)
84  {
85  bFacePatchI[tmpCounter] = patchI;
86  bFaceFaceI[tmpCounter] = faceI;
87  tmpCounter++;
88  }
89  }
90 
91  // Initialize state local index offset, it will be used in getLocalStateIndex function
92  this->calcStateLocalIndexOffset(stateLocalIndexOffset);
93 
94  // Initialize adjStateID. It stores the stateID for a given stateName
95  this->calcAdjStateID(adjStateID);
96 
97  // Local adjoint state sizes
98  // first get how many state variables are registered.
99  // Note turbStates are treated separatedly
100  nVolScalarStates = stateInfo_["volScalarStates"].size();
101  nVolVectorStates = stateInfo_["volVectorStates"].size();
102  nSurfaceScalarStates = stateInfo_["surfaceScalarStates"].size();
103  nModelStates = stateInfo_["modelStates"].size();
104 
105  // number of boundary states, NOTE: this does not contain boundary phis becaues
106  // phi state already contains boundary phis
107  nLocalAdjointBoundaryStates = (nVolVectorStates * 3 + nVolScalarStates + nModelStates) * nLocalBoundaryFaces;
108 
109  // we can now calculate adjoint state size
110  label nLocalCellStates = (nVolVectorStates * 3 + nVolScalarStates + nModelStates) * nLocalCells;
111  label nLocalFaceStates = nSurfaceScalarStates * nLocalFaces;
112  nLocalAdjointStates = nLocalCellStates + nLocalFaceStates;
113 
114  // Setup the global numbering to convert a local index to the associated global index
115  globalAdjointStateNumbering = DAUtility::genGlobalIndex(nLocalAdjointStates);
116  globalCellNumbering = DAUtility::genGlobalIndex(nLocalCells);
117  globalCellVectorNumbering = DAUtility::genGlobalIndex(nLocalCells * 3);
118  globalFaceNumbering = DAUtility::genGlobalIndex(nLocalFaces);
119  globalXvNumbering = DAUtility::genGlobalIndex(nLocalXv);
120 
121  // global Adjoint state sizes
122  nGlobalAdjointStates = globalAdjointStateNumbering.size();
123  nGlobalCells = globalCellNumbering.size();
124  nGlobalFaces = globalFaceNumbering.size();
125  nGlobalXv = globalXvNumbering.size();
126 
127  // now compute nUndecomposedPoints based on pointProcAddressing
128  // this will be used in generating the total sensitivity for the undecomposed domain
129  // for sensitivity map plot
130  if (!Pstream::parRun())
131  {
132  // for serial cases, pointProcAddressing is an empty list, so manually assign it
133  for (label i = 0; i < nLocalPoints; i++)
134  {
135  pointProcAddressing.append(i);
136  }
137 
138  nUndecomposedPoints = nLocalPoints;
139  }
140  else
141  {
142  // for parallel cases, we can read pointProcAddressing
143  // get the global point size
144  label pointMaxIdx = max(pointProcAddressing);
145  reduce(pointMaxIdx, maxOp<label>());
146  // +1 since procAddressing point index starts with 0
147  nUndecomposedPoints = pointMaxIdx + 1;
148  }
149 
150  // initialize stuff
151  // calculate nLocalCoupledBFaces and isCoupledFace
152  isCoupledFace.setSize(nLocalFaces);
153  for (label i = 0; i < nLocalFaces; i++)
154  {
155  isCoupledFace[i] = 0;
156  }
157 
158  nLocalCoupledBFaces = 0;
159  label faceIdx = nLocalInternalFaces;
160  forAll(mesh_.boundaryMesh(), patchI)
161  {
162  forAll(mesh_.boundaryMesh()[patchI], faceI)
163  {
164  if (mesh_.boundaryMesh()[patchI].coupled())
165  {
166  // this is a coupled patch
167  isCoupledFace[faceIdx] = 1;
168  nLocalCoupledBFaces++;
169  }
170  faceIdx++;
171  }
172  }
173  // now initialize the gloalindex for bFace
174  globalCoupledBFaceNumbering = DAUtility::genGlobalIndex(nLocalCoupledBFaces);
175  nGlobalCoupledBFaces = globalCoupledBFaceNumbering.size();
176 
177  // calculate some local lists for indexing
178  this->calcLocalIdxLists(adjStateName4LocalAdjIdx, cellIFaceI4LocalAdjIdx);
179 
180  if (daOption_.getOption<label>("debug"))
181  {
182  this->writeAdjointIndexing();
183  }
184 }
185 
186 void DAIndex::calcStateLocalIndexOffset(HashTable<label>& offset)
187 {
188  /*
189  Description:
190  Calculate the indexing offset for all states (stateLocalIndexOffset),
191  this will be used in the DAIndex::getLocalAdjointStateIndex function
192 
193  For state-by-state ordering, we set u_0, v_0, w_0, u_1, v_1, w_1,
194  ...., p_0, p_1, ... nuTilda_0, nuTilda_1, ... with subscript being the
195  cell index. stateLocalIndexingOffset will return how many states are
196  before a specific stateName
197 
198  For cell by cell ordering, we set u_0, v_0, w_0, p_0, nuTilda_0, phi_0, ....
199  u_N, v_N, w_N, p_N, nuTilda_N, phi_N with subscript being the cell index.
200  so stateLocalIndexingOffset will return how many states are before a specific
201  stateName for a given cell index
202 
203  Output:
204  offset: hash table of local state variable index offset, This will be used in
205  determing the local indexing for adjoint states. It differs depending on whether
206  we use state-by-state or cell-by-cell ordering
207  */
208 
209  word adjStateOrdering = daOption_.getOption<word>("adjStateOrdering");
210 
211  if (adjStateOrdering == "state")
212  {
213 
214  forAll(adjStateNames, idxI)
215  {
216  word stateName = adjStateNames[idxI];
217 
218  label counter = 0;
219 
220  forAll(stateInfo_["volVectorStates"], idx)
221  {
222  if (stateInfo_["volVectorStates"][idx] == stateName)
223  {
224  offset.set(stateName, counter * nLocalCells);
225  }
226  counter += 3;
227  }
228 
229  forAll(stateInfo_["volScalarStates"], idx)
230  {
231  if (stateInfo_["volScalarStates"][idx] == stateName)
232  {
233  offset.set(stateName, counter * nLocalCells);
234  }
235  counter++;
236  }
237 
238  forAll(stateInfo_["modelStates"], idx)
239  {
240  if (stateInfo_["modelStates"][idx] == stateName)
241  {
242  offset.set(stateName, counter * nLocalCells);
243  }
244  counter++;
245  }
246 
247  forAll(stateInfo_["surfaceScalarStates"], idx)
248  {
249  if (stateInfo_["surfaceScalarStates"][idx] == stateName && idx == 0)
250  {
251  offset.set(stateName, counter * nLocalCells);
252  }
253  if (stateInfo_["surfaceScalarStates"][idx] == stateName && idx > 0)
254  {
255  offset.set(stateName, counter * nLocalFaces);
256  }
257  counter++;
258  }
259  }
260  }
261  else if (adjStateOrdering == "cell")
262  {
263 
264  forAll(adjStateNames, idxI)
265  {
266  word stateName = adjStateNames[idxI];
267 
268  label counter = 0;
269 
270  forAll(stateInfo_["volVectorStates"], idx)
271  {
272  if (stateInfo_["volVectorStates"][idx] == stateName)
273  {
274  offset.set(stateName, counter);
275  }
276  counter += 3;
277  }
278 
279  forAll(stateInfo_["volScalarStates"], idx)
280  {
281  if (stateInfo_["volScalarStates"][idx] == stateName)
282  {
283  offset.set(stateName, counter);
284  }
285  counter++;
286  }
287 
288  forAll(stateInfo_["modelStates"], idx)
289  {
290  if (stateInfo_["modelStates"][idx] == stateName)
291  {
292  offset.set(stateName, counter);
293  }
294  counter++;
295  }
296 
297  forAll(stateInfo_["surfaceScalarStates"], idx)
298  {
299  if (stateInfo_["surfaceScalarStates"][idx] == stateName)
300  {
301  offset.set(stateName, counter);
302  }
303  counter++;
304  }
305  }
306 
307  // We also need a few more offsets
308 
309  // calculate faceOwner
310  faceOwner.setSize(nLocalFaces);
311  const UList<label>& internalFaceOwner = mesh_.owner(); // these only include internal faces owned cellI
312  forAll(faceOwner, idxI)
313  {
314  if (idxI < nLocalInternalFaces)
315  {
316  faceOwner[idxI] = internalFaceOwner[idxI];
317  }
318  else
319  {
320  label relIdx = idxI - nLocalInternalFaces;
321  label patchIdx = bFacePatchI[relIdx];
322  label faceIdx = bFaceFaceI[relIdx];
323  const UList<label>& pFaceCells = mesh_.boundaryMesh()[patchIdx].faceCells();
324  faceOwner[idxI] = pFaceCells[faceIdx];
325  }
326  }
327 
328  // Calculate the cell owned face index. Note: we can't use mesh.cells here since it will have
329  // duplicated face indices
330  List<List<label>> cellOwnedFaces;
331  cellOwnedFaces.setSize(nLocalCells);
332  forAll(faceOwner, idxI)
333  {
334  label ownedCellI = faceOwner[idxI];
335  cellOwnedFaces[ownedCellI].append(idxI);
336  }
337  //Info<<"cellOwnedFaces "<<cellOwnedFaces<<endl;
338  // check if every cells have owned faces
339  // This is unnecessary since some cells may own no face.
340  //forAll(cellOwnedFaces,idxI)
341  //{
342  // if(cellOwnedFaces[idxI].size()==0) FatalErrorIn("")<<"cell "<<idxI<<" owns no faces"<<abort(FatalError);
343  //}
344 
345  // We first calculate phiAccumulatedOffset
348  {
349  phiAccumulatdOffset[idxI] = 0;
350  }
351  // if we have no surfaceScalarStates, phiAccumulatdOffset remains zeros
352  if (stateInfo_["surfaceScalarStates"].size() > 0)
353  {
355  {
356  if (idxI == 0)
357  {
358  phiAccumulatdOffset[idxI] = 0;
359  }
360  else
361  {
362  phiAccumulatdOffset[idxI] = cellOwnedFaces[idxI - 1].size() + phiAccumulatdOffset[idxI - 1];
363  }
364  }
365  }
366  //Info<<"phiAccumulatdOffset "<<phiAccumulatdOffset<<endl;
367 
368  // Now calculate the phiLocalOffset
369  phiLocalOffset.setSize(nLocalFaces);
370  forAll(phiLocalOffset, idxI)
371  {
372  phiLocalOffset[idxI] = 0;
373  }
374  // if we have no surfaceScalarStates, phiAccumulatdOffset remains zeros
375  if (stateInfo_["surfaceScalarStates"].size() > 0)
376  {
377  forAll(cellOwnedFaces, idxI) // idxI is cell Index
378  {
379  forAll(cellOwnedFaces[idxI], offsetI)
380  {
381  label ownedFace = cellOwnedFaces[idxI][offsetI];
382  phiLocalOffset[ownedFace] = offsetI;
383  }
384  }
385  }
386  //Info<<"phiLocalOffset "<<phiLocalOffset<<endl;
387  //Info<<"stateLocalIndexOffset "<<stateLocalIndexOffset<<endl;
388  }
389  else
390  {
391  FatalErrorIn("") << "adjStateOrdering invalid" << abort(FatalError);
392  }
393 
394  return;
395 }
396 
397 void DAIndex::calcAdjStateID(HashTable<label>& adjStateID)
398 {
399  /*
400  Description:
401  The stateID is an alternative for the stateNames
402  stateID starts from 0 for the first volVector state
403  e.g., if the state variables are U, p, nut, phi, their
404  state ID are U=0, p=1, nut=2, phi=3
405 
406  Output:
407  adjStateID: the state ID list
408  */
409 
410  label id = 0;
411  forAll(stateInfo_["volVectorStates"], idx)
412  {
413  word stateName = stateInfo_["volVectorStates"][idx];
414  adjStateID.set(stateName, id);
415  id++;
416  }
417 
418  forAll(stateInfo_["volScalarStates"], idx)
419  {
420  word stateName = stateInfo_["volScalarStates"][idx];
421  adjStateID.set(stateName, id);
422  id++;
423  }
424 
425  forAll(stateInfo_["modelStates"], idx)
426  {
427  word stateName = stateInfo_["modelStates"][idx];
428  adjStateID.set(stateName, id);
429  id++;
430  }
431 
432  forAll(stateInfo_["surfaceScalarStates"], idx)
433  {
434  word stateName = stateInfo_["surfaceScalarStates"][idx];
435  adjStateID.set(stateName, id);
436  id++;
437  }
438  return;
439 }
440 
442  wordList& stateName4LocalAdjIdx,
443  scalarList& cellIFaceI4LocalIdx)
444 {
445  /*
446  Description:
447  Calculate indexing lists:
448  cellIFaceI4LocalAdjIdx
449  adjStateName4LocalAdjIdx
450 
451  Output:
452  cellIFaceI4LocalAdjIdx: stores the cell/face index for a local adjoint index
453  For vector fields, the decima of cellIFaceI4LocalIdx denotes the vector component
454  e.g., 10.1 means cellI=10, y compoent of U
455 
456  adjStateName4LocalAdjIdx: stores the state name for a local adjoint index
457  */
458 
459  cellIFaceI4LocalIdx.setSize(nLocalAdjointStates);
460  stateName4LocalAdjIdx.setSize(nLocalAdjointStates);
461 
462  forAll(stateInfo_["volVectorStates"], idx)
463  {
464  word stateName = stateInfo_["volVectorStates"][idx];
465  forAll(mesh_.cells(), cellI)
466  {
467  for (label i = 0; i < 3; i++)
468  {
469  label localIdx = this->getLocalAdjointStateIndex(stateName, cellI, i);
470  cellIFaceI4LocalIdx[localIdx] = cellI + i / 10.0;
471 
472  stateName4LocalAdjIdx[localIdx] = stateName;
473  }
474  }
475  }
476 
477  forAll(stateInfo_["volScalarStates"], idx)
478  {
479  word stateName = stateInfo_["volScalarStates"][idx];
480  forAll(mesh_.cells(), cellI)
481  {
482  label localIdx = this->getLocalAdjointStateIndex(stateName, cellI);
483  cellIFaceI4LocalIdx[localIdx] = cellI;
484 
485  stateName4LocalAdjIdx[localIdx] = stateName;
486  }
487  }
488 
489  forAll(stateInfo_["modelStates"], idx)
490  {
491  word stateName = stateInfo_["modelStates"][idx];
492  forAll(mesh_.cells(), cellI)
493  {
494  label localIdx = this->getLocalAdjointStateIndex(stateName, cellI);
495  cellIFaceI4LocalIdx[localIdx] = cellI;
496 
497  stateName4LocalAdjIdx[localIdx] = stateName;
498  }
499  }
500 
501  forAll(stateInfo_["surfaceScalarStates"], idx)
502  {
503  word stateName = stateInfo_["surfaceScalarStates"][idx];
504  forAll(mesh_.faces(), faceI)
505  {
506  label localIdx = this->getLocalAdjointStateIndex(stateName, faceI);
507  cellIFaceI4LocalIdx[localIdx] = faceI;
508 
509  stateName4LocalAdjIdx[localIdx] = stateName;
510  }
511  }
512 
513  return;
514 }
515 
517  const word stateName,
518  const label idxJ,
519  const label comp) const
520 {
521  /*
522  Description:
523  Return the global adjoint index given a state name, a local index,
524  and vector component (optional)
525 
526  Input:
527  stateName: name of the state variable for the global indexing
528 
529  idxJ: the local index for the state variable, typically it is the state's
530  local cell index or face index
531 
532  comp: if the state is a vector, give its componet for global indexing.
533  NOTE: for volVectorState, one need to set comp; while for other states,
534  comp is simply ignored in this function
535 
536  Example:
537  Image we have two state variables (p, T) and we have three cells, the state
538  variable vector reads (state-by-state ordering):
539 
540  w= [p0, p1, p2, T0, T1, T2] <- p0 means p for the 0th cell
541  0 1 2 3 4 5 <- adjoint local index
542 
543  Then getLocalAdjointStateIndex("p",1) returns 1 and
544  getLocalAdjointStateIndex("T",1) returns 4
545 
546  If we use cell-by-cell ordering, the state variable vector reads
547  w= [p0, T0, p1, T1, p2, T2]
548  0 1 2 3 4 5 <- adjoint local index
549 
550  Then getLocalAdjointStateIndex("p",1) returns 2 and
551  getLocalAdjointStateIndex("T",1) returns 3
552 
553  Similarly, we can apply this functions for vector state variables, again
554  we assume we have two state variables (U, p) and three cells, then the
555  state-by-state adjoint ordering gives
556 
557  w= [u0, v0, w0, u1, v1, w1, u2, v2, w2, p0, p1, p2]
558  0 1 2 3 4 5 6 7 8 9 10 11 <- adjoint local index
559 
560  Then getLocalAdjointStateIndex("U", 1, 2) returns 5 and
561  getLocalAdjointStateIndex("p",1) returns 10
562 
563  NOTE: the three compoent for U are [u,v,w]
564 
565  */
566 
567  word adjStateOrdering = daOption_.getOption<word>("adjStateOrdering");
568 
569  if (adjStateOrdering == "state")
570  {
571  /*
572  state by state indexing
573  we set u_0, v_1, w_2, u_3, v_4, w_5, ...., p_np, p_np+1, ... nuTilda_nnu,
574  nuTilda_nnu+1, ... so getStateLocalIndexingOffset(p) will return np
575  For vector, one need to provide comp, for scalar, comp is not needed.
576  */
577  forAll(adjStateNames, idxI)
578  {
579  if (adjStateNames[idxI] == stateName)
580  {
581  if (adjStateType[stateName] == "volVectorState")
582  {
583  if (comp == -1)
584  {
585  FatalErrorIn("") << "comp needs to be set for vector states!"
586  << abort(FatalError);
587  }
588  else
589  {
590  return stateLocalIndexOffset[stateName] + idxJ * 3 + comp;
591  }
592  }
593  else
594  {
595  return stateLocalIndexOffset[stateName] + idxJ;
596  }
597  }
598  }
599  }
600  else if (adjStateOrdering == "cell")
601  {
602  // cell by cell ordering
603  // We set u_0, v_0, w_0, p_0, nuTilda_0, phi_0a,phi_0b,phi_0c.... u_N, v_N, w_N, p_N, nuTilda_N, phi_N
604  // To get the local index, we need to do:
605  // idxLocal =
606  // cellI*(nVectorStates*3+nScalarStates+nTurbStates)
607  // + phiAccumulatedOffset (how many phis have been accumulated. Note: we have mulitple phis for a cellI)
608  // + stateLocalIndexOffset+comp
609  // + phiLocalOffset (only for phi idx, ie. 0a or 0b or oc. Note: we have mulitple phis for a cellI)
610 
611  label nCellStates = 3 * nVolVectorStates
613  + nModelStates;
614 
615  const word& stateType = adjStateType[stateName];
616  label returnV = -99999999;
617  if (stateType == "surfaceScalarState") // for surfaceScalarState idxJ is faceI
618  {
619  label idxN = faceOwner[idxJ]; // idxN is the cell who owns faceI
620  returnV = idxN * nCellStates
621  + stateLocalIndexOffset[stateName]
622  + phiAccumulatdOffset[idxN]
623  + phiLocalOffset[idxJ];
624  return returnV;
625  }
626  else if (stateType == "volVectorState") // for other states idxJ is cellI
627  {
628  if (comp == -1)
629  {
630  FatalErrorIn("") << "comp needs to be set for vector states!"
631  << abort(FatalError);
632  }
633  else
634  {
635 
636  returnV = idxJ * nCellStates
637  + stateLocalIndexOffset[stateName]
638  + comp
639  + phiAccumulatdOffset[idxJ];
640  }
641  return returnV;
642  }
643  else
644  {
645  returnV = idxJ * nCellStates
646  + stateLocalIndexOffset[stateName]
647  + phiAccumulatdOffset[idxJ];
648  return returnV;
649  }
650  }
651  else
652  {
653  FatalErrorIn("") << "adjStateOrdering invalid" << abort(FatalError);
654  }
655 
656  // if no stateName found, return an error
657  FatalErrorIn("") << "stateName not found!" << abort(FatalError);
658  return -1;
659 }
660 
662  const word stateName,
663  const label idxI,
664  const label comp) const
665 {
666  /*
667  Description:
668  This function has the same input as DAIndex::getLocalAdjointStateIndex
669  the only difference is that this function returns the global adjoint
670  state index by calling globalAdjointStateNumbering.toGlobal()
671 
672  Input:
673  stateName: name of the state variable for the global indexing
674 
675  idxJ: the local index for the state variable, typically it is the state's
676  local cell index or face index
677 
678  comp: if the state is a vector, give its componet for global indexing.
679  NOTE: for volVectorState, one need to set comp; while for other states,
680  comp is simply ignored in this function
681 
682 
683  Example:
684  Image we have two state variables (p,T) and five cells, running on two CPU
685  processors, the proc0 owns two cells and the proc1 owns three cells,
686  then the global adjoint state variables reads (state-by-state)
687 
688  w = [p0, p1, T0, T1 | p0, p1, p2, T0, T1, T2] <- p0 means p for the 0th cell on local processor
689  0 1 2 3 | 4 5 6 7 8 9 <- global adjoint index
690  ---- proc0 -----|--------- proc1 -------
691 
692  Then, on proc0, getGlobalAdjointStateIndex("T", 1) returns 3
693  and on proc1, getGlobalAdjointStateIndex("T", 1) returns 8
694 
695  */
696  // For vector, one need to provide comp, for scalar, comp is not needed.
697  label localIdx = this->getLocalAdjointStateIndex(stateName, idxI, comp);
698  label globalIdx = globalAdjointStateNumbering.toGlobal(localIdx);
699  return globalIdx;
700 }
701 
703  const label idxPoint,
704  const label idxCoord) const
705 {
706  /*
707  Description:
708  This function has the same input as DAIndex::getLocalXvIndex except that
709  this function returns the global xv index
710 
711  Input:
712  idxPoint: local point index
713 
714  idxCoord: the compoent of the point
715 
716  Example:
717  Image we have three points, running on two CPU cores, and the proc0 owns
718  one point and proc1 owns two points, and the Xv vector reads
719 
720  Xv = [x0, y0, z0 | x0, y0, z0, x1, y1, z1] <- x0 means the x for the 0th point
721  0 1 2 3 4 5 6 7 8 <- global Xv index
722  -- proc0 --|--------- proc1 -------
723  Then, on proc0, getGlobalXvIndex(0,1) returns 1
724  and on proc1, getGlobalXvIndex(0,1) returns 4
725 
726  */
727 
728  label localXvIdx = this->getLocalXvIndex(idxPoint, idxCoord);
729  label globalXvIdx = globalXvNumbering.toGlobal(localXvIdx);
730  return globalXvIdx;
731 }
732 
734  const label idxPoint,
735  const label idxCoord) const
736 {
737  /*
738  Description:
739  Returns the local xv index for a given local cell index and its component
740 
741  Input:
742  idxPoint: local point index
743 
744  idxCoord: the compoent of the point
745 
746  Example:
747  Image we have two points, and the Xv vector reads
748 
749  Xv = [x0, y0, z0, x1, y1, z1] <- x0 means the x for the 0th point
750  0 1 2 3 4 5 <- local Xv index
751 
752  Then, getLocalXvIndex(1,1) returns 4
753 
754  */
755 
756  label localXvIdx = idxPoint * 3 + idxCoord;
757  return localXvIdx;
758 }
759 
760 label DAIndex::getLocalCellIndex(const label cellI) const
761 {
762  /*
763  Description:
764  Returns the local cell index for a given local cell index
765 
766  Input:
767  cellI: local mesh cell index
768 
769  Example:
770  Image we have three cells, the local vector reads
771 
772  cVec = [c0, c1, c2] <- c0 means the 0th cell
773  0 1 2 <- local cell index
774 
775  Then, getLocalCellIndex(1) returns 1
776  NOTE: we essentially just return cellI
777 
778  */
779  return cellI;
780 }
781 
782 label DAIndex::getGlobalCellIndex(const label cellI) const
783 {
784  /*
785  Description:
786  Returns the global cell index for a given local cell index
787 
788  Input:
789  cellI: local cell index
790 
791  Example:
792  Image we have nine cells, running on two CPU cores, and the proc0 owns
793  three cell and proc1 owns six cell, and the cell vector reads
794 
795  cVec = [c0, c1, c2 | c0, c1, c2, c3, c4, c5] <- c0 means the 0th cell
796  0 1 2 3 4 5 6 7 8 <- global cell index
797  -- proc0 --|--------- proc1 -------
798  Then, on proc0, getGlobalCellIndex(1) returns 1
799  and on proc1, getGlobalCellIndex(1) returns 4
800 
801  */
802 
803  label localIdx = this->getLocalCellIndex(cellI);
804  label globalIdx = globalCellNumbering.toGlobal(localIdx);
805  return globalIdx;
806 }
807 
809  const label cellI,
810  const label comp) const
811 {
812  /*
813  Description:
814  Returns the local cell index for a given local cell vector index
815 
816  Input:
817  cellI: local mesh cell index
818 
819  comp: the vector component
820 
821  Example:
822  Image we have two cells, the local vector reads
823 
824  cVec = [c0a, c0b, c0c, c1a, c1b, c1c] <- c0b means the 0th cell, 1st vector component
825  0 1 2 3 4 5 <- local cell vector index
826 
827  Then, getLocalCellIndex(1,1) returns 4
828 
829  */
830  label localIdx = cellI * 3 + comp;
831  return localIdx;
832 }
833 
835  const label cellI,
836  const label comp) const
837 {
838  /*
839  Description:
840  Returns the global cell index for a given local cell vector index
841 
842  Input:
843  cellI: local cell index
844 
845  comp: the vector component
846 
847  Example:
848  Image we have three cells, running on two CPU cores, and the proc0 owns
849  two cells and proc1 owns one cell, and the cell vector reads
850 
851  cVec = [c0a, c0b, c0c, c1a, c1b, c1c | c0a, c0b, c0c] <- c0b means the 0th cell, 1st vector component
852  0 1 2 3 4 5 6 7 8 <- global cell index
853  --------- proc0 -------------|---- proc1 ---
854  Then, on proc0, getGlobalCellVectorIndex(0, 1) returns 1
855  and on proc1, getGlobalCellVectorIndex(0, 1) returns 7
856 
857  */
858 
859  label localIdx = this->getLocalCellVectorIndex(cellI, comp);
860  label globalIdx = globalCellVectorNumbering.toGlobal(localIdx);
861  return globalIdx;
862 }
863 
864 label DAIndex::getLocalFaceIndex(const label faceI) const
865 {
866  /*
867  Description:
868  Returns the local face index for a given local face index
869 
870  Input:
871  faceI: local mesh face index (including the boundary faces)
872 
873  Example:
874  Image we have three faces, the local vector reads
875 
876  fVec = [f0, f1, f2] <- f0 means the 0th face
877  0 1 2 <- local face index
878 
879  Then, getLocalFaceIndex(1) returns 1
880  NOTE: we essentially just return faceI
881 
882  */
883  return faceI;
884 }
885 
886 label DAIndex::getGlobalFaceIndex(const label faceI) const
887 {
888  /*
889  Description:
890  Returns the global face index for a given local face index
891 
892  Input:
893  faceI: local mesh face index (including the boundary faces)
894 
895  Example:
896  Image we have nine faces, running on two CPU cores, and the proc0 owns
897  three faces and proc1 owns six faces, and the face vector reads
898 
899  fVec = [f0, f1, f2 | f0, f1, f2, f3, f4, f5] <- f0 means the 0th face
900  0 1 2 3 4 5 6 7 8 <- global face index
901  -- proc0 --|--------- proc1 -------
902  Then, on proc0, getGlobalFaceIndex(1) returns 1
903  and on proc1, getGlobalFaceIndex(1) returns 4
904 
905  */
906 
907  label localIdx = this->getLocalFaceIndex(faceI);
908  label globalIdx = globalFaceNumbering.toGlobal(localIdx);
909  return globalIdx;
910 }
911 
912 void DAIndex::calcAdjStateID4GlobalAdjIdx(labelList& adjStateID4GlobalAdjIdx) const
913 {
914  /*
915  Description:
916  Compute adjStateID4GlobalAdjIdx
917 
918  Output:
919  adjStateID4GlobalAdjIdx: labelList that stores the adjStateID for given a global adj index
920  NOTE: adjStateID4GlobalAdjIdx contains all the global adj indices, so its memory usage
921  is high. We should avoid having any sequential list; however, to make the connectivity
922  calculation easier, we keep it for now.
923  *******delete this list after used!************
924  */
925 
926  if (adjStateID4GlobalAdjIdx.size() != nGlobalAdjointStates)
927  {
928  FatalErrorIn("") << "adjStateID4GlobalAdjIdx.size()!=nGlobalAdjointStates"
929  << abort(FatalError);
930  }
931 
932  Vec stateIVec;
933  VecCreate(PETSC_COMM_WORLD, &stateIVec);
934  VecSetSizes(stateIVec, nLocalAdjointStates, PETSC_DECIDE);
935  VecSetFromOptions(stateIVec);
936  VecSet(stateIVec, 0); // default value
937 
938  forAll(stateInfo_["volVectorStates"], idx)
939  {
940  word stateName = stateInfo_["volVectorStates"][idx];
941  PetscScalar valIn = adjStateID[stateName] + 1; // we need to use 1-based indexing here for scattering
942  forAll(mesh_.cells(), cellI)
943  {
944  for (label i = 0; i < 3; i++)
945  {
946  label globalIdx = this->getGlobalAdjointStateIndex(stateName, cellI, i);
947  VecSetValues(stateIVec, 1, &globalIdx, &valIn, INSERT_VALUES);
948  }
949  }
950  }
951 
952  forAll(stateInfo_["volScalarStates"], idx)
953  {
954  word stateName = stateInfo_["volScalarStates"][idx];
955  PetscScalar valIn = adjStateID[stateName] + 1; // we need to use 1-based indexing here for scattering
956  forAll(mesh_.cells(), cellI)
957  {
958  label globalIdx = this->getGlobalAdjointStateIndex(stateName, cellI);
959  VecSetValues(stateIVec, 1, &globalIdx, &valIn, INSERT_VALUES);
960  }
961  }
962 
963  forAll(stateInfo_["modelStates"], idx)
964  {
965  word stateName = stateInfo_["modelStates"][idx];
966  PetscScalar valIn = adjStateID[stateName] + 1; // we need to use 1-based indexing here for scattering
967  forAll(mesh_.cells(), cellI)
968  {
969  label globalIdx = this->getGlobalAdjointStateIndex(stateName, cellI);
970  VecSetValues(stateIVec, 1, &globalIdx, &valIn, INSERT_VALUES);
971  }
972  }
973 
974  forAll(stateInfo_["surfaceScalarStates"], idx)
975  {
976  word stateName = stateInfo_["surfaceScalarStates"][idx];
977  PetscScalar valIn = adjStateID[stateName] + 1; // we need to use 1-based indexing here for scattering
978  forAll(mesh_.faces(), faceI)
979  {
980  label globalIdx = this->getGlobalAdjointStateIndex(stateName, faceI);
981  VecSetValues(stateIVec, 1, &globalIdx, &valIn, INSERT_VALUES);
982  }
983  }
984 
985  VecAssemblyBegin(stateIVec);
986  VecAssemblyEnd(stateIVec);
987 
988  // scatter to local array for all procs
989  Vec vout;
990  VecScatter ctx;
991  VecScatterCreateToAll(stateIVec, &ctx, &vout);
992  VecScatterBegin(ctx, stateIVec, vout, INSERT_VALUES, SCATTER_FORWARD);
993  VecScatterEnd(ctx, stateIVec, vout, INSERT_VALUES, SCATTER_FORWARD);
994 
995  PetscScalar* stateIVecArray;
996  VecGetArray(vout, &stateIVecArray);
997 
998  for (label i = 0; i < nGlobalAdjointStates; i++)
999  {
1000  adjStateID4GlobalAdjIdx[i] = static_cast<label>(stateIVecArray[i]) - 1; // subtract 1 and return to 0-based indexing
1001  }
1002 
1003  VecRestoreArray(vout, &stateIVecArray);
1004  VecScatterDestroy(&ctx);
1005  VecDestroy(&vout);
1006 
1007  return;
1008 }
1009 
1010 void DAIndex::printMatChars(const Mat matIn) const
1011 {
1012  /*
1013  Description:
1014  Calculate and print some matrix statistics such as the
1015  max ratio of on and off diagonal elements
1016  */
1017 
1018  PetscInt nCols, Istart, Iend;
1019  const PetscInt* cols;
1020  const PetscScalar* vals;
1021  scalar maxRatio = 0.0;
1022  label maxRatioRow = -1;
1023  scalar diagV = -1.0;
1024  scalar maxNonDiagV = -1.0;
1025  label maxNonDiagCol = -1;
1026  scalar small = 1e-12;
1027  scalar allNonZeros = 0.0;
1028  label maxCols = -1;
1029 
1030  this->getMatNonZeros(matIn, maxCols, allNonZeros);
1031 
1032  MatGetOwnershipRange(matIn, &Istart, &Iend);
1033  for (label i = Istart; i < Iend; i++)
1034  {
1035  scalar diag = 0;
1036  scalar nonDiagSum = 0;
1037  scalar maxV = 0.0;
1038  label maxVIdx = -1;
1039  MatGetRow(matIn, i, &nCols, &cols, &vals);
1040  for (label n = 0; n < nCols; n++)
1041  {
1042  if (i == cols[n])
1043  {
1044  diag = vals[n];
1045  }
1046  if (vals[n] != 0)
1047  {
1048  if (i != cols[n])
1049  {
1050  nonDiagSum = nonDiagSum + fabs(vals[n]);
1051  }
1052  if (fabs(vals[n]) > maxV)
1053  {
1054  maxV = fabs(vals[n]);
1055  maxVIdx = cols[n];
1056  }
1057  }
1058  }
1059 
1060  if (fabs(nonDiagSum / (diag + small)) > maxRatio)
1061  {
1062  maxRatio = fabs(nonDiagSum / (diag + small));
1063  maxRatioRow = i;
1064  maxNonDiagCol = maxVIdx;
1065  diagV = diag;
1066  maxNonDiagV = maxV;
1067  }
1068 
1069  MatRestoreRow(matIn, i, &nCols, &cols, &vals);
1070  }
1071 
1072  label rowStateID = -1;
1073  label colStateID = -1;
1074  vector rowCoord(0, 0, 0), colCoord(0, 0, 0);
1075 
1076  forAll(stateInfo_["volVectorStates"], idx)
1077  {
1078  const word& stateName = stateInfo_["volVectorStates"][idx];
1079  forAll(mesh_.cells(), cellI)
1080  {
1081  for (label i = 0; i < 3; i++)
1082  {
1083  label idxJ = getGlobalAdjointStateIndex(stateName, cellI, i);
1084  if (idxJ == maxRatioRow)
1085  {
1086  rowStateID = adjStateID[stateName];
1087  rowCoord = mesh_.C()[cellI];
1088  }
1089  if (idxJ == maxNonDiagCol)
1090  {
1091  colStateID = adjStateID[stateName];
1092  colCoord = mesh_.C()[cellI];
1093  }
1094  }
1095  }
1096  }
1097 
1098  forAll(stateInfo_["volScalarStates"], idx)
1099  {
1100  const word& stateName = stateInfo_["volScalarStates"][idx];
1101  forAll(mesh_.cells(), cellI)
1102  {
1103 
1104  label idxJ = getGlobalAdjointStateIndex(stateName, cellI);
1105  if (idxJ == maxRatioRow)
1106  {
1107  rowStateID = adjStateID[stateName];
1108  rowCoord = mesh_.C()[cellI];
1109  }
1110  if (idxJ == maxNonDiagCol)
1111  {
1112  colStateID = adjStateID[stateName];
1113  colCoord = mesh_.C()[cellI];
1114  }
1115  }
1116  }
1117 
1118  forAll(stateInfo_["modelStates"], idx)
1119  {
1120  const word& stateName = stateInfo_["modelStates"][idx];
1121  forAll(mesh_.cells(), cellI)
1122  {
1123 
1124  label idxJ = getGlobalAdjointStateIndex(stateName, cellI);
1125  if (idxJ == maxRatioRow)
1126  {
1127  rowStateID = adjStateID[stateName];
1128  rowCoord = mesh_.C()[cellI];
1129  }
1130  if (idxJ == maxNonDiagCol)
1131  {
1132  colStateID = adjStateID[stateName];
1133  colCoord = mesh_.C()[cellI];
1134  }
1135  }
1136  }
1137 
1138  forAll(stateInfo_["surfaceScalarStates"], idx)
1139  {
1140  const word& stateName = stateInfo_["surfaceScalarStates"][idx];
1141  forAll(mesh_.faces(), faceI)
1142  {
1143 
1144  label idxJ = getGlobalAdjointStateIndex(stateName, faceI);
1145 
1146  if (idxJ == maxRatioRow)
1147  {
1148  rowStateID = adjStateID[stateName];
1149  if (faceI < nLocalInternalFaces)
1150  {
1151  rowCoord = mesh_.Cf()[faceI];
1152  }
1153  else
1154  {
1155  label relIdx = faceI - nLocalInternalFaces;
1156  label patchIdx = bFacePatchI[relIdx];
1157  label faceIdx = bFaceFaceI[relIdx];
1158  rowCoord = mesh_.Cf().boundaryField()[patchIdx][faceIdx];
1159  }
1160  }
1161  if (idxJ == maxNonDiagCol)
1162  {
1163  colStateID = adjStateID[stateName];
1164  if (faceI < nLocalInternalFaces)
1165  {
1166  colCoord = mesh_.Cf()[faceI];
1167  }
1168  else
1169  {
1170  label relIdx = faceI - nLocalInternalFaces;
1171  label patchIdx = bFacePatchI[relIdx];
1172  label faceIdx = bFaceFaceI[relIdx];
1173  colCoord = mesh_.Cf().boundaryField()[patchIdx][faceIdx];
1174  }
1175  }
1176  }
1177  }
1178 
1179  // create a list to store the info
1180  List<scalar> matCharInfo(13);
1181  matCharInfo[0] = maxRatio;
1182  matCharInfo[1] = diagV;
1183  matCharInfo[2] = maxNonDiagV;
1184  matCharInfo[3] = maxRatioRow;
1185  matCharInfo[4] = rowStateID;
1186  matCharInfo[5] = rowCoord.x();
1187  matCharInfo[6] = rowCoord.y();
1188  matCharInfo[7] = rowCoord.z();
1189  matCharInfo[8] = maxNonDiagCol;
1190  matCharInfo[9] = colStateID;
1191  matCharInfo[10] = colCoord.x();
1192  matCharInfo[11] = colCoord.y();
1193  matCharInfo[12] = colCoord.z();
1194 
1195  // now gather all the info
1196  label myProc = Pstream::myProcNo();
1197  label nProcs = Pstream::nProcs();
1198  // create listlist for gathering
1199  List<List<scalar>> gatheredList(nProcs);
1200  // assign values for the listlists
1201  gatheredList[myProc] = matCharInfo;
1202  // gather all info to the master proc
1203  Pstream::gatherList(gatheredList);
1204  // scatter all info to every procs
1205  Pstream::scatterList(gatheredList);
1206 
1207  scalar maxRatioGathered = -1.0;
1208  label procI = -1;
1209  for (label i = 0; i < nProcs; i++)
1210  {
1211  if (fabs(gatheredList[i][0]) > maxRatioGathered)
1212  {
1213  maxRatioGathered = fabs(gatheredList[i][0]);
1214  procI = i;
1215  }
1216  }
1217 
1218  Info << endl;
1219  Info << "Jacobian Matrix Characteristics: " << endl;
1220  Info << " Mat maxCols: " << maxCols << endl;
1221  Info << " Mat allNonZeros: " << allNonZeros << endl;
1222  Info << " Max nonDiagSum/Diag: " << gatheredList[procI][0]
1223  << " Diag: " << gatheredList[procI][1] << " MaxNonDiag: " << gatheredList[procI][2] << endl;
1224  Info << " MaxRatioRow: " << gatheredList[procI][3] << " RowState: " << gatheredList[procI][4]
1225  << " RowCoord: (" << gatheredList[procI][5] << " " << gatheredList[procI][6]
1226  << " " << gatheredList[procI][7] << ")" << endl;
1227  Info << " MaxNonDiagCol: " << gatheredList[procI][8] << " ColState: " << gatheredList[procI][9]
1228  << " ColCoord: (" << gatheredList[procI][10] << " " << gatheredList[procI][11]
1229  << " " << gatheredList[procI][12] << ")" << endl;
1230  Info << " Max nonDiagSum/Diag ProcI: " << procI << endl;
1231  Info << endl;
1232 
1233  return;
1234 }
1235 
1237  const Mat matIn,
1238  label& maxCols,
1239  scalar& allNonZeros) const
1240 {
1241  /*
1242  Description:
1243  Get the max nonzeros per row, and all the nonzeros for this matrix
1244  */
1245 
1246  PetscInt nCols, Istart, Iend;
1247  const PetscInt* cols;
1248  const PetscScalar* vals;
1249 
1250  // set the counter
1251  maxCols = 0;
1252  allNonZeros = 0.0;
1253 
1254  // Determine which rows are on the current processor
1255  MatGetOwnershipRange(matIn, &Istart, &Iend);
1256 
1257  // loop over the matrix and find the largest number of cols
1258  for (label i = Istart; i < Iend; i++)
1259  {
1260  MatGetRow(matIn, i, &nCols, &cols, &vals);
1261  if (nCols < 0)
1262  {
1263  std::cout << "Warning! procI: " << Pstream::myProcNo() << " nCols <0 at rowI: " << i << std::endl;
1264  std::cout << "Set nCols to zero " << std::endl;
1265  nCols = 0;
1266  }
1267  if (nCols > maxCols) // perhaps actually check vals?
1268  {
1269  maxCols = nCols;
1270  }
1271  allNonZeros += nCols;
1272  MatRestoreRow(matIn, i, &nCols, &cols, &vals);
1273  }
1274 
1275  //reduce the maxcols value so that all procs have the same size
1276  reduce(maxCols, maxOp<label>());
1277 
1278  reduce(allNonZeros, sumOp<scalar>());
1279 
1280  return;
1281 }
1282 
1284 {
1285 
1286  scalar xx, yy, zz; // face owner coordinates
1287 
1288  //output the matrix to a file
1289  label myProc = Pstream::myProcNo();
1290  label nProcs = Pstream::nProcs();
1291  std::ostringstream fileNameStream("");
1292  fileNameStream << "AdjointIndexing"
1293  << "_" << myProc << "_of_" << nProcs << ".txt";
1294  word fileName = fileNameStream.str();
1295  OFstream aOut(fileName);
1296  aOut.precision(9);
1297 
1298  forAll(stateInfo_["volVectorStates"], idx)
1299  {
1300  const word& stateName = stateInfo_["volVectorStates"][idx];
1301  forAll(mesh_.cells(), cellI)
1302  {
1303  xx = mesh_.C()[cellI].x();
1304  yy = mesh_.C()[cellI].y();
1305  zz = mesh_.C()[cellI].z();
1306  for (label i = 0; i < 3; i++)
1307  {
1308  label glbIdx = getGlobalAdjointStateIndex(stateName, cellI, i);
1309  aOut << "Cell: " << cellI << " State: " << stateName << i << " glbIdx: " << glbIdx
1310  << " x: " << xx << " y: " << yy << " z: " << zz << endl;
1311  }
1312  }
1313  }
1314 
1315  forAll(stateInfo_["volScalarStates"], idx)
1316  {
1317  const word& stateName = stateInfo_["volScalarStates"][idx];
1318  forAll(mesh_.cells(), cellI)
1319  {
1320  xx = mesh_.C()[cellI].x();
1321  yy = mesh_.C()[cellI].y();
1322  zz = mesh_.C()[cellI].z();
1323  label glbIdx = getGlobalAdjointStateIndex(stateName, cellI);
1324  aOut << "Cell: " << cellI << " State: " << stateName << " glbIdx: " << glbIdx
1325  << " x: " << xx << " y: " << yy << " z: " << zz << endl;
1326  }
1327  }
1328 
1329  forAll(stateInfo_["modelStates"], idx)
1330  {
1331  const word& stateName = stateInfo_["modelStates"][idx];
1332  forAll(mesh_.cells(), cellI)
1333  {
1334  xx = mesh_.C()[cellI].x();
1335  yy = mesh_.C()[cellI].y();
1336  zz = mesh_.C()[cellI].z();
1337  label glbIdx = getGlobalAdjointStateIndex(stateName, cellI);
1338  aOut << "Cell: " << cellI << " State: " << stateName << " glbIdx: " << glbIdx
1339  << " x: " << xx << " y: " << yy << " z: " << zz << endl;
1340  }
1341  }
1342 
1343  forAll(stateInfo_["surfaceScalarStates"], idx)
1344  {
1345  const word& stateName = stateInfo_["surfaceScalarStates"][idx];
1346  label cellI = -1;
1347  forAll(mesh_.faces(), faceI)
1348  {
1349  if (faceI < nLocalInternalFaces)
1350  {
1351  xx = mesh_.Cf()[faceI].x();
1352  yy = mesh_.Cf()[faceI].y();
1353  zz = mesh_.Cf()[faceI].z();
1354  }
1355  else
1356  {
1357  label relIdx = faceI - nLocalInternalFaces;
1358  label patchIdx = bFacePatchI[relIdx];
1359  label faceIdx = bFaceFaceI[relIdx];
1360  xx = mesh_.Cf().boundaryField()[patchIdx][faceIdx].x();
1361  yy = mesh_.Cf().boundaryField()[patchIdx][faceIdx].y();
1362  zz = mesh_.Cf().boundaryField()[patchIdx][faceIdx].z();
1363 
1364  const polyPatch& pp = mesh_.boundaryMesh()[patchIdx];
1365  const UList<label>& pFaceCells = pp.faceCells();
1366  cellI = pFaceCells[faceIdx];
1367  }
1368 
1369  label glbIdx = getGlobalAdjointStateIndex(stateName, faceI);
1370  aOut << "Face: " << faceI << " State: " << stateName << " glbIdx: " << glbIdx
1371  << " x: " << xx << " y: " << yy << " z: " << zz
1372  << " OwnerCellI: " << cellI << endl;
1373  }
1374  }
1375 
1376  // write point indexing
1377  std::ostringstream fileNameStreamPoint("");
1378  fileNameStreamPoint << "PointIndexing"
1379  << "_" << myProc << "_of_" << nProcs << ".txt";
1380  word fileNamePoint = fileNameStreamPoint.str();
1381  OFstream aOutPoint(fileNamePoint);
1382  aOutPoint.precision(9);
1383 
1384  forAll(mesh_.points(), idxI)
1385  {
1386  xx = mesh_.points()[idxI].x();
1387  yy = mesh_.points()[idxI].y();
1388  zz = mesh_.points()[idxI].z();
1389  for (label i = 0; i < 3; i++)
1390  {
1391  label glbIdx = getGlobalXvIndex(idxI, i);
1392  aOutPoint << "Point: " << idxI << " Coords: " << i << " glbIdx: " << glbIdx
1393  << " x: " << xx << " y: " << yy << " z: " << zz << endl;
1394  }
1395  }
1396 
1397  return;
1398 }
1399 
1400 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1401 
1402 } // End namespace Foam
1403 
1404 // ************************************************************************* //
Foam::DAIndex::getGlobalFaceIndex
label getGlobalFaceIndex(const label faceI) const
get global face index for a local face index
Definition: DAIndex.C:886
Foam::DAIndex::faceOwner
labelList faceOwner
owner cell of a given face
Definition: DAIndex.H:195
Foam::DAIndex::globalFaceNumbering
globalIndex globalFaceNumbering
Definition: DAIndex.H:170
Foam::DAIndex::nLocalFaces
label nLocalFaces
local face size
Definition: DAIndex.H:86
forAll
forAll(pseudoP.boundaryField(), patchI)
Definition: solvePseudoPEqn.H:10
Foam::DAStateInfo::New
static autoPtr< DAStateInfo > New(const word modelType, const fvMesh &mesh, const DAOption &daOption, const DAModel &daModel)
Definition: DAStateInfo.C:43
Foam::DAIndex::getMatNonZeros
void getMatNonZeros(const Mat matIn, label &maxCols, scalar &allNonZeros) const
get number of non zeros for a matrix
Definition: DAIndex.C:1236
Foam::DAIndex::globalAdjointStateNumbering
globalIndex globalAdjointStateNumbering
Definition: DAIndex.H:167
Foam::DAIndex::getLocalCellIndex
label getLocalCellIndex(const label cellI) const
get local cell index for a local cell index
Definition: DAIndex.C:760
DAIndex.H
Foam::DAIndex::bFacePatchI
labelList bFacePatchI
Definition: DAIndex.H:110
Foam::DAOption
Definition: DAOption.H:29
Foam::DAIndex::getGlobalAdjointStateIndex
label getGlobalAdjointStateIndex(const word stateName, const label idxI, const label comp=-1) const
get global adjoint index for a given state name, cell/face indxI and its component (optional,...
Definition: DAIndex.C:661
daOption
DAOption daOption(mesh, pyOptions_)
Foam::DAIndex::globalCellVectorNumbering
globalIndex globalCellVectorNumbering
Definition: DAIndex.H:169
Foam::DAOption::getOption
classType getOption(const word key) const
get an option from subDict and key
Definition: DAOption.H:92
Foam::DAIndex::adjStateType
HashTable< word > adjStateType
hash table of adjoint state types, e.g., volVectorState for a given state name
Definition: DAIndex.H:77
Foam::DAIndex::nLocalCells
label nLocalCells
local cell size
Definition: DAIndex.H:83
Foam::DAIndex::writeAdjointIndexing
void writeAdjointIndexing()
write the adjoint indexing for debugging
Definition: DAIndex.C:1283
Foam::DAIndex::phiLocalOffset
labelList phiLocalOffset
phi local indexing offset for cell-by-cell indexing
Definition: DAIndex.H:201
Foam::DAIndex::stateInfo_
HashTable< wordList > stateInfo_
the StateInfo_ list from DAStateInfo object
Definition: DAIndex.H:53
Foam::DAIndex::calcLocalIdxLists
void calcLocalIdxLists(wordList &adjStateName4LocalAdjIdx, scalarList &cellIFaceI4LocalAdjIdx)
compute local lists such as adjStateName4LocalAdjIdx and cellIFaceI4LocalAdjIdx;
Definition: DAIndex.C:441
Foam::DAIndex::calcStateLocalIndexOffset
void calcStateLocalIndexOffset(HashTable< label > &offset)
calculate stateLocalIndexOffset
Definition: DAIndex.C:186
mesh
fvMesh & mesh
Definition: createRefsHeatTransfer.H:4
Foam::DAIndex::nVolVectorStates
label nVolVectorStates
number of state variables for volVectorField
Definition: DAIndex.H:157
solverName
word solverName
Definition: createAdjointCompressible.H:30
Foam::DAIndex::globalXvNumbering
globalIndex globalXvNumbering
Definition: DAIndex.H:173
Foam::DAIndex::globalCellNumbering
globalIndex globalCellNumbering
Definition: DAIndex.H:168
Foam::DAIndex::nVolScalarStates
label nVolScalarStates
number of state variables for volScalarField
Definition: DAIndex.H:154
Foam::DAIndex::getGlobalCellVectorIndex
label getGlobalCellVectorIndex(const label cellI, const label comp) const
get global cell index for a local cell vector index
Definition: DAIndex.C:834
Foam::DAIndex::adjStateNames
List< word > adjStateNames
list of adjoint state names for a specific solver
Definition: DAIndex.H:74
Foam::DAIndex::getGlobalXvIndex
label getGlobalXvIndex(const label idxPoint, const label idxCoord) const
get global Xv index for a given point index and coordinate component (x, y, or z)
Definition: DAIndex.C:702
dafoam_plot3dtransform.vals
vals
Definition: dafoam_plot3dtransform.py:39
Foam::DAIndex::phiAccumulatdOffset
labelList phiAccumulatdOffset
the accumulated phi indexing offset for cell-by-cell indexing
Definition: DAIndex.H:198
Foam::DAModel
Definition: DAModel.H:59
Foam::DAIndex::calcAdjStateID
void calcAdjStateID(HashTable< label > &adjStateID)
set adjoint state unique ID: adjStateID
Definition: DAIndex.C:397
Foam::DAIndex::stateLocalIndexOffset
HashTable< label > stateLocalIndexOffset
Definition: DAIndex.H:122
Foam
Definition: multiFreqScalarFvPatchField.C:144
Foam::DAIndex::getLocalFaceIndex
label getLocalFaceIndex(const label faceI) const
get local face index for a local face index
Definition: DAIndex.C:864
stateInfo_
stateInfo_
Definition: createAdjointCompressible.H:32
Foam::DAIndex::adjStateID
HashTable< label > adjStateID
a unique number ID for adjoint states, it depends on the sequence of adjStateNames
Definition: DAIndex.H:125
Foam::DAIndex::nLocalInternalFaces
label nLocalInternalFaces
local internal face size
Definition: DAIndex.H:98
Foam::DAIndex::getLocalXvIndex
label getLocalXvIndex(const label idxPoint, const label idxCoord) const
get local Xv index for a given point index and coordinate component (x, y, or z)
Definition: DAIndex.C:733
Foam::DAIndex::calcAdjStateID4GlobalAdjIdx
void calcAdjStateID4GlobalAdjIdx(labelList &adjStateID4GlobalAdjIdx) const
compute global list adjStateID4GlobalAdjIdx that stores the stateID for a given globalAdjIndx
Definition: DAIndex.C:912
Foam::DAIndex::getLocalCellVectorIndex
label getLocalCellVectorIndex(const label cellI, const label comp) const
get local cell index for a local cell vector index
Definition: DAIndex.C:808
Foam::DAIndex::getGlobalCellIndex
label getGlobalCellIndex(const label cellI) const
get global cell index for a local cell index
Definition: DAIndex.C:782
Foam::DAIndex::mesh_
const fvMesh & mesh_
Foam::fvMesh object.
Definition: DAIndex.H:44
daModel
DAModel daModel(mesh, daOption)
Foam::DAIndex::printMatChars
void printMatChars(const Mat matIn) const
print petsc matrix statistics such as the max on/off diagonral ratio
Definition: DAIndex.C:1010
Foam::DAIndex::getLocalAdjointStateIndex
label getLocalAdjointStateIndex(const word stateName, const label idxI, const label comp=-1) const
get local adjoint index for a given state name, cell/face indxI and its component (optional,...
Definition: DAIndex.C:516
Foam::DAIndex::nModelStates
label nModelStates
number of model states, NOTE: they are counted separately
Definition: DAIndex.H:163
Foam::DAIndex::nGlobalAdjointStates
label nGlobalAdjointStates
number of global adjoint states (including all cells and faces)
Definition: DAIndex.H:148
Foam::DAUtility::genGlobalIndex
static globalIndex genGlobalIndex(const label localIndexSize)
generate global index numbering for local-global index transferring
Definition: DAUtility.C:599
Foam::DAIndex::daOption_
const DAOption & daOption_
Foam::DAOption object.
Definition: DAIndex.H:47
Foam::DAIndex::bFaceFaceI
labelList bFaceFaceI
Definition: DAIndex.H:116
Foam::DAIndex::nLocalAdjointStates
label nLocalAdjointStates
number of local adjoint states (including all cells and faces)
Definition: DAIndex.H:145