Loading...
Searching...
No Matches
sensitivitySurface.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-2020, 2022 PCOpt/NTUA
9 Copyright (C) 2013-2020, 2022 FOSS GP
10 Copyright (C) 2019-2022 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
30#include "sensitivitySurface.H"
32#include "faMatrices.H"
33#include "famSup.H"
34#include "famLaplacian.H"
35#include "volSurfaceMapping.H"
37
38// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
40namespace Foam
41{
42
43// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
44
47(
49 sensitivitySurface,
51);
52
53
54// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
55
57(
58 const bool computeVectorFieldSize
59)
60{
61 label size(0);
62 for (const label patchI : sensitivityPatchIDs_)
63 {
64 const fvPatch& patch = mesh_.boundary()[patchI];
65 const label patchSize = patch.size();
66 size += label(computeVectorFieldSize ? 3*patchSize : patchSize);
67 }
68 return size;
69}
70
71
73{
74 // Read in parameters
75 const label iters(dict().getOrDefault<label>("iters", 500));
76 const scalar tolerance(dict().getOrDefault<scalar>("tolerance", 1.e-06));
77
78 autoPtr<faMesh> aMeshPtr = faMesh::TryNew(mesh_);
79
80 if (aMeshPtr)
81 {
82 Info<< "Loaded the existing faMesh" << nl;
83 }
84 else
85 {
86 // Dictionary used to construct the faMesh
87 dictionary faMeshDefinition;
88
89 // Check and read system/faMeshDefinition
90 {
91 IOobject io
92 (
93 "faMeshDefinition",
94 mesh_.time().caseSystem(),
95 mesh_,
99 );
100
101 if (io.typeHeaderOk<IOdictionary>(false))
102 {
103 Info<< "Using system/faMeshDefinition" << nl;
104 faMeshDefinition = IOdictionary(io);
105 }
106 else if (debug)
107 {
108 Info<< "No " << io.name() << " in " << io.path() << nl;
109 }
110 }
111
112 // Check and read system/finite-area/faMeshDefinition
113 if (faMeshDefinition.empty())
114 {
115 IOobject io
116 (
117 "faMeshDefinition",
118 mesh_.time().caseSystem()/faMesh::prefix(),
119 mesh_,
123 );
124
125 if (io.typeHeaderOk<IOdictionary>(false))
126 {
127 Info<< "Using system/finite-area/faMeshDefinition" << nl;
128 faMeshDefinition = IOdictionary(io);
129 }
130 else if (debug)
131 {
132 Info<< "No " << io.name() << " in " << io.path() << nl;
133 }
134 }
135
136 // No specified faMeshDefinition?
137 // - generate faMesh from all patches on which we compute sensitivities
138
139 if (faMeshDefinition.empty())
140 {
141 wordList polyMeshPatches(sensitivityPatchIDs_.size());
142 label i(0);
143 for (const label patchID : sensitivityPatchIDs_)
144 {
145 polyMeshPatches[i++] = mesh_.boundary()[patchID].name();
146 }
147 faMeshDefinition.add<wordList>("polyMeshPatches", polyMeshPatches);
148 (void)faMeshDefinition.subDictOrAdd("boundary");
149
150 // TBD: Place all edges into the "defaultPatch" ?
151 // faMeshDefinition.subDictOrAdd("defaultPatch")
152 // .add("name", "undefined");
153
154 Info<< "Create faMeshDefinition from sensitivity patches"
155 << nl << nl;
156
157 faMeshDefinition.writeEntry("faMeshDefinition", Info);
158 }
159
160 // Construct faMesh from faMeshDefinition
161 aMeshPtr.reset(new faMesh(mesh_, faMeshDefinition));
162 }
163 faMesh& aMesh = *aMeshPtr;
164
165
166 // Physical radius of the smoothing, provided either directly or computed
167 // based on the average 'length' of boundary faces
168 const scalar Rphysical
169 (dict().getOrDefault<scalar>("radius", computeRadius(aMesh)));
171 << "Physical radius of the sensitivity smoothing "
172 << Rphysical << nl << endl;
173
174 // Radius used as the diffusivity in the Helmholtz filter, computed as a
175 // function of the physical radius
176 const dimensionedScalar RpdeSqr
177 (
178 "RpdeSqr", dimArea, sqr(Rphysical/(2.*::sqrt(3.)))
179 );
180
181 dimensionedScalar one(dimless, Foam::one{});
182
183 // Mapping engine
184 volSurfaceMapping vsm(aMesh);
185
186 // Source term in faMatrix needs to be an areaField
187 areaVectorField sens
188 (
189 aMesh.newIOobject("sens"),
190 aMesh,
191 dimensionedVector(dimless, Foam::zero{}),
193 );
194
195 // Copy sensitivities to area field
196 sens.primitiveFieldRef() =
197 vsm.mapToSurface<vector>(wallFaceSensVecPtr_());
198
199 // Initialisation of the smoothed sensitivities field based on the original
200 // sensitivities
201 areaVectorField smoothedSens("smoothedSens", sens);
202 for (label iter = 0; iter < iters; ++iter)
203 {
204 Info<< "Sensitivity smoothing iteration " << iter << endl;
205
206 faVectorMatrix smoothEqn
207 (
208 fam::Sp(one, smoothedSens)
209 - fam::laplacian(RpdeSqr, smoothedSens)
210 ==
211 sens
212 );
213
214 smoothEqn.relax();
215
216 const scalar residual(mag(smoothEqn.solve().initialResidual()));
217
219 << "Max smoothSens " << gMax(mag(smoothedSens)()) << endl;
220
221 // Print execution time
222 mesh_.time().printExecutionTime(Info);
223
224 // Check convergence
225 if (residual < tolerance)
226 {
227 Info<< "\n***Reached smoothing equation convergence limit, "
228 "iteration " << iter << "***\n\n";
229 break;
230 }
231 }
232
233 // Transfer smooth sensitivity field to wallFaceSensVecPtr_ for defining
234 // derivatives_
235 vsm.mapToVolume(smoothedSens, wallFaceSensVecPtr_());
236
237 // Write normal, regularised sensitivities to file
238 volScalarField volSmoothedSens
239 (
240 mesh_.newIOobject("smoothedSurfaceSens" + suffix_),
241 mesh_,
243 );
244 areaVectorField nf(aMesh.faceAreaNormals());
245 nf.normalise();
246 areaScalarField smoothedSensNormal(smoothedSens & nf);
247 vsm.mapToVolume(smoothedSensNormal, volSmoothedSens.boundaryFieldRef());
248 volSmoothedSens.write();
249}
250
251
252scalar sensitivitySurface::computeRadius(const faMesh& aMesh)
253{
254 scalar averageArea(gAverage(aMesh.S().field()));
255 const Vector<label>& geometricD = mesh_.geometricD();
256 const boundBox& bounds = mesh_.bounds();
257 forAll(geometricD, iDir)
258 {
259 if (geometricD[iDir] == -1)
260 {
261 averageArea /= bounds.span()[iDir];
262 }
263 }
264 scalar mult = dict().getOrDefault<scalar>("meanRadiusMultiplier", 10);
266 return mult*pow(averageArea, scalar(1)/scalar(mesh_.nGeometricD() - 1));
267}
268
269
270// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
271
272sensitivitySurface::sensitivitySurface
273(
274 const fvMesh& mesh,
275 const dictionary& dict,
277)
278:
280 smoothSensitivities_(dict.getOrDefault("smoothSensitivities", false)),
281 returnVectorField_
282 (dict.getOrDefault<bool>("returnVectorField", true))
283 //finalResultIncludesArea_
284 // (dict.getOrDefault<bool>("finalResultIncludesArea", false))
285{
286 // Allocate boundary field pointers
292}
293
294
295// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
296
298{
300 smoothSensitivities_ = dict().getOrDefault("smoothSensitivities", false);
302 dict().getOrDefault<bool>("returnVectorField", true);
303 //finalResultIncludesArea_ =
304 // dict().getOrDefault<bool>("finalResultIncludesArea", false);
305}
306
307
309(
310 autoPtr<designVariables>& designVars
311)
312{
313 // Compute point-based sensitivities
315
316 // Transfer point sensitivities to point field
317 vectorField pointSens(mesh_.nPoints(), Zero);
318 for (const label patchI : sensitivityPatchIDs_)
319 {
320 const polyPatch& pp = mesh_.boundaryMesh()[patchI];
321 const labelList& meshPoints = pp.meshPoints();
322 forAll(meshPoints, ppi)
323 {
324 pointSens[meshPoints[ppi]] = wallPointSensVecPtr_()[patchI][ppi];
325 }
326 }
327
328 // vectorField face-sensitivities
329 vectorField faceVecSens(computeFaceDerivativesSize(false), Zero);
330
331 // Map sensitivities from points to faces
332 volPointInterpolationAdjoint interpolation(mesh_);
333 interpolation.interpolateSensitivitiesField
334 (pointSens, faceVecSens, sensitivityPatchIDs_);
335
336 // Transfer non-regularised sensitivities to wallFaceSens* fields and write
337 label nPassedFaces(0);
338 for (const label patchI : sensitivityPatchIDs_)
339 {
340 const fvPatch& patch = mesh_.boundary()[patchI];
341 tmp<vectorField> nf = patch.nf();
342 wallFaceSensVecPtr_()[patchI] =
343 SubField<vector>(faceVecSens, patch.size(), nPassedFaces)
344 /patch.magSf();
345 wallFaceSensNormalPtr_()[patchI] = wallFaceSensVecPtr_()[patchI] & nf();
346 wallFaceSensNormalVecPtr_()[patchI] =
347 wallFaceSensNormalPtr_()[patchI]*nf;
348 nPassedFaces += patch.size();
349 }
350 write();
351
352 // Regularise sensitivities if necessary
354 {
356 }
357
358 // Make sure we have the correct sensitivities size
360 nPassedFaces = 0;
361 for (const label patchI : sensitivityPatchIDs_)
362 {
363 const fvPatch& patch = mesh_.boundary()[patchI];
364 const vectorField nf(patch.nf());
366 {
367 const Vector<label>& sd = mesh_.solutionD();
368 forAll(patch, fI)
369 {
370 const label gfI = nPassedFaces + fI;
371 const vector& fSens = wallFaceSensVecPtr_()[patchI][fI];
372 derivatives_[3*gfI ] = scalar(sd[0] == -1 ? 0 : fSens.x());
373 derivatives_[3*gfI + 1] = scalar(sd[1] == -1 ? 0 : fSens.y());
374 derivatives_[3*gfI + 2] = scalar(sd[2] == -1 ? 0 : fSens.z());
375 }
376 }
377 else
378 {
379 forAll(patch, fI)
380 {
381 derivatives_[nPassedFaces + fI]
382 = wallFaceSensVecPtr_()[patchI][fI] & nf[fI];
383 }
384 }
385 nPassedFaces += patch.size();
386 }
387}
388
389
390// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
391
392} // End namespace Foam
393
394// ************************************************************************* //
Macros for easy insertion into run-time selection tables.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
uindirectPrimitivePatch pp(UIndirectList< face >(mesh.faces(), faceLabels), mesh.points())
bool empty() const noexcept
True if the list is empty.
Definition DLListBase.H:189
Internal::FieldType & primitiveFieldRef(const bool updateAccessTime=true)
Return a reference to the internal field values.
Boundary & boundaryFieldRef(const bool updateAccessTime=true)
Return a reference to the boundary field.
void normalise()
Normalise the field inplace. See notes in Field.
IOdictionary is derived from dictionary and IOobject to give the dictionary automatic IO functionalit...
@ NO_REGISTER
Do not request registration (bool: false).
@ MUST_READ
Reading required.
@ NO_WRITE
Ignore writing from objectRegistry::writeObject().
Defines the attributes of an object for which implicit objectRegistry management is supported,...
Definition IOobject.H:191
autoPtr< boundaryVectorField > wallFaceSensVecPtr_
Wall face sens w.r.t. (x,y.z).
labelHashSet sensitivityPatchIDs_
Patches on which to compute shape sensitivities.
autoPtr< pointBoundaryVectorField > wallPointSensVecPtr_
Wall point sens w.r.t. (x,y.z).
autoPtr< boundaryScalarField > wallFaceSensNormalPtr_
Wall face sens projected to normal.
autoPtr< boundaryVectorField > wallFaceSensNormalVecPtr_
Normal sens as vectors.
const Type & initialResidual() const noexcept
Return initial residual.
SubField is a Field obtained as a section of another Field, without its own allocation....
Definition SubField.H:58
Templated 3D Vector derived from VectorSpace adding construction from 3 components,...
Definition Vector.H:61
const Cmpt & x() const noexcept
Access to the vector x component.
Definition Vector.H:135
const Cmpt & z() const noexcept
Access to the vector z component.
Definition Vector.H:145
const Cmpt & y() const noexcept
Access to the vector y component.
Definition Vector.H:140
Abstract base class for adjoint-based sensitivities.
scalarField derivatives_
The sensitivity derivative values.
word suffix_
Append this word to files related to the sensitivities.
Base class for adjoint solvers.
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition autoPtr.H:65
void reset(T *p=nullptr) noexcept
Delete managed object and set to new given pointer.
Definition autoPtrI.H:37
A bounding box defined in terms of min/max extrema points.
Definition boundBox.H:71
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition dictionary.H:133
dictionary & subDictOrAdd(const word &keyword, enum keyType::option matchOpt=keyType::REGEX)
Find and return a sub-dictionary for manipulation.
Definition dictionary.C:481
void writeEntry(Ostream &os) const
Write sub-dictionary with its dictName as its header.
entry * add(entry *entryPtr, bool mergeEntry=false)
Add a new entry.
Definition dictionary.C:625
void relax(const scalar alpha)
Relax matrix (for steady-state solution).
Definition faMatrix.C:484
SolverPerformance< Type > solve(const dictionary &)
Solve returning the solution statistics.
Finite area mesh (used for 2-D non-Euclidian finite area method) defined using a patch of faces on a ...
Definition faMesh.H:140
const DimensionedField< scalar, areaMesh > & S() const
Return face areas.
Definition faMesh.C:1139
static autoPtr< faMesh > TryNew(const word &areaName, const polyMesh &pMesh)
Read construction from polyMesh if all files are available.
Definition faMeshNew.C:188
static const word & prefix() noexcept
The prefix to the parent registry name: finite-area.
Definition faMesh.C:66
const areaVectorField & faceAreaNormals() const
Return face area normals.
Definition faMesh.C:1189
static const word & zeroGradientType() noexcept
The type name for zeroGradient patch fields.
Mesh data needed to do the Finite Volume discretisation.
Definition fvMesh.H:85
const fvBoundaryMesh & boundary() const noexcept
Return reference to boundary mesh.
Definition fvMesh.H:395
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition fvPatch.H:71
Abstract base class for volume field interpolation.
IOobject newIOobject(const word &name, IOobjectOption ioOpt) const
Create an IOobject at the current time instance (timeName) with the specified options.
A class representing the concept of 1 (one) that can be used to avoid manipulating objects known to b...
Definition one.H:57
const polyBoundaryMesh & boundaryMesh() const noexcept
Return boundary mesh.
Definition polyMesh.H:609
const boundBox & bounds() const noexcept
Return mesh bounding box.
Definition polyMesh.H:617
const Vector< label > & geometricD() const
Return the vector of geometric directions in mesh.
Definition polyMesh.C:850
A patch is a list of labels that address the faces in the global face list.
Definition polyPatch.H:73
label nPoints() const noexcept
Number of mesh points.
virtual bool write(const bool writeOnProc=true) const
Write using setting from DB.
Calculation of adjoint-based sensitivities at wall points using the E-SI formulation.
void read()
Read controls and update solver pointers if necessary.
virtual void assembleSensitivities(autoPtr< designVariables > &designVars)
Assemble sensitivities.
Calculation of adjoint based sensitivities at wall faces.
void read()
Read controls and update solver pointers if necessary.
bool returnVectorField_
Return the complete vector of sensitivities.
scalar computeRadius(const faMesh &aMesh)
Compute the physical smoothing radius based on the average boundary face 'length'.
bool smoothSensitivities_
Smooth sensitivity derivatives based on a surface Laplace solver.
label computeFaceDerivativesSize(const bool computeVectorFieldSize)
Compute the size of the return field.
void smoothSensitivities()
Smooth sensitivity derivatives based on the computation of the 'Sobolev gradient'.
virtual void assembleSensitivities(autoPtr< designVariables > &designVars)
Assemble sensitivities.
const fvMesh & mesh_
Definition sensitivity.H:68
A class for managing temporary objects.
Definition tmp.H:75
Interpolate from cell centres to points (vertices) using inverse distance weighting.
Volume to surface and surface to volume mapping.
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition zero.H:58
#define defineTypeNameAndDebug(Type, DebugSwitch)
Define the typeName and debug information.
Definition className.H:142
dynamicFvMesh & mesh
const volSurfaceMapping vsm(aMesh)
Calculate the matrix for the laplacian of the field.
Calculate the finiteArea matrix for implicit and explicit sources.
const auto & io
#define DebugInfo
Report an information message using Foam::Info.
Namespace for bounding specifications. At the moment, mostly for tables.
Namespace for handling debugging switches.
Definition debug.C:45
tmp< faMatrix< Type > > laplacian(const GeometricField< Type, faPatchField, areaMesh > &vf)
zeroField Sp(const Foam::zero, const GeometricField< Type, faPatchField, areaMesh > &)
A no-op source.
const std::string patch
OpenFOAM patch number as a std::string.
Namespace for OpenFOAM.
Type gAverage(const FieldField< Field, Type > &f, const label comm)
The global arithmetic average of a FieldField.
List< word > wordList
List of word.
Definition fileName.H:60
const dimensionSet dimless
Dimensionless.
List< label > labelList
A List of labels.
Definition List.H:62
dimensionedSymmTensor sqr(const dimensionedVector &dv)
GeometricField< scalar, fvPatchField, volMesh > volScalarField
const dimensionSet dimArea(sqr(dimLength))
messageStream Info
Information stream (stdout output on master, null elsewhere).
dimensionedScalar pow(const dimensionedScalar &ds, const dimensionedScalar &expt)
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition Ostream.H:519
GeometricField< vector, faPatchField, areaMesh > areaVectorField
dimensionedScalar sqrt(const dimensionedScalar &ds)
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
GeometricField< scalar, faPatchField, areaMesh > areaScalarField
faMatrix< vector > faVectorMatrix
Definition faMatrices.H:47
Field< vector > vectorField
Specialisation of Field<T> for vector.
static constexpr const zero Zero
Global zero (0).
Definition zero.H:127
autoPtr< typename GeometricField< Type, fvPatchField, volMesh >::Boundary > createZeroBoundaryPtr(const fvMesh &mesh, bool printAllocation=false)
dimensioned< scalar > dimensionedScalar
Dimensioned scalar obtained from generic dimensioned type.
Vector< scalar > vector
Definition vector.H:57
Type gMax(const FieldField< Field, Type > &f)
dimensioned< vector > dimensionedVector
Dimensioned vector obtained from generic dimensioned type.
constexpr char nl
The newline '\n' character (0x0a).
Definition Ostream.H:50
runTime write()
loopControl iters(runTime, aMesh.solutionDict(), "solution")
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition stdFoam.H:299