adjointkOmegaSST.C
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2014-2022 PCOpt/NTUA
9  Copyright (C) 2014-2022 FOSS GP
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "adjointkOmegaSST.H"
30 #include "wallFvPatch.H"
33 #include "linear.H"
34 #include "reverseLinear.H"
38 
39 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
40 
41 namespace Foam
42 {
43 namespace incompressibleAdjoint
44 {
45 namespace adjointRASModels
46 {
47 
48 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
49 
52 
53 
54 // * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
55 
57 {
59  (
60  min
61  (
62  max
63  (
64  (scalar(1)/betaStar_)*sqrt(k())/(omega()*y_),
65  scalar(500)*nu()/(sqr(y_)*omega())
66  ),
68  ),
69  scalar(10)
70  );
71 
72  return tanh(pow4(arg1));
73 }
74 
75 
77 {
79  (
80  max
81  (
82  (scalar(2)/betaStar_)*sqrt(k())/(omega()*y_),
83  scalar(500)*nu()/(sqr(y_)*omega())
84  ),
85  scalar(100)
86  );
87 
88  return tanh(sqr(arg2));
89 }
90 
91 
93 (
94  const volScalarField& GbyNu0,
95  const volScalarField& F2,
96  const volScalarField& S2
97 ) const
98 {
99  return min
100  (
101  GbyNu0,
103  *max(a1_*omega(), b1_*F2*sqrt(S2))
104  );
105 }
106 
107 
109 (
110  const volScalarField::Internal& GbyNu0,
112  const volScalarField::Internal& S2
113 ) const
114 {
115  return min
116  (
117  GbyNu0,
118  (c1_/a1_)*betaStar_*omega()()
119  *max(a1_*omega()(), b1_*F2*sqrt(S2))
120  );
121 }
122 
123 
125 {
126  auto tzeroFirstCell =
128  (
129  IOobject
130  (
131  "zeroFirstCell",
132  runTime_.timeName(),
133  mesh_,
136  ),
137  mesh_,
139  );
140  volScalarField& zeroFirstCell = tzeroFirstCell.ref();
141 
143  label counter(0);
144  for (const fvPatchScalarField& omegab : omega().boundaryField())
145  {
146  const fvPatch& patch = omegab.patch();
147  if (isA<omegaWallFunctionFvPatchScalarField>(omegab))
148  {
149  const label patchi = patch.index();
150  const labelList& faceCells = patch.faceCells();
151  fvPatchScalarField& bf = zeroFirstCell.boundaryFieldRef()[patchi];
152  forAll(faceCells, faceI)
153  {
154  const label cellI = faceCells[faceI];
155 
156  zeroFirstCell[cellI] = 0.;
157  bf[faceI] = 0.;
158  firstCellIDs_[counter++] = cellI;
159  }
160  }
161  }
162  firstCellIDs_.setSize(counter);
164  zeroFirstCell.correctBoundaryConditions();
165 
166  return tzeroFirstCell;
167 }
168 
169 
171 {
172  const volVectorField& U = primalVars_.U();
173  const volVectorField& Ua = adjointVars_.UaInst();
174  word scheme("coeffsDiff");
175  tmp<volScalarField> tdR_dnut
176  (
177  dNutdbMult(U, Ua, nutRef(), scheme)
178  + dNutdbMult(k(), ka(), alphaK_, nutRef(), scheme)
181  );
182  volScalarField& dRdnut = tdR_dnut.ref();
183 
184  forAll(mesh_.boundary(), pI)
185  {
186  const fvPatch& patch = mesh_.boundary()[pI];
187  const fvPatchScalarField& nutb = nutRef().boundaryField()[pI];
188  const labelList& faceCells = patch.faceCells();
189  if (isA<nutkWallFunctionFvPatchScalarField>(nutb))
190  {
191  fvPatchScalarField& bf = dRdnut.boundaryFieldRef()[pI];
192  const scalarField kSnGrad(k().boundaryField()[pI].snGrad());
193  const scalarField omegaSnGrad
194  (
195  omega().boundaryField()[pI].snGrad()
196  );
197  const fvPatchScalarField& akb = alphaK_.boundaryField()[pI];
198  const fvPatchScalarField& aOmegab = alphaOmega_.boundaryField()[pI];
199  const vectorField USnGrad(U.boundaryField()[pI].snGrad());
200  const fvPatchTensorField& gradUb = gradU_.boundaryField()[pI];
201  const vectorField nf(mesh_.boundary()[pI].nf());
202  forAll(faceCells, fI)
203  {
204  const label cI(faceCells[fI]);
205  bf[fI] =
206  - wa()[cI]*zeroFirstCell_[cI]*aOmegab[fI]*omegaSnGrad[fI]
207  - ka()[cI]*akb[fI]*kSnGrad[fI]
208  - (Ua[cI] & (USnGrad[fI] + (dev2(gradUb[fI]) & nf[fI])));
209  }
210  }
211  }
212 
213  return tdR_dnut;
214 }
215 
216 
218 (
219  const volScalarField& F2,
220  const volScalarField& S,
221  const volScalarField& case_1_nut,
222  const volScalarField& case_2_nut,
223  const volScalarField& case_3_nut
224 ) const
225 {
226  return
227  (
228  - case_1_nut*k()/sqr(omega())
229  - a1_*k()/(b1_*S*F2*F2)*dF2_domega(F2, case_2_nut, case_3_nut)
230  );
231 }
232 
233 
235 (
236  const volScalarField& F2,
237  const volScalarField& S,
238  const volScalarField& case_2_nut
239 ) const
240 {
241  return
242  (
244  - a1_*k()/(b1_*S*F2*F2)*dF2_dk(F2, case_2_nut)
245  );
246 }
247 
248 
250 (
251  const volScalarField& F2,
252  const volScalarField& case_2_nut,
253  const volScalarField& case_3_nut
254 ) const
255 {
256  tmp<volScalarField> arg2 = min
257  (
258  max
259  (
260  (scalar(2)/betaStar_)*sqrt(k())/(omega()*y_),
261  scalar(500)*nu()/(sqr(y_)*omega())
262  ),
263  scalar(100)
264  );
265 
266  return
267  - scalar(2)*arg2*(1 - F2*F2)*
268  (
269  case_2_nut*scalar(2)*sqrt(k())/(betaStar_*sqr(omega())*y_)
270  + case_3_nut*scalar(500)*nu()/sqr(omega()*y_)
271  );
272 }
273 
274 
276 (
277  const volScalarField& F2,
278  const volScalarField& case_2_nut
279 ) const
280 {
281  tmp<volScalarField> arg2 = min
282  (
283  max
284  (
285  (scalar(2)/betaStar_)*sqrt(k())/(omega()*y_),
286  scalar(500)*nu()/(sqr(y_)*omega())
287  ),
288  scalar(100)
289  );
291  return
292  case_2_nut*scalar(2)*arg2*(1 - F2*F2)
293  /(betaStar_*omega()*y_*sqrt(k()));
294 }
295 
296 
298 {
299  return
300  (
302  *(
303  max(a1_*omega(), b1_*F2_*S_)
304  + case_1_nut_*a1_*omega()
305  + (scalar(1) - case_1_nut_)*omega()*b1_*S_
307  )
308  );
309 }
310 
311 
313 {
314  return
317 }
318 
319 
321 {
322  const volVectorField& U = primalVars_.U();
324  tmp<volScalarField> tGPrime = GbyNu(GbyNu0_, F2_, S2_);
326  word scheme("coeffsDiff");
327 
328  tmp<volScalarField> tdRdF1
329  (
330  nutRef()
331  *(
335  )
336  );
337  volScalarField& dRdF1 = tdRdF1.ref();
338 
339  typedef fixedValueFvPatchScalarField fixedValue;
340  typedef zeroGradientFvPatchScalarField zeroGrad;
341  typedef omegaWallFunctionFvPatchScalarField omegaWF;
342  forAll(mesh_.boundary(), pI)
343  {
344  const fvPatchScalarField& kb = k().boundaryField()[pI];
345  const fvPatchScalarField& omegab = omega().boundaryField()[pI];
346  fvPatchScalarField& dRdF1b = dRdF1.boundaryFieldRef()[pI];
347  if
348  (
349  isA<zeroGrad>(kb)
350  && (isA<zeroGrad>(omegab) || isA<omegaWF>(omegab))
351  )
352  {
353  dRdF1b = dRdF1b.patchInternalField();
354  }
355  else if (isA<fixedValue>(kb) && isA<fixedValue>(omegab)
356  )
357  {
358  // Note: might need revisiting
359  dRdF1b = dRdF1b.patchInternalField();
360  }
361  }
362 
363  volScalarField dR_dF1_coeffs
364  (
366  *(
367  (gamma1_ - gamma2_)*((2.0/3.0)*omega()*tdivU - tGPrime)
368  + omega()*omega()*(beta1_ - beta2_) + CDkOmega_
369  )
370  );
371 
372  forAll(mesh_.boundary(), pI)
373  {
374  const fvPatchScalarField& kb = k().boundaryField()[pI];
375  const fvPatchScalarField& omegab = omega().boundaryField()[pI];
376  fvPatchScalarField& dRdF1b = dR_dF1_coeffs.boundaryFieldRef()[pI];
377  if
378  (
379  isA<zeroGrad>(kb)
380  && (isA<zeroGrad>(omegab) || isA<omegaWF>(omegab))
381  )
382  {
383  dRdF1b = Zero;
384  }
385  else if (isA<fixedValue>(kb) && isA<fixedValue>(omegab))
386  {
387  dRdF1b = dRdF1b.patchInternalField();
388  }
389  }
391  dRdF1 += dR_dF1_coeffs;
392  return tdRdF1;
393 }
394 
395 
397 (
398  const volScalarField& arg1
399 ) const
400 {
401  return
402  (
403  4*pow3(arg1)*(scalar(1) - F1_*F1_)
404  *(
405  - case_1_F1_*sqrt(k())/(betaStar_*omega()*omega()*y_)
406  - case_2_F1_*scalar(500)*nu()/sqr(omega()*y_)
409  )
410  );
411 }
412 
413 
415 (
416  const volScalarField& arg1
417 ) const
418 {
419  return
420  (
421  - case_3_F1_*scalar(4)*pow3(arg1)*(scalar(1) - F1_*F1_)
422  *scalar(8)*k()*sqr(alphaOmega2_/(CDkOmegaPlus_*y_))/omega()*gradK_
423  );
424 }
425 
426 
428 {
429  tmp<volScalarField> arg1 = min
430  (
431  min
432  (
433  max
434  (
435  (scalar(1)/betaStar_)*sqrt(k())/(omega()*y_),
436  scalar(500)*nu()/(sqr(y_)*omega())
437  ),
439  ),
440  scalar(10)
441  );
442 
443  volScalarField dR_dF1(this->dR_dF1());
444  volScalarField dF1_domega(this->dF1_domega(arg1));
446 
447  surfaceScalarField dR_dGradOmega
448  (
449  interpolationScheme<vector>("div(dR_dGradOmega)")().
451  );
452 
453  return
454  (
456  - fvc::div(dR_dGradOmega)
457  );
458 }
459 
460 
462 {
463  tmp<volVectorField> tsource
464  (
466  );
467  volVectorField& source = tsource.ref();
468 
469  forAll(mesh_.boundary(), pI)
470  {
471  const fvPatchScalarField& omegab = omega().boundaryField()[pI];
472  fvPatchVectorField& sourceb = source.boundaryFieldRef()[pI];
473  if
474  (
475  isA<zeroGradientFvPatchScalarField>(omegab)
476  || isA<omegaWallFunctionFvPatchScalarField>(omegab)
477  )
478  {
479  sourceb = Zero;
480  }
481  else if (isA<fixedValueFvPatchScalarField>(omegab))
482  {
483  sourceb = sourceb.patchInternalField();
484  }
485  }
486 
487  surfaceScalarField sourceFaces
488  (
489  interpolationScheme<vector>("sourceAdjontkOmegaSST")().
490  interpolate(source) & mesh_.Sf()
491  );
492 
493  return
494  (
495  // Differentiation of omega in CDkOmega
497  // Differentiation of grad(omega) in CDkOmega
498  + fvc::div(sourceFaces)
499  );
500 }
501 
502 
504 {
505  tmp<volVectorField> tsource
506  (
508  );
509  volVectorField& source = tsource.ref();
510 
511  forAll(mesh_.boundary(), pI)
512  {
513  const fvPatchScalarField& kb = k().boundaryField()[pI];
514  fvPatchVectorField& sourceb = source.boundaryFieldRef()[pI];
515  if (isA<zeroGradientFvPatchScalarField>(kb))
516  {
517  sourceb = Zero;
518  }
519  else if (isA<fixedValueFvPatchScalarField>(kb))
520  {
521  sourceb = sourceb.patchInternalField();
522  }
523  }
524 
525  return
526  fvc::div
527  (
528  interpolationScheme<vector>("sourceAdjontkOmegaSST")().
529  interpolate(source) & mesh_.Sf()
530  );
531 }
532 
533 
535 (
536  const volScalarField& arg1
537 ) const
538 {
539  return
540  (
541  4*pow3(arg1)*(scalar(1) - F1_*F1_)
542  *(
543  case_1_F1_*0.5/(betaStar_*omega()*sqrt(k())*y_)
545  )
546  );
547 }
548 
549 
551 (
552  const volScalarField& arg1
553 ) const
554 {
555  return
556  (
557  - case_3_F1_*scalar(4)*pow3(arg1)*(scalar(1) - F1_*F1_)
558  *scalar(8)*k()*sqr(alphaOmega2_/(CDkOmegaPlus_*y_))/omega()
559  *gradOmega_
560  );
561 }
562 
563 
565 {
566  tmp<volScalarField> arg1 = min
567  (
568  min
569  (
570  max
571  (
572  (scalar(1)/betaStar_)*sqrt(k())/(omega()*y_),
573  scalar(500)*nu()/(sqr(y_)*omega())
574  ),
576  ),
577  scalar(10)
578  );
579 
580  volScalarField dR_dF1(this->dR_dF1());
581  volScalarField dF1_dk(this->dF1_dk(arg1));
582  volVectorField dF1_dGradK(this->dF1_dGradK(arg1));
583 
584  surfaceScalarField dR_dGradK
585  (
586  interpolationScheme<vector>("div(dR_dGradK)")().
588  );
589 
590  return
591  (
593  - fvc::div(dR_dGradK)
594  );
595 }
596 
597 
599 (
600  const volScalarField& primalField,
601  const volScalarField& adjointField,
602  const word& schemeName
603 ) const
604 {
606  (interpolationScheme<scalar>(schemeName));
607  surfaceScalarField snGradPrimal(fvc::snGrad(primalField)*mesh_.magSf());
608  surfaceScalarField flux(scheme().interpolate(adjointField)*snGradPrimal);
609 
610  forAll(mesh_.boundary(), pI)
611  {
612  const fvPatchScalarField& primalbf = primalField.boundaryField()[pI];
613  if (isA<zeroGradientFvPatchScalarField>(primalbf))
614  {
615  // Needless, but just to be safe
616  snGradPrimal.boundaryFieldRef()[pI] = Zero;
617  flux.boundaryFieldRef()[pI] = Zero;
618  }
619  else if (isA<fixedValueFvPatchScalarField>(primalbf))
620  {
621  // Note: to be potentially revisited
622  snGradPrimal.boundaryFieldRef()[pI] = Zero;
623  flux.boundaryFieldRef()[pI] = Zero;
624  }
625  }
626 
627  return (fvc::div(flux) - adjointField*fvc::div(snGradPrimal));
628 }
629 
630 
632 (
633  const volScalarField& primalField,
634  const volScalarField& adjointField,
635  const volScalarField& coeffField,
636  const volScalarField& bcField,
637  const word& schemeName
638 ) const
639 {
641  (interpolationScheme<scalar>(schemeName));
642  surfaceScalarField snGradPrimal(fvc::snGrad(primalField)*mesh_.magSf());
643  surfaceScalarField flux(scheme().interpolate(adjointField)*snGradPrimal);
644 
645  forAll(mesh_.boundary(), pI)
646  {
647  const fvPatchScalarField& bc = bcField.boundaryField()[pI];
648  if (isA<zeroGradientFvPatchScalarField>(bc))
649  {
650  const fvPatchScalarField& coeffFieldb =
651  coeffField.boundaryField()[pI];
652  snGradPrimal.boundaryFieldRef()[pI] *=
653  coeffFieldb/coeffFieldb.patchInternalField();
654  flux.boundaryFieldRef()[pI] = Zero;
655  }
656  else if (isA<fixedValueFvPatchScalarField>(bc))
657  {
658  snGradPrimal.boundaryFieldRef()[pI] = Zero;
659  flux.boundaryFieldRef()[pI] = Zero;
660  }
661  }
662 
663  return coeffField*(fvc::div(flux) - adjointField*fvc::div(snGradPrimal));
664 }
665 
666 
668 (
669  const volVectorField& U,
670  const volVectorField& Ua,
671  const volScalarField& nut,
672  const word& schemeName
673 ) const
674 {
676  (interpolationScheme<vector>(schemeName));
678  surfaceScalarField flux(scheme().interpolate(Ua) & snGradU);
679 
680  // Terms form the Laplacian part of the momentum stresses
681  forAll(mesh_.boundary(), pI)
682  {
683  const fvPatchScalarField& bc = nut.boundaryField()[pI];
684  if (isA<zeroGradientFvPatchScalarField>(bc))
685  {
686  flux.boundaryFieldRef()[pI] = Zero;
687  }
688  else if (isA<fixedValueFvPatchScalarField>(bc))
689  {
690  snGradU.boundaryFieldRef()[pI] = Zero;
691  flux.boundaryFieldRef()[pI] = Zero;
692  }
693  }
694 
695  // Terms form the tranpose gradient in the momentum stresses
696  const surfaceVectorField& Sf = mesh_.Sf();
697  surfaceTensorField fluxTranspose
698  (
699  reverseLinear<vector>(mesh_).interpolate(Ua)*Sf
700  );
701  forAll(mesh_.boundary(), pI)
702  {
703  const fvPatchVectorField& Ub = U.boundaryField()[pI];
704  if (!isA<coupledFvPatchVectorField>(Ub))
705  {
706  const vectorField Uai(Ua.boundaryField()[pI].patchInternalField());
707  const vectorField& Sfb = Sf.boundaryField()[pI];
708  fluxTranspose.boundaryFieldRef()[pI] = Uai*Sfb;
709  }
710  }
711  volScalarField M(dev2(gradU_) && fvc::div(fluxTranspose));
712  const DimensionedField<scalar, volMesh>& V = mesh_.V();
713  forAll(mesh_.boundary(), pI)
714  {
715  const fvPatchScalarField& bc = nut.boundaryField()[pI];
716  if (isA<zeroGradientFvPatchScalarField>(bc))
717  {
718  const vectorField Uai(Ua.boundaryField()[pI].patchInternalField());
719  const tensorField dev2GradU
720  (
721  dev2(gradU_.boundaryField()[pI].patchInternalField())
722  );
723  const vectorField& Sfb = Sf.boundaryField()[pI];
724  const labelList& faceCells = mesh_.boundary()[pI].faceCells();
725  forAll(faceCells, fI)
726  {
727  const label celli = faceCells[fI];
728  M[celli] -= ((Uai[fI] & dev2GradU[fI]) & Sfb[fI])/V[celli];
729  }
730  }
731  }
732  M.correctBoundaryConditions();
733 
734  //surfaceScalarField fluxTranspose =
735  // fvc::interpolate(UaGradU, schemeName) & mesh_.Sf();
736  //forAll(mesh_.boundary(), pI)
737  //{
738  // const fvPatchScalarField& bc = nut.boundaryField()[pI];
739  // const vectorField& Sf = mesh_.boundary()[pI].Sf();
740  // if (isA<zeroGradientFvPatchScalarField>(bc))
741  // {
742  // fluxTranspose.boundaryFieldRef()[pI] =
743  // (
744  // UaGradU.boundaryField()[pI].patchInternalField()
745  // - (
746  // Ua.boundaryField()[pI].patchInternalField()
747  // & gradU_.boundaryField()[pI]
748  // )
749  // ) & Sf;
750  // }
751  // else if (isA<fixedValueFvPatchScalarField>(bc))
752  // {
753  // fluxTranspose.boundaryFieldRef()[pI] =
754  // UaGradU.boundaryField()[pI].patchInternalField() & Sf;
755  // }
756  //}
757  return
758  fvc::div(flux) - (Ua & fvc::div(snGradU)) + M;
759  //fvc::div(flux + fluxTranspose) - (Ua & fvc::div(snGradU));
760 }
761 
762 
764 (
765  const volScalarField& primalField,
766  const volScalarField& adjointField
767 ) const
768 {
769  // Grab the interpolation scheme from the primal convection term
770  tmp<surfaceInterpolationScheme<scalar>> primalInterpolationScheme
771  (
772  convectionScheme(primalField.name())
773  );
774 
775  surfaceVectorField interpolatedPrimal
776  (
777  primalInterpolationScheme().interpolate(primalField)*mesh_.Sf()
778  );
780  (
781  //reverseLinear<scalar>(mesh_).interpolate(adjointField)
782  linear<scalar>(mesh_).interpolate(adjointField)
783  *interpolatedPrimal
784  );
785 
786  const volVectorField& U = primalVars_.U();
787  forAll(mesh_.boundary(), pI)
788  {
789  const fvPatchVectorField& bc = U.boundaryField()[pI];
790  if (isA<zeroGradientFvPatchVectorField>(bc))
791  {
792  flux.boundaryFieldRef()[pI] = Zero;
793  }
794  else if (isA<fixedValueFvPatchVectorField>(bc))
795  {
796  interpolatedPrimal.boundaryFieldRef()[pI] = Zero;
797  flux.boundaryFieldRef()[pI] = Zero;
798  }
799  }
800 
801  return (-fvc::div(flux) + adjointField*fvc::div(interpolatedPrimal));
802 }
803 
804 
806 (
807  tmp<volSymmTensorField>& GbyNuMult
808 ) const
809 {
811  (
813  );
814 
815  const volVectorField& U = primalVars_.U();
816  forAll(mesh_.boundary(), pI)
817  {
818  const fvPatchVectorField& bc = U.boundaryField()[pI];
819  if (isA<zeroGradientFvPatchVectorField>(bc))
820  {
821  flux.boundaryFieldRef()[pI] = Zero;
822  }
823  else if (isA<fixedValueFvPatchVectorField>(bc))
824  {
825  flux.boundaryFieldRef()[pI] =
826  mesh_.boundary()[pI].Sf()
827  & GbyNuMult().boundaryField()[pI].patchInternalField();
828  }
829  }
830 
831  return fvc::div(flux);
832 }
833 
834 
836 (
837  tmp<volScalarField>& divUMult
838 ) const
839 {
841  (
843  );
844 
845  const volVectorField& U = primalVars_.U();
846  forAll(mesh_.boundary(), pI)
847  {
848  const fvPatchVectorField& bc = U.boundaryField()[pI];
849  if (isA<zeroGradientFvPatchVectorField>(bc))
850  {
851  flux.boundaryFieldRef()[pI] = Zero;
852  }
853  else if (isA<fixedValueFvPatchVectorField>(bc))
854  {
855  flux.boundaryFieldRef()[pI] =
856  mesh_.boundary()[pI].Sf()
857  *divUMult().boundaryField()[pI].patchInternalField();
858  }
859  }
860 
861  divUMult.clear();
862 
863  return -fvc::div(flux);
864 }
865 
866 
868 (
869  const volScalarField& primalField,
870  const volScalarField& adjointField,
871  const volScalarField& coeffField
872 ) const
873 {
874  // Note: we could grab the snGrad scheme from the diffusion term directly
875  surfaceScalarField snGradPrimal(fvc::snGrad(primalField)*mesh_.magSf());
877  (
878  reverseLinear<scalar>(mesh_).interpolate(adjointField)*snGradPrimal
879  );
880 
881  const volVectorField& U = primalVars_.U();
882  forAll(mesh_.boundary(), pI)
883  {
884  const fvPatchVectorField& bc = U.boundaryField()[pI];
885  if (!isA<coupledFvPatchVectorField>(bc))
886  {
887  flux.boundaryFieldRef()[pI] = Zero;
888  snGradPrimal.boundaryFieldRef()[pI] = Zero;
889  }
890  }
891  return (fvc::div(flux) - adjointField*fvc::div(snGradPrimal))*coeffField;
892 }
893 
894 
896 (
897  tmp<volScalarField>& mult,
898  const volScalarField& F2,
899  const volScalarField& S,
900  const volScalarField& case_1_nut,
901  const volTensorField& gradU
902 ) const
903 {
905  (
906  mult*a1_*k()*(1 - case_1_nut)/(b1_*F2*S*S*S)*twoSymm(gradU)
907  );
908  M.correctBoundaryConditions();
909  mult.clear();
910 
911  surfaceVectorField returnFieldFlux
912  (
914  );
915 
916  const volVectorField& U = primalVars_.U();
917  forAll(mesh_.boundary(), pI)
918  {
919  const fvPatchVectorField& bc = U.boundaryField()[pI];
920  if (isA<zeroGradientFvPatchVectorField>(bc))
921  {
922  returnFieldFlux.boundaryFieldRef()[pI] = Zero;
923  }
924  else if (isA<fixedValueFvPatchVectorField>(bc))
925  {
926  returnFieldFlux.boundaryFieldRef()[pI] =
927  mesh_.boundary()[pI].Sf()
928  & M.boundaryField()[pI].patchInternalField();
929  }
930  }
931 
932  // Note: potentially missing contributions form patches with a calculated
933  // nut bc
934 
935  return fvc::div(returnFieldFlux);
936 }
937 
938 
940 (
941  fvScalarMatrix& kaEqn,
942  const volScalarField& dR_dnut
943 )
944 {
945  // Add source term from the differentiation of nutWallFunction
946  scalarField& source = kaEqn.source();
948  const volScalarField& ka = this->ka();
949  const volScalarField& wa = this->wa();
950  const volScalarField& k = this->k();
951  const volScalarField& omega = this->omega();
952  forAll(nutRef().boundaryFieldRef(), patchi)
953  {
954  fvPatchScalarField& nutWall = nutRef().boundaryFieldRef()[patchi];
955  if (isA<nutkWallFunctionFvPatchScalarField>(nutWall))
956  {
957  const fvPatch& patch = mesh_.boundary()[patchi];
958  const scalarField& magSf = patch.magSf();
959 
962 
963  const scalarField& y = turbModel().y()[patchi];
964  const tmp<scalarField> tnuw = turbModel().nu(patchi);
965  const scalarField& nuw = tnuw();
966 
967  const nutWallFunctionFvPatchScalarField& nutWF =
968  refCast<nutWallFunctionFvPatchScalarField>(nutWall);
969  const wallFunctionCoefficients& wallCoeffs = nutWF.wallCoeffs();
970  const scalar Cmu = wallCoeffs.Cmu();
971  const scalar kappa = wallCoeffs.kappa();
972  const scalar E = wallCoeffs.E();
973  const scalar yPlusLam = wallCoeffs.yPlusLam();
974 
975  const scalar Cmu25 = pow025(Cmu);
976 
977  const labelList& faceCells = patch.faceCells();
978  const fvPatchScalarField& dR_dnutw =
979  dR_dnut.boundaryField()[patchi];
980  const fvPatchScalarField& omegaw = omega.boundaryField()[patchi];
981  bool addTermsFromOmegaWallFuction
982  (isA<omegaWallFunctionFvPatchScalarField>(omegaw));
983 
984  const fvPatchVectorField& Uw =
985  primalVars_.U().boundaryField()[patchi];
986  const scalarField magGradUw(mag(Uw.snGrad()));
987  forAll(nuw, facei)
988  {
989  const label celli = faceCells[facei];
990 
991  const scalar sqrtkCell(sqrt(k[celli]));
992  const scalar yPlus = Cmu25*y[facei]*sqrtkCell/nuw[facei];
993  const scalar logEyPlus = log(E*yPlus);
994  const scalar dnut_dyPlus =
995  nuw[facei]*kappa*(logEyPlus - 1)/sqr(logEyPlus);
996  const scalar dyPlus_dk =
997  Cmu25*y[facei]/(2*nuw[facei]*sqrtkCell);
998  const scalar dnut_dk = dnut_dyPlus*dyPlus_dk;
999 
1000  if (yPlusLam < yPlus)
1001  {
1002  // Terms from nutkWallFunction
1003  source[celli] -= dR_dnutw[facei]*dnut_dk*magSf[facei];
1004  }
1005  if (addTermsFromOmegaWallFuction)
1006  {
1007  const scalar denom(Cmu25*kappa*y[facei]);
1008  const scalar omegaLog(sqrtkCell/denom);
1009  // Terms from omegaLog in omegaWallFunction
1010  source[celli] +=
1011  wa[celli]*omegaLog/omega[celli]
1012  /(2*sqrtkCell*denom);
1013 
1014  // Terms from G at the first cell off the wall
1015  source[celli] +=
1016  case_1_Pk_[celli]*ka[celli]*V[celli]
1017  *(
1018  (nutWall[facei] + nuw[facei])
1019  *magGradUw[facei]
1020  *Cmu25
1021  /(2.0*sqrtkCell*kappa*y[facei])
1022  );
1023 
1024  if (yPlusLam < yPlus)
1025  {
1026  source[celli] +=
1027  case_1_Pk_[celli]*ka[celli]*V[celli]
1028  *dnut_dk
1029  *magGradUw[facei]
1030  *Cmu25*sqrtkCell
1031  /(kappa*y[facei]);
1032  }
1033  }
1034  }
1035  }
1036  }
1037 }
1038 
1039 
1041 {
1043  {
1044  Info<< "Updating primal-based fields of the adjoint turbulence "
1045  << "model ..." << endl;
1046 
1047  const volVectorField& U = primalVars_.U();
1048  gradU_ = fvc::grad(U);
1049  gradOmega_ = fvc::grad(omega());
1050  gradK_ = fvc::grad(k());
1051 
1052  S2_ = 2*magSqr(symm(gradU_))
1054  S_ = sqrt(S2_);
1055  GbyNu0_ = gradU_ && dev(twoSymm(gradU_));
1056 
1057  // Instead of computing G directly here, delegate to RASModelVariables
1058  // to make sure G is computed consistently when the primal fields are
1059  // averaged. The local value computed here is just used to update
1060  // the switch fields
1061  /*
1062  volScalarField G(primalVars_.turbulence()->GName(), nutRef()*GbyNu0_);
1063  omega().correctBoundaryConditions();
1064  */
1066  (
1067  IOobject
1068  (
1069  type() + ":G",
1070  mesh_.time().timeName(),
1071  mesh_,
1074  ),
1075  mesh_,
1077  );
1078  G.ref() = primalVars_.RASModelVariables()->G()();
1079 
1080  CDkOmega_ =
1081  (2*alphaOmega2_)*(gradK_ & gradOmega_)/omega();
1082  CDkOmegaPlus_ = max
1083  (
1084  CDkOmega_,
1085  dimensionedScalar("1.0e-10", dimless/sqr(dimTime), 1.0e-10)
1086  );
1087  F1_ = F1();
1088  F2_ = F2();
1089  case_1_Pk_ = neg(G - c1_*betaStar_*k()*omega());
1090  case_2_Pk_ = pos0(G - c1_*betaStar_*k()*omega());
1091  case_3_Pk_ = neg(a1_*omega() - b1_*F2_*S_);
1092 
1093 
1094  alphaK_ = alphaK(F1_);
1096  beta_ = beta(F1_);
1097  gamma_ = gamma(F1_);
1098 
1099  // Switch fields for F1
1100  {
1101  volScalarField arg1_C3
1102  (
1103  (scalar(1)/betaStar_)*sqrt(k())/(omega()*y_)
1104  - scalar(500)*nu()/(sqr(y_)*omega())
1105  );
1106  volScalarField arg1_C2
1107  (
1108  max
1109  (
1110  (scalar(1)/betaStar_)*sqrt(k())/(omega()*y_),
1111  scalar(500)*nu()/(sqr(y_)*omega())
1112  )
1113  - (4*alphaOmega2_)*k()/(CDkOmegaPlus_*sqr(y_))
1114  );
1115  volScalarField arg1_C1
1116  (
1117  min
1118  (
1119  max
1120  (
1121  (scalar(1)/betaStar_)*sqrt(k())/(omega()*y_),
1122  scalar(500)*nu()/(sqr(y_)*omega())
1123  ),
1124  (4*alphaOmega2_)*k()/(CDkOmegaPlus_*sqr(y_))
1125  ) - scalar(10)
1126  );
1127  volScalarField CDkOmegaPlus_C1
1128  (
1129  CDkOmega_
1130  - dimensionedScalar("1.0e-10", dimless/sqr(dimTime), 1.0e-10)
1131  );
1132 
1133  case_1_F1_ = pos(arg1_C3)*neg(arg1_C2)*neg(arg1_C1);
1134  case_2_F1_ = neg0(arg1_C3)*neg(arg1_C2)*neg(arg1_C1);
1135  case_3_F1_ = pos0(arg1_C2)*neg(arg1_C1)*pos(CDkOmegaPlus_C1);
1136  case_4_F1_ = pos0(arg1_C2)*neg(arg1_C1);
1137  }
1138 
1139  // Switch fields for nut
1140  {
1141  volScalarField nut_C1(a1_*omega() - b1_*F2_*S_);
1142  volScalarField arg2_C2
1143  (
1144  (scalar(2)/betaStar_)*sqrt(k())/(omega()*y_)
1145  - scalar(500)*nu()/(sqr(y_)*omega())
1146  );
1147  volScalarField arg2_C1
1148  (
1149  max
1150  (
1151  (scalar(2)/betaStar_)*sqrt(k())/(omega()*y_),
1152  scalar(500)*nu()/(sqr(y_)*omega())
1153  ) - scalar(100)
1154  );
1155 
1156  case_1_nut_ = pos(nut_C1);
1157  case_2_nut_ = neg0(nut_C1)*pos(arg2_C2)*neg(arg2_C1);
1158  case_3_nut_ = neg0(nut_C1)*neg0(arg2_C2)*neg(arg2_C1);
1159  }
1160 
1161  {
1162  volScalarField GPrime_C1
1163  (
1164  GbyNu0_
1165  - (c1_/a1_)*betaStar_*omega()*max(a1_*omega(), b1_*F2_*S_)
1166  );
1167  case_1_GPrime_ = neg(GPrime_C1);
1168  case_2_GPrime_ = pos0(GPrime_C1);
1169  }
1170 
1171  dnut_domega_ =
1175  DkEff_ = DkEff(F1_);
1177  changedPrimalSolution_ = false;
1178  }
1179 }
1180 
1181 
1183 (
1184  const word& varName
1185 ) const
1186 {
1188  const surfaceScalarField& phiInst = primalVars_.phiInst();
1189  word divEntry("div(" + phiInst.name() + ',' + varName +')');
1190  ITstream& divScheme = mesh_.divScheme(divEntry);
1191  // Skip the first entry which might be 'bounded' or 'Gauss'.
1192  // If it is 'bounded', skip the second entry as well
1193  word discarded(divScheme);
1194  if (discarded == "bounded")
1195  {
1196  discarded = word(divScheme);
1197  }
1199 }
1200 
1201 
1202 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
1203 
1204 adjointkOmegaSST::adjointkOmegaSST
1205 (
1206  incompressibleVars& primalVars,
1207  incompressibleAdjointMeanFlowVars& adjointVars,
1208  objectiveManager& objManager,
1209  const word& adjointTurbulenceModelName,
1210  const word& modelName
1211 )
1212 :
1214  (
1215  modelName,
1216  primalVars,
1217  adjointVars,
1218  objManager,
1219  adjointTurbulenceModelName
1220  ),
1221 
1222  kappa_
1223  (
1224  dimensioned<scalar>::getOrAddToDict
1225  (
1226  "kappa",
1227  coeffDict_,
1228  0.41
1229  )
1230  ),
1231  alphaK1_
1232  (
1233  dimensioned<scalar>::getOrAddToDict
1234  (
1235  "alphaK1",
1236  this->coeffDict_,
1237  0.85
1238  )
1239  ),
1240  alphaK2_
1241  (
1242  dimensioned<scalar>::getOrAddToDict
1243  (
1244  "alphaK2",
1245  this->coeffDict_,
1246  1.0
1247  )
1248  ),
1249  alphaOmega1_
1250  (
1251  dimensioned<scalar>::getOrAddToDict
1252  (
1253  "alphaOmega1",
1254  this->coeffDict_,
1255  0.5
1256  )
1257  ),
1258  alphaOmega2_
1259  (
1260  dimensioned<scalar>::getOrAddToDict
1261  (
1262  "alphaOmega2",
1263  this->coeffDict_,
1264  0.856
1265  )
1266  ),
1267  gamma1_
1268  (
1269  dimensioned<scalar>::getOrAddToDict
1270  (
1271  "gamma1",
1272  this->coeffDict_,
1273  5.0/9.0
1274  )
1275  ),
1276  gamma2_
1277  (
1278  dimensioned<scalar>::getOrAddToDict
1279  (
1280  "gamma2",
1281  this->coeffDict_,
1282  0.44
1283  )
1284  ),
1285  beta1_
1286  (
1287  dimensioned<scalar>::getOrAddToDict
1288  (
1289  "beta1",
1290  this->coeffDict_,
1291  0.075
1292  )
1293  ),
1294  beta2_
1295  (
1296  dimensioned<scalar>::getOrAddToDict
1297  (
1298  "beta2",
1299  this->coeffDict_,
1300  0.0828
1301  )
1302  ),
1303  betaStar_
1304  (
1305  dimensioned<scalar>::getOrAddToDict
1306  (
1307  "betaStar",
1308  this->coeffDict_,
1309  0.09
1310  )
1311  ),
1312  a1_
1313  (
1314  dimensioned<scalar>::lookupOrAddToDict
1315  (
1316  "a1",
1317  this->coeffDict_,
1318  0.31
1319  )
1320  ),
1321  b1_
1322  (
1323  dimensioned<scalar>::lookupOrAddToDict
1324  (
1325  "b1",
1326  this->coeffDict_,
1327  1.0
1328  )
1329  ),
1330  c1_
1331  (
1332  dimensioned<scalar>::lookupOrAddToDict
1333  (
1334  "c1",
1335  this->coeffDict_,
1336  10.0
1337  )
1338  ),
1339  F3_
1340  (
1341  Switch::lookupOrAddToDict
1342  (
1343  "F3",
1344  this->coeffDict_,
1345  false
1346  )
1347  ),
1348 
1349  y_(primalVars_.RASModelVariables()().d()),
1350 
1351  //Primal Gradient Fields
1352  gradU_
1353  (
1354  IOobject
1355  (
1356  "rasModel::gradU",
1357  runTime_.timeName(),
1358  mesh_,
1359  IOobject::NO_READ,
1360  IOobject::NO_WRITE
1361  ),
1362  mesh_,
1364  ),
1365  gradOmega_
1366  (
1367  IOobject
1368  (
1369  "rasModel::gradOmega",
1370  runTime_.timeName(),
1371  mesh_,
1372  IOobject::NO_READ,
1373  IOobject::NO_WRITE
1374  ),
1375  mesh_,
1377  ),
1378  gradK_
1379  (
1380  IOobject
1381  (
1382  "rasModel::gradK",
1383  runTime_.timeName(),
1384  mesh_,
1385  IOobject::NO_READ,
1386  IOobject::NO_WRITE
1387  ),
1388  mesh_,
1390  ),
1391 
1392  S2_
1393  (
1394  IOobject
1395  (
1396  "S2",
1397  runTime_.timeName(),
1398  mesh_,
1399  IOobject::NO_READ,
1400  IOobject::NO_WRITE
1401  ),
1402  mesh_,
1404  ),
1405  S_
1406  (
1407  IOobject
1408  (
1409  "kOmegaSST_S",
1410  runTime_.timeName(),
1411  mesh_,
1412  IOobject::NO_READ,
1413  IOobject::NO_WRITE
1414  ),
1415  mesh_,
1417  ),
1418  GbyNu0_
1419  (
1420  IOobject
1421  (
1422  "adjointRASModel::GbyNu0",
1423  runTime_.timeName(),
1424  mesh_,
1425  IOobject::NO_READ,
1426  IOobject::NO_WRITE
1427  ),
1428  mesh_,
1430  ),
1431  CDkOmega_
1432  (
1433  IOobject
1434  (
1435  "CDkOmega_",
1436  runTime_.timeName(),
1437  mesh_,
1438  IOobject::NO_READ,
1439  IOobject::NO_WRITE
1440  ),
1441  mesh_,
1443  ),
1444  CDkOmegaPlus_
1445  (
1446  IOobject
1447  (
1448  "CDkOmegaPlus",
1449  runTime_.timeName(),
1450  mesh_,
1451  IOobject::NO_READ,
1452  IOobject::NO_WRITE
1453  ),
1454  mesh_,
1456  ),
1457  F1_
1458  (
1459  IOobject
1460  (
1461  "F1",
1462  runTime_.timeName(),
1463  mesh_,
1464  IOobject::NO_READ,
1465  IOobject::NO_WRITE
1466  ),
1467  mesh_,
1469  ),
1470  F2_
1471  (
1472  IOobject
1473  (
1474  "F2",
1475  runTime_.timeName(),
1476  mesh_,
1477  IOobject::NO_READ,
1478  IOobject::NO_WRITE
1479  ),
1480  mesh_,
1482  ),
1483  // Model Field coefficients
1484  alphaK_
1485  (
1486  IOobject
1487  (
1488  "alphaK",
1489  runTime_.timeName(),
1490  mesh_,
1491  IOobject::NO_READ,
1492  IOobject::NO_WRITE
1493  ),
1494  mesh_,
1496  ),
1497  alphaOmega_
1498  (
1499  IOobject
1500  (
1501  "alphaOmega",
1502  runTime_.timeName(),
1503  mesh_,
1504  IOobject::NO_READ,
1505  IOobject::NO_WRITE
1506  ),
1507  mesh_,
1509  ),
1510  beta_
1511  (
1512  IOobject
1513  (
1514  "beta",
1515  runTime_.timeName(),
1516  mesh_,
1517  IOobject::NO_READ,
1518  IOobject::NO_WRITE
1519  ),
1520  mesh_,
1522  ),
1523  gamma_
1524  (
1525  IOobject
1526  (
1527  "gamma",
1528  runTime_.timeName(),
1529  mesh_,
1530  IOobject::NO_READ,
1531  IOobject::NO_WRITE
1532  ),
1533  mesh_,
1535  ),
1536 
1537  case_1_F1_
1538  (
1539  IOobject
1540  (
1541  "case_1_F1",
1542  runTime_.timeName(),
1543  mesh_,
1544  IOobject::NO_READ,
1545  IOobject::NO_WRITE
1546  ),
1547  mesh_,
1549  ),
1550  case_2_F1_
1551  (
1552  IOobject
1553  (
1554  "case_2_F1",
1555  runTime_.timeName(),
1556  mesh_,
1557  IOobject::NO_READ,
1558  IOobject::NO_WRITE
1559  ),
1560  mesh_,
1562  ),
1563  case_3_F1_
1564  (
1565  IOobject
1566  (
1567  "case_3_F1",
1568  runTime_.timeName(),
1569  mesh_,
1570  IOobject::NO_READ,
1571  IOobject::NO_WRITE
1572  ),
1573  mesh_,
1575  ),
1576  case_4_F1_
1577  (
1578  IOobject
1579  (
1580  "case_4_F1",
1581  runTime_.timeName(),
1582  mesh_,
1583  IOobject::NO_READ,
1584  IOobject::NO_WRITE
1585  ),
1586  mesh_,
1588  ),
1589  case_1_Pk_
1590  (
1591  IOobject
1592  (
1593  "case_1_Pk",
1594  runTime_.timeName(),
1595  mesh_,
1596  IOobject::NO_READ,
1597  IOobject::NO_WRITE
1598  ),
1599  mesh_,
1601  ),
1602  case_2_Pk_
1603  (
1604  IOobject
1605  (
1606  "case_2_Pk",
1607  runTime_.timeName(),
1608  mesh_,
1609  IOobject::NO_READ,
1610  IOobject::NO_WRITE
1611  ),
1612  mesh_,
1614  ),
1615  case_3_Pk_
1616  (
1617  IOobject
1618  (
1619  "case_3_Pk",
1620  runTime_.timeName(),
1621  mesh_,
1622  IOobject::NO_READ,
1623  IOobject::NO_WRITE
1624  ),
1625  mesh_,
1627  ),
1628 
1629  case_1_nut_
1630  (
1631  IOobject
1632  (
1633  "case_1_nut",
1634  runTime_.timeName(),
1635  mesh_,
1636  IOobject::NO_READ,
1637  IOobject::NO_WRITE
1638  ),
1639  mesh_,
1641  ),
1642  case_2_nut_
1643  (
1644  IOobject
1645  (
1646  "case_2_nut",
1647  runTime_.timeName(),
1648  mesh_,
1649  IOobject::NO_READ,
1650  IOobject::NO_WRITE
1651  ),
1652  mesh_,
1654  ),
1655  case_3_nut_
1656  (
1657  IOobject
1658  (
1659  "case_3_nut",
1660  runTime_.timeName(),
1661  mesh_,
1662  IOobject::NO_READ,
1663  IOobject::NO_WRITE
1664  ),
1665  mesh_,
1667  ),
1668  case_1_GPrime_
1669  (
1670  IOobject
1671  (
1672  "case_1_GPrime",
1673  runTime_.timeName(),
1674  mesh_,
1675  IOobject::NO_READ,
1676  IOobject::NO_WRITE
1677  ),
1678  mesh_,
1680  ),
1681  case_2_GPrime_
1682  (
1683  IOobject
1684  (
1685  "case_2_GPrime",
1686  runTime_.timeName(),
1687  mesh_,
1688  IOobject::NO_READ,
1689  IOobject::NO_WRITE
1690  ),
1691  mesh_,
1693  ),
1694 
1695  // Zero 1rst cell field
1696  firstCellIDs_(0),
1697  zeroFirstCell_(zeroFirstCell()),
1698 
1699  // Turbulence model multipliers
1700  dnut_domega_
1701  (
1702  IOobject
1703  (
1704  "dnut_domega",
1705  runTime_.timeName(),
1706  mesh_,
1707  IOobject::NO_READ,
1708  IOobject::NO_WRITE
1709  ),
1710  mesh_,
1712  ),
1713  dnut_dk_
1714  (
1715  IOobject
1716  (
1717  "dnut_dk",
1718  runTime_.timeName(),
1719  mesh_,
1720  IOobject::NO_READ,
1721  IOobject::NO_WRITE
1722  ),
1723  mesh_,
1725  ),
1726  DOmegaEff_
1727  (
1728  IOobject
1729  (
1730  "DomegaEff",
1731  runTime_.timeName(),
1732  mesh_,
1733  IOobject::NO_READ,
1734  IOobject::NO_WRITE
1735  ),
1736  mesh_,
1737  dimensionedScalar(nutRef().dimensions(), Zero)
1738  ),
1739  DkEff_
1740  (
1741  IOobject
1742  (
1743  "DkEff",
1744  runTime_.timeName(),
1745  mesh_,
1746  IOobject::NO_READ,
1747  IOobject::NO_WRITE
1748  ),
1749  mesh_,
1750  dimensionedScalar(nutRef().dimensions(), Zero)
1751  )
1752 {
1754  adjointTMVariablesBaseNames_[0] = "ka";
1755  adjointTMVariablesBaseNames_[1] = "wa";
1756  // Read in adjoint fields
1758  (
1760  mesh_,
1761  "ka",
1762  adjointVars.solverName(),
1763  adjointVars.useSolverNameForFields()
1764  );
1766  (
1768  mesh_,
1769  "wa",
1770  adjointVars.solverName(),
1771  adjointVars.useSolverNameForFields()
1772  );
1773 
1774  setMeanFields();
1775 
1776  // No sensitivity contributions from the adjoint to the eikonal equation
1777  // for the moment
1778  includeDistance_ = false;
1779 
1780  // Update the primal related fields here so that functions computing
1781  // sensitivities have the updated fields in case of continuation
1783 }
1784 
1785 
1786 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
1787 
1790  const volVectorField& Ua = adjointVars_.UaInst();
1791  return devReff(Ua);
1792 }
1793 
1794 
1796 (
1797  const volVectorField& U
1798 ) const
1799 {
1800  return
1802  (
1803  IOobject
1804  (
1805  "devRhoReff",
1806  runTime_.timeName(),
1807  mesh_,
1810  ),
1811  -nuEff()*dev(twoSymm(fvc::grad(U)))
1812  );
1813 }
1814 
1815 
1817 {
1818  tmp<volScalarField> tnuEff = nuEff();
1819  const volScalarField& nuEff = tnuEff();
1820 
1821  return
1822  (
1823  - fvm::laplacian(nuEff, Ua)
1824  - fvc::div(nuEff*dev(fvc::grad(Ua)().T()))
1825  );
1826 
1827  /* WIP
1828  const volVectorField& U = primalVars_.U();
1829  const surfaceVectorField& Sf = mesh_.Sf();
1830  tmp<surfaceTensorField> tflux =
1831  reverseLinear<vector>(mesh_).interpolate(Ua)*Sf;
1832  surfaceTensorField& flux = tflux.ref();
1833  forAll(mesh_.boundary(), pI)
1834  {
1835  const fvPatchVectorField& Ub = U.boundaryField()[pI];
1836  if (!isA<coupledFvPatchVectorField>(Ub))
1837  {
1838  const vectorField Uai = Ua.boundaryField()[pI].patchInternalField();
1839  const vectorField& Sfb = Sf.boundaryField()[pI];
1840  flux.boundaryFieldRef()[pI] = Uai*Sfb;
1841  }
1842  }
1843  volTensorField M(nuEff*dev2(fvc::div(flux)));
1844  const DimensionedField<scalar, volMesh>& V = mesh_.V();
1845 
1846  forAll(mesh_.boundary(), pI)
1847  {
1848  const fvPatchVectorField& Ub = U.boundaryField()[pI];
1849  if (!isA<coupledFvPatchVectorField>(Ub))
1850  {
1851  const fvPatchScalarField& nuEffb = nuEff.boundaryField()[pI];
1852  const vectorField nf = mesh_.boundary()[pI].nf();
1853  const vectorField Uai = Ua.boundaryField()[pI].patchInternalField();
1854  const labelList& faceCells = mesh_.boundary()[pI].faceCells();
1855  const vectorField& Sfb = Sf.boundaryField()[pI];
1856 
1857  forAll(faceCells, fI)
1858  {
1859  const label celli = faceCells[fI];
1860  const tensor t(dev2(Uai[fI]*Sfb[fI]));
1861  M[celli] -= nuEffb[fI]*(t - nf[fI]*(nf[fI] & t))/V[celli];
1862  }
1863  }
1864  }
1865  M.correctBoundaryConditions();
1866 
1867  surfaceVectorField returnFlux =
1868  - (Sf & reverseLinear<tensor>(mesh_).interpolate(M));
1869  forAll(mesh_.boundary(), pI)
1870  {
1871  const fvPatchVectorField& Ub = U.boundaryField()[pI];
1872  if (isA<zeroGradientFvPatchVectorField>(Ub))
1873  {
1874  returnFlux.boundaryFieldRef()[pI] = Zero;
1875  }
1876  else if (isA<fixedValueFvPatchVectorField>(Ub))
1877  {
1878  const scalarField& deltaCoeffs = mesh_.boundary()[pI].deltaCoeffs();
1879  const fvPatchScalarField& nuEffb = nuEff.boundaryField()[pI];
1880  const vectorField Uai = Ua.boundaryField()[pI].patchInternalField();
1881  const vectorField nf = mesh_.boundary()[pI].nf();
1882  const vectorField& Sfb = Sf.boundaryField()[pI];
1883 
1884  returnFlux.boundaryFieldRef()[pI] =
1885  - (Sfb & M.boundaryField()[pI].patchInternalField())
1886  + nuEffb*deltaCoeffs*(nf & dev2(Uai*Sfb));
1887  }
1888  }
1889 
1890  return
1891  (
1892  - fvm::laplacian(nuEff, Ua)
1893  + fvc::div(returnFlux)
1894  );
1895  */
1896 }
1897 
1900 {
1901  return (ka()*gradK_ + wa()*gradOmega_);
1902 }
1903 
1904 
1906 {
1907  tmp<volVectorField> tmeanFlowSource
1908  (
1910  (
1911  IOobject
1912  (
1913  "adjointMeanFlowSource" + type(),
1914  mesh_.time().timeName(),
1915  mesh_,
1918  ),
1919  mesh_,
1921  )
1922  );
1923  volVectorField& meanFlowSource = tmeanFlowSource.ref();
1924 
1925  // Contributions from the convection terms of the turbulence model
1926  meanFlowSource +=
1928  + convectionMeanFlowSource(k(), ka());
1929 
1930  // Contributions from GbyNu, including gradU
1931  tmp<volSymmTensorField> twoSymmGradU(twoSymm(gradU_));
1932  tmp<volSymmTensorField> GbyNuMult
1933  (
1934  // First part of GPrime and G from Pk
1935  2.*dev(twoSymmGradU())*zeroFirstCell_
1937  // Second part of GPrime
1938  + twoSymmGradU()*wa()*zeroFirstCell_*gamma_*case_2_GPrime_
1940  );
1941  twoSymmGradU.clear();
1942  meanFlowSource += GMeanFlowSource(GbyNuMult);
1943  GbyNuMult.clear();
1944 
1945  // Contributions from divU
1946  tmp<volScalarField> divUMult
1947  (
1948  (2.0/3.0)*(zeroFirstCell_*wa()*omega()*gamma_ + ka()*k())
1949  );
1950  meanFlowSource += divUMeanFlowSource(divUMult);
1951 
1952  // Contributions from S2, existing in nut
1953  const volVectorField& U = primalVars_.U();
1954  const volVectorField& Ua = adjointVars_.UaInst();
1955  tmp<volScalarField> nutMeanFlowSourceMult
1956  (
1957  // nut in the diffusion coefficients
1960  + dNutdbMult(U, Ua, nutRef(), "coeffsDiff")
1961  // nut in G
1963  );
1964  meanFlowSource +=
1966  (
1967  nutMeanFlowSourceMult,
1968  F2_,
1969  S_,
1970  case_1_nut_,
1971  gradU_
1972  );
1973 
1974  // G at the first cell includes mag(U.snGrad())
1975  // Add term here
1976  forAll(omega().boundaryFieldRef(), patchi)
1977  {
1978  fvPatchScalarField& omegaWall = omega().boundaryFieldRef()[patchi];
1979  if (isA<omegaWallFunctionFvPatchScalarField>(omegaWall))
1980  {
1981  const fvPatch& patch = mesh_.boundary()[patchi];
1982 
1983  const autoPtr<incompressible::turbulenceModel>& turbModel =
1985 
1986  const scalarField& y = turbModel().y()[patchi];
1987  const tmp<scalarField> tnuw = turbModel().nu(patchi);
1988  const scalarField& nuw = tnuw();
1989 
1990  const nutWallFunctionFvPatchScalarField& nutw =
1991  refCast<nutWallFunctionFvPatchScalarField>
1992  (nutRef().boundaryFieldRef()[patchi]);
1993  const wallFunctionCoefficients& wallCoeffs = nutw.wallCoeffs();
1994  const scalar Cmu = wallCoeffs.Cmu();
1995  const scalar kappa = wallCoeffs.kappa();
1996  const scalar Cmu25 = pow025(Cmu);
1997 
1998  const labelList& faceCells = patch.faceCells();
1999 
2000  const fvPatchVectorField& Uw =
2001  primalVars_.U().boundaryField()[patchi];
2002  vectorField snGradUw(Uw.snGrad());
2003  const scalarField& deltaCoeffs = patch.deltaCoeffs();
2004  forAll(faceCells, facei)
2005  {
2006  const label celli = faceCells[facei];
2007  // Volume will be added when meanFlowSource is added to UaEqn
2008  meanFlowSource[celli] +=
2009  ka()[celli]*case_1_Pk_[celli]
2010  *(nutw[facei] + nuw[facei])
2011  *snGradUw[facei].normalise()
2012  *Cmu25*sqrt(k()[celli])
2013  *deltaCoeffs[facei]
2014  /(kappa*y[facei]);
2015  }
2016  }
2017  }
2018  return tmeanFlowSource;
2019 }
2020 
2021 
2022 tmp<volScalarField> adjointkOmegaSST::nutJacobianTMVar1() const
2023 {
2024  // Compute dnut_dk anew since the current copy of dnut_dk_
2025  // might not be updated
2026  const volVectorField& U = primalVars_.U();
2027  tmp<volScalarField> S2
2028  (
2029  2*magSqr(symm(fvc::grad(U)))
2031  );
2032  volScalarField S(sqrt(S2));
2033  volScalarField F2(this->F2());
2034 
2035  // Computation of nut switches
2036  volScalarField nut_C1(a1_*omega() - b1_*F2*S);
2037  volScalarField arg2_C2
2038  (
2039  (scalar(2)/betaStar_)*sqrt(k())/(omega()*y_)
2040  - scalar(500)*nu()/(sqr(y_)*omega())
2041  );
2042  volScalarField arg2_C1
2043  (
2044  max
2045  (
2046  (scalar(2)/betaStar_)*sqrt(k())/(omega()*y_),
2047  scalar(500)*nu()/(sqr(y_)*omega())
2048  ) - scalar(100)
2049  );
2050  volScalarField case_2_nut(neg0(nut_C1)*pos(arg2_C2)*neg(arg2_C1));
2051 
2052  return dnut_dk(F2, S, case_2_nut);
2053 }
2054 
2055 
2057 {
2058  // Compute dnut_omega anew since the current copy of dnut_domega_
2059  // might not be updated
2060  const volVectorField& U = primalVars_.U();
2062  (
2063  2*magSqr(symm(fvc::grad(U)))
2065  );
2066  volScalarField S(sqrt(S2));
2067  volScalarField F2(this->F2());
2068 
2069  // Computation of nut switches
2070  volScalarField nut_C1(a1_*omega() - b1_*F2*S);
2071  volScalarField arg2_C2
2072  (
2073  (scalar(2)/betaStar_)*sqrt(k())/(omega()*y_)
2074  - scalar(500)*nu()/(sqr(y_)*omega())
2075  );
2076  volScalarField arg2_C1
2077  (
2078  max
2079  (
2080  (scalar(2)/betaStar_)*sqrt(k())/(omega()*y_),
2081  scalar(500)*nu()/(sqr(y_)*omega())
2082  ) - scalar(100)
2083  );
2084  volScalarField case_1_nut(pos(nut_C1));
2085  volScalarField case_2_nut(neg0(nut_C1)*pos(arg2_C2)*neg(arg2_C1));
2086  volScalarField case_3_nut(neg0(nut_C1)*neg0(arg2_C2)*neg(arg2_C1));
2087 
2088  return dnut_domega(F2, S, case_1_nut, case_2_nut, case_3_nut);
2089 }
2090 
2091 
2093 (
2094  tmp<volScalarField>& dNutdUMult
2095 ) const
2096 {
2097  const volVectorField& U = primalVars_.U();
2098  volTensorField gradU(fvc::grad(U));
2100  (
2101  2*magSqr(symm(gradU))
2103  );
2104  volScalarField S(sqrt(S2));
2105  volScalarField F2(this->F2());
2106 
2107  // Computation of nut switches
2108  volScalarField nut_C1(a1_*omega() - b1_*F2*S);
2109  volScalarField case_1_nut(pos(nut_C1));
2110 
2111  return nutMeanFlowSource(dNutdUMult, F2, S, case_1_nut, gradU);
2112 }
2113 
2114 
2116 {
2117  return
2118  (
2119  alphaK_.boundaryField()[patchI]*nutRef().boundaryField()[patchI]
2120  + nu()().boundaryField()[patchI]
2121  );
2122 }
2123 
2124 
2126 {
2127  return
2128  (
2129  alphaOmega_.boundaryField()[patchI]*nutRef().boundaryField()[patchI]
2130  + nu()().boundaryField()[patchI]
2131  );
2132 }
2133 
2134 
2136 {
2138 
2139  if (!adjointTurbulence_)
2140  {
2141  return;
2142  }
2143 
2145 
2146  // Primal and adjoint fields
2147  const volVectorField& U = primalVars_.U();
2149  volScalarField dR_dnut(this->dR_dnut());
2151 
2152  tmp<fvScalarMatrix> waEqn
2153  (
2154  fvm::div(-phi, wa())
2158  + waEqnSourceFromF1()
2160  + fvm::Sp(zeroFirstCell_*scalar(2.)*beta_*omega(), wa())
2161  + fvm::SuSp
2162  (
2163  zeroFirstCell_()*gamma_*((2.0/3.0)*divU - dGPrime_domega().ref()()),
2164  wa()
2165  )
2166  - (case_2_Pk_*c1_ - scalar(1))*betaStar_*k()*ka()
2167  );
2168 
2169  // Boundary manipulate changes the diagonal component, so relax has to
2170  // come after that
2171  waEqn.ref().boundaryManipulate(wa().boundaryFieldRef());
2172  waEqn.ref().relax();
2173 
2174  // Sources from the objective should be added after the boundary
2175  // manipulation
2176  objectiveManager_.addTMEqn2Source(waEqn.ref());
2177  waEqn.ref().solve();
2178 
2179  // Adjoint Turbulent kinetic energy equation
2180  tmp<fvScalarMatrix> kaEqn
2181  (
2182  fvm::div(-phi, ka())
2183  + fvm::SuSp(fvc::div(phi), ka())
2184  - fvm::laplacian(DkEff_, ka())
2185  + fvm::Sp(betaStar_*omega(), ka())
2186  - case_2_Pk_()*c1_*betaStar_*omega()()*ka()()
2187  + fvm::SuSp(scalar(2.0/3.0)*divU, ka())
2189  + kaEqnSourceFromF1()
2190  + dR_dnut()*dnut_dk_()
2191  - zeroFirstCell_()*gamma_*dGPrime_dk().ref()()*wa()
2192  );
2193 
2194  kaEqn.ref().relax();
2195  kaEqn.ref().boundaryManipulate(ka().boundaryFieldRef());
2196  addWallFunctionTerms(kaEqn.ref(), dR_dnut);
2197  // Add sources from the objective functions
2198  objectiveManager_.addTMEqn1Source(kaEqn.ref());
2199 
2200  kaEqn.ref().solve();
2201 
2203  {
2204  dimensionedScalar maxwa = max(mag(wa()));
2206  Info<< "Max mag of adjoint dissipation = " << maxwa.value() << endl;
2207  Info<< "Max mag of adjoint kinetic energy = " << maxka.value() << endl;
2208  }
2209 }
2210 
2213 {
2214  return adjMomentumBCSourcePtr_();
2215 }
2216 
2217 
2219 {
2222 
2223  forAll(mesh_.boundary(), patchi)
2224  {
2225  vectorField nf(mesh_.boundary()[patchi].nf());
2226  wallShapeSens[patchi] = nf & FITerm.boundaryField()[patchi];
2227  }
2228  return wallShapeSens;
2229 }
2230 
2233 {
2234  return wallFloCoSensitivitiesPtr_();
2235 }
2236 
2237 
2239 {
2241  (
2242  IOobject
2243  (
2244  "adjointEikonalSource" + type(),
2245  runTime_.timeName(),
2246  mesh_,
2249  ),
2250  mesh_,
2252  );
2253 }
2254 
2255 
2257 {
2258  const volVectorField& U = primalVars_.U();
2259  const volScalarField& kInst =
2260  primalVars_.RASModelVariables()->TMVar1Inst();
2261  const volScalarField& omegaInst =
2262  primalVars_.RASModelVariables()->TMVar2Inst();
2263 
2264  tmp<volScalarField> arg1 = min
2265  (
2266  min
2267  (
2268  max
2269  (
2270  (scalar(1)/betaStar_)*sqrt(k())/(omega()*y_),
2271  scalar(500)*nu()/(sqr(y_)*omega())
2272  ),
2273  (4*alphaOmega2_)*k()/(CDkOmegaPlus_*sqr(y_))
2274  ),
2275  scalar(10)
2276  );
2277 
2278  // Interpolation schemes used by the primal convection terms
2279  auto kScheme(convectionScheme(kInst.name()));
2280  auto omegaScheme(convectionScheme(omegaInst.name()));
2281  const surfaceVectorField& Sf = mesh_.Sf();
2282  tmp<volTensorField> tFISens
2283  (
2285  (
2286  IOobject
2287  (
2288  type() + "FISensTerm",
2289  mesh_.time().timeName(),
2290  mesh_,
2293  ),
2294  mesh_,
2296  zeroGradientFvPatchTensorField::typeName
2297  )
2298  );
2299  volTensorField& FISens = tFISens.ref();
2300  FISens =
2301  // k convection
2302  - ka()*fvc::div
2303  (
2304  kScheme().interpolate(k())
2306  )
2307  // k diffusion
2308  + ka()*T(fvc::grad(DkEff_*gradK_))
2309  - DkEff_*(fvc::grad(ka())*gradK_)
2310  // omega convection
2312  (
2313  omegaScheme().interpolate(omega())
2315  )
2316  // omega diffusion
2319  // terms including GbyNu0
2320  + (
2322  + case_1_Pk_*ka()*nutRef()
2324  // S2 (includes contribution from nut in UEqn as well)
2325  + (
2326  dR_dnut()*a1_*k()/(b1_*S_*S_*S_*F2_)
2328  *(c1_/a1_)*betaStar_*omega()*b1_*F2_/S_
2329  )*T(gradU_ & twoSymm(gradU_))*(1. - case_1_nut_)
2330  // CDkOmega in omegaEqn
2331  + 2.*wa()*(1. - F1_)*alphaOmega2_/omega()*zeroFirstCell_
2333  // F1
2334  - dR_dF1()
2335  *(dF1_dGradK(arg1)*gradK_ + dF1_dGradOmega(arg1)*gradOmega_);
2336 
2337  FISens.correctBoundaryConditions();
2338 
2339  return tFISens;
2340 }
2341 
2342 
2344 (
2345  const word& designVarsName
2346 ) const
2347 {
2348  // Missing proper terms - return zero for now
2350 }
2351 
2352 
2354 {
2357 }
2358 
2359 
2361 {
2362  if (adjointRASModel::read())
2363  {
2365  alphaK1_.readIfPresent(this->coeffDict());
2366  alphaK2_.readIfPresent(this->coeffDict());
2369  gamma1_.readIfPresent(this->coeffDict());
2370  gamma2_.readIfPresent(this->coeffDict());
2371  beta1_.readIfPresent(this->coeffDict());
2372  beta2_.readIfPresent(this->coeffDict());
2374  a1_.readIfPresent(this->coeffDict());
2375  b1_.readIfPresent(this->coeffDict());
2376  c1_.readIfPresent(this->coeffDict());
2377  F3_.readIfPresent("F3", this->coeffDict());
2378 
2379  return true;
2380  }
2381  else
2382  {
2383  return false;
2384  }
2385 }
2386 
2387 
2388 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
2389 
2390 } // End namespace adjointRASModels
2391 } // End namespace incompressible
2392 } // End namespace Foam
2393 
2394 // ************************************************************************* //
volScalarField DOmegaEff_
Diffusivity of the omega equation.
virtual tmp< volScalarField > GbyNu(const volScalarField &GbyNu0, const volScalarField &F2, const volScalarField &S2) const
tmp< volVectorField > nutMeanFlowSource(tmp< volScalarField > &mult, const volScalarField &F2, const volScalarField &S, const volScalarField &case_1_nut, const volTensorField &gradU) const
Contributions from nut(U)
dimensionedScalar tanh(const dimensionedScalar &ds)
virtual const boundaryVectorField & wallShapeSensitivities()
Sensitivity derivative contributions when using the (E)SI approach.
const Type & value() const noexcept
Return const reference to value.
virtual void addTMEqn1Source(fvScalarMatrix &adjTMEqn1)=0
Add contribution to first adjoint turbulence model PDE.
tmp< GeometricField< typename outerProduct< vector, Type >::type, fvPatchField, volMesh >> grad(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
Definition: fvcGrad.C:47
bool includeDistance_
Does the turbulence model include distances and should the adjoint to the distance field be computed...
tmp< volScalarField > dnut_dk(const volScalarField &F2, const volScalarField &S, const volScalarField &case_2_nut) const
Nut Jacobian wrt k.
virtual tmp< scalarField > topologySensitivities(const word &designVarsName) const
const surfaceVectorField & Sf() const
Return cell face area vectors.
tmp< volVectorField > dF1_dGradK(const volScalarField &arg1) const
F1 Jacobian wrt grad(k)
fvPatchField< vector > fvPatchVectorField
virtual tmp< Field< Type > > snGrad() const
Return patch-normal gradient.
Definition: fvPatchField.C:174
dimensionedScalar log(const dimensionedScalar &ds)
Inversed weight central-differencing interpolation scheme class.
Definition: reverseLinear.H:53
tmp< volScalarField > dF2_domega(const volScalarField &F2, const volScalarField &case_2_nut, const volScalarField &case_3_nut) const
F2 Jacobian wrt omega.
tmp< volScalarField > diffusionNutMeanFlowMult(const volScalarField &primalField, const volScalarField &adjointField, const volScalarField &coeffField) const
Contributions from nut(U), in the diffusion coefficients of the turbulence model. ...
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:132
tmp< volVectorField > dF1_dGradOmega(const volScalarField &arg1) const
F1 Jacobian wrt grad(omega)
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:120
tmp< volScalarField > waEqnSourceFromF1() const
Source to waEqn from the differentiation of F1.
Central-differencing interpolation scheme class.
Definition: linear.H:51
const word & name() const noexcept
Return the object name.
Definition: IOobjectI.H:150
tmp< surfaceScalarField > flux(const volVectorField &vvf)
Return the face-flux field obtained from the given volVectorField.
const dimensionedScalar G
Newtonian constant of gravitation.
bool interpolate(const vector &p1, const vector &p2, const vector &o, vector &n, scalar l)
Definition: curveTools.C:75
const wallFunctionCoefficients & wallCoeffs() const noexcept
Return wallFunctionCoefficients.
T & ref() const
Return non-const reference to the contents of a non-null managed pointer.
Definition: tmpI.H:210
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
dimensionedSymmTensor sqr(const dimensionedVector &dv)
tmp< GeometricField< Type, fvPatchField, volMesh > > div(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
Definition: fvcDiv.C:42
bool readIfPresent(const dictionary &dict)
Update the value of dimensioned<Type> if found in the dictionary, lookup in dictionary with the name(...
class for managing incompressible objective functions.
virtual bool read()
Read adjointRASProperties dictionary.
virtual tmp< volSymmTensorField > devReff() const
Return the effective stress tensor including the laminar stress.
volScalarField dnut_domega_
Nut Jacobian w.r.t. omega.
static tmp< edgeInterpolationScheme< Type > > scheme(const edgeScalarField &faceFlux, Istream &schemeData)
Return weighting factors for scheme given from Istream.
GeometricField< vector, fvsPatchField, surfaceMesh > surfaceVectorField
tmp< volScalarField > kaEqnSourceFromF1() const
Source to kaEqn from the differentiation of F1.
dimensioned< vector > dimensionedVector
Dimensioned vector obtained from generic dimensioned type.
dimensionedScalar sqrt(const dimensionedScalar &ds)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:487
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:68
dimensionedScalar pow025(const dimensionedScalar &ds)
virtual const boundaryVectorField & wallFloCoSensitivities()
Sensitivity terms for flow control, emerging from the.
tmp< volScalarField > dF1_domega(const volScalarField &arg1) const
F1 Jacobian wrt omega (no contributions from grad(omega))
tmp< volVectorField > GMeanFlowSource(tmp< volSymmTensorField > &GbyNuMult) const
Contributions from the G.
A simple wrapper around bool so that it can be read as a word: true/false, on/off, yes/no, any/none. Also accepts 0/1 as a string and shortcuts t/f, y/n.
Definition: Switch.H:77
static void nullifyField(GeometricField< Type, PatchField, GeoMesh > &fieldPtr)
Nullify field and old times, if present.
#define F2(B, C, D)
Definition: SHA1.C:150
const surfaceScalarField & phiInst() const
Return const reference to volume flux.
autoPtr< boundaryVectorField > adjMomentumBCSourcePtr_
Source to the adjoint momentum BC emerging from differentiating the turbulence model.
tmp< volScalarField::Internal > beta(const volScalarField::Internal &F1) const
virtual tmp< volVectorField > adjointMeanFlowSource()
Source term added to the adjoint mean flow due to the differentiation of the turbulence model...
Generic dimensioned Type class.
Ignore writing from objectRegistry::writeObject()
const dimensionSet dimless
Dimensionless.
autoPtr< boundaryVectorField > wallShapeSensitivitiesPtr_
Wall sensitivity term for shape optimisation.
Smooth ATC in cells next to a set of patches supplied by type.
Definition: faceCells.H:52
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:361
const DimensionedField< scalar, volMesh > & V() const
Return cell volumes.
tmp< volScalarField > kaEqnSourceFromCDkOmega() const
Source to kaEqn from the differentiation of CDkOmega.
virtual tmp< volScalarField > nutJacobianTMVar1() const
Jacobian of nut wrt to k.
GeometricField< vector, fvPatchField, volMesh > volVectorField
Definition: volFieldsFwd.H:85
virtual tmp< volScalarField > distanceSensitivities()
Contributions to the adjoint eikonal equation (zero for now)
tmp< volScalarField > alphaK(const volScalarField &F1) const
const dimensionedScalar kappa
Coulomb constant: default SI units: [N.m2/C2].
tmp< volScalarField > alphaOmega(const volScalarField &F1) const
dimensionedScalar neg(const dimensionedScalar &ds)
tmp< volVectorField > convectionMeanFlowSource(const volScalarField &primalField, const volScalarField &adjointField) const
Contributions from the turbulence model convection terms.
Macros for easy insertion into run-time selection tables.
dimensionedSymmTensor twoSymm(const dimensionedSymmTensor &dt)
tmp< volScalarField > nu() const
Return the laminar viscosity.
tmp< volScalarField > DkEff(const volScalarField &F1) const
Return the effective diffusivity for k.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:413
void addWallFunctionTerms(fvScalarMatrix &kaEqn, const volScalarField &dR_dnut)
Contributions from the differentiation of k existing in nutkWallFunction.
Switch adjointTurbulence_
Turbulence on/off flag.
tmp< surfaceInterpolationScheme< scalar > > convectionScheme(const word &varName) const
Return the interpolation scheme used by the primal convection term of the equation corresponding to t...
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:84
autoPtr< boundaryVectorField > wallFloCoSensitivitiesPtr_
Wall sensitivity term for flow control optimisation.
word timeName
Definition: getTimeIndex.H:3
dimensionedScalar pos(const dimensionedScalar &ds)
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: POSIX.C:752
const surfaceScalarField & phi() const
Return const reference to volume flux.
Base class for solution control classes.
bool changedPrimalSolution_
Has the primal solution changed?
The class nutWallFunction is an abstract base class that hosts calculation methods and common functi...
const dimensionedScalar e
Elementary charge.
Definition: createFields.H:11
void setSize(const label n)
Alias for resize()
Definition: List.H:289
virtual tmp< volScalarField > nutJacobianTMVar2() const
Jacobian of nut wrt to omega.
dimensionedSymmTensor dev(const dimensionedSymmTensor &dt)
virtual void correct()
Solve the adjoint turbulence equations.
bool useSolverNameForFields() const
Append solver name to fields?
Definition: variablesSet.C:83
virtual tmp< volTensorField > FISensitivityTerm()
Sensitivity derivative contributions when using the FI approach.
tmp< volScalarField > DomegaEff(const volScalarField &F1) const
Return the effective diffusivity for omega.
fvPatchField< scalar > fvPatchScalarField
volTensorField gradU_
Cached primal gradient fields.
A class for handling words, derived from Foam::string.
Definition: word.H:63
static tmp< surfaceInterpolationScheme< Type > > New(const fvMesh &mesh, Istream &schemeData)
Return new tmp interpolation scheme.
virtual tmp< fvVectorMatrix > divDevReff(volVectorField &U) const
Return the transpose part of the adjoint momentum stresses.
Abstract base class for incompressible turbulence models.
bool printMaxMags() const
Print max mags of solver fields.
dimensionedScalar neg0(const dimensionedScalar &ds)
GeometricField< tensor, fvsPatchField, surfaceMesh > surfaceTensorField
tmp< volVectorField > divUMeanFlowSource(tmp< volScalarField > &divUMult) const
Contributions from the divU.
static tmp< T > New(Args &&... args)
Construct tmp with forwarding arguments.
Definition: tmp.H:203
tmp< volScalarField > dR_dnut()
Derivative of the primal equations wrt nut.
A special matrix type and solver, designed for finite volume solutions of scalar equations. Face addressing is used to make all matrix assembly and solution loops vectorise.
Definition: fvPatchField.H:64
zeroField SuSp(const Foam::zero, const GeometricField< Type, fvPatchField, volMesh > &)
A no-op source.
wordList adjointTMVariablesBaseNames_
Base names of the adjoint fields.
addToRunTimeSelectionTable(adjointRASModel, adjointkOmegaSST, dictionary)
dimensioned< tensor > dimensionedTensor
Dimensioned tensor obtained from generic dimensioned type.
autoPtr< volScalarField > adjointTMVariable1Ptr_
Adjoint turbulence model variable 1.
virtual void nullify()
Nullify all adjoint turbulence model fields and their old times.
const word & solverName() const
Return solver name.
Definition: variablesSet.C:77
virtual void correct()
Solve the adjoint turbulence equations.
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:26
autoPtr< volScalarField > adjointTMVariable2Ptr_
Adjoint turbulence model variable 2.
zeroField Sp(const Foam::zero, const GeometricField< Type, fvPatchField, volMesh > &)
A no-op source.
tmp< volScalarField > dNutdbMult(const volScalarField &primalField, const volScalarField &adjointField, const volScalarField &coeffField, const volScalarField &bcField, const word &schemeName) const
Term multiplying dnut/db, coming from the turbulence model.
virtual tmp< volVectorField > nutJacobianU(tmp< volScalarField > &dNutdUMult) const
Jacobian of nut wrt the flow velocity.
const volVectorField & U() const
Return const reference to velocity.
volScalarField DkEff_
Diffusivity of the k equation.
volScalarField case_1_Pk_
Switch fields for the production in the k Eqn.
virtual void addTMEqn2Source(fvScalarMatrix &adjTMEqn2)=0
Add contribution to second adjoint turbulence model PDE.
const surfaceScalarField & magSf() const
Return cell face area magnitudes.
dimensionedScalar pos0(const dimensionedScalar &ds)
virtual const volScalarField & nut() const
Return the turbulence viscosity.
SolverPerformance< Type > solve(const dictionary &)
Solve returning the solution statistics.
static word timeName(const scalar t, const int precision=precision_)
Return time name of given scalar time formatted with the given precision.
Definition: Time.C:760
tmp< fvMatrix< Type > > div(const surfaceScalarField &flux, const GeometricField< Type, fvPatchField, volMesh > &vf, const word &name)
Definition: fvmDiv.C:41
virtual tmp< Field< Type > > patchInternalField() const
Return internal field next to patch as patch field.
Definition: fvPatchField.C:182
rDeltaT ref()
const dictionary & coeffDict() const
Const access to the coefficients dictionary.
tmp< volScalarField > dF1_dk(const volScalarField &arg1) const
F1 Jacobian wrt k (no contributions from grad(k))
UPtrList< const labelUList > faceCells() const
Return a list of faceCells for each patch.
void relax(const scalar alpha)
Relax matrix (for steady-state solution).
Definition: fvMatrix.C:1100
scalar Cmu() const noexcept
Return the object: Cmu.
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
const solverControl & getSolverControl() const
Return const reference to solverControl.
tmp< volScalarField > dF2_dk(const volScalarField &F2, const volScalarField &case_2_nut) const
F2 Jacobian wrt k.
tmp< fvScalarMatrix > waEqnSourceFromCDkOmega() const
Source to waEqn from the differentiation of CDkOmega.
const autoPtr< incompressible::RASModelVariables > & RASModelVariables() const
Return const reference to the turbulence model variables.
Manages the adjoint mean flow fields and their mean values.
Continuous adjoint to the kOmegaSST turbulence model for incompressible flows.
const volVectorField & UaInst() const
Return const reference to velocity.
Field< tensor > tensorField
Specialisation of Field<T> for tensor.
Field< Type > & source() noexcept
Definition: fvMatrix.H:534
virtual tmp< scalarField > diffusionCoeffVar1(label patchI) const
Diffusion coeff at the boundary for k.
dimensionedScalar pow3(const dimensionedScalar &ds)
dimensionedSymmTensor dev2(const dimensionedSymmTensor &dt)
tmp< surfaceScalarField > absolute(const tmp< surfaceScalarField > &tphi, const volVectorField &U)
Return the given relative flux in absolute form.
Definition: fvcMeshPhi.C:183
U
Definition: pEqn.H:72
tmp< volScalarField > coeffsDifferentiation(const volScalarField &primalField, const volScalarField &adjointField, const word &schemeName) const
Differentiation of the turbulence model diffusion coefficients.
This boundary condition provides a wall function for the specific dissipation rate (i...
ITstream & divScheme(const word &name) const
Get div scheme for given name, or default.
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:50
dimensionedSymmTensor symm(const dimensionedSymmTensor &dt)
void updatePrimalRelatedFields()
Update of the primal cached fields.
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
label nCells() const noexcept
Number of mesh cells.
tmp< fvMatrix< Type > > laplacian(const GeometricField< Type, fvPatchField, volMesh > &vf, const word &name)
Definition: fvmLaplacian.C:41
scalar yPlus
IOobject(const IOobject &)=default
Copy construct.
tmp< volScalarField > dnut_domega(const volScalarField &F2, const volScalarField &S, const volScalarField &case_1_nut, const volScalarField &case_2_nut, const volScalarField &case_3_nut) const
Nut Jacobian wrt omega.
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
Definition: areaFieldsFwd.H:42
dimensionedScalar pow4(const dimensionedScalar &ds)
Nothing to be read.
const std::string patch
OpenFOAM patch number as a std::string.
const dimensionSet dimTime(0, 0, 1, 0, 0, 0, 0)
Definition: dimensionSets.H:51
tmp< volScalarField::Internal > gamma(const volScalarField::Internal &F1) const
Boundary & boundaryFieldRef(const bool updateAccessTime=true)
Return a reference to the boundary field.
virtual tmp< scalarField > diffusionCoeffVar2(label patchI) const
Diffusion coeff at the boundary for omega.
messageStream Info
Information stream (stdout output on master, null elsewhere)
objectiveManager & objectiveManager_
Reference to the objectiveManager.
Internal & ref(const bool updateAccessTime=true)
Same as internalFieldRef()
const autoPtr< incompressible::turbulenceModel > & turbulence() const
Return const reference to the turbulence model.
Field< vector > vectorField
Specialisation of Field<T> for vector.
virtual tmp< volVectorField > nonConservativeMomentumSource() const
Non-conservative part of the terms added to the mean flow equations.
void clear() const noexcept
If object pointer points to valid object: delete object and set pointer to nullptr.
Definition: tmpI.H:263
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
Definition: HashPtrTable.H:48
void boundaryManipulate(typename GeometricField< Type, fvPatchField, volMesh >::Boundary &values)
Manipulate based on a boundary field.
Definition: fvMatrix.C:1265
scalar kb
tmp< volScalarField > dGPrime_dk() const
GbyNu Jacobian wrt k.
virtual tmp< volScalarField > nuEff() const
Return the effective viscosity.
zeroField divU
Definition: alphaSuSp.H:3
List< label > labelList
A List of labels.
Definition: List.H:62
A class for managing temporary objects.
Definition: HashPtrTable.H:50
volScalarField S2_
Primal cached fields involved in the solution of the.
Class to host the wall-function coefficients being used in the wall function boundary conditions...
virtual bool read()
Read adjointRASProperties dictionary.
Defines the attributes of an object for which implicit objectRegistry management is supported...
Definition: IOobject.H:166
const nearWallDist & y() const
Return the near wall distances.
const Boundary & boundaryField() const noexcept
Return const-reference to the boundary field.
tmp< volScalarField > dGPrime_domega() const
GbyNu Jacobian wrt omega.
virtual const boundaryVectorField & adjointMomentumBCSource() const
Source for the outlet adjoint momentum BC coming from differentiating the turbulence model...
bool readIfPresent(const word &key, const dictionary &dict)
Update the value of the Switch if it is found in the dictionary.
Definition: Switch.C:331
#define M(I)
tmp< volScalarField > dR_dF1() const
Derivative of the primal equations wrt F1.
dimensioned< typename typeOfMag< Type >::type > magSqr(const dimensioned< Type > &dt)
tmp< GeometricField< Type, fvsPatchField, surfaceMesh > > snGrad(const GeometricField< Type, fvPatchField, volMesh > &vf, const word &name)
Definition: fvcSnGrad.C:40
An input stream of tokens.
Definition: ITstream.H:48
scalar nut
static void setField(autoPtr< GeometricField< Type, fvPatchField, volMesh >> &fieldPtr, const fvMesh &mesh, const word &baseName, const word &solverName, const bool useSolverNameForFields)
Read vol fields.
const dimensionSet dimArea(sqr(dimLength))
Definition: dimensionSets.H:57
Namespace for OpenFOAM.
A class representing the concept of 1 (one) that can be used to avoid manipulating objects known to b...
Definition: one.H:57
const fvBoundaryMesh & boundary() const
Return reference to boundary mesh.
Definition: fvMesh.C:705
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:157
const dimensionSet dimVelocity