sensitivitySurfacePointsIncompressible.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
33#include "syncTools.H"
34
35// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
36
37namespace Foam
38{
39
40namespace incompressible
41{
42
43// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
44
47(
51);
52
53// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
54
56{
58 dict().getOrDefault<bool>("includeSurfaceArea", false);
60 dict().getOrDefault<bool>("includePressure", true);
62 dict().getOrDefault<bool>("includeGradStressTerm", true);
64 dict().getOrDefault<bool>("includeTransposeStresses", true);
66 dict().getOrDefault<bool>("useSnGradInTranposeStresses", false);
68 dict().getOrDefault<bool>("includeDivTerm", false);
70 dict().getOrDefault<bool>
71 (
72 "includeDistance",
73 adjointVars_.adjointTurbulence().ref().includeDistance()
74 );
76 dict().getOrDefault<bool>("includeMeshMovement", true);
78 dict().getOrDefault<bool>("includeObjectiveContribution", true);
79
80 // Allocate new solvers if necessary
82 {
83 eikonalSolver_.reset
84 (
86 (
87 mesh_,
88 dict(),
91 sensitivityPatchIDs_
92 )
93 );
94 }
95
97 {
99 (
101 (
102 mesh_,
103 dict(),
104 *this,
105 sensitivityPatchIDs_,
107 )
108 );
109 }
110}
111
112
114{
115 // Solve extra equations if necessary
116 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
117 autoPtr<boundaryVectorField> distanceSensPtr(nullptr);
119 {
120 eikonalSolver_->solve();
121 distanceSensPtr.reset(createZeroBoundaryPtr<vector>(mesh_));
122 const boundaryVectorField& sens =
123 eikonalSolver_->distanceSensitivities();
124 for (const label patchI : sensitivityPatchIDs_)
125 {
126 distanceSensPtr()[patchI] = sens[patchI];
127 }
128 }
129
130 autoPtr<boundaryVectorField> meshMovementSensPtr(nullptr);
132 {
133 meshMovementSolver_->solve();
134 meshMovementSensPtr.reset(createZeroBoundaryPtr<vector>(mesh_));
135 const boundaryVectorField& sens =
136 meshMovementSolver_->meshMovementSensitivities();
137 for (const label patchI : sensitivityPatchIDs_)
138 {
139 meshMovementSensPtr()[patchI] = sens[patchI];
140 }
141 }
142
143 // Add to other terms multiplying dxFace/dxPoints
144 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
145 for (const label patchI : sensitivityPatchIDs_)
146 {
147 const fvPatch& patch = mesh_.boundary()[patchI];
148 tmp<vectorField> tnf = patch.nf();
149 const scalarField& magSf = patch.magSf();
150 // Distance related terms
152 {
153 wallFaceSens_()[patchI] += distanceSensPtr()[patchI];
154 }
155
156 // Mesh movement related terms
158 {
159 wallFaceSens_()[patchI] += meshMovementSensPtr()[patchI];
160 }
161
162 // Add local face area
163 //~~~~~~~~~~~~~~~~~~~~
164 // Sensitivities DO include locale surface area, to get
165 // the correct weighting from the contributions of various faces.
166 // Normalized at the end.
167 // dSfdbMult already includes the local area. No need to re-multiply
168 wallFaceSens_()[patchI] *= magSf;
169 dnfdbMult_()[patchI] *= magSf;
170 }
171}
172
173
175{
176 // Geometric (or "direct") sensitivities are better computed directly on
177 // the points. Compute them and add the ones that depend on dxFace/dxPoint
178 for (const label patchI : sensitivityPatchIDs_)
179 {
180 const fvPatch& patch = mesh_.boundary()[patchI];
181 vectorField nf(patch.nf());
182
183 // Point sens result for patch
184 vectorField& pointPatchSens = wallPointSensVecPtr_()[patchI];
185
186 // Face sens for patch
187 const vectorField& facePatchSens = wallFaceSens_()[patchI];
188
189 // Geometry variances
190 const vectorField& dSfdbMultPatch = dSfdbMult_()[patchI];
191 const vectorField& dnfdbMultPatch = dnfdbMult_()[patchI];
192
193 // Correspondance of local point addressing to global point addressing
194 const labelList& meshPoints = patch.patch().meshPoints();
195
196 // List with mesh faces. Global addressing
197 const faceList& faces = mesh_.faces();
198
199 // Each local patch point belongs to these local patch faces
200 // (local numbering)
201 const labelListList& patchPointFaces = patch.patch().pointFaces();
202
203 // Index of first face in patch
204 const label patchStartIndex = patch.start();
205
206 // Geometry differentiation engine
207 deltaBoundary dBoundary(mesh_);
208
209 // Loop over patch points.
210 // Collect contributions from each boundary face this point belongs to
211 forAll(meshPoints, ppI)
212 {
213 const labelList& pointFaces = patchPointFaces[ppI];
214 forAll(pointFaces, pfI)
215 {
216 label localFaceIndex = pointFaces[pfI];
217 label globalFaceIndex = patchStartIndex + localFaceIndex;
218 const face& faceI = faces[globalFaceIndex];
219
220 // Point coordinates. All indices in global numbering
221 pointField p(faceI.points(mesh_.points()));
222 tensorField p_d(faceI.size(), Zero);
223 forAll(faceI, facePointI)
224 {
225 if (faceI[facePointI] == meshPoints[ppI])
226 {
227 p_d[facePointI] = tensor::I;
228 }
229 }
230 tensorField deltaNormals =
231 dBoundary.makeFaceCentresAndAreas_d(p, p_d);
232
233 // Element [0] is the variation in the face center
234 // (dxFace/dxPoint)
235 const tensor& deltaCf = deltaNormals[0];
236 pointPatchSens[ppI] += facePatchSens[localFaceIndex] & deltaCf;
237
238 // Term multiplying d(Sf)/d(point displacement) and
239 // d(nf)/d(point displacement)
240 //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
242 {
243 // Element [1] is the variation in the (dimensional) normal
244 const tensor& deltaSf = deltaNormals[1];
245 pointPatchSens[ppI] +=
246 dSfdbMultPatch[localFaceIndex] & deltaSf;
247
248 // Element [2] is the variation in the unit normal
249 const tensor& deltaNf = deltaNormals[2];
250 pointPatchSens[ppI] +=
251 dnfdbMultPatch[localFaceIndex] & deltaNf;
252 }
253 }
254 }
255 }
256}
257
258
260(
261 vectorField& pointNormals,
262 scalarField& pointMagSf
263)
264{
265 for (const label patchI : sensitivityPatchIDs_)
266 {
267 const fvPatch& patch = mesh_.boundary()[patchI];
268 const scalarField& magSf = patch.magSf();
269 vectorField nf(patch.nf());
270
271 // Correspondance of local point addressing to global point addressing
272 const labelList& meshPoints = patch.patch().meshPoints();
273
274 // Each local patch point belongs to these local patch faces
275 // (local numbering)
276 const labelListList& patchPointFaces = patch.patch().pointFaces();
277
278 // Loop over patch points
279 forAll(meshPoints, ppI)
280 {
281 const labelList& pointFaces = patchPointFaces[ppI];
282 forAll(pointFaces, pfI)
283 {
284 const label localFaceIndex = pointFaces[pfI];
285
286 // Accumulate information for point normals
287 pointNormals[meshPoints[ppI]] += nf[localFaceIndex];
288 pointMagSf[meshPoints[ppI]] += magSf[localFaceIndex];
289 }
290 }
291 }
292
294 (
295 mesh_,
296 pointNormals,
299 );
301 (
302 mesh_,
303 pointMagSf,
305 scalar(0)
306 );
307}
308
309
311{
312 word suffix(dict().getOrDefault<word>("suffix", word::null));
313 // Determine suffix for fields holding the sens
315 {
317 (
318 adjointVars_.solverName() + "ESI" + suffix
319 );
320 }
321 else
322 {
324 (
325 adjointVars_.solverName() + "SI" + suffix
326 );
327 }
328}
329
330
331// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
332
334(
335 const fvMesh& mesh,
336 const dictionary& dict,
338)
339:
342 includeSurfaceArea_(false),
343 includePressureTerm_(false),
344 includeGradStressTerm_(false),
345 includeTransposeStresses_(false),
346 useSnGradInTranposeStresses_(false),
347 includeDivTerm_(false),
348 includeDistance_(false),
349 includeMeshMovement_(false),
350 includeObjective_(false),
351 eikonalSolver_(nullptr),
352 meshMovementSolver_(nullptr),
353 wallFaceSens_(createZeroBoundaryPtr<vector>(mesh_)),
354 dSfdbMult_(createZeroBoundaryPtr<vector>(mesh_)),
355 dnfdbMult_(createZeroBoundaryPtr<vector>(mesh_))
356
357{
358 read();
359
360 // Allocate boundary field pointer
361 wallPointSensVecPtr_.reset(createZeroBoundaryPointFieldPtr<vector>(mesh_));
362 wallPointSensNormalPtr_.reset
363 (
364 createZeroBoundaryPointFieldPtr<scalar>(mesh_)
365 );
366 wallPointSensNormalVecPtr_.reset
367 (
368 createZeroBoundaryPointFieldPtr<vector>(mesh_)
369 );
370
371 // Allocate appropriate space for sensitivities
372 label nTotalPoints(0);
373 for (const label patchI : sensitivityPatchIDs_)
374 {
375 label nPoints = mesh_.boundaryMesh()[patchI].nPoints();
376 nTotalPoints += returnReduce(nPoints, sumOp<label>());
377 }
378
379 // Derivatives for all (x,y,z) components of the displacement are kept
380 derivatives_ = scalarField(3*nTotalPoints, Zero);
381}
382
383
384// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
385
386bool sensitivitySurfacePoints::readDict(const dictionary& dict)
387{
388 if (sensitivity::readDict(dict))
389 {
390 if (eikonalSolver_)
391 {
392 eikonalSolver_().readDict(dict);
393 }
394
396 {
397 meshMovementSolver_().readDict(dict);
398 }
399
400 return true;
401 }
402
403 return false;
404}
405
406
408{
409 // Grab references
410 const volScalarField& p = primalVars_.p();
411 const volVectorField& U = primalVars_.U();
412
413 const volScalarField& pa = adjointVars_.pa();
414 const volVectorField& Ua = adjointVars_.Ua();
417
418 // Solve extra equations if necessary
420 {
421 eikonalSolver_->accumulateIntegrand(dt);
422 }
423
425 {
426 meshMovementSolver_->accumulateIntegrand(dt);
427 }
428
429 // Terms from the adjoint turbulence model
430 const boundaryVectorField& adjointTMsensitivities =
431 adjointTurbulence->wallShapeSensitivities();
432
433 // Objective references
435
437 << " Calculating adjoint sensitivity. " << endl;
438
439 tmp<volScalarField> tnuEff = adjointTurbulence->nuEff();
440 const volScalarField& nuEff = tnuEff.ref();
441
442 // Deal with the stress part first since it's the most awkward in terms
443 // of memory managment
445 {
446 // Terms corresponding to contributions from converting delta
447 // to thetas are added through the corresponding adjoint
448 // boundary conditions instead of grabbing contributions from
449 // the objective function. Useful to have a unified
450 // formulation for low- and high-re meshes
451
453 const volVectorField& gradp = tgradp.ref();
454 for (const label patchI : sensitivityPatchIDs_)
455 {
456 const fvPatch& patch = mesh_.boundary()[patchI];
457 tmp<vectorField> tnf = patch.nf();
458 const fvPatchVectorField& Uab = Ua.boundaryField()[patchI];
459 wallFaceSens_()[patchI] -=
460 (Uab & tnf)*gradp.boundaryField()[patchI]*dt;
461 }
462 tgradp.clear();
463
464 // We only need to modify the boundaryField of gradU locally.
465 // If grad(U) is cached then
466 // a. The .ref() call fails since the tmp is initialised from a
467 // const ref
468 // b. we would be changing grad(U) for all other places in the code
469 // that need it
470 // So, always allocate new memory and avoid registering the new field
471 tmp<volTensorField> tgradU =
472 volTensorField::New("gradULocal", fvc::grad(U));
473 volTensorField::Boundary& gradUbf = tgradU.ref().boundaryFieldRef();
474
475 // Explicitly correct the boundary gradient to get rid of the
476 // tangential component
477 forAll(mesh_.boundary(), patchI)
478 {
479 const fvPatch& patch = mesh_.boundary()[patchI];
480 if (isA<wallFvPatch>(patch))
481 {
482 tmp<vectorField> tnf = mesh_.boundary()[patchI].nf();
483 gradUbf[patchI] = tnf*U.boundaryField()[patchI].snGrad();
484 }
485 }
486
487 tmp<volSymmTensorField> tstress = nuEff*twoSymm(tgradU);
488 const volSymmTensorField& stress = tstress.cref();
490 (Foam::createZeroFieldPtr<vector>(mesh_, "temp", sqr(dimVelocity)));
491 volVectorField& temp = ptemp.ref();
492 for (label idir = 0; idir < pTraits<vector>::nComponents; ++idir)
493 {
494 unzipRow(stress, idir, temp);
495 volTensorField gradStressDir(fvc::grad(temp));
496 for (const label patchI : sensitivityPatchIDs_)
497 {
498 const fvPatch& patch = mesh_.boundary()[patchI];
499 tmp<vectorField> tnf = patch.nf();
500 const fvPatchVectorField& Uab = Ua.boundaryField()[patchI];
501 wallFaceSens_()[patchI] +=
502 (
503 Uab.component(idir)
504 *(gradStressDir.boundaryField()[patchI] & tnf)
505 )*dt;
506 }
507 }
508 }
509
510 // Transpose part of the adjoint stresses
511 // Dealt with separately to deallocate gradUa as soon as possible
513 {
514 tmp<volTensorField> tgradUa = fvc::grad(Ua);
515 const volTensorField::Boundary& gradUabf =
516 tgradUa.cref().boundaryField();
517 for (const label patchI : sensitivityPatchIDs_)
518 {
519 const fvPatch& patch = mesh_.boundary()[patchI];
520 tmp<vectorField> tnf = patch.nf();
521 const vectorField& nf = tnf();
522 vectorField gradUaNf
523 (
525 ? (Ua.boundaryField()[patchI].snGrad() & nf)*nf
526 : (gradUabf[patchI] & nf)
527 );
528 wallFaceSens_()[patchI] -=
529 nuEff.boundaryField()[patchI]
530 *(gradUaNf & U.boundaryField()[patchI].snGrad())*tnf;
531 }
532 }
533
534 // The face-based part of the sensitivities, i.e. terms that multiply
535 // dxFace/dxPoint.
536 for (const label patchI : sensitivityPatchIDs_)
537 {
538 const fvPatch& patch = mesh_.boundary()[patchI];
539 tmp<vectorField> tnf = patch.nf();
540 const vectorField& nf = tnf();
541
542 // Adjoint stress term
543 // vectorField stressTerm
544 // (
545 // -(nf & DUa.boundaryField()[patchI])
546 // *nuEff.boundaryField()[patchI]
547 // & gradU.boundaryField()[patchI].T();
548 // )
549
550 vectorField stressTerm
551 (
552 - (
553 Ua.boundaryField()[patchI].snGrad()
554 & U.boundaryField()[patchI].snGrad()
555 )
556 * nuEff.boundaryField()[patchI]
557 * nf
558 );
559
560 if (includeDivTerm_)
561 {
562 stressTerm +=
563 scalar(1./3.)*nuEff.boundaryField()[patchI]
564 * (
565 ((Ua.boundaryField()[patchI].snGrad() &nf)*nf)
566 & U.boundaryField()[patchI].snGrad()
567 )
568 *nf;
569 }
570
571 // Adjoint pressure terms
572 vectorField pressureTerm(patch.size(), Zero);
574 {
575 pressureTerm =
576 (
577 (nf*pa.boundaryField()[patchI])
578 & U.boundaryField()[patchI].snGrad()
579 )
580 *nf;
581 }
582
583 vectorField dxdbMultiplierTot(patch.size(), Zero);
585 {
586 // Term from objectives multiplying dxdb
587 forAll(functions, funcI)
588 {
589 const scalar wei = functions[funcI].weight();
590 // dt added in wallFaceSens_
591 dxdbMultiplierTot +=
592 wei*functions[funcI].dxdbDirectMultiplier(patchI);
593
594 // Fill in multipliers of d(Sf)/db and d(nf)/db
595 dSfdbMult_()[patchI] +=
596 wei*dt*functions[funcI].dSdbMultiplier(patchI);
597 dnfdbMult_()[patchI] +=
598 wei*dt*functions[funcI].dndbMultiplier(patchI);
599 }
600 }
601
602 // Fill in dxFace/dxPoint multiplier.
603 // Missing geometric contributions which are directly computed on the
604 // points
605 wallFaceSens_()[patchI] +=
606 (
607 stressTerm
608 + pressureTerm
609 + adjointTMsensitivities[patchI]
610 + dxdbMultiplierTot
611 )*dt;
612 }
613
614 // Add terms from physics other than the typical incompressible flow eqns
616 (wallFaceSens_(), sensitivityPatchIDs_, dt);
617}
618
619
621{
622 // Add remaining parts to term multiplying dxFace/dxPoints
623 // Solves for post-processing PDEs
625
626 // Geometric (or "direct") sensitivities are better computed directly on
627 // the points. Compute them and add the ones that depend on dxFace/dxPoint
629
630 // polyPatch::pointNormals will give the wrong result for points
631 // belonging to multiple patches or patch-processorPatch intersections.
632 // Keeping a mesh-wide field to allow easy reduction using syncTools.
633 // A bit expensive? Better way?
634 vectorField pointNormals(mesh_.nPoints(), Zero);
635 scalarField pointMagSf(mesh_.nPoints(), Zero);
636 constructGlobalPointNormalsAndAreas(pointNormals, pointMagSf);
637
638 // Do parallel communications to avoid wrong values at processor boundaries
639 // Global field for accumulation
640 vectorField pointSensGlobal(mesh_.nPoints(), Zero);
641 for (const label patchI : sensitivityPatchIDs_)
642 {
643 const labelList& meshPoints = mesh_.boundaryMesh()[patchI].meshPoints();
644 forAll(meshPoints, ppI)
645 {
646 const label globaPointI = meshPoints[ppI];
647 pointSensGlobal[globaPointI] +=
648 wallPointSensVecPtr_()[patchI][ppI];
649 }
650 }
651
652 // Accumulate dJ/dx_i
654 (
655 mesh_,
656 pointSensGlobal,
659 );
660
661 // Transfer back to local fields
662 for (const label patchI : sensitivityPatchIDs_)
663 {
664 const labelList& meshPoints =
665 mesh_.boundaryMesh()[patchI].meshPoints();
666 wallPointSensVecPtr_()[patchI].map(pointSensGlobal, meshPoints);
667 }
668
669 // Compute normal sens and append to return field
670 label nPassedDVs(0);
671 for (const label patchI : sensitivityPatchIDs_)
672 {
673 const polyPatch& patch = mesh_.boundaryMesh()[patchI];
674 List<scalarField> procPatchSens(Pstream::nProcs());
675 //if (patch.size()>0)
676 {
677 const labelList& meshPoints = patch.meshPoints();
678
679 // Avoid storing unit point normals in the global list since we
680 // might divide multiple times with the number of faces belonging
681 // to the point. Instead do the division locally, per patch use
682 vectorField patchPointNormals(pointNormals, meshPoints);
683 patchPointNormals /= mag(patchPointNormals) + VSMALL;
685 {
686 wallPointSensVecPtr_()[patchI] /=
687 scalarField(pointMagSf, meshPoints);
688 }
689 wallPointSensNormalPtr_()[patchI] =
690 wallPointSensVecPtr_()[patchI]
691 & patchPointNormals;
692 wallPointSensNormalVecPtr_()[patchI] =
693 wallPointSensNormalPtr_()[patchI]
694 *patchPointNormals;
695
696 // 1. Gather sens from all processors for this patch and communicate
697 // them back. Potentially large memory overhead but the rest of the
698 // code structure assumes that all procs know all sensitivity
699 // derivatives
700 //
701 // 2. Transfer vectorial sensitivities to scalarField.
702 // Needed since the normal point vector is wrongly computed at patch
703 // boundaries and cannot be used to reconstruct a vectorial movement
704 // from just its normal component
705 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
706
707 procPatchSens[Pstream::myProcNo()].setSize
708 (
709 3*wallPointSensNormalVecPtr_()[patchI].size()
710 );
711 scalarField& patchScalarSens = procPatchSens[Pstream::myProcNo()];
712 forAll(wallPointSensNormalVecPtr_()[patchI], ptI)
713 {
714 patchScalarSens[3*ptI] =
715 wallPointSensNormalVecPtr_()[patchI][ptI].x();
716 patchScalarSens[3*ptI + 1] =
717 wallPointSensNormalVecPtr_()[patchI][ptI].y();
718 patchScalarSens[3*ptI + 2] =
719 wallPointSensNormalVecPtr_()[patchI][ptI].z();
720 }
721 Pstream::allGatherList(procPatchSens);
722
723 forAll(procPatchSens, procI)
724 {
725 const scalarField& procSens = procPatchSens[procI];
726 forAll(procSens, dvI)
727 {
728 derivatives_[nPassedDVs + dvI] = procSens[dvI];
729 }
730 nPassedDVs += procSens.size();
731 }
732 }
733 }
734}
735
736
738{
739 // Reset terms in post-processing PDEs
741 {
742 eikonalSolver_->reset();
743 }
745 {
746 meshMovementSolver_->reset();
747 }
748
749 // Reset local fields to zero
753
754 // Reset sensitivity fields
757}
758
759
761{
765}
766
767
768// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
769
770} // End namespace Foam
771} // End namespace incompressible
772
773// ************************************************************************* //
Macros for easy insertion into run-time selection tables.
#define addToRunTimeSelectionTable(baseType, thisType, argNames)
Add to construction table with typeName as the key.
tmp< Field< cmptType > > component(const direction) const
Return a component field of the field.
Definition: Field.C:545
Generic GeometricBoundaryField class.
const Boundary & boundaryField() const
Return const-reference to the boundary field.
void setSize(const label n)
Alias for resize()
Definition: List.H:218
label nProcs() const noexcept
Number of ranks associated with PstreamBuffers.
static void allGatherList(const List< commsStruct > &comms, List< T > &values, const int tag, const label comm)
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers....
Definition: PtrList.H:73
static const Tensor I
Definition: Tensor.H:81
static autoPtr< Time > New()
Construct (dummy) Time - no functionObjects or libraries.
Definition: Time.C:717
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
Base class for adjoint solvers.
Definition: adjointSolver.H:60
Pointer management similar to std::unique_ptr, with some additional methods and type checking.
Definition: autoPtr.H:66
T & ref()
Return reference to the managed object without nullptr checking.
Definition: autoPtr.H:161
void reset(autoPtr< T > &&other) noexcept
Delete managed object and set to new given pointer.
Definition: autoPtrI.H:117
Differentiation of the mesh data structure.
Definition: deltaBoundary.H:59
vectorField makeFaceCentresAndAreas_d(const pointField &p, const pointField &p_d)
Definition: deltaBoundary.C:72
A list of keyword definitions, which are a keyword followed by a number of values (eg,...
Definition: dictionary.H:126
T getOrDefault(const word &keyword, const T &deflt, enum keyType::option matchOpt=keyType::REGEX) const
A face is a list of labels corresponding to mesh vertices.
Definition: face.H:75
pointField points(const UList< point > &pts) const
Return the points corresponding to this face.
Definition: faceI.H:87
virtual bool write()
Write the output fields.
Mesh data needed to do the Finite Volume discretisation.
Definition: fvMesh.H:91
const fvBoundaryMesh & boundary() const
Return reference to boundary mesh.
Definition: fvMesh.C:712
A finiteVolume patch using a polyPatch and a fvBoundaryMesh.
Definition: fvPatch.H:71
const volScalarField & pa() const
Return const reference to pressure.
const volVectorField & Ua() const
Return const reference to velocity.
Base class for incompressibleAdjoint solvers.
virtual void additionalSensitivityMapTerms(boundaryVectorField &sensitivityMap, const labelHashSet &patchIDs, const scalar dt)
const autoPtr< incompressibleAdjoint::adjointRASModel > & adjointTurbulence() const
Return const reference to the adjointRASModel.
const volVectorField & U() const
Return const reference to velocity.
const volScalarField & p() const
Return const reference to pressure.
const autoPtr< incompressible::RASModelVariables > & RASModelVariables() const
Return const reference to the turbulence model variables.
Solver of the adjoint to the Laplace grid displacement equation.
Abstract base class for adjoint-based sensitivities in incompressible flows.
virtual void clearSensitivities()
Zero sensitivity fields and their constituents.
Calculation of adjoint based sensitivities at wall points.
bool includeTransposeStresses_
Include the transpose part of the adjoint stresses.
virtual void clearSensitivities()
Zero sensitivity fields and their constituents.
bool includeDistance_
Include distance variation in sens computation.
bool useSnGradInTranposeStresses_
Use snGrad in the transpose part of the adjoint stresses.
void constructGlobalPointNormalsAndAreas(vectorField &pointNormals, scalarField &pointMagSf)
Construct globally correct point normals and point areas.
void setSuffixName()
Set suffix name for sensitivity fields.
autoPtr< boundaryVectorField > wallFaceSens_
The face-based part of the sensitivities.
bool includePressureTerm_
Include the adjoint pressure term in sens computation.
bool includeGradStressTerm_
Include the term containing the grad of the stress at the boundary.
bool includeSurfaceArea_
Include surface area in sens computation.
void read()
Read controls and update solver pointers if necessary.
bool includeMeshMovement_
Include mesh movement variation in sens computation.
bool includeDivTerm_
Include the term from the deviatoric part of the stresses.
virtual void accumulateIntegrand(const scalar dt)
Accumulate sensitivity integrands.
autoPtr< boundaryVectorField > dSfdbMult_
Multipliers of d(Sf)/db and d(nf)/db.
bool includeObjective_
Include terms directly emerging from the objective function.
PtrList< objective > & getObjectiveFunctions()
Return reference to objective functions.
virtual const faceList & faces() const
Return raw faces.
Definition: polyMesh.C:1108
const polyBoundaryMesh & boundaryMesh() const
Return boundary mesh.
Definition: polyMesh.H:456
virtual const pointField & points() const
Return raw points.
Definition: polyMesh.C:1083
A patch is a list of labels that address the faces in the global face list.
Definition: polyPatch.H:75
label nPoints() const noexcept
Number of mesh points.
int myProcNo() const noexcept
Return processor number.
const fvMesh & mesh_
Definition: sensitivity.H:69
const dictionary & dict() const
Return the construction dictionary.
Definition: sensitivity.C:57
void clearSensitivities()
Zero sensitivity fields and their constituents.
void setSuffix(const word &suffix)
Set suffix.
void write()
Write sensitivity fields.
static void syncPointList(const polyMesh &mesh, List< T > &pointValues, const CombineOp &cop, const T &nullValue, const TransformOp &top)
Synchronize values on all mesh points.
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
const word & solverName() const
Return solver name.
Definition: variablesSet.C:84
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
volScalarField & p
dynamicFvMesh & mesh
label nPoints
#define DebugInfo
Report an information message using Foam::Info.
tmp< GeometricField< typename outerProduct< vector, Type >::type, fvPatchField, volMesh > > grad(const GeometricField< Type, fvsPatchField, surfaceMesh > &ssf)
Definition: fvcGrad.C:54
Namespace for OpenFOAM.
dimensionedSymmTensor sqr(const dimensionedVector &dv)
dimensionedSymmTensor twoSymm(const dimensionedSymmTensor &dt)
const dimensionSet dimVelocity
Field< scalar > scalarField
Specialisation of Field<T> for scalar.
Ostream & endl(Ostream &os)
Add newline and flush stream.
Definition: Ostream.H:372
dimensioned< typename typeOfMag< Type >::type > mag(const dimensioned< Type > &dt)
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
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)
T returnReduce(const T &value, const BinaryOp &bop, const int tag=UPstream::msgType(), const label comm=UPstream::worldComm)
Reduce (copy) and return value.
autoPtr< typename GeometricField< Type, fvPatchField, volMesh >::Boundary > createZeroBoundaryPtr(const fvMesh &mesh, bool printAllocation=false)
dictionary dict
#define forAll(list, i)
Loop across all elements in list.
Definition: stdFoam.H:333
A non-counting (dummy) refCount.
Definition: refCount.H:59