adjointBoundaryCondition.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 
31 #include "emptyFvPatch.H"
32 #include "adjointSolverManager.H"
33 #include "HashTable.H"
35 #include "ATCUaGradU.H"
36 
37 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
38 
39 namespace Foam
40 {
41 
42 // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
43 
44 template<class Type>
45 template<class Type2>
46 tmp
47 <
49 >
51 {
52  // Return field
53  typedef typename outerProduct<vector, Type2>::type GradType;
54  auto tresGrad = tmp<Field<GradType>>::New(patch_.size(), Zero);
55  auto& resGrad = tresGrad.ref();
56 
57  const labelList& faceCells = patch_.faceCells();
58  const fvMesh& mesh = patch_.boundaryMesh().mesh();
59  const cellList& cells = mesh.cells();
60 
61  // Go through the surfaceInterpolation scheme defined in gradSchemes for
62  // consistency
63  const GeometricField<Type2, fvPatchField, volMesh>& field =
65 
66  // Gives problems when grad(AdjointVar) is computed using a limited scheme,
67  // since it is not possible to know a priori how many words to expect in the
68  // stream.
69  // Interpolation scheme is now read through interpolation schemes.
70  /*
71  word gradSchemeName("grad(" + name + ')');
72  ITstream& is = mesh.gradScheme(gradSchemeName);
73  word schemeData(is);
74  */
75 
76  // If there are many patches calling this function, the computation of
77  // the surface field might be a significant computational
78  // burden. Cache the interpolated field and fetch from the registry when
79  // possible.
80  const word surfFieldName("interpolated" + name + "ForBoundaryGrad");
81  typedef GeometricField<Type2, fvsPatchField, surfaceMesh> surfFieldType;
82  surfFieldType* surfFieldPtr =
83  mesh.objectRegistry::template getObjectPtr<surfFieldType>(surfFieldName);
84 
85  if (!surfFieldPtr)
86  {
87  solution::cachePrintMessage("Calculating and caching", name, field);
88 
89  surfFieldPtr =
91  (
92  mesh, mesh.interpolationScheme("interpolate(" + name + ")")
93  )().interpolate(field).ptr();
94  surfFieldPtr->rename(surfFieldName);
95  regIOobject::store(surfFieldPtr);
96  }
97  else
98  {
99  if (surfFieldPtr->upToDate(field))
100  {
102  }
103  else
104  {
105  solution::cachePrintMessage("Updating", name, field);
106  delete surfFieldPtr;
107 
108  surfFieldPtr =
110  (
111  mesh, mesh.interpolationScheme("interpolate(" + name + ")")
112  )().interpolate(field).ptr();
113  surfFieldPtr->rename(surfFieldName);
114  regIOobject::store(surfFieldPtr);
115  }
116  }
117  surfFieldType& surfField = *surfFieldPtr;
118 
119  // Auxiliary fields
120  const surfaceVectorField& Sf = mesh.Sf();
121  tmp<vectorField> tnf = patch_.nf();
122  const vectorField& nf = tnf();
123  const scalarField& V = mesh.V();
124  const labelUList& owner = mesh.owner();
125 
126  // Compute grad value of cell adjacent to the boundary
127  forAll(faceCells, fI)
128  {
129  const label cI = faceCells[fI];
130  const cell& cellI = cells[cI];
131  for (const label faceI : cellI) // global face numbering
132  {
133  label patchID = mesh.boundaryMesh().whichPatch(faceI);
134  if (patchID == -1) //face is internal
135  {
136  const label own = owner[faceI];
137  tensor flux = Sf[faceI]*surfField[faceI];
138  if (cI == own)
139  {
140  resGrad[fI] += flux;
141  }
142  else
143  {
144  resGrad[fI] -= flux;
145  }
146  }
147  else // Face is boundary. Covers coupled patches as well
148  {
149  if (!isA<emptyFvPatch>(mesh.boundary()[patchID]))
150  {
151  const fvPatch& patchForFlux = mesh.boundary()[patchID];
152  const label boundaryFaceI = faceI - patchForFlux.start();
153  const vectorField& Sfb = Sf.boundaryField()[patchID];
154  resGrad[fI] +=
155  Sfb[boundaryFaceI]
156  *surfField.boundaryField()[patchID][boundaryFaceI];
157  }
158  }
159  }
160  resGrad[fI] /= V[cI];
161  }
162 
163  // This has concluded the computation of the grad at the cell next to the
164  // boundary. We now need to compute the grad at the boundary face
165  const fvPatchField<Type2>& bField = field.boundaryField()[patch_.index()];
166  resGrad = nf*bField.snGrad() + (resGrad - nf*(nf & resGrad));
167 
168  return tresGrad;
169 }
170 
171 
172 template<class Type>
174 {
175  if (!addATCUaGradUTerm_.good())
176  {
177  addATCUaGradUTerm_ = bool(isA<ATCUaGradU>(getATC()));
178  }
179  return addATCUaGradUTerm_;
180 }
181 
182 
183 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
184 
185 template<class Type>
187 (
188  const adjointBoundaryCondition<Type>& adjointBC
189 )
190 :
191  patch_(adjointBC.patch_),
192  managerName_(adjointBC.managerName_),
193  adjointSolverName_(adjointBC.adjointSolverName_),
194  simulationType_(adjointBC.simulationType_),
195  boundaryContrPtr_
196  (
198  (
199  adjointBC.managerName_,
200  adjointBC.adjointSolverName_,
201  adjointBC.simulationType_,
202  adjointBC.patch_
203  )
204  ),
205  addATCUaGradUTerm_(Switch::INVALID)
206 {}
207 
208 
209 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
210 
211 template<class Type>
213 (
214  const fvPatch& p,
216  const word& solverName
217 )
218 :
219  patch_(p),
220  managerName_("objectiveManager" + solverName),
221  adjointSolverName_(solverName),
222  simulationType_("incompressible"),
223  boundaryContrPtr_(nullptr),
224  addATCUaGradUTerm_(Switch::INVALID)
225 {
226  // Set the boundaryContribution pointer
228 }
229 
230 
231 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
232 
233 template<class Type>
235 {
236  return managerName_;
237 }
238 
239 
240 template<class Type>
242 {
243  return adjointSolverName_;
244 }
245 
246 
247 template<class Type>
249 {
250  return simulationType_;
251 }
252 
253 
254 template<class Type>
256 {
257  // Note:
258  // Check whether there is an objectiveFunctionManager object in the registry
259  // Necessary for decomposePar if the libadjoint is loaded
260  // through controlDict. A nicer way should be found
261  const fvMesh& meshRef = patch_.boundaryMesh().mesh();
262  if (meshRef.foundObject<regIOobject>(managerName_))
263  {
264  boundaryContrPtr_.reset
265  (
267  (
268  managerName_,
269  adjointSolverName_,
270  simulationType_,
271  patch_
272  ).ptr()
273  );
274  }
275  else
276  {
278  << "No objectiveManager " << managerName_ << " available." << nl
279  << "Setting boundaryAdjointContributionPtr to nullptr. " << nl
280  << "OK for decomposePar."
281  << endl;
282  }
283 }
284 
285 
286 template<class Type>
287 boundaryAdjointContribution&
289 {
290  return boundaryContrPtr_();
291 }
292 
293 
294 template<class Type>
296 {
297  return
298  patch_.boundaryMesh().mesh().template
299  lookupObject<ATCModel>("ATCModel" + adjointSolverName_);
300 }
301 
302 
303 template<class Type>
305 {
306  // Does nothing in base
307 }
308 
309 
310 template<class Type>
311 tmp
312 <
314 >
316 {
317  return nullptr;
318 }
319 
320 
321 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
322 
323 } // End namespace Foam
324 
325 // ************************************************************************* //
tmp< Field< typename Foam::outerProduct< Foam::vector, Type2 >::type > > computePatchGrad(word name)
Get gradient of field on a specific boundary.
adjointBoundaryCondition(const fvPatch &p, const DimensionedField< Type, volMesh > &iF, const word &solverName)
Construct from field and base name.
virtual void updatePrimalBasedQuantities()
Update the primal based quantities related to the adjoint boundary conditions.
const word & simulationType() const
Return the simulationType.
const word & adjointSolverName() const
Return adjointSolverName.
const surfaceVectorField & Sf() const
Return cell face area vectors.
const Type & lookupObject(const word &name, const bool recursive=false) const
Lookup and return const reference to the object of the given Type. Fatal if not found or the wrong ty...
type
Types of root.
Definition: Roots.H:52
rDeltaTY field()
List< cell > cellList
List of cell.
Definition: cellListFwd.H:39
static autoPtr< boundaryAdjointContribution > New(const word &managerName, const word &adjointSolverName, const word &simulationType, const fvPatch &patch)
Return a reference to the selected turbulence model.
tmp< surfaceScalarField > flux(const volVectorField &vvf)
Return the face-flux field obtained from the given volVectorField.
constexpr char nl
The newline &#39;\n&#39; character (0x0a)
Definition: Ostream.H:50
GeometricField< vector, fvsPatchField, surfaceMesh > surfaceVectorField
Tensor< scalar > tensor
Definition: symmTensor.H:57
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
tmp< DimensionedField< TypeR, GeoMesh > > New(const tmp< DimensionedField< TypeR, GeoMesh >> &tf1, const word &name, const dimensionSet &dimensions, const bool initCopy=false)
Global function forwards to reuseTmpDimensionedField::New.
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
bool store()
Register object with its registry and transfer ownership to the registry.
Definition: regIOobjectI.H:36
void setBoundaryContributionPtr()
Set the ptr to the correct boundaryAdjointContribution.
typeOfRank< typename pTraits< arg1 >::cmptType, direction(pTraits< arg1 >::rank)+direction(pTraits< arg2 >::rank) >::type type
Definition: products.H:118
const cellList & cells() const
const DimensionedField< scalar, volMesh > & V() const
Return cell volumes.
GeometricField< vector, fvPatchField, volMesh > volVectorField
Definition: volFieldsFwd.H:82
bool addATCUaGradUTerm()
Whether to add the extra term from the UaGradU formulation.
UList< label > labelUList
A UList of labels.
Definition: UList.H:78
ITstream & interpolationScheme(const word &name) const
Get interpolation scheme for given name, or default.
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:421
static void cachePrintMessage(const char *message, const word &name, const FieldType &fld)
Helper for printing cache message.
virtual tmp< Field< typename Foam::outerProduct< Foam::vector, Type >::type > > dxdbMult() const
Return contribution to sensitivity derivatives.
dynamicFvMesh & mesh
word name(const expressions::valueTypeCode typeCode)
A word representation of a valueTypeCode. Empty for expressions::valueTypeCode::INVALID.
Definition: exprTraits.C:127
const cellShapeList & cells
const polyMesh & mesh() const noexcept
Return the mesh reference.
const ATCModel & getATC() const
ATC type might be useful for a number of BCs. Return here.
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
Definition: polyMesh.H:608
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.
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Base class for selecting the adjoint transpose convection model. Inherits from regIOobject to add loo...
Definition: ATCModel.H:56
label whichPatch(const label meshFacei) const
Return patch index for a given mesh face index. Uses binary search.
void reset(const label nPoints, const label nInternalFaces, const label nFaces, const label nCells)
Reset this primitiveMesh given the primitive array sizes.
Abstract base class for computing contributions of the objective functions to the adjoint boundary co...
boundaryAdjointContribution & getBoundaryAdjContribution()
Get boundaryContribution.
const labelUList & owner() const
Internal face owner. Note bypassing virtual mechanism so.
Definition: fvMesh.H:572
#define WarningInFunction
Report a warning using Foam::Warning.
Base class for solution control classes.
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:78
Field with dimensions and associated with geometry type GeoMesh which is used to size the field and a...
Definition: areaFieldsFwd.H:42
regIOobject is an abstract class derived from IOobject to handle automatic object registration with t...
Definition: regIOobject.H:66
const fvBoundaryMesh & boundary() const noexcept
Return reference to boundary mesh.
Definition: fvMesh.H:395
Field< vector > vectorField
Specialisation of Field<T> for vector.
bool foundObject(const word &name, const bool recursive=false) const
Is the named Type found?
List< label > labelList
A List of labels.
Definition: List.H:62
volScalarField & p
const word & objectiveManagerName() const
Return objectiveManager name.
Namespace for OpenFOAM.
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:127