adjointSpalartAllmaras.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) 2007-2021 PCOpt/NTUA
9 Copyright (C) 2013-2021 FOSS GP
10 Copyright (C) 2019-2020 OpenCFD Ltd.
11-------------------------------------------------------------------------------
12License
13 This file is part of OpenFOAM.
14
15 OpenFOAM is free software: you can redistribute it and/or modify it
16 under the terms of the GNU General Public License as published by
17 the Free Software Foundation, either version 3 of the License, or
18 (at your option) any later version.
19
20 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
21 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
22 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 for more details.
24
25 You should have received a copy of the GNU General Public License
26 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
27
28\*---------------------------------------------------------------------------*/
29
32#include "wallDist.H"
33#include "wallFvPatch.H"
36#include "coupledFvPatch.H"
37#include "ATCModel.H"
38
39// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
40
41namespace Foam
42{
43namespace incompressibleAdjoint
44{
45namespace adjointRASModels
46{
47
48// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
49
52(
56);
57
58
59// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
60
61// * * * * * * * * * * * * Primal Spalart - Allmaras * * * * * * * * * * * * //
62
64{
65 return nuTilda()/nu();
66}
67
68
70{
71 const volScalarField chi3(pow3(chi));
72 return chi3/(chi3 + pow3(Cv1_));
73}
74
75
77(
78 const volScalarField& chi,
79 const volScalarField& fv1
80) const
81{
82 return 1.0 - chi/(1.0 + chi*fv1);
83}
84
85
87(
88 const volScalarField& chi,
89 const volScalarField& fv1
90) const
91{
92 volScalarField Omega(::sqrt(2.0)*mag(skew(gradU_)));
93
94 return
95 (
96 max
97 (
98 Omega
99 + fv2(chi, fv1)*nuTilda()/sqr(kappa_*y_),
100 Cs_*Omega
101 )
102 );
103}
104
105
107(
108 const volScalarField& Stilda
109) const
110{
111 auto tr =
113 (
114 min
115 (
117 scalar(10)
118 )
119 );
120 tr.ref().boundaryFieldRef() == Zero;
121
122 return tr;
123}
124
125
127(
128 const volScalarField& Stilda
129) const
130{
131 const volScalarField g(r_ + Cw2_*(pow6(r_) - r_));
132
133 return g*pow((1.0 + pow6(Cw3_))/(pow6(g) + pow6(Cw3_)), 1.0/6.0);
134}
135
136
138{
139 return
141 ("DnuTildaEff", (nuTilda() + this->nu())/sigmaNut_);
142}
143
144
146{
147 return primalVars_.RASModelVariables()().TMVar1();
148}
149
150
152{
153 return primalVars_.RASModelVariables()().nutRef();
154}
155
156
157// * * * * * * * * * * * Adjoint Spalart - Allmaras * * * * * * * * * * * * //
158
160(
161 const volScalarField& chi
162) const
163{
164 volScalarField chi3(pow3(chi));
165
166 return 3.0*pow3(Cv1_)*sqr(chi/(chi3 + pow3(Cv1_)));
167}
168
169
171(
172 const volScalarField& chi,
173 const volScalarField& fv1,
174 const volScalarField& dFv1dChi
175) const
176{
177 return (chi*chi*dFv1dChi - 1.)/sqr(1. + chi*fv1);
178}
179
180
182(
183 const volScalarField& Omega,
184 const volScalarField& fv2
185) const
186{
187 volScalarField fieldSwitch
188 (
189 Omega + fv2*nuTilda()/sqr(kappa_*y_) - Cs_*Omega
190 );
191
192 return pos(fieldSwitch) + neg(fieldSwitch)*Cs_;
193}
194
195
197(
198 const volScalarField& Omega,
199 const volScalarField& fv2,
200 const volScalarField& dFv2dChi
201) const
202{
203 volScalarField invDenom(1./sqr(kappa_*y_));
204 volScalarField fieldSwitch(Omega + fv2*nuTilda()*invDenom - Cs_*Omega);
205
206 return pos(fieldSwitch)*(dFv2dChi*nuTilda()*invDenom/nu() + fv2*invDenom);
207}
208
209
211(
212 const volScalarField& Omega,
213 const volScalarField& fv2
214) const
215{
217 volScalarField fieldSwitch(Omega + aux - Cs_*Omega);
218
219 return - 2.*pos(fieldSwitch)*aux/y_;
220}
221
222
224(
225 const volScalarField& Stilda
226) const
227{
228 tmp<volScalarField> tdrdNutilda
229 (
231 *(scalar(10) - r_)/(scalar(10) - r_ + SMALL)
232 );
233 tdrdNutilda.ref().boundaryFieldRef() == Zero;
234
235 return tdrdNutilda;
236}
237
238
240(
241 const volScalarField& Stilda
242) const
243{
244 tmp<volScalarField> tdrdStilda
245 (
247 *(scalar(10) - r_)/(scalar(10) - r_ + SMALL)
248 );
249 tdrdStilda.ref().boundaryFieldRef() == Zero;
250
251 return tdrdStilda;
252}
253
254
256(
257 const volScalarField& Stilda
258) const
259{
260 tmp<volScalarField> tdrdDelta
261 (
263 *(scalar(10) - r_)/(scalar(10) - r_ + SMALL)
264 );
265 tdrdDelta.ref().boundaryFieldRef() == Zero;
266
267 return tdrdDelta;
268}
269
270
272(
273 const volScalarField& Stilda
274) const
275{
276 volScalarField g(r_ + Cw2_*(pow6(r_) - r_));
277
278 dimensionedScalar pow6Cw3 = pow6(Cw3_);
279 volScalarField pow6g(pow6(g));
280
281 return
282 pow6Cw3/(pow6g + pow6Cw3)
283 *pow((1.0 + pow6Cw3)/(pow6g + pow6Cw3), 1.0/6.0)
284 *(1.0 + Cw2_*(6.0*pow5(r_) - 1.0));
285}
286
287
289(
290 const volScalarField& Stilda,
291 const volScalarField& dfwdr,
292 const volScalarField& dStildadNuTilda
293) const
294{
295 volScalarField invDenom(1./sqr(kappa_*y_));
296
297 return
298 dfwdr*(dr_dNuTilda(Stilda) + dr_dStilda(Stilda)*dStildadNuTilda);
299}
300
301
303(
304 const volScalarField& Stilda,
305 const volScalarField& dfwdr,
306 const volScalarField& dStildadOmega
307) const
308{
309 return dfwdr*dr_dStilda(Stilda)*dStildadOmega;
310}
311
312
314(
315 const volScalarField& Stilda,
316 const volScalarField& dfwdr,
317 const volScalarField& dStildadDelta
318) const
319{
320 return dfwdr*(dr_dDelta(Stilda) + dr_dStilda(Stilda)*dStildadDelta);
321}
322
323
325(
326 const volScalarField& fw,
327 const volScalarField& dfwdNuTilda
328) const
329{
330 return Cw1_*(nuTilda()*dfwdNuTilda + fw)/sqr(y_);
331}
332
333
335(
336 const volScalarField& dStildadNuTilda
337) const
338{
339 return - Cb1_*dStildadNuTilda;
340}
341
342
344(
345 const volScalarField& fv1,
346 const volScalarField& dFv1dChi
347) const
348{
349 return dFv1dChi*nuTilda()/nu() + fv1;
350}
351
352
354{
355 // Store boundary field of the conservative part,
356 // for use in adjoint outlet boundary conditions
357 forAll(mesh_.boundary(), pI)
358 {
359 const fvPatch& patch = mesh_.boundary()[pI];
360 if(!isA<coupledFvPatch>(patch))
361 {
362 tmp<vectorField> tnf = patch.nf();
365 *nuaTilda().boundaryField()[pI];
366 }
367 }
368
370}
371
372
374{
376 {
377 Info<< "Updating primal-based fields of the adjoint turbulence "
378 << "model ..." << endl;
379
380 // Grab references
381 const volVectorField& U = primalVars_.U();
382
383 // Update gradient fields
384 gradU_ = mask_*fvc::grad(U, "gradUStilda");
386
387 const volScalarField Omega(::sqrt(2.0)*mag(skew(gradU_)));
388
389 // Primal SA fields
390 volScalarField chi(this->chi());
391 volScalarField fv1(this->fv1(chi));
392 volScalarField fv2(this->fv2(chi, fv1));
393 Stilda_ = Stilda(chi, fv1);
394 r_ = r(Stilda_);
395 fw_ = this->fw(Stilda_);
396
397 // Derivatives of primal fields wrt to nuTilda
401 (this->dStilda_dNuTilda(Omega, fv2, dFv2_dChi));
404 (this->dfw_dNuTilda(Stilda_, dfw_dr, dStilda_dNuTilda));
405
406 // Fields to be used in the nuaTilda equation
408 symm(mask_*fvc::grad(U, "adjointProductionU"));
409
411 nuTilda()
412 *(
415 );
416
418
419 // Constant multiplier in the adjoint momentum source term
422 (this->dfw_dOmega(Stilda_, dfw_dr, dStilda_dOmega));
423
425 2.*skew(gradU_)
426 /(Omega + dimensionedScalar("SMALL", Omega.dimensions(), SMALL))
427 *(
430 );
431
432 // Set changedPrimalSolution_ to false to avoid recomputing these
433 // fields unless the primal has changed
435 }
436}
437
438
440{
443 {
445 }
446 else
447 {
449 (
451 (
453 (
454 "unitMask",
455 mesh_.time().timeName(),
456 mesh_,
459 ),
460 mesh_,
461 dimensionedScalar("unit", dimless, scalar(1))
462 )
463 );
464 }
465
466 return mask;
467}
468
469
470// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
471
473(
474 incompressibleVars& primalVars,
476 objectiveManager& objManager,
477 const word& adjointTurbulenceModelName,
478 const word& modelName
479)
480:
482 (
483 modelName,
484 primalVars,
485 adjointVars,
486 objManager,
487 adjointTurbulenceModelName
488 ),
489
490 sigmaNut_
491 (
492 dimensioned<scalar>::getOrAddToDict
493 (
494 "sigmaNut",
495 this->coeffDict_,
496 0.66666
497 )
498 ),
499 kappa_
500 (
501 dimensioned<scalar>::getOrAddToDict
502 (
503 "kappa",
504 this->coeffDict_,
505 0.41
506 )
507 ),
508
509 Cb1_
510 (
511 dimensioned<scalar>::getOrAddToDict
512 (
513 "Cb1",
514 this->coeffDict_,
515 0.1355
516 )
517 ),
518 Cb2_
519 (
520 dimensioned<scalar>::getOrAddToDict
521 (
522 "Cb2",
523 this->coeffDict_,
524 0.622
525 )
526 ),
527 Cw1_(Cb1_/sqr(kappa_) + (1.0 + Cb2_)/sigmaNut_),
528 Cw2_
529 (
530 dimensioned<scalar>::getOrAddToDict
531 (
532 "Cw2",
533 this->coeffDict_,
534 0.3
535 )
536 ),
537 Cw3_
538 (
539 dimensioned<scalar>::getOrAddToDict
540 (
541 "Cw3",
542 this->coeffDict_,
543 2.0
544 )
545 ),
546 Cv1_
547 (
548 dimensioned<scalar>::getOrAddToDict
549 (
550 "Cv1",
551 this->coeffDict_,
552 7.1
553 )
554 ),
555 Cs_
556 (
557 dimensioned<scalar>::getOrAddToDict
558 (
559 "Cs",
560 this->coeffDict_,
561 0.3
562 )
563 ),
564
565 limitAdjointProduction_
566 (
567 coeffDict_.getOrDefault("limitAdjointProduction", true)
568 ),
569
570 y_(primalVars_.RASModelVariables()().d()),
571
572 mask_(allocateMask()),
573
574 symmAdjointProductionU_
575 (
577 (
578 "symmAdjointProductionU",
579 runTime_.timeName(),
580 mesh_,
581 IOobject::NO_READ,
582 IOobject::NO_WRITE
583 ),
584 mesh_,
586 ),
587
588 productionDestructionSource_
589 (
591 (
592 "productionDestructionSource",
593 runTime_.timeName(),
594 mesh_,
595 IOobject::NO_READ,
596 IOobject::NO_WRITE
597 ),
598 mesh_,
600 ),
601
602 Stilda_
603 (
605 (
606 "Stilda",
607 runTime_.timeName(),
608 mesh_,
609 IOobject::NO_READ,
610 IOobject::NO_WRITE
611 ),
612 mesh_,
614 ),
615
616 r_
617 (
619 (
620 "r",
621 runTime_.timeName(),
622 mesh_,
623 IOobject::NO_READ,
624 IOobject::NO_WRITE
625 ),
626 mesh_,
628 ),
629
630 fw_
631 (
633 (
634 "fw",
635 runTime_.timeName(),
636 mesh_,
637 IOobject::NO_READ,
638 IOobject::NO_WRITE
639 ),
640 mesh_,
642 ),
643
644 Cdnut_
645 (
647 (
648 "Cdnut",
649 runTime_.timeName(),
650 mesh_,
651 IOobject::NO_READ,
652 IOobject::NO_WRITE
653 ),
654 mesh_,
656 ),
657
658 momentumSourceMult_
659 (
661 (
662 "momentumSourceMult",
663 runTime_.timeName(),
664 mesh_,
665 IOobject::NO_READ,
666 IOobject::NO_WRITE
667 ),
668 mesh_,
670 ),
671
672 gradU_(fvc::grad(primalVars.U())),
673 gradNuTilda_(fvc::grad(nuTilda())),
674 minStilda_("SMALL", Stilda_.dimensions(), SMALL)
675{
677 adjointTMVariablesBaseNames_[0] = "nuaTilda";
678 // Read nuaTilda field and reset pointer to the first
679 // adjoint turbulence model variable
681 (
683 mesh_,
684 "nuaTilda",
685 adjointVars.solverName(),
686 adjointVars.useSolverNameForFields()
687 );
688
690
691 // Set the includeDistance to true, to allow for the automatic solution
692 // of the adjoint eikonal equation when computing sensitivities
693 includeDistance_ = true;
694
695 // Update the primal related fields here so that functions computing
696 // sensitivities have the updated fields in case of continuation
698}
699
700
701// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
702
704{
705 const volVectorField& Ua = adjointVars_.UaInst();
706 return devReff(Ua);
707}
708
709
711(
712 const volVectorField& U
713) const
714{
715 return
717 (
719 (
720 "devRhoReff",
722 mesh_,
725 ),
727 );
728}
729
730
732{
733 tmp<volScalarField> tnuEff(nuEff());
734 const volScalarField& nuEff = tnuEff();
735
736 return
737 (
738 - fvm::laplacian(nuEff, Ua)
739 - fvc::div(nuEff*dev(fvc::grad(Ua)().T()))
740 );
741}
742
743
745{
747 (adjointSpalartAllmaras, "adjointSpalartAllmaras::addMomentumSource");
748 // cm formulation
749 //return (- nuTilda()*fvc::grad(nuaTilda() - conservativeMomentumSource());
750
751 // ncm formulation
753}
754
755
757{
758 volScalarField chi(this->chi());
759 volScalarField fv1(this->fv1(chi));
761
762 return dnut_dNuTilda(fv1, dFv1_dChi);
763}
764
765
767{
768 tmp<scalarField> tdiffCoeff
769 (
770 new scalarField(mesh_.boundary()[patchI].size(), Zero)
771 );
772
773 scalarField& diffCoeff = tdiffCoeff.ref();
774
775 diffCoeff =
776 (nuTilda().boundaryField()[patchI] + nu()().boundaryField()[patchI])
777 /sigmaNut_.value();
778
779 return tdiffCoeff;
780}
781
782
785{
786 // Computed in conservativeMomentumSource
788}
789
790
792{
794
795 forAll(mesh_.boundary(), patchI)
796 {
797 const fvPatch& patch = mesh_.boundary()[patchI];
798
799 tmp<vectorField> tnf = patch.nf();
800 if (isA<wallFvPatch>(patch) && patch.size() != 0)
801 {
802 wallShapeSens[patchI] =
803 - nuaTilda().boundaryField()[patchI].snGrad()
804 *diffusionCoeffVar1(patchI)
805 *nuTilda().boundaryField()[patchI].snGrad()*tnf;
806 }
807 }
808
809 return wallShapeSens;
810}
811
812
814{
816
817 forAll(mesh_.boundary(), patchI)
818 {
819 tmp<vectorField> tnf = mesh_.boundary()[patchI].nf();
820
821 wallFloCoSens[patchI] =
822 nuaTilda().boundaryField()[patchI]
823 *nuTilda().boundaryField()[patchI]*tnf;
824 }
825
826 return wallFloCoSens;
827}
828
829
831{
832 const volVectorField& U = primalVars_.U();
833 const volVectorField& Ua = adjointVars_.Ua();
834
835 // Primal SA fields
836 volScalarField chi(this->chi());
837 volScalarField fv1(this->fv1(chi));
838 volScalarField fv2(this->fv2(chi, fv1));
839 volScalarField Omega(::sqrt(2.0)*mag(gradU_));
840
841 // Derivatives of primal fields wrt to nuTilda
847 (this->dfw_dDelta(Stilda_, dfw_dr, dStilda_dDelta));
848
849 auto tadjointEikonalSource =
851 (
852 "adjointEikonalSource" + type(),
853 (
855 + Cw1_*sqr(nuTilda()/y_)*(dfw_dDelta - 2.*fw_/y_)
856 )*nuaTilda()
857 );
858 volScalarField& adjointEikonalSource = tadjointEikonalSource.ref();
859
860 // if wall functions are used, add appropriate source terms
862 SAwallFunctionPatchField;
863
864 const volScalarField::Boundary& nutBoundary = nut().boundaryField();
865 const scalarField& V = mesh_.V().field();
866
867 tmp<volScalarField> tnuEff = nuEff();
868 const volScalarField& nuEff = tnuEff();
869
870 forAll(nutBoundary, patchi)
871 {
872 const fvPatch& patch = mesh_.boundary()[patchi];
873 if
874 (
875 isA<SAwallFunctionPatchField>(nutBoundary[patchi])
876 && patch.size() != 0
877 )
878 {
879 const scalar kappa_(0.41);
880 const scalar E_(9.8);
881 tmp<vectorField> tnf = patch.nf();
882 const vectorField& nf = tnf.ref();
883 const scalarField& magSf = patch.magSf();
884
885 const fvPatchVectorField& Up = U.boundaryField()[patchi];
886 const fvPatchVectorField& Uap = Ua.boundaryField()[patchi];
887 const vectorField Uc(Up.patchInternalField());
888 const vectorField Uc_t(Uc - (Uc & nf)*nf);
889
890 // By convention, tf has the direction of the tangent
891 // PRIMAL velocity at the first cell off the wall
892 const vectorField tf(Uc_t/mag(Uc_t));
893
894 const scalarField nuw(nuEff.boundaryField()[patchi]);
895 const scalarField nu(this->nu()().boundaryField()[patchi]);
896 const fvPatchScalarField& yC = y()[patchi];
897
898 const scalarField magGradU(mag(Up.snGrad()));
899
900 // Note: What happens in separation?? sign change needed
901 const scalarField vtau(sqrt(nuw*magGradU));
902
903 // Note: mag for positive uPlus
904 const scalarField uPlus(mag(Uc)/vtau);
905
906 const scalarField yPlus(yC*vtau/nu);
907 const scalarField kUu(min(kappa_*uPlus, scalar(50)));
908 const scalarField auxA
909 ((kappa_/E_)*(exp(kUu) - 1 - kUu - 0.5*kUu*kUu));
910 const scalarField Cwf_d(sqr(vtau)/nu/(yPlus+uPlus*(1 + auxA)));
911
912 // Tangential components are according to tf
914 (
916 (
917 "objectiveManager" + objectiveManager_.adjointSolverName(),
919 "incompressible",
920 patch
921 )
922 );
923 tmp<vectorField> tsource(boundaryContrPtr->normalVelocitySource());
924
925 const scalarField rt(tsource() & tf);
926 const scalarField Uap_t(Uap & tf);
927
928 const labelList& faceCells = patch.faceCells();
929 forAll(faceCells, faceI)
930 {
931 label cellI = faceCells[faceI];
932 adjointEikonalSource[cellI] -=
933 2.*( rt[faceI] + Uap_t[faceI] )
934 *vtau[faceI]*Cwf_d[faceI]*magSf[faceI]
935 /V[cellI]; // Divide with cell volume since the term
936 // will be used as a source term in the
937 // adjoint eikonal equation
938 }
939 }
940 }
941
942 return tadjointEikonalSource;
943}
944
945
947{
948 const volVectorField& U = primalVars_.U();
949
951 const volTensorField& gradU = tgradU.cref();
952 tmp<volVectorField> tgradNuTilda = fvc::grad(nuTilda());
953 volVectorField& gradNuTilda = tgradNuTilda.ref();
954 tmp<volVectorField> tgradNuaTilda = fvc::grad(nuaTilda());
955 volVectorField::Boundary& gradNuaTildab =
956 tgradNuaTilda.ref().boundaryFieldRef();
957
958 // Explicitly correct the boundary gradient to get rid of
959 // the tangential component
960 forAll(mesh_.boundary(), patchI)
961 {
962 const fvPatch& patch = mesh_.boundary()[patchI];
963 if (isA<wallFvPatch>(patch))
964 {
965 tmp<vectorField> tnf = patch.nf();
966 const vectorField& nf = tnf();
967 // gradU:: can cause problems in zeroGradient patches for U
968 // and zero fixedValue for nuTilda.
969 // S becomes 0 and is used as a denominator in G
970 //gradU.boundaryField()[patchI] =
971 // nf * U_.boundaryField()[patchI].snGrad();
972 gradNuTilda.boundaryFieldRef()[patchI] =
973 nf*nuTilda().boundaryField()[patchI].snGrad();
974 gradNuaTildab[patchI] =
975 nf*nuaTilda().boundaryField()[patchI].snGrad();
976 }
977 }
978
979 // delta vorticity
980 volScalarField Omega(::sqrt(2.0)*mag(skew(gradU)));
981 volTensorField deltaOmega
982 (
983 (
984 (gradU & gradU)().T() //jk
985 - (gradU & gradU.T()) //symmetric
986 )
987 /(Omega + dimensionedScalar("SMALL", Omega.dimensions(), SMALL))
988 );
989 tgradU.clear();
990
991 volScalarField chi(this->chi());
992 volScalarField fv1(this->fv1(chi));
993 volScalarField fv2(this->fv2(chi, fv1));
994
998 (this->dfw_dOmega(Stilda_, dfw_dr, dStilda_dOmega));
999
1000 return
1002 (
1003 "volSensTerm",
1004 // jk, cm formulation for the TM model convection
1005 - (nuaTilda()*(U*gradNuTilda))
1006 // jk, symmetric in theory
1007 + nuaTilda()*fvc::grad(DnuTildaEff()*gradNuTilda)().T()
1008 // jk
1009 - DnuTildaEff()*(tgradNuaTilda*gradNuTilda)
1010 // symmetric
1011 + 2.*nuaTilda()*Cb2_/sigmaNut_*(gradNuTilda*gradNuTilda)
1012 + (
1015 )
1016 *nuaTilda()*deltaOmega // jk
1017 );
1018}
1019
1020
1022{
1024}
1025
1026
1028{
1030 (adjointSpalartAllmaras, "adjointSpalartAllmaras::correct");
1031 if (!adjointTurbulence_)
1032 {
1033 return;
1034 }
1035
1037
1039
1041 const volVectorField& Ua = adjointVars_.UaInst();
1042
1044 volScalarField gradUaR
1045 (
1047 );
1048
1049 dimensionedScalar oneOverSigmaNut = 1./sigmaNut_;
1050
1052
1053 tmp<fvScalarMatrix> nuaTildaEqn
1054 (
1056 + fvm::div(-phi, nuaTilda())
1058 // Note: Susp
1060 + fvc::laplacian(2.0*Cb2_*oneOverSigmaNut*nuaTilda(), nuTilda())
1061 + gradNua*oneOverSigmaNut
1062 ==
1063 // always a negative contribution to the lhs. No Sp used!
1065 //always a positive contribution to the lhs. no need for SuSp
1067 - Cdnut_*gradUaR
1068 );
1069
1070 // Add sources from the objective functions
1071 objectiveManager_.addTMEqn1Source(nuaTildaEqn.ref());
1072
1073 nuaTildaEqn.ref().relax();
1074 solve(nuaTildaEqn);
1076 nuaTilda().relax();
1077
1079 {
1080 scalar maxDeltaNuaTilda =
1081 gMax(mag(nuaTilda() - nuaTilda().prevIter())());
1082 dimensionedScalar maxNuaTilda = max(mag(nuaTilda()));
1083 Info<< "Max mag of nuaTilda = " << maxNuaTilda.value() << endl;
1084 Info<< "Max mag of delta nuaTilda = " << maxDeltaNuaTilda << endl;
1085 }
1086}
1087
1088
1090{
1092 {
1095
1096 Cb1_.readIfPresent(this->coeffDict());
1097 Cb2_.readIfPresent(this->coeffDict());
1098 Cw1_ = Cb1_/sqr(kappa_) + (1.0 + Cb2_)/sigmaNut_;
1099 Cw2_.readIfPresent(this->coeffDict());
1100 Cw3_.readIfPresent(this->coeffDict());
1101 Cv1_.readIfPresent(this->coeffDict());
1102 Cs_.readIfPresent(this->coeffDict());
1103
1104 return true;
1105 }
1106 else
1107 {
1108 return false;
1109 }
1110}
1111
1112
1113// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
1114
1115} // End namespace adjointRASModels
1116} // End namespace incompressibleAdjoint
1117} // End namespace Foam
1118
1119// ************************************************************************* //
Macros for easy insertion into run-time selection tables.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
const uniformDimensionedVectorField & g
surfaceScalarField & phi
static tmp< volScalarField > createLimiter(const fvMesh &mesh, const dictionary &dict)
Definition: ATCModel.C:221
const dimensionSet & dimensions() const
Return dimensions.
const Field< Type > & field() const
Return field.
Generic GeometricBoundaryField class.
void relax(const scalar alpha)
Relax field (for steady-state solution).
tmp< GeometricField< Type, PatchField, GeoMesh > > T() const
Return transpose (only if it is a tensor field)
Boundary & boundaryFieldRef(const bool updateAccessTime=true)
Return a reference to the boundary field.
Internal & ref(const bool updateAccessTime=true)
Return a reference to the dimensioned internal field.
const Boundary & boundaryField() const
Return const-reference to the boundary field.
void storePrevIter() const
Store the field as the previous iteration value.
void correctBoundaryConditions()
Correct boundary field.
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition: IOobject.H:170
void setSize(const label n)
Alias for resize()
Definition: List.H:218
tmp< volScalarField::Internal > Stilda() const
static autoPtr< Time > New()
Construct (dummy) Time - no functionObjects or libraries.
Definition: Time.C:717
static word timeName(const scalar t, const int precision=precision_)
Definition: Time.C:780
label size() const noexcept
The number of elements in the list.
Definition: UPtrListI.H:106
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: autoPtr.H:66
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
const Type & value() const
Return const reference to value.
bool readIfPresent(const dictionary &dict)
Smooth ATC in cells next to a set of patches supplied by type.
Definition: faceCells.H:59
const DimensionedField< scalar, volMesh > & V() const
Return cell volumes.
const fvBoundaryMesh & boundary() const
Return reference to boundary mesh.
Definition: fvMesh.C:712
const Time & time() const
Return the top-level database.
Definition: fvMesh.H:290
virtual tmp< Field< Type > > patchInternalField() const
Return internal field next to patch as patch field.
Definition: fvPatchField.C:237
virtual tmp< Field< Type > > snGrad() const
Return patch-normal gradient.
Definition: fvPatchField.C:229
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:71
Manages the adjoint mean flow fields and their mean values.
const volVectorField & Ua() const
Return const reference to velocity.
const volVectorField & UaInst() const
Return const reference to velocity.
const solverControl & getSolverControl() const
Return const reference to solverControl.
Abstract base class for incompressible turbulence models.
dictionary coeffDict_
Model coefficients dictionary.
autoPtr< boundaryVectorField > wallShapeSensitivitiesPtr_
Wall sensitivity term for shape optimisation.
Switch adjointTurbulence_
Turbulence on/off flag.
bool changedPrimalSolution_
Has the primal solution changed?
autoPtr< boundaryVectorField > adjMomentumBCSourcePtr_
const nearWallDist & y() const
Return the near wall distances.
autoPtr< volScalarField > adjointTMVariable1Ptr_
Adjoint turbulence model variable 1.
objectiveManager & objectiveManager_
Reference to the objectiveManager.
wordList adjointTMVariablesBaseNames_
Base names of the adjoint fields.
autoPtr< boundaryVectorField > wallFloCoSensitivitiesPtr_
Wall sensitivity term for flow control optimisation.
const dictionary & coeffDict() const
Const access to the coefficients dictionary.
virtual bool read()
Read adjointRASProperties dictionary.
Continuous adjoint to the Spalart-Allmaras one-eqn mixing-length model for incompressible flows.
tmp< volScalarField > dfw_dNuTilda(const volScalarField &Stilda, const volScalarField &dfwdr, const volScalarField &dStildadNuTilda) const
virtual tmp< fvVectorMatrix > divDevReff(volVectorField &U) const
Return the diffusion term for the momentum equation.
const volScalarField & nuTilda() const
References to the primal turbulence model variables.
tmp< volScalarField > dStilda_dNuTilda(const volScalarField &Omega, const volScalarField &fv2, const volScalarField &dFv2dChi) const
virtual tmp< volTensorField > FISensitivityTerm()
Term contributing to the computation of FI-based sensitivities.
tmp< volScalarField > dfw_dOmega(const volScalarField &Stilda, const volScalarField &dfwdr, const volScalarField &dStildadOmega) const
tmp< volScalarField > dFv2_dChi(const volScalarField &chi, const volScalarField &fv1, const volScalarField &dFv1dChi) const
tmp< volScalarField > fw(const volScalarField &Stilda) const
tmp< volScalarField > dStilda_dDelta(const volScalarField &Omega, const volScalarField &fv2) const
virtual void correct()
Solve the adjoint turbulence equations.
tmp< volVectorField > conservativeMomentumSource()
Conservative source term for the adjoint momentum equations.
tmp< volScalarField > dStilda_dOmega(const volScalarField &Omega, const volScalarField &fv2) const
void updatePrimalRelatedFields()
Update the constant primal-related fields.
virtual tmp< volSymmTensorField > devReff() const
Return the effective stress tensor including the laminar stress.
tmp< volScalarField > dP_dNuTilda(const volScalarField &dStildadNuTilda) const
virtual void nullify()
Nullify all adjoint turbulence model fields and their old times.
tmp< volScalarField > dr_dNuTilda(const volScalarField &Stilda) const
tmp< volScalarField > fv1(const volScalarField &chi) const
virtual tmp< volScalarField > nutJacobianTMVar1() const
Jacobian of nut wrt the first turbulence model variable.
tmp< volScalarField > Stilda(const volScalarField &chi, const volScalarField &fv1) const
volScalarField & nuaTilda()
Access to the adjoint Spalart - Allmaras field.
tmp< volScalarField > dfw_dDelta(const volScalarField &Stilda, const volScalarField &dfwdr, const volScalarField &dStildadDelta) const
tmp< volScalarField > dfw_dr(const volScalarField &Stilda) const
virtual const boundaryVectorField & wallShapeSensitivities()
Sensitivity terms for shape optimisation, emerging from.
virtual const boundaryVectorField & wallFloCoSensitivities()
Sensitivity terms for flow control, emerging from the.
tmp< volScalarField > dD_dNuTilda(const volScalarField &fw, const volScalarField &dfwdNuTilda) const
tmp< volScalarField > dr_dStilda(const volScalarField &Stilda) const
tmp< volScalarField > dnut_dNuTilda(const volScalarField &fv1, const volScalarField &dFv1dChi) const
tmp< volScalarField > dr_dDelta(const volScalarField &Stilda) const
const volScalarField & nut() const
Return the turbulence viscosity.
tmp< volScalarField > fv2(const volScalarField &chi, const volScalarField &fv1) const
volScalarField mask_
Field for masking (convergence enhancement)
tmp< volScalarField > dFv1_dChi(const volScalarField &chi) const
tmp< volScalarField > r(const volScalarField &Stilda) const
virtual tmp< volScalarField > nuEff() const
Return the effective viscosity.
tmp< volScalarField > nu() const
Return the laminar viscosity.
virtual void correct()=0
Solve the adjoint turbulence equations.
Base class for solution control classes.
const volVectorField & U() const
Return const reference to velocity.
const surfaceScalarField & phi() const
Return const reference to volume flux.
const autoPtr< incompressible::RASModelVariables > & RASModelVariables() const
Return const reference to the turbulence model variables.
This boundary condition provides a wall function for the turbulent viscosity (i.e....
class for managing incompressible objective functions.
const word & adjointSolverName() const
Return name of the adjointSolver.
virtual void addTMEqn1Source(fvScalarMatrix &adjTMEqn1)=0
Add contribution to first adjoint turbulence model PDE.
const quaternion & r() const
Definition: septernionI.H:74
bool printMaxMags() const
Print max mags of solver fields.
A class for managing temporary objects.
Definition: tmp.H:65
const T & cref() const
Definition: tmpI.H:213
void clear() const noexcept
Definition: tmpI.H:287
T & ref() const
Definition: tmpI.H:227
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 word & solverName() const
Return solver name.
Definition: variablesSet.C:84
bool useSolverNameForFields() const
Append solver name to fields?
Definition: variablesSet.C:90
static void nullifyField(GeometricField< Type, PatchField, GeoMesh > &fieldPtr)
Nullify field and old times, if present.
A class for handling words, derived from Foam::string.
Definition: word.H:68
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition: className.H:121
U
Definition: pEqn.H:72
const volScalarField & T
scalar uPlus
scalar yPlus
word timeName
Definition: getTimeIndex.H:3
tmp< GeometricField< typename outerProduct< vector, Type >::type, fvPatchField, volMesh > > grad(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
Definition: fvcGrad.C:54
tmp< GeometricField< Type, fvPatchField, volMesh > > div(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
Definition: fvcDiv.C:49
tmp< GeometricField< Type, fvPatchField, volMesh > > laplacian(const GeometricField< Type, fvPatchField, volMesh > &vf, const word &name)
Definition: fvcLaplacian.C:47
tmp< fvMatrix< Type > > laplacian(const GeometricField< Type, fvPatchField, volMesh > &vf, const word &name)
Definition: fvmLaplacian.C:48
tmp< fvMatrix< Type > > div(const surfaceScalarField &flux, const GeometricField< Type, fvPatchField, volMesh > &vf, const word &name)
Definition: fvmDiv.C:48
tmp< fvMatrix< Type > > ddt(const GeometricField< Type, fvPatchField, volMesh > &vf)
Definition: fvmDdt.C:48
zeroField SuSp(const Foam::zero, const GeometricField< Type, fvPatchField, volMesh > &)
A no-op source.
zeroField Sp(const Foam::zero, const GeometricField< Type, fvPatchField, volMesh > &)
A no-op source.
Namespace for OpenFOAM.
dimensionedSymmTensor dev(const dimensionedSymmTensor &dt)
dimensionedScalar pow6(const dimensionedScalar &ds)
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
dimensionedScalar pos(const dimensionedScalar &ds)
dimensionedScalar pow5(const dimensionedScalar &ds)
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:47
dimensionedSymmTensor symm(const dimensionedSymmTensor &dt)
dimensionedScalar exp(const dimensionedScalar &ds)
const dimensionSet dimless
Dimensionless.
dimensionedScalar tr(const dimensionedSphericalTensor &dt)
dimensionedSymmTensor sqr(const dimensionedVector &dv)
const dimensionSet dimLength(0, 1, 0, 0, 0, 0, 0)
Definition: dimensionSets.H:52
dimensionedScalar pow3(const dimensionedScalar &ds)
const dimensionSet dimTime(0, 0, 1, 0, 0, 0, 0)
Definition: dimensionSets.H:53
dimensionedSymmTensor twoSymm(const dimensionedSymmTensor &dt)
messageStream Info
Information stream (stdout output on master, null elsewhere)
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: MSwindows.C:598
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
dimensionedScalar sqrt(const dimensionedScalar &ds)
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:33
dimensionedScalar neg(const dimensionedScalar &ds)
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
Type gMax(const FieldField< Field, Type > &f)
dimensionedTensor skew(const dimensionedTensor &dt)
#define addProfiling(name, descr)
Define profiling trigger with specified name and description string.
CEqn solve()
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333