DAPartDeriv.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2 
3  DAFoam : Discrete Adjoint with OpenFOAM
4  Version : v4
5 
6 \*---------------------------------------------------------------------------*/
7 
8 #include "DAPartDeriv.H"
9 
10 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
11 
12 namespace Foam
13 {
14 
15 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
16 
17 DAPartDeriv::DAPartDeriv(
18  const word modelType,
19  const fvMesh& mesh,
20  const DAOption& daOption,
21  const DAModel& daModel,
22  const DAIndex& daIndex,
23  const DAJacCon& daJacCon,
24  const DAResidual& daResidual)
25  : modelType_(modelType),
26  mesh_(mesh),
27  daOption_(daOption),
28  daModel_(daModel),
29  daIndex_(daIndex),
30  daJacCon_(daJacCon),
31  daResidual_(daResidual),
32  allOptions_(daOption.getAllOptions())
33 {
34  // initialize stateInfo_
35  word solverName = daOption.getOption<word>("solverName");
36  autoPtr<DAStateInfo> daStateInfo(DAStateInfo::New(solverName, mesh, daOption, daModel));
37  stateInfo_ = daStateInfo->getStateInfo();
38 }
39 
40 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
41 
43  const Vec jacConColors,
44  const Vec normStatePerturbVec,
45  const label colorI,
46  const scalar delta,
47  Vec wVec)
48 {
49  /*
50  Descripton:
51  Perturb state variable vec such that it can be used to compute
52  perturbed residual vector later
53 
54  Input:
55  jacConColors: the coloring vector for this Jacobian, obtained from Foam::DAJacCon
56 
57  normStatePerturbVec: state normalization vector, 1.0 means no normalization, the
58  actually perturbation added on the wVec is normStatePerturbVec * delta
59 
60  colorI: we perturb the rows that associated with the coloring index colorI
61 
62  delta: the delta value for perturbation the actually perturbation added on
63  the wVec is normStatePerturbVec * delta
64 
65  Input/Output:
66  wVec: the perturbed state variable vector
67 
68  Example:
69  Assuming we have five element in wVec {0.1, 0.5, 1.0, 1.5, 2.0}
70  If jacConColors reads {0, 0, 1, 0, 1},
71  normStatePerturbVec reads {1.0, 1.0, 0.5, 1.0, 0.1}
72  colorI = 1, delta = 0.01
73 
74  Then after calling this function wVec reads
75  {0.1, 0.5, 1.005, 1.5, 2.001}
76  */
77  PetscInt Istart, Iend;
78  VecGetOwnershipRange(jacConColors, &Istart, &Iend);
79 
80  const PetscScalar* colorArray;
81  VecGetArrayRead(jacConColors, &colorArray);
82 
83  const PetscScalar* normStateArray;
84  VecGetArrayRead(normStatePerturbVec, &normStateArray);
85 
86  PetscScalar* wVecArray;
87  VecGetArray(wVec, &wVecArray);
88 
89  PetscScalar deltaVal = 0.0;
90  assignValueCheckAD(deltaVal, delta);
91 
92  for (label i = Istart; i < Iend; i++)
93  {
94  label relIdx = i - Istart;
95  label colorJ = colorArray[relIdx];
96  if (colorI == colorJ)
97  {
98  wVecArray[relIdx] += deltaVal * normStateArray[relIdx];
99  }
100  }
101 
102  VecRestoreArrayRead(jacConColors, &colorArray);
103  VecRestoreArray(wVec, &wVecArray);
104  VecRestoreArrayRead(normStatePerturbVec, &normStateArray);
105 
106  return;
107 }
108 
110  const Vec resVec,
111  const Vec coloredColumn,
112  const label transposed,
113  Mat jacMat,
114  const scalar jacLowerBound) const
115 {
116  /*
117  Description:
118  Set the values from resVec to jacMat
119 
120  Input:
121  resVec: residual vector, obtained after calling the DAResidual::masterFunction
122 
123  coloredColumn: a vector to determine the element in resVec is associated with
124  which column in the jacMat. coloredColumn is computed in DAJacCon::calcColoredColumns
125  -1 in coloredColumn means don't set values to jacMat for this column
126 
127  transposed: whether the jacMat is transposed or not, for dRdWT transpoed = 1, for
128  all the other cases, set it to 0
129 
130  jacLowerBound: any |value| that is smaller than lowerBound will be set to zero in PartDerivMat
131 
132  Output:
133  jacMat: the jacobian matrix to set
134 
135  Example:
136  Condering a 5 by 5 jacMat with all zeros, and
137 
138  resVec
139  {
140  0.1,
141  0.2,
142  0.3,
143  0.4,
144  0.5
145  }
146 
147  coloredColumn
148  {
149  -1
150  1
151  3
152  -1
153  0
154  }
155 
156  transposed = 0
157 
158  Then, after calling this function, jacMat reads
159 
160  0.0 0.0 0.0 0.0 0.0
161  0.0 0.2 0.0 0.0 0.0
162  0.0 0.0 0.0 0.3 0.0
163  0.0 0.0 0.0 0.0 0.0
164  0.5 0.0 0.0 0.0 0.0
165  */
166 
167  label rowI, colI;
168  PetscScalar val;
169  PetscInt Istart, Iend;
170  const PetscScalar* resVecArray;
171  const PetscScalar* coloredColumnArray;
172 
173  VecGetArrayRead(resVec, &resVecArray);
174  VecGetArrayRead(coloredColumn, &coloredColumnArray);
175 
176  // get the local ownership range
177  VecGetOwnershipRange(resVec, &Istart, &Iend);
178 
179  // Loop over the owned values of this row and set the corresponding
180  // Jacobian entries
181  for (PetscInt i = Istart; i < Iend; i++)
182  {
183  label relIdx = i - Istart;
184  colI = coloredColumnArray[relIdx];
185  if (colI >= 0)
186  {
187  rowI = i;
188  val = resVecArray[relIdx];
189  // if val < bound, don't set the matrix. The exception is that
190  // we always set values for diagonal elements (colI==rowI)
191  // Another exception is that jacLowerBound is less than 1e-16
192  if (jacLowerBound < 1.0e-16 || fabs(val) > jacLowerBound || colI == rowI)
193  {
194  if (transposed)
195  {
196  MatSetValue(jacMat, colI, rowI, val, INSERT_VALUES);
197  }
198  else
199  {
200  MatSetValue(jacMat, rowI, colI, val, INSERT_VALUES);
201  }
202  }
203  }
204  }
205 
206  VecRestoreArrayRead(resVec, &resVecArray);
207  VecRestoreArrayRead(coloredColumn, &coloredColumnArray);
208 }
209 
210 void DAPartDeriv::setNormStatePerturbVec(Vec* normStatePerturbVec)
211 {
212  /*
213  Description:
214  Set the values for the normStatePerturbVec
215 
216  Input/Output:
217  normStatePerturbVec: the vector to store the state normalization
218  values, this will be used in DAPartDeriv::perturbStates
219 
220  The normalization referene values are set in "normalizeStates" in DAOption
221  */
222  label localSize = daIndex_.nLocalAdjointStates;
223  VecCreate(PETSC_COMM_WORLD, normStatePerturbVec);
224  VecSetSizes(*normStatePerturbVec, localSize, PETSC_DETERMINE);
225  VecSetFromOptions(*normStatePerturbVec);
226  VecSet(*normStatePerturbVec, 1.0);
227 
228  dictionary normStateDict = allOptions_.subDict("normalizeStates");
229 
230  wordList normStateNames = normStateDict.toc();
231 
232  forAll(stateInfo_["volVectorStates"], idxI)
233  {
234  word stateName = stateInfo_["volVectorStates"][idxI];
235  if (normStateNames.found(stateName))
236  {
237  scalar scale = normStateDict.getScalar(stateName);
238  PetscScalar scaleValue = 0.0;
239  assignValueCheckAD(scaleValue, scale);
240  forAll(mesh_.cells(), idxI)
241  {
242  for (label comp = 0; comp < 3; comp++)
243  {
244  label glbIdx = daIndex_.getGlobalAdjointStateIndex(stateName, idxI, comp);
245  VecSetValue(*normStatePerturbVec, glbIdx, scaleValue, INSERT_VALUES);
246  }
247  }
248  }
249  }
250 
251  forAll(stateInfo_["volScalarStates"], idxI)
252  {
253  const word stateName = stateInfo_["volScalarStates"][idxI];
254  if (normStateNames.found(stateName))
255  {
256  scalar scale = normStateDict.getScalar(stateName);
257  PetscScalar scaleValue = 0.0;
258  assignValueCheckAD(scaleValue, scale);
259  forAll(mesh_.cells(), idxI)
260  {
261  label glbIdx = daIndex_.getGlobalAdjointStateIndex(stateName, idxI);
262  VecSetValue(*normStatePerturbVec, glbIdx, scaleValue, INSERT_VALUES);
263  }
264  }
265  }
266 
267  forAll(stateInfo_["modelStates"], idxI)
268  {
269  const word stateName = stateInfo_["modelStates"][idxI];
270  if (normStateNames.found(stateName))
271  {
272  scalar scale = normStateDict.getScalar(stateName);
273  PetscScalar scaleValue = 0.0;
274  assignValueCheckAD(scaleValue, scale);
275  forAll(mesh_.cells(), idxI)
276  {
277  label glbIdx = daIndex_.getGlobalAdjointStateIndex(stateName, idxI);
278  VecSetValue(*normStatePerturbVec, glbIdx, scaleValue, INSERT_VALUES);
279  }
280  }
281  }
282 
283  forAll(stateInfo_["surfaceScalarStates"], idxI)
284  {
285  const word stateName = stateInfo_["surfaceScalarStates"][idxI];
286  if (normStateNames.found(stateName))
287  {
288  scalar scale = normStateDict.getScalar(stateName);
289  PetscScalar scaleValue = 0.0;
290 
291  forAll(mesh_.faces(), faceI)
292  {
293  if (faceI < daIndex_.nLocalInternalFaces)
294  {
295  scale = mesh_.magSf()[faceI];
296  assignValueCheckAD(scaleValue, scale);
297  }
298  else
299  {
300  label relIdx = faceI - daIndex_.nLocalInternalFaces;
301  label patchIdx = daIndex_.bFacePatchI[relIdx];
302  label faceIdx = daIndex_.bFaceFaceI[relIdx];
303  scale = mesh_.magSf().boundaryField()[patchIdx][faceIdx];
304  assignValueCheckAD(scaleValue, scale);
305  }
306 
307  label glbIdx = daIndex_.getGlobalAdjointStateIndex(stateName, faceI);
308  VecSetValue(*normStatePerturbVec, glbIdx, scaleValue, INSERT_VALUES);
309  }
310  }
311  }
312 
313  VecAssemblyBegin(*normStatePerturbVec);
314  VecAssemblyEnd(*normStatePerturbVec);
315 }
316 
318  const dictionary& options,
319  Mat jacMat)
320 {
321  /*
322  Description:
323  Initialize jacMat
324 
325  Input:
326  options.transposed. Whether to compute the transposed of dRdW
327  */
328 
329  label transposed = options.getLabel("transposed");
330 
331  // now initialize the memory for the jacobian itself
332  label localSize = daIndex_.nLocalAdjointStates;
333 
334  // create dRdWT
335  //MatCreate(PETSC_COMM_WORLD, jacMat);
336  MatSetSizes(
337  jacMat,
338  localSize,
339  localSize,
340  PETSC_DETERMINE,
341  PETSC_DETERMINE);
342  MatSetFromOptions(jacMat);
343  daJacCon_.preallocatedRdW(jacMat, transposed);
344  //MatSetOption(jacMat, MAT_NEW_NONZERO_ALLOCATION_ERR, PETSC_FALSE);
345  MatSetUp(jacMat);
346  MatZeroEntries(jacMat);
347  Info << "Partial derivative matrix created. " << mesh_.time().elapsedCpuTime() << " s" << endl;
348 }
349 
351  const dictionary& options,
352  const Vec xvVec,
353  const Vec wVec,
354  Mat jacMat)
355 {
356  /*
357  Description:
358  Compute jacMat. We use coloring accelerated finite-difference
359 
360  Input:
361 
362  options.transposed. Whether to compute the transposed of dRdW
363 
364  options.isPC: whether to compute the jacMat for preconditioner
365 
366  options.lowerBound: any |value| that is smaller than lowerBound will be set to zero in dRdW
367 
368  xvVec: the volume mesh coordinate vector
369 
370  wVec: the state variable vector
371 
372  Output:
373  jacMat: the partial derivative matrix dRdW to compute
374  */
375 
376  label transposed = options.getLabel("transposed");
377 
378  // initialize coloredColumn vector
379  Vec coloredColumn;
380  VecDuplicate(wVec, &coloredColumn);
381  VecZeroEntries(coloredColumn);
382 
383  DAResidual& daResidual = const_cast<DAResidual&>(daResidual_);
384 
385  // zero all the matrices
386  MatZeroEntries(jacMat);
387 
388  Vec wVecNew;
389  VecDuplicate(wVec, &wVecNew);
390  VecCopy(wVec, wVecNew);
391 
392  // initialize residual vectors
393  Vec resVecRef, resVec;
394  VecDuplicate(wVec, &resVec);
395  VecDuplicate(wVec, &resVecRef);
396  VecZeroEntries(resVec);
397  VecZeroEntries(resVecRef);
398 
399  // set up state normalization vector
400  Vec normStatePerturbVec;
401  this->setNormStatePerturbVec(&normStatePerturbVec);
402 
403  dictionary mOptions;
404  mOptions.set("updateState", 1);
405  mOptions.set("updateMesh", 0);
406  mOptions.set("setResVec", 1);
407  mOptions.set("isPC", options.getLabel("isPC"));
408  daResidual.masterFunction(mOptions, xvVec, wVec, resVecRef);
409 
410  scalar jacLowerBound = options.getScalar("lowerBound");
411 
412  scalar delta = daOption_.getSubDictOption<scalar>("adjPartDerivFDStep", "State");
413  scalar rDelta = 1.0 / delta;
414  PetscScalar rDeltaValue = 0.0;
415  assignValueCheckAD(rDeltaValue, rDelta);
416 
417  label nColors = daJacCon_.getNJacConColors();
418 
419  word partDerivName = modelType_;
420  if (transposed)
421  {
422  partDerivName += "T";
423  }
424  if (options.getLabel("isPC"))
425  {
426  partDerivName += "PC";
427  }
428 
429  label printInterval = daOption_.getOption<label>("printInterval");
430  for (label color = 0; color < nColors; color++)
431  {
432  scalar eTime = mesh_.time().elapsedCpuTime();
433  // print progress
434  if (color % printInterval == 0 or color == nColors - 1)
435  {
436  Info << partDerivName << ": " << color << " of " << nColors
437  << ", ExecutionTime: " << eTime << " s" << endl;
438  }
439 
440  // perturb states
441  this->perturbStates(
443  normStatePerturbVec,
444  color,
445  delta,
446  wVecNew);
447 
448  // compute residual
449  daResidual.masterFunction(mOptions, xvVec, wVecNew, resVec);
450 
451  // reset state perburbation
452  VecCopy(wVec, wVecNew);
453 
454  // compute residual partial using finite-difference
455  VecAXPY(resVec, -1.0, resVecRef);
456  VecScale(resVec, rDeltaValue);
457 
458  // compute the colored coloumn and assign resVec to jacMat
459  daJacCon_.calcColoredColumns(color, coloredColumn);
460  this->setPartDerivMat(resVec, coloredColumn, transposed, jacMat, jacLowerBound);
461  }
462 
463  // call masterFunction again to reset the wVec to OpenFOAM field
464  daResidual.masterFunction(mOptions, xvVec, wVec, resVecRef);
465 
466  MatAssemblyBegin(jacMat, MAT_FINAL_ASSEMBLY);
467  MatAssemblyEnd(jacMat, MAT_FINAL_ASSEMBLY);
468 
469  if (daOption_.getOption<label>("debug"))
470  {
471  daIndex_.printMatChars(jacMat);
472  }
473 }
474 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
475 
476 } // End namespace Foam
477 
478 // ************************************************************************* //
Foam::DAJacCon
Definition: DAJacCon.H:35
Foam::DAStateInfo::New
static autoPtr< DAStateInfo > New(const word modelType, const fvMesh &mesh, const DAOption &daOption, const DAModel &daModel)
Definition: DAStateInfo.C:43
Foam::DAJacCon::calcColoredColumns
void calcColoredColumns(const label colorI, Vec coloredColumn) const
calculate the colored column vector
Definition: DAJacCon.C:2691
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
Foam::DAPartDeriv::daIndex_
const DAIndex & daIndex_
DAIndex object.
Definition: DAPartDeriv.H:59
Foam::DAPartDeriv::setPartDerivMat
void setPartDerivMat(const Vec resVec, const Vec coloredColumn, const label transposed, Mat jacMat, const scalar jacLowerBound=1e-30) const
set values for the partial derivative matrix
Definition: DAPartDeriv.C:109
Foam::DAPartDeriv::daJacCon_
const DAJacCon & daJacCon_
DAJacCon object.
Definition: DAPartDeriv.H:62
Foam::DAJacCon::getJacConColor
Vec getJacConColor() const
return DAJacCon::jacConColors_
Definition: DAJacCon.H:272
Foam::DAPartDeriv::initializePartDerivMat
void initializePartDerivMat(const dictionary &options, Mat jacMat)
initialize partial derivative matrix
Definition: DAPartDeriv.C:317
Foam::DAOption::getOption
classType getOption(const word key) const
get an option from subDict and key
Definition: DAOption.H:92
Foam::DAPartDeriv::daOption_
const DAOption & daOption_
DAOption object.
Definition: DAPartDeriv.H:53
Foam::DAJacCon::getNJacConColors
label getNJacConColors() const
get the number of JacCon colors
Definition: DAJacCon.H:252
Foam::DAPartDeriv::mesh_
const fvMesh & mesh_
fvMesh
Definition: DAPartDeriv.H:50
solverName
word solverName
Definition: createAdjoint.H:14
mesh
fvMesh & mesh
Definition: createRefsHeatTransfer.H:4
Foam::DAOption::getSubDictOption
classType getSubDictOption(const word subDict, const word subDictKey) const
get an dictionary option from subDict and key
Definition: DAOption.H:165
Foam::DAPartDeriv::stateInfo_
HashTable< wordList > stateInfo_
the stateInfo_ list from DAStateInfo object
Definition: DAPartDeriv.H:71
Foam::DAIndex
Definition: DAIndex.H:32
assignValueCheckAD
#define assignValueCheckAD(valA, valB)
Definition: DAMacroFunctions.H:103
Foam::DAJacCon::preallocatedRdW
void preallocatedRdW(Mat dRMat, const label transposed) const
preallocate dRdW matrix using the preallocVec
Definition: DAJacCon.C:228
Foam::DAModel
Definition: DAModel.H:57
Foam
Definition: checkGeometry.C:32
forAll
forAll(nuTilda1, cellI)
Definition: nuTilda1EqnIrkPimple.H:19
Foam::DAIndex::nLocalInternalFaces
label nLocalInternalFaces
local internal face size
Definition: DAIndex.H:98
Foam::DAResidual
Definition: DAResidual.H:36
Foam::DAPartDeriv::calcPartDerivMat
void calcPartDerivMat(const dictionary &options, const Vec xvVec, const Vec wVec, Mat jacMat)
compute the partial derivative matrix
Definition: DAPartDeriv.C:350
DAPartDeriv.H
Foam::DAResidual::masterFunction
void masterFunction(const dictionary &options, const Vec xvVec, const Vec wVec, Vec resVec)
the master function that compute the residual vector given the state and point vectors
Definition: DAResidual.C:90
Foam::DAPartDeriv::modelType_
const word modelType_
the name of the jacCon matrix
Definition: DAPartDeriv.H:47
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::DAPartDeriv::daResidual_
const DAResidual & daResidual_
DAResidual object.
Definition: DAPartDeriv.H:65
Foam::DAPartDeriv::perturbStates
void perturbStates(const Vec jacConColors, const Vec normStatePerturbVec, const label colorI, const scalar delta, Vec wVec)
perturb state variables given a color index
Definition: DAPartDeriv.C:42
Foam::DAPartDeriv::setNormStatePerturbVec
void setNormStatePerturbVec(Vec *normStatePerturbVec)
setup the state normalization vector
Definition: DAPartDeriv.C:210
Foam::DAPartDeriv::allOptions_
const dictionary & allOptions_
all the DAFoam option
Definition: DAPartDeriv.H:68
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