objectiveMoment.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-2019, 2022 PCOpt/NTUA
9  Copyright (C) 2013-2019, 2022 FOSS GP
10  Copyright (C) 2019-2023 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 
30 #include "objectiveMoment.H"
31 #include "createZeroField.H"
32 #include "wallFvPatch.H"
34 
35 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
36 
37 namespace Foam
38 {
39 
40 namespace objectives
41 {
42 
43 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
44 
45 defineTypeNameAndDebug(objectiveMoment, 0);
47 (
48  objectiveIncompressible,
49  objectiveMoment,
51 );
52 
53 
54 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
55 
57 (
58  const fvMesh& mesh,
59  const dictionary& dict,
60  const word& adjointSolverName,
61  const word& primalSolverName
62 )
63 :
64  objectiveIncompressible(mesh, dict, adjointSolverName, primalSolverName),
65  momentPatches_
66  (
67  mesh_.boundaryMesh().patchSet
68  (
69  dict.get<wordRes>("patches")
70  ).sortedToc()
71  ),
72  momentDirection_(dict.get<vector>("direction")),
73  rotationCentre_(dict.get<vector>("rotationCenter")),
74  Aref_(dict.get<scalar>("Aref")),
75  lRef_(dict.get<scalar>("lRef")),
76  rhoInf_(dict.get<scalar>("rhoInf")),
77  UInf_(dict.get<scalar>("UInf")),
78  invDenom_(2./(rhoInf_*UInf_*UInf_*Aref_*lRef_)),
79  devReff_(vars_.turbulence()->devReff()())
80 {
81  // Sanity check and print info
82  if (momentPatches_.empty())
83  {
85  << "No valid patch name on which to minimize " << type() << endl
86  << exit(FatalError);
87  }
88  if (debug)
89  {
90  Info<< "Minimizing " << type() << " in patches:" << endl;
91  for (const label patchI : momentPatches_)
92  {
93  Info<< "\t " << mesh_.boundary()[patchI].name() << endl;
94  }
95  }
96 
97  // Allocate boundary field pointers
98  bdJdpPtr_.reset(createZeroBoundaryPtr<vector>(mesh_));
99  bdSdbMultPtr_.reset(createZeroBoundaryPtr<vector>(mesh_));
100  bdxdbMultPtr_.reset(createZeroBoundaryPtr<vector>(mesh_));
101  bdxdbDirectMultPtr_.reset(createZeroBoundaryPtr<vector>(mesh_));
102  bdJdnutPtr_.reset(createZeroBoundaryPtr<scalar>(mesh_));
103  //bdJdGradUPtr_.reset(createZeroBoundaryPtr<tensor>(mesh_));
104 }
105 
106 
107 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
108 
109 scalar objectiveMoment::J()
110 {
111  vector pressureMoment(Zero);
112  vector viscousMoment(Zero);
113  vector cumulativeMoment(Zero);
114 
115  // Update field here and use the same value for all functions
116  const volScalarField& p = vars_.pInst();
117  devReff_ = vars_.turbulence()->devReff()();
118 
119  for (const label patchI : momentPatches_)
120  {
121  const fvPatch& patch = mesh_.boundary()[patchI];
122  const vectorField& Sf = patch.Sf();
123  vectorField dx(patch.Cf() - rotationCentre_);
124  pressureMoment += gSum
125  (
126  rhoInf_*(dx ^ Sf)*p.boundaryField()[patchI]
127  );
128 
129  // Viscous term calculated using the full tensor derivative
130  viscousMoment += gSum
131  (
132  rhoInf_*(dx^(devReff_.boundaryField()[patchI] & Sf))
133  );
134  }
135 
136  cumulativeMoment = pressureMoment + viscousMoment;
137 
138  scalar moment = cumulativeMoment & momentDirection_;
139  scalar Cm = moment*invDenom_;
141  "Moment|Coeff " << moment << "|" << Cm << endl;
142  J_ = Cm;
143  return Cm;
144 }
145 
146 
148 {
149  if (computeMeanFields_)
150  {
151  const volVectorField& U = vars_.U();
155 
156  devReff_ = turbVars->devReff(lamTransp, U)();
157  }
158 }
159 
160 
162 {
163  for (const label patchI : momentPatches_)
164  {
165  const fvPatch& patch = mesh_.boundary()[patchI];
166  tmp<vectorField> tdx = patch.Cf() - rotationCentre_;
167  bdJdpPtr_()[patchI] = (momentDirection_ ^ tdx)*invDenom_*rhoInf_;
168  }
169 }
170 
171 
173 {
174  const volScalarField& p = vars_.p();
175 
176  for (const label patchI : momentPatches_)
177  {
178  const fvPatch& patch = mesh_.boundary()[patchI];
179  tmp<vectorField> tdx = patch.Cf() - rotationCentre_;
180  bdSdbMultPtr_()[patchI] =
181  (
182  (
183  rhoInf_*
184  (
185  (momentDirection_ ^ tdx()) &
186  (
187  devReff_.boundaryField()[patchI]
188  )
189  )
190  )
191  + rhoInf_*(momentDirection_ ^ tdx())*p.boundaryField()[patchI]
192  )
193  *invDenom_;
194  }
195 }
196 
197 
199 {
200  const volScalarField& p = vars_.p();
201  const volVectorField& U = vars_.U();
202 
205  const singlePhaseTransportModel& lamTransp = vars_.laminarTransport();
206 
207  // We only need to modify the boundaryField of gradU locally.
208  // If grad(U) is cached then
209  // a. The .ref() call fails since the tmp is initialised from a
210  // const ref
211  // b. we would be changing grad(U) for all other places in the code
212  // that need it
213  // So, always allocate new memory and avoid registering the new field
214  tmp<volTensorField> tgradU =
215  volTensorField::New("gradULocal", fvc::grad(U));
216  volTensorField::Boundary& gradUbf = tgradU.ref().boundaryFieldRef();
217 
218  // Explicitly correct the boundary gradient to get rid of the
219  // tangential component
220  forAll(mesh_.boundary(), patchI)
221  {
222  const fvPatch& patch = mesh_.boundary()[patchI];
223  if (isA<wallFvPatch>(patch))
224  {
225  tmp<vectorField> tnf = mesh_.boundary()[patchI].nf();
226  gradUbf[patchI] = tnf*U.boundaryField()[patchI].snGrad();
227  }
228  }
229 
230  // Term coming from gradp
231  tmp<volVectorField> tgradp = fvc::grad(p);
232  const volVectorField& gradp = tgradp.cref();
233  for (const label patchI : momentPatches_)
234  {
235  const fvPatch& patch = mesh_.boundary()[patchI];
236  tmp<vectorField> tnf = patch.nf();
237  tmp<vectorField> tdx = patch.Cf() - rotationCentre_;
238  bdxdbMultPtr_()[patchI] =
239  (momentDirection_ & (tdx ^ tnf))*gradp.boundaryField()[patchI]
240  *invDenom_*rhoInf_;
241  }
242  tgradp.clear();
243 
244  // Term coming from stresses
245  tmp<volScalarField> tnuEff = lamTransp.nu() + turbVars->nut();
246  tmp<volSymmTensorField> tstress = tnuEff*twoSymm(tgradU);
247  const volSymmTensorField& stress = tstress.cref();
248  autoPtr<volVectorField> ptemp
249  (Foam::createZeroFieldPtr<vector>( mesh_, "temp", sqr(dimVelocity)));
250  volVectorField& temp = ptemp.ref();
251 
252  for (label idir = 0; idir < pTraits<vector>::nComponents; ++idir)
253  {
254  unzipRow(stress, idir, temp);
255  volTensorField gradStressDir(fvc::grad(temp));
256  for (const label patchI : momentPatches_)
257  {
258  const fvPatch& patch = mesh_.boundary()[patchI];
259  tmp<vectorField> tnf = patch.nf();
260  tmp<vectorField> tdx = patch.Cf() - rotationCentre_;
261  tmp<scalarField> taux = (momentDirection_ ^ tdx)().component(idir);
262  bdxdbMultPtr_()[patchI] -=
263  taux*(gradStressDir.boundaryField()[patchI] & tnf)
264  *invDenom_*rhoInf_;
265  }
266  }
267 }
268 
269 
271 {
272  const volScalarField& p = vars_.p();
273 
274  for (const label patchI : momentPatches_)
275  {
276  const fvPatch& patch = mesh_.boundary()[patchI];
277  tmp<vectorField> tnf = patch.nf();
278  const vectorField& nf = tnf();
279  const vectorField dx(patch.Cf() - rotationCentre_);
280  const vectorField force
281  (
282  rhoInf_
283  *(
284  ((p.boundaryField()[patchI]*nf)
285  + (devReff_.boundaryField()[patchI] & nf))
286  )
287  );
288  bdxdbDirectMultPtr_()[patchI] =
289  (force^momentDirection_)*invDenom_*rhoInf_;
290  }
291 }
292 
293 
295 {
296  const volVectorField& U = vars_.U();
298 
299  for (const label patchI : momentPatches_)
300  {
301  const fvPatch& patch = mesh_.boundary()[patchI];
302  tmp<vectorField> tnf = patch.nf();
303  tmp<vectorField> tdx = patch.Cf() - rotationCentre_;
304  const fvPatchSymmTensorField& bdevGradU =
305  devGradU.boundaryField()[patchI];
306  bdJdnutPtr_()[patchI] =
307  - rhoInf_*((tdx ^ (bdevGradU & tnf)) & momentDirection_)*invDenom_;
308  }
309 }
310 
311 
312 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
313 
314 } // End namespace objectives
315 } // End namespace Foam
316 
317 // ************************************************************************* //
List< ReturnType > get(const UPtrList< T > &list, const AccessOp &aop)
List of values generated by applying the access operation to each list item.
GeometricField< symmTensor, fvPatchField, volMesh > volSymmTensorField
Definition: volFieldsFwd.H:85
const volScalarField & pInst() const
Return const reference to pressure.
dictionary dict
tmp< GeometricField< typename outerProduct< vector, Type >::type, fvPatchField, volMesh >> grad(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
Definition: fvcGrad.C:47
autoPtr< boundaryVectorField > bdxdbMultPtr_
Term multiplying delta(x)/delta b at the boundary.
Definition: objective.H:171
virtual void update_dxdbMultiplier()
Update delta(x)/delta b multiplier.
errorManipArg< error, int > exit(error &err, const int errNo=1)
Definition: errorManip.H:125
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
A list of keyword definitions, which are a keyword followed by a number of values (eg...
Definition: dictionary.H:129
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
T & ref() const
Return non-const reference to the contents of a non-null managed pointer.
Definition: tmpI.H:235
GeometricField< tensor, fvPatchField, volMesh > volTensorField
Definition: volFieldsFwd.H:86
dimensionedSymmTensor sqr(const dimensionedVector &dv)
virtual void update_dSdbMultiplier()
Update delta(n dS)/delta b multiplier.
Addressing for all faces on surface of mesh. Can either be read from polyMesh or from triSurface...
Definition: boundaryMesh.H:58
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:531
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:70
void unzipRow(const FieldField< Field, SymmTensor< Cmpt >> &input, const direction idx, FieldField< Field, Vector< Cmpt >> &result)
Extract a symmTensor field field row (x,y,z) == (0,1,2)
Abstract base class with a fat-interface to all derived classes covering all possible ways in which t...
::Foam::direction nComponents(const expressions::valueTypeCode) noexcept
The number of components associated with given valueTypeCode.
Definition: exprTraits.C:40
GeometricField< vector, fvPatchField, volMesh > volVectorField
Definition: volFieldsFwd.H:82
Macros for easy insertion into run-time selection tables.
dimensionedSymmTensor twoSymm(const dimensionedSymmTensor &dt)
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
GeometricField< scalar, fvPatchField, volMesh > volScalarField
Definition: volFieldsFwd.H:81
autoPtr< boundaryScalarField > bdJdnutPtr_
Jacobian wrt to nut.
fileName::Type type(const fileName &name, const bool followLink=true)
Return the file type: DIRECTORY or FILE, normally following symbolic links.
Definition: POSIX.C:799
objectiveMoment(const fvMesh &mesh, const dictionary &dict, const word &adjointSolverName, const word &primalSolverName)
from components
dynamicFvMesh & mesh
Type gSum(const FieldField< Field, Type > &f)
bool computeMeanFields_
Definition: objective.H:68
const singlePhaseTransportModel & laminarTransport() const
Return const reference to transport model.
A class for handling words, derived from Foam::string.
Definition: word.H:63
defineTypeNameAndDebug(objectivePartialVolume, 1)
virtual void update_boundarydJdp()
Update values to be added to the adjoint wall velocity.
const volScalarField & p() const
Return const reference to pressure.
A List of wordRe with additional matching capabilities.
Definition: wordRes.H:53
const fvMesh & mesh_
Definition: objective.H:63
scalar J_
Objective function value and weight.
Definition: objective.H:76
#define DebugInfo
Report an information message using Foam::Info.
const volVectorField & U() const
Return const reference to velocity.
static tmp< GeometricField< tensor, fvPatchField, volMesh > > New(const word &name, IOobjectOption::registerOption regOpt, const Mesh &mesh, const dimensionSet &dims, const word &patchFieldType=fvPatchField< tensor >::calculatedType())
Return tmp field (NO_READ, NO_WRITE) from name, mesh, dimensions and patch type. [Takes current timeN...
bool empty() const noexcept
True if the hash table is empty.
Definition: HashTable.H:337
A Vector of values with scalar precision, where scalar is float/double depending on the compilation f...
int debug
Static debugging option.
autoPtr< boundaryVectorField > bdJdpPtr_
Adjoint (intlet,wall) velocity.
Info<< "Reading field U\"<< endl;volVectorField U(IOobject("U", runTime.timeName(), mesh, IOobject::MUST_READ, IOobject::AUTO_WRITE), mesh);volScalarField rho(IOobject("rho", runTime.timeName(), mesh, IOobject::NO_READ, IOobject::AUTO_WRITE), thermo.rho());volVectorField rhoU(IOobject("rhoU", runTime.timeName(), mesh, IOobject::NO_READ, IOobject::NO_WRITE), rho *U);volScalarField rhoE(IOobject("rhoE", runTime.timeName(), mesh, IOobject::NO_READ, IOobject::NO_WRITE), rho *(e+0.5 *magSqr(U)));surfaceScalarField pos(IOobject("pos", runTime.timeName(), mesh), mesh, dimensionedScalar("pos", dimless, 1.0));surfaceScalarField neg(IOobject("neg", runTime.timeName(), mesh), mesh, dimensionedScalar("neg", dimless, -1.0));surfaceScalarField phi("phi", fvc::flux(rhoU));Info<< "Creating turbulence model\"<< endl;autoPtr< compressible::turbulenceModel > turbulence(compressible::turbulenceModel::New(rho, U, phi, thermo))
Definition: createFields.H:94
addToRunTimeSelectionTable(objectiveGeometric, objectivePartialVolume, dictionary)
const autoPtr< incompressible::RASModelVariables > & RASModelVariables() const
Return const reference to the turbulence model variables.
const incompressibleVars & vars_
virtual void update_boundarydJdnut()
Update dJ/dnut multiplier.
U
Definition: pEqn.H:72
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
const std::string patch
OpenFOAM patch number as a std::string.
List< label > sortedToc(const UList< bool > &bools)
Return the (sorted) values corresponding to &#39;true&#39; entries.
Definition: BitOps.C:195
messageStream Info
Information stream (stdout output on master, null elsewhere)
Internal & ref(const bool updateAccessTime=true)
Same as internalFieldRef()
const fvBoundaryMesh & boundary() const noexcept
Return reference to boundary mesh.
Definition: fvMesh.H:395
const autoPtr< incompressible::turbulenceModel > & turbulence() const
Return const reference to the turbulence model.
Field< vector > vectorField
Specialisation of Field<T> for vector.
Pointer management similar to std::unique_ptr, with some additional methods and type checking...
Definition: HashPtrTable.H:48
virtual void update_dxdbDirectMultiplier()
Update delta(x)/delta b multiplier coming directly from the objective.
autoPtr< boundaryVectorField > bdxdbDirectMultPtr_
Term multiplying delta(x)/delta b at the boundary for objectives that directly depend on x...
Definition: objective.H:178
volScalarField & p
A class for managing temporary objects.
Definition: HashPtrTable.H:50
autoPtr< boundaryVectorField > bdSdbMultPtr_
Term multiplying delta(n dS)/delta b.
Definition: objective.H:161
virtual void update_meanValues()
Update mean drag and lift values.
A simple single-phase transport model based on viscosityModel.
Abstract base class for objective functions in incompressible flows.
virtual scalar J()
Return the objective function value.
const Boundary & boundaryField() const noexcept
Return const-reference to the boundary field.
Namespace for OpenFOAM.
virtual tmp< volScalarField > nu() const
Return the laminar viscosity.
SymmTensor< Cmpt > devTwoSymm(const SymmTensor< Cmpt > &st)
Return the deviatoric part of twice the symmetric part of a SymmTensor.
Definition: SymmTensorI.H:491
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127
const dimensionSet dimVelocity