DAFvSourceActuatorDisk.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2 
3  DAFoam : Discrete Adjoint with OpenFOAM
4  Version : v3
5 
6 \*---------------------------------------------------------------------------*/
7 
9 
10 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
11 
12 namespace Foam
13 {
14 
15 defineTypeNameAndDebug(DAFvSourceActuatorDisk, 0);
16 addToRunTimeSelectionTable(DAFvSource, DAFvSourceActuatorDisk, dictionary);
17 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
18 
20  const word modelType,
21  const fvMesh& mesh,
22  const DAOption& daOption,
23  const DAModel& daModel,
24  const DAIndex& daIndex)
25  : DAFvSource(modelType, mesh, daOption, daModel, daIndex)
26 {
28 
29  printInterval_ = daOption.getOption<label>("printInterval");
30 
31  // now we need to initialize actuatorDiskDVs_ by synchronizing the values
32  // defined in fvSource from DAOption to actuatorDiskDVs_
33  // NOTE: we need to call this function whenever we change the actuator
34  // design variables during optimization
36 }
37 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
38 
40 {
41  /*
42  Description:
43  Compute the actuator disk source term.
44  We follow: Hoekstra, A RANS-based analysis tool for ducted propeller systems
45  in open water condition, International Shipbuilding Progress
46  source = rStar * sqrt(1.0 - rStar) * scale
47  where rStar is the normalized radial location and scale is used to
48  make sure the integral force equals the desired total thrust
49 
50  NOTE: rotDir = right means propeller rotates clockwise viewed from
51  the tail of the aircraft looking forward
52 
53  There are two options to assign the source term:
54  1. cylinderAnnulusToCell. Users prescribe a cylinderAnnulus and the fvSource will be
55  added to all the cells inside this cylinderAnnulus
56  2. cylinderAnnulusSmooth. Users prescribe the cylinderAnnulus and the Gaussian function
57  will be used to smoothly assign fvSource term. This allows us to use the actuatorDisk
58  parameters as design variables and move the actuator during optimization
59 
60  Example:
61  An example of the fvSource in pyOptions in pyDAFoam can be
62  defOptions =
63  {
64  "fvSource"
65  {
66  "disk1"
67  {
68  "type": "actuatorDisk",
69  "source": "cylinderAnnulusToCell",
70  "p1": [0.5, 0.3, 0.1], # p1 and p2 define the axis and width
71  "p2": [0.5, 0.3, 0.5], # p2-p1 should be streamwise
72  "innerRadius": 0.1,
73  "outerRadius": 0.8,
74  "rotDir": "left",
75  "scale": 1.0,
76  "POD": 0.7
77  },
78  "disk2"
79  {
80  "type": "actuatorDisk",
81  "source": "cylinderAnnulusSmooth",
82  "center": [0.0, 0.0, 0.0],
83  "direction": [1.0, 0.0, 0.0],
84  "innerRadius": 0.1,
85  "outerRadius": 0.8,
86  "rotDir": "right",
87  "scale": 0.1,
88  "POD": 1.0,
89  "eps": 0.05 # eps should be of cell size
90  "expM": 1.0,
91  "expN": 0.5,
92  }
93  }
94  }
95  */
96 
97  forAll(fvSource, idxI)
98  {
99  fvSource[idxI] = vector::zero;
100  }
101 
102  const dictionary& allOptions = daOption_.getAllOptions();
103 
104  dictionary fvSourceSubDict = allOptions.subDict("fvSource");
105 
106  word diskName0 = fvSourceSubDict.toc()[0];
107  word source0 = fvSourceSubDict.subDict(diskName0).getWord("source");
108 
109  if (source0 == "cylinderAnnulusToCell")
110  {
111 
112  // loop over all the cell indices for all actuator disks
113  forAll(fvSourceCellIndices_.toc(), idxI)
114  {
115 
116  // name of this disk
117  word diskName = fvSourceCellIndices_.toc()[idxI];
118 
119  // sub dictionary with all parameters for this disk
120  dictionary diskSubDict = fvSourceSubDict.subDict(diskName);
121 
122  // now read in all parameters for this actuator disk
123  scalarList point1;
124  scalarList point2;
125  diskSubDict.readEntry<scalarList>("p1", point1);
126  diskSubDict.readEntry<scalarList>("p2", point2);
127  vector p1 = {point1[0], point1[1], point1[2]};
128  vector p2 = {point2[0], point2[1], point2[2]};
129  vector diskCenter = (p1 + p2) / 2.0;
130  vector diskDir = p2 - p1; // NOTE: p2 - p1 should be streamwise
131  vector diskDirNorm = diskDir / mag(diskDir);
132  scalar outerRadius = diskSubDict.getScalar("outerRadius");
133  scalar innerRadius = diskSubDict.getScalar("innerRadius");
134  word rotDir = diskSubDict.getWord("rotDir");
135  scalar scale = diskSubDict.getScalar("scale");
136  scalar POD = diskSubDict.getScalar("POD");
137 
138  // loop over all cell indices for this disk and computer the source term
139  scalar thrustSourceSum = 0.0;
140  scalar torqueSourceSum = 0.0;
141  forAll(fvSourceCellIndices_[diskName], idxJ)
142  {
143  // cell index
144  label cellI = fvSourceCellIndices_[diskName][idxJ];
145 
146  // the cell center coordinates of this cellI
147  vector cellC = mesh_.C()[cellI];
148  // cell center to disk center vector
149  vector cellC2AVec = cellC - diskCenter;
150  // tmp tensor for calculating the axial/radial components of cellC2AVec
151  tensor cellC2AVecE(tensor::zero);
152  cellC2AVecE.xx() = cellC2AVec.x();
153  cellC2AVecE.yy() = cellC2AVec.y();
154  cellC2AVecE.zz() = cellC2AVec.z();
155 
156  // now we need to decompose cellC2AVec into axial and radial components
157  // the axial component of cellC2AVec vector
158  vector cellC2AVecA = cellC2AVecE & diskDirNorm;
159  // the radial component of cellC2AVec vector
160  vector cellC2AVecR = cellC2AVec - cellC2AVecA;
161 
162  // now we can use the cross product to compute the tangential
163  // (circ) direction of cellI
164  vector cellC2AVecC(vector::zero);
165  if (rotDir == "left")
166  {
167  // propeller rotates counter-clockwise viewed from the tail of the aircraft looking forward
168  cellC2AVecC = cellC2AVecR ^ diskDirNorm; // circ
169  }
170  else if (rotDir == "right")
171  {
172  // propeller rotates clockwise viewed from the tail of the aircraft looking forward
173  cellC2AVecC = diskDirNorm ^ cellC2AVecR; // circ
174  }
175  else
176  {
177  FatalErrorIn(" ") << "rotDir not valid" << abort(FatalError);
178  }
179 
180  // the magnitude of radial component of cellC2AVecR
181  scalar cellC2AVecRLen = mag(cellC2AVecR);
182  // the magnitude of tangential component of cellC2AVecR
183  scalar cellC2AVecCLen = mag(cellC2AVecC);
184  // the normalized cellC2AVecC (tangential) vector
185  vector cellC2AVecCNorm = cellC2AVecC / cellC2AVecCLen;
186 
187  // now we can use Hoekstra's formulation to compute source
188  scalar rPrime = cellC2AVecRLen / outerRadius;
189  scalar rPrimeHub = innerRadius / outerRadius;
190  // rStar is normalized radial location
191  scalar rStar = (rPrime - rPrimeHub) / (1.0 - rPrimeHub);
192  // axial force, NOTE: user need to prescribe "scale" such that the integrated
193  // axial force matches the desired thrust
194  scalar fAxial = rStar * sqrt(1.0 - rStar) * scale;
195  // we use Hoekstra's method to calculate the fCirc based on fAxial
196  scalar fCirc = fAxial * POD / constant::mathematical::pi / rPrime;
197  vector sourceVec = (fAxial * diskDirNorm + fCirc * cellC2AVecCNorm);
198  // the source is the force normalized by the cell volume
199  fvSource[cellI] += sourceVec;
200  thrustSourceSum += fAxial * mesh_.V()[cellI];
201  torqueSourceSum += fCirc * mesh_.V()[cellI];
202  }
203 
204  reduce(thrustSourceSum, sumOp<scalar>());
205  reduce(torqueSourceSum, sumOp<scalar>());
206 
207  if (daOption_.getOption<word>("runStatus") == "solvePrimal")
208  {
209  if (mesh_.time().timeIndex() % printInterval_ == 0 || mesh_.time().timeIndex() == 1)
210  {
211  Info << "ThrustCoeff Source Term for " << diskName << ": " << thrustSourceSum << endl;
212  Info << "TorqueCoeff Source Term for " << diskName << ": " << torqueSourceSum << endl;
213  }
214  }
215  }
216  }
217  else if (source0 == "cylinderAnnulusSmooth")
218  {
219 
220  forAll(fvSourceSubDict.toc(), idxI)
221  {
222  word diskName = fvSourceSubDict.toc()[idxI];
223  dictionary diskSubDict = fvSourceSubDict.subDict(diskName);
224 
225  scalarList direction;
226  diskSubDict.readEntry<scalarList>("direction", direction);
227  vector dirNorm = {direction[0], direction[1], direction[2]};
228  dirNorm = dirNorm / mag(dirNorm);
229  vector center = {
230  actuatorDiskDVs_[diskName][0], actuatorDiskDVs_[diskName][1], actuatorDiskDVs_[diskName][2]};
231  scalar innerRadius = actuatorDiskDVs_[diskName][3];
232  scalar outerRadius = actuatorDiskDVs_[diskName][4];
233  word rotDir = diskSubDict.getWord("rotDir");
234  // we will calculate or read scale later
235  scalar scale;
236  scalar POD = actuatorDiskDVs_[diskName][6];
237  scalar eps = diskSubDict.getScalar("eps");
238  scalar expM = actuatorDiskDVs_[diskName][7];
239  scalar expN = actuatorDiskDVs_[diskName][8];
240  // Now we need to compute normalized eps in the radial direction, i.e. epsRStar this is because
241  // we need to smooth the radial distribution of the thrust, here the radial location is
242  // normalized as rStar = (r - rInner) / (rOuter - rInner), so to make epsRStar consistent with this
243  // we need to normalize eps with the demoninator of rStar, i.e. Outer - rInner
244  scalar epsRStar = eps / (outerRadius - innerRadius);
245  scalar rStarMin = epsRStar;
246  scalar rStarMax = 1.0 - epsRStar;
247  scalar fRMin = pow(rStarMin, expM) * pow(1.0 - rStarMin, expN);
248  scalar fRMax = pow(rStarMax, expM) * pow(1.0 - rStarMax, expN);
249 
250  label adjustThrust = diskSubDict.getLabel("adjustThrust");
251  // if adjustThrust = False, we just read "scale" from daOption
252  // if we want to adjust thrust, we calculate scale, instead of reading from daOption
253  // to calculate the scale, we just compute the fAxial with scale = 1, then we find
254  // the correct scale = targetThrust / thrust_with_scale_1
255  if (adjustThrust)
256  {
257  scale = 1.0;
258  scalar tmpThrustSumAll = 0.0;
259  forAll(mesh_.cells(), cellI)
260  {
261  // the cell center coordinates of this cellI
262  vector cellC = mesh_.C()[cellI];
263  // cell center to disk center vector
264  vector cellC2AVec = cellC - center;
265  // tmp tensor for calculating the axial/radial components of cellC2AVec
266  tensor cellC2AVecE(tensor::zero);
267  cellC2AVecE.xx() = cellC2AVec.x();
268  cellC2AVecE.yy() = cellC2AVec.y();
269  cellC2AVecE.zz() = cellC2AVec.z();
270 
271  // now we need to decompose cellC2AVec into axial and radial components
272  // the axial component of cellC2AVec vector
273  vector cellC2AVecA = cellC2AVecE & dirNorm;
274  // the radial component of cellC2AVec vector
275  vector cellC2AVecR = cellC2AVec - cellC2AVecA;
276 
277  // the magnitude of radial component of cellC2AVecR
278  scalar cellC2AVecRLen = mag(cellC2AVecR);
279  // the magnitude of axial component of cellC2AVecR
280  scalar cellC2AVecALen = mag(cellC2AVecA);
281 
282  // now we can use the smoothed formulation to compute source
283  scalar rPrime = cellC2AVecRLen / outerRadius;
284  scalar rPrimeHub = innerRadius / outerRadius;
285  // rStar is normalized radial location
286  scalar rStar = (rPrime - rPrimeHub) / (1.0 - rPrimeHub);
287 
288  scalar fAxial = 0.0;
289 
290  scalar dA2 = cellC2AVecALen * cellC2AVecALen;
291 
292  if (rStar < rStarMin)
293  {
294  scalar dR2 = (rStar - rStarMin) * (rStar - rStarMin);
295  scalar fR = fRMin * exp(-dR2 / epsRStar / epsRStar) * scale;
296  fAxial = fR * exp(-dA2 / eps / eps);
297  }
298  else if (rStar >= rStarMin && rStar <= rStarMax)
299  {
300  scalar fR = pow(rStar, expM) * pow(1.0 - rStar, expN) * scale;
301  fAxial = fR * exp(-dA2 / eps / eps);
302  }
303  else
304  {
305  scalar dR2 = (rStar - rStarMax) * (rStar - rStarMax);
306  scalar fR = fRMax * exp(-dR2 / epsRStar / epsRStar) * scale;
307  fAxial = fR * exp(-dA2 / eps / eps);
308  }
309 
310  tmpThrustSumAll += fAxial * mesh_.V()[cellI];
311  }
312  reduce(tmpThrustSumAll, sumOp<scalar>());
313  scalar targetThrust = actuatorDiskDVs_[diskName][9];
314  scale = targetThrust / tmpThrustSumAll;
315  }
316  else
317  {
318  scale = actuatorDiskDVs_[diskName][5];
319  }
320 
321  // now we have the correct scale, repeat the loop to assign fvSource
322  scalar thrustSourceSum = 0.0;
323  scalar torqueSourceSum = 0.0;
324  forAll(mesh_.cells(), cellI)
325  {
326  // the cell center coordinates of this cellI
327  vector cellC = mesh_.C()[cellI];
328  // cell center to disk center vector
329  vector cellC2AVec = cellC - center;
330  // tmp tensor for calculating the axial/radial components of cellC2AVec
331  tensor cellC2AVecE(tensor::zero);
332  cellC2AVecE.xx() = cellC2AVec.x();
333  cellC2AVecE.yy() = cellC2AVec.y();
334  cellC2AVecE.zz() = cellC2AVec.z();
335 
336  // now we need to decompose cellC2AVec into axial and radial components
337  // the axial component of cellC2AVec vector
338  vector cellC2AVecA = cellC2AVecE & dirNorm;
339  // the radial component of cellC2AVec vector
340  vector cellC2AVecR = cellC2AVec - cellC2AVecA;
341 
342  // now we can use the cross product to compute the tangential
343  // (circ) direction of cellI
344  vector cellC2AVecC(vector::zero);
345  if (rotDir == "left")
346  {
347  // propeller rotates counter-clockwise viewed from the tail of the aircraft looking forward
348  cellC2AVecC = cellC2AVecR ^ dirNorm; // circ
349  }
350  else if (rotDir == "right")
351  {
352  // propeller rotates clockwise viewed from the tail of the aircraft looking forward
353  cellC2AVecC = dirNorm ^ cellC2AVecR; // circ
354  }
355  else
356  {
357  FatalErrorIn(" ") << "rotDir not valid" << abort(FatalError);
358  }
359 
360  // the magnitude of radial component of cellC2AVecR
361  scalar cellC2AVecRLen = mag(cellC2AVecR);
362  // the magnitude of tangential component of cellC2AVecR
363  scalar cellC2AVecCLen = mag(cellC2AVecC);
364  // the magnitude of axial component of cellC2AVecR
365  scalar cellC2AVecALen = mag(cellC2AVecA);
366  // the normalized cellC2AVecC (tangential) vector
367  vector cellC2AVecCNorm = cellC2AVecC / cellC2AVecCLen;
368 
369  // now we can use the smoothed formulation to compute source
370  scalar rPrime = cellC2AVecRLen / outerRadius;
371  scalar rPrimeHub = innerRadius / outerRadius;
372  // rStar is normalized radial location
373  scalar rStar = (rPrime - rPrimeHub) / (1.0 - rPrimeHub);
374 
375  scalar fAxial = 0.0;
376  scalar dA2 = cellC2AVecALen * cellC2AVecALen;
377 
378  if (rStar < rStarMin)
379  {
380  scalar dR2 = (rStar - rStarMin) * (rStar - rStarMin);
381  scalar fR = fRMin * exp(-dR2 / epsRStar / epsRStar) * scale;
382  fAxial = fR * exp(-dA2 / eps / eps);
383  }
384  else if (rStar >= rStarMin && rStar <= rStarMax)
385  {
386  scalar fR = pow(rStar, expM) * pow(1.0 - rStar, expN) * scale;
387  fAxial = fR * exp(-dA2 / eps / eps);
388  }
389  else
390  {
391  scalar dR2 = (rStar - rStarMax) * (rStar - rStarMax);
392  scalar fR = fRMax * exp(-dR2 / epsRStar / epsRStar) * scale;
393  fAxial = fR * exp(-dA2 / eps / eps);
394  }
395  // we use Hoekstra's method to calculate the fCirc based on fAxial
396  // here we add 0.01*eps/outerRadius to avoid diving a zero rPrime
397  // this might happen if a cell center is very close to actuator center
398  scalar fCirc = fAxial * POD / constant::mathematical::pi / (rPrime + 0.01 * eps / outerRadius);
399 
400  vector sourceVec = (fAxial * dirNorm + fCirc * cellC2AVecCNorm);
401  // the source is the force normalized by the cell volume
402  fvSource[cellI] += sourceVec;
403  thrustSourceSum += fAxial * mesh_.V()[cellI];
404  torqueSourceSum += fCirc * mesh_.V()[cellI];
405  }
406 
407  reduce(thrustSourceSum, sumOp<scalar>());
408  reduce(torqueSourceSum, sumOp<scalar>());
409 
410  if (daOption_.getOption<word>("runStatus") == "solvePrimal")
411  {
412  if (mesh_.time().timeIndex() % printInterval_ == 0 || mesh_.time().timeIndex() == 1)
413  {
414  Info << "ThrustCoeff Source Term for " << diskName << ": " << thrustSourceSum << endl;
415  Info << "TorqueCoeff Source Term for " << diskName << ": " << torqueSourceSum << endl;
416  if (adjustThrust)
417  {
418  Info << "Dynamically adjusted scale for " << diskName << ": " << scale << endl;
419  }
420  if (daOption_.getOption<label>("debug"))
421  {
422  Info << "adjustThrust for " << diskName << ": " << adjustThrust << endl;
423  Info << "center for " << diskName << ": " << center << endl;
424  Info << "innerRadius for " << diskName << ": " << innerRadius << endl;
425  Info << "outerRadius for " << diskName << ": " << outerRadius << endl;
426  Info << "scale for " << diskName << ": " << scale << endl;
427  Info << "POD for " << diskName << ": " << POD << endl;
428  Info << "eps for " << diskName << ": " << eps << endl;
429  Info << "expM for " << diskName << ": " << expM << endl;
430  Info << "expN for " << diskName << ": " << expN << endl;
431  Info << "epsRStar for " << diskName << ": " << epsRStar << endl;
432  Info << "rStarMin for " << diskName << ": " << rStarMin << endl;
433  Info << "rStarMax for " << diskName << ": " << rStarMax << endl;
434  }
435  }
436  }
437  }
438  }
439  else
440  {
441  FatalErrorIn("calcFvSourceCells") << "source: " << source0 << " not supported!"
442  << "Options are: cylinderAnnulusToCell and cylinderAnnulusSmooth!"
443  << abort(FatalError);
444  }
445 
446  fvSource.correctBoundaryConditions();
447 }
448 
449 void DAFvSourceActuatorDisk::calcFvSourceCellIndices(HashTable<labelList>& fvSourceCellIndices)
450 {
451  /*
452  Description:
453  Calculate the lists of cell indices that are within the actuator disk space
454  NOTE: we support multiple actuator disks.
455 
456  Output:
457  fvSourceCellIndices: Hash table that contains the lists of cell indices that
458  are within the actuator disk space. The hash key is the name of the disk. We support
459  multiple disks. An example of fvSourceCellIndices can be:
460 
461  fvSourceCellIndices=
462  {
463  "disk1": {1,2,3,4,5},
464  "disk2": {6,7,8,9,10,11,12}
465  }
466 
467  Example:
468  An example of the fvSource in pyOptions in pyDAFoam can be
469  defOptions =
470  {
471  "fvSource"
472  {
473  "disk1"
474  {
475  "type": "actuatorDisk",
476  "source": cylinderAnnulusToCell,
477  "p1": [0.5, 0.3, 0.1], # p1 and p2 define the axis and width
478  "p2": [0.5, 0.3, 0.5],
479  "innerRadius": 0.1,
480  "outerRadius": 0.8,
481  "rotDir": "left",
482  "scale": 1.0,
483  "POD": 0.7
484  },
485  "disk2"
486  {
487  "type": "actuatorDisk",
488  "source": cylinderAnnulusToCell,
489  "p1": [0.0, 0.0, 0.1],
490  "p2": [0.0, 0.0, 0.5],
491  "innerRadius": 0.1,
492  "outerRadius": 0.8,
493  "rotDir": "right",
494  "scale": 0.1,
495  "POD": 1.0
496  }
497  }
498  }
499  */
500 
501  const dictionary& allOptions = daOption_.getAllOptions();
502 
503  dictionary fvSourceSubDict = allOptions.subDict("fvSource");
504 
505  if (fvSourceSubDict.toc().size() == 0)
506  {
507  FatalErrorIn("calcSourceCells") << "actuatorDisk is selected as fvSource "
508  << " but the options are empty!"
509  << abort(FatalError);
510  }
511 
512  forAll(fvSourceSubDict.toc(), idxI)
513  {
514  word diskName = fvSourceSubDict.toc()[idxI];
515 
516  fvSourceCellIndices.set(diskName, {});
517 
518  dictionary diskSubDict = fvSourceSubDict.subDict(diskName);
519  word sourceType = diskSubDict.getWord("source");
520  // all avaiable source type are in src/meshTools/sets/cellSources
521  // Example of IO parameters os in applications/utilities/mesh/manipulation/topoSet
522  if (sourceType == "cylinderAnnulusToCell")
523  {
524  // create a topoSet
525  autoPtr<topoSet> currentSet(
526  topoSet::New(
527  "cellSet",
528  mesh_,
529  "set0",
530  IOobject::NO_READ));
531  // we need to change the min and max because they need to
532  // be of type point; however, we can't parse point type
533  // in pyDict, we need to change them here.
534 
535  scalarList point1;
536  scalarList point2;
537  diskSubDict.readEntry<scalarList>("p1", point1);
538  diskSubDict.readEntry<scalarList>("p2", point2);
539 
540  point p1;
541  point p2;
542  p1[0] = point1[0];
543  p1[1] = point1[1];
544  p1[2] = point1[2];
545  p2[0] = point2[0];
546  p2[1] = point2[1];
547  p2[2] = point2[2];
548 
549  scalar outerRadius = diskSubDict.getScalar("outerRadius");
550  scalar innerRadius = diskSubDict.getScalar("innerRadius");
551 
552  dictionary tmpDict;
553  tmpDict.set("p1", p1);
554  tmpDict.set("p2", p2);
555  tmpDict.set("innerRadius", innerRadius);
556  tmpDict.set("outerRadius", outerRadius);
557 
558  // create the source
559  autoPtr<topoSetSource> sourceSet(
560  topoSetSource::New(sourceType, mesh_, tmpDict));
561 
562  // add the sourceSet to topoSet
563  sourceSet().applyToSet(topoSetSource::NEW, currentSet());
564  // get the face index from currentSet, we need to use
565  // this special for loop
566  for (const label i : currentSet())
567  {
568  fvSourceCellIndices[diskName].append(i);
569  }
570  }
571  else if (sourceType == "cylinderAnnulusSmooth")
572  {
573  // do nothing, no need to compute the cell indices since
574  // we are using Gaussian function to compute a smooth
575  // distribution of fvSource term
576  }
577  else
578  {
579  FatalErrorIn("calcFvSourceCells") << "source: " << sourceType << " not supported!"
580  << "Options are: cylinderAnnulusToCell and cylinderAnnulusSmooth!"
581  << abort(FatalError);
582  }
583  }
584 
585  if (daOption_.getOption<label>("debug"))
586  {
587  Info << "fvSourceCellIndices " << fvSourceCellIndices << endl;
588  }
589 }
590 
591 } // End namespace Foam
592 
593 // ************************************************************************* //
Foam::DAFvSource
Definition: DAFvSource.H:34
Foam::DAFvSourceActuatorDisk::printInterval_
label printInterval_
print interval for primal and adjoint
Definition: DAFvSourceActuatorDisk.H:39
allOptions
const dictionary & allOptions
Definition: createRefsRhoSimpleC.H:15
Foam::DAFvSource::actuatorDiskDVs_
HashTable< List< scalar > > actuatorDiskDVs_
the list of design variables for all the actuator disks
Definition: DAFvSource.H:62
Foam::DAFvSource::syncDAOptionToActuatorDVs
void syncDAOptionToActuatorDVs()
synchronize the values in DAOption and actuatorDiskDVs_
Definition: DAFvSource.C:113
forAll
forAll(pseudoP.boundaryField(), patchI)
Definition: solvePseudoPEqn.H:10
DAFvSourceActuatorDisk.H
Foam::DAFvSource::daOption_
const DAOption & daOption_
DAOption object.
Definition: DAFvSource.H:53
Foam::DAOption
Definition: DAOption.H:29
daOption
DAOption daOption(mesh, pyOptions_)
Foam::DAOption::getOption
classType getOption(const word key) const
get an option from subDict and key
Definition: DAOption.H:92
fvSource
volScalarField & fvSource
Definition: createRefsHeatTransfer.H:7
Foam::DAFvSourceActuatorDisk::fvSourceCellIndices_
HashTable< labelList > fvSourceCellIndices_
HashTable that contains lists of cell indices that are within the actuator disk space.
Definition: DAFvSourceActuatorDisk.H:33
Foam::DAOption::getAllOptions
const dictionary & getAllOptions() const
return a reference of allOptions_ dictionary
Definition: DAOption.H:56
mesh
fvMesh & mesh
Definition: createRefsHeatTransfer.H:4
Foam::DAFvSourceActuatorDisk::DAFvSourceActuatorDisk
DAFvSourceActuatorDisk(const word modelType, const fvMesh &mesh, const DAOption &daOption, const DAModel &daModel, const DAIndex &daIndex)
Definition: DAFvSourceActuatorDisk.C:19
Foam::DAIndex
Definition: DAIndex.H:32
Foam::DAModel
Definition: DAModel.H:59
Foam
Definition: multiFreqScalarFvPatchField.C:144
Foam::DAFvSourceActuatorDisk::calcFvSource
virtual void calcFvSource(volVectorField &fvSource)
compute the FvSource term
Definition: DAFvSourceActuatorDisk.C:39
Foam::defineTypeNameAndDebug
defineTypeNameAndDebug(DAFvSource, 0)
Foam::DAFvSource::mesh_
const fvMesh & mesh_
fvMesh
Definition: DAFvSource.H:50
Foam::addToRunTimeSelectionTable
addToRunTimeSelectionTable(DAFvSource, DAFvSourceActuatorDisk, dictionary)
Foam::DAFvSourceActuatorDisk::calcFvSourceCellIndices
void calcFvSourceCellIndices(HashTable< labelList > &fvSourceCellIndices)
calculate DAFvSourceActuatorDisk::fvSourceCellIndices_
Definition: DAFvSourceActuatorDisk.C:449
daModel
DAModel daModel(mesh, daOption)
daIndex
DAIndex daIndex(mesh, daOption, daModel)