adjointWallVelocityFvPatchVectorField.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 -------------------------------------------------------------------------------
12 License
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 "fvMatrix.H"
34 
35 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
36 
39 (
40  const fvPatch& p,
42 )
43 :
44  fixedValueFvPatchVectorField(p, iF),
46  kappa_(0.41),
47  E_(9.8)
48 {}
49 
50 
53 (
55  const fvPatch& p,
57  const fvPatchFieldMapper& mapper
58 )
59 :
60  fixedValueFvPatchVectorField(ptf, p, iF, mapper),
61  adjointVectorBoundaryCondition(p, iF, ptf.adjointSolverName_),
62  kappa_(ptf.kappa_),
63  E_(ptf.E_)
64 {}
65 
66 
69 (
70  const fvPatch& p,
72  const dictionary& dict
73 )
74 :
75  fixedValueFvPatchVectorField(p, iF),
76  adjointVectorBoundaryCondition(p, iF, dict.get<word>("solverName")),
77  kappa_(dict.getOrDefault<scalar>("kappa", 0.41)),
78  E_(dict.getOrDefault<scalar>("E", 9.8))
79 {
81  (
82  vectorField("value", dict, p.size())
83  );
84 }
85 
86 
89 (
92 )
93 :
94  fixedValueFvPatchVectorField(pivpvf, iF),
96  kappa_(pivpvf.kappa_),
97  E_(pivpvf.E_)
98 {}
99 
100 
101 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
102 
104 (
105  fvMatrix<vector>& matrix
106 )
107 {
109  (
111  "adjointWallVelocityFvPatchVectorField::manipulateMatrix"
112  );
113  // Grab ref to the diagonal matrix
114  vectorField& source = matrix.source();
115 
116  // Define boundary condition type
118  SAwallFunctionPatchField;
119 
120  if
121  (
122  isA<SAwallFunctionPatchField>(boundaryContrPtr_->turbulentDiffusivity())
123  && patch().size() != 0
124  )
125  {
126  const tmp<vectorField> tnf = patch().nf();
127  const vectorField& nf = tnf();
128  const scalarField& magSf = patch().magSf();
129 
130  const fvPatchField<vector>& Up = boundaryContrPtr_->Ub();
131  const fvPatchField<vector>& Uap = *this;
132 
133  const vectorField Uc(Up.patchInternalField());
134  const vectorField Uc_t(Uc - (Uc & nf)*nf);
135 
136  // By convention, tf has the direction of the tangent PRIMAL velocity
137  // at the first cell off the wall
138  const vectorField tf(Uc_t/mag(Uc_t));
139 
140  tmp<scalarField> tnuw = boundaryContrPtr_->momentumDiffusion();
141  const scalarField& nuw = tnuw();
142  tmp<scalarField> tnu = boundaryContrPtr_->laminarDiffusivity();
143  const scalarField& nu = tnu();
144  tmp<scalarField> tyC = boundaryContrPtr_->wallDistance();
145  const scalarField& yC = tyC();
146 
147  const scalarField magGradU(mag(Up.snGrad()));
148  const scalarField vtau(sqrt(nuw*magGradU));
149  const scalarField uPlus(mag(Uc)/vtau);
150  const scalarField yPlus(yC*vtau/nu);
151  const scalarField kUu(min(kappa_*uPlus, scalar(50)));
152  const scalarField auxA((kappa_/E_)*(exp(kUu)-1 - kUu - 0.5*kUu*kUu));
153  const scalarField auxB(-(1 + auxA)/(yPlus + uPlus*(1 + auxA)));
154 
155  // Tangent components are according to tf
156  tmp<vectorField> tsource = boundaryContrPtr_->normalVelocitySource();
157  const scalarField rt(tsource() & tf);
158  const scalarField Uap_t(Uap & tf);
159 
160  forAll(Up, faceI)
161  {
162  label cellI = patch().faceCells()[faceI];
163  source[cellI] +=
164  2*auxB[faceI]*vtau[faceI]*((rt[faceI] + Uap_t[faceI]))
165  *(Uc[faceI]/mag(Uc[faceI]))*magSf[faceI];
166  }
167  }
168 }
169 
170 
172 {
173  if (updated())
174  {
175  return;
176  }
177 
178  const fvPatchField<vector>& Up = boundaryContrPtr_->Ub();
179 
180  // Patch geometry
181  tmp<vectorField> tnf = patch().nf();
182  const vectorField& nf = tnf();
183 
184  // Internal fields
185  vectorField Uac(this->patchInternalField());
186  vectorField Uc(Up.patchInternalField());
187 
188  // Tangent vector based on the direction of Vc
189  vectorField Uc_t(Uc - (Uc & nf)*nf);
190  vectorField tf1(Uc_t/mag(Uc_t));
191 
192  // Tangent vector as the cross product of tf1 x nf
193  vectorField tf2((tf1 ^ nf)/mag(tf1 ^ nf));
194 
195  // Normal adjoint component comes from the objective function
196  tmp<vectorField> tsource = boundaryContrPtr_->normalVelocitySource();
197  vectorField Uan(-(tsource() & nf)*nf);
198 
199  // Tangential adjoint velocity in the t1 direction depends on the primal
200  // wall function used
201  vectorField Uap_t1(patch().size(), Zero);
203  SAwallFunctionPatchField;
204 
205  const fvPatchScalarField& nutb = boundaryContrPtr_->turbulentDiffusivity();
206  if (isA<SAwallFunctionPatchField>(nutb))
207  {
208  Uap_t1 = (Uac & tf1)*tf1;
209  // leaving out second term for now
210  //- (1./delta)*((gradUaC & nf) & tf1)*tf1;
211  }
212  else
213  {
214  Uap_t1 = - (tsource() & tf1)*tf1;
215  }
216 
217  // Adjoint velocity in the t2 direction
218  vectorField Uap_t2(-(tsource() & tf2)*tf2);
219 
220  operator==(Uan + Uap_t1 + Uap_t2);
222  fixedValueFvPatchVectorField::updateCoeffs();
223 }
224 
225 
227 {
229  writeEntry("value", os);
230  os.writeEntry("kappa", kappa_);
231  os.writeEntry("E", E_);
232  os.writeEntry("solverName", adjointSolverName_);
233 }
234 
235 
236 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
237 
238 namespace Foam
239 {
241  (
243  adjointWallVelocityFvPatchVectorField
244  );
245 }
246 
247 // ************************************************************************* //
List< ReturnType > get(const UPtrList< T > &list, const AccessOp &aop)
List of values generated by applying the access operation to each list item.
Adjoint wall velocity boundary condition. If nutUSpaldingWallFunction is employed in the flow solutio...
scalar uPlus
dictionary dict
#define addProfiling(name, descr)
Define profiling trigger with specified name and description string.
fvPatchField< vector > fvPatchVectorField
virtual tmp< Field< Type > > snGrad() const
Return patch-normal gradient.
Definition: fvPatchField.C:174
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:120
dimensionedScalar sqrt(const dimensionedScalar &ds)
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:68
Abstract base class with a fat-interface to all derived classes covering all possible ways in which t...
Ostream & writeEntry(const keyType &key, const T &value)
Write a keyword/value entry.
Definition: Ostream.H:312
virtual void write(Ostream &) const
Write.
Definition: fvPatchField.C:333
Macros for easy insertion into run-time selection tables.
virtual void updateCoeffs()
Update the coefficients associated with the patch field.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:413
This boundary condition provides a wall function for the turbulent viscosity (i.e. nut) based on velocity (i.e. U). Using Spalding&#39;s law gives a continuous nut profile to the wall.
dimensionedScalar exp(const dimensionedScalar &ds)
fvPatchField< scalar > fvPatchScalarField
virtual void manipulateMatrix(fvMatrix< vector > &matrix)
In case of High-Re runs based on the nutUSpaldingWallFunction add source terms in the first cell cent...
A class for handling words, derived from Foam::string.
Definition: word.H:63
A FieldMapper for finite-volume patch fields.
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
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:26
An Ostream is an abstract base class for all output systems (streams, files, token lists...
Definition: Ostream.H:55
virtual tmp< Field< Type > > patchInternalField() const
Return internal field next to patch as patch field.
Definition: fvPatchField.C:182
OBJstream os(runTime.globalPath()/outputName)
Field< Type > & source() noexcept
Definition: fvMatrix.H:534
adjointWallVelocityFvPatchVectorField(const fvPatch &, const DimensionedField< vector, volMesh > &)
Construct from patch and internal field.
scalar yPlus
Base class for solution control classes.
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
Definition: areaFieldsFwd.H:42
const std::string patch
OpenFOAM patch number as a std::string.
Field< vector > vectorField
Specialisation of Field<T> for vector.
volScalarField & p
A class for managing temporary objects.
Definition: HashPtrTable.H:50
tmp< faMatrix< Type > > operator==(const faMatrix< Type > &, const faMatrix< Type > &)
makePatchTypeField(fvPatchScalarField, atmBoundaryLayerInletEpsilonFvPatchScalarField)
volScalarField & nu
Namespace for OpenFOAM.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:157