mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: overhaul of the adjoint optimisation library
Parts of the adjoint optimisation library were re-designed to generalise the way sensitivity derivatives (SDs) are computed and to allow easier extension to primal problems other than the ones governed by incompressible flows. In specific: - the adjoint solver now holds virtual functions returning the part of SDs that depends only on the primal and the adjoint fields. - a new class named designVariables was introduced which, apart from defining the design variables of the optimisation problem and providing hooks for updating them in an optimisation loop, provides the part of the SDs that affects directly the flow residuals (e.g. geometric variations in shape optimisation, derivatives of source terms in topology optimisation, etc). The final assembly of the SDs happens here, with the updated sensitivity class acting as an intermediate. With the new structure, when the primal problem changes (for instance, passive scalars are included), the same design variables and sensitivity classes can be re-used for all physics, with additional contributions to the SDs being limited (and contained) to the new adjoint solver to be implemented. The old code structure would require new SD classes for each additional primal problem. As a side-effect, setting up a case has arguably become a bit easier and more intuitive. Additional changes include: --------------------------- - Changes in the formulation and computation of shape sensitivity derivatives using the E-SI approach. The latter is now derived directly from the FI approach, with proper discretization for the terms and boundary conditions that emerge from applying the Gauss divergence theorem used to transition from FI to E-SI. When E-SI and FI are based on the same Laplace grid displacement model, they are now numerically equivalent (the previous formulation proved the theoretical equivalence of the two approaches but numerical results could differ, depending on the case). - Sensitivity maps at faces are now computed based (and are deriving from) sensitivity maps at points, with a constistent point-to-face interpolation (requires the differentiation of volPointInterpolation). - The objective class now allocates only the member pointers that correspond to the non-zero derivatives of the objective w.r.t. the flow and geometric quantities, leading to a reduced memory footprint. Additionally, contributions from volume-based objectives to the adjoint equations have been re-worked, removing the need for objectiveManager to be virtual. - In constrained optimisation, an adjoint solver needs to be present for each constraint function. For geometric constraints though, no adjoint equations need to solved. This is now accounted for through the null adjoint solver and the geometric objectives which do not allocate adjoint fields for this kind of constraints, reducing memory requirements and file clutter. - Refactoring of the updateMethod to collaborate with the new designVariables. Additionally, all updateMethods can now read and write restart data in binary, facilitating exact continuation. Furthermore, code shared by various quasi-Newton methods (BFGS, DBFGS, LBFGS, SR1) has been organised in the namesake class. Over and above, an SQP variant capable of tackling inequality constraints has been added (ISQP, with I indicating that the QP problem in the presence of inequality constraints is solved through an interior point method). Inequality constraints can be one-sided (constraint < upper-value) or double-sided (lower-value < constraint < upper-value). - Bounds can now be defined for the design variables. For volumetricBSplines in specific, these can be computed as the mid-points of the control points and their neighbouring ones. This usually leads to better-defined optimisation problems and reduces the chances of an invalid mesh during optimisation. - Convergence criteria can now be defined for the optimisation loop which will stop if the relative objective function reduction over the last objective value is lower than a given threshold and constraints are satisfied within a give tolerance. If no criteria are defined, the optimisation will run for the max. given number of cycles provided in controlDict. - Added a new grid displacement method based on the p-Laplacian equation, which seems to outperform other PDE-based approaches. TUT: updated the shape optimisation tutorials and added a new one showcasing the use of double-sided constraints, ISQP, applying no-overlapping constraints to volumetric B-Splines control points and defining convergence criteria for the optimisation loop.
This commit is contained in:
committed by
Andrew Heather
parent
ae8b654a86
commit
b6a30fae61
@ -64,13 +64,13 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
// Solve all primal equations
|
// Solve all primal equations
|
||||||
om.solvePrimalEquations();
|
om.solvePrimalEquations();
|
||||||
|
|
||||||
|
// Clear sensitivities
|
||||||
|
om.clearSensitivities();
|
||||||
|
|
||||||
|
// Solve all adjoint equations
|
||||||
|
om.solveAdjointEquations();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update primal-based quantities of the adjoint solvers
|
|
||||||
om.updatePrimalBasedQuantities();
|
|
||||||
|
|
||||||
// Solve all adjoint equations
|
|
||||||
om.solveAdjointEquations();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Info<< "End\n" << endl;
|
Info<< "End\n" << endl;
|
||||||
|
|||||||
@ -60,7 +60,8 @@ int main(int argc, char *argv[])
|
|||||||
forAll(adjointSolvers, asI)
|
forAll(adjointSolvers, asI)
|
||||||
{
|
{
|
||||||
adjointSolvers[asI].getObjectiveManager().updateAndWrite();
|
adjointSolvers[asI].getObjectiveManager().updateAndWrite();
|
||||||
adjointSolvers[asI].computeObjectiveSensitivities();
|
adjointSolvers[asI].
|
||||||
|
computeObjectiveSensitivities(om.getDesignVariables());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +0,0 @@
|
|||||||
writeActiveDesignVariables.C
|
|
||||||
|
|
||||||
EXE = $(FOAM_APPBIN)/writeActiveDesignVariables
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
EXE_INC = \
|
|
||||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
|
||||||
-I$(LIB_SRC)/meshTools/lnInclude \
|
|
||||||
-I$(LIB_SRC)/finiteVolume/cfdTools \
|
|
||||||
-I$(LIB_SRC)/dynamicMesh/lnInclude \
|
|
||||||
-I$(LIB_SRC)/optimisation/adjointOptimisation/adjoint/lnInclude
|
|
||||||
|
|
||||||
EXE_LIBS = \
|
|
||||||
-lfiniteVolume \
|
|
||||||
-lmeshTools \
|
|
||||||
-lfvOptions \
|
|
||||||
-ldynamicMesh \
|
|
||||||
-lfvMotionSolvers \
|
|
||||||
-ladjointOptimisation
|
|
||||||
@ -1,108 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | www.openfoam.com
|
|
||||||
\\/ M anipulation |
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
|
||||||
Copyright (C) 2013-2019 FOSS GP
|
|
||||||
Copyright (C) 2019-2022 OpenCFD Ltd.
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
License
|
|
||||||
This file is part of OpenFOAM.
|
|
||||||
|
|
||||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Application
|
|
||||||
writeActiveDesignVariables
|
|
||||||
|
|
||||||
Description
|
|
||||||
Writes the active design variables based on the selected parameterisation
|
|
||||||
scheme, as read from the meshMovement part of optimisationDict.
|
|
||||||
Keeps a back-up of the original optimisationDict in
|
|
||||||
system/optimisationDict.org, as comments in the dict will be lost.
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "fvCFD.H"
|
|
||||||
#include "optMeshMovement.H"
|
|
||||||
#include "updateMethod.H"
|
|
||||||
#include "OFstream.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
|
||||||
{
|
|
||||||
#include "setRootCase.H"
|
|
||||||
#include "createTime.H"
|
|
||||||
#include "createMesh.H"
|
|
||||||
|
|
||||||
IOdictionary optDict
|
|
||||||
(
|
|
||||||
IOobject
|
|
||||||
(
|
|
||||||
"optimisationDict",
|
|
||||||
mesh.time().caseSystem(),
|
|
||||||
mesh,
|
|
||||||
IOobject::MUST_READ_IF_MODIFIED,
|
|
||||||
IOobject::NO_WRITE
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Back-up old optimisationDict, to maintain potential comments in it
|
|
||||||
if (Pstream::master())
|
|
||||||
{
|
|
||||||
Foam::cp(optDict.objectPath(), optDict.objectPath() + ".org");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Construct mesh movement object and grab active design variables
|
|
||||||
// Will exit with error if not implemented for this type
|
|
||||||
const dictionary& movementDict =
|
|
||||||
optDict.subDict("optimisation").subDict("meshMovement");
|
|
||||||
// Empty patch list will do
|
|
||||||
labelList patchIDs(0);
|
|
||||||
autoPtr<optMeshMovement> movementPtr
|
|
||||||
(optMeshMovement::New(mesh, movementDict, patchIDs));
|
|
||||||
const labelList activeDesignVariables =
|
|
||||||
movementPtr().getActiveDesignVariables();
|
|
||||||
|
|
||||||
// Construct update method to grab the type
|
|
||||||
dictionary& updateMethodDict =
|
|
||||||
optDict.subDict("optimisation").subDict("updateMethod");
|
|
||||||
autoPtr<updateMethod> updMethod(updateMethod::New(mesh, updateMethodDict));
|
|
||||||
|
|
||||||
// Add to appropriate dictionary (creates it if it does not exist)
|
|
||||||
dictionary& coeffsDict = updateMethodDict.subDictOrAdd(updMethod().type());
|
|
||||||
coeffsDict.add<labelList>
|
|
||||||
(
|
|
||||||
"activeDesignVariables",
|
|
||||||
activeDesignVariables,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
// Write modified dictionary
|
|
||||||
optDict.regIOobject::writeObject
|
|
||||||
(
|
|
||||||
IOstreamOption(IOstreamOption::ASCII),
|
|
||||||
true
|
|
||||||
);
|
|
||||||
|
|
||||||
Info<< "End\n" << endl;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2021 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2021 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019-2021 OpenCFD Ltd.
|
Copyright (C) 2019-2021 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -214,6 +214,7 @@ void ATCModel::computeLimiter
|
|||||||
scheme.interpolate(limiter)
|
scheme.interpolate(limiter)
|
||||||
);
|
);
|
||||||
limiter = fvc::average(faceLimiter);
|
limiter = fvc::average(faceLimiter);
|
||||||
|
limiter.correctBoundaryConditions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -52,26 +52,26 @@ faceCells::faceCells
|
|||||||
:
|
:
|
||||||
zeroATCcells(mesh, dict)
|
zeroATCcells(mesh, dict)
|
||||||
{
|
{
|
||||||
|
DynamicList<label> cellIDs;
|
||||||
for (const fvPatch& patch : mesh_.boundary())
|
for (const fvPatch& patch : mesh_.boundary())
|
||||||
{
|
{
|
||||||
for (const word& patchType : zeroATCPatches_)
|
for (const word& patchType : zeroATCPatches_)
|
||||||
{
|
{
|
||||||
if (patch.type() == patchType)
|
if (patch.type() == patchType)
|
||||||
{
|
{
|
||||||
const labelList& faceCells_ = patch.faceCells();
|
cellIDs.push_back(patch.faceCells());
|
||||||
zeroATCcells_.append(faceCells_);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const label zoneID: zeroATCZones_)
|
for (const label zoneID : zeroATCZones_)
|
||||||
{
|
{
|
||||||
if (zoneID !=-1)
|
if (zoneID != -1)
|
||||||
{
|
{
|
||||||
const labelList& zoneCells = mesh_.cellZones()[zoneID];
|
cellIDs.push_back(mesh_.cellZones()[zoneID]);
|
||||||
zeroATCcells_.append(zoneCells);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
zeroATCZones_.transfer(cellIDs);
|
||||||
|
|
||||||
Info<< "Setting limiter on "
|
Info<< "Setting limiter on "
|
||||||
<< returnReduce(zeroATCcells_.size(), sumOp<label>())
|
<< returnReduce(zeroATCcells_.size(), sumOp<label>())
|
||||||
|
|||||||
@ -27,6 +27,7 @@ solvers/primalSolvers/incompressible/RASTurbulenceModel/RASTurbulenceModel.C
|
|||||||
solvers/adjointSolvers/adjointSolver/adjointSolver.C
|
solvers/adjointSolvers/adjointSolver/adjointSolver.C
|
||||||
solvers/adjointSolvers/incompressible/incompressibleAdjointSolver/incompressibleAdjointSolver.C
|
solvers/adjointSolvers/incompressible/incompressibleAdjointSolver/incompressibleAdjointSolver.C
|
||||||
solvers/adjointSolvers/incompressible/adjointSimple/adjointSimple.C
|
solvers/adjointSolvers/incompressible/adjointSimple/adjointSimple.C
|
||||||
|
solvers/adjointSolvers/null/adjointNull.C
|
||||||
|
|
||||||
/* ADJOINT SOLVER MANAGER */
|
/* ADJOINT SOLVER MANAGER */
|
||||||
solvers/adjointSolverManager/adjointSolverManager.C
|
solvers/adjointSolverManager/adjointSolverManager.C
|
||||||
@ -49,16 +50,16 @@ objectives/incompressible/objectiveForce/objectiveForce.C
|
|||||||
objectives/incompressible/objectiveMoment/objectiveMoment.C
|
objectives/incompressible/objectiveMoment/objectiveMoment.C
|
||||||
objectives/incompressible/objectivePtLosses/objectivePtLosses.C
|
objectives/incompressible/objectivePtLosses/objectivePtLosses.C
|
||||||
objectives/incompressible/objectivePowerDissipation/objectivePowerDissipation.C
|
objectives/incompressible/objectivePowerDissipation/objectivePowerDissipation.C
|
||||||
objectives/incompressible/objectivePartialVolume/objectivePartialVolume.C
|
|
||||||
objectives/incompressible/objectiveNutSqr/objectiveNutSqr.C
|
objectives/incompressible/objectiveNutSqr/objectiveNutSqr.C
|
||||||
objectives/incompressible/objectiveFlowRate/objectiveFlowRate.C
|
objectives/incompressible/objectiveFlowRate/objectiveFlowRate.C
|
||||||
objectives/incompressible/objectiveFlowRatePartition/objectiveFlowRatePartition.C
|
objectives/incompressible/objectiveFlowRatePartition/objectiveFlowRatePartition.C
|
||||||
objectives/incompressible/objectiveUniformityPatch/objectiveUniformityPatch.C
|
objectives/incompressible/objectiveUniformityPatch/objectiveUniformityPatch.C
|
||||||
objectives/incompressible/objectiveUniformityCellZone/objectiveUniformityCellZone.C
|
objectives/incompressible/objectiveUniformityCellZone/objectiveUniformityCellZone.C
|
||||||
|
objectives/geometric/objectiveGeometric/objectiveGeometric.C
|
||||||
|
objectives/geometric/objectivePartialVolume/objectivePartialVolume.C
|
||||||
|
|
||||||
/* OBJECTIVE MANAGER*/
|
/* OBJECTIVE MANAGER*/
|
||||||
objectiveManager/objectiveManager/objectiveManager.C
|
objectiveManager/objectiveManager.C
|
||||||
objectiveManager/objectiveManagerIncompressible/objectiveManagerIncompressible.C
|
|
||||||
|
|
||||||
/* BOUNDARY ADJOINT CONTRIBUTIONS */
|
/* BOUNDARY ADJOINT CONTRIBUTIONS */
|
||||||
boundaryAdjointContributions/boundaryAdjointContribution/boundaryAdjointContribution.C
|
boundaryAdjointContributions/boundaryAdjointContribution/boundaryAdjointContribution.C
|
||||||
@ -120,6 +121,7 @@ parameterization/Bezier/Bezier.C
|
|||||||
dynamicMesh/motionSolver/volumetricBSplinesMotionSolver/volumetricBSplinesMotionSolver.C
|
dynamicMesh/motionSolver/volumetricBSplinesMotionSolver/volumetricBSplinesMotionSolver.C
|
||||||
dynamicMesh/motionSolver/elasticityMotionSolver/elasticityMotionSolver.C
|
dynamicMesh/motionSolver/elasticityMotionSolver/elasticityMotionSolver.C
|
||||||
dynamicMesh/motionSolver/laplacianMotionSolver/laplacianMotionSolver.C
|
dynamicMesh/motionSolver/laplacianMotionSolver/laplacianMotionSolver.C
|
||||||
|
dynamicMesh/motionSolver/pLaplacianMotionSolver/pLaplacianMotionSolver.C
|
||||||
|
|
||||||
/* DISPLACEMENT METHOD */
|
/* DISPLACEMENT METHOD */
|
||||||
displacementMethod/displacementMethod/displacementMethod.C
|
displacementMethod/displacementMethod/displacementMethod.C
|
||||||
@ -128,28 +130,24 @@ displacementMethod/displacementMethoddisplacementLaplacian/displacementMethoddis
|
|||||||
displacementMethod/displacementMethodvelocityLaplacian/displacementMethodvelocityLaplacian.C
|
displacementMethod/displacementMethodvelocityLaplacian/displacementMethodvelocityLaplacian.C
|
||||||
displacementMethod/displacementMethodelasticityMotionSolver/displacementMethodelasticityMotionSolver.C
|
displacementMethod/displacementMethodelasticityMotionSolver/displacementMethodelasticityMotionSolver.C
|
||||||
displacementMethod/displacementMethodlaplacianMotionSolver/displacementMethodlaplacianMotionSolver.C
|
displacementMethod/displacementMethodlaplacianMotionSolver/displacementMethodlaplacianMotionSolver.C
|
||||||
|
displacementMethod/displacementMethodpLaplacianMotionSolver/displacementMethodpLaplacianMotionSolver.C
|
||||||
|
|
||||||
/* INTERPOLATION SCHEMES */
|
/* INTERPOLATION SCHEMES */
|
||||||
interpolation/pointVolInterpolation/pointVolInterpolation.C
|
interpolation/pointVolInterpolation/pointVolInterpolation.C
|
||||||
|
interpolation/volPointInterpolation/volPointInterpolationAdjoint.C
|
||||||
|
|
||||||
/* ADJOINT SENSITIVITY */
|
/* ADJOINT SENSITIVITY */
|
||||||
optimisation/adjointSensitivity/sensitivity/sensitivity.C
|
optimisation/adjointSensitivity/sensitivity/sensitivity.C
|
||||||
optimisation/adjointSensitivity/shapeSensitivitiesBase/shapeSensitivitiesBase.C
|
optimisation/adjointSensitivity/adjointSensitivity/adjointSensitivity/adjointSensitivity.C
|
||||||
incoSens=optimisation/adjointSensitivity/incompressible
|
optimisation/adjointSensitivity/adjointSensitivity/adjointEikonalSolver/adjointEikonalSolver.C
|
||||||
$(incoSens)/adjointSensitivity/adjointSensitivityIncompressible.C
|
optimisation/adjointSensitivity/adjointSensitivity/shape/adjointMeshMovementSolver/adjointMeshMovementSolver.C
|
||||||
$(incoSens)/shapeSensitivities/shapeSensitivitiesIncompressible.C
|
optimisation/adjointSensitivity/adjointSensitivity/shape/shapeSensitivityBase/ShapeSensitivitiesBase.C
|
||||||
$(incoSens)/adjointEikonalSolver/adjointEikonalSolverIncompressible.C
|
optimisation/adjointSensitivity/adjointSensitivity/shape/FI/sensitivityShapeFI.C
|
||||||
$(incoSens)/adjointMeshMovementSolver/adjointMeshMovementSolverIncompressible.C
|
optimisation/adjointSensitivity/adjointSensitivity/shape/ESI/sensitivityShapeESI.C
|
||||||
$(incoSens)/sensitivitySurface/sensitivitySurfaceIncompressible.C
|
optimisation/adjointSensitivity/adjointSensitivity/shape/surfacePoints/sensitivitySurfacePoints.C
|
||||||
$(incoSens)/sensitivitySurfacePoints/sensitivitySurfacePointsIncompressible.C
|
optimisation/adjointSensitivity/adjointSensitivity/shape/surface/sensitivitySurface.C
|
||||||
$(incoSens)/sensitivityMultiple/sensitivityMultipleIncompressible.C
|
optimisation/adjointSensitivity/adjointSensitivity/topO/sensitivityTopO.C
|
||||||
$(incoSens)/SIBase/SIBaseIncompressible.C
|
optimisation/adjointSensitivity/adjointSensitivity/multiple/sensitivityMultiple.C
|
||||||
$(incoSens)/FIBase/FIBaseIncompressible.C
|
|
||||||
$(incoSens)/sensitivityVolBSplines/sensitivityVolBSplinesIncompressible.C
|
|
||||||
$(incoSens)/sensitivityVolBSplinesFI/sensitivityVolBSplinesFIIncompressible.C
|
|
||||||
$(incoSens)/sensitivityBezier/sensitivityBezierIncompressible.C
|
|
||||||
$(incoSens)/sensitivityBezierFI/sensitivityBezierFIIncompressible.C
|
|
||||||
|
|
||||||
/* LINE SEARCH */
|
/* LINE SEARCH */
|
||||||
optimisation/lineSearch/lineSearch/lineSearch.C
|
optimisation/lineSearch/lineSearch/lineSearch.C
|
||||||
@ -159,32 +157,32 @@ optimisation/lineSearch/stepUpdate/bisection/bisection.C
|
|||||||
optimisation/lineSearch/stepUpdate/quadratic/quadratic.C
|
optimisation/lineSearch/stepUpdate/quadratic/quadratic.C
|
||||||
|
|
||||||
/* UPDATE METHOD */
|
/* UPDATE METHOD */
|
||||||
updateMethod=optimisation/updateMethod/
|
updateMethod=optimisation/updateMethod
|
||||||
$(updateMethod)/updateMethod/updateMethod.C
|
$(updateMethod)/updateMethod/updateMethod.C
|
||||||
$(updateMethod)/constrainedOptimisationMethod/constrainedOptimisationMethod.C
|
$(updateMethod)/constrainedOptimisationMethod/constrainedOptimisationMethod.C
|
||||||
$(updateMethod)/steepestDescent/steepestDescent.C
|
$(updateMethod)/steepestDescent/steepestDescent.C
|
||||||
|
$(updateMethod)/quasiNewton/quasiNewton.C
|
||||||
$(updateMethod)/BFGS/BFGS.C
|
$(updateMethod)/BFGS/BFGS.C
|
||||||
$(updateMethod)/DBFGS/DBFGS.C
|
$(updateMethod)/DBFGS/DBFGS.C
|
||||||
$(updateMethod)/LBFGS/LBFGS.C
|
$(updateMethod)/LBFGS/LBFGS.C
|
||||||
$(updateMethod)/SR1/SR1.C
|
$(updateMethod)/SR1/SR1.C
|
||||||
$(updateMethod)/conjugateGradient/conjugateGradient.C
|
$(updateMethod)/conjugateGradient/conjugateGradient.C
|
||||||
$(updateMethod)/constraintProjection/constraintProjection.C
|
$(updateMethod)/constraintProjection/constraintProjection.C
|
||||||
|
$(updateMethod)/SQPBase/SQPBase.C
|
||||||
$(updateMethod)/SQP/SQP.C
|
$(updateMethod)/SQP/SQP.C
|
||||||
|
$(updateMethod)/ISQP/ISQP.C
|
||||||
|
|
||||||
/* OPT MESH MOVEMENT */
|
/* DESIGN VARIABLES */
|
||||||
optMeshMovement=optimisation/optMeshMovement
|
optimisation/designVariables/designVariables/designVariables.C
|
||||||
$(optMeshMovement)/optMeshMovement/optMeshMovement.C
|
shapeVars=optimisation/designVariables/shape
|
||||||
$(optMeshMovement)/optMeshMovementVolumetricBSplines/optMeshMovementVolumetricBSplines.C
|
$(shapeVars)/shapeDesignVariables/shapeDesignVariables.C
|
||||||
$(optMeshMovement)/optMeshMovementVolumetricBSplinesExternalMotionSolver/optMeshMovementVolumetricBSplinesExternalMotionSolver.C
|
$(shapeVars)/volumetricBSplines/morphingBoxConstraints/morphingBoxConstaint/morphingBoxConstraint.C
|
||||||
$(optMeshMovement)/optMeshMovementBezier/optMeshMovementBezier.C
|
$(shapeVars)/volumetricBSplines/morphingBoxConstraints/none/noConstraint.C
|
||||||
$(optMeshMovement)/optMeshMovementNULL/optMeshMovementNULL.C
|
$(shapeVars)/volumetricBSplines/volumetricBSplinesDesignVariables.C
|
||||||
|
$(shapeVars)/Bezier/BezierDesignVariables.C
|
||||||
/* OPTIMIZATION TYPE */
|
|
||||||
incoOptType=optimisation/optimisationType/incompressible
|
|
||||||
$(incoOptType)/optimisationType/optimisationTypeIncompressible.C
|
|
||||||
$(incoOptType)/shapeOptimisation/shapeOptimisationIncompressible.C
|
|
||||||
|
|
||||||
/* OPTIMIZATION MANAGER */
|
/* OPTIMIZATION MANAGER */
|
||||||
|
optimisation/optimisationManager/optimisationManager/designVariablesUpdate/designVariablesUpdate.C
|
||||||
optimisation/optimisationManager/optimisationManager/optimisationManager.C
|
optimisation/optimisationManager/optimisationManager/optimisationManager.C
|
||||||
optimisation/optimisationManager/singleRun/singleRun.C
|
optimisation/optimisationManager/singleRun/singleRun.C
|
||||||
optimisation/optimisationManager/steadyOptimisation/steadyOptimisation.C
|
optimisation/optimisationManager/steadyOptimisation/steadyOptimisation.C
|
||||||
|
|||||||
@ -9,8 +9,10 @@ EXE_INC = \
|
|||||||
-I$(LIB_SRC)/TurbulenceModels/turbulenceModels/lnInclude \
|
-I$(LIB_SRC)/TurbulenceModels/turbulenceModels/lnInclude \
|
||||||
-I$(LIB_SRC)/transportModels \
|
-I$(LIB_SRC)/transportModels \
|
||||||
-I$(LIB_SRC)/transportModels/incompressible/singlePhaseTransportModel \
|
-I$(LIB_SRC)/transportModels/incompressible/singlePhaseTransportModel \
|
||||||
|
-I$(LIB_SRC)/transportModels/geometricVoF/lnInclude \
|
||||||
-I$(LIB_SRC)/fvMotionSolver/lnInclude \
|
-I$(LIB_SRC)/fvMotionSolver/lnInclude \
|
||||||
-I$(LIB_SRC)/dynamicMesh/lnInclude \
|
-I$(LIB_SRC)/dynamicMesh/lnInclude \
|
||||||
|
-I$(LIB_SRC)/fileFormats/lnInclude \
|
||||||
-I$(LIB_SRC)/fvOptions/lnInclude
|
-I$(LIB_SRC)/fvOptions/lnInclude
|
||||||
|
|
||||||
LIB_LIBS = \
|
LIB_LIBS = \
|
||||||
@ -24,4 +26,5 @@ LIB_LIBS = \
|
|||||||
-lincompressibleTransportModels \
|
-lincompressibleTransportModels \
|
||||||
-lfvMotionSolvers \
|
-lfvMotionSolvers \
|
||||||
-ldynamicMesh \
|
-ldynamicMesh \
|
||||||
|
-lgeometricVoF \
|
||||||
-lfvOptions
|
-lfvOptions
|
||||||
|
|||||||
@ -314,12 +314,7 @@ tmp
|
|||||||
>
|
>
|
||||||
adjointBoundaryCondition<Type>::dxdbMult() const
|
adjointBoundaryCondition<Type>::dxdbMult() const
|
||||||
{
|
{
|
||||||
return
|
return nullptr;
|
||||||
tmp<Field<typename Foam::outerProduct<Foam::vector, Type>::type>>::New
|
|
||||||
(
|
|
||||||
patch_.size(),
|
|
||||||
Zero
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2021 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2021 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019-2020 OpenCFD Ltd.
|
Copyright (C) 2019-2020 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -114,9 +114,10 @@ void Foam::adjointWallVelocityFvPatchVectorField::manipulateMatrix
|
|||||||
typedef Foam::nutUSpaldingWallFunctionFvPatchScalarField
|
typedef Foam::nutUSpaldingWallFunctionFvPatchScalarField
|
||||||
SAwallFunctionPatchField;
|
SAwallFunctionPatchField;
|
||||||
|
|
||||||
|
tmp<fvPatchScalarField> nutPatch(boundaryContrPtr_->turbulentDiffusivity());
|
||||||
if
|
if
|
||||||
(
|
(
|
||||||
isA<SAwallFunctionPatchField>(boundaryContrPtr_->turbulentDiffusivity())
|
isA<SAwallFunctionPatchField>(nutPatch())
|
||||||
&& patch().size() != 0
|
&& patch().size() != 0
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@ -199,8 +200,8 @@ void Foam::adjointWallVelocityFvPatchVectorField::updateCoeffs()
|
|||||||
typedef Foam::nutUSpaldingWallFunctionFvPatchScalarField
|
typedef Foam::nutUSpaldingWallFunctionFvPatchScalarField
|
||||||
SAwallFunctionPatchField;
|
SAwallFunctionPatchField;
|
||||||
|
|
||||||
const fvPatchScalarField& nutb = boundaryContrPtr_->turbulentDiffusivity();
|
tmp<fvPatchScalarField> nutb(boundaryContrPtr_->turbulentDiffusivity());
|
||||||
if (isA<SAwallFunctionPatchField>(nutb))
|
if (isA<SAwallFunctionPatchField>(nutb()))
|
||||||
{
|
{
|
||||||
Uap_t1 = (Uac & tf1)*tf1;
|
Uap_t1 = (Uac & tf1)*tf1;
|
||||||
// leaving out second term for now
|
// leaving out second term for now
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2019 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019-2021 OpenCFD Ltd.
|
Copyright (C) 2019-2021 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -28,6 +28,7 @@ License
|
|||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "boundaryAdjointContribution.H"
|
#include "boundaryAdjointContribution.H"
|
||||||
|
#include "fvPatchFieldsFwd.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -139,6 +140,13 @@ tmp<scalarField> boundaryAdjointContribution::TMVariable2()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
tmp<fvPatchScalarField>
|
||||||
|
boundaryAdjointContribution::turbulentDiffusivity() const
|
||||||
|
{
|
||||||
|
NotImplemented;
|
||||||
|
return tmp<fvPatchScalarField>(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
} // End namespace Foam
|
} // End namespace Foam
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2019 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
Copyright (C) 2019 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -79,6 +79,18 @@ protected:
|
|||||||
const fvPatch& patch_;
|
const fvPatch& patch_;
|
||||||
|
|
||||||
|
|
||||||
|
// Protected Member Functions
|
||||||
|
|
||||||
|
template<class returnType, class sourceType, class castType>
|
||||||
|
tmp<Field<returnType>> sumContributions
|
||||||
|
(
|
||||||
|
PtrList<sourceType>& sourceList,
|
||||||
|
const fvPatchField<returnType>&(castType::*boundaryFunction)
|
||||||
|
(const label),
|
||||||
|
bool (castType::*hasFunction)() const
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//- Runtime type information
|
//- Runtime type information
|
||||||
@ -156,7 +168,7 @@ public:
|
|||||||
virtual const fvPatchVectorField& Ub() const = 0;
|
virtual const fvPatchVectorField& Ub() const = 0;
|
||||||
virtual const fvPatchScalarField& pb() const = 0;
|
virtual const fvPatchScalarField& pb() const = 0;
|
||||||
virtual const fvsPatchScalarField& phib() const = 0;
|
virtual const fvsPatchScalarField& phib() const = 0;
|
||||||
virtual const fvPatchScalarField& turbulentDiffusivity() const = 0;
|
virtual tmp<fvPatchScalarField> turbulentDiffusivity() const;
|
||||||
virtual const fvPatchVectorField& Uab() const = 0;
|
virtual const fvPatchVectorField& Uab() const = 0;
|
||||||
virtual const fvPatchScalarField& pab() const = 0;
|
virtual const fvPatchScalarField& pab() const = 0;
|
||||||
virtual const fvsPatchScalarField& phiab() const = 0;
|
virtual const fvsPatchScalarField& phiab() const = 0;
|
||||||
@ -173,6 +185,12 @@ public:
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#ifdef NoRepository
|
||||||
|
#include "boundaryAdjointContributionTemplates.C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2019 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
Copyright (C) 2019 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -31,10 +31,11 @@ License
|
|||||||
|
|
||||||
template<class returnType, class sourceType, class castType>
|
template<class returnType, class sourceType, class castType>
|
||||||
Foam::tmp<Foam::Field<returnType>>
|
Foam::tmp<Foam::Field<returnType>>
|
||||||
Foam::boundaryAdjointContributionIncompressible::sumContributions
|
Foam::boundaryAdjointContribution::sumContributions
|
||||||
(
|
(
|
||||||
PtrList<sourceType>& sourceList,
|
PtrList<sourceType>& sourceList,
|
||||||
const fvPatchField<returnType>&(castType::*boundaryFunction)(const label)
|
const fvPatchField<returnType>& (castType::*boundaryFunction)(const label),
|
||||||
|
bool (castType::*hasFunction)() const
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Objective function contribution
|
// Objective function contribution
|
||||||
@ -45,9 +46,12 @@ Foam::boundaryAdjointContributionIncompressible::sumContributions
|
|||||||
for (sourceType& funcI : sourceList)
|
for (sourceType& funcI : sourceList)
|
||||||
{
|
{
|
||||||
castType& cfuncI = refCast<castType>(funcI);
|
castType& cfuncI = refCast<castType>(funcI);
|
||||||
const fvPatchField<returnType>& dJdvar =
|
if ((cfuncI.*hasFunction)())
|
||||||
(cfuncI.*boundaryFunction)(patch_.index());
|
{
|
||||||
dJtotdvar += cfuncI.weight()*dJdvar;
|
const fvPatchField<returnType>& dJdvar =
|
||||||
|
(cfuncI.*boundaryFunction)(patch_.index());
|
||||||
|
dJtotdvar += cfuncI.weight()*dJdvar;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return tdJtotdvar;
|
return tdJtotdvar;
|
||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2021 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2021 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
Copyright (C) 2019 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -93,7 +93,8 @@ tmp<vectorField> boundaryAdjointContributionIncompressible::velocitySource()
|
|||||||
sumContributions
|
sumContributions
|
||||||
(
|
(
|
||||||
objectiveManager_.getObjectiveFunctions(),
|
objectiveManager_.getObjectiveFunctions(),
|
||||||
&objectiveIncompressible::boundarydJdv
|
&objectiveIncompressible::boundarydJdv,
|
||||||
|
&objectiveIncompressible::hasBoundarydJdv
|
||||||
);
|
);
|
||||||
vectorField& source = tsource.ref();
|
vectorField& source = tsource.ref();
|
||||||
|
|
||||||
@ -113,7 +114,8 @@ tmp<scalarField> boundaryAdjointContributionIncompressible::pressureSource()
|
|||||||
sumContributions
|
sumContributions
|
||||||
(
|
(
|
||||||
objectiveManager_.getObjectiveFunctions(),
|
objectiveManager_.getObjectiveFunctions(),
|
||||||
&objectiveIncompressible::boundarydJdvn
|
&objectiveIncompressible::boundarydJdvn,
|
||||||
|
&objectiveIncompressible::hasBoundarydJdvn
|
||||||
);
|
);
|
||||||
|
|
||||||
scalarField& source = tsource.ref();
|
scalarField& source = tsource.ref();
|
||||||
@ -138,7 +140,8 @@ boundaryAdjointContributionIncompressible::tangentVelocitySource()
|
|||||||
sumContributions
|
sumContributions
|
||||||
(
|
(
|
||||||
objectiveManager_.getObjectiveFunctions(),
|
objectiveManager_.getObjectiveFunctions(),
|
||||||
&objectiveIncompressible::boundarydJdvt
|
&objectiveIncompressible::boundarydJdvt,
|
||||||
|
&objectiveIncompressible::hasBoundarydJdvt
|
||||||
);
|
);
|
||||||
|
|
||||||
vectorField& source = tsource.ref();
|
vectorField& source = tsource.ref();
|
||||||
@ -165,7 +168,8 @@ boundaryAdjointContributionIncompressible::normalVelocitySource()
|
|||||||
sumContributions
|
sumContributions
|
||||||
(
|
(
|
||||||
objectiveManager_.getObjectiveFunctions(),
|
objectiveManager_.getObjectiveFunctions(),
|
||||||
&objectiveIncompressible::boundarydJdp
|
&objectiveIncompressible::boundarydJdp,
|
||||||
|
&objectiveIncompressible::hasBoundarydJdp
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -177,7 +181,8 @@ tmp<scalarField> boundaryAdjointContributionIncompressible::energySource()
|
|||||||
sumContributions
|
sumContributions
|
||||||
(
|
(
|
||||||
objectiveManager_.getObjectiveFunctions(),
|
objectiveManager_.getObjectiveFunctions(),
|
||||||
&objectiveIncompressible::boundarydJdT
|
&objectiveIncompressible::boundarydJdT,
|
||||||
|
&objectiveIncompressible::hasBoundarydJdT
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -190,7 +195,8 @@ boundaryAdjointContributionIncompressible::adjointTMVariable1Source()
|
|||||||
sumContributions
|
sumContributions
|
||||||
(
|
(
|
||||||
objectiveManager_.getObjectiveFunctions(),
|
objectiveManager_.getObjectiveFunctions(),
|
||||||
&objectiveIncompressible::boundarydJdTMvar1
|
&objectiveIncompressible::boundarydJdTMvar1,
|
||||||
|
&objectiveIncompressible::hasBoundarydJdTMVar1
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -203,7 +209,8 @@ boundaryAdjointContributionIncompressible::adjointTMVariable2Source()
|
|||||||
sumContributions
|
sumContributions
|
||||||
(
|
(
|
||||||
objectiveManager_.getObjectiveFunctions(),
|
objectiveManager_.getObjectiveFunctions(),
|
||||||
&objectiveIncompressible::boundarydJdTMvar2
|
&objectiveIncompressible::boundarydJdTMvar2,
|
||||||
|
&objectiveIncompressible::hasBoundarydJdTMVar2
|
||||||
);
|
);
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -216,7 +223,8 @@ boundaryAdjointContributionIncompressible::dJdnut()
|
|||||||
sumContributions
|
sumContributions
|
||||||
(
|
(
|
||||||
objectiveManager_.getObjectiveFunctions(),
|
objectiveManager_.getObjectiveFunctions(),
|
||||||
&objectiveIncompressible::boundarydJdnut
|
&objectiveIncompressible::boundarydJdnut,
|
||||||
|
&objectiveIncompressible::hasBoundarydJdnut
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -228,7 +236,8 @@ boundaryAdjointContributionIncompressible::dJdGradU()
|
|||||||
sumContributions
|
sumContributions
|
||||||
(
|
(
|
||||||
objectiveManager_.getObjectiveFunctions(),
|
objectiveManager_.getObjectiveFunctions(),
|
||||||
&objectiveIncompressible::boundarydJdGradU
|
&objectiveIncompressible::boundarydJdGradU,
|
||||||
|
&objectiveIncompressible::hasBoundarydJdGradU
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,14 +340,10 @@ boundaryAdjointContributionIncompressible::phib() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const fvPatchScalarField&
|
tmp<fvPatchScalarField>
|
||||||
boundaryAdjointContributionIncompressible::turbulentDiffusivity() const
|
boundaryAdjointContributionIncompressible::turbulentDiffusivity() const
|
||||||
{
|
{
|
||||||
return
|
return primalVars_.RASModelVariables()().nutPatchField(patch_.index());
|
||||||
primalVars_.RASModelVariables()().nutRef().boundaryField()
|
|
||||||
[
|
|
||||||
patch_.index()
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2019 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
Copyright (C) 2019 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -96,17 +96,6 @@ protected:
|
|||||||
const incompressibleAdjointSolver& adjointSolver_;
|
const incompressibleAdjointSolver& adjointSolver_;
|
||||||
|
|
||||||
|
|
||||||
// Protected Member Functions
|
|
||||||
|
|
||||||
template<class returnType, class sourceType, class castType>
|
|
||||||
tmp<Field<returnType>> sumContributions
|
|
||||||
(
|
|
||||||
PtrList<sourceType>& sourceList,
|
|
||||||
const fvPatchField<returnType>&(castType::*boundaryFunction)
|
|
||||||
(const label)
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//- Runtime type information
|
//- Runtime type information
|
||||||
@ -155,7 +144,7 @@ public:
|
|||||||
const fvPatchVectorField& Ub() const;
|
const fvPatchVectorField& Ub() const;
|
||||||
const fvPatchScalarField& pb() const;
|
const fvPatchScalarField& pb() const;
|
||||||
const fvsPatchScalarField& phib() const;
|
const fvsPatchScalarField& phib() const;
|
||||||
const fvPatchScalarField& turbulentDiffusivity() const;
|
tmp<fvPatchScalarField> turbulentDiffusivity() const;
|
||||||
const fvPatchVectorField& Uab() const;
|
const fvPatchVectorField& Uab() const;
|
||||||
const fvPatchScalarField& pab() const;
|
const fvPatchScalarField& pab() const;
|
||||||
const fvsPatchScalarField& phiab() const;
|
const fvsPatchScalarField& phiab() const;
|
||||||
@ -175,12 +164,6 @@ public:
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
#ifdef NoRepository
|
|
||||||
# include "boundaryAdjointContributionIncompressibleTemplates.C"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
|
|||||||
@ -97,6 +97,12 @@ Foam::autoPtr<Foam::displacementMethod> Foam::displacementMethod::New
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
bool Foam::displacementMethod::preferPointField() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::displacementMethod::boundControlField(vectorField& controlField)
|
void Foam::displacementMethod::boundControlField(vectorField& controlField)
|
||||||
{
|
{
|
||||||
// Does nothing in base
|
// Does nothing in base
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2019 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
Copyright (C) 2019 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -66,12 +66,15 @@ protected:
|
|||||||
fvMesh& mesh_;
|
fvMesh& mesh_;
|
||||||
|
|
||||||
//- IDs of the patches to be moved
|
//- IDs of the patches to be moved
|
||||||
const labelList& patchIDs_;
|
labelList patchIDs_;
|
||||||
|
|
||||||
autoPtr<motionSolver> motionPtr_;
|
autoPtr<motionSolver> motionPtr_;
|
||||||
|
|
||||||
scalar maxDisplacement_;
|
scalar maxDisplacement_;
|
||||||
|
|
||||||
|
//- Whether the motion solver prefers a point of a vol field as input
|
||||||
|
bool preferPointField_;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -130,33 +133,42 @@ public:
|
|||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
//- Set motion filed related to model based on given motion
|
//- Whether the motion solver prefers a point of a vol field as input
|
||||||
virtual void setMotionField(const pointVectorField& pointMovement) = 0;
|
virtual bool preferPointField() const;
|
||||||
|
|
||||||
//- Set motion filed related to model based on given motion
|
//- Set motion filed related to model based on given motion
|
||||||
virtual void setMotionField(const volVectorField& cellMovement) = 0;
|
virtual void setMotionField(const pointVectorField& pointMovement) = 0;
|
||||||
|
|
||||||
//- Set control field as a vectorField. For methods working with
|
//- Set motion filed related to model based on given motion
|
||||||
//- parameters (RBF etc)
|
virtual void setMotionField(const volVectorField& cellMovement) = 0;
|
||||||
virtual void setControlField(const vectorField& controlField) = 0;
|
|
||||||
|
|
||||||
//- Set control field as a vectorField. For methods working with
|
//- Set control field as a vectorField. For methods working with
|
||||||
//- parameters (RBF etc)
|
//- parameters (RBF etc)
|
||||||
virtual void setControlField(const scalarField& controlField) = 0;
|
virtual void setControlField(const vectorField& controlField) = 0;
|
||||||
|
|
||||||
//- Bound control field in certain directions etc. For methods working
|
//- Set control field as a vectorField. For methods working with
|
||||||
//- with parameters (RBF etc)
|
//- parameters (RBF etc)
|
||||||
//- does nothing by default
|
virtual void setControlField(const scalarField& controlField) = 0;
|
||||||
virtual void boundControlField(vectorField& controlField);
|
|
||||||
|
|
||||||
//- Get access to motionSolver
|
//- Bound control field in certain directions etc. For methods working
|
||||||
autoPtr<motionSolver>& getMotionSolver();
|
//- with parameters (RBF etc)
|
||||||
|
//- does nothing by default
|
||||||
|
virtual void boundControlField(vectorField& controlField);
|
||||||
|
|
||||||
//- Get max displacement
|
//- Get access to motionSolver
|
||||||
scalar getMaxDisplacement() const;
|
autoPtr<motionSolver>& getMotionSolver();
|
||||||
|
|
||||||
//- Update mesh
|
//- Get max displacement
|
||||||
void update();
|
scalar getMaxDisplacement() const;
|
||||||
|
|
||||||
|
//- Set parametertised patch IDs
|
||||||
|
inline void setPatchIDs(const labelList& patchIDs)
|
||||||
|
{
|
||||||
|
patchIDs_ = patchIDs;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Update mesh
|
||||||
|
void update();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2019 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019-2020 OpenCFD Ltd.
|
Copyright (C) 2019-2020 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -98,6 +98,12 @@ displacementMethodelasticityMotionSolver
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
bool displacementMethodelasticityMotionSolver::preferPointField() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void displacementMethodelasticityMotionSolver::setMotionField
|
void displacementMethodelasticityMotionSolver::setMotionField
|
||||||
(
|
(
|
||||||
const pointVectorField& pointMovement
|
const pointVectorField& pointMovement
|
||||||
@ -105,17 +111,17 @@ void displacementMethodelasticityMotionSolver::setMotionField
|
|||||||
{
|
{
|
||||||
if (resetFields_)
|
if (resetFields_)
|
||||||
{
|
{
|
||||||
pointMotionU_.primitiveFieldRef() = vector::zero;
|
pointMotionU_.primitiveFieldRef() = Zero;
|
||||||
cellMotionU_.primitiveFieldRef() = vector::zero;
|
cellMotionU_.primitiveFieldRef() = Zero;
|
||||||
cellMotionU_.correctBoundaryConditions();
|
cellMotionU_.correctBoundaryConditions();
|
||||||
}
|
}
|
||||||
|
|
||||||
maxDisplacement_ = SMALL;
|
maxDisplacement_ = SMALL;
|
||||||
|
|
||||||
// Update the boundary conditions of the pointField in order to make
|
// Update the boundary conditions of the pointField in order to make sure
|
||||||
// sure that the boundary will move according to the initial BCs
|
// that the boundary will move according to the initial BCs without the
|
||||||
// without the interference of the volPointInterpolation in the elasticityMotionSolver
|
// interference of the volPointInterpolation in the elasticityMotionSolver
|
||||||
for (label patchI : patchIDs_)
|
for (const label patchI : patchIDs_)
|
||||||
{
|
{
|
||||||
// Set boundary field. Needed for the motionSolver class
|
// Set boundary field. Needed for the motionSolver class
|
||||||
pointMotionU_.boundaryFieldRef()[patchI] ==
|
pointMotionU_.boundaryFieldRef()[patchI] ==
|
||||||
@ -145,7 +151,8 @@ void displacementMethodelasticityMotionSolver::setMotionField
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the volField boundary conditions, used for the elasticity PDEs solution
|
// Update the volField boundary conditions,
|
||||||
|
// used for the elasticity PDEs solution
|
||||||
const pointField& points = mesh_.points();
|
const pointField& points = mesh_.points();
|
||||||
for (label patchI : patchIDs_)
|
for (label patchI : patchIDs_)
|
||||||
{
|
{
|
||||||
@ -164,15 +171,12 @@ void displacementMethodelasticityMotionSolver::setMotionField
|
|||||||
const volVectorField& cellMovement
|
const volVectorField& cellMovement
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
auto cellMotionUbf = cellMotionU_.boundaryFieldRef();
|
auto& cellMotionUbf = cellMotionU_.boundaryFieldRef();
|
||||||
|
|
||||||
// Set boundary mesh movement and calculate
|
// Set boundary mesh movement and calculate
|
||||||
// max current boundary displacement
|
// max current boundary displacement
|
||||||
forAll(patchIDs_, pI)
|
for (const label patchI : patchIDs_)
|
||||||
{
|
{
|
||||||
label patchI = patchIDs_[pI];
|
|
||||||
|
|
||||||
// Set boundary field. Needed for the motionSolver class
|
|
||||||
cellMotionUbf[patchI] == cellMovement.boundaryField()[patchI];
|
cellMotionUbf[patchI] == cellMovement.boundaryField()[patchI];
|
||||||
|
|
||||||
// Find max value
|
// Find max value
|
||||||
@ -180,10 +184,7 @@ void displacementMethodelasticityMotionSolver::setMotionField
|
|||||||
max
|
max
|
||||||
(
|
(
|
||||||
maxDisplacement_,
|
maxDisplacement_,
|
||||||
gMax
|
gMax(mag(cellMotionUbf[patchI]))
|
||||||
(
|
|
||||||
mag(cellMotionUbf[patchI])
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2019 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
Copyright (C) 2019 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -105,6 +105,9 @@ public:
|
|||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
|
//- Whether the motion solver prefers a point of a vol field as input
|
||||||
|
virtual bool preferPointField() const;
|
||||||
|
|
||||||
//- Set motion filed related to model based on given motion
|
//- Set motion filed related to model based on given motion
|
||||||
void setMotionField(const pointVectorField& pointMovement);
|
void setMotionField(const pointVectorField& pointMovement);
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2019 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019-2020 OpenCFD Ltd.
|
Copyright (C) 2019-2020 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -57,24 +57,6 @@ displacementMethodlaplacianMotionSolver::displacementMethodlaplacianMotionSolver
|
|||||||
displacementMethod(mesh, patchIDs),
|
displacementMethod(mesh, patchIDs),
|
||||||
pointMotionU_(refCast<laplacianMotionSolver>(motionPtr_()).pointMotionU()),
|
pointMotionU_(refCast<laplacianMotionSolver>(motionPtr_()).pointMotionU()),
|
||||||
cellMotionU_(refCast<laplacianMotionSolver>(motionPtr_()).cellMotionU()),
|
cellMotionU_(refCast<laplacianMotionSolver>(motionPtr_()).cellMotionU()),
|
||||||
/*
|
|
||||||
// getting a reference from the database is dangerous since multiple
|
|
||||||
// fields with the same name might be registered
|
|
||||||
pointMotionU_
|
|
||||||
(
|
|
||||||
const_cast<pointVectorField&>
|
|
||||||
(
|
|
||||||
mesh_.lookupObject<pointVectorField>("pointMotionU")
|
|
||||||
)
|
|
||||||
),
|
|
||||||
cellMotionU_
|
|
||||||
(
|
|
||||||
const_cast<volVectorField&>
|
|
||||||
(
|
|
||||||
mesh_.lookupObject<volVectorField>("cellMotionU")
|
|
||||||
)
|
|
||||||
),
|
|
||||||
*/
|
|
||||||
resetFields_
|
resetFields_
|
||||||
(
|
(
|
||||||
IOdictionary::readContents
|
IOdictionary::readContents
|
||||||
@ -97,6 +79,12 @@ displacementMethodlaplacianMotionSolver::displacementMethodlaplacianMotionSolver
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
bool displacementMethodlaplacianMotionSolver::preferPointField() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void displacementMethodlaplacianMotionSolver::setMotionField
|
void displacementMethodlaplacianMotionSolver::setMotionField
|
||||||
(
|
(
|
||||||
const pointVectorField& pointMovement
|
const pointVectorField& pointMovement
|
||||||
@ -104,14 +92,16 @@ void displacementMethodlaplacianMotionSolver::setMotionField
|
|||||||
{
|
{
|
||||||
if (resetFields_)
|
if (resetFields_)
|
||||||
{
|
{
|
||||||
pointMotionU_.primitiveFieldRef() = vector::zero;
|
pointMotionU_.primitiveFieldRef() = Zero;
|
||||||
cellMotionU_.primitiveFieldRef() = vector::zero;
|
cellMotionU_.primitiveFieldRef() = Zero;
|
||||||
cellMotionU_.correctBoundaryConditions();
|
cellMotionU_.correctBoundaryConditions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
maxDisplacement_ = SMALL;
|
||||||
|
|
||||||
// Set boundary mesh movement and calculate
|
// Set boundary mesh movement and calculate
|
||||||
// max current boundary displacement
|
// max current boundary displacement
|
||||||
for (label patchI : patchIDs_)
|
for (const label patchI : patchIDs_)
|
||||||
{
|
{
|
||||||
// Set boundary field. Needed for the motionSolver class
|
// Set boundary field. Needed for the motionSolver class
|
||||||
pointMotionU_.boundaryFieldRef()[patchI] ==
|
pointMotionU_.boundaryFieldRef()[patchI] ==
|
||||||
@ -140,6 +130,8 @@ void displacementMethodlaplacianMotionSolver::setMotionField
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
// Transfer movement to cellMotionU
|
||||||
|
refCast<laplacianMotionSolver>(motionPtr_()).setBoundaryConditions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -148,28 +140,28 @@ void displacementMethodlaplacianMotionSolver::setMotionField
|
|||||||
const volVectorField& cellMovement
|
const volVectorField& cellMovement
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
NotImplemented;
|
if (resetFields_)
|
||||||
/*
|
{
|
||||||
|
pointMotionU_.primitiveFieldRef() = Zero;
|
||||||
|
cellMotionU_.primitiveFieldRef() = Zero;
|
||||||
|
cellMotionU_.correctBoundaryConditions();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& cellMotionUbf = cellMotionU_.boundaryFieldRef();
|
||||||
// Set boundary mesh movement and calculate max current boundary
|
// Set boundary mesh movement and calculate max current boundary
|
||||||
// displacement
|
// displacement
|
||||||
forAll(patchIDs_, pI)
|
for (const label patchI : patchIDs_)
|
||||||
{
|
{
|
||||||
label patchI = patchIDs_[pI];
|
cellMotionUbf[patchI] == cellMovement.boundaryField()[patchI];
|
||||||
cellMotionU_.boundaryField()[patchI] ==
|
|
||||||
cellMovement.boundaryField()[patchI];
|
|
||||||
|
|
||||||
// Find max value
|
// Find max value
|
||||||
maxDisplacement_ =
|
maxDisplacement_ =
|
||||||
max
|
max
|
||||||
(
|
(
|
||||||
maxDisplacement_,
|
maxDisplacement_,
|
||||||
gMax
|
gMax(mag(cellMotionUbf[patchI]))
|
||||||
(
|
|
||||||
mag(cellMovement.boundaryField()[patchI])
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2019 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
Copyright (C) 2019 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -102,6 +102,9 @@ public:
|
|||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
|
//- Whether the motion solver prefers a point of a vol field as input
|
||||||
|
virtual bool preferPointField() const;
|
||||||
|
|
||||||
//- Set motion filed related to model based on given motion
|
//- Set motion filed related to model based on given motion
|
||||||
void setMotionField(const pointVectorField& pointMovement);
|
void setMotionField(const pointVectorField& pointMovement);
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,191 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2021 PCOpt/NTUA
|
||||||
|
Copyright (C) 2021 FOSS GP
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "displacementMethodpLaplacianMotionSolver.H"
|
||||||
|
#include "pLaplacianMotionSolver.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
defineTypeNameAndDebug(displacementMethodpLaplacianMotionSolver, 1);
|
||||||
|
addToRunTimeSelectionTable
|
||||||
|
(
|
||||||
|
displacementMethod,
|
||||||
|
displacementMethodpLaplacianMotionSolver,
|
||||||
|
dictionary
|
||||||
|
);
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
displacementMethodpLaplacianMotionSolver::
|
||||||
|
displacementMethodpLaplacianMotionSolver
|
||||||
|
(
|
||||||
|
fvMesh& mesh,
|
||||||
|
const labelList& patchIDs
|
||||||
|
)
|
||||||
|
:
|
||||||
|
displacementMethod(mesh, patchIDs),
|
||||||
|
pointMotionU_(refCast<pLaplacianMotionSolver>(motionPtr_()).pointMotionU()),
|
||||||
|
cellMotionU_(refCast<pLaplacianMotionSolver>(motionPtr_()).cellMotionU()),
|
||||||
|
resetFields_
|
||||||
|
(
|
||||||
|
IOdictionary
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"dynamicMeshDict",
|
||||||
|
mesh.time().constant(),
|
||||||
|
mesh,
|
||||||
|
IOobject::MUST_READ_IF_MODIFIED,
|
||||||
|
IOobject::AUTO_WRITE,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
).subDict("pLaplacianMotionSolverCoeffs").getOrDefault<bool>
|
||||||
|
(
|
||||||
|
"resetFields",
|
||||||
|
true
|
||||||
|
)
|
||||||
|
)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
bool displacementMethodpLaplacianMotionSolver::preferPointField() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void displacementMethodpLaplacianMotionSolver::setMotionField
|
||||||
|
(
|
||||||
|
const pointVectorField& pointMovement
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (resetFields_)
|
||||||
|
{
|
||||||
|
pointMotionU_.primitiveFieldRef() = Zero;
|
||||||
|
cellMotionU_.primitiveFieldRef() = Zero;
|
||||||
|
cellMotionU_.correctBoundaryConditions();
|
||||||
|
}
|
||||||
|
|
||||||
|
maxDisplacement_ = SMALL;
|
||||||
|
|
||||||
|
// Set boundary mesh movement and calculate
|
||||||
|
// max current boundary displacement
|
||||||
|
for (label patchI : patchIDs_)
|
||||||
|
{
|
||||||
|
// Set boundary field. Needed for the motionSolver class
|
||||||
|
pointMotionU_.boundaryFieldRef()[patchI] ==
|
||||||
|
pointMovement.boundaryField()[patchI].patchInternalField()();
|
||||||
|
|
||||||
|
// Set boundary field values as seen from the internalField!
|
||||||
|
// Needed for determining the max displacement
|
||||||
|
pointMotionU_.boundaryFieldRef()[patchI].setInInternalField
|
||||||
|
(
|
||||||
|
pointMotionU_.primitiveFieldRef(),
|
||||||
|
pointMovement.boundaryField()[patchI].patchInternalField()()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Find max value
|
||||||
|
maxDisplacement_ =
|
||||||
|
max
|
||||||
|
(
|
||||||
|
maxDisplacement_,
|
||||||
|
gMax
|
||||||
|
(
|
||||||
|
mag
|
||||||
|
(
|
||||||
|
pointMotionU_.boundaryField()[patchI].
|
||||||
|
patchInternalField()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Transfer movement to cellMotionU
|
||||||
|
refCast<pLaplacianMotionSolver>(motionPtr_()).setBoundaryConditions();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void displacementMethodpLaplacianMotionSolver::setMotionField
|
||||||
|
(
|
||||||
|
const volVectorField& cellMovement
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (resetFields_)
|
||||||
|
{
|
||||||
|
pointMotionU_.primitiveFieldRef() = Zero;
|
||||||
|
cellMotionU_.primitiveFieldRef() = Zero;
|
||||||
|
cellMotionU_.correctBoundaryConditions();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& cellMotionUbf = cellMotionU_.boundaryFieldRef();
|
||||||
|
// Set boundary mesh movement and calculate max current boundary
|
||||||
|
// displacement
|
||||||
|
for (const label patchI : patchIDs_)
|
||||||
|
{
|
||||||
|
cellMotionUbf[patchI] == cellMovement.boundaryField()[patchI];
|
||||||
|
|
||||||
|
// Find max value
|
||||||
|
maxDisplacement_ =
|
||||||
|
max
|
||||||
|
(
|
||||||
|
maxDisplacement_,
|
||||||
|
gMax(mag(cellMotionUbf[patchI]))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void displacementMethodpLaplacianMotionSolver::setControlField
|
||||||
|
(
|
||||||
|
const vectorField& controlField
|
||||||
|
)
|
||||||
|
{
|
||||||
|
NotImplemented;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void displacementMethodpLaplacianMotionSolver::setControlField
|
||||||
|
(
|
||||||
|
const scalarField& controlField
|
||||||
|
)
|
||||||
|
{
|
||||||
|
NotImplemented;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -5,9 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
Copyright (C) 2021 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2019 FOSS GP
|
Copyright (C) 2021 FOSS GP
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -25,23 +24,22 @@ License
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
Class
|
Class
|
||||||
Foam::optMeshMovementVolumetricBSplines
|
Foam::displacementMethodpLaplacianMotionSolver
|
||||||
|
|
||||||
Description
|
Description
|
||||||
Converts NURBS volume control points update to actual mesh movement.
|
Wrapper class for the pLaplacian motion solver
|
||||||
Internal points are also moved based on the movement of the control points
|
|
||||||
|
|
||||||
SourceFiles
|
SourceFiles
|
||||||
optMeshMovementVolumetricBSplines.C
|
displacementMethodpLaplacianMotionSolver.C
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#ifndef optMeshMovementVolumetricBSplines_H
|
#ifndef displacementMethodpLaplacianMotionSolver_H
|
||||||
#define optMeshMovementVolumetricBSplines_H
|
#define displacementMethodpLaplacianMotionSolver_H
|
||||||
|
|
||||||
#include "optMeshMovement.H"
|
#include "displacementMethod.H"
|
||||||
#include "volBSplinesBase.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -49,27 +47,22 @@ namespace Foam
|
|||||||
{
|
{
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
Class optMeshMovementVolumetricBSplines Declaration
|
Class displacementMethodpLaplacianMotionSolver Declaration
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
class optMeshMovementVolumetricBSplines
|
class displacementMethodpLaplacianMotionSolver
|
||||||
:
|
:
|
||||||
public optMeshMovement
|
public displacementMethod
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Protected data
|
// Protected data
|
||||||
|
|
||||||
//- Reference to underlaying volumetric B-Splines morpher
|
pointVectorField& pointMotionU_;
|
||||||
volBSplinesBase& volBSplinesBase_;
|
|
||||||
|
|
||||||
//- Backup of initial control points. Useful for line-search
|
volVectorField& cellMotionU_;
|
||||||
List<vectorField> cpsInit_;
|
|
||||||
|
|
||||||
|
bool resetFields_;
|
||||||
// Protected Member Functions
|
|
||||||
|
|
||||||
vectorField controlPointMovement(const scalarField& correction);
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -77,53 +70,56 @@ private:
|
|||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
//- No copy construct
|
//- No copy construct
|
||||||
optMeshMovementVolumetricBSplines
|
displacementMethodpLaplacianMotionSolver
|
||||||
(
|
(
|
||||||
const optMeshMovementVolumetricBSplines&
|
const displacementMethodpLaplacianMotionSolver&
|
||||||
) = delete;
|
) = delete;
|
||||||
|
|
||||||
//- No copy assignment
|
//- No copy assignment
|
||||||
void operator=(const optMeshMovementVolumetricBSplines&) = delete;
|
void operator=
|
||||||
|
(
|
||||||
|
const displacementMethodpLaplacianMotionSolver&
|
||||||
|
) = delete;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//- Runtime type information
|
//- Runtime type information
|
||||||
TypeName("volumetricBSplines");
|
TypeName("pLaplacianMotionSolver");
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
//- Construct from components
|
//- Construct from components
|
||||||
optMeshMovementVolumetricBSplines
|
displacementMethodpLaplacianMotionSolver
|
||||||
(
|
(
|
||||||
fvMesh& mesh,
|
fvMesh& mesh,
|
||||||
const dictionary& dict,
|
|
||||||
const labelList& patchIDs
|
const labelList& patchIDs
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
//- Destructor
|
//- Destructor
|
||||||
virtual ~optMeshMovementVolumetricBSplines() = default;
|
virtual ~displacementMethodpLaplacianMotionSolver() = default;
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
//- Calculates surface mesh movement
|
//- Whether the motion solver prefers a point of a vol field as input
|
||||||
void moveMesh();
|
virtual bool preferPointField() const;
|
||||||
|
|
||||||
//- Store design variables and mesh, to act as the starting point of
|
//- Set motion filed related to model based on given motion
|
||||||
//- line search
|
void setMotionField(const pointVectorField& pointMovement);
|
||||||
virtual void storeDesignVariables();
|
|
||||||
|
|
||||||
//- Reset to starting point of line search
|
//- Set motion filed related to model based on given motion
|
||||||
virtual void resetDesignVariables();
|
void setMotionField(const volVectorField& cellMovement);
|
||||||
|
|
||||||
//- Compute eta value based on max displacement
|
//- Set control field as a vectorField. For methods working with
|
||||||
virtual scalar computeEta(const scalarField& correction);
|
//- parameters (RBF etc)
|
||||||
|
void setControlField(const vectorField& controlField);
|
||||||
|
|
||||||
//- Return active design variables
|
//- Set control field as a vectorField. For methods working with
|
||||||
virtual labelList getActiveDesignVariables() const;
|
//- parameters (RBF etc)
|
||||||
|
void setControlField(const scalarField& controlField);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2019 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
Copyright (C) 2019 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -29,6 +29,7 @@ License
|
|||||||
|
|
||||||
#include "elasticityMotionSolver.H"
|
#include "elasticityMotionSolver.H"
|
||||||
#include "motionInterpolation.H"
|
#include "motionInterpolation.H"
|
||||||
|
#include "motionDiffusivity.H"
|
||||||
#include "wallDist.H"
|
#include "wallDist.H"
|
||||||
#include "fixedValuePointPatchFields.H"
|
#include "fixedValuePointPatchFields.H"
|
||||||
#include "fvMatrices.H"
|
#include "fvMatrices.H"
|
||||||
@ -36,6 +37,7 @@ License
|
|||||||
#include "fvmDiv.H"
|
#include "fvmDiv.H"
|
||||||
#include "fvmDiv.H"
|
#include "fvmDiv.H"
|
||||||
#include "fvmLaplacian.H"
|
#include "fvmLaplacian.H"
|
||||||
|
#include "surfaceInterpolate.H"
|
||||||
#include "addToRunTimeSelectionTable.H"
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
@ -57,6 +59,19 @@ namespace Foam
|
|||||||
|
|
||||||
void Foam::elasticityMotionSolver::setBoundaryConditions()
|
void Foam::elasticityMotionSolver::setBoundaryConditions()
|
||||||
{
|
{
|
||||||
|
// Adjust boundary conditions based on the steps to be executed
|
||||||
|
forAll(cellMotionU_.boundaryField(), patchI)
|
||||||
|
{
|
||||||
|
fvPatchVectorField& bc =
|
||||||
|
cellMotionU_.boundaryFieldRef()[patchI];
|
||||||
|
if (isA<fixedValueFvPatchVectorField>(bc))
|
||||||
|
{
|
||||||
|
auto& fixedValueBCs =
|
||||||
|
refCast<fixedValueFvPatchVectorField>(bc);
|
||||||
|
fixedValueBCs == fixedValueBCs/scalar(nSteps_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
// Adjust boundary conditions based on the steps to be executed
|
// Adjust boundary conditions based on the steps to be executed
|
||||||
forAll(pointMotionU_.boundaryField(), patchI)
|
forAll(pointMotionU_.boundaryField(), patchI)
|
||||||
{
|
{
|
||||||
@ -88,6 +103,7 @@ void Foam::elasticityMotionSolver::setBoundaryConditions()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -141,21 +157,10 @@ Foam::elasticityMotionSolver::elasticityMotionSolver
|
|||||||
? motionInterpolation::New(fvMesh_, coeffDict().lookup("interpolation"))
|
? motionInterpolation::New(fvMesh_, coeffDict().lookup("interpolation"))
|
||||||
: motionInterpolation::New(fvMesh_)
|
: motionInterpolation::New(fvMesh_)
|
||||||
),
|
),
|
||||||
E_
|
diffusivityPtr_
|
||||||
(
|
(
|
||||||
IOobject
|
motionDiffusivity::New(fvMesh_, coeffDict().lookup("diffusivity"))
|
||||||
(
|
|
||||||
"mu",
|
|
||||||
mesh.time().timeName(),
|
|
||||||
mesh,
|
|
||||||
IOobject::NO_READ,
|
|
||||||
IOobject::NO_WRITE
|
|
||||||
),
|
|
||||||
fvMesh_,
|
|
||||||
dimensionedScalar(dimless, Zero),
|
|
||||||
fvPatchFieldBase::zeroGradientType()
|
|
||||||
),
|
),
|
||||||
exponent_(this->coeffDict().get<scalar>("exponent")),
|
|
||||||
nSteps_(this->coeffDict().get<label>("steps")),
|
nSteps_(this->coeffDict().get<label>("steps")),
|
||||||
nIters_(this->coeffDict().get<label>("iters")),
|
nIters_(this->coeffDict().get<label>("iters")),
|
||||||
tolerance_(this->coeffDict().get<scalar>("tolerance"))
|
tolerance_(this->coeffDict().get<scalar>("tolerance"))
|
||||||
@ -175,7 +180,7 @@ Foam::tmp<Foam::pointField> Foam::elasticityMotionSolver::curPoints() const
|
|||||||
void Foam::elasticityMotionSolver::solve()
|
void Foam::elasticityMotionSolver::solve()
|
||||||
{
|
{
|
||||||
// Re-init to zero
|
// Re-init to zero
|
||||||
cellMotionU_.primitiveFieldRef() = vector::zero;
|
cellMotionU_.primitiveFieldRef() = Zero;
|
||||||
|
|
||||||
// Adjust boundary conditions based on the number of steps to be executed
|
// Adjust boundary conditions based on the number of steps to be executed
|
||||||
// and interpolate to faces
|
// and interpolate to faces
|
||||||
@ -187,19 +192,18 @@ void Foam::elasticityMotionSolver::solve()
|
|||||||
Info<< "Step " << istep << endl;
|
Info<< "Step " << istep << endl;
|
||||||
|
|
||||||
// Update diffusivity
|
// Update diffusivity
|
||||||
const scalarField& vols = mesh().cellVolumes();
|
diffusivityPtr_->correct();
|
||||||
E_.primitiveFieldRef() = 1./pow(vols, exponent_);
|
const surfaceScalarField E(diffusivityPtr_->operator()());
|
||||||
E_.correctBoundaryConditions();
|
const surfaceVectorField& Sf = fvMesh_.Sf();
|
||||||
|
|
||||||
for (label iter = 0; iter < nIters_; ++iter)
|
for (label iter = 0; iter < nIters_; ++iter)
|
||||||
{
|
{
|
||||||
Info<< "Iteration " << iter << endl;
|
Info<< "Iteration " << iter << endl;
|
||||||
cellMotionU_.storePrevIter();
|
cellMotionU_.storePrevIter();
|
||||||
fvVectorMatrix dEqn
|
fvVectorMatrix dEqn
|
||||||
(
|
(
|
||||||
fvm::laplacian(2*E_, cellMotionU_)
|
fvm::laplacian(2*E, cellMotionU_)
|
||||||
+ fvc::div(2*E_*T(fvc::grad(cellMotionU_)))
|
+ fvc::div(2*E*(fvc::interpolate(fvc::grad(cellMotionU_)) & Sf))
|
||||||
- fvc::div(E_*fvc::div(cellMotionU_)*tensor::I)
|
- fvc::div(E*fvc::interpolate(fvc::div(cellMotionU_))*Sf)
|
||||||
);
|
);
|
||||||
|
|
||||||
scalar residual = mag(dEqn.solve().initialResidual());
|
scalar residual = mag(dEqn.solve().initialResidual());
|
||||||
@ -218,12 +222,34 @@ void Foam::elasticityMotionSolver::solve()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interpolationPtr_->interpolate
|
||||||
|
(
|
||||||
|
cellMotionU_,
|
||||||
|
pointMotionU_
|
||||||
|
);
|
||||||
|
|
||||||
|
tmp<vectorField> newPoints
|
||||||
|
(
|
||||||
|
fvMesh_.points() + pointMotionU_.primitiveField()
|
||||||
|
);
|
||||||
|
|
||||||
|
/*
|
||||||
// Interpolate from cells to points
|
// Interpolate from cells to points
|
||||||
interpolationPtr_->interpolate(cellMotionU_, pointMotionU_);
|
interpolationPtr_->interpolate(cellMotionU_, pointMotionU_);
|
||||||
|
|
||||||
|
syncTools::syncPointList
|
||||||
|
(
|
||||||
|
fvMesh_,
|
||||||
|
pointMotionU_.primitiveFieldRef(),
|
||||||
|
maxEqOp<vector>(),
|
||||||
|
vector::zero
|
||||||
|
);
|
||||||
|
|
||||||
vectorField newPoints
|
vectorField newPoints
|
||||||
(
|
(
|
||||||
mesh().points() + pointMotionU_.primitiveFieldRef()
|
mesh().points() + pointMotionU_.primitiveFieldRef()
|
||||||
);
|
);
|
||||||
|
*/
|
||||||
|
|
||||||
// Move points and check mesh
|
// Move points and check mesh
|
||||||
fvMesh_.movePoints(newPoints);
|
fvMesh_.movePoints(newPoints);
|
||||||
@ -259,7 +285,14 @@ void Foam::elasticityMotionSolver::movePoints(const pointField&)
|
|||||||
|
|
||||||
void Foam::elasticityMotionSolver::updateMesh(const mapPolyMesh&)
|
void Foam::elasticityMotionSolver::updateMesh(const mapPolyMesh&)
|
||||||
{
|
{
|
||||||
// Do nothing
|
// Update diffusivity. Note two stage to make sure old one is de-registered
|
||||||
|
// before creating/registering new one.
|
||||||
|
diffusivityPtr_.reset(nullptr);
|
||||||
|
diffusivityPtr_ = motionDiffusivity::New
|
||||||
|
(
|
||||||
|
fvMesh_,
|
||||||
|
coeffDict().lookup("diffusivity")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2019 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
Copyright (C) 2019 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -60,6 +60,7 @@ namespace Foam
|
|||||||
|
|
||||||
// Forward class declarations
|
// Forward class declarations
|
||||||
class motionInterpolation;
|
class motionInterpolation;
|
||||||
|
class motionDiffusivity;
|
||||||
class mapPolyMesh;
|
class mapPolyMesh;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
@ -84,11 +85,8 @@ protected:
|
|||||||
//- Interpolation used to transfer cell displacement to the points
|
//- Interpolation used to transfer cell displacement to the points
|
||||||
autoPtr<motionInterpolation> interpolationPtr_;
|
autoPtr<motionInterpolation> interpolationPtr_;
|
||||||
|
|
||||||
//- Inverse cell volume diffusivity
|
//- Diffusivity used to control the motion
|
||||||
volScalarField E_;
|
autoPtr<motionDiffusivity> diffusivityPtr_;
|
||||||
|
|
||||||
//- Exponent to stiffen highly morphed cells
|
|
||||||
scalar exponent_;
|
|
||||||
|
|
||||||
//- Intermediate steps to solve the PDEs
|
//- Intermediate steps to solve the PDEs
|
||||||
label nSteps_;
|
label nSteps_;
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2019 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
Copyright (C) 2019 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -29,8 +29,10 @@ License
|
|||||||
|
|
||||||
#include "laplacianMotionSolver.H"
|
#include "laplacianMotionSolver.H"
|
||||||
#include "motionInterpolation.H"
|
#include "motionInterpolation.H"
|
||||||
#include "addToRunTimeSelectionTable.H"
|
#include "motionDiffusivity.H"
|
||||||
#include "fvmLaplacian.H"
|
#include "fvmLaplacian.H"
|
||||||
|
#include "syncTools.H"
|
||||||
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -47,29 +49,6 @@ namespace Foam
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
|
||||||
|
|
||||||
void Foam::laplacianMotionSolver::setBoundaryConditions()
|
|
||||||
{
|
|
||||||
pointMotionU_.boundaryFieldRef().updateCoeffs();
|
|
||||||
auto& cellMotionUbf = cellMotionU_.boundaryFieldRef();
|
|
||||||
|
|
||||||
forAll(cellMotionU_.boundaryField(), pI)
|
|
||||||
{
|
|
||||||
fvPatchVectorField& bField = cellMotionUbf[pI];
|
|
||||||
if (isA<fixedValueFvPatchVectorField>(bField))
|
|
||||||
{
|
|
||||||
const pointField& points = fvMesh_.points();
|
|
||||||
const polyPatch& patch = fvMesh_.boundaryMesh()[pI];
|
|
||||||
forAll(bField, fI)
|
|
||||||
{
|
|
||||||
bField[fI] = patch[fI].average(points, pointMotionU_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
Foam::laplacianMotionSolver::laplacianMotionSolver
|
Foam::laplacianMotionSolver::laplacianMotionSolver
|
||||||
@ -114,6 +93,10 @@ Foam::laplacianMotionSolver::laplacianMotionSolver
|
|||||||
? motionInterpolation::New(fvMesh_, coeffDict().lookup("interpolation"))
|
? motionInterpolation::New(fvMesh_, coeffDict().lookup("interpolation"))
|
||||||
: motionInterpolation::New(fvMesh_)
|
: motionInterpolation::New(fvMesh_)
|
||||||
),
|
),
|
||||||
|
diffusivityPtr_
|
||||||
|
(
|
||||||
|
motionDiffusivity::New(fvMesh_, coeffDict().lookup("diffusivity"))
|
||||||
|
),
|
||||||
nIters_(this->coeffDict().get<label>("iters")),
|
nIters_(this->coeffDict().get<label>("iters")),
|
||||||
tolerance_(this->coeffDict().get<scalar>("tolerance"))
|
tolerance_(this->coeffDict().get<scalar>("tolerance"))
|
||||||
{}
|
{}
|
||||||
@ -129,9 +112,17 @@ Foam::tmp<Foam::pointField> Foam::laplacianMotionSolver::curPoints() const
|
|||||||
pointMotionU_
|
pointMotionU_
|
||||||
);
|
);
|
||||||
|
|
||||||
|
syncTools::syncPointList
|
||||||
|
(
|
||||||
|
fvMesh_,
|
||||||
|
pointMotionU_.primitiveFieldRef(),
|
||||||
|
maxEqOp<vector>(),
|
||||||
|
vector::zero
|
||||||
|
);
|
||||||
|
|
||||||
tmp<vectorField> tcurPoints
|
tmp<vectorField> tcurPoints
|
||||||
(
|
(
|
||||||
fvMesh_.points() + pointMotionU_.internalField()
|
fvMesh_.points() + pointMotionU_.primitiveField()
|
||||||
);
|
);
|
||||||
|
|
||||||
twoDCorrectPoints(tcurPoints.ref());
|
twoDCorrectPoints(tcurPoints.ref());
|
||||||
@ -142,7 +133,7 @@ Foam::tmp<Foam::pointField> Foam::laplacianMotionSolver::curPoints() const
|
|||||||
|
|
||||||
void Foam::laplacianMotionSolver::solve()
|
void Foam::laplacianMotionSolver::solve()
|
||||||
{
|
{
|
||||||
setBoundaryConditions();
|
diffusivityPtr_->correct();
|
||||||
|
|
||||||
// Iteratively solve the Laplace equation, to account for non-orthogonality
|
// Iteratively solve the Laplace equation, to account for non-orthogonality
|
||||||
for (label iter = 0; iter < nIters_; ++iter)
|
for (label iter = 0; iter < nIters_; ++iter)
|
||||||
@ -150,7 +141,13 @@ void Foam::laplacianMotionSolver::solve()
|
|||||||
Info<< "Iteration " << iter << endl;
|
Info<< "Iteration " << iter << endl;
|
||||||
fvVectorMatrix dEqn
|
fvVectorMatrix dEqn
|
||||||
(
|
(
|
||||||
fvm::laplacian(cellMotionU_)
|
fvm::laplacian
|
||||||
|
(
|
||||||
|
dimensionedScalar("viscosity", dimViscosity, 1.0)
|
||||||
|
* diffusivityPtr_->operator()(),
|
||||||
|
cellMotionU_,
|
||||||
|
"laplacian(diffusivity,cellMotionU)"
|
||||||
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
scalar residual = mag(dEqn.solve().initialResidual());
|
scalar residual = mag(dEqn.solve().initialResidual());
|
||||||
@ -169,6 +166,27 @@ void Foam::laplacianMotionSolver::solve()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::laplacianMotionSolver::setBoundaryConditions()
|
||||||
|
{
|
||||||
|
pointMotionU_.boundaryFieldRef().updateCoeffs();
|
||||||
|
auto& cellMotionUbf = cellMotionU_.boundaryFieldRef();
|
||||||
|
|
||||||
|
forAll(cellMotionU_.boundaryField(), pI)
|
||||||
|
{
|
||||||
|
fvPatchVectorField& bField = cellMotionUbf[pI];
|
||||||
|
if (isA<fixedValueFvPatchVectorField>(bField))
|
||||||
|
{
|
||||||
|
const pointField& points = fvMesh_.points();
|
||||||
|
const polyPatch& patch = fvMesh_.boundaryMesh()[pI];
|
||||||
|
forAll(bField, fI)
|
||||||
|
{
|
||||||
|
bField[fI] = patch[fI].average(points, pointMotionU_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::laplacianMotionSolver::movePoints(const pointField&)
|
void Foam::laplacianMotionSolver::movePoints(const pointField&)
|
||||||
{
|
{
|
||||||
// Do nothing
|
// Do nothing
|
||||||
@ -177,7 +195,14 @@ void Foam::laplacianMotionSolver::movePoints(const pointField&)
|
|||||||
|
|
||||||
void Foam::laplacianMotionSolver::updateMesh(const mapPolyMesh&)
|
void Foam::laplacianMotionSolver::updateMesh(const mapPolyMesh&)
|
||||||
{
|
{
|
||||||
// Do nothing
|
// Update diffusivity. Note two stage to make sure old one is de-registered
|
||||||
|
// before creating/registering new one.
|
||||||
|
diffusivityPtr_.reset(nullptr);
|
||||||
|
diffusivityPtr_ = motionDiffusivity::New
|
||||||
|
(
|
||||||
|
fvMesh_,
|
||||||
|
coeffDict().lookup("diffusivity")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2019 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
Copyright (C) 2019 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -59,6 +59,7 @@ namespace Foam
|
|||||||
|
|
||||||
// Forward class declarations
|
// Forward class declarations
|
||||||
class motionInterpolation;
|
class motionInterpolation;
|
||||||
|
class motionDiffusivity;
|
||||||
class mapPolyMesh;
|
class mapPolyMesh;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
@ -80,6 +81,9 @@ protected:
|
|||||||
//- Interpolation used to transfer cell displacement to the points
|
//- Interpolation used to transfer cell displacement to the points
|
||||||
autoPtr<motionInterpolation> interpolationPtr_;
|
autoPtr<motionInterpolation> interpolationPtr_;
|
||||||
|
|
||||||
|
//- Diffusivity used to control the motion
|
||||||
|
autoPtr<motionDiffusivity> diffusivityPtr_;
|
||||||
|
|
||||||
//- Number of laplacian iterations per solution step
|
//- Number of laplacian iterations per solution step
|
||||||
label nIters_;
|
label nIters_;
|
||||||
|
|
||||||
@ -87,16 +91,6 @@ protected:
|
|||||||
scalar tolerance_;
|
scalar tolerance_;
|
||||||
|
|
||||||
|
|
||||||
// Protected Member Functions
|
|
||||||
|
|
||||||
//- Set boundary conditions of cellMotionU based on pointMotionU.
|
|
||||||
// Avoiding the use of the cellMotionFvPatchField bc
|
|
||||||
// due to the use of the registry in order to grab pointMotionU, which
|
|
||||||
// may give problems if multiple objects of this class are constructed
|
|
||||||
// at the same time
|
|
||||||
void setBoundaryConditions();
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
||||||
@ -144,6 +138,13 @@ public:
|
|||||||
//- Solve for motion
|
//- Solve for motion
|
||||||
virtual void solve();
|
virtual void solve();
|
||||||
|
|
||||||
|
//- Set boundary conditions of cellMotionU based on pointMotionU.
|
||||||
|
// Avoiding the use of the cellMotionFvPatchField bc
|
||||||
|
// due to the use of the registry in order to grab pointMotionU, which
|
||||||
|
// may give problems if multiple objects of this class are constructed
|
||||||
|
// at the same time
|
||||||
|
void setBoundaryConditions();
|
||||||
|
|
||||||
//- Update local data for geometry changes
|
//- Update local data for geometry changes
|
||||||
virtual void movePoints(const pointField&);
|
virtual void movePoints(const pointField&);
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,219 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2021-2023 PCOpt/NTUA
|
||||||
|
Copyright (C) 2021-2023 FOSS GP
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "pLaplacianMotionSolver.H"
|
||||||
|
#include "motionInterpolation.H"
|
||||||
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
#include "syncTools.H"
|
||||||
|
#include "fvmLaplacian.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
defineTypeNameAndDebug(pLaplacianMotionSolver, 1);
|
||||||
|
|
||||||
|
addToRunTimeSelectionTable
|
||||||
|
(
|
||||||
|
motionSolver,
|
||||||
|
pLaplacianMotionSolver,
|
||||||
|
dictionary
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::pLaplacianMotionSolver::pLaplacianMotionSolver
|
||||||
|
(
|
||||||
|
const polyMesh& mesh,
|
||||||
|
const IOdictionary& dict
|
||||||
|
)
|
||||||
|
:
|
||||||
|
motionSolver(mesh, dict, typeName),
|
||||||
|
fvMotionSolver(mesh),
|
||||||
|
useFixedValuePointMotionUBCs_
|
||||||
|
(coeffDict().getOrDefault<bool>("useFixedValuePointMotionUBCs", false)),
|
||||||
|
pointMotionU_
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"pointMotionU",
|
||||||
|
mesh.time().timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::READ_IF_PRESENT,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
pointMesh::New(mesh),
|
||||||
|
dimensionedVector(dimless, Zero),
|
||||||
|
word
|
||||||
|
(
|
||||||
|
useFixedValuePointMotionUBCs_
|
||||||
|
? fixedValuePointPatchVectorField::typeName
|
||||||
|
: calculatedPointPatchField<vector>::typeName
|
||||||
|
)
|
||||||
|
),
|
||||||
|
cellMotionU_
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"cellMotionU",
|
||||||
|
mesh.time().timeName(),
|
||||||
|
mesh,
|
||||||
|
IOobject::READ_IF_PRESENT,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
fvMesh_,
|
||||||
|
dimensionedVector(pointMotionU_.dimensions(), Zero),
|
||||||
|
pointMotionU_.boundaryField().types()
|
||||||
|
),
|
||||||
|
interpolationPtr_
|
||||||
|
(
|
||||||
|
coeffDict().found("interpolation")
|
||||||
|
? motionInterpolation::New(fvMesh_, coeffDict().lookup("interpolation"))
|
||||||
|
: motionInterpolation::New(fvMesh_)
|
||||||
|
),
|
||||||
|
nIters_(this->coeffDict().get<label>("iters")),
|
||||||
|
tolerance_(this->coeffDict().get<scalar>("tolerance")),
|
||||||
|
toleranceIntermediate_
|
||||||
|
(
|
||||||
|
this->coeffDict().
|
||||||
|
getOrDefault<scalar>("toleranceIntermediate", 100*tolerance_)
|
||||||
|
),
|
||||||
|
exponent_(this->coeffDict().get<label>("exponent"))
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::pLaplacianMotionSolver::setBoundaryConditions()
|
||||||
|
{
|
||||||
|
pointMotionU_.boundaryFieldRef().updateCoeffs();
|
||||||
|
auto& cellMotionUbf = cellMotionU_.boundaryFieldRef();
|
||||||
|
|
||||||
|
forAll(cellMotionU_.boundaryField(), pI)
|
||||||
|
{
|
||||||
|
fvPatchVectorField& bField = cellMotionUbf[pI];
|
||||||
|
if (isA<fixedValueFvPatchVectorField>(bField))
|
||||||
|
{
|
||||||
|
const pointField& points = fvMesh_.points();
|
||||||
|
const polyPatch& patch = fvMesh_.boundaryMesh()[pI];
|
||||||
|
forAll(bField, fI)
|
||||||
|
{
|
||||||
|
bField[fI] = patch[fI].average(points, pointMotionU_);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tmp<Foam::pointField> Foam::pLaplacianMotionSolver::curPoints() const
|
||||||
|
{
|
||||||
|
interpolationPtr_->interpolate
|
||||||
|
(
|
||||||
|
cellMotionU_,
|
||||||
|
pointMotionU_
|
||||||
|
);
|
||||||
|
|
||||||
|
syncTools::syncPointList
|
||||||
|
(
|
||||||
|
fvMesh_,
|
||||||
|
pointMotionU_.primitiveFieldRef(),
|
||||||
|
maxEqOp<vector>(),
|
||||||
|
vector::zero
|
||||||
|
);
|
||||||
|
|
||||||
|
tmp<vectorField> tcurPoints
|
||||||
|
(
|
||||||
|
fvMesh_.points() + pointMotionU_.internalField()
|
||||||
|
);
|
||||||
|
|
||||||
|
twoDCorrectPoints(tcurPoints.ref());
|
||||||
|
|
||||||
|
return tcurPoints;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::pLaplacianMotionSolver::solve()
|
||||||
|
{
|
||||||
|
// setBoundaryConditions();
|
||||||
|
|
||||||
|
for (label exp = 2; exp < exponent_ + 1; ++exp)
|
||||||
|
{
|
||||||
|
scalar tolerance
|
||||||
|
(exp == exponent_ ? tolerance_ : toleranceIntermediate_);
|
||||||
|
Info<< "Solving for exponent " << exp << endl;
|
||||||
|
|
||||||
|
for (label iter = 0; iter < nIters_; ++iter)
|
||||||
|
{
|
||||||
|
Info<< "Iteration " << iter << endl;
|
||||||
|
cellMotionU_.storePrevIter();
|
||||||
|
volScalarField gamma(pow(mag(fvc::grad(cellMotionU_)), exp - 2));
|
||||||
|
gamma.correctBoundaryConditions();
|
||||||
|
fvVectorMatrix dEqn
|
||||||
|
(
|
||||||
|
fvm::laplacian(gamma, cellMotionU_)
|
||||||
|
);
|
||||||
|
|
||||||
|
scalar residual = mag(dEqn.solve().initialResidual());
|
||||||
|
|
||||||
|
cellMotionU_.relax();
|
||||||
|
|
||||||
|
// Print execution time
|
||||||
|
fvMesh_.time().printExecutionTime(Info);
|
||||||
|
|
||||||
|
// Check convergence
|
||||||
|
if (residual < tolerance)
|
||||||
|
{
|
||||||
|
Info<< "\n***Reached mesh movement convergence limit at"
|
||||||
|
<< " iteration " << iter << "***\n\n";
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
gamma.write();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::pLaplacianMotionSolver::movePoints(const pointField&)
|
||||||
|
{
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::pLaplacianMotionSolver::updateMesh(const mapPolyMesh&)
|
||||||
|
{
|
||||||
|
// Do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,178 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2021-2023 PCOpt/NTUA
|
||||||
|
Copyright (C) 2021-2023 FOSS GP
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::pLaplacianMotionSolver
|
||||||
|
|
||||||
|
Description
|
||||||
|
Similar to velocityLaplacian but with a variable diffusivity, based
|
||||||
|
on the gradient of the displacement.
|
||||||
|
The boundary displacement is set as a boundary condition
|
||||||
|
on pointMotionU; the latter is generated automatically if not found.
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
pLaplacianMotionSolver.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef pLaplacianMotionSolver_H
|
||||||
|
#define pLaplacianMotionSolver_H
|
||||||
|
|
||||||
|
#include "velocityMotionSolver.H"
|
||||||
|
#include "fvMotionSolver.H"
|
||||||
|
#include "volPointInterpolation.H"
|
||||||
|
#include "polyMesh.H"
|
||||||
|
#include "pointMesh.H"
|
||||||
|
#include "pointPatchField.H"
|
||||||
|
#include "pointPatchFieldsFwd.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// Forward class declarations
|
||||||
|
class motionInterpolation;
|
||||||
|
class mapPolyMesh;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class pLaplacianMotionSolver Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class pLaplacianMotionSolver
|
||||||
|
:
|
||||||
|
public motionSolver,
|
||||||
|
public fvMotionSolver
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// Protected data
|
||||||
|
|
||||||
|
// Use a fixedValue boundary condition for the moving patches? When
|
||||||
|
// using this motionSolver in an optimisation context, we usually go
|
||||||
|
// from point movement to face movement, solve the grid dispalcement
|
||||||
|
// PDE and then interpolate the movement back to the points. If the
|
||||||
|
// boundary conditions of pointMotionU are fixedValue, the initial
|
||||||
|
// values will be retained, otherwise they will be overwritten by the
|
||||||
|
// face-to-point interpolation. The latter is usually beneficial for
|
||||||
|
// the resulting mesh quality but does not give us the exact geometry.
|
||||||
|
bool useFixedValuePointMotionUBCs_;
|
||||||
|
|
||||||
|
mutable pointVectorField pointMotionU_;
|
||||||
|
volVectorField cellMotionU_;
|
||||||
|
|
||||||
|
//- Interpolation used to transfer cell displacement to the points
|
||||||
|
autoPtr<motionInterpolation> interpolationPtr_;
|
||||||
|
|
||||||
|
//- Number of pLaplacian iterations per solution step
|
||||||
|
label nIters_;
|
||||||
|
|
||||||
|
//- Residual threshold
|
||||||
|
scalar tolerance_;
|
||||||
|
|
||||||
|
//- Residual threshold for intermediate exponents
|
||||||
|
scalar toleranceIntermediate_;
|
||||||
|
|
||||||
|
//- Exponent defining the order or the p-Laplacian
|
||||||
|
label exponent_;
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
//- No copy construct
|
||||||
|
pLaplacianMotionSolver(const pLaplacianMotionSolver&) = delete;
|
||||||
|
|
||||||
|
//- No copy assignment
|
||||||
|
void operator=(const pLaplacianMotionSolver&) = delete;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
TypeName("pLaplacianMotionSolver");
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct from mesh and dictionary
|
||||||
|
pLaplacianMotionSolver
|
||||||
|
(
|
||||||
|
const polyMesh& mesh,
|
||||||
|
const IOdictionary& dict
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
//- Destructor
|
||||||
|
virtual ~pLaplacianMotionSolver() = default;
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
//- Set boundary conditions of cellMotionU based on pointMotionU.
|
||||||
|
// Avoiding the use of the cellMotionFvPatchField bc
|
||||||
|
// due to the use of the registry in order to grab pointMotionU, which
|
||||||
|
// may give problems if multiple objects of this class are constructed
|
||||||
|
// at the same time
|
||||||
|
void setBoundaryConditions();
|
||||||
|
|
||||||
|
//- Get const and non-const references to pointMotionU
|
||||||
|
inline pointVectorField& pointMotionU();
|
||||||
|
inline const pointVectorField& pointMotionU() const;
|
||||||
|
|
||||||
|
//- Get const and non-const references to cellMotionU
|
||||||
|
inline volVectorField& cellMotionU();
|
||||||
|
inline const volVectorField& cellMotionU() const;
|
||||||
|
|
||||||
|
//- Return point location obtained from the current motion field
|
||||||
|
virtual tmp<pointField> curPoints() const;
|
||||||
|
|
||||||
|
//- Solve for motion
|
||||||
|
virtual void solve();
|
||||||
|
|
||||||
|
//- Update local data for geometry changes
|
||||||
|
virtual void movePoints(const pointField&);
|
||||||
|
|
||||||
|
//- Update the mesh corresponding to given map
|
||||||
|
virtual void updateMesh(const mapPolyMesh&);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#include "pLaplacianMotionSolverI.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -5,9 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2013-2019 FOSS GP
|
Copyright (C) 2021-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
Copyright (C) 2021-2023 FOSS GP
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -27,47 +26,34 @@ License
|
|||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
|
|
||||||
namespace incompressible
|
|
||||||
{
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
inline bool sensitivitySurface::getIncludeObjective() const
|
inline Foam::pointVectorField& Foam::pLaplacianMotionSolver::pointMotionU()
|
||||||
{
|
{
|
||||||
return includeObjective_;
|
return pointMotionU_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool sensitivitySurface::getIncludeSurfaceArea() const
|
inline const Foam::pointVectorField&
|
||||||
|
Foam::pLaplacianMotionSolver::pointMotionU() const
|
||||||
{
|
{
|
||||||
return includeSurfaceArea_;
|
return pointMotionU_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void sensitivitySurface::setIncludeObjective
|
inline Foam::volVectorField& Foam::pLaplacianMotionSolver::cellMotionU()
|
||||||
(
|
|
||||||
const bool includeObjective
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
includeObjective_ = includeObjective;
|
return cellMotionU_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
inline void sensitivitySurface::setIncludeSurfaceArea
|
inline const Foam::volVectorField&
|
||||||
(
|
Foam::pLaplacianMotionSolver::cellMotionU() const
|
||||||
const bool includeSurfaceArea
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
includeSurfaceArea_ = includeSurfaceArea;
|
return cellMotionU_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
} // End namespace incompressible
|
|
||||||
} // End namespace Foam
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,345 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||||
|
Copyright (C) 2016-2020 OpenCFD Ltd.
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "volPointInterpolationAdjoint.H"
|
||||||
|
#include "volFields.H"
|
||||||
|
#include "pointFields.H"
|
||||||
|
#include "emptyFvPatch.H"
|
||||||
|
#include "coupledPointPatchField.H"
|
||||||
|
#include "pointConstraints.H"
|
||||||
|
#include "symmetryPolyPatch.H"
|
||||||
|
#include "symmetryPlanePolyPatch.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
void Foam::volPointInterpolationAdjoint::pushUntransformedData
|
||||||
|
(
|
||||||
|
List<Type>& pointData
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
// Transfer onto coupled patch
|
||||||
|
const globalMeshData& gmd = mesh().globalData();
|
||||||
|
const indirectPrimitivePatch& cpp = gmd.coupledPatch();
|
||||||
|
const labelList& meshPoints = cpp.meshPoints();
|
||||||
|
|
||||||
|
const mapDistribute& slavesMap = gmd.globalCoPointSlavesMap();
|
||||||
|
const labelListList& slaves = gmd.globalCoPointSlaves();
|
||||||
|
|
||||||
|
List<Type> elems(slavesMap.constructSize());
|
||||||
|
forAll(meshPoints, i)
|
||||||
|
{
|
||||||
|
elems[i] = pointData[meshPoints[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Combine master data with slave data
|
||||||
|
forAll(slaves, i)
|
||||||
|
{
|
||||||
|
const labelList& slavePoints = slaves[i];
|
||||||
|
|
||||||
|
// Copy master data to slave slots
|
||||||
|
forAll(slavePoints, j)
|
||||||
|
{
|
||||||
|
elems[slavePoints[j]] = elems[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Push slave-slot data back to slaves
|
||||||
|
slavesMap.reverseDistribute(elems.size(), elems, false);
|
||||||
|
|
||||||
|
// Extract back onto mesh
|
||||||
|
forAll(meshPoints, i)
|
||||||
|
{
|
||||||
|
pointData[meshPoints[i]] = elems[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
Foam::tmp<Foam::Field<Type>> Foam::volPointInterpolationAdjoint::flatBoundaryField
|
||||||
|
(
|
||||||
|
const GeometricField<Type, fvPatchField, volMesh>& vf
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
const fvMesh& mesh = vf.mesh();
|
||||||
|
const fvBoundaryMesh& bm = mesh.boundary();
|
||||||
|
|
||||||
|
tmp<Field<Type>> tboundaryVals
|
||||||
|
(
|
||||||
|
new Field<Type>(mesh.nBoundaryFaces())
|
||||||
|
);
|
||||||
|
Field<Type>& boundaryVals = tboundaryVals.ref();
|
||||||
|
|
||||||
|
forAll(vf.boundaryField(), patchi)
|
||||||
|
{
|
||||||
|
label bFacei = bm[patchi].patch().start() - mesh.nInternalFaces();
|
||||||
|
|
||||||
|
if
|
||||||
|
(
|
||||||
|
!isA<emptyFvPatch>(bm[patchi])
|
||||||
|
&& !vf.boundaryField()[patchi].coupled()
|
||||||
|
)
|
||||||
|
{
|
||||||
|
SubList<Type>
|
||||||
|
(
|
||||||
|
boundaryVals,
|
||||||
|
vf.boundaryField()[patchi].size(),
|
||||||
|
bFacei
|
||||||
|
) = vf.boundaryField()[patchi];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
const polyPatch& pp = bm[patchi].patch();
|
||||||
|
|
||||||
|
forAll(pp, i)
|
||||||
|
{
|
||||||
|
boundaryVals[bFacei++] = Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tboundaryVals;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
void Foam::volPointInterpolationAdjoint::addSeparated
|
||||||
|
(
|
||||||
|
GeometricField<Type, pointPatchField, pointMesh>& pf
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
Pout<< "volPointInterpolation::addSeparated" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto& pfi = pf.ref();
|
||||||
|
auto& pfbf = pf.boundaryFieldRef();
|
||||||
|
|
||||||
|
const label startOfRequests = UPstream::nRequests();
|
||||||
|
|
||||||
|
forAll(pfbf, patchi)
|
||||||
|
{
|
||||||
|
if (pfbf[patchi].coupled())
|
||||||
|
{
|
||||||
|
refCast<coupledPointPatchField<Type>>
|
||||||
|
(pfbf[patchi]).initSwapAddSeparated
|
||||||
|
(
|
||||||
|
Pstream::commsTypes::nonBlocking,
|
||||||
|
pfi
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for outstanding requests
|
||||||
|
UPstream::waitRequests(startOfRequests);
|
||||||
|
|
||||||
|
forAll(pfbf, patchi)
|
||||||
|
{
|
||||||
|
if (pfbf[patchi].coupled())
|
||||||
|
{
|
||||||
|
refCast<coupledPointPatchField<Type>>
|
||||||
|
(pfbf[patchi]).swapAddSeparated
|
||||||
|
(
|
||||||
|
Pstream::commsTypes::nonBlocking,
|
||||||
|
pfi
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
void Foam::volPointInterpolationAdjoint::interpolateSensitivitiesField
|
||||||
|
(
|
||||||
|
const GeometricField<Type, pointPatchField, pointMesh>& pf,
|
||||||
|
typename GeometricField<Type, fvPatchField, volMesh>::Boundary& vf,
|
||||||
|
const labelHashSet& patchIDs
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
const Field<Type>& pfi = pf.primitiveField();
|
||||||
|
|
||||||
|
// Get face data in flat list
|
||||||
|
const fvMesh& Mesh = mesh();
|
||||||
|
const fvBoundaryMesh& bm = Mesh.boundary();
|
||||||
|
|
||||||
|
tmp<Field<Type>> tboundaryVals
|
||||||
|
(
|
||||||
|
new Field<Type>(Mesh.nBoundaryFaces(), Zero)
|
||||||
|
);
|
||||||
|
Field<Type>& boundaryVals = tboundaryVals.ref();
|
||||||
|
|
||||||
|
// Do points on 'normal' patches from the surrounding patch faces
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
const primitivePatch& boundary = boundaryPtr_();
|
||||||
|
const labelList& mp = boundary.meshPoints();
|
||||||
|
|
||||||
|
forAll(mp, i)
|
||||||
|
{
|
||||||
|
label pointi = mp[i];
|
||||||
|
|
||||||
|
if (isPatchPoint_[pointi])
|
||||||
|
{
|
||||||
|
const labelList& pFaces = boundary.pointFaces()[i];
|
||||||
|
const scalarList& pWeights = boundaryPointWeights_[i];
|
||||||
|
const Type& val = pfi[pointi];
|
||||||
|
// Face-to-point weights should, in general, have half the weight
|
||||||
|
// of what they actually do in volPointInterpolation since, in
|
||||||
|
// a complete case, a face laying on the opposite side of the
|
||||||
|
// symmetry plane would also contribute to a point laying on
|
||||||
|
// the symmetry plane.
|
||||||
|
// For face-to-point interpolation this is not a problem, but for
|
||||||
|
// the adjoint point-to-face interpolation, the correct value of
|
||||||
|
// the weight should be taken into consideration
|
||||||
|
scalar mod(isSymmetryPoint_[pointi] ? 0.5 : 1);
|
||||||
|
|
||||||
|
forAll(pFaces, j)
|
||||||
|
{
|
||||||
|
if (boundaryIsPatchFace_[pFaces[j]])
|
||||||
|
{
|
||||||
|
boundaryVals[pFaces[j]] += mod*pWeights[j]*val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transfer values to face-based sensitivity field
|
||||||
|
for (const label patchi : patchIDs)
|
||||||
|
{
|
||||||
|
label bFacei = bm[patchi].patch().start() - Mesh.nInternalFaces();
|
||||||
|
if (!isA<emptyFvPatch>(bm[patchi]) && !vf[patchi].coupled())
|
||||||
|
{
|
||||||
|
vf[patchi] =
|
||||||
|
SubList<Type>
|
||||||
|
(
|
||||||
|
boundaryVals,
|
||||||
|
vf[patchi].size(),
|
||||||
|
bFacei
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
void Foam::volPointInterpolationAdjoint::interpolateBoundaryField
|
||||||
|
(
|
||||||
|
const GeometricField<Type, fvPatchField, volMesh>& vf,
|
||||||
|
GeometricField<Type, pointPatchField, pointMesh>& pf
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
const primitivePatch& boundary = boundaryPtr_();
|
||||||
|
|
||||||
|
Field<Type>& pfi = pf.primitiveFieldRef();
|
||||||
|
|
||||||
|
// Get face data in flat list
|
||||||
|
tmp<Field<Type>> tboundaryVals(flatBoundaryField(vf));
|
||||||
|
const Field<Type>& boundaryVals = tboundaryVals();
|
||||||
|
|
||||||
|
|
||||||
|
// Do points on 'normal' patches from the surrounding patch faces
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
const labelList& mp = boundary.meshPoints();
|
||||||
|
|
||||||
|
forAll(mp, i)
|
||||||
|
{
|
||||||
|
label pointi = mp[i];
|
||||||
|
|
||||||
|
if (isPatchPoint_[pointi])
|
||||||
|
{
|
||||||
|
const labelList& pFaces = boundary.pointFaces()[i];
|
||||||
|
const scalarList& pWeights = boundaryPointWeights_[i];
|
||||||
|
|
||||||
|
Type& val = pfi[pointi];
|
||||||
|
|
||||||
|
val = Zero;
|
||||||
|
forAll(pFaces, j)
|
||||||
|
{
|
||||||
|
if (boundaryIsPatchFace_[pFaces[j]])
|
||||||
|
{
|
||||||
|
scalar mod(1);
|
||||||
|
if (isSymmetryPoint_[pointi])
|
||||||
|
{
|
||||||
|
const label globalFaceI =
|
||||||
|
mesh().nInternalFaces() + pFaces[j];
|
||||||
|
const label facePatchID =
|
||||||
|
mesh().boundaryMesh().whichPatch(globalFaceI);
|
||||||
|
const polyPatch& pp = mesh().boundaryMesh()[facePatchID];
|
||||||
|
if
|
||||||
|
(
|
||||||
|
isA<symmetryPolyPatch>(pp)
|
||||||
|
|| isA<symmetryPlanePolyPatch>(pp)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
mod = 0;
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
//{
|
||||||
|
// mod = 2;
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
val += mod*pWeights[j]*boundaryVals[pFaces[j]];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sum collocated contributions
|
||||||
|
pointConstraints::syncUntransformedData(mesh(), pfi, plusEqOp<Type>());
|
||||||
|
|
||||||
|
// And add separated contributions
|
||||||
|
addSeparated(pf);
|
||||||
|
|
||||||
|
// Optionally normalise
|
||||||
|
/*
|
||||||
|
if (normalisationPtr_)
|
||||||
|
{
|
||||||
|
const scalarField& normalisation = normalisationPtr_();
|
||||||
|
forAll(mp, i)
|
||||||
|
{
|
||||||
|
pfi[mp[i]] *= normalisation[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// Push master data to slaves. It is possible (not sure how often) for
|
||||||
|
// a coupled point to have its master on a different patch so
|
||||||
|
// to make sure just push master data to slaves.
|
||||||
|
pushUntransformedData(pfi);
|
||||||
|
|
||||||
|
// Apply displacement constraints
|
||||||
|
const pointConstraints& pcs = pointConstraints::New(pf.mesh());
|
||||||
|
|
||||||
|
pcs.constrain(pf, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,391 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||||
|
Copyright (C) 2020 OpenCFD Ltd.
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "volPointInterpolationAdjoint.H"
|
||||||
|
#include "fvMesh.H"
|
||||||
|
#include "volFields.H"
|
||||||
|
#include "pointFields.H"
|
||||||
|
#include "pointConstraints.H"
|
||||||
|
#include "surfaceFields.H"
|
||||||
|
#include "processorPointPatch.H"
|
||||||
|
#include "symmetryPolyPatch.H"
|
||||||
|
#include "symmetryPlanePolyPatch.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
defineTypeNameAndDebug(volPointInterpolationAdjoint, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::volPointInterpolationAdjoint::calcBoundaryAddressing()
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
Pout<< "volPointInterpolationAdjoint::calcBoundaryAddressing() : "
|
||||||
|
<< "constructing boundary addressing"
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
boundaryPtr_.reset
|
||||||
|
(
|
||||||
|
new primitivePatch
|
||||||
|
(
|
||||||
|
SubList<face>
|
||||||
|
(
|
||||||
|
mesh().faces(),
|
||||||
|
mesh().nBoundaryFaces(),
|
||||||
|
mesh().nInternalFaces()
|
||||||
|
),
|
||||||
|
mesh().points()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
const primitivePatch& boundary = boundaryPtr_();
|
||||||
|
|
||||||
|
boundaryIsPatchFace_.setSize(boundary.size());
|
||||||
|
boundaryIsPatchFace_ = false;
|
||||||
|
|
||||||
|
// Store per mesh point whether it is on any 'real' patch. Currently
|
||||||
|
// boolList just so we can use syncUntransformedData (does not take
|
||||||
|
// bitSet. Tbd)
|
||||||
|
boolList isPatchPoint(mesh().nPoints(), false);
|
||||||
|
boolList isSymmetryPoint(mesh().nPoints(), false);
|
||||||
|
|
||||||
|
const polyBoundaryMesh& pbm = mesh().boundaryMesh();
|
||||||
|
|
||||||
|
// Get precalculated volField only so we can use coupled() tests for
|
||||||
|
// cyclicAMI
|
||||||
|
const surfaceScalarField& magSf = mesh().magSf();
|
||||||
|
|
||||||
|
forAll(pbm, patchi)
|
||||||
|
{
|
||||||
|
const polyPatch& pp = pbm[patchi];
|
||||||
|
|
||||||
|
if
|
||||||
|
(
|
||||||
|
!isA<emptyPolyPatch>(pp)
|
||||||
|
&& !magSf.boundaryField()[patchi].coupled()
|
||||||
|
&& !isA<symmetryPolyPatch>(pp)
|
||||||
|
&& !isA<symmetryPlanePolyPatch>(pp)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
label bFacei = pp.start()-mesh().nInternalFaces();
|
||||||
|
|
||||||
|
forAll(pp, i)
|
||||||
|
{
|
||||||
|
boundaryIsPatchFace_[bFacei] = true;
|
||||||
|
|
||||||
|
const face& f = boundary[bFacei++];
|
||||||
|
|
||||||
|
forAll(f, fp)
|
||||||
|
{
|
||||||
|
isPatchPoint[f[fp]] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (isA<symmetryPolyPatch>(pp) || isA<symmetryPlanePolyPatch>(pp))
|
||||||
|
{
|
||||||
|
const labelList& meshPoints = pp.meshPoints();
|
||||||
|
for (const label pointI : meshPoints)
|
||||||
|
{
|
||||||
|
isSymmetryPoint[pointI] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure point status is synchronised so even processor that holds
|
||||||
|
// no face of a certain patch still can have boundary points marked.
|
||||||
|
pointConstraints::syncUntransformedData
|
||||||
|
(
|
||||||
|
mesh(),
|
||||||
|
isPatchPoint,
|
||||||
|
orEqOp<bool>()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Convert to bitSet
|
||||||
|
isPatchPoint_.setSize(mesh().nPoints());
|
||||||
|
isPatchPoint_.assign(isPatchPoint);
|
||||||
|
|
||||||
|
isSymmetryPoint_.setSize(mesh().nPoints());
|
||||||
|
isSymmetryPoint_.assign(isSymmetryPoint);
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
label nPatchFace = 0;
|
||||||
|
forAll(boundaryIsPatchFace_, i)
|
||||||
|
{
|
||||||
|
if (boundaryIsPatchFace_[i])
|
||||||
|
{
|
||||||
|
nPatchFace++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
label nPatchPoint = 0;
|
||||||
|
forAll(isPatchPoint_, i)
|
||||||
|
{
|
||||||
|
if (isPatchPoint_[i])
|
||||||
|
{
|
||||||
|
nPatchPoint++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Pout<< "boundary:" << nl
|
||||||
|
<< " faces :" << boundary.size() << nl
|
||||||
|
<< " of which on proper patch:" << nPatchFace << nl
|
||||||
|
<< " points:" << boundary.nPoints() << nl
|
||||||
|
<< " of which on proper patch:" << nPatchPoint << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::volPointInterpolationAdjoint::makeBoundaryWeights
|
||||||
|
(
|
||||||
|
scalarField& sumWeights
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
Pout<< "volPointInterpolationAdjoint::makeBoundaryWeights() : "
|
||||||
|
<< "constructing weighting factors for boundary points." << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pointField& points = mesh().points();
|
||||||
|
const pointField& faceCentres = mesh().faceCentres();
|
||||||
|
|
||||||
|
const primitivePatch& boundary = boundaryPtr_();
|
||||||
|
|
||||||
|
boundaryPointWeights_.clear();
|
||||||
|
boundaryPointWeights_.setSize(boundary.meshPoints().size());
|
||||||
|
|
||||||
|
forAll(boundary.meshPoints(), i)
|
||||||
|
{
|
||||||
|
label pointi = boundary.meshPoints()[i];
|
||||||
|
|
||||||
|
if (isPatchPoint_[pointi])
|
||||||
|
{
|
||||||
|
const labelList& pFaces = boundary.pointFaces()[i];
|
||||||
|
|
||||||
|
scalarList& pw = boundaryPointWeights_[i];
|
||||||
|
pw.setSize(pFaces.size());
|
||||||
|
|
||||||
|
sumWeights[pointi] = 0.0;
|
||||||
|
|
||||||
|
forAll(pFaces, i)
|
||||||
|
{
|
||||||
|
if (boundaryIsPatchFace_[pFaces[i]])
|
||||||
|
{
|
||||||
|
label facei = mesh().nInternalFaces() + pFaces[i];
|
||||||
|
|
||||||
|
pw[i] = 1.0/mag(points[pointi] - faceCentres[facei]);
|
||||||
|
sumWeights[pointi] += pw[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pw[i] = 0.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::volPointInterpolationAdjoint::makeWeights()
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
Pout<< "volPointInterpolationAdjoint::makeWeights() : "
|
||||||
|
<< "constructing weighting factors"
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pointMesh& pMesh = pointMesh::New(mesh());
|
||||||
|
|
||||||
|
// Update addressing over all boundary faces
|
||||||
|
calcBoundaryAddressing();
|
||||||
|
|
||||||
|
|
||||||
|
// Running sum of weights
|
||||||
|
tmp<pointScalarField> tsumWeights
|
||||||
|
(
|
||||||
|
new pointScalarField
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"volPointSumWeights",
|
||||||
|
mesh().polyMesh::instance(),
|
||||||
|
mesh()
|
||||||
|
),
|
||||||
|
pMesh,
|
||||||
|
dimensionedScalar(dimless, Zero)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
pointScalarField& sumWeights = tsumWeights.ref();
|
||||||
|
|
||||||
|
|
||||||
|
// Create boundary weights; sumWeights
|
||||||
|
makeBoundaryWeights(sumWeights);
|
||||||
|
|
||||||
|
|
||||||
|
const primitivePatch& boundary = boundaryPtr_();
|
||||||
|
const labelList& mp = boundary.meshPoints();
|
||||||
|
|
||||||
|
|
||||||
|
// Sum collocated contributions
|
||||||
|
pointConstraints::syncUntransformedData
|
||||||
|
(
|
||||||
|
mesh(),
|
||||||
|
sumWeights,
|
||||||
|
plusEqOp<scalar>()
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Push master data to slaves. It is possible (not sure how often) for
|
||||||
|
// a coupled point to have its master on a different patch so
|
||||||
|
// to make sure just push master data to slaves. Reuse the syncPointData
|
||||||
|
// structure.
|
||||||
|
pushUntransformedData(sumWeights);
|
||||||
|
|
||||||
|
// Normalise boundary weights
|
||||||
|
forAll(mp, i)
|
||||||
|
{
|
||||||
|
const label pointi = mp[i];
|
||||||
|
|
||||||
|
scalarList& pw = boundaryPointWeights_[i];
|
||||||
|
// Note:pw only sized for isPatchPoint
|
||||||
|
forAll(pw, i)
|
||||||
|
{
|
||||||
|
pw[i] /= sumWeights[pointi];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
Pout<< "volPointInterpolationAdjoint::makeWeights() : "
|
||||||
|
<< "finished constructing weighting factors"
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::volPointInterpolationAdjoint::volPointInterpolationAdjoint(const fvMesh& vm)
|
||||||
|
:
|
||||||
|
MeshObject<fvMesh, Foam::UpdateableMeshObject, volPointInterpolationAdjoint>
|
||||||
|
(
|
||||||
|
vm
|
||||||
|
)
|
||||||
|
{
|
||||||
|
makeWeights();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::volPointInterpolationAdjoint::~volPointInterpolationAdjoint()
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::volPointInterpolationAdjoint::updateMesh(const mapPolyMesh&)
|
||||||
|
{
|
||||||
|
makeWeights();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::volPointInterpolationAdjoint::movePoints()
|
||||||
|
{
|
||||||
|
makeWeights();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::volPointInterpolationAdjoint::interpolateSensitivitiesField
|
||||||
|
(
|
||||||
|
const vectorField& pf,
|
||||||
|
vectorField& vf,
|
||||||
|
const labelHashSet& patchIDs
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
// Get face data in flat list
|
||||||
|
const fvMesh& Mesh = mesh();
|
||||||
|
|
||||||
|
vectorField boundaryVals(Mesh.nBoundaryFaces(), Zero);
|
||||||
|
|
||||||
|
// Do points on 'normal' patches from the surrounding patch faces
|
||||||
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
const primitivePatch& boundary = boundaryPtr_();
|
||||||
|
const labelList& mp = boundary.meshPoints();
|
||||||
|
|
||||||
|
forAll(mp, i)
|
||||||
|
{
|
||||||
|
label pointi = mp[i];
|
||||||
|
|
||||||
|
if (isPatchPoint_[pointi])
|
||||||
|
{
|
||||||
|
const labelList& pFaces = boundary.pointFaces()[i];
|
||||||
|
const scalarList& pWeights = boundaryPointWeights_[i];
|
||||||
|
const vector& val = pf[pointi];
|
||||||
|
// In symmetry planes, face-to-point weights should, in general,
|
||||||
|
// have half the weight of what they actually do in
|
||||||
|
// volPointInterpolation since, in a complete case, a face laying
|
||||||
|
// on the opposite side of the symmetry plane would also contribute
|
||||||
|
// to a point laying on the symmetry plane.
|
||||||
|
// For face-to-point interpolation this is not a problem, but for
|
||||||
|
// the adjoint point-to-face interpolation, the correct value of
|
||||||
|
// the weight should be taken into consideration
|
||||||
|
scalar mod(isSymmetryPoint_[pointi] ? 0.5 : 1);
|
||||||
|
|
||||||
|
forAll(pFaces, j)
|
||||||
|
{
|
||||||
|
if (boundaryIsPatchFace_[pFaces[j]])
|
||||||
|
{
|
||||||
|
boundaryVals[pFaces[j]] += mod*pWeights[j]*val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transfer values to face-based sensitivity field
|
||||||
|
label nPassedFaces(0);
|
||||||
|
for (const label patchi : patchIDs)
|
||||||
|
{
|
||||||
|
const fvPatch& patch = Mesh.boundary()[patchi];
|
||||||
|
label bFacei = patch.start() - Mesh.nInternalFaces();
|
||||||
|
SubList<vector> patchFaceSens(vf, patch.size(), nPassedFaces);
|
||||||
|
patchFaceSens = SubList<vector>(boundaryVals, patch.size(), bFacei);
|
||||||
|
nPassedFaces += patch.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,193 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||||
|
Copyright (C) 2016-2020 OpenCFD Ltd.
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::volPointInterpolationAdjoint
|
||||||
|
|
||||||
|
Description
|
||||||
|
Interpolate from cell centres to points (vertices) using inverse distance
|
||||||
|
weighting
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
volPointInterpolationAdjoint.C
|
||||||
|
volPointInterpolate.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef volPointInterpolationAdjoint_H
|
||||||
|
#define volPointInterpolationAdjoint_H
|
||||||
|
|
||||||
|
#include "MeshObject.H"
|
||||||
|
#include "scalarList.H"
|
||||||
|
#include "volFields.H"
|
||||||
|
#include "pointFields.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
class fvMesh;
|
||||||
|
class pointMesh;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class volPointInterpolationAdjoint Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class volPointInterpolationAdjoint
|
||||||
|
:
|
||||||
|
public MeshObject<fvMesh, UpdateableMeshObject, volPointInterpolationAdjoint>
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// Protected data
|
||||||
|
|
||||||
|
//- Boundary addressing
|
||||||
|
autoPtr<primitivePatch> boundaryPtr_;
|
||||||
|
|
||||||
|
//- Per boundary face whether is on non-coupled, non-empty patch
|
||||||
|
bitSet boundaryIsPatchFace_;
|
||||||
|
|
||||||
|
//- Per mesh(!) point whether is on non-coupled, non-empty patch (on
|
||||||
|
// any processor)
|
||||||
|
bitSet isPatchPoint_;
|
||||||
|
|
||||||
|
//- Per mesh(!) point whether is on symmetry plane
|
||||||
|
// any processor)
|
||||||
|
bitSet isSymmetryPoint_;
|
||||||
|
|
||||||
|
//- Per boundary point the weights per pointFaces.
|
||||||
|
scalarListList boundaryPointWeights_;
|
||||||
|
|
||||||
|
|
||||||
|
// Protected Member Functions
|
||||||
|
|
||||||
|
//- Construct addressing over all boundary faces
|
||||||
|
void calcBoundaryAddressing();
|
||||||
|
|
||||||
|
//- Make weights for points on uncoupled patches
|
||||||
|
void makeBoundaryWeights(scalarField& sumWeights);
|
||||||
|
|
||||||
|
//- Construct all point weighting factors
|
||||||
|
void makeWeights();
|
||||||
|
|
||||||
|
//- Helper: push master point data to collocated points
|
||||||
|
template<class Type>
|
||||||
|
void pushUntransformedData(List<Type>&) const;
|
||||||
|
|
||||||
|
//- Get boundary field in same order as boundary faces. Field is
|
||||||
|
// zero on all coupled and empty patches
|
||||||
|
template<class Type>
|
||||||
|
tmp<Field<Type>> flatBoundaryField
|
||||||
|
(
|
||||||
|
const GeometricField<Type, fvPatchField, volMesh>& vf
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Add separated contributions
|
||||||
|
template<class Type>
|
||||||
|
void addSeparated
|
||||||
|
(
|
||||||
|
GeometricField<Type, pointPatchField, pointMesh>&
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- No copy construct
|
||||||
|
volPointInterpolationAdjoint(const volPointInterpolationAdjoint&) = delete;
|
||||||
|
|
||||||
|
//- No copy assignment
|
||||||
|
void operator=(const volPointInterpolationAdjoint&) = delete;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Declare name of the class and its debug switch
|
||||||
|
ClassName("volPointInterpolationAdjoint");
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Constructor given fvMesh and pointMesh.
|
||||||
|
explicit volPointInterpolationAdjoint(const fvMesh&);
|
||||||
|
|
||||||
|
|
||||||
|
//- Destructor
|
||||||
|
~volPointInterpolationAdjoint();
|
||||||
|
|
||||||
|
|
||||||
|
// Member functions
|
||||||
|
|
||||||
|
// Edit
|
||||||
|
|
||||||
|
//- Update mesh topology using the morph engine
|
||||||
|
void updateMesh(const mapPolyMesh&);
|
||||||
|
|
||||||
|
//- Correct weighting factors for moving mesh.
|
||||||
|
bool movePoints();
|
||||||
|
|
||||||
|
|
||||||
|
// Interpolation Functions
|
||||||
|
|
||||||
|
//- Interpolate sensitivties from points to faces
|
||||||
|
// conditions
|
||||||
|
template<class Type>
|
||||||
|
void interpolateSensitivitiesField
|
||||||
|
(
|
||||||
|
const GeometricField<Type, pointPatchField, pointMesh>& pf,
|
||||||
|
typename GeometricField<Type, fvPatchField, volMesh>::Boundary& vf,
|
||||||
|
const labelHashSet& patchIDs
|
||||||
|
) const;
|
||||||
|
|
||||||
|
template<class Type>
|
||||||
|
void interpolateBoundaryField
|
||||||
|
(
|
||||||
|
const GeometricField<Type, fvPatchField, volMesh>& vf,
|
||||||
|
GeometricField<Type, pointPatchField, pointMesh>& pf
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Interpolate sensitivties from points to faces
|
||||||
|
void interpolateSensitivitiesField
|
||||||
|
(
|
||||||
|
const vectorField& pf,
|
||||||
|
vectorField& vf,
|
||||||
|
const labelHashSet& patchIDs
|
||||||
|
) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#ifdef NoRepository
|
||||||
|
#include "volPointInterpolateAdjoint.C"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2021 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2021 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019-2021 OpenCFD Ltd.
|
Copyright (C) 2019-2021 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -38,7 +38,6 @@ namespace Foam
|
|||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
defineTypeNameAndDebug(objectiveManager, 0);
|
defineTypeNameAndDebug(objectiveManager, 0);
|
||||||
defineRunTimeSelectionTable(objectiveManager, dictionary);
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -67,7 +66,7 @@ objectiveManager::objectiveManager
|
|||||||
adjointSolverName_(adjointSolverName),
|
adjointSolverName_(adjointSolverName),
|
||||||
primalSolverName_(primalSolverName),
|
primalSolverName_(primalSolverName),
|
||||||
objectives_(0),
|
objectives_(0),
|
||||||
weigthedObjectiveFile_(nullptr)
|
weightedObjectiveFile_(nullptr)
|
||||||
{
|
{
|
||||||
// Construct objectives
|
// Construct objectives
|
||||||
//~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~
|
||||||
@ -107,7 +106,7 @@ objectiveManager::objectiveManager
|
|||||||
if (objectives_.size() > 1)
|
if (objectives_.size() > 1)
|
||||||
{
|
{
|
||||||
const Time& time = mesh_.time();
|
const Time& time = mesh_.time();
|
||||||
weigthedObjectiveFile_.reset
|
weightedObjectiveFile_.reset
|
||||||
(
|
(
|
||||||
new OFstream
|
new OFstream
|
||||||
(
|
(
|
||||||
@ -117,59 +116,26 @@ objectiveManager::objectiveManager
|
|||||||
);
|
);
|
||||||
|
|
||||||
unsigned int width = IOstream::defaultPrecision() + 5;
|
unsigned int width = IOstream::defaultPrecision() + 5;
|
||||||
weigthedObjectiveFile_()
|
weightedObjectiveFile_()
|
||||||
<< setw(4) << "#" << " "
|
<< setw(4) << "#" << " "
|
||||||
<< setw(width) << "weightedObjective" << " ";
|
<< setw(width) << "weightedObjective" << " ";
|
||||||
for (objective& objI : objectives_)
|
for (objective& objI : objectives_)
|
||||||
{
|
{
|
||||||
weigthedObjectiveFile_()
|
weightedObjectiveFile_()
|
||||||
<< setw(width) << objI.objectiveName() << " ";
|
<< setw(width) << objI.objectiveName() << " ";
|
||||||
}
|
}
|
||||||
weigthedObjectiveFile_()
|
weightedObjectiveFile_()
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
autoPtr<objectiveManager> objectiveManager::New
|
|
||||||
(
|
|
||||||
const fvMesh& mesh,
|
|
||||||
const dictionary& dict,
|
|
||||||
const word& adjointSolverName,
|
|
||||||
const word& primalSolverName
|
|
||||||
)
|
|
||||||
{
|
|
||||||
// Determine type of objectiveManager from objectiveType
|
|
||||||
const word objectiveType(dict.get<word>("type"));
|
|
||||||
const word managerType("objectiveManager" & objectiveType);
|
|
||||||
|
|
||||||
auto* ctorPtr = dictionaryConstructorTable(managerType);
|
|
||||||
|
|
||||||
if (!ctorPtr)
|
|
||||||
{
|
|
||||||
FatalIOErrorInLookup
|
|
||||||
(
|
|
||||||
dict,
|
|
||||||
"objectiveManagerType",
|
|
||||||
managerType,
|
|
||||||
*dictionaryConstructorTablePtr_
|
|
||||||
) << exit(FatalIOError);
|
|
||||||
}
|
|
||||||
|
|
||||||
return autoPtr<objectiveManager>
|
|
||||||
(
|
|
||||||
ctorPtr(mesh, dict, adjointSolverName, primalSolverName)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
bool objectiveManager::readDict(const dictionary& dict)
|
bool objectiveManager::readDict(const dictionary& dict)
|
||||||
{
|
{
|
||||||
|
dict_ = dict;
|
||||||
for (objective& obj : objectives_)
|
for (objective& obj : objectives_)
|
||||||
{
|
{
|
||||||
obj.readDict
|
obj.readDict
|
||||||
@ -233,15 +199,20 @@ void objectiveManager::incrementIntegrationTimes(const scalar timeSpan)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
scalar objectiveManager::print()
|
scalar objectiveManager::print(bool negate)
|
||||||
{
|
{
|
||||||
scalar objValue(Zero);
|
scalar objValue(Zero);
|
||||||
Info<< "Adjoint solver " << adjointSolverName_ << endl;
|
Info<< "Adjoint solver " << adjointSolverName_ << endl;
|
||||||
for (objective& obj : objectives_)
|
for (objective& obj : objectives_)
|
||||||
{
|
{
|
||||||
scalar cost = obj.JCycle();
|
// This function is used to obtain the value used to figure out if
|
||||||
scalar weight = obj.weight();
|
// line search is converged or not. If the objective is not updated
|
||||||
objValue += weight*cost;
|
// in each iteration of the primal solver, the old objective value
|
||||||
|
// might be returned. Force the update of the objective the next
|
||||||
|
// time objective::J() is called.
|
||||||
|
obj.setComputed(false);
|
||||||
|
const scalar cost = obj.JCycle(negate);
|
||||||
|
objValue += cost;
|
||||||
|
|
||||||
Info<< obj.objectiveName() << " : " << cost << endl;
|
Info<< obj.objectiveName() << " : " << cost << endl;
|
||||||
}
|
}
|
||||||
@ -252,35 +223,53 @@ scalar objectiveManager::print()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void objectiveManager::setWrite(const bool shouldWrite)
|
||||||
|
{
|
||||||
|
for (objective& obj : objectives_)
|
||||||
|
{
|
||||||
|
obj.setWrite(shouldWrite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool objectiveManager::writeObjectives()
|
||||||
|
{
|
||||||
|
for (const objective& obj : objectives_)
|
||||||
|
{
|
||||||
|
// Write objective function to file
|
||||||
|
if (obj.shouldWrite())
|
||||||
|
{
|
||||||
|
obj.write();
|
||||||
|
obj.writeMeanValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool objectiveManager::writeObjectives
|
bool objectiveManager::writeObjectives
|
||||||
(
|
(
|
||||||
const scalar weightedObjective,
|
const scalar weightedObjective,
|
||||||
const bool valid
|
const bool valid
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
for (const objective& obj : objectives_)
|
if (weightedObjectiveFile_.valid())
|
||||||
{
|
|
||||||
// Write objective function to file
|
|
||||||
obj.write();
|
|
||||||
obj.writeMeanValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (weigthedObjectiveFile_)
|
|
||||||
{
|
{
|
||||||
unsigned int width = IOstream::defaultPrecision() + 5;
|
unsigned int width = IOstream::defaultPrecision() + 5;
|
||||||
weigthedObjectiveFile_()
|
weightedObjectiveFile_()
|
||||||
<< setw(4) << mesh_.time().timeName() << " "
|
<< setw(4) << mesh_.time().timeName() << " "
|
||||||
<< setw(width) << weightedObjective << " ";
|
<< setw(width) << weightedObjective << " ";
|
||||||
|
|
||||||
for (objective& objI : objectives_)
|
for (objective& objI : objectives_)
|
||||||
{
|
{
|
||||||
weigthedObjectiveFile_()
|
weightedObjectiveFile_()
|
||||||
<< setw(width) << objI.JCycle() << " ";
|
<< setw(width) << objI.JCycle() << " ";
|
||||||
}
|
}
|
||||||
weigthedObjectiveFile_() << endl;
|
weightedObjectiveFile_() << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return writeObjectives();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -332,6 +321,24 @@ void objectiveManager::checkIntegrationTimes() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void objectiveManager::addSource(fvVectorMatrix& matrix)
|
||||||
|
{
|
||||||
|
for (objective& obj : objectives_)
|
||||||
|
{
|
||||||
|
obj.addSource(matrix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void objectiveManager::addSource(fvScalarMatrix& matrix)
|
||||||
|
{
|
||||||
|
for (objective& obj : objectives_)
|
||||||
|
{
|
||||||
|
obj.addSource(matrix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
} // End namespace Foam
|
} // End namespace Foam
|
||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2021 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2021 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
Copyright (C) 2019 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -29,7 +29,7 @@ Class
|
|||||||
Foam::objectiveManager
|
Foam::objectiveManager
|
||||||
|
|
||||||
Description
|
Description
|
||||||
class for managing incompressible objective functions.
|
Class for managing objective functions.
|
||||||
|
|
||||||
SourceFiles
|
SourceFiles
|
||||||
objectiveManager.C
|
objectiveManager.C
|
||||||
@ -61,11 +61,11 @@ protected:
|
|||||||
// Protected data
|
// Protected data
|
||||||
|
|
||||||
const fvMesh& mesh_;
|
const fvMesh& mesh_;
|
||||||
const dictionary& dict_;
|
dictionary dict_;
|
||||||
const word adjointSolverName_;
|
const word adjointSolverName_;
|
||||||
const word primalSolverName_;
|
const word primalSolverName_;
|
||||||
PtrList<objective> objectives_;
|
PtrList<objective> objectives_;
|
||||||
autoPtr<OFstream> weigthedObjectiveFile_;
|
autoPtr<OFstream> weightedObjectiveFile_;
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -83,22 +83,6 @@ public:
|
|||||||
|
|
||||||
TypeName("objectiveManager");
|
TypeName("objectiveManager");
|
||||||
|
|
||||||
// Declare run-time constructor selection table
|
|
||||||
|
|
||||||
declareRunTimeSelectionTable
|
|
||||||
(
|
|
||||||
autoPtr,
|
|
||||||
objectiveManager,
|
|
||||||
dictionary,
|
|
||||||
(
|
|
||||||
const fvMesh& mesh,
|
|
||||||
const dictionary& dict,
|
|
||||||
const word& adjointSolverName,
|
|
||||||
const word& primalSolverName
|
|
||||||
),
|
|
||||||
(mesh, dict, adjointSolverName, primalSolverName)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
//- Construct from components
|
//- Construct from components
|
||||||
@ -110,17 +94,6 @@ public:
|
|||||||
const word& primalSolverName
|
const word& primalSolverName
|
||||||
);
|
);
|
||||||
|
|
||||||
// Selectors
|
|
||||||
|
|
||||||
//- Return a reference to the selected turbulence model
|
|
||||||
static autoPtr<objectiveManager> New
|
|
||||||
(
|
|
||||||
const fvMesh& mesh,
|
|
||||||
const dictionary& dict,
|
|
||||||
const word& adjointSolverName,
|
|
||||||
const word& primalSolverName
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
//- Destructor
|
//- Destructor
|
||||||
virtual ~objectiveManager() = default;
|
virtual ~objectiveManager() = default;
|
||||||
@ -143,7 +116,12 @@ public:
|
|||||||
void incrementIntegrationTimes(const scalar timeSpan);
|
void incrementIntegrationTimes(const scalar timeSpan);
|
||||||
|
|
||||||
//- Print to screen
|
//- Print to screen
|
||||||
scalar print();
|
scalar print(bool negate = false);
|
||||||
|
|
||||||
|
//- Should the objectives be written to file upon calling write()?
|
||||||
|
void setWrite(const bool shouldWrite);
|
||||||
|
//- Write objective function history
|
||||||
|
virtual bool writeObjectives();
|
||||||
|
|
||||||
//- Write objective function history
|
//- Write objective function history
|
||||||
virtual bool writeObjectives
|
virtual bool writeObjectives
|
||||||
@ -175,16 +153,10 @@ public:
|
|||||||
void checkIntegrationTimes() const;
|
void checkIntegrationTimes() const;
|
||||||
|
|
||||||
//- Add contribution to adjoint momentum PDEs
|
//- Add contribution to adjoint momentum PDEs
|
||||||
virtual void addUaEqnSource(fvVectorMatrix& UaEqn) = 0;
|
virtual void addSource(fvVectorMatrix& matrix);
|
||||||
|
|
||||||
//- Add contribution to adjoint momentum PDEs
|
//- Add contribution to a scalar adjoint PDEs
|
||||||
virtual void addPaEqnSource(fvScalarMatrix& paEqn) = 0;
|
virtual void addSource(fvScalarMatrix& matrix);
|
||||||
|
|
||||||
//- Add contribution to first adjoint turbulence model PDE
|
|
||||||
virtual void addTMEqn1Source(fvScalarMatrix& adjTMEqn1) = 0;
|
|
||||||
|
|
||||||
//- Add contribution to second adjoint turbulence model PDE
|
|
||||||
virtual void addTMEqn2Source(fvScalarMatrix& adjTMEqn2) = 0;
|
|
||||||
|
|
||||||
|
|
||||||
// IO
|
// IO
|
||||||
@ -1,132 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | www.openfoam.com
|
|
||||||
\\/ M anipulation |
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
|
||||||
Copyright (C) 2013-2019 FOSS GP
|
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
License
|
|
||||||
This file is part of OpenFOAM.
|
|
||||||
|
|
||||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "objectiveManagerIncompressible.H"
|
|
||||||
#include "addToRunTimeSelectionTable.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
defineTypeNameAndDebug(objectiveManagerIncompressible, 0);
|
|
||||||
addToRunTimeSelectionTable
|
|
||||||
(
|
|
||||||
objectiveManager,
|
|
||||||
objectiveManagerIncompressible,
|
|
||||||
dictionary
|
|
||||||
);
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
objectiveManagerIncompressible::objectiveManagerIncompressible
|
|
||||||
(
|
|
||||||
const fvMesh& mesh,
|
|
||||||
const dictionary& dict,
|
|
||||||
const word& adjointSolverName,
|
|
||||||
const word& primalSolverName
|
|
||||||
)
|
|
||||||
:
|
|
||||||
objectiveManager(mesh, dict, adjointSolverName, primalSolverName)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
void objectiveManagerIncompressible::addUaEqnSource(fvVectorMatrix& UaEqn)
|
|
||||||
{
|
|
||||||
// Add contributions from objective functions
|
|
||||||
for (objective& obj : objectives_)
|
|
||||||
{
|
|
||||||
auto& icoObj = refCast<objectiveIncompressible>(obj);
|
|
||||||
|
|
||||||
if (icoObj.hasdJdv())
|
|
||||||
{
|
|
||||||
scalar weight = icoObj.weight();
|
|
||||||
UaEqn += weight*icoObj.dJdv();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void objectiveManagerIncompressible::addPaEqnSource(fvScalarMatrix& paEqn)
|
|
||||||
{
|
|
||||||
// Add contributions from objective functions
|
|
||||||
for (objective& obj : objectives_)
|
|
||||||
{
|
|
||||||
auto& icoObj = refCast<objectiveIncompressible>(obj);
|
|
||||||
|
|
||||||
if (icoObj.hasdJdp())
|
|
||||||
{
|
|
||||||
scalar weight = icoObj.weight();
|
|
||||||
paEqn += weight*icoObj.dJdp();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void objectiveManagerIncompressible::addTMEqn1Source(fvScalarMatrix& adjTMEqn1)
|
|
||||||
{
|
|
||||||
// Add contributions from objective functions
|
|
||||||
for (objective& obj : objectives_)
|
|
||||||
{
|
|
||||||
auto& icoObj = refCast<objectiveIncompressible>(obj);
|
|
||||||
|
|
||||||
if (icoObj.hasdJdTMVar1())
|
|
||||||
{
|
|
||||||
scalar weight = icoObj.weight();
|
|
||||||
adjTMEqn1 += weight*icoObj.dJdTMvar1();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void objectiveManagerIncompressible::addTMEqn2Source(fvScalarMatrix& adjTMEqn2)
|
|
||||||
{
|
|
||||||
// Add contributions from objective functions
|
|
||||||
for (objective& obj : objectives_)
|
|
||||||
{
|
|
||||||
auto& icoObj = refCast<objectiveIncompressible>(obj);
|
|
||||||
|
|
||||||
if (icoObj.hasdJdTMVar2())
|
|
||||||
{
|
|
||||||
scalar weight = icoObj.weight();
|
|
||||||
adjTMEqn2 += weight*icoObj.dJdTMvar2();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
} // End namespace Foam
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -0,0 +1,119 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2023 PCOpt/NTUA
|
||||||
|
Copyright (C) 2023 FOSS GP
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "objectiveGeometric.H"
|
||||||
|
#include "createZeroField.H"
|
||||||
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
defineTypeNameAndDebug(objectiveGeometric, 0);
|
||||||
|
defineRunTimeSelectionTable(objectiveGeometric, dictionary);
|
||||||
|
addToRunTimeSelectionTable
|
||||||
|
(
|
||||||
|
objective,
|
||||||
|
objectiveGeometric,
|
||||||
|
objective
|
||||||
|
);
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
objectiveGeometric::objectiveGeometric
|
||||||
|
(
|
||||||
|
const fvMesh& mesh,
|
||||||
|
const dictionary& dict,
|
||||||
|
const word& adjointSolverName,
|
||||||
|
const word& primalSolverName
|
||||||
|
)
|
||||||
|
:
|
||||||
|
objective(mesh, dict, adjointSolverName, primalSolverName)
|
||||||
|
{
|
||||||
|
weight_ = dict.get<scalar>("weight");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
autoPtr<objectiveGeometric> objectiveGeometric::New
|
||||||
|
(
|
||||||
|
const fvMesh& mesh,
|
||||||
|
const dictionary& dict,
|
||||||
|
const word& adjointSolverName,
|
||||||
|
const word& primalSolverName
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const word modelType(dict.get<word>("type"));
|
||||||
|
|
||||||
|
Info<< "Creating objective function : " << dict.dictName()
|
||||||
|
<< " of type " << modelType << endl;
|
||||||
|
|
||||||
|
auto* ctorPtr = dictionaryConstructorTable(modelType);
|
||||||
|
|
||||||
|
if (!ctorPtr)
|
||||||
|
{
|
||||||
|
FatalIOErrorInLookup
|
||||||
|
(
|
||||||
|
dict,
|
||||||
|
"objectiveGeometric",
|
||||||
|
modelType,
|
||||||
|
*dictionaryConstructorTablePtr_
|
||||||
|
) << exit(FatalIOError);
|
||||||
|
}
|
||||||
|
|
||||||
|
return autoPtr<objectiveGeometric>
|
||||||
|
(
|
||||||
|
ctorPtr(mesh, dict, adjointSolverName, primalSolverName)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void objectiveGeometric::update()
|
||||||
|
{
|
||||||
|
// Update geometric fields
|
||||||
|
objective::update();
|
||||||
|
|
||||||
|
// Divide everything with normalization factor
|
||||||
|
doNormalization();
|
||||||
|
|
||||||
|
// Set objective as not computed, for the next optimisation cycle
|
||||||
|
computed_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -5,9 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
Copyright (C) 2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2019 FOSS GP
|
Copyright (C) 2023 FOSS GP
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -27,22 +26,21 @@ License
|
|||||||
|
|
||||||
|
|
||||||
Class
|
Class
|
||||||
Foam::objectiveManagerIncompressible
|
Foam::objectiveGeometric
|
||||||
|
|
||||||
Description
|
Description
|
||||||
class for managing incompressible objective functions.
|
Abstract base class for objective functions that contain only geometric
|
||||||
|
quantities
|
||||||
|
|
||||||
SourceFiles
|
SourceFiles
|
||||||
objectiveManagerIncompressible.C
|
objectiveGeometric.C
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#ifndef objectiveManagerIncompressible_H
|
#ifndef objectiveGeometric_H
|
||||||
#define objectiveManagerIncompressible_H
|
#define objectiveGeometric_H
|
||||||
|
|
||||||
#include "objectiveManager.H"
|
#include "objective.H"
|
||||||
#include "objectiveIncompressible.H"
|
|
||||||
#include "runTimeSelectionTables.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -50,35 +48,64 @@ namespace Foam
|
|||||||
{
|
{
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
Class objectiveManagerIncompressible Declaration
|
Class objectiveGeometric Declaration
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
class objectiveManagerIncompressible
|
class objectiveGeometric
|
||||||
:
|
:
|
||||||
public objectiveManager
|
public objective
|
||||||
{
|
{
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
//- No copy construct
|
//- No copy construct
|
||||||
objectiveManagerIncompressible
|
objectiveGeometric(const objectiveGeometric&) = delete;
|
||||||
(
|
|
||||||
const objectiveManagerIncompressible&
|
|
||||||
) = delete;
|
|
||||||
|
|
||||||
//- No copy assignment
|
//- No copy assignment
|
||||||
void operator=(const objectiveManagerIncompressible&) = delete;
|
void operator=(const objectiveGeometric&) = delete;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
TypeName("objectiveManagerIncompressible");
|
//- Runtime type information
|
||||||
|
TypeName("geometric");
|
||||||
|
|
||||||
|
|
||||||
|
// Declare run-time constructor selection table
|
||||||
|
|
||||||
|
declareRunTimeSelectionTable
|
||||||
|
(
|
||||||
|
autoPtr,
|
||||||
|
objectiveGeometric,
|
||||||
|
dictionary,
|
||||||
|
(
|
||||||
|
const fvMesh& mesh,
|
||||||
|
const dictionary& dict,
|
||||||
|
const word& adjointSolverName,
|
||||||
|
const word& primalSolverName
|
||||||
|
),
|
||||||
|
(mesh, dict, adjointSolverName, primalSolverName)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
//- Construct from components
|
//- Construct from components
|
||||||
objectiveManagerIncompressible
|
objectiveGeometric
|
||||||
|
(
|
||||||
|
const fvMesh& mesh,
|
||||||
|
const dictionary& dict,
|
||||||
|
const word& adjointSolverName,
|
||||||
|
const word& primalSolverName
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Selectors
|
||||||
|
|
||||||
|
//- Return a reference to the selected turbulence model
|
||||||
|
static autoPtr<objectiveGeometric> New
|
||||||
(
|
(
|
||||||
const fvMesh& mesh,
|
const fvMesh& mesh,
|
||||||
const dictionary& dict,
|
const dictionary& dict,
|
||||||
@ -88,22 +115,16 @@ public:
|
|||||||
|
|
||||||
|
|
||||||
//- Destructor
|
//- Destructor
|
||||||
virtual ~objectiveManagerIncompressible() = default;
|
virtual ~objectiveGeometric() = default;
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
//- Add contribution to adjoint momentum PDEs
|
//- Return the objective function value
|
||||||
virtual void addUaEqnSource(fvVectorMatrix& UaEqn);
|
virtual scalar J() = 0;
|
||||||
|
|
||||||
//- Add contribution to adjoint momentum PDEs
|
//- Update objective function derivatives
|
||||||
virtual void addPaEqnSource(fvScalarMatrix& paEqn);
|
virtual void update();
|
||||||
|
|
||||||
//- Add contribution to adjoint turbulence model PDE
|
|
||||||
virtual void addTMEqn1Source(fvScalarMatrix& adjTMEqn1);
|
|
||||||
|
|
||||||
//- Add contribution to adjoint turbulence model PDE
|
|
||||||
virtual void addTMEqn2Source(fvScalarMatrix& adjTMEqn2);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2020 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2020 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019-2020 OpenCFD Ltd.
|
Copyright (C) 2019-2020 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -45,7 +45,7 @@ namespace objectives
|
|||||||
defineTypeNameAndDebug(objectivePartialVolume, 1);
|
defineTypeNameAndDebug(objectivePartialVolume, 1);
|
||||||
addToRunTimeSelectionTable
|
addToRunTimeSelectionTable
|
||||||
(
|
(
|
||||||
objectiveIncompressible,
|
objectiveGeometric,
|
||||||
objectivePartialVolume,
|
objectivePartialVolume,
|
||||||
dictionary
|
dictionary
|
||||||
);
|
);
|
||||||
@ -61,7 +61,7 @@ objectivePartialVolume::objectivePartialVolume
|
|||||||
const word& primalSolverName
|
const word& primalSolverName
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
objectiveIncompressible(mesh, dict, adjointSolverName, primalSolverName),
|
objectiveGeometric(mesh, dict, adjointSolverName, primalSolverName),
|
||||||
initVol_(Zero),
|
initVol_(Zero),
|
||||||
objectivePatches_
|
objectivePatches_
|
||||||
(
|
(
|
||||||
@ -72,7 +72,11 @@ objectivePartialVolume::objectivePartialVolume
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Read target volume if present. Else use the current one as a target
|
// Read target volume if present. Else use the current one as a target
|
||||||
if (!dict.readIfPresent("initialVolume", initVol_))
|
if
|
||||||
|
(
|
||||||
|
!objective::readIfPresent("initialVolume", initVol_)
|
||||||
|
&& !dict.readIfPresent("initialVolume", initVol_)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
const scalar oneThird(1.0/3.0);
|
const scalar oneThird(1.0/3.0);
|
||||||
for (const label patchi : objectivePatches_)
|
for (const label patchi : objectivePatches_)
|
||||||
@ -129,10 +133,18 @@ void objectivePartialVolume::update_dSdbMultiplier()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool objectivePartialVolume::writeData(Ostream& os) const
|
||||||
|
{
|
||||||
|
os.writeEntry("initialVolume", initVol_);
|
||||||
|
return objective::writeData(os);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void objectivePartialVolume::addHeaderInfo() const
|
void objectivePartialVolume::addHeaderInfo() const
|
||||||
{
|
{
|
||||||
objFunctionFilePtr_()
|
objFunctionFilePtr_()
|
||||||
<< setw(width_) << "#VInit" << " "
|
<< setw(4) << "#" << " "
|
||||||
|
<< setw(width_) << "VInit" << " "
|
||||||
<< setw(width_) << initVol_ << endl;
|
<< setw(width_) << initVol_ << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2020 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2020 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019-2020 OpenCFD Ltd.
|
Copyright (C) 2019-2020 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -39,7 +39,7 @@ SourceFiles
|
|||||||
#ifndef objectivePartialVolume_H
|
#ifndef objectivePartialVolume_H
|
||||||
#define objectivePartialVolume_H
|
#define objectivePartialVolume_H
|
||||||
|
|
||||||
#include "objectiveIncompressible.H"
|
#include "objectiveGeometric.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -55,7 +55,7 @@ namespace objectives
|
|||||||
|
|
||||||
class objectivePartialVolume
|
class objectivePartialVolume
|
||||||
:
|
:
|
||||||
public objectiveIncompressible
|
public objectiveGeometric
|
||||||
{
|
{
|
||||||
// Private data
|
// Private data
|
||||||
|
|
||||||
@ -98,6 +98,9 @@ public:
|
|||||||
//- sensitivity term
|
//- sensitivity term
|
||||||
void update_dSdbMultiplier();
|
void update_dSdbMultiplier();
|
||||||
|
|
||||||
|
//- Write initial volume for continuation
|
||||||
|
virtual bool writeData(Ostream& os) const;
|
||||||
|
|
||||||
// Helper write functions
|
// Helper write functions
|
||||||
|
|
||||||
//- Write headers for additional columns
|
//- Write headers for additional columns
|
||||||
@ -107,7 +110,7 @@ public:
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
} // End namespace objectivePartialVolume
|
} // End namespace objectives
|
||||||
} // End namespace Foam
|
} // End namespace Foam
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2019, 2022 PCOpt/NTUA
|
Copyright (C) 2007-2023, 2022 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2019, 2022 FOSS GP
|
Copyright (C) 2013-2023, 2022 FOSS GP
|
||||||
Copyright (C) 2019-2023 OpenCFD Ltd.
|
Copyright (C) 2019-2023 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -216,7 +216,7 @@ void objectiveForce::update_dxdbMultiplier()
|
|||||||
tgradp.clear();
|
tgradp.clear();
|
||||||
|
|
||||||
// Term coming from stresses
|
// Term coming from stresses
|
||||||
tmp<volScalarField> tnuEff = lamTransp.nu() + turbVars->nutRef();
|
tmp<volScalarField> tnuEff = lamTransp.nu() + turbVars->nut();
|
||||||
tmp<volSymmTensorField> tstress = tnuEff*twoSymm(tgradU);
|
tmp<volSymmTensorField> tstress = tnuEff*twoSymm(tgradU);
|
||||||
const volSymmTensorField& stress = tstress.cref();
|
const volSymmTensorField& stress = tstress.cref();
|
||||||
autoPtr<volVectorField> ptemp
|
autoPtr<volVectorField> ptemp
|
||||||
@ -260,14 +260,14 @@ void objectiveForce::update_boundarydJdGradU()
|
|||||||
const autoPtr<incompressible::RASModelVariables>& turbVars =
|
const autoPtr<incompressible::RASModelVariables>& turbVars =
|
||||||
vars_.RASModelVariables();
|
vars_.RASModelVariables();
|
||||||
const singlePhaseTransportModel& lamTransp = vars_.laminarTransport();
|
const singlePhaseTransportModel& lamTransp = vars_.laminarTransport();
|
||||||
volScalarField nuEff(lamTransp.nu() + turbVars->nutRef());
|
volScalarField nuEff(lamTransp.nu() + turbVars->nut());
|
||||||
for (const label patchI : forcePatches_)
|
for (const label patchI : forcePatches_)
|
||||||
{
|
{
|
||||||
const fvPatch& patch = mesh_.boundary()[patchI];
|
const fvPatch& patch = mesh_.boundary()[patchI];
|
||||||
const vectorField& Sf = patch.Sf();
|
const vectorField& Sf = patch.Sf();
|
||||||
bdJdGradUPtr_()[patchI] =
|
bdJdGradUPtr_()[patchI] =
|
||||||
- nuEff.boundaryField()[patchI]
|
- nuEff.boundaryField()[patchI]
|
||||||
*dev(forceDirection_*Sf + Sf*forceDirection_);
|
*dev(forceDirection_*Sf + Sf*forceDirection_)/denom();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2019 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019-2021 OpenCFD Ltd.
|
Copyright (C) 2019-2021 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -89,7 +89,6 @@ objectiveIncompressible::objectiveIncompressible
|
|||||||
bdJdnutPtr_(nullptr),
|
bdJdnutPtr_(nullptr),
|
||||||
bdJdGradUPtr_(nullptr)
|
bdJdGradUPtr_(nullptr)
|
||||||
{
|
{
|
||||||
weight_ = dict.get<scalar>("weight");
|
|
||||||
computeMeanFields_ = vars_.computeMeanFields();
|
computeMeanFields_ = vars_.computeMeanFields();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,312 +199,10 @@ void objectiveIncompressible::doNormalization()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const volVectorField& objectiveIncompressible::dJdv()
|
|
||||||
{
|
|
||||||
if (!dJdvPtr_)
|
|
||||||
{
|
|
||||||
// If pointer is not set, set it to a zero field
|
|
||||||
dJdvPtr_.reset
|
|
||||||
(
|
|
||||||
createZeroFieldPtr<vector>
|
|
||||||
(
|
|
||||||
mesh_,
|
|
||||||
("dJdv_"+type()),
|
|
||||||
dimLength/sqr(dimTime)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return *dJdvPtr_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const volScalarField& objectiveIncompressible::dJdp()
|
|
||||||
{
|
|
||||||
if (!dJdpPtr_)
|
|
||||||
{
|
|
||||||
// If pointer is not set, set it to a zero field
|
|
||||||
dJdpPtr_.reset
|
|
||||||
(
|
|
||||||
createZeroFieldPtr<scalar>
|
|
||||||
(
|
|
||||||
mesh_,
|
|
||||||
("dJdp_"+type()),
|
|
||||||
dimensionSet(0, 3, -2, 0, 0, 0, 0)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return *dJdpPtr_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const volScalarField& objectiveIncompressible::dJdT()
|
|
||||||
{
|
|
||||||
if (!dJdTPtr_)
|
|
||||||
{
|
|
||||||
// If pointer is not set, set it to a zero field
|
|
||||||
dJdTPtr_.reset
|
|
||||||
(
|
|
||||||
createZeroFieldPtr<scalar>
|
|
||||||
(
|
|
||||||
mesh_,
|
|
||||||
("dJdT_"+type()),
|
|
||||||
dimensionSet(0, 3, -2, 0, 0, 0, 0)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return *dJdTPtr_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const volScalarField& objectiveIncompressible::dJdTMvar1()
|
|
||||||
{
|
|
||||||
if (!dJdTMvar1Ptr_)
|
|
||||||
{
|
|
||||||
// If pointer is not set, set it to a zero field
|
|
||||||
dJdTMvar1Ptr_.reset
|
|
||||||
(
|
|
||||||
createZeroFieldPtr<scalar>
|
|
||||||
(
|
|
||||||
mesh_,
|
|
||||||
("dJdTMvar1_"+type()),
|
|
||||||
dimensionSet(0, 0, -2, 0, 0, 0, 0)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return *dJdTMvar1Ptr_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const volScalarField& objectiveIncompressible::dJdTMvar2()
|
|
||||||
{
|
|
||||||
if (!dJdTMvar2Ptr_)
|
|
||||||
{
|
|
||||||
// If pointer is not set, set it to a zero field
|
|
||||||
dJdTMvar2Ptr_.reset
|
|
||||||
(
|
|
||||||
createZeroFieldPtr<scalar>
|
|
||||||
(
|
|
||||||
mesh_,
|
|
||||||
("dJdTMvar2_"+type()),
|
|
||||||
dimensionSet(0, 3, -2, 0, 0, 0, 0)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return *dJdTMvar2Ptr_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const fvPatchVectorField& objectiveIncompressible::boundarydJdv
|
|
||||||
(
|
|
||||||
const label patchI
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (!bdJdvPtr_)
|
|
||||||
{
|
|
||||||
bdJdvPtr_.reset(createZeroBoundaryPtr<vector>(mesh_));
|
|
||||||
}
|
|
||||||
return bdJdvPtr_()[patchI];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const fvPatchScalarField& objectiveIncompressible::boundarydJdvn
|
|
||||||
(
|
|
||||||
const label patchI
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (!bdJdvnPtr_)
|
|
||||||
{
|
|
||||||
bdJdvnPtr_.reset(createZeroBoundaryPtr<scalar>(mesh_));
|
|
||||||
}
|
|
||||||
return bdJdvnPtr_()[patchI];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const fvPatchVectorField& objectiveIncompressible::boundarydJdvt
|
|
||||||
(
|
|
||||||
const label patchI
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (!bdJdvtPtr_)
|
|
||||||
{
|
|
||||||
bdJdvtPtr_.reset(createZeroBoundaryPtr<vector>(mesh_));
|
|
||||||
}
|
|
||||||
return bdJdvtPtr_()[patchI];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const fvPatchVectorField& objectiveIncompressible::boundarydJdp
|
|
||||||
(
|
|
||||||
const label patchI
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (!bdJdpPtr_)
|
|
||||||
{
|
|
||||||
bdJdpPtr_.reset(createZeroBoundaryPtr<vector>(mesh_));
|
|
||||||
}
|
|
||||||
return bdJdpPtr_()[patchI];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const fvPatchScalarField& objectiveIncompressible::boundarydJdT
|
|
||||||
(
|
|
||||||
const label patchI
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (!bdJdTPtr_)
|
|
||||||
{
|
|
||||||
bdJdTPtr_.reset(createZeroBoundaryPtr<scalar>(mesh_));
|
|
||||||
}
|
|
||||||
return bdJdTPtr_()[patchI];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const fvPatchScalarField& objectiveIncompressible::boundarydJdTMvar1
|
|
||||||
(
|
|
||||||
const label patchI
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (!bdJdTMvar1Ptr_)
|
|
||||||
{
|
|
||||||
bdJdTMvar1Ptr_.reset(createZeroBoundaryPtr<scalar>(mesh_));
|
|
||||||
}
|
|
||||||
return bdJdTMvar1Ptr_()[patchI];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const fvPatchScalarField& objectiveIncompressible::boundarydJdTMvar2
|
|
||||||
(
|
|
||||||
const label patchI
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (!bdJdTMvar2Ptr_)
|
|
||||||
{
|
|
||||||
bdJdTMvar2Ptr_.reset(createZeroBoundaryPtr<scalar>(mesh_));
|
|
||||||
}
|
|
||||||
return bdJdTMvar2Ptr_()[patchI];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const fvPatchScalarField& objectiveIncompressible::boundarydJdnut
|
|
||||||
(
|
|
||||||
const label patchI
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (!bdJdnutPtr_)
|
|
||||||
{
|
|
||||||
bdJdnutPtr_.reset(createZeroBoundaryPtr<scalar>(mesh_));
|
|
||||||
}
|
|
||||||
return bdJdnutPtr_()[patchI];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const fvPatchTensorField& objectiveIncompressible::boundarydJdGradU
|
|
||||||
(
|
|
||||||
const label patchI
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (!bdJdGradUPtr_)
|
|
||||||
{
|
|
||||||
bdJdGradUPtr_.reset(createZeroBoundaryPtr<tensor>(mesh_));
|
|
||||||
}
|
|
||||||
return bdJdGradUPtr_()[patchI];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const boundaryVectorField& objectiveIncompressible::boundarydJdv()
|
|
||||||
{
|
|
||||||
if (!bdJdvPtr_)
|
|
||||||
{
|
|
||||||
bdJdvPtr_.reset(createZeroBoundaryPtr<vector>(mesh_));
|
|
||||||
}
|
|
||||||
return bdJdvPtr_();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const boundaryScalarField& objectiveIncompressible::boundarydJdvn()
|
|
||||||
{
|
|
||||||
if (!bdJdvnPtr_)
|
|
||||||
{
|
|
||||||
bdJdvnPtr_.reset(createZeroBoundaryPtr<scalar>(mesh_));
|
|
||||||
}
|
|
||||||
return bdJdvnPtr_();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const boundaryVectorField& objectiveIncompressible::boundarydJdvt()
|
|
||||||
{
|
|
||||||
if (!bdJdvtPtr_)
|
|
||||||
{
|
|
||||||
bdJdvtPtr_.reset(createZeroBoundaryPtr<vector>(mesh_));
|
|
||||||
}
|
|
||||||
return bdJdvtPtr_();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const boundaryVectorField& objectiveIncompressible::boundarydJdp()
|
|
||||||
{
|
|
||||||
if (!bdJdpPtr_)
|
|
||||||
{
|
|
||||||
bdJdpPtr_.reset(createZeroBoundaryPtr<vector>(mesh_));
|
|
||||||
}
|
|
||||||
return bdJdpPtr_();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const boundaryScalarField& objectiveIncompressible::boundarydJdT()
|
|
||||||
{
|
|
||||||
if (!bdJdTPtr_)
|
|
||||||
{
|
|
||||||
bdJdTPtr_.reset(createZeroBoundaryPtr<scalar>(mesh_));
|
|
||||||
}
|
|
||||||
return bdJdTPtr_();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const boundaryScalarField& objectiveIncompressible::boundarydJdTMvar1()
|
|
||||||
{
|
|
||||||
if (!bdJdTMvar1Ptr_)
|
|
||||||
{
|
|
||||||
bdJdTMvar1Ptr_.reset(createZeroBoundaryPtr<scalar>(mesh_));
|
|
||||||
}
|
|
||||||
return bdJdTMvar1Ptr_();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const boundaryScalarField& objectiveIncompressible::boundarydJdTMvar2()
|
|
||||||
{
|
|
||||||
if (!bdJdTMvar2Ptr_)
|
|
||||||
{
|
|
||||||
bdJdTMvar2Ptr_.reset(createZeroBoundaryPtr<scalar>(mesh_));
|
|
||||||
}
|
|
||||||
return bdJdTMvar2Ptr_();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const boundaryScalarField& objectiveIncompressible::boundarydJdnut()
|
|
||||||
{
|
|
||||||
if (!bdJdnutPtr_)
|
|
||||||
{
|
|
||||||
bdJdnutPtr_.reset(createZeroBoundaryPtr<scalar>(mesh_));
|
|
||||||
}
|
|
||||||
return bdJdnutPtr_();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const boundaryTensorField& objectiveIncompressible::boundarydJdGradU()
|
|
||||||
{
|
|
||||||
if (!bdJdGradUPtr_)
|
|
||||||
{
|
|
||||||
bdJdGradUPtr_.reset(createZeroBoundaryPtr<tensor>(mesh_));
|
|
||||||
}
|
|
||||||
return *bdJdGradUPtr_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void objectiveIncompressible::update()
|
void objectiveIncompressible::update()
|
||||||
{
|
{
|
||||||
// Objective function value
|
// Update geometric fields
|
||||||
J();
|
objective::update();
|
||||||
|
|
||||||
// Update mean values here since they might be used in the
|
// Update mean values here since they might be used in the
|
||||||
// subsequent functions
|
// subsequent functions
|
||||||
@ -517,9 +214,6 @@ void objectiveIncompressible::update()
|
|||||||
update_dJdT();
|
update_dJdT();
|
||||||
update_dJdTMvar1();
|
update_dJdTMvar1();
|
||||||
update_dJdTMvar2();
|
update_dJdTMvar2();
|
||||||
update_dJdb();
|
|
||||||
update_divDxDbMultiplier();
|
|
||||||
update_gradDxDbMultiplier();
|
|
||||||
|
|
||||||
// boundaryFields
|
// boundaryFields
|
||||||
update_boundarydJdv();
|
update_boundarydJdv();
|
||||||
@ -531,15 +225,12 @@ void objectiveIncompressible::update()
|
|||||||
update_boundarydJdTMvar2();
|
update_boundarydJdTMvar2();
|
||||||
update_boundarydJdnut();
|
update_boundarydJdnut();
|
||||||
update_boundarydJdGradU();
|
update_boundarydJdGradU();
|
||||||
update_boundarydJdb();
|
|
||||||
update_dSdbMultiplier();
|
|
||||||
update_dndbMultiplier();
|
|
||||||
update_dxdbMultiplier();
|
|
||||||
update_dxdbDirectMultiplier();
|
|
||||||
update_boundaryEdgeContribution();
|
|
||||||
|
|
||||||
// Divide everything with normalization factor
|
// Divide everything with normalization factor
|
||||||
doNormalization();
|
doNormalization();
|
||||||
|
|
||||||
|
// Set objective as not computed, for the next optimisation cycle
|
||||||
|
computed_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -722,6 +413,15 @@ void objectiveIncompressible::update_dJdTMvar
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void objectiveIncompressible::addSource(fvVectorMatrix& matrix)
|
||||||
|
{
|
||||||
|
if (fieldNames_.found(matrix.psi().name()) && hasdJdv())
|
||||||
|
{
|
||||||
|
matrix += weight()*dJdv();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool objectiveIncompressible::write(const bool valid) const
|
bool objectiveIncompressible::write(const bool valid) const
|
||||||
{
|
{
|
||||||
return objective::write(valid);
|
return objective::write(valid);
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2019 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019-2020 OpenCFD Ltd.
|
Copyright (C) 2019-2020 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -176,76 +176,76 @@ public:
|
|||||||
virtual void doNormalization();
|
virtual void doNormalization();
|
||||||
|
|
||||||
//- Contribution to field adjoint momentum eqs
|
//- Contribution to field adjoint momentum eqs
|
||||||
const volVectorField& dJdv();
|
inline const volVectorField& dJdv();
|
||||||
|
|
||||||
//- Contribution to field adjoint continuity eq
|
//- Contribution to field adjoint continuity eq
|
||||||
const volScalarField& dJdp();
|
inline const volScalarField& dJdp();
|
||||||
|
|
||||||
//- Contribution to field adjoint energy eq
|
//- Contribution to field adjoint energy eq
|
||||||
const volScalarField& dJdT();
|
inline const volScalarField& dJdT();
|
||||||
|
|
||||||
//- Contribution to field adjoint turbulence model variable 1
|
//- Contribution to field adjoint turbulence model variable 1
|
||||||
const volScalarField& dJdTMvar1();
|
inline const volScalarField& dJdTMvar1();
|
||||||
|
|
||||||
//- Contribution to field adjoint turbulence model variable 2
|
//- Contribution to field adjoint turbulence model variable 2
|
||||||
const volScalarField& dJdTMvar2();
|
inline const volScalarField& dJdTMvar2();
|
||||||
|
|
||||||
//- Objective partial deriv wrt velocity for a specific patch
|
//- Objective partial deriv wrt velocity for a specific patch
|
||||||
const fvPatchVectorField& boundarydJdv(const label);
|
const fvPatchVectorField& boundarydJdv(const label);
|
||||||
|
|
||||||
//- Objective partial deriv wrt normal velocity for a specific patch
|
//- Objective partial deriv wrt normal velocity for a specific patch
|
||||||
const fvPatchScalarField& boundarydJdvn(const label);
|
inline const fvPatchScalarField& boundarydJdvn(const label);
|
||||||
|
|
||||||
//- Objective partial deriv wrt tangent velocity for a specific patch
|
//- Objective partial deriv wrt tangent velocity for a specific patch
|
||||||
const fvPatchVectorField& boundarydJdvt(const label);
|
inline const fvPatchVectorField& boundarydJdvt(const label);
|
||||||
|
|
||||||
//- Objective partial deriv wrt pressure (times normal) for a specific
|
//- Objective partial deriv wrt pressure (times normal) for a specific
|
||||||
//- patch
|
//- patch
|
||||||
const fvPatchVectorField& boundarydJdp(const label);
|
inline const fvPatchVectorField& boundarydJdp(const label);
|
||||||
|
|
||||||
//- Objective partial deriv wrt temperature for a specific patch
|
//- Objective partial deriv wrt temperature for a specific patch
|
||||||
const fvPatchScalarField& boundarydJdT(const label);
|
inline const fvPatchScalarField& boundarydJdT(const label);
|
||||||
|
|
||||||
//- Objective partial deriv wrt turbulence model var 1 for a specific
|
//- Objective partial deriv wrt turbulence model var 1 for a specific
|
||||||
//- patch
|
//- patch
|
||||||
const fvPatchScalarField& boundarydJdTMvar1(const label);
|
inline const fvPatchScalarField& boundarydJdTMvar1(const label);
|
||||||
|
|
||||||
//- Objective partial deriv wrt turbulence model var 2 for a specific
|
//- Objective partial deriv wrt turbulence model var 2 for a specific
|
||||||
//- patch
|
//- patch
|
||||||
const fvPatchScalarField& boundarydJdTMvar2(const label);
|
inline const fvPatchScalarField& boundarydJdTMvar2(const label);
|
||||||
|
|
||||||
//- Objective partial deriv wrt nut for a specific patch
|
//- Objective partial deriv wrt nut for a specific patch
|
||||||
const fvPatchScalarField& boundarydJdnut(const label);
|
inline const fvPatchScalarField& boundarydJdnut(const label);
|
||||||
|
|
||||||
//- Objective partial deriv wrt stress tensor
|
//- Objective partial deriv wrt stress tensor
|
||||||
const fvPatchTensorField& boundarydJdGradU(const label);
|
inline const fvPatchTensorField& boundarydJdGradU(const label);
|
||||||
|
|
||||||
//- Objective partial deriv wrt velocity for all patches
|
//- Objective partial deriv wrt velocity for all patches
|
||||||
const boundaryVectorField& boundarydJdv();
|
inline const boundaryVectorField& boundarydJdv();
|
||||||
|
|
||||||
//- Objective partial deriv wrt normal velocity for all patches
|
//- Objective partial deriv wrt normal velocity for all patches
|
||||||
const boundaryScalarField& boundarydJdvn();
|
inline const boundaryScalarField& boundarydJdvn();
|
||||||
|
|
||||||
//- Objective partial deriv wrt tangent velocity for all patches
|
//- Objective partial deriv wrt tangent velocity for all patches
|
||||||
const boundaryVectorField& boundarydJdvt();
|
inline const boundaryVectorField& boundarydJdvt();
|
||||||
|
|
||||||
//- Objective partial deriv wrt pressure (times normal) for all patches
|
//- Objective partial deriv wrt pressure (times normal) for all patches
|
||||||
const boundaryVectorField& boundarydJdp();
|
inline const boundaryVectorField& boundarydJdp();
|
||||||
|
|
||||||
//- Objective partial deriv wrt temperature for all patches
|
//- Objective partial deriv wrt temperature for all patches
|
||||||
const boundaryScalarField& boundarydJdT();
|
inline const boundaryScalarField& boundarydJdT();
|
||||||
|
|
||||||
//- Objective partial deriv wrt turbulence model var 1 for all patches
|
//- Objective partial deriv wrt turbulence model var 1 for all patches
|
||||||
const boundaryScalarField& boundarydJdTMvar1();
|
inline const boundaryScalarField& boundarydJdTMvar1();
|
||||||
|
|
||||||
//- Objective partial deriv wrt turbulence model var 2 for all patches
|
//- Objective partial deriv wrt turbulence model var 2 for all patches
|
||||||
const boundaryScalarField& boundarydJdTMvar2();
|
inline const boundaryScalarField& boundarydJdTMvar2();
|
||||||
|
|
||||||
//- Objective partial deriv wrt nut for all patches
|
//- Objective partial deriv wrt nut for all patches
|
||||||
const boundaryScalarField& boundarydJdnut();
|
inline const boundaryScalarField& boundarydJdnut();
|
||||||
|
|
||||||
//- Objective partial deriv wrt gradU
|
//- Objective partial deriv wrt gradU
|
||||||
const boundaryTensorField& boundarydJdGradU();
|
inline const boundaryTensorField& boundarydJdGradU();
|
||||||
|
|
||||||
//- Update objective function derivatives
|
//- Update objective function derivatives
|
||||||
virtual void update();
|
virtual void update();
|
||||||
@ -295,6 +295,9 @@ public:
|
|||||||
virtual void update_dJdb()
|
virtual void update_dJdb()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
virtual void update_dJdbField()
|
||||||
|
{}
|
||||||
|
|
||||||
virtual void update_divDxDbMultiplier()
|
virtual void update_divDxDbMultiplier()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
@ -328,20 +331,16 @@ public:
|
|||||||
virtual void update_boundarydJdGradU()
|
virtual void update_boundarydJdGradU()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual void update_boundarydJdb()
|
//- Vector sources can be given only to the adjoint momentum equations.
|
||||||
|
//- Implemented in base objectiveIncompressible
|
||||||
|
virtual void addSource(fvVectorMatrix& matrix);
|
||||||
|
|
||||||
|
//- Scalar sources are more ambigious (adjoint pressure, turbulence
|
||||||
|
//- model, energy, etc equations), so the equivalent functions should
|
||||||
|
//- be overridden on an objective-basis
|
||||||
|
virtual void addSource(fvScalarMatrix& matrix)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
virtual void update_dSdbMultiplier()
|
|
||||||
{}
|
|
||||||
|
|
||||||
virtual void update_dndbMultiplier()
|
|
||||||
{}
|
|
||||||
|
|
||||||
virtual void update_dxdbMultiplier()
|
|
||||||
{}
|
|
||||||
|
|
||||||
virtual void update_dxdbDirectMultiplier()
|
|
||||||
{}
|
|
||||||
|
|
||||||
//- Some objectives need to store some auxiliary values.
|
//- Some objectives need to store some auxiliary values.
|
||||||
//- If averaging is enabled, update these mean values here.
|
//- If averaging is enabled, update these mean values here.
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2019 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019-2020 OpenCFD Ltd.
|
Copyright (C) 2019-2020 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -30,6 +30,189 @@ License
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
inline const Foam::volVectorField& Foam::objectiveIncompressible::dJdv()
|
||||||
|
{
|
||||||
|
return *dJdvPtr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::volScalarField& Foam::objectiveIncompressible::dJdp()
|
||||||
|
{
|
||||||
|
return *dJdpPtr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::volScalarField& Foam::objectiveIncompressible::dJdT()
|
||||||
|
{
|
||||||
|
return *dJdTPtr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::volScalarField& Foam::objectiveIncompressible::dJdTMvar1()
|
||||||
|
{
|
||||||
|
return *dJdTMvar1Ptr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::volScalarField& Foam::objectiveIncompressible::dJdTMvar2()
|
||||||
|
{
|
||||||
|
return *dJdTMvar2Ptr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::fvPatchVectorField&
|
||||||
|
Foam::objectiveIncompressible::boundarydJdv
|
||||||
|
(
|
||||||
|
const label patchI
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return bdJdvPtr_()[patchI];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::fvPatchScalarField&
|
||||||
|
Foam::objectiveIncompressible::boundarydJdvn
|
||||||
|
(
|
||||||
|
const label patchI
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return bdJdvnPtr_()[patchI];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::fvPatchVectorField&
|
||||||
|
Foam::objectiveIncompressible::boundarydJdvt
|
||||||
|
(
|
||||||
|
const label patchI
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return bdJdvtPtr_()[patchI];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::fvPatchVectorField&
|
||||||
|
Foam::objectiveIncompressible::boundarydJdp
|
||||||
|
(
|
||||||
|
const label patchI
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return bdJdpPtr_()[patchI];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::fvPatchScalarField&
|
||||||
|
Foam::objectiveIncompressible::boundarydJdT
|
||||||
|
(
|
||||||
|
const label patchI
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return bdJdTPtr_()[patchI];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::fvPatchScalarField&
|
||||||
|
Foam::objectiveIncompressible::boundarydJdTMvar1
|
||||||
|
(
|
||||||
|
const label patchI
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return bdJdTMvar1Ptr_()[patchI];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::fvPatchScalarField&
|
||||||
|
Foam::objectiveIncompressible::boundarydJdTMvar2
|
||||||
|
(
|
||||||
|
const label patchI
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return bdJdTMvar2Ptr_()[patchI];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::fvPatchScalarField&
|
||||||
|
Foam::objectiveIncompressible::boundarydJdnut
|
||||||
|
(
|
||||||
|
const label patchI
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return bdJdnutPtr_()[patchI];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::fvPatchTensorField&
|
||||||
|
Foam::objectiveIncompressible::boundarydJdGradU
|
||||||
|
(
|
||||||
|
const label patchI
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return bdJdGradUPtr_()[patchI];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::boundaryVectorField&
|
||||||
|
Foam::objectiveIncompressible::boundarydJdv()
|
||||||
|
{
|
||||||
|
return bdJdvPtr_();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::boundaryScalarField&
|
||||||
|
Foam::objectiveIncompressible::boundarydJdvn()
|
||||||
|
{
|
||||||
|
return bdJdvnPtr_();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::boundaryVectorField&
|
||||||
|
Foam::objectiveIncompressible::boundarydJdvt()
|
||||||
|
{
|
||||||
|
return bdJdvtPtr_();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::boundaryVectorField&
|
||||||
|
Foam::objectiveIncompressible::boundarydJdp()
|
||||||
|
{
|
||||||
|
return bdJdpPtr_();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::boundaryScalarField&
|
||||||
|
Foam::objectiveIncompressible::boundarydJdT()
|
||||||
|
{
|
||||||
|
return bdJdTPtr_();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::boundaryScalarField&
|
||||||
|
Foam::objectiveIncompressible::boundarydJdTMvar1()
|
||||||
|
{
|
||||||
|
return bdJdTMvar1Ptr_();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::boundaryScalarField&
|
||||||
|
Foam::objectiveIncompressible::boundarydJdTMvar2()
|
||||||
|
{
|
||||||
|
return bdJdTMvar2Ptr_();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::boundaryScalarField&
|
||||||
|
Foam::objectiveIncompressible::boundarydJdnut()
|
||||||
|
{
|
||||||
|
return bdJdnutPtr_();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::boundaryTensorField&
|
||||||
|
Foam::objectiveIncompressible::boundarydJdGradU()
|
||||||
|
{
|
||||||
|
return *bdJdGradUPtr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool Foam::objectiveIncompressible::hasdJdv() const
|
inline bool Foam::objectiveIncompressible::hasdJdv() const
|
||||||
{
|
{
|
||||||
return bool(dJdvPtr_);
|
return bool(dJdvPtr_);
|
||||||
|
|||||||
@ -242,7 +242,7 @@ void objectiveMoment::update_dxdbMultiplier()
|
|||||||
tgradp.clear();
|
tgradp.clear();
|
||||||
|
|
||||||
// Term coming from stresses
|
// Term coming from stresses
|
||||||
tmp<volScalarField> tnuEff = lamTransp.nu() + turbVars->nutRef();
|
tmp<volScalarField> tnuEff = lamTransp.nu() + turbVars->nut();
|
||||||
tmp<volSymmTensorField> tstress = tnuEff*twoSymm(tgradU);
|
tmp<volSymmTensorField> tstress = tnuEff*twoSymm(tgradU);
|
||||||
const volSymmTensorField& stress = tstress.cref();
|
const volSymmTensorField& stress = tstress.cref();
|
||||||
autoPtr<volVectorField> ptemp
|
autoPtr<volVectorField> ptemp
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2020 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2020 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -27,6 +27,7 @@ License
|
|||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "objectiveNutSqr.H"
|
#include "objectiveNutSqr.H"
|
||||||
|
#include "incompressiblePrimalSolver.H"
|
||||||
#include "incompressibleAdjointSolver.H"
|
#include "incompressibleAdjointSolver.H"
|
||||||
#include "createZeroField.H"
|
#include "createZeroField.H"
|
||||||
#include "addToRunTimeSelectionTable.H"
|
#include "addToRunTimeSelectionTable.H"
|
||||||
@ -50,6 +51,27 @@ addToRunTimeSelectionTable
|
|||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
void objectiveNutSqr::populateFieldNames()
|
||||||
|
{
|
||||||
|
if (adjointTurbulenceNames_.empty())
|
||||||
|
{
|
||||||
|
const incompressibleAdjointSolver& adjSolver =
|
||||||
|
mesh_.lookupObject<incompressibleAdjointSolver>(adjointSolverName_);
|
||||||
|
const autoPtr<incompressibleAdjoint::adjointRASModel>& adjointRAS =
|
||||||
|
adjSolver.getAdjointVars().adjointTurbulence();
|
||||||
|
const wordList& baseNames =
|
||||||
|
adjointRAS().getAdjointTMVariablesBaseNames();
|
||||||
|
forAll(baseNames, nI)
|
||||||
|
{
|
||||||
|
fieldNames_.push_back
|
||||||
|
(adjSolver.extendedVariableName(baseNames[nI]));
|
||||||
|
adjointTurbulenceNames_.
|
||||||
|
push_back(adjSolver.extendedVariableName(baseNames[nI]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
objectiveNutSqr::objectiveNutSqr
|
objectiveNutSqr::objectiveNutSqr
|
||||||
@ -61,7 +83,8 @@ objectiveNutSqr::objectiveNutSqr
|
|||||||
)
|
)
|
||||||
:
|
:
|
||||||
objectiveIncompressible(mesh, dict, adjointSolverName, primalSolverName),
|
objectiveIncompressible(mesh, dict, adjointSolverName, primalSolverName),
|
||||||
zones_(mesh_.cellZones().indices(dict.get<wordRes>("zones")))
|
zones_(mesh_.cellZones().indices(dict.get<wordRes>("zones"))),
|
||||||
|
adjointTurbulenceNames_()
|
||||||
{
|
{
|
||||||
// Check if cellZones provided include at least one cell
|
// Check if cellZones provided include at least one cell
|
||||||
checkCellZonesSize(zones_);
|
checkCellZonesSize(zones_);
|
||||||
@ -70,13 +93,19 @@ objectiveNutSqr::objectiveNutSqr
|
|||||||
// Allocate term to be added to volume-based sensitivity derivatives
|
// Allocate term to be added to volume-based sensitivity derivatives
|
||||||
divDxDbMultPtr_.reset
|
divDxDbMultPtr_.reset
|
||||||
(
|
(
|
||||||
createZeroFieldPtr<scalar>
|
new volScalarField
|
||||||
(
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"divDxDbMult" + objectiveName_,
|
||||||
|
mesh_.time().timeName(),
|
||||||
|
mesh_,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
mesh_,
|
mesh_,
|
||||||
("divDxdbMult"+type()) ,
|
dimensionedScalar(sqr(dimLength)/pow3(dimTime), Zero),
|
||||||
// Dimensions are set in a way that the gradient of this term
|
fvPatchFieldBase::zeroGradientType()
|
||||||
// matches the source of the adjoint grid displacement PDE
|
|
||||||
sqr(dimLength)/pow3(dimTime)
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -125,6 +154,9 @@ void objectiveNutSqr::update_dJdv()
|
|||||||
tmp<volVectorField> dnutdU = adjointRAS->nutJacobianU(dnutdUMult);
|
tmp<volVectorField> dnutdU = adjointRAS->nutJacobianU(dnutdUMult);
|
||||||
if (dnutdU)
|
if (dnutdU)
|
||||||
{
|
{
|
||||||
|
// If nut depends on U, allocate dJdv and add Ua to the fieldNames.
|
||||||
|
// It should be safe to do this here since objectives are updated
|
||||||
|
// before the first adjoint solution
|
||||||
if (!dJdvPtr_)
|
if (!dJdvPtr_)
|
||||||
{
|
{
|
||||||
dJdvPtr_.reset
|
dJdvPtr_.reset
|
||||||
@ -137,6 +169,10 @@ void objectiveNutSqr::update_dJdv()
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
if (!fieldNames_.size())
|
||||||
|
{
|
||||||
|
fieldNames_.push_back(adjSolver.extendedVariableName("Ua"));
|
||||||
|
}
|
||||||
for (const label zI : zones_)
|
for (const label zI : zones_)
|
||||||
{
|
{
|
||||||
const cellZone& zoneI = mesh_.cellZones()[zI];
|
const cellZone& zoneI = mesh_.cellZones()[zI];
|
||||||
@ -204,6 +240,22 @@ void objectiveNutSqr::update_divDxDbMultiplier()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void objectiveNutSqr::addSource(fvScalarMatrix& matrix)
|
||||||
|
{
|
||||||
|
populateFieldNames();
|
||||||
|
const label fieldI = fieldNames_.find(matrix.psi().name());
|
||||||
|
|
||||||
|
if (fieldI == 0)
|
||||||
|
{
|
||||||
|
matrix += weight()*dJdTMvar1();
|
||||||
|
}
|
||||||
|
if (fieldI == 1)
|
||||||
|
{
|
||||||
|
matrix += weight()*dJdTMvar2();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
} // End namespace objectives
|
} // End namespace objectives
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2022 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -76,6 +76,20 @@ class objectiveNutSqr
|
|||||||
//- Where to define the objective
|
//- Where to define the objective
|
||||||
labelList zones_;
|
labelList zones_;
|
||||||
|
|
||||||
|
//- List with the names of the adjoint turbulence model fields
|
||||||
|
// This is kept separately from fieldNames since the latter may
|
||||||
|
// or may not include Ua, depending on whether nut is a function
|
||||||
|
// of U. This makes deciding on whether to add or not sources
|
||||||
|
// to a given fvScalarMatrix tricky, hence the utilisation of
|
||||||
|
// adjointTurbulenceNames_
|
||||||
|
wordList adjointTurbulenceNames_;
|
||||||
|
|
||||||
|
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
//- Populate fieldNames
|
||||||
|
void populateFieldNames();
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -116,6 +130,9 @@ public:
|
|||||||
//- Update field to be added to be added to volume-based
|
//- Update field to be added to be added to volume-based
|
||||||
//- sensitivity derivatives, emerging from delta ( dV ) / delta b
|
//- sensitivity derivatives, emerging from delta ( dV ) / delta b
|
||||||
void update_divDxDbMultiplier();
|
void update_divDxDbMultiplier();
|
||||||
|
|
||||||
|
//- Add source terms to the adjoint turbulence model equations
|
||||||
|
virtual void addSource(fvScalarMatrix& matrix);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2022 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -51,6 +51,25 @@ addToRunTimeSelectionTable
|
|||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
|
void objectivePowerDissipation::populateFieldNames()
|
||||||
|
{
|
||||||
|
if (fieldNames_.size() == 1)
|
||||||
|
{
|
||||||
|
const incompressibleAdjointSolver& adjSolver =
|
||||||
|
mesh_.lookupObject<incompressibleAdjointSolver>(adjointSolverName_);
|
||||||
|
const autoPtr<incompressibleAdjoint::adjointRASModel>& adjointRAS =
|
||||||
|
adjSolver.getAdjointVars().adjointTurbulence();
|
||||||
|
const wordList& baseNames =
|
||||||
|
adjointRAS().getAdjointTMVariablesBaseNames();
|
||||||
|
forAll(baseNames, nI)
|
||||||
|
{
|
||||||
|
fieldNames_.push_back
|
||||||
|
(adjSolver.extendedVariableName(baseNames[nI]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
objectivePowerDissipation::objectivePowerDissipation
|
objectivePowerDissipation::objectivePowerDissipation
|
||||||
@ -65,14 +84,12 @@ objectivePowerDissipation::objectivePowerDissipation
|
|||||||
zones_(mesh_.cellZones().indices(dict.get<wordRes>("zones")))
|
zones_(mesh_.cellZones().indices(dict.get<wordRes>("zones")))
|
||||||
{
|
{
|
||||||
// Append Ua name to fieldNames
|
// Append Ua name to fieldNames
|
||||||
/*
|
|
||||||
fieldNames_.setSize
|
fieldNames_.setSize
|
||||||
(
|
(
|
||||||
1,
|
1,
|
||||||
mesh_.lookupObject<solver>(adjointSolverName_).
|
mesh_.lookupObject<solver>(adjointSolverName_).
|
||||||
extendedVariableName("Ua")
|
extendedVariableName("Ua")
|
||||||
);
|
);
|
||||||
*/
|
|
||||||
|
|
||||||
// Check if cellZones provided include at least one cell
|
// Check if cellZones provided include at least one cell
|
||||||
checkCellZonesSize(zones_);
|
checkCellZonesSize(zones_);
|
||||||
@ -93,13 +110,19 @@ objectivePowerDissipation::objectivePowerDissipation
|
|||||||
// Allocate terms to be added to volume-based sensitivity derivatives
|
// Allocate terms to be added to volume-based sensitivity derivatives
|
||||||
divDxDbMultPtr_.reset
|
divDxDbMultPtr_.reset
|
||||||
(
|
(
|
||||||
createZeroFieldPtr<scalar>
|
new volScalarField
|
||||||
(
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"divDxDbMult" + objectiveName_,
|
||||||
|
mesh_.time().timeName(),
|
||||||
|
mesh_,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
mesh_,
|
mesh_,
|
||||||
("divDxdbMult" + type()),
|
dimensionedScalar(sqr(dimLength)/pow3(dimTime), Zero),
|
||||||
// Dimensions are set in a way that the gradient of this term
|
fvPatchFieldBase::zeroGradientType()
|
||||||
// matches the source of the adjoint grid displacement PDE
|
|
||||||
sqr(dimLength)/pow3(dimTime)
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
gradDxDbMultPtr_.reset
|
gradDxDbMultPtr_.reset
|
||||||
@ -250,7 +273,21 @@ void objectivePowerDissipation::update_gradDxDbMultiplier()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
gradDxDbMult.correctBoundaryConditions();
|
gradDxDbMult.correctBoundaryConditions();
|
||||||
// Missing contribution from gradU in nut
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void objectivePowerDissipation::addSource(fvScalarMatrix& matrix)
|
||||||
|
{
|
||||||
|
populateFieldNames();
|
||||||
|
const label fieldI = fieldNames_.find(matrix.psi().name());
|
||||||
|
if (fieldI == 1)
|
||||||
|
{
|
||||||
|
matrix += weight()*dJdTMvar1Ptr_();
|
||||||
|
}
|
||||||
|
if (fieldI == 2)
|
||||||
|
{
|
||||||
|
matrix += weight()*dJdTMvar2Ptr_();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2022 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -66,6 +66,12 @@ class objectivePowerDissipation
|
|||||||
labelList zones_;
|
labelList zones_;
|
||||||
|
|
||||||
|
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
//- Populate fieldNames
|
||||||
|
void populateFieldNames();
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//- Runtime type information
|
//- Runtime type information
|
||||||
@ -107,6 +113,9 @@ public:
|
|||||||
|
|
||||||
//- Update grad(dx/db multiplier). Volume-based sensitivity term
|
//- Update grad(dx/db multiplier). Volume-based sensitivity term
|
||||||
virtual void update_gradDxDbMultiplier();
|
virtual void update_gradDxDbMultiplier();
|
||||||
|
|
||||||
|
//- Add source terms to the adjoint turbulence model equations
|
||||||
|
virtual void addSource(fvScalarMatrix& matrix);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -107,7 +107,7 @@ void objectivePtLosses::initialize()
|
|||||||
const scalar mass = gSum(phiPatch);
|
const scalar mass = gSum(phiPatch);
|
||||||
if (mag(mass) > SMALL)
|
if (mag(mass) > SMALL)
|
||||||
{
|
{
|
||||||
objectiveReportPatches.append(patchI);
|
objectiveReportPatches.push_back(patchI);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2022 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -67,14 +67,12 @@ objectiveUniformityCellZone::objectiveUniformityCellZone
|
|||||||
volZone_(zones_.size(), Zero)
|
volZone_(zones_.size(), Zero)
|
||||||
{
|
{
|
||||||
// Append Ua name to fieldNames
|
// Append Ua name to fieldNames
|
||||||
/*
|
|
||||||
fieldNames_.setSize
|
fieldNames_.setSize
|
||||||
(
|
(
|
||||||
1,
|
1,
|
||||||
mesh_.lookupObject<solver>(adjointSolverName_).
|
mesh_.lookupObject<solver>(adjointSolverName_).
|
||||||
extendedVariableName("Ua")
|
extendedVariableName("Ua")
|
||||||
);
|
);
|
||||||
*/
|
|
||||||
|
|
||||||
// Check if cellZones provided include at least one cell
|
// Check if cellZones provided include at least one cell
|
||||||
checkCellZonesSize(zones_);
|
checkCellZonesSize(zones_);
|
||||||
@ -92,13 +90,19 @@ objectiveUniformityCellZone::objectiveUniformityCellZone
|
|||||||
// Allocate term to be added to volume-based sensitivity derivatives
|
// Allocate term to be added to volume-based sensitivity derivatives
|
||||||
divDxDbMultPtr_.reset
|
divDxDbMultPtr_.reset
|
||||||
(
|
(
|
||||||
createZeroFieldPtr<scalar>
|
new volScalarField
|
||||||
(
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"divDxDbMult" + objectiveName_,
|
||||||
|
mesh_.time().timeName(),
|
||||||
|
mesh_,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
mesh_,
|
mesh_,
|
||||||
("divDxdbMult" + type()) ,
|
dimensionedScalar(sqr(dimLength)/pow3(dimTime), Zero),
|
||||||
// Dimensions are set in a way that the gradient of this term
|
fvPatchFieldBase::zeroGradientType()
|
||||||
// matches the source of the adjoint grid displacement PDE
|
|
||||||
sqr(dimLength)/pow3(dimTime)
|
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -106,7 +106,7 @@ void objectiveUniformityPatch::initialize()
|
|||||||
const scalar mass = gSum(phiPatch);
|
const scalar mass = gSum(phiPatch);
|
||||||
if (mass > SMALL)
|
if (mass > SMALL)
|
||||||
{
|
{
|
||||||
objectiveReportPatches.append(patchI);
|
objectiveReportPatches.push_back(patchI);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2020 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019-2021 OpenCFD Ltd.
|
Copyright (C) 2019-2021 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -50,6 +50,10 @@ void objective::makeFolder()
|
|||||||
const Time& time = mesh_.time();
|
const Time& time = mesh_.time();
|
||||||
objFunctionFolder_ =
|
objFunctionFolder_ =
|
||||||
time.globalPath()/"optimisation"/type()/time.timeName();
|
time.globalPath()/"optimisation"/type()/time.timeName();
|
||||||
|
if (mesh_.name() != polyMesh::defaultRegion)
|
||||||
|
{
|
||||||
|
objFunctionFolder_ /= mesh_.name();
|
||||||
|
}
|
||||||
|
|
||||||
mkDir(objFunctionFolder_);
|
mkDir(objFunctionFolder_);
|
||||||
}
|
}
|
||||||
@ -131,10 +135,12 @@ objective::objective
|
|||||||
computeMeanFields_(false), // is reset in derived classes
|
computeMeanFields_(false), // is reset in derived classes
|
||||||
nullified_(false),
|
nullified_(false),
|
||||||
normalize_(dict.getOrDefault<bool>("normalize", false)),
|
normalize_(dict.getOrDefault<bool>("normalize", false)),
|
||||||
|
shouldWrite_(true),
|
||||||
|
|
||||||
J_(Zero),
|
J_(Zero),
|
||||||
JMean_(this->getOrDefault<scalar>("JMean", Zero)),
|
JMean_(this->getOrDefault<scalar>("JMean", Zero)),
|
||||||
weight_(Zero),
|
weight_(dict.get<scalar>("weight")),
|
||||||
|
computed_(false),
|
||||||
normFactor_(nullptr),
|
normFactor_(nullptr),
|
||||||
target_
|
target_
|
||||||
(
|
(
|
||||||
@ -142,14 +148,22 @@ objective::objective
|
|||||||
autoPtr<scalar>::New(dict.get<scalar>("target")) :
|
autoPtr<scalar>::New(dict.get<scalar>("target")) :
|
||||||
nullptr
|
nullptr
|
||||||
),
|
),
|
||||||
|
targetLeft_
|
||||||
|
(
|
||||||
|
dict.found("targetLeft") ?
|
||||||
|
autoPtr<scalar>::New(dict.get<scalar>("targetLeft")) :
|
||||||
|
nullptr
|
||||||
|
),
|
||||||
integrationStartTimePtr_(nullptr),
|
integrationStartTimePtr_(nullptr),
|
||||||
integrationEndTimePtr_(nullptr),
|
integrationEndTimePtr_(nullptr),
|
||||||
|
fieldNames_(),
|
||||||
|
|
||||||
// Initialize pointers to nullptr.
|
// Initialize pointers to nullptr.
|
||||||
// Not all of them are required for each objective function.
|
// Not all of them are required for each objective function.
|
||||||
// Each child should allocate whatever is needed.
|
// Each child should allocate whatever is needed.
|
||||||
|
|
||||||
dJdbPtr_(nullptr),
|
dJdbPtr_(nullptr),
|
||||||
|
dJdbFieldPtr_(nullptr),
|
||||||
bdJdbPtr_(nullptr),
|
bdJdbPtr_(nullptr),
|
||||||
bdSdbMultPtr_(nullptr),
|
bdSdbMultPtr_(nullptr),
|
||||||
bdndbMultPtr_(nullptr),
|
bdndbMultPtr_(nullptr),
|
||||||
@ -196,6 +210,9 @@ objective::objective
|
|||||||
normFactor_.reset(new scalar(normFactor));
|
normFactor_.reset(new scalar(normFactor));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set the weight factor in case of continuation
|
||||||
|
this->readIfPresent("weight", weight_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -245,7 +262,7 @@ bool objective::readDict(const dictionary& dict)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
scalar objective::JCycle() const
|
scalar objective::JCycle(bool negate) const
|
||||||
{
|
{
|
||||||
scalar J(J_);
|
scalar J(J_);
|
||||||
if
|
if
|
||||||
@ -260,7 +277,14 @@ scalar objective::JCycle() const
|
|||||||
// Subtract target, in case the objective is used as a constraint
|
// Subtract target, in case the objective is used as a constraint
|
||||||
if (target_.valid())
|
if (target_.valid())
|
||||||
{
|
{
|
||||||
J -= target_();
|
if (negate)
|
||||||
|
{
|
||||||
|
J = - J + targetLeft_();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
J -= target_();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Normalize here, in order to get the correct value for line search
|
// Normalize here, in order to get the correct value for line search
|
||||||
@ -268,6 +292,7 @@ scalar objective::JCycle() const
|
|||||||
{
|
{
|
||||||
J /= normFactor_();
|
J /= normFactor_();
|
||||||
}
|
}
|
||||||
|
J *= weight_;
|
||||||
|
|
||||||
return J;
|
return J;
|
||||||
}
|
}
|
||||||
@ -277,7 +302,12 @@ void objective::updateNormalizationFactor()
|
|||||||
{
|
{
|
||||||
if (normalize_ && !normFactor_)
|
if (normalize_ && !normFactor_)
|
||||||
{
|
{
|
||||||
normFactor_.reset(new scalar(JCycle()));
|
scalar J(JCycle()/weight_);
|
||||||
|
normFactor_.reset(new scalar(J));
|
||||||
|
DebugInfo
|
||||||
|
<< "objective " << name() << ":: updating norm factor "
|
||||||
|
<< "to " << normFactor_()
|
||||||
|
<< " for time = " << mesh_.time().timeName() << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -343,6 +373,10 @@ void objective::doNormalization()
|
|||||||
{
|
{
|
||||||
dJdbPtr_().primitiveFieldRef() *= oneOverNorm;
|
dJdbPtr_().primitiveFieldRef() *= oneOverNorm;
|
||||||
}
|
}
|
||||||
|
if (hasdJdbField())
|
||||||
|
{
|
||||||
|
dJdbFieldPtr_() *= oneOverNorm;
|
||||||
|
}
|
||||||
if (hasBoundarydJdb())
|
if (hasBoundarydJdb())
|
||||||
{
|
{
|
||||||
bdJdbPtr_() *= oneOverNorm;
|
bdJdbPtr_() *= oneOverNorm;
|
||||||
@ -393,7 +427,8 @@ bool objective::isWithinIntegrationTime() const
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
FatalErrorInFunction
|
FatalErrorInFunction
|
||||||
<< "Unallocated integration start or end time"
|
<< "Unallocated integration start or end time for objective '"
|
||||||
|
<< objectiveName_ << "'"
|
||||||
<< exit(FatalError);
|
<< exit(FatalError);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -416,193 +451,24 @@ void objective::incrementIntegrationTimes(const scalar timeSpan)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const volScalarField& objective::dJdb()
|
void objective::update()
|
||||||
{
|
{
|
||||||
if (!dJdbPtr_)
|
// Objective function value
|
||||||
{
|
J();
|
||||||
// If pointer is not set, set it to a zero field
|
|
||||||
dJdbPtr_.reset
|
|
||||||
(
|
|
||||||
createZeroFieldPtr<scalar>
|
|
||||||
(
|
|
||||||
mesh_,
|
|
||||||
("dJdb_" + objectiveName_),
|
|
||||||
dimensionSet(0, 5, -2, 0, 0, 0, 0)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return *dJdbPtr_;
|
// volFields
|
||||||
}
|
update_dJdb();
|
||||||
|
update_dJdbField();
|
||||||
|
update_divDxDbMultiplier();
|
||||||
|
update_gradDxDbMultiplier();
|
||||||
|
|
||||||
|
// boundaryFields
|
||||||
const fvPatchVectorField& objective::boundarydJdb(const label patchI)
|
update_boundarydJdb();
|
||||||
{
|
update_dSdbMultiplier();
|
||||||
if (!bdJdbPtr_)
|
update_dndbMultiplier();
|
||||||
{
|
update_dxdbMultiplier();
|
||||||
bdJdbPtr_.reset(createZeroBoundaryPtr<vector>(mesh_));
|
update_dxdbDirectMultiplier();
|
||||||
}
|
update_boundaryEdgeContribution();
|
||||||
return bdJdbPtr_()[patchI];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const fvPatchVectorField& objective::dSdbMultiplier(const label patchI)
|
|
||||||
{
|
|
||||||
if (!bdSdbMultPtr_)
|
|
||||||
{
|
|
||||||
bdSdbMultPtr_.reset(createZeroBoundaryPtr<vector>(mesh_));
|
|
||||||
}
|
|
||||||
return bdSdbMultPtr_()[patchI];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const fvPatchVectorField& objective::dndbMultiplier(const label patchI)
|
|
||||||
{
|
|
||||||
if (!bdndbMultPtr_)
|
|
||||||
{
|
|
||||||
bdndbMultPtr_.reset(createZeroBoundaryPtr<vector>(mesh_));
|
|
||||||
}
|
|
||||||
return bdndbMultPtr_()[patchI];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const fvPatchVectorField& objective::dxdbMultiplier(const label patchI)
|
|
||||||
{
|
|
||||||
if (!bdxdbMultPtr_)
|
|
||||||
{
|
|
||||||
bdxdbMultPtr_.reset(createZeroBoundaryPtr<vector>(mesh_));
|
|
||||||
}
|
|
||||||
return bdxdbMultPtr_()[patchI];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const fvPatchVectorField& objective::dxdbDirectMultiplier(const label patchI)
|
|
||||||
{
|
|
||||||
if (!bdxdbDirectMultPtr_)
|
|
||||||
{
|
|
||||||
bdxdbDirectMultPtr_.reset(createZeroBoundaryPtr<vector>(mesh_));
|
|
||||||
}
|
|
||||||
return bdxdbDirectMultPtr_()[patchI];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const vectorField& objective::boundaryEdgeMultiplier
|
|
||||||
(
|
|
||||||
const label patchI,
|
|
||||||
const label edgeI
|
|
||||||
)
|
|
||||||
{
|
|
||||||
if (!bdxdbDirectMultPtr_)
|
|
||||||
{
|
|
||||||
FatalErrorInFunction
|
|
||||||
<< "Unallocated boundaryEdgeMultiplier field"
|
|
||||||
<< exit(FatalError);
|
|
||||||
}
|
|
||||||
return bEdgeContribution_()[patchI][edgeI];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const boundaryVectorField& objective::boundarydJdb()
|
|
||||||
{
|
|
||||||
if (!bdJdbPtr_)
|
|
||||||
{
|
|
||||||
bdJdbPtr_.reset(createZeroBoundaryPtr<vector>(mesh_));
|
|
||||||
}
|
|
||||||
return *bdJdbPtr_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const boundaryVectorField& objective::dSdbMultiplier()
|
|
||||||
{
|
|
||||||
if (!bdSdbMultPtr_)
|
|
||||||
{
|
|
||||||
bdSdbMultPtr_.reset(createZeroBoundaryPtr<vector>(mesh_));
|
|
||||||
}
|
|
||||||
return *bdSdbMultPtr_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const boundaryVectorField& objective::dndbMultiplier()
|
|
||||||
{
|
|
||||||
if (!bdndbMultPtr_)
|
|
||||||
{
|
|
||||||
bdndbMultPtr_.reset(createZeroBoundaryPtr<vector>(mesh_));
|
|
||||||
}
|
|
||||||
return *bdndbMultPtr_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const boundaryVectorField& objective::dxdbMultiplier()
|
|
||||||
{
|
|
||||||
if (!bdxdbMultPtr_)
|
|
||||||
{
|
|
||||||
bdxdbMultPtr_.reset(createZeroBoundaryPtr<vector>(mesh_));
|
|
||||||
}
|
|
||||||
return *bdxdbMultPtr_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const boundaryVectorField& objective::dxdbDirectMultiplier()
|
|
||||||
{
|
|
||||||
if (!bdxdbDirectMultPtr_)
|
|
||||||
{
|
|
||||||
bdxdbDirectMultPtr_.reset(createZeroBoundaryPtr<vector>(mesh_));
|
|
||||||
}
|
|
||||||
return *bdxdbDirectMultPtr_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const vectorField3& objective::boundaryEdgeMultiplier()
|
|
||||||
{
|
|
||||||
if (!bdxdbDirectMultPtr_)
|
|
||||||
{
|
|
||||||
FatalErrorInFunction
|
|
||||||
<< "Unallocated boundaryEdgeMultiplier field"
|
|
||||||
<< endl << endl
|
|
||||||
<< exit(FatalError);
|
|
||||||
}
|
|
||||||
return *bEdgeContribution_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const volScalarField& objective::divDxDbMultiplier()
|
|
||||||
{
|
|
||||||
if (!divDxDbMultPtr_)
|
|
||||||
{
|
|
||||||
// If pointer is not set, set it to a zero field
|
|
||||||
divDxDbMultPtr_.reset
|
|
||||||
(
|
|
||||||
createZeroFieldPtr<scalar>
|
|
||||||
(
|
|
||||||
mesh_,
|
|
||||||
("divDxDbMult"+objectiveName_),
|
|
||||||
// Variable dimensions!!
|
|
||||||
// Dummy dimensionless. Only the internalField will be used
|
|
||||||
dimless
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return *divDxDbMultPtr_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const volTensorField& objective::gradDxDbMultiplier()
|
|
||||||
{
|
|
||||||
if (!gradDxDbMultPtr_)
|
|
||||||
{
|
|
||||||
// If pointer is not set, set it to a zero field
|
|
||||||
gradDxDbMultPtr_.reset
|
|
||||||
(
|
|
||||||
createZeroFieldPtr<tensor>
|
|
||||||
(
|
|
||||||
mesh_,
|
|
||||||
("gradDxDbMult"+objectiveName_),
|
|
||||||
// Variable dimensions!!
|
|
||||||
dimensionSet(pow2(dimLength)/pow3(dimTime))
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return *gradDxDbMultPtr_;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -614,6 +480,10 @@ void objective::nullify()
|
|||||||
{
|
{
|
||||||
dJdbPtr_() == dimensionedScalar(dJdbPtr_().dimensions(), Zero);
|
dJdbPtr_() == dimensionedScalar(dJdbPtr_().dimensions(), Zero);
|
||||||
}
|
}
|
||||||
|
if (hasdJdbField())
|
||||||
|
{
|
||||||
|
dJdbFieldPtr_() = Zero;
|
||||||
|
}
|
||||||
if (hasBoundarydJdb())
|
if (hasBoundarydJdb())
|
||||||
{
|
{
|
||||||
bdJdbPtr_() == vector::zero;
|
bdJdbPtr_() == vector::zero;
|
||||||
@ -676,6 +546,11 @@ bool objective::write(const bool valid) const
|
|||||||
file<< setw(width_) << "#target" << " "
|
file<< setw(width_) << "#target" << " "
|
||||||
<< setw(width_) << target_() << endl;
|
<< setw(width_) << target_() << endl;
|
||||||
}
|
}
|
||||||
|
if (targetLeft_.valid())
|
||||||
|
{
|
||||||
|
file<< setw(width_) << "#targetLeft" << " "
|
||||||
|
<< setw(width_) << targetLeft_() << endl;
|
||||||
|
}
|
||||||
if (normalize_)
|
if (normalize_)
|
||||||
{
|
{
|
||||||
file<< setw(width_) << "#normFactor " << " "
|
file<< setw(width_) << "#normFactor " << " "
|
||||||
@ -685,6 +560,10 @@ bool objective::write(const bool valid) const
|
|||||||
file<< setw(4) << "#" << " ";
|
file<< setw(4) << "#" << " ";
|
||||||
file<< setw(width_) << "J" << " ";
|
file<< setw(width_) << "J" << " ";
|
||||||
file<< setw(width_) << "JCycle" << " ";
|
file<< setw(width_) << "JCycle" << " ";
|
||||||
|
if (targetLeft_)
|
||||||
|
{
|
||||||
|
file<< setw(width_) << "JCycleLeft" << " ";
|
||||||
|
}
|
||||||
addHeaderColumns();
|
addHeaderColumns();
|
||||||
file<< endl;
|
file<< endl;
|
||||||
}
|
}
|
||||||
@ -693,6 +572,10 @@ bool objective::write(const bool valid) const
|
|||||||
file<< setw(4) << mesh_.time().value() << " ";
|
file<< setw(4) << mesh_.time().value() << " ";
|
||||||
file<< setw(width_) << J_ << " ";
|
file<< setw(width_) << J_ << " ";
|
||||||
file<< setw(width_) << JCycle() << " ";
|
file<< setw(width_) << JCycle() << " ";
|
||||||
|
if (targetLeft_)
|
||||||
|
{
|
||||||
|
file<< setw(width_) << JCycle(true) << " ";
|
||||||
|
}
|
||||||
addColumnValues();
|
addColumnValues();
|
||||||
file<< endl;
|
file<< endl;
|
||||||
}
|
}
|
||||||
@ -708,12 +591,14 @@ void objective::writeInstantaneousValue() const
|
|||||||
// File is opened only upon invocation of the write function
|
// File is opened only upon invocation of the write function
|
||||||
// in order to avoid various instantiations of the same objective
|
// in order to avoid various instantiations of the same objective
|
||||||
// opening the same file
|
// opening the same file
|
||||||
|
unsigned int width = IOstream::defaultPrecision() + 6;
|
||||||
if (!instantValueFilePtr_)
|
if (!instantValueFilePtr_)
|
||||||
{
|
{
|
||||||
setInstantValueFilePtr();
|
setInstantValueFilePtr();
|
||||||
}
|
}
|
||||||
|
|
||||||
instantValueFilePtr_() << mesh_.time().value() << tab << J_ << endl;
|
instantValueFilePtr_()
|
||||||
|
<< setw(width) << mesh_.time().value() << tab << J_ << endl;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -764,6 +649,7 @@ bool objective::writeData(Ostream& os) const
|
|||||||
{
|
{
|
||||||
os.writeEntry("normFactor", normFactor_());
|
os.writeEntry("normFactor", normFactor_());
|
||||||
}
|
}
|
||||||
|
os.writeEntry("weight", weight_);
|
||||||
return os.good();
|
return os.good();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2020 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2020 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019-2020 OpenCFD Ltd.
|
Copyright (C) 2019-2020 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -73,6 +73,7 @@ protected:
|
|||||||
bool computeMeanFields_;
|
bool computeMeanFields_;
|
||||||
bool nullified_;
|
bool nullified_;
|
||||||
bool normalize_;
|
bool normalize_;
|
||||||
|
bool shouldWrite_;
|
||||||
|
|
||||||
//- Objective function value and weight
|
//- Objective function value and weight
|
||||||
scalar J_;
|
scalar J_;
|
||||||
@ -83,23 +84,47 @@ protected:
|
|||||||
//- Objective weight
|
//- Objective weight
|
||||||
scalar weight_;
|
scalar weight_;
|
||||||
|
|
||||||
|
//- Whether the objective is computed or not
|
||||||
|
// Some objective (e.g. geometric ones) might not change from one
|
||||||
|
// iteration of the primal solver to the next and might be expensive
|
||||||
|
// to evaluate. This can be used to compute them only once per
|
||||||
|
// optimisation cycle
|
||||||
|
bool computed_;
|
||||||
|
|
||||||
//- Normalization factor
|
//- Normalization factor
|
||||||
autoPtr<scalar> normFactor_;
|
autoPtr<scalar> normFactor_;
|
||||||
|
|
||||||
//- Target value, in case the objective is used as a constraint
|
//- Target value, in case the objective is used as a constraint
|
||||||
// Should be used in caution and with updateMethods than get affected
|
// Should be used with caution and with updateMethods
|
||||||
// by the target value, without requiring a sqr (e.g. SQP, MMA)
|
// than get affected by the target value, without
|
||||||
|
// requiring a sqr (e.g. SQP, MMA)
|
||||||
autoPtr<scalar> target_;
|
autoPtr<scalar> target_;
|
||||||
|
|
||||||
|
//- Target on the left hand-side of a double inequality,
|
||||||
|
//- for double sided constraints
|
||||||
|
autoPtr<scalar> targetLeft_;
|
||||||
|
|
||||||
//- Objective integration start and end times (for unsteady flows)
|
//- Objective integration start and end times (for unsteady flows)
|
||||||
autoPtr<scalar> integrationStartTimePtr_;
|
autoPtr<scalar> integrationStartTimePtr_;
|
||||||
autoPtr<scalar> integrationEndTimePtr_;
|
autoPtr<scalar> integrationEndTimePtr_;
|
||||||
|
|
||||||
|
//- List of adjoint fields for which this objective will contribute
|
||||||
|
//- sources to their equations.
|
||||||
|
// Only for volume-based objectives for the moment
|
||||||
|
wordList fieldNames_;
|
||||||
|
|
||||||
//- Contribution to field sensitivity derivatives
|
//- Contribution to field sensitivity derivatives
|
||||||
// Topology optimisation or other variants with
|
// Topology optimisation or other variants with
|
||||||
// as many design variables as the mesh cells
|
// as many design variables as the mesh cells
|
||||||
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
autoPtr<volScalarField> dJdbPtr_;
|
autoPtr<volScalarField> dJdbPtr_;
|
||||||
|
|
||||||
|
//- Contribution to sensitivity derivatives with a
|
||||||
|
//- random number of design variables
|
||||||
|
//- (neither surface, nor volume based)
|
||||||
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
autoPtr<scalarField> dJdbFieldPtr_;
|
||||||
|
|
||||||
// Contribution to surface sensitivity derivatives
|
// Contribution to surface sensitivity derivatives
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
@ -155,9 +180,6 @@ protected:
|
|||||||
|
|
||||||
// Protected Member Functions
|
// Protected Member Functions
|
||||||
|
|
||||||
//- Return objective dictionary
|
|
||||||
const dictionary& dict() const;
|
|
||||||
|
|
||||||
//- Set the output file ptr
|
//- Set the output file ptr
|
||||||
void setObjectiveFilePtr() const;
|
void setObjectiveFilePtr() const;
|
||||||
|
|
||||||
@ -241,9 +263,10 @@ public:
|
|||||||
//- Return the instantaneous objective function value
|
//- Return the instantaneous objective function value
|
||||||
virtual scalar J() = 0;
|
virtual scalar J() = 0;
|
||||||
|
|
||||||
//- Return the mean objective function value, if it exists,
|
//- Return the objective function of the optimisation cycle.
|
||||||
//- otherwise the mean one
|
// This corresponds to the mean value, if it exists, or the
|
||||||
scalar JCycle() const;
|
// instantaneous value otherwise
|
||||||
|
scalar JCycle(bool negate = false) const;
|
||||||
|
|
||||||
//- Accumulate contribution for the mean objective value
|
//- Accumulate contribution for the mean objective value
|
||||||
// For steady-state runs
|
// For steady-state runs
|
||||||
@ -256,6 +279,12 @@ public:
|
|||||||
//- Return the objective function weight
|
//- Return the objective function weight
|
||||||
scalar weight() const;
|
scalar weight() const;
|
||||||
|
|
||||||
|
//- Return the normalization factor
|
||||||
|
const autoPtr<scalar>& normFactor() const;
|
||||||
|
|
||||||
|
//- Return the objective target value
|
||||||
|
const autoPtr<scalar>& target() const;
|
||||||
|
|
||||||
//- Is the objective normalized
|
//- Is the objective normalized
|
||||||
bool normalize() const;
|
bool normalize() const;
|
||||||
|
|
||||||
@ -269,53 +298,56 @@ public:
|
|||||||
void incrementIntegrationTimes(const scalar timeSpan);
|
void incrementIntegrationTimes(const scalar timeSpan);
|
||||||
|
|
||||||
//- Contribution to field sensitivities
|
//- Contribution to field sensitivities
|
||||||
const volScalarField& dJdb();
|
inline const volScalarField& dJdb();
|
||||||
|
|
||||||
|
//- Contribution to sensitivities with a random number of designVars
|
||||||
|
inline const scalarField& dJdbField();
|
||||||
|
|
||||||
//- Contribution to surface sensitivities for a specific patch
|
//- Contribution to surface sensitivities for a specific patch
|
||||||
const fvPatchVectorField& boundarydJdb(const label);
|
inline const fvPatchVectorField& boundarydJdb(const label);
|
||||||
|
|
||||||
//- Multiplier of delta(n dS)/delta b
|
//- Multiplier of delta(n dS)/delta b
|
||||||
const fvPatchVectorField& dSdbMultiplier(const label);
|
inline const fvPatchVectorField& dSdbMultiplier(const label);
|
||||||
|
|
||||||
//- Multiplier of delta(n dS)/delta b
|
//- Multiplier of delta(n dS)/delta b
|
||||||
const fvPatchVectorField& dndbMultiplier(const label);
|
inline const fvPatchVectorField& dndbMultiplier(const label);
|
||||||
|
|
||||||
//- Multiplier of delta(x)/delta b
|
//- Multiplier of delta(x)/delta b
|
||||||
const fvPatchVectorField& dxdbMultiplier(const label);
|
inline const fvPatchVectorField& dxdbMultiplier(const label);
|
||||||
|
|
||||||
//- Multiplier of delta(x)/delta b
|
//- Multiplier of delta(x)/delta b
|
||||||
const fvPatchVectorField& dxdbDirectMultiplier(const label);
|
inline const fvPatchVectorField& dxdbDirectMultiplier(const label);
|
||||||
|
|
||||||
//- Multiplier located at patch boundary edges
|
//- Multiplier located at patch boundary edges
|
||||||
const vectorField& boundaryEdgeMultiplier
|
inline const vectorField& boundaryEdgeMultiplier
|
||||||
(
|
(
|
||||||
const label patchI,
|
const label patchI,
|
||||||
const label edgeI
|
const label edgeI
|
||||||
);
|
);
|
||||||
|
|
||||||
//- Contribution to surface sensitivities for all patches
|
//- Contribution to surface sensitivities for all patches
|
||||||
const boundaryVectorField& boundarydJdb();
|
inline const boundaryVectorField& boundarydJdb();
|
||||||
|
|
||||||
//- Multiplier of delta(n dS)/delta b for all patches
|
//- Multiplier of delta(n dS)/delta b for all patches
|
||||||
const boundaryVectorField& dSdbMultiplier();
|
inline const boundaryVectorField& dSdbMultiplier();
|
||||||
|
|
||||||
//- Multiplier of delta(n dS)/delta b for all patches
|
//- Multiplier of delta(n dS)/delta b for all patches
|
||||||
const boundaryVectorField& dndbMultiplier();
|
inline const boundaryVectorField& dndbMultiplier();
|
||||||
|
|
||||||
//- Multiplier of delta(x)/delta b for all patches
|
//- Multiplier of delta(x)/delta b for all patches
|
||||||
const boundaryVectorField& dxdbMultiplier();
|
inline const boundaryVectorField& dxdbMultiplier();
|
||||||
|
|
||||||
//- Multiplier of delta(x)/delta b for all patches
|
//- Multiplier of delta(x)/delta b for all patches
|
||||||
const boundaryVectorField& dxdbDirectMultiplier();
|
inline const boundaryVectorField& dxdbDirectMultiplier();
|
||||||
|
|
||||||
//- Multiplier located at patch boundary edges
|
//- Multiplier located at patch boundary edges
|
||||||
const vectorField3& boundaryEdgeMultiplier();
|
inline const vectorField3& boundaryEdgeMultiplier();
|
||||||
|
|
||||||
//- Multiplier of grad( delta(x)/delta b) for volume-based sensitivities
|
//- Multiplier of grad( delta(x)/delta b) for volume-based sensitivities
|
||||||
const volScalarField& divDxDbMultiplier();
|
inline const volScalarField& divDxDbMultiplier();
|
||||||
|
|
||||||
//- Multiplier of grad( delta(x)/delta b) for volume-based sensitivities
|
//- Multiplier of grad( delta(x)/delta b) for volume-based sensitivities
|
||||||
const volTensorField& gradDxDbMultiplier();
|
inline const volTensorField& gradDxDbMultiplier();
|
||||||
|
|
||||||
//- Update objective function derivatives
|
//- Update objective function derivatives
|
||||||
virtual void update() = 0;
|
virtual void update() = 0;
|
||||||
@ -327,6 +359,13 @@ public:
|
|||||||
//- which the factor is not known a priori
|
//- which the factor is not known a priori
|
||||||
virtual void updateNormalizationFactor();
|
virtual void updateNormalizationFactor();
|
||||||
|
|
||||||
|
|
||||||
|
virtual void update_dJdb()
|
||||||
|
{}
|
||||||
|
|
||||||
|
virtual void update_dJdbField()
|
||||||
|
{}
|
||||||
|
|
||||||
//- Update objective function derivative term
|
//- Update objective function derivative term
|
||||||
virtual void update_boundarydJdb()
|
virtual void update_boundarydJdb()
|
||||||
{}
|
{}
|
||||||
@ -360,6 +399,15 @@ public:
|
|||||||
virtual void update_gradDxDbMultiplier()
|
virtual void update_gradDxDbMultiplier()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
//- Manipulate fvVectorMatrix through the objective
|
||||||
|
virtual void addSource(fvVectorMatrix& matrix)
|
||||||
|
{}
|
||||||
|
|
||||||
|
//- Manipulate fvVectorMatrix through the objective
|
||||||
|
virtual void addSource(fvScalarMatrix& matrix)
|
||||||
|
{}
|
||||||
|
|
||||||
//- Write objective function history
|
//- Write objective function history
|
||||||
virtual bool write(const bool valid = true) const;
|
virtual bool write(const bool valid = true) const;
|
||||||
|
|
||||||
@ -392,8 +440,15 @@ public:
|
|||||||
//- Return the objective name
|
//- Return the objective name
|
||||||
inline const word& objectiveName() const;
|
inline const word& objectiveName() const;
|
||||||
|
|
||||||
|
//- Should the objective be written to file upon calling write()?
|
||||||
|
inline bool shouldWrite() const;
|
||||||
|
|
||||||
|
//- Should the objective be written to file upon calling write()?
|
||||||
|
inline void setWrite(const bool shouldWrite);
|
||||||
|
|
||||||
// Inline functions for checking whether pointers are set or not
|
// Inline functions for checking whether pointers are set or not
|
||||||
inline bool hasdJdb() const;
|
inline bool hasdJdb() const;
|
||||||
|
inline bool hasdJdbField() const;
|
||||||
inline bool hasBoundarydJdb() const;
|
inline bool hasBoundarydJdb() const;
|
||||||
inline bool hasdSdbMult() const;
|
inline bool hasdSdbMult() const;
|
||||||
inline bool hasdndbMult() const;
|
inline bool hasdndbMult() const;
|
||||||
@ -406,6 +461,11 @@ public:
|
|||||||
// Inline functions for checking whether integration times are set
|
// Inline functions for checking whether integration times are set
|
||||||
inline bool hasIntegrationStartTime() const;
|
inline bool hasIntegrationStartTime() const;
|
||||||
inline bool hasIntegrationEndTime() const;
|
inline bool hasIntegrationEndTime() const;
|
||||||
|
// Set the computed status of the objective
|
||||||
|
inline void setComputed(const bool isComputed);
|
||||||
|
|
||||||
|
//- Return objective dictionary
|
||||||
|
const dictionary& dict() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2019 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019-2020 OpenCFD Ltd.
|
Copyright (C) 2019-2020 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -36,12 +36,148 @@ inline const Foam::word& Foam::objective::objectiveName() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool Foam::objective::shouldWrite() const
|
||||||
|
{
|
||||||
|
return shouldWrite_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void Foam::objective::setWrite(const bool shouldWrite)
|
||||||
|
{
|
||||||
|
shouldWrite_ = shouldWrite;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::volScalarField& Foam::objective::dJdb()
|
||||||
|
{
|
||||||
|
return *dJdbPtr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::scalarField& Foam::objective::dJdbField()
|
||||||
|
{
|
||||||
|
return *dJdbFieldPtr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::fvPatchVectorField&
|
||||||
|
Foam::objective::boundarydJdb(const label patchI)
|
||||||
|
{
|
||||||
|
return bdJdbPtr_()[patchI];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::fvPatchVectorField&
|
||||||
|
Foam::objective::dSdbMultiplier(const label patchI)
|
||||||
|
{
|
||||||
|
return bdSdbMultPtr_()[patchI];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::fvPatchVectorField&
|
||||||
|
Foam::objective::dndbMultiplier(const label patchI)
|
||||||
|
{
|
||||||
|
return bdndbMultPtr_()[patchI];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::fvPatchVectorField&
|
||||||
|
Foam::objective::dxdbMultiplier(const label patchI)
|
||||||
|
{
|
||||||
|
return bdxdbMultPtr_()[patchI];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::fvPatchVectorField&
|
||||||
|
Foam::objective::dxdbDirectMultiplier(const label patchI)
|
||||||
|
{
|
||||||
|
return bdxdbDirectMultPtr_()[patchI];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::vectorField& Foam::objective::boundaryEdgeMultiplier
|
||||||
|
(
|
||||||
|
const label patchI,
|
||||||
|
const label edgeI
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!bdxdbDirectMultPtr_)
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "Unallocated boundaryEdgeMultiplier field"
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
return bEdgeContribution_()[patchI][edgeI];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::boundaryVectorField& Foam::objective::boundarydJdb()
|
||||||
|
{
|
||||||
|
return *bdJdbPtr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::boundaryVectorField& Foam::objective::dSdbMultiplier()
|
||||||
|
{
|
||||||
|
return *bdSdbMultPtr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::boundaryVectorField& Foam::objective::dndbMultiplier()
|
||||||
|
{
|
||||||
|
return *bdndbMultPtr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::boundaryVectorField& Foam::objective::dxdbMultiplier()
|
||||||
|
{
|
||||||
|
return *bdxdbMultPtr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::boundaryVectorField& Foam::objective::dxdbDirectMultiplier()
|
||||||
|
{
|
||||||
|
return *bdxdbDirectMultPtr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::vectorField3& Foam::objective::boundaryEdgeMultiplier()
|
||||||
|
{
|
||||||
|
if (!bdxdbDirectMultPtr_)
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "Unallocated boundaryEdgeMultiplier field"
|
||||||
|
<< endl << endl
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
return *bEdgeContribution_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::volScalarField& Foam::objective::divDxDbMultiplier()
|
||||||
|
{
|
||||||
|
return *divDxDbMultPtr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::volTensorField& Foam::objective::gradDxDbMultiplier()
|
||||||
|
{
|
||||||
|
return *gradDxDbMultPtr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool Foam::objective::hasdJdb() const
|
inline bool Foam::objective::hasdJdb() const
|
||||||
{
|
{
|
||||||
return bool(dJdbPtr_);
|
return bool(dJdbPtr_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool Foam::objective::hasdJdbField() const
|
||||||
|
{
|
||||||
|
return bool(dJdbFieldPtr_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline bool Foam::objective::hasBoundarydJdb() const
|
inline bool Foam::objective::hasBoundarydJdb() const
|
||||||
{
|
{
|
||||||
return bool(bdJdbPtr_);
|
return bool(bdJdbPtr_);
|
||||||
@ -101,4 +237,11 @@ inline bool Foam::objective::hasIntegrationEndTime() const
|
|||||||
return bool(integrationEndTimePtr_);
|
return bool(integrationEndTimePtr_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void Foam::objective::setComputed(const bool isComputed)
|
||||||
|
{
|
||||||
|
computed_ = isComputed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
|
|||||||
@ -27,18 +27,23 @@ License
|
|||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "adjointEikonalSolverIncompressible.H"
|
#include "adjointEikonalSolver.H"
|
||||||
|
#include "adjointSolver.H"
|
||||||
|
#include "fvc.H"
|
||||||
|
#include "fvm.H"
|
||||||
|
#include "surfaceInterpolation.H"
|
||||||
|
#include "volFieldsFwd.H"
|
||||||
#include "wallFvPatch.H"
|
#include "wallFvPatch.H"
|
||||||
#include "patchDistMethod.H"
|
#include "patchDistMethod.H"
|
||||||
|
#include "fvOptions.H"
|
||||||
|
#include "zeroGradientFvPatchField.H"
|
||||||
|
#include "sensitivityTopO.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace incompressible
|
|
||||||
{
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
defineTypeNameAndDebug(adjointEikonalSolver, 0);
|
defineTypeNameAndDebug(adjointEikonalSolver, 0);
|
||||||
@ -55,7 +60,7 @@ wordList adjointEikonalSolver::patchTypes() const
|
|||||||
|
|
||||||
for (const label patchi : wallPatchIDs_)
|
for (const label patchi : wallPatchIDs_)
|
||||||
{
|
{
|
||||||
daTypes[patchi] = fvPatchFieldBase::zeroGradientType();
|
daTypes[patchi] = zeroGradientFvPatchScalarField::typeName;
|
||||||
}
|
}
|
||||||
|
|
||||||
return daTypes;
|
return daTypes;
|
||||||
@ -66,7 +71,6 @@ void adjointEikonalSolver::read()
|
|||||||
{
|
{
|
||||||
nEikonalIters_ = dict_.getOrDefault<label>("iters", 1000);
|
nEikonalIters_ = dict_.getOrDefault<label>("iters", 1000);
|
||||||
tolerance_ = dict_.getOrDefault<scalar>("tolerance", 1e-6);
|
tolerance_ = dict_.getOrDefault<scalar>("tolerance", 1e-6);
|
||||||
epsilon_ = dict_.getOrDefault<scalar>("epsilon", 0.1);
|
|
||||||
const scalar defaultEps =
|
const scalar defaultEps =
|
||||||
mesh_.schemesDict().subDict("wallDist").
|
mesh_.schemesDict().subDict("wallDist").
|
||||||
subOrEmptyDict("advectionDiffusionCoeffs").
|
subOrEmptyDict("advectionDiffusionCoeffs").
|
||||||
@ -78,7 +82,7 @@ void adjointEikonalSolver::read()
|
|||||||
tmp<surfaceScalarField> adjointEikonalSolver::computeYPhi()
|
tmp<surfaceScalarField> adjointEikonalSolver::computeYPhi()
|
||||||
{
|
{
|
||||||
// Primal distance field
|
// Primal distance field
|
||||||
const volScalarField& d = RASModelVars_().d();
|
const volScalarField& d = adjointSolver_.yWall();
|
||||||
|
|
||||||
volVectorField ny
|
volVectorField ny
|
||||||
(
|
(
|
||||||
@ -118,15 +122,13 @@ adjointEikonalSolver::adjointEikonalSolver
|
|||||||
(
|
(
|
||||||
const fvMesh& mesh,
|
const fvMesh& mesh,
|
||||||
const dictionary& dict,
|
const dictionary& dict,
|
||||||
const autoPtr<incompressible::RASModelVariables>& RASModelVars,
|
adjointSolver& adjointSolver,
|
||||||
incompressibleAdjointVars& adjointVars,
|
|
||||||
const labelHashSet& sensitivityPatchIDs
|
const labelHashSet& sensitivityPatchIDs
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
mesh_(mesh),
|
mesh_(mesh),
|
||||||
dict_(dict.subOrEmptyDict("adjointEikonalSolver")),
|
dict_(dict.subOrEmptyDict("adjointEikonalSolver")),
|
||||||
RASModelVars_(RASModelVars),
|
adjointSolver_(adjointSolver),
|
||||||
adjointTurbulence_(adjointVars.adjointTurbulence()),
|
|
||||||
sensitivityPatchIDs_(sensitivityPatchIDs),
|
sensitivityPatchIDs_(sensitivityPatchIDs),
|
||||||
nEikonalIters_(-1),
|
nEikonalIters_(-1),
|
||||||
tolerance_(-1),
|
tolerance_(-1),
|
||||||
@ -138,17 +140,19 @@ adjointEikonalSolver::adjointEikonalSolver
|
|||||||
(
|
(
|
||||||
word
|
word
|
||||||
(
|
(
|
||||||
adjointVars.useSolverNameForFields() ?
|
adjointSolver.useSolverNameForFields() ?
|
||||||
"da" + adjointTurbulence_().adjointSolverName() :
|
"da" + adjointSolver.solverName() :
|
||||||
"da"
|
"da"
|
||||||
),
|
),
|
||||||
mesh_.time().timeName(),
|
mesh_.time().timeName(),
|
||||||
mesh_,
|
mesh_,
|
||||||
IOobject::READ_IF_PRESENT,
|
IOobject::READ_IF_PRESENT,
|
||||||
IOobject::AUTO_WRITE
|
IOobject::AUTO_WRITE
|
||||||
|
// adjointVars.writeFields() ?
|
||||||
|
// IOobject::AUTO_WRITE : IOobject::NO_WRITE
|
||||||
),
|
),
|
||||||
mesh_,
|
mesh_,
|
||||||
dimensionedScalar(sqr(dimLength)/pow3(dimTime), Zero),
|
dimensionedScalar(adjointSolver.daDimensions() , Zero),
|
||||||
patchTypes()
|
patchTypes()
|
||||||
),
|
),
|
||||||
source_
|
source_
|
||||||
@ -162,7 +166,7 @@ adjointEikonalSolver::adjointEikonalSolver
|
|||||||
IOobject::NO_WRITE
|
IOobject::NO_WRITE
|
||||||
),
|
),
|
||||||
mesh_,
|
mesh_,
|
||||||
dimensionedScalar(dimLength/pow3(dimTime), Zero)
|
dimensionedScalar(adjointSolver.daDimensions()/dimLength, Zero)
|
||||||
),
|
),
|
||||||
distanceSensPtr_(createZeroBoundaryPtr<vector>(mesh_))
|
distanceSensPtr_(createZeroBoundaryPtr<vector>(mesh_))
|
||||||
{
|
{
|
||||||
@ -175,6 +179,7 @@ adjointEikonalSolver::adjointEikonalSolver
|
|||||||
bool adjointEikonalSolver::readDict(const dictionary& dict)
|
bool adjointEikonalSolver::readDict(const dictionary& dict)
|
||||||
{
|
{
|
||||||
dict_ = dict.subOrEmptyDict("adjointEikonalSolver");
|
dict_ = dict.subOrEmptyDict("adjointEikonalSolver");
|
||||||
|
read();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -183,7 +188,7 @@ bool adjointEikonalSolver::readDict(const dictionary& dict)
|
|||||||
void adjointEikonalSolver::accumulateIntegrand(const scalar dt)
|
void adjointEikonalSolver::accumulateIntegrand(const scalar dt)
|
||||||
{
|
{
|
||||||
// Accumulate integrand from the current time step
|
// Accumulate integrand from the current time step
|
||||||
source_ += adjointTurbulence_->distanceSensitivities()*dt;
|
source_ += adjointSolver_.adjointEikonalSource()*dt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -192,12 +197,29 @@ void adjointEikonalSolver::solve()
|
|||||||
read();
|
read();
|
||||||
|
|
||||||
// Primal distance field
|
// Primal distance field
|
||||||
const volScalarField& d = RASModelVars_().d();
|
const volScalarField& d = adjointSolver_.yWall();
|
||||||
|
|
||||||
// Convecting flux
|
// Convecting flux
|
||||||
tmp<surfaceScalarField> tyPhi = computeYPhi();
|
tmp<surfaceScalarField> tyPhi = computeYPhi();
|
||||||
const surfaceScalarField& yPhi = tyPhi();
|
const surfaceScalarField& yPhi = tyPhi();
|
||||||
|
|
||||||
|
volScalarField scaleDims
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"scaleDims",
|
||||||
|
mesh_.time().timeName(),
|
||||||
|
mesh_,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE,
|
||||||
|
false
|
||||||
|
),
|
||||||
|
mesh_,
|
||||||
|
dimensionedScalar("scaleDims", dimTime/dimLength, scalar(1))
|
||||||
|
);
|
||||||
|
|
||||||
|
fv::options& fvOptions(fv::options::New(this->mesh_));
|
||||||
|
|
||||||
// Iterate the adjoint to the eikonal equation
|
// Iterate the adjoint to the eikonal equation
|
||||||
for (label iter = 0; iter < nEikonalIters_; ++iter)
|
for (label iter = 0; iter < nEikonalIters_; ++iter)
|
||||||
{
|
{
|
||||||
@ -211,10 +233,15 @@ void adjointEikonalSolver::solve()
|
|||||||
+ fvm::SuSp(-epsilon_*fvc::laplacian(d), da_)
|
+ fvm::SuSp(-epsilon_*fvc::laplacian(d), da_)
|
||||||
- epsilon_*fvm::laplacian(d, da_)
|
- epsilon_*fvm::laplacian(d, da_)
|
||||||
+ source_
|
+ source_
|
||||||
|
==
|
||||||
|
fvOptions(scaleDims, da_)
|
||||||
);
|
);
|
||||||
|
|
||||||
daEqn.relax();
|
daEqn.relax();
|
||||||
|
fvOptions.constrain(daEqn);
|
||||||
scalar residual = daEqn.solve().initialResidual();
|
scalar residual = daEqn.solve().initialResidual();
|
||||||
|
fvOptions.correct(da_);
|
||||||
|
|
||||||
Info<< "Max da " << gMax(mag(da_)()) << endl;
|
Info<< "Max da " << gMax(mag(da_)()) << endl;
|
||||||
|
|
||||||
mesh_.time().printExecutionTime(Info);
|
mesh_.time().printExecutionTime(Info);
|
||||||
@ -247,7 +274,7 @@ boundaryVectorField& adjointEikonalSolver::distanceSensitivities()
|
|||||||
|
|
||||||
boundaryVectorField& distanceSens = distanceSensPtr_();
|
boundaryVectorField& distanceSens = distanceSensPtr_();
|
||||||
|
|
||||||
const volScalarField& d = RASModelVars_().d();
|
const volScalarField& d = adjointSolver_.yWall();
|
||||||
for (const label patchi : sensitivityPatchIDs_)
|
for (const label patchi : sensitivityPatchIDs_)
|
||||||
{
|
{
|
||||||
vectorField nf(mesh_.boundary()[patchi].nf());
|
vectorField nf(mesh_.boundary()[patchi].nf());
|
||||||
@ -262,32 +289,35 @@ boundaryVectorField& adjointEikonalSolver::distanceSensitivities()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
tmp<volTensorField> adjointEikonalSolver::getFISensitivityTerm() const
|
tmp<volTensorField> adjointEikonalSolver::getFISensitivityTerm() const
|
||||||
{
|
{
|
||||||
Info<< "Calculating distance sensitivities " << endl;
|
Info<< "Calculating distance sensitivities " << endl;
|
||||||
|
|
||||||
const volScalarField& d = RASModelVars_().d();
|
const volScalarField& d = adjointSolver_.yWall();
|
||||||
const volVectorField gradD(fvc::grad(d));
|
const volVectorField gradD(fvc::grad(d));
|
||||||
|
|
||||||
volVectorField gradDDa
|
auto gradDDa
|
||||||
(
|
(
|
||||||
IOobject
|
tmp<volVectorField>::New
|
||||||
(
|
(
|
||||||
"gradDDa",
|
IOobject
|
||||||
mesh_.time().timeName(),
|
(
|
||||||
|
"gradDDa",
|
||||||
|
mesh_.time().timeName(),
|
||||||
|
mesh_,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
mesh_,
|
mesh_,
|
||||||
IOobject::NO_READ,
|
dimensionedVector(d.dimensions()*da_.dimensions()/dimLength, Zero),
|
||||||
IOobject::AUTO_WRITE
|
patchDistMethod::patchTypes<vector>(mesh_, wallPatchIDs_)
|
||||||
),
|
)
|
||||||
mesh_,
|
|
||||||
dimensionedVector(d.dimensions()*da_.dimensions()/dimLength, Zero),
|
|
||||||
patchDistMethod::patchTypes<vector>(mesh_, wallPatchIDs_)
|
|
||||||
);
|
);
|
||||||
gradDDa = fvc::grad(d*da_);
|
gradDDa.ref() = fvc::grad(d*da_);
|
||||||
|
|
||||||
tmp<volTensorField> tdistanceSens
|
auto tdistanceSens
|
||||||
(
|
(
|
||||||
new volTensorField
|
tmp<volTensorField>::New
|
||||||
(
|
(
|
||||||
IOobject
|
IOobject
|
||||||
(
|
(
|
||||||
@ -298,20 +328,46 @@ tmp<volTensorField> adjointEikonalSolver::getFISensitivityTerm() const
|
|||||||
IOobject::AUTO_WRITE
|
IOobject::AUTO_WRITE
|
||||||
),
|
),
|
||||||
mesh_,
|
mesh_,
|
||||||
dimensionedTensor(da_.dimensions(), Zero)
|
dimensionedTensor(da_.dimensions(), Zero),
|
||||||
|
zeroGradientFvPatchField<tensor>::typeName
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
volTensorField& distanceSens = tdistanceSens.ref();
|
volTensorField& distanceSens = tdistanceSens.ref();
|
||||||
|
|
||||||
distanceSens =
|
distanceSens =
|
||||||
- 2.*da_*gradD*gradD
|
- 2.*da_*gradD*gradD
|
||||||
- epsilon_*gradD*gradDDa
|
- epsilon_*gradDDa*gradD
|
||||||
+ epsilon_*da_*d*fvc::grad(gradD);
|
// grad(gradD) is symmetric theoretically but not numerically when
|
||||||
|
// computed with the Gauss divergence theorem. The following maintains
|
||||||
|
// exactly the same behaviour as the one before the re-factoring of
|
||||||
|
// sensitivities but avoid calling the tranpose operator.
|
||||||
|
+ epsilon_*da_*d*fvc::div(fvc::interpolate(gradD)*mesh_.Sf());
|
||||||
|
distanceSens.correctBoundaryConditions();
|
||||||
|
|
||||||
return tdistanceSens;
|
return tdistanceSens;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
tmp<scalarField> adjointEikonalSolver::topologySensitivities
|
||||||
|
(
|
||||||
|
const word& designVarsName
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
const volScalarField& d = adjointSolver_.yWall();
|
||||||
|
|
||||||
|
auto tres(tmp<scalarField>::New(d.primitiveField().size(), Zero));
|
||||||
|
scalarField dSens(d.primitiveField()*da_.primitiveField());
|
||||||
|
|
||||||
|
fv::options& fvOptions(fv::options::New(this->mesh_));
|
||||||
|
sensitivityTopO::postProcessSens
|
||||||
|
(
|
||||||
|
tres.ref(), dSens, fvOptions, d.name(), designVarsName
|
||||||
|
);
|
||||||
|
|
||||||
|
return tres;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const volScalarField& adjointEikonalSolver::da()
|
const volScalarField& adjointEikonalSolver::da()
|
||||||
{
|
{
|
||||||
return da_;
|
return da_;
|
||||||
@ -320,7 +376,7 @@ const volScalarField& adjointEikonalSolver::da()
|
|||||||
|
|
||||||
tmp<volVectorField> adjointEikonalSolver::gradEikonal()
|
tmp<volVectorField> adjointEikonalSolver::gradEikonal()
|
||||||
{
|
{
|
||||||
const volScalarField& d = RASModelVars_().d();
|
const volScalarField& d = adjointSolver_.yWall();
|
||||||
volVectorField gradD(fvc::grad(d));
|
volVectorField gradD(fvc::grad(d));
|
||||||
return tmp<volVectorField>::New("gradEikonal", 2*gradD & fvc::grad(gradD));
|
return tmp<volVectorField>::New("gradEikonal", 2*gradD & fvc::grad(gradD));
|
||||||
}
|
}
|
||||||
@ -328,7 +384,6 @@ tmp<volVectorField> adjointEikonalSolver::gradEikonal()
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
} // End namespace incompressible
|
|
||||||
} // End namespace Foam
|
} // End namespace Foam
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
@ -27,7 +27,7 @@ License
|
|||||||
|
|
||||||
|
|
||||||
Class
|
Class
|
||||||
Foam::incompressible::adjointEikonalSolver
|
Foam::adjointEikonalSolver
|
||||||
|
|
||||||
Description
|
Description
|
||||||
Solver of the adjoint to the eikonal PDE
|
Solver of the adjoint to the eikonal PDE
|
||||||
@ -123,25 +123,26 @@ SourceFiles
|
|||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#ifndef adjointEikonalSolverIncompressible_H
|
#ifndef adjointEikonalSolver_H
|
||||||
#define adjointEikonalSolverIncompressible_H
|
#define adjointEikonalSolver_H
|
||||||
|
|
||||||
#include "IOdictionary.H"
|
#include "IOdictionary.H"
|
||||||
#include "incompressibleAdjointVars.H"
|
#include "volFieldsFwd.H"
|
||||||
|
#include "fvMesh.H"
|
||||||
|
#include "calculatedFvPatchField.H"
|
||||||
#include "createZeroField.H"
|
#include "createZeroField.H"
|
||||||
#include "boundaryFieldsFwd.H"
|
#include "boundaryFieldsFwd.H"
|
||||||
#include "RASModelVariables.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace incompressible
|
// Forward Declaration
|
||||||
{
|
class adjointSolver;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
Class adjointEikonalSolver Declaration
|
Class adjointEikonalSolver Declaration
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
class adjointEikonalSolver
|
class adjointEikonalSolver
|
||||||
@ -165,10 +166,7 @@ protected:
|
|||||||
|
|
||||||
dictionary dict_;
|
dictionary dict_;
|
||||||
|
|
||||||
const autoPtr<incompressible::RASModelVariables>& RASModelVars_;
|
adjointSolver& adjointSolver_;
|
||||||
|
|
||||||
autoPtr<Foam::incompressibleAdjoint::adjointRASModel>&
|
|
||||||
adjointTurbulence_;
|
|
||||||
|
|
||||||
const labelHashSet& sensitivityPatchIDs_;
|
const labelHashSet& sensitivityPatchIDs_;
|
||||||
|
|
||||||
@ -214,8 +212,7 @@ public:
|
|||||||
(
|
(
|
||||||
const fvMesh& mesh,
|
const fvMesh& mesh,
|
||||||
const dictionary& dict,
|
const dictionary& dict,
|
||||||
const autoPtr<incompressible::RASModelVariables>& RASModelVars,
|
adjointSolver& adjointSolver,
|
||||||
incompressibleAdjointVars& adjointVars,
|
|
||||||
const labelHashSet& sensitivityPatchIDs
|
const labelHashSet& sensitivityPatchIDs
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -244,6 +241,9 @@ public:
|
|||||||
//- Return the volume-based sensitivity term depending on da
|
//- Return the volume-based sensitivity term depending on da
|
||||||
tmp<volTensorField> getFISensitivityTerm() const;
|
tmp<volTensorField> getFISensitivityTerm() const;
|
||||||
|
|
||||||
|
//- Return sensitivity contribution to topology optimisation
|
||||||
|
tmp<scalarField> topologySensitivities(const word& designVarsName) const;
|
||||||
|
|
||||||
//- Return the adjoint distance field
|
//- Return the adjoint distance field
|
||||||
const volScalarField& da();
|
const volScalarField& da();
|
||||||
|
|
||||||
@ -257,7 +257,6 @@ public:
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
} // End namespace incompressible
|
|
||||||
} // End namespace Foam
|
} // End namespace Foam
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2022 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019-2021 OpenCFD Ltd.
|
Copyright (C) 2019-2021 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -27,41 +27,57 @@ License
|
|||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "adjointEikonalSolver.H"
|
||||||
#include "runTimeSelectionTables.H"
|
#include "runTimeSelectionTables.H"
|
||||||
#include "adjointSensitivityIncompressible.H"
|
#include "adjointSensitivity.H"
|
||||||
#include "boundaryAdjointContribution.H"
|
#include "adjointSolver.H"
|
||||||
#include "incompressibleAdjointSolver.H"
|
#include "designVariables.H"
|
||||||
#include "wallFvPatch.H"
|
|
||||||
#include "fvOptions.H"
|
#include "fvOptions.H"
|
||||||
|
#include "reverseLinear.H"
|
||||||
|
#include "sensitivity.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace incompressible
|
|
||||||
{
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
defineTypeNameAndDebug(adjointSensitivity, 0);
|
defineTypeNameAndDebug(adjointSensitivity, 0);
|
||||||
defineRunTimeSelectionTable(adjointSensitivity, dictionary);
|
defineRunTimeSelectionTable(adjointSensitivity, dictionary);
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
adjointSensitivity::adjointSensitivity
|
adjointSensitivity::adjointSensitivity
|
||||||
(
|
(
|
||||||
const fvMesh& mesh,
|
const fvMesh& mesh,
|
||||||
const dictionary& dict,
|
const dictionary& dict,
|
||||||
incompressibleAdjointSolver& adjointSolver
|
class adjointSolver& adjointSolver
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
sensitivity(mesh, dict),
|
sensitivity(mesh, dict),
|
||||||
derivatives_(0),
|
|
||||||
adjointSolver_(adjointSolver),
|
adjointSolver_(adjointSolver),
|
||||||
primalVars_(adjointSolver.getPrimalVars()),
|
derivatives_(0),
|
||||||
adjointVars_(adjointSolver.getAdjointVars()),
|
suffix_(word::null),
|
||||||
objectiveManager_(adjointSolver.getObjectiveManager())
|
includeDistance_
|
||||||
|
(
|
||||||
|
this->dict().getOrDefault<bool>
|
||||||
|
(
|
||||||
|
"includeDistance",
|
||||||
|
adjointSolver_.includeDistance()
|
||||||
|
)
|
||||||
|
),
|
||||||
|
eikonalSolver_(nullptr),
|
||||||
|
gradDxDbMult_(nullptr),
|
||||||
|
divDxDbMult_(nullptr),
|
||||||
|
dxdbMult_(nullptr),
|
||||||
|
dSfdbMult_(nullptr),
|
||||||
|
dnfdbMult_(nullptr),
|
||||||
|
dxdbDirectMult_(nullptr),
|
||||||
|
pointDxDbDirectMult_(nullptr),
|
||||||
|
bcDxDbMult_(nullptr),
|
||||||
|
optionsDxDbMult_(nullptr)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
@ -71,14 +87,15 @@ autoPtr<adjointSensitivity> adjointSensitivity::New
|
|||||||
(
|
(
|
||||||
const fvMesh& mesh,
|
const fvMesh& mesh,
|
||||||
const dictionary& dict,
|
const dictionary& dict,
|
||||||
incompressibleAdjointSolver& adjointSolver
|
class adjointSolver& adjointSolver
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
const word modelType(dict.get<word>("type"));
|
const word sensType =
|
||||||
|
dict.optionalSubDict(mesh.name()).get<word>("sensitivityType");
|
||||||
|
|
||||||
Info<< "adjointSensitivity type : " << modelType << endl;
|
Info<< "adjointSensitivity type : " << sensType << endl;
|
||||||
|
|
||||||
auto* ctorPtr = dictionaryConstructorTable(modelType);
|
auto* ctorPtr = dictionaryConstructorTable(sensType);
|
||||||
|
|
||||||
if (!ctorPtr)
|
if (!ctorPtr)
|
||||||
{
|
{
|
||||||
@ -86,7 +103,7 @@ autoPtr<adjointSensitivity> adjointSensitivity::New
|
|||||||
(
|
(
|
||||||
dict,
|
dict,
|
||||||
"adjointSensitivity",
|
"adjointSensitivity",
|
||||||
modelType,
|
sensType,
|
||||||
*dictionaryConstructorTablePtr_
|
*dictionaryConstructorTablePtr_
|
||||||
) << exit(FatalIOError);
|
) << exit(FatalIOError);
|
||||||
}
|
}
|
||||||
@ -100,9 +117,47 @@ autoPtr<adjointSensitivity> adjointSensitivity::New
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
const scalarField& adjointSensitivity::calculateSensitivities()
|
bool adjointSensitivity::readDict(const dictionary& dict)
|
||||||
{
|
{
|
||||||
assembleSensitivities();
|
if (sensitivity::readDict(dict))
|
||||||
|
{
|
||||||
|
// The adjoint eikonal solver requires the parameterized patches
|
||||||
|
// as an argument, if they exist. Allocation will be managed by
|
||||||
|
// derived classes that have access to them
|
||||||
|
includeDistance_ = this->dict().getOrDefault<bool>
|
||||||
|
(
|
||||||
|
"includeDistance",
|
||||||
|
adjointSolver_.includeDistance()
|
||||||
|
);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool adjointSensitivity::computeDxDbInternalField() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void adjointSensitivity::assembleSensitivities
|
||||||
|
(
|
||||||
|
autoPtr<designVariables>& designVars
|
||||||
|
)
|
||||||
|
{
|
||||||
|
derivatives_ = designVars->assembleSensitivities(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const scalarField& adjointSensitivity::calculateSensitivities
|
||||||
|
(
|
||||||
|
autoPtr<designVariables>& designVars
|
||||||
|
)
|
||||||
|
{
|
||||||
|
assembleSensitivities(designVars);
|
||||||
write(type());
|
write(type());
|
||||||
return derivatives_;
|
return derivatives_;
|
||||||
}
|
}
|
||||||
@ -116,10 +171,18 @@ const scalarField& adjointSensitivity::getSensitivities() const
|
|||||||
|
|
||||||
void adjointSensitivity::clearSensitivities()
|
void adjointSensitivity::clearSensitivities()
|
||||||
{
|
{
|
||||||
derivatives_ = scalar(0);
|
derivatives_ = Zero;
|
||||||
if (fieldSensPtr_)
|
if (fieldSensPtr_)
|
||||||
{
|
{
|
||||||
fieldSensPtr_().primitiveFieldRef() = scalar(0);
|
fieldSensPtr_().primitiveFieldRef() = Zero;
|
||||||
|
}
|
||||||
|
if (eikonalSolver_)
|
||||||
|
{
|
||||||
|
eikonalSolver_->reset();
|
||||||
|
}
|
||||||
|
if (adjointMeshMovementSolver_)
|
||||||
|
{
|
||||||
|
adjointMeshMovementSolver_->reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,51 +193,8 @@ void adjointSensitivity::write(const word& baseName)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
tmp<volTensorField> adjointSensitivity::computeGradDxDbMultiplier()
|
|
||||||
{
|
|
||||||
return adjointSolver_.computeGradDxDbMultiplier();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
tmp<volVectorField> adjointSensitivity::adjointMeshMovementSource()
|
|
||||||
{
|
|
||||||
tmp<volTensorField> tgradDxDbMult = computeGradDxDbMultiplier();
|
|
||||||
volTensorField& gradDxDbMult = tgradDxDbMult.ref();
|
|
||||||
|
|
||||||
tmp<volVectorField> tadjointMeshMovementSource
|
|
||||||
(
|
|
||||||
new volVectorField
|
|
||||||
(
|
|
||||||
IOobject
|
|
||||||
(
|
|
||||||
"adjointMeshMovementSource",
|
|
||||||
mesh_.time().timeName(),
|
|
||||||
mesh_,
|
|
||||||
IOobject::NO_READ,
|
|
||||||
IOobject::NO_WRITE
|
|
||||||
),
|
|
||||||
mesh_,
|
|
||||||
dimensionedVector(gradDxDbMult.dimensions()/dimLength, Zero)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
volVectorField& source = tadjointMeshMovementSource.ref();
|
|
||||||
|
|
||||||
source -= fvc::div(gradDxDbMult.T());
|
|
||||||
|
|
||||||
// Terms from fvOptions
|
|
||||||
fv::options::New(this->mesh_).postProcessSens
|
|
||||||
(
|
|
||||||
source.primitiveFieldRef(), adjointVars_.solverName()
|
|
||||||
);
|
|
||||||
|
|
||||||
return (tadjointMeshMovementSource);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
} // End namespace incompressible
|
|
||||||
} // End namespace Foam
|
} // End namespace Foam
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,299 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
|
Copyright (C) 2019 OpenCFD Ltd.
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::adjointSensitivity
|
||||||
|
|
||||||
|
Description
|
||||||
|
Abstract base class for adjoint-based sensitivities
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
adjointSensitivity.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef adjointSensitivityIncompressible_H
|
||||||
|
#define adjointSensitivityIncompressible_H
|
||||||
|
|
||||||
|
#include "boundaryFieldsFwd.H"
|
||||||
|
#include "adjointEikonalSolver.H"
|
||||||
|
#include "adjointMeshMovementSolver.H"
|
||||||
|
#include "sensitivity.H"
|
||||||
|
#include "volFieldsFwd.H"
|
||||||
|
#include "wallFvPatch.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// Forward declaration
|
||||||
|
class adjointSolver;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class adjointSensitivity Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class adjointSensitivity
|
||||||
|
:
|
||||||
|
public sensitivity
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
|
||||||
|
// Protected data
|
||||||
|
|
||||||
|
//- Reference to the underlaying adjoint solver
|
||||||
|
adjointSolver& adjointSolver_;
|
||||||
|
|
||||||
|
//- The sensitivity derivative values
|
||||||
|
scalarField derivatives_;
|
||||||
|
|
||||||
|
//- Append this word to files related to the sensitivities
|
||||||
|
word suffix_;
|
||||||
|
|
||||||
|
//- Include distance variation in sensitivity computations
|
||||||
|
bool includeDistance_;
|
||||||
|
|
||||||
|
//- Adjoint eikonal equation solver
|
||||||
|
autoPtr<adjointEikonalSolver> eikonalSolver_;
|
||||||
|
|
||||||
|
//- Adjoint grid displacement solver
|
||||||
|
autoPtr<adjointMeshMovementSolver> adjointMeshMovementSolver_;
|
||||||
|
|
||||||
|
// Fields to accumulated through the adjoint solver
|
||||||
|
|
||||||
|
// Shape optimisation
|
||||||
|
|
||||||
|
//- Multiplier of grad(dx/b)
|
||||||
|
autoPtr<volTensorField> gradDxDbMult_;
|
||||||
|
|
||||||
|
//- Multiplier of div(dx/db)
|
||||||
|
autoPtr<scalarField> divDxDbMult_;
|
||||||
|
|
||||||
|
//- Multiplier of face dx/db
|
||||||
|
// The term that multiplies the adjoint-related part of the
|
||||||
|
// sensitivities in the (E)SI approach
|
||||||
|
autoPtr<boundaryVectorField> dxdbMult_;
|
||||||
|
|
||||||
|
//- Multiplier of dSf/db
|
||||||
|
autoPtr<boundaryVectorField> dSfdbMult_;
|
||||||
|
|
||||||
|
//- Multiplier of dnf/db
|
||||||
|
autoPtr<boundaryVectorField> dnfdbMult_;
|
||||||
|
|
||||||
|
//- Multiplier of dCf/db, found in the objective function
|
||||||
|
autoPtr<boundaryVectorField> dxdbDirectMult_;
|
||||||
|
|
||||||
|
//- Multiplier of dx/db computed at points,
|
||||||
|
//- found in the objective function
|
||||||
|
autoPtr<pointBoundaryVectorField> pointDxDbDirectMult_;
|
||||||
|
|
||||||
|
//- Multiplier of dx/db, coming from boundary conditions that
|
||||||
|
//- depend on the geometry, like rotatingWallVelocity
|
||||||
|
autoPtr<boundaryVectorField> bcDxDbMult_;
|
||||||
|
|
||||||
|
//- dx/db multiplier coming from fvOptions
|
||||||
|
autoPtr<vectorField> optionsDxDbMult_;
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
//- No copy construct
|
||||||
|
adjointSensitivity(const adjointSensitivity&) = delete;
|
||||||
|
|
||||||
|
//- No copy assignment
|
||||||
|
void operator=(const adjointSensitivity&) = delete;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
TypeName("adjointSensitivity");
|
||||||
|
|
||||||
|
|
||||||
|
// Declare run-time constructor selection table
|
||||||
|
|
||||||
|
declareRunTimeSelectionTable
|
||||||
|
(
|
||||||
|
autoPtr,
|
||||||
|
adjointSensitivity,
|
||||||
|
dictionary,
|
||||||
|
(
|
||||||
|
const fvMesh& mesh,
|
||||||
|
const dictionary& dict,
|
||||||
|
adjointSolver& adjointSolver
|
||||||
|
),
|
||||||
|
(
|
||||||
|
mesh,
|
||||||
|
dict,
|
||||||
|
adjointSolver
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct from components
|
||||||
|
adjointSensitivity
|
||||||
|
(
|
||||||
|
const fvMesh& mesh,
|
||||||
|
const dictionary& dict,
|
||||||
|
adjointSolver& adjointSolver
|
||||||
|
);
|
||||||
|
|
||||||
|
// Selectors
|
||||||
|
|
||||||
|
//- Return a reference to the selected turbulence model
|
||||||
|
static autoPtr<adjointSensitivity> New
|
||||||
|
(
|
||||||
|
const fvMesh& mesh,
|
||||||
|
const dictionary& dict,
|
||||||
|
adjointSolver& adjointSolver
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
//- Destructor
|
||||||
|
virtual ~adjointSensitivity() = default;
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
//- Read dictionary if changed
|
||||||
|
virtual bool readDict(const dictionary& dict);
|
||||||
|
|
||||||
|
//- Const access to adjoint solver
|
||||||
|
inline const adjointSolver& getAdjointSolver() const
|
||||||
|
{
|
||||||
|
return adjointSolver_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Non-const access to adjoint solver
|
||||||
|
inline adjointSolver& getAdjointSolver()
|
||||||
|
{
|
||||||
|
return adjointSolver_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Should the adjoint eikonal PDE should be solved
|
||||||
|
inline bool includeDistance() const
|
||||||
|
{
|
||||||
|
return includeDistance_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Return the adjoint eikonal solver
|
||||||
|
inline autoPtr<adjointEikonalSolver>& getAdjointEikonalSolver()
|
||||||
|
{
|
||||||
|
return eikonalSolver_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Return the adjoint eikonal solver
|
||||||
|
inline autoPtr<adjointMeshMovementSolver>&
|
||||||
|
getAdjointMeshMovementSolver()
|
||||||
|
{
|
||||||
|
return adjointMeshMovementSolver_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Set suffix
|
||||||
|
inline void setSuffix(const word& suffix)
|
||||||
|
{
|
||||||
|
suffix_ = suffix;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Get suffix
|
||||||
|
inline const word& getSuffix() const
|
||||||
|
{
|
||||||
|
return suffix_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Should the parameterization compute the internalField of dxdb
|
||||||
|
virtual bool computeDxDbInternalField() const;
|
||||||
|
|
||||||
|
//- Accumulate sensitivity integrands
|
||||||
|
// Corresponds to the flow and adjoint part of the sensitivities
|
||||||
|
virtual void accumulateIntegrand(const scalar dt) = 0;
|
||||||
|
|
||||||
|
//- Assemble sensitivities
|
||||||
|
// Adds the geometric part of the sensitivities
|
||||||
|
virtual void assembleSensitivities
|
||||||
|
(
|
||||||
|
autoPtr<designVariables>& designVars
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Calculates and returns sensitivity fields.
|
||||||
|
// Used with optimisation libraries
|
||||||
|
virtual const scalarField& calculateSensitivities
|
||||||
|
(
|
||||||
|
autoPtr<designVariables>& designVars
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Returns the sensitivity fields
|
||||||
|
// Assumes it has already been updated/computed
|
||||||
|
const scalarField& getSensitivities() const;
|
||||||
|
|
||||||
|
//- Zero sensitivity fields and their constituents
|
||||||
|
virtual void clearSensitivities();
|
||||||
|
|
||||||
|
//- Write sensitivity fields.
|
||||||
|
// If valid, copies boundaryFields to volFields and writes them.
|
||||||
|
// Virtual to be reimplemented by control points-based methods
|
||||||
|
// (Bezier, RBF) which do not need to write fields
|
||||||
|
virtual void write(const word& baseName = word::null);
|
||||||
|
|
||||||
|
// Access functions to multipliers
|
||||||
|
|
||||||
|
// Shape optimisation
|
||||||
|
|
||||||
|
inline const autoPtr<volTensorField>& gradDxDbMult() const;
|
||||||
|
inline autoPtr<volTensorField>& gradDxDbMult();
|
||||||
|
inline const autoPtr<scalarField>& divDxDbMult() const;
|
||||||
|
inline const autoPtr<boundaryVectorField>& dxdbMult() const;
|
||||||
|
inline const autoPtr<boundaryVectorField>& dSfdbMult() const;
|
||||||
|
inline const autoPtr<boundaryVectorField>& dnfdbMult() const;
|
||||||
|
inline const autoPtr<boundaryVectorField>&
|
||||||
|
dxdbDirectMult() const;
|
||||||
|
inline const autoPtr<pointBoundaryVectorField>&
|
||||||
|
pointDxDbDirectMult() const;
|
||||||
|
inline const autoPtr<boundaryVectorField>& bcDxDbMult() const;
|
||||||
|
inline const autoPtr<vectorField>& optionsDxDbMult() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#include "adjointSensitivityI.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,96 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2023 PCOpt/NTUA
|
||||||
|
Copyright (C) 2023 FOSS GP
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <Foam::http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
inline const Foam::autoPtr<Foam::volTensorField>&
|
||||||
|
Foam::adjointSensitivity::gradDxDbMult() const
|
||||||
|
{
|
||||||
|
return gradDxDbMult_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline Foam::autoPtr<Foam::volTensorField>&
|
||||||
|
Foam::adjointSensitivity::gradDxDbMult()
|
||||||
|
{
|
||||||
|
return gradDxDbMult_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const Foam::autoPtr<Foam::scalarField>&
|
||||||
|
Foam::adjointSensitivity::divDxDbMult() const
|
||||||
|
{
|
||||||
|
return divDxDbMult_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::autoPtr<Foam::boundaryVectorField>&
|
||||||
|
Foam::adjointSensitivity::dxdbMult() const
|
||||||
|
{
|
||||||
|
return dxdbMult_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline const Foam::autoPtr<Foam::boundaryVectorField>&
|
||||||
|
Foam::adjointSensitivity::dSfdbMult() const
|
||||||
|
{
|
||||||
|
return dSfdbMult_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const Foam::autoPtr<Foam::boundaryVectorField>&
|
||||||
|
Foam::adjointSensitivity::dnfdbMult() const
|
||||||
|
{
|
||||||
|
return dnfdbMult_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const Foam::autoPtr<Foam::boundaryVectorField>&
|
||||||
|
Foam::adjointSensitivity::dxdbDirectMult() const
|
||||||
|
{
|
||||||
|
return dxdbDirectMult_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const Foam::autoPtr<Foam::pointBoundaryVectorField>&
|
||||||
|
Foam::adjointSensitivity::pointDxDbDirectMult() const
|
||||||
|
{
|
||||||
|
return pointDxDbDirectMult_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const Foam::autoPtr<Foam::boundaryVectorField>&
|
||||||
|
Foam::adjointSensitivity::bcDxDbMult() const
|
||||||
|
{
|
||||||
|
return bcDxDbMult_;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline const Foam::autoPtr<Foam::vectorField>&
|
||||||
|
Foam::adjointSensitivity::optionsDxDbMult() const
|
||||||
|
{
|
||||||
|
return optionsDxDbMult_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -27,7 +27,8 @@ License
|
|||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "sensitivityMultipleIncompressible.H"
|
#include "adjointSensitivity.H"
|
||||||
|
#include "sensitivityMultiple.H"
|
||||||
#include "addToRunTimeSelectionTable.H"
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
@ -35,9 +36,6 @@ License
|
|||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace incompressible
|
|
||||||
{
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
defineTypeNameAndDebug(sensitivityMultiple, 0);
|
defineTypeNameAndDebug(sensitivityMultiple, 0);
|
||||||
@ -54,11 +52,11 @@ sensitivityMultiple::sensitivityMultiple
|
|||||||
(
|
(
|
||||||
const fvMesh& mesh,
|
const fvMesh& mesh,
|
||||||
const dictionary& dict,
|
const dictionary& dict,
|
||||||
incompressibleAdjointSolver& adjointSolver
|
adjointSolver& adjointSolver
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
adjointSensitivity(mesh, dict, adjointSolver),
|
adjointSensitivity(mesh, dict, adjointSolver),
|
||||||
sensTypes_(dict.subDict("sensTypes").toc()),
|
sensTypes_(this->dict().get<wordList>("sensitivityTypes")),
|
||||||
sens_(sensTypes_.size())
|
sens_(sensTypes_.size())
|
||||||
{
|
{
|
||||||
forAll(sensTypes_, sI)
|
forAll(sensTypes_, sI)
|
||||||
@ -69,10 +67,11 @@ sensitivityMultiple::sensitivityMultiple
|
|||||||
adjointSensitivity::New
|
adjointSensitivity::New
|
||||||
(
|
(
|
||||||
mesh,
|
mesh,
|
||||||
dict.subDict("sensTypes").subDict(sensTypes_[sI]),
|
this->dict().subDict(sensTypes_[sI]),
|
||||||
adjointSolver
|
adjointSolver
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
sens_[sI].setSuffix(sensTypes_[sI]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,14 +80,11 @@ sensitivityMultiple::sensitivityMultiple
|
|||||||
|
|
||||||
bool sensitivityMultiple::readDict(const dictionary& dict)
|
bool sensitivityMultiple::readDict(const dictionary& dict)
|
||||||
{
|
{
|
||||||
if (sensitivity::readDict(dict))
|
if (adjointSensitivity::readDict(dict))
|
||||||
{
|
{
|
||||||
forAll(sens_, sI)
|
forAll(sens_, sI)
|
||||||
{
|
{
|
||||||
sens_[sI].readDict
|
sens_[sI].readDict(dict.subDict(sensTypes_[sI]));
|
||||||
(
|
|
||||||
dict.subDict("sensTypes").subDict(sensTypes_[sI])
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -107,21 +103,27 @@ void sensitivityMultiple::accumulateIntegrand(const scalar dt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void sensitivityMultiple::assembleSensitivities()
|
void sensitivityMultiple::assembleSensitivities
|
||||||
|
(
|
||||||
|
autoPtr<designVariables>& designVars
|
||||||
|
)
|
||||||
{
|
{
|
||||||
forAll(sens_, sI)
|
forAll(sens_, sI)
|
||||||
{
|
{
|
||||||
sens_[sI].assembleSensitivities();
|
sens_[sI].assembleSensitivities(designVars);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const scalarField& sensitivityMultiple::calculateSensitivities()
|
const scalarField& sensitivityMultiple::calculateSensitivities
|
||||||
|
(
|
||||||
|
autoPtr<designVariables>& designVars
|
||||||
|
)
|
||||||
{
|
{
|
||||||
forAll(sens_, sI)
|
forAll(sens_, sI)
|
||||||
{
|
{
|
||||||
Info<< "Computing sensitivities " << sensTypes_[sI] << endl;
|
Info<< "Computing sensitivities " << sensTypes_[sI] << endl;
|
||||||
derivatives_ = sens_[sI].calculateSensitivities();
|
sens_[sI].calculateSensitivities(designVars);
|
||||||
}
|
}
|
||||||
write(type());
|
write(type());
|
||||||
|
|
||||||
@ -149,7 +151,6 @@ void sensitivityMultiple::write(const word& baseName)
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
} // End namespace incompressible
|
|
||||||
} // End namespace Foam
|
} // End namespace Foam
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
@ -26,7 +26,7 @@ License
|
|||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Class
|
Class
|
||||||
Foam::incompressible::sensitivityMultiple
|
Foam::sensitivityMultiple
|
||||||
|
|
||||||
Description
|
Description
|
||||||
Calculation of adjoint based sensitivities of multiple types
|
Calculation of adjoint based sensitivities of multiple types
|
||||||
@ -36,19 +36,16 @@ SourceFiles
|
|||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#ifndef sensitivityMultipleIncompressible_H
|
#ifndef sensitivityMultiple_H
|
||||||
#define sensitivityMultipleIncompressible_H
|
#define sensitivityMultiple_H
|
||||||
|
|
||||||
#include "adjointSensitivityIncompressible.H"
|
#include "adjointSensitivity.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace incompressible
|
|
||||||
{
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
Class sensitivityMultiple Declaration
|
Class sensitivityMultiple Declaration
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
@ -90,7 +87,7 @@ public:
|
|||||||
(
|
(
|
||||||
const fvMesh& mesh,
|
const fvMesh& mesh,
|
||||||
const dictionary& dict,
|
const dictionary& dict,
|
||||||
incompressibleAdjointSolver& adjointSolver
|
adjointSolver& adjointSolver
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@ -107,10 +104,13 @@ public:
|
|||||||
virtual void accumulateIntegrand(const scalar dt);
|
virtual void accumulateIntegrand(const scalar dt);
|
||||||
|
|
||||||
//- Assemble sensitivities
|
//- Assemble sensitivities
|
||||||
virtual void assembleSensitivities();
|
virtual void assembleSensitivities(autoPtr<designVariables>& designVars);
|
||||||
|
|
||||||
//- Calculates sensitivities at wall surface points
|
//- Calculates sensitivities at wall surface points
|
||||||
const scalarField& calculateSensitivities();
|
const scalarField& calculateSensitivities
|
||||||
|
(
|
||||||
|
autoPtr<designVariables>& designVars
|
||||||
|
);
|
||||||
|
|
||||||
//- Zero sensitivity fields and their constituents
|
//- Zero sensitivity fields and their constituents
|
||||||
virtual void clearSensitivities();
|
virtual void clearSensitivities();
|
||||||
@ -122,7 +122,6 @@ public:
|
|||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
} // End namespace incompressible
|
|
||||||
} // End namespace Foam
|
} // End namespace Foam
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
@ -0,0 +1,168 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
|
Copyright (C) 2019-2020 OpenCFD Ltd.
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
ESITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "boundaryFieldsFwd.H"
|
||||||
|
#include "sensitivityShapeESI.H"
|
||||||
|
#include "adjointSolver.H"
|
||||||
|
#include "ShapeSensitivitiesBase.H"
|
||||||
|
#include "fvOptions.H"
|
||||||
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
defineTypeNameAndDebug(sensitivityShapeESI, 0);
|
||||||
|
addToRunTimeSelectionTable
|
||||||
|
(
|
||||||
|
adjointSensitivity, sensitivityShapeESI, dictionary
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
void sensitivityShapeESI::computeDxDbMult()
|
||||||
|
{
|
||||||
|
if (eikonalSolver_)
|
||||||
|
{
|
||||||
|
eikonalSolver_->solve();
|
||||||
|
}
|
||||||
|
if (adjointMeshMovementSolver_)
|
||||||
|
{
|
||||||
|
adjointMeshMovementSolver_->solve();
|
||||||
|
boundaryVectorField& meshMovementSens =
|
||||||
|
adjointMeshMovementSolver_->meshMovementSensitivities();
|
||||||
|
PtrList<objective>& functions =
|
||||||
|
adjointSolver_.getObjectiveManager().getObjectiveFunctions();
|
||||||
|
for (const label patchI : geometryVariationIntegrationPatches())
|
||||||
|
{
|
||||||
|
const fvPatch& patch = mesh_.boundary()[patchI];
|
||||||
|
const scalarField& magSf = patch.magSf();
|
||||||
|
const vectorField& Sf = patch.Sf();
|
||||||
|
dxdbMult_()[patchI] = meshMovementSens[patchI]*magSf;
|
||||||
|
for (objective& func : functions)
|
||||||
|
{
|
||||||
|
if (func.hasDivDxDbMult())
|
||||||
|
{
|
||||||
|
Info<< func.objectiveName() << " " << patch.name() << endl;
|
||||||
|
dxdbDirectMult_()[patchI] +=
|
||||||
|
func.weight()
|
||||||
|
*func.divDxDbMultiplier().boundaryField()[patchI]
|
||||||
|
*Sf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (const label patchI : geometryVariationIntegrationPatches())
|
||||||
|
{
|
||||||
|
const vectorField& Sf = mesh_.boundary()[patchI].Sf();
|
||||||
|
dxdbMult_()[patchI] += Sf & gradDxDbMult_().boundaryField()[patchI];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
sensitivityShapeESI::sensitivityShapeESI
|
||||||
|
(
|
||||||
|
const fvMesh& mesh,
|
||||||
|
const dictionary& dict,
|
||||||
|
adjointSolver& adjointSolver
|
||||||
|
)
|
||||||
|
:
|
||||||
|
ShapeSensitivitiesBase(mesh, dict, adjointSolver)
|
||||||
|
{
|
||||||
|
dxdbMult_.reset(createZeroBoundaryPtr<vector>(mesh_));
|
||||||
|
// The boundary values of divDxDbMultiplier are stored in dxdbDirectMult
|
||||||
|
// after applying the Gauss divergence theorem.
|
||||||
|
// Allocate dxdbDirectMult if necessary
|
||||||
|
if (hasMultiplier(&objective::hasDivDxDbMult))
|
||||||
|
{
|
||||||
|
dxdbDirectMult_.reset(createZeroBoundaryPtr<vector>(mesh_));
|
||||||
|
}
|
||||||
|
if (dict.getOrDefault<bool>("includeMeshMovement", true))
|
||||||
|
{
|
||||||
|
adjointMeshMovementSolver_.reset
|
||||||
|
(
|
||||||
|
new adjointMeshMovementSolver(mesh, dict, *this)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
bool Foam::sensitivityShapeESI::readDict(const dictionary& dict)
|
||||||
|
{
|
||||||
|
if (ShapeSensitivitiesBase::readDict(dict))
|
||||||
|
{
|
||||||
|
bool includeMeshMovement =
|
||||||
|
dict.getOrDefault<bool>("includeMeshMovement", true);
|
||||||
|
|
||||||
|
if (includeMeshMovement)
|
||||||
|
{
|
||||||
|
if (adjointMeshMovementSolver_)
|
||||||
|
{
|
||||||
|
adjointMeshMovementSolver_->readDict(dict);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
adjointMeshMovementSolver_.reset
|
||||||
|
(
|
||||||
|
new adjointMeshMovementSolver(mesh_, dict, *this)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void sensitivityShapeESI::assembleSensitivities
|
||||||
|
(
|
||||||
|
autoPtr<designVariables>& designVars
|
||||||
|
)
|
||||||
|
{
|
||||||
|
computeDxDbMult();
|
||||||
|
if (designVars)
|
||||||
|
{
|
||||||
|
adjointSensitivity::assembleSensitivities(designVars);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2019 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
Copyright (C) 2019 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -19,29 +19,30 @@ License
|
|||||||
|
|
||||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
ESITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
for more details.
|
for more details.
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
Class
|
Class
|
||||||
Foam::optMeshMovementBezier
|
Foam::sensitivityShapeESI
|
||||||
|
|
||||||
Description
|
Description
|
||||||
Converts NURBS control points update to actual mesh movement
|
Class for computing sensitivity derivatives using the Enhanced Surface
|
||||||
|
Integral (E-SI) formulation, when a parameterization scheme is inluded
|
||||||
|
through the design variables. Sensitivity maps are implemented in class
|
||||||
|
sensitivitySurfacePoints
|
||||||
|
|
||||||
SourceFiles
|
SourceFiles
|
||||||
optMeshMovementBezier.C
|
sensitivityShapeESI.C
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#ifndef optMeshMovementBezier_H
|
#ifndef sensitivityShapeESI_H
|
||||||
#define optMeshMovementBezier_H
|
#define sensitivityShapeESI_H
|
||||||
|
|
||||||
#include "optMeshMovement.H"
|
#include "ShapeSensitivitiesBase.H"
|
||||||
#include "Bezier.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -49,30 +50,19 @@ namespace Foam
|
|||||||
{
|
{
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
Class optMeshMovementBezier Declaration
|
Class sensitivityShapeESI Declaration
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
class optMeshMovementBezier
|
class sensitivityShapeESI
|
||||||
:
|
:
|
||||||
public optMeshMovement
|
public ShapeSensitivitiesBase
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Protected data
|
|
||||||
|
|
||||||
//- Parameterization based on NURBS curves
|
|
||||||
Bezier Bezier_;
|
|
||||||
|
|
||||||
//- Boundary movement due to change of NURBS control points
|
|
||||||
pointVectorField dx_;
|
|
||||||
|
|
||||||
//- Cumulative change of control points
|
|
||||||
vectorField cumulativeChange_;
|
|
||||||
|
|
||||||
|
|
||||||
// Protected Member Functions
|
// Protected Member Functions
|
||||||
|
|
||||||
void computeBoundaryMovement(const scalarField& correction);
|
//- Compute dxdbMult from its various components
|
||||||
|
void computeDxDbMult();
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@ -80,43 +70,45 @@ private:
|
|||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
//- No copy construct
|
//- No copy construct
|
||||||
optMeshMovementBezier(const optMeshMovementBezier&) = delete;
|
sensitivityShapeESI(const sensitivityShapeESI&) = delete;
|
||||||
|
|
||||||
//- No copy assignment
|
//- No copy assignment
|
||||||
void operator=(const optMeshMovementBezier&) = delete;
|
void operator=(const sensitivityShapeESI&) = delete;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//- Runtime type information
|
//- Runtime type information
|
||||||
TypeName("Bezier");
|
TypeName("shapeESI");
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
//- Construct from components
|
//- Construct from components
|
||||||
optMeshMovementBezier
|
sensitivityShapeESI
|
||||||
(
|
(
|
||||||
fvMesh& mesh,
|
const fvMesh& mesh,
|
||||||
const dictionary& dict,
|
const dictionary& dict,
|
||||||
const labelList& patchIDs
|
adjointSolver& adjointSolver
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
//- Destructor
|
//- Destructor
|
||||||
virtual ~optMeshMovementBezier() = default;
|
virtual ~sensitivityShapeESI() = default;
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
//- Calculates surface mesh movement
|
//- Read dict if changed
|
||||||
void moveMesh();
|
virtual bool readDict(const dictionary& dict);
|
||||||
|
|
||||||
//- Compute eta value based on max displacement
|
//- Assemble sensitivities
|
||||||
virtual scalar computeEta(const scalarField& correction);
|
// Solve the adjoint eikonal PDE and the adjoint grid displacement PDE,
|
||||||
|
// if needed, and assemble the sensitivities
|
||||||
//- Return active design variables
|
virtual void assembleSensitivities
|
||||||
virtual labelList getActiveDesignVariables() const;
|
(
|
||||||
|
autoPtr<designVariables>& designVars
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,88 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
|
Copyright (C) 2019-2020 OpenCFD Ltd.
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "adjointSensitivity.H"
|
||||||
|
#include "sensitivityShapeFI.H"
|
||||||
|
#include "adjointSolver.H"
|
||||||
|
#include "fvOptions.H"
|
||||||
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
defineTypeNameAndDebug(sensitivityShapeFI, 0);
|
||||||
|
addToRunTimeSelectionTable
|
||||||
|
(
|
||||||
|
adjointSensitivity, sensitivityShapeFI, dictionary
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
sensitivityShapeFI::sensitivityShapeFI
|
||||||
|
(
|
||||||
|
const fvMesh& mesh,
|
||||||
|
const dictionary& dict,
|
||||||
|
adjointSolver& adjointSolver
|
||||||
|
)
|
||||||
|
:
|
||||||
|
ShapeSensitivitiesBase(mesh, dict, adjointSolver)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
bool sensitivityShapeFI::computeDxDbInternalField() const
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void sensitivityShapeFI::assembleSensitivities
|
||||||
|
(
|
||||||
|
autoPtr<designVariables>& designVars
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (eikonalSolver_)
|
||||||
|
{
|
||||||
|
eikonalSolver_->solve();
|
||||||
|
}
|
||||||
|
adjointSensitivity::assembleSensitivities(designVars);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2019 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
Copyright (C) 2019 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -26,73 +26,79 @@ License
|
|||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Class
|
Class
|
||||||
Foam::optMeshMovementNULL
|
Foam::sensitivityShapeFI
|
||||||
|
|
||||||
Description
|
Description
|
||||||
A dummy optMeshMovement object
|
Class for computing Field Integral (FI)-based sensitivity derivatives
|
||||||
|
|
||||||
SourceFiles
|
SourceFiles
|
||||||
optMeshMovementNULL.C
|
sensitivityShapeFI.C
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#ifndef optMeshMovementNULL_H
|
#ifndef sensitivityShapeFI_H
|
||||||
#define optMeshMovementNULL_H
|
#define sensitivityShapeFI_H
|
||||||
|
|
||||||
#include "optMeshMovement.H"
|
#include "ShapeSensitivitiesBase.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
Class optMeshMovementNULL Declaration
|
Class sensitivityShapeFI Declaration
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
class optMeshMovementNULL
|
class sensitivityShapeFI
|
||||||
:
|
:
|
||||||
public optMeshMovement
|
public ShapeSensitivitiesBase
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
//- No copy construct
|
//- No copy construct
|
||||||
optMeshMovementNULL(const optMeshMovementNULL&) = delete;
|
sensitivityShapeFI(const sensitivityShapeFI&) = delete;
|
||||||
|
|
||||||
//- No copy assignment
|
//- No copy assignment
|
||||||
void operator=(const optMeshMovementNULL&) = delete;
|
void operator=(const sensitivityShapeFI&) = delete;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//- Runtime type information
|
//- Runtime type information
|
||||||
TypeName("none");
|
TypeName("shapeFI");
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
//- Construct from components
|
//- Construct from components
|
||||||
optMeshMovementNULL
|
sensitivityShapeFI
|
||||||
(
|
(
|
||||||
fvMesh& mesh,
|
const fvMesh& mesh,
|
||||||
const dictionary& dict,
|
const dictionary& dict,
|
||||||
const labelList& patchIDs
|
adjointSolver& adjointSolver
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
//- Destructor
|
//- Destructor
|
||||||
virtual ~optMeshMovementNULL() = default;
|
virtual ~sensitivityShapeFI() = default;
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
//- Calculates surface mesh movement
|
//- Should the parameterization compute the internalField of dxdb
|
||||||
void moveMesh();
|
virtual bool computeDxDbInternalField() const;
|
||||||
|
|
||||||
//- Compute eta value based on max displacement
|
//- Assemble sensitivities
|
||||||
virtual scalar computeEta(const scalarField& correction);
|
// Solve the adjoint eikonal PDE, if needed, and calls the assembles
|
||||||
|
// the sensitivities
|
||||||
|
virtual void assembleSensitivities
|
||||||
|
(
|
||||||
|
autoPtr<designVariables>& designVars
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -5,9 +5,9 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2022 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019-2020 OpenCFD Ltd.
|
Copyright (C) 2019 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -27,133 +27,145 @@ License
|
|||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "adjointMeshMovementSolverIncompressible.H"
|
#include "adjointMeshMovementSolver.H"
|
||||||
#include "incompressibleAdjointSolver.H"
|
#include "adjointEikonalSolver.H"
|
||||||
#include "fixedValueFvPatchFields.H"
|
#include "adjointSolver.H"
|
||||||
#include "subCycleTime.H"
|
#include "fvc.H"
|
||||||
|
#include "fvm.H"
|
||||||
|
#include "ShapeSensitivitiesBase.H"
|
||||||
|
#include "reverseLinear.H"
|
||||||
|
#include "volFieldsFwd.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace incompressible
|
|
||||||
{
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
defineTypeNameAndDebug(adjointMeshMovementSolver, 0);
|
defineTypeNameAndDebug(adjointMeshMovementSolver, 0);
|
||||||
|
|
||||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
// * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
void adjointMeshMovementSolver::read()
|
void adjointMeshMovementSolver::read()
|
||||||
{
|
{
|
||||||
nLaplaceIters_ = dict_.getOrDefault<label>("iters", 1000);
|
iters_ = dict_.getOrDefault<label>("iters", 1000);
|
||||||
tolerance_ = dict_.getOrDefault<scalar>("tolerance", 1e-6);
|
tolerance_ = dict_.getOrDefault<scalar>("tolerance", 1.e-06);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
void adjointMeshMovementSolver::setSource()
|
||||||
|
{
|
||||||
|
volTensorField& gradDxDbMult = adjointSensitivity_.gradDxDbMult()();
|
||||||
|
|
||||||
|
// Add part related to the adjoint eikaonal equation, if necessary
|
||||||
|
const autoPtr<adjointEikonalSolver>& eikonalSolver =
|
||||||
|
adjointSensitivity_.getAdjointEikonalSolver();
|
||||||
|
if (eikonalSolver)
|
||||||
|
{
|
||||||
|
gradDxDbMult += eikonalSolver->getFISensitivityTerm();
|
||||||
|
}
|
||||||
|
|
||||||
|
source_ -=
|
||||||
|
fvc::div
|
||||||
|
(
|
||||||
|
mesh_.Sf()
|
||||||
|
& reverseLinear<tensor>(mesh_).interpolate(gradDxDbMult)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Terms from objectives defined in (part of the) internal field
|
||||||
|
PtrList<objective>& functions =
|
||||||
|
adjointSensitivity_.getAdjointSolver().getObjectiveManager().
|
||||||
|
getObjectiveFunctions();
|
||||||
|
for (objective& func : functions)
|
||||||
|
{
|
||||||
|
if (func.hasDivDxDbMult())
|
||||||
|
{
|
||||||
|
source_ -= func.weight()*fvc::grad(func.divDxDbMultiplier());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Terms from fvOptions
|
||||||
|
source_.primitiveFieldRef() += adjointSensitivity_.optionsDxDbMult()();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
adjointMeshMovementSolver::adjointMeshMovementSolver
|
adjointMeshMovementSolver::adjointMeshMovementSolver
|
||||||
(
|
(
|
||||||
const fvMesh& mesh,
|
const fvMesh& mesh,
|
||||||
const dictionary& dict,
|
const dictionary& dict,
|
||||||
Foam::incompressible::adjointSensitivity& adjointSensitivity,
|
ShapeSensitivitiesBase& adjointSensitivity
|
||||||
const labelHashSet& sensitivityPatchIDs,
|
|
||||||
const autoPtr<adjointEikonalSolver>& adjointEikonalSolverPtr
|
|
||||||
)
|
)
|
||||||
:
|
:
|
||||||
mesh_(mesh),
|
mesh_(mesh),
|
||||||
dict_(dict.subOrEmptyDict("adjointMeshMovementSolver")),
|
dict_(dict.subOrEmptyDict("adjointMeshMovementSolver")),
|
||||||
|
meshMovementSensPtr_(createZeroBoundaryPtr<vector>(mesh)),
|
||||||
adjointSensitivity_(adjointSensitivity),
|
adjointSensitivity_(adjointSensitivity),
|
||||||
sensitivityPatchIDs_(sensitivityPatchIDs),
|
|
||||||
nLaplaceIters_(-1),
|
|
||||||
tolerance_(-1),
|
|
||||||
ma_
|
ma_
|
||||||
(
|
(
|
||||||
IOobject
|
variablesSet::autoCreateMeshMovementField
|
||||||
(
|
(
|
||||||
word
|
mesh_,
|
||||||
(
|
adjointSensitivity.getAdjointSolver().useSolverNameForFields()
|
||||||
adjointSensitivity.adjointVars().useSolverNameForFields()
|
? ("ma" + adjointSensitivity.getAdjointSolver().solverName())
|
||||||
? "ma" + adjointSensitivity.adjointSolver().solverName()
|
: "ma",
|
||||||
: "ma"
|
adjointSensitivity.getAdjointSolver().maDimensions()
|
||||||
),
|
)
|
||||||
mesh.time().timeName(),
|
|
||||||
mesh,
|
|
||||||
IOobject::READ_IF_PRESENT,
|
|
||||||
IOobject::AUTO_WRITE
|
|
||||||
),
|
|
||||||
mesh,
|
|
||||||
dimensionedVector(pow3(dimLength/dimTime), Zero),
|
|
||||||
fixedValueFvPatchVectorField::typeName
|
|
||||||
),
|
),
|
||||||
source_
|
source_
|
||||||
(
|
(
|
||||||
IOobject
|
IOobject
|
||||||
(
|
(
|
||||||
"sourceAdjointMeshMovement",
|
"sourceadjointMeshMovement",
|
||||||
mesh_.time().timeName(),
|
mesh_.time().timeName(),
|
||||||
mesh_,
|
mesh_,
|
||||||
IOobject::NO_READ,
|
IOobject::NO_READ,
|
||||||
IOobject::NO_WRITE
|
IOobject::NO_WRITE
|
||||||
),
|
),
|
||||||
mesh_,
|
mesh_,
|
||||||
dimensionedVector(dimLength/pow3(dimTime), Zero)
|
dimensionedVector
|
||||||
|
(
|
||||||
|
adjointSensitivity.getAdjointSolver().maDimensions()/sqr(dimLength),
|
||||||
|
Zero
|
||||||
|
)
|
||||||
),
|
),
|
||||||
meshMovementSensPtr_(createZeroBoundaryPtr<vector>(mesh_)),
|
iters_(0),
|
||||||
adjointEikonalSolverPtr_(adjointEikonalSolverPtr)
|
tolerance_(Zero)
|
||||||
{
|
{
|
||||||
read();
|
read();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
bool adjointMeshMovementSolver::readDict(const dictionary& dict)
|
bool adjointMeshMovementSolver::readDict
|
||||||
|
(
|
||||||
|
const dictionary& dict
|
||||||
|
)
|
||||||
{
|
{
|
||||||
dict_ = dict.subOrEmptyDict("adjointMeshMovementSolver");
|
dict_ = dict.subOrEmptyDict("adjointMeshMovementSolver");
|
||||||
|
read();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void adjointMeshMovementSolver::accumulateIntegrand(const scalar dt)
|
|
||||||
{
|
|
||||||
// Accumulate integrand from the current time step
|
|
||||||
source_ += adjointSensitivity_.adjointMeshMovementSource()*dt;
|
|
||||||
|
|
||||||
// Part of the source depending on the adjoint distance can be added only
|
|
||||||
// after solving the adjoint eikonal equation. Added in solve()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void adjointMeshMovementSolver::solve()
|
void adjointMeshMovementSolver::solve()
|
||||||
{
|
{
|
||||||
read();
|
setSource();
|
||||||
|
|
||||||
// Add source from the adjoint eikonal equation
|
|
||||||
if (adjointEikonalSolverPtr_)
|
|
||||||
{
|
|
||||||
source_ -=
|
|
||||||
fvc::div(adjointEikonalSolverPtr_().getFISensitivityTerm()().T());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate the adjoint to the mesh movement equation
|
// Iterate the adjoint to the mesh movement equation
|
||||||
for (label iter = 0; iter < nLaplaceIters_; iter++)
|
for (label iter = 0; iter < iters_; iter++)
|
||||||
{
|
{
|
||||||
Info<< "Adjoint Mesh Movement Iteration: " << iter << endl;
|
Info<< "adjoint Mesh Movement Iteration: " << iter << endl;
|
||||||
|
|
||||||
fvVectorMatrix maEqn
|
fvVectorMatrix maEqn
|
||||||
(
|
(
|
||||||
fvm::laplacian(ma_)
|
fvm::laplacian(ma_) + source_
|
||||||
+ source_
|
|
||||||
);
|
);
|
||||||
|
|
||||||
maEqn.boundaryManipulate(ma_.boundaryFieldRef());
|
maEqn.boundaryManipulate(ma_.boundaryFieldRef());
|
||||||
|
|
||||||
//scalar residual = max(maEqn.solve().initialResidual());
|
|
||||||
scalar residual =
|
scalar residual =
|
||||||
mag(Foam::solve(maEqn, mesh_.solverDict("ma")).initialResidual());
|
mag(Foam::solve(maEqn, mesh_.solverDict("ma")).initialResidual());
|
||||||
|
|
||||||
@ -176,19 +188,22 @@ void adjointMeshMovementSolver::solve()
|
|||||||
void adjointMeshMovementSolver::reset()
|
void adjointMeshMovementSolver::reset()
|
||||||
{
|
{
|
||||||
source_ == dimensionedVector(source_.dimensions(), Zero);
|
source_ == dimensionedVector(source_.dimensions(), Zero);
|
||||||
meshMovementSensPtr_() = vector::zero;
|
meshMovementSensPtr_() = Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
boundaryVectorField& adjointMeshMovementSolver::meshMovementSensitivities()
|
boundaryVectorField& adjointMeshMovementSolver::meshMovementSensitivities()
|
||||||
{
|
{
|
||||||
Info<< "Calculating mesh movement sensitivities " << endl;
|
|
||||||
|
|
||||||
boundaryVectorField& meshMovementSens = meshMovementSensPtr_();
|
boundaryVectorField& meshMovementSens = meshMovementSensPtr_();
|
||||||
|
|
||||||
for (const label patchi : sensitivityPatchIDs_)
|
for
|
||||||
|
(
|
||||||
|
const label patchi
|
||||||
|
: adjointSensitivity_.geometryVariationIntegrationPatches()
|
||||||
|
)
|
||||||
{
|
{
|
||||||
// No surface area included. Will be done by the actual sensitivity tool
|
// No surface area included.
|
||||||
|
// Will be added during the assembly of the sensitivities
|
||||||
meshMovementSens[patchi] = -ma_.boundaryField()[patchi].snGrad();
|
meshMovementSens[patchi] = -ma_.boundaryField()[patchi].snGrad();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -196,15 +211,8 @@ boundaryVectorField& adjointMeshMovementSolver::meshMovementSensitivities()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const volVectorField& adjointMeshMovementSolver::ma()
|
|
||||||
{
|
|
||||||
return ma_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
} // End namespace incompressible
|
|
||||||
} // End namespace Foam
|
} // End namespace Foam
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
@ -25,20 +25,23 @@ License
|
|||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
Class
|
Class
|
||||||
Foam::incompressible::adjointMeshMovementSolver
|
Foam::adjointMeshMovementSolver
|
||||||
|
|
||||||
Description
|
Description
|
||||||
Solver of the adjoint to the Laplace grid displacement equation
|
Class solving the adjoint grid dispalcement PDEs.
|
||||||
|
Assumes the primal grid displacement PDE is a Laplace one with uniform
|
||||||
|
diffusivity.
|
||||||
|
|
||||||
Reference:
|
Reference:
|
||||||
\verbatim
|
\verbatim
|
||||||
Kavvadias, I., Papoutsis-Kiachagias, E., & Giannakoglou, K. (2015).
|
For the derivation of the adjoint grid displacement PDEs, see
|
||||||
On the proper treatment of grid sensitivities in continuous adjoint
|
Kavvadias, I., Papoutsis-Kiachagias, E., & Giannakoglou, K. (2015).
|
||||||
methods for shape optimization.
|
On the proper treatment of grid sensitivities in continuous adjoint
|
||||||
Journal of Computational Physics, 301, 1–18.
|
methods for shape optimization.
|
||||||
http://doi.org/10.1016/j.jcp.2015.08.012
|
Journal of Computational Physics, 301, 1–18.
|
||||||
|
http://doi.org/10.1016/j.jcp.2015.08.012
|
||||||
|
|
||||||
\endverbatim
|
\endverbatim
|
||||||
|
|
||||||
SourceFiles
|
SourceFiles
|
||||||
@ -46,48 +49,63 @@ SourceFiles
|
|||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#ifndef adjointMeshMovementSolverIncompressible_H
|
#ifndef adjointMeshMovementSolver_H
|
||||||
#define adjointMeshMovementSolverIncompressible_H
|
#define adjointMeshMovementSolver_H
|
||||||
|
|
||||||
#include "adjointSensitivityIncompressible.H"
|
|
||||||
#include "adjointEikonalSolverIncompressible.H"
|
|
||||||
#include "createZeroField.H"
|
|
||||||
#include "boundaryFieldsFwd.H"
|
#include "boundaryFieldsFwd.H"
|
||||||
|
#include "createZeroField.H"
|
||||||
|
#include "variablesSet.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace incompressible
|
// Forward declarations
|
||||||
{
|
class ShapeSensitivitiesBase;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
Class adjointMeshMovementSolver Declaration
|
Class adjointMeshMovementSolver Decleration
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
class adjointMeshMovementSolver
|
class adjointMeshMovementSolver
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Protected data
|
// Protected Data Members
|
||||||
|
|
||||||
|
//- Reference to mesh
|
||||||
const fvMesh& mesh_;
|
const fvMesh& mesh_;
|
||||||
|
|
||||||
|
//- Dictionary containing solution controls
|
||||||
dictionary dict_;
|
dictionary dict_;
|
||||||
Foam::incompressible::adjointSensitivity& adjointSensitivity_;
|
|
||||||
const labelHashSet& sensitivityPatchIDs_;
|
//- Part of sensitivity derivatives coming from the adjoint grid
|
||||||
label nLaplaceIters_;
|
//- displacement PDE
|
||||||
scalar tolerance_;
|
autoPtr<boundaryVectorField> meshMovementSensPtr_;
|
||||||
|
|
||||||
|
// Underlaying adjoint sensitivities
|
||||||
|
ShapeSensitivitiesBase& adjointSensitivity_;
|
||||||
|
|
||||||
|
//- Adjoint grid displacement field
|
||||||
volVectorField ma_;
|
volVectorField ma_;
|
||||||
|
|
||||||
|
//- Source term of the adjoint grid displacement PDEs
|
||||||
volVectorField source_;
|
volVectorField source_;
|
||||||
|
|
||||||
//- Wall face sens w.r.t.(x, y.z) //wall face sens w.r.t. (x,y.z)
|
//- Solution controls
|
||||||
autoPtr<boundaryVectorField> meshMovementSensPtr_;
|
label iters_;
|
||||||
const autoPtr<adjointEikonalSolver>& adjointEikonalSolverPtr_;
|
scalar tolerance_;
|
||||||
|
|
||||||
|
|
||||||
|
// Protected Member Functions
|
||||||
|
|
||||||
//- Read options each time a new solution is found
|
//- Read options each time a new solution is found
|
||||||
void read();
|
void read();
|
||||||
|
|
||||||
|
//- Set the source term of the PDE
|
||||||
|
void setSource();
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -97,7 +115,7 @@ private:
|
|||||||
adjointMeshMovementSolver(const adjointMeshMovementSolver&) = delete;
|
adjointMeshMovementSolver(const adjointMeshMovementSolver&) = delete;
|
||||||
|
|
||||||
//- No copy assignment
|
//- No copy assignment
|
||||||
void operator=(const adjointMeshMovementSolver&) = delete;
|
void operator=( const adjointMeshMovementSolver) = delete;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -113,44 +131,44 @@ public:
|
|||||||
(
|
(
|
||||||
const fvMesh& mesh,
|
const fvMesh& mesh,
|
||||||
const dictionary& dict,
|
const dictionary& dict,
|
||||||
Foam::incompressible::adjointSensitivity& adjointSensitivity,
|
ShapeSensitivitiesBase& adjointSensitivity
|
||||||
const labelHashSet& sensitivityPatchIDs,
|
|
||||||
const autoPtr<adjointEikonalSolver>& adjointEikonalSolverPtr
|
|
||||||
);
|
);
|
||||||
|
|
||||||
//- Destructor
|
|
||||||
|
// Destructor
|
||||||
virtual ~adjointMeshMovementSolver() = default;
|
virtual ~adjointMeshMovementSolver() = default;
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
//- Read dict if changed
|
//- Read dict if changed
|
||||||
virtual bool readDict(const dictionary& dict);
|
virtual bool readDict(const dictionary& dict);
|
||||||
|
|
||||||
//- Accumulate source term
|
//- Calculate the adjoint distance field
|
||||||
void accumulateIntegrand(const scalar dt);
|
virtual void solve();
|
||||||
|
|
||||||
//- Calculate the adjoint distance field
|
//- Reset the source term
|
||||||
void solve();
|
void reset();
|
||||||
|
|
||||||
//- Reset source term
|
//- Return the sensitivity term depending on ma
|
||||||
void reset();
|
boundaryVectorField& meshMovementSensitivities();
|
||||||
|
|
||||||
//- Return the sensitivity term depending on da
|
//- Return the adjoint distance field
|
||||||
boundaryVectorField& meshMovementSensitivities();
|
inline const volVectorField& ma() const
|
||||||
|
{
|
||||||
//- Return the adjoint distance field
|
return ma_;
|
||||||
const volVectorField& ma();
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
} // End namespace incompressible
|
|
||||||
} // End namespace Foam
|
} // End namespace Foam
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2020 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2020 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019-2020 OpenCFD Ltd.
|
Copyright (C) 2019-2020 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -27,20 +27,58 @@ License
|
|||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "shapeSensitivitiesBase.H"
|
#include "HashSet.H"
|
||||||
|
#include "ShapeSensitivitiesBase.H"
|
||||||
|
#include "adjointSensitivity.H"
|
||||||
|
#include "adjointSolver.H"
|
||||||
#include "addToRunTimeSelectionTable.H"
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
defineTypeNameAndDebug(shapeSensitivitiesBase, 0);
|
defineTypeNameAndDebug(ShapeSensitivitiesBase, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
void Foam::shapeSensitivitiesBase::writeFaceBasedSens() const
|
void Foam::ShapeSensitivitiesBase::allocateEikonalSolver()
|
||||||
|
{
|
||||||
|
// Allocate distance solver if needed
|
||||||
|
if (includeDistance_ && !eikonalSolver_)
|
||||||
|
{
|
||||||
|
eikonalSolver_.reset
|
||||||
|
(
|
||||||
|
new adjointEikonalSolver
|
||||||
|
(
|
||||||
|
mesh_,
|
||||||
|
this->dict(),
|
||||||
|
adjointSolver_,
|
||||||
|
geometryVariationIntegrationPatches()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::ShapeSensitivitiesBase::hasMultiplier
|
||||||
|
(
|
||||||
|
bool (objective::*hasFunction)() const
|
||||||
|
)
|
||||||
|
{
|
||||||
|
bool hasMult(false);
|
||||||
|
const PtrList<objective>& objectives =
|
||||||
|
adjointSolver_.getObjectiveManager().getObjectiveFunctions();
|
||||||
|
for (const objective& func : objectives)
|
||||||
|
{
|
||||||
|
hasMult = hasMult || (func.*hasFunction)();
|
||||||
|
}
|
||||||
|
return hasMult;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::ShapeSensitivitiesBase::writeFaceBasedSens() const
|
||||||
{
|
{
|
||||||
// Wall face sensitivity projected to normal
|
// Wall face sensitivity projected to normal
|
||||||
if (wallFaceSensNormalPtr_)
|
if (wallFaceSensNormalPtr_)
|
||||||
@ -48,7 +86,7 @@ void Foam::shapeSensitivitiesBase::writeFaceBasedSens() const
|
|||||||
constructAndWriteSensitivityField<scalar>
|
constructAndWriteSensitivityField<scalar>
|
||||||
(
|
(
|
||||||
wallFaceSensNormalPtr_,
|
wallFaceSensNormalPtr_,
|
||||||
"faceSensNormal" + surfaceFieldSuffix_
|
"faceSensNormal" + suffix_
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -60,7 +98,7 @@ void Foam::shapeSensitivitiesBase::writeFaceBasedSens() const
|
|||||||
constructAndWriteSensitivityField<vector>
|
constructAndWriteSensitivityField<vector>
|
||||||
(
|
(
|
||||||
wallFaceSensVecPtr_,
|
wallFaceSensVecPtr_,
|
||||||
"faceSensVec" + surfaceFieldSuffix_
|
"faceSensVec" + suffix_
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,14 +108,14 @@ void Foam::shapeSensitivitiesBase::writeFaceBasedSens() const
|
|||||||
constructAndWriteSensitivityField<vector>
|
constructAndWriteSensitivityField<vector>
|
||||||
(
|
(
|
||||||
wallFaceSensNormalVecPtr_,
|
wallFaceSensNormalVecPtr_,
|
||||||
"faceSensNormalVec" + surfaceFieldSuffix_
|
"faceSensNormalVec" + suffix_
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::shapeSensitivitiesBase::writePointBasedSens() const
|
void Foam::ShapeSensitivitiesBase::writePointBasedSens() const
|
||||||
{
|
{
|
||||||
// Wall point sensitivity projected to normal
|
// Wall point sensitivity projected to normal
|
||||||
if (wallPointSensNormalPtr_)
|
if (wallPointSensNormalPtr_)
|
||||||
@ -85,7 +123,7 @@ void Foam::shapeSensitivitiesBase::writePointBasedSens() const
|
|||||||
constructAndWriteSensitivtyPointField<scalar>
|
constructAndWriteSensitivtyPointField<scalar>
|
||||||
(
|
(
|
||||||
wallPointSensNormalPtr_,
|
wallPointSensNormalPtr_,
|
||||||
"pointSensNormal" + surfaceFieldSuffix_
|
"pointSensNormal" + suffix_
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +138,7 @@ void Foam::shapeSensitivitiesBase::writePointBasedSens() const
|
|||||||
constructAndWriteSensitivtyPointField<vector>
|
constructAndWriteSensitivtyPointField<vector>
|
||||||
(
|
(
|
||||||
wallPointSensVecPtr_,
|
wallPointSensVecPtr_,
|
||||||
"pointSensVec" + surfaceFieldSuffix_
|
"pointSensVec" + suffix_
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,69 +148,14 @@ void Foam::shapeSensitivitiesBase::writePointBasedSens() const
|
|||||||
constructAndWriteSensitivtyPointField<vector>
|
constructAndWriteSensitivtyPointField<vector>
|
||||||
(
|
(
|
||||||
wallPointSensNormalVecPtr_,
|
wallPointSensNormalVecPtr_,
|
||||||
"pointSensNormalVec" + surfaceFieldSuffix_
|
"pointSensNormalVec" + suffix_
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::ShapeSensitivitiesBase::clearSurfaceFields()
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
Foam::shapeSensitivitiesBase::shapeSensitivitiesBase
|
|
||||||
(
|
|
||||||
const fvMesh& mesh,
|
|
||||||
const dictionary& dict
|
|
||||||
)
|
|
||||||
:
|
|
||||||
meshShape_(mesh),
|
|
||||||
surfaceFieldSuffix_(),
|
|
||||||
writeAllSurfaceFiles_
|
|
||||||
(
|
|
||||||
dict.getOrDefault<bool>
|
|
||||||
(
|
|
||||||
"writeAllSurfaceFiles",
|
|
||||||
false
|
|
||||||
)
|
|
||||||
),
|
|
||||||
sensitivityPatchIDs_
|
|
||||||
(
|
|
||||||
mesh.boundaryMesh().patchSet
|
|
||||||
(
|
|
||||||
dict.get<wordRes>("patches", keyType::REGEX_RECURSIVE)
|
|
||||||
)
|
|
||||||
),
|
|
||||||
wallFaceSensVecPtr_(nullptr),
|
|
||||||
wallFaceSensNormalPtr_(nullptr),
|
|
||||||
wallFaceSensNormalVecPtr_(nullptr),
|
|
||||||
|
|
||||||
wallPointSensVecPtr_(nullptr),
|
|
||||||
wallPointSensNormalPtr_(nullptr),
|
|
||||||
wallPointSensNormalVecPtr_(nullptr)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
const Foam::labelHashSet&
|
|
||||||
Foam::shapeSensitivitiesBase::sensitivityPatchIDs() const
|
|
||||||
{
|
|
||||||
return sensitivityPatchIDs_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Foam::shapeSensitivitiesBase::setSensitivityPatchIDs
|
|
||||||
(
|
|
||||||
const labelHashSet& sensPatchIDs
|
|
||||||
)
|
|
||||||
{
|
|
||||||
sensitivityPatchIDs_ = sensPatchIDs;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Foam::shapeSensitivitiesBase::clearSensitivities()
|
|
||||||
{
|
{
|
||||||
// Face-based boundary sens
|
// Face-based boundary sens
|
||||||
if (wallFaceSensVecPtr_)
|
if (wallFaceSensVecPtr_)
|
||||||
@ -213,21 +196,212 @@ void Foam::shapeSensitivitiesBase::clearSensitivities()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::shapeSensitivitiesBase::write()
|
void Foam::ShapeSensitivitiesBase::allocateMultipliers()
|
||||||
{
|
{
|
||||||
|
gradDxDbMult_.reset
|
||||||
|
(
|
||||||
|
new volTensorField
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"gradDxDbMult",
|
||||||
|
mesh_.time().timeName(),
|
||||||
|
mesh_,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
mesh_,
|
||||||
|
dimensionedTensor(sqr(dimLength)/pow3(dimTime), Zero)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
if (hasMultiplier(&objective::hasDivDxDbMult))
|
||||||
|
{
|
||||||
|
divDxDbMult_.reset(new scalarField(mesh_.nCells(), Zero));
|
||||||
|
}
|
||||||
|
if (hasMultiplier(&objective::hasdSdbMult))
|
||||||
|
{
|
||||||
|
dSfdbMult_.reset(createZeroBoundaryPtr<vector>(mesh_));
|
||||||
|
}
|
||||||
|
if (hasMultiplier(&objective::hasdndbMult))
|
||||||
|
{
|
||||||
|
dnfdbMult_.reset(createZeroBoundaryPtr<vector>(mesh_));
|
||||||
|
}
|
||||||
|
if (hasMultiplier(&objective::hasdxdbDirectMult))
|
||||||
|
{
|
||||||
|
dxdbDirectMult_.reset(createZeroBoundaryPtr<vector>(mesh_));
|
||||||
|
}
|
||||||
|
bcDxDbMult_.reset(createZeroBoundaryPtr<vector>(mesh_));
|
||||||
|
optionsDxDbMult_.reset(new vectorField(mesh_.nCells(), Zero));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::ShapeSensitivitiesBase::clearMultipliers()
|
||||||
|
{
|
||||||
|
gradDxDbMult_() = dimensionedTensor(gradDxDbMult_().dimensions(), Zero);
|
||||||
|
if (divDxDbMult_)
|
||||||
|
{
|
||||||
|
divDxDbMult_() = Zero;
|
||||||
|
}
|
||||||
|
if (eikonalSolver_)
|
||||||
|
{
|
||||||
|
eikonalSolver_->reset();
|
||||||
|
}
|
||||||
|
if (dxdbMult_)
|
||||||
|
{
|
||||||
|
dxdbMult_() = Zero;
|
||||||
|
}
|
||||||
|
if (dSfdbMult_)
|
||||||
|
{
|
||||||
|
dSfdbMult_() = Zero;
|
||||||
|
}
|
||||||
|
if (dnfdbMult_)
|
||||||
|
{
|
||||||
|
dnfdbMult_() = Zero;
|
||||||
|
}
|
||||||
|
if (dxdbDirectMult_)
|
||||||
|
{
|
||||||
|
dxdbDirectMult_() = Zero;
|
||||||
|
}
|
||||||
|
if (pointDxDbDirectMult_)
|
||||||
|
{
|
||||||
|
for (vectorField& field : pointDxDbDirectMult_())
|
||||||
|
{
|
||||||
|
field = Zero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bcDxDbMult_() = Zero;
|
||||||
|
optionsDxDbMult_() = Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::ShapeSensitivitiesBase::ShapeSensitivitiesBase
|
||||||
|
(
|
||||||
|
const fvMesh& mesh,
|
||||||
|
const dictionary& dict,
|
||||||
|
class adjointSolver& adjointSolver
|
||||||
|
)
|
||||||
|
:
|
||||||
|
adjointSensitivity(mesh, dict, adjointSolver),
|
||||||
|
sensitivityPatchIDs_
|
||||||
|
(
|
||||||
|
mesh.boundaryMesh().patchSet
|
||||||
|
(
|
||||||
|
dict.optionalSubDict(mesh.name()).
|
||||||
|
get<wordRes>("patches", keyType::REGEX_RECURSIVE)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
writeAllSurfaceFiles_
|
||||||
|
(
|
||||||
|
dict.getOrDefault<bool>("writeAllSurfaceFiles", false)
|
||||||
|
),
|
||||||
|
wallFaceSensVecPtr_(nullptr),
|
||||||
|
wallFaceSensNormalPtr_(nullptr),
|
||||||
|
wallFaceSensNormalVecPtr_(nullptr),
|
||||||
|
|
||||||
|
wallPointSensVecPtr_(nullptr),
|
||||||
|
wallPointSensNormalPtr_(nullptr),
|
||||||
|
wallPointSensNormalVecPtr_(nullptr)
|
||||||
|
{
|
||||||
|
allocateEikonalSolver();
|
||||||
|
allocateMultipliers();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
bool Foam::ShapeSensitivitiesBase::readDict(const dictionary& dict)
|
||||||
|
{
|
||||||
|
if (adjointSensitivity::readDict(dict))
|
||||||
|
{
|
||||||
|
sensitivityPatchIDs_ =
|
||||||
|
mesh_.boundaryMesh().patchSet
|
||||||
|
(
|
||||||
|
dict_.optionalSubDict(mesh_.name()).
|
||||||
|
get<wordRes>("patches", keyType::REGEX_RECURSIVE)
|
||||||
|
);
|
||||||
|
writeAllSurfaceFiles_ =
|
||||||
|
dict_.getOrDefault<bool>("writeAllSurfaceFiles", false);
|
||||||
|
|
||||||
|
if (includeDistance_)
|
||||||
|
{
|
||||||
|
if (eikonalSolver_)
|
||||||
|
{
|
||||||
|
eikonalSolver_().readDict(dict);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
allocateEikonalSolver();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Foam::labelHashSet&
|
||||||
|
Foam::ShapeSensitivitiesBase::geometryVariationIntegrationPatches() const
|
||||||
|
{
|
||||||
|
return sensitivityPatchIDs_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::ShapeSensitivitiesBase::accumulateIntegrand(const scalar dt)
|
||||||
|
{
|
||||||
|
// Accumulate multiplier of grad(dxdb)
|
||||||
|
adjointSolver_.accumulateGradDxDbMultiplier(gradDxDbMult_(), dt);
|
||||||
|
|
||||||
|
// Accumulate multiplier of div(dxdb)
|
||||||
|
adjointSolver_.accumulateDivDxDbMultiplier(divDxDbMult_, dt);
|
||||||
|
|
||||||
|
// Terms from fvOptions - missing contributions from turbulence models
|
||||||
|
adjointSolver_.accumulateOptionsDxDbMultiplier(optionsDxDbMult_(), dt);
|
||||||
|
|
||||||
|
// Accumulate source for the adjoint to the eikonal equation
|
||||||
|
if (eikonalSolver_)
|
||||||
|
{
|
||||||
|
eikonalSolver_->accumulateIntegrand(dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Accumulate direct sensitivities
|
||||||
|
adjointSolver_.accumulateGeometryVariationsMultipliers
|
||||||
|
(
|
||||||
|
dSfdbMult_,
|
||||||
|
dnfdbMult_,
|
||||||
|
dxdbDirectMult_,
|
||||||
|
pointDxDbDirectMult_,
|
||||||
|
geometryVariationIntegrationPatches(),
|
||||||
|
dt
|
||||||
|
);
|
||||||
|
|
||||||
|
// Accumulate sensitivities due to boundary conditions
|
||||||
|
adjointSolver_.accumulateBCSensitivityIntegrand
|
||||||
|
(bcDxDbMult_, geometryVariationIntegrationPatches(), dt);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::ShapeSensitivitiesBase::clearSensitivities()
|
||||||
|
{
|
||||||
|
adjointSensitivity::clearSensitivities();
|
||||||
|
clearSurfaceFields();
|
||||||
|
clearMultipliers();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::ShapeSensitivitiesBase::write(const word& baseName)
|
||||||
|
{
|
||||||
|
adjointSensitivity::write(baseName);
|
||||||
writeFaceBasedSens();
|
writeFaceBasedSens();
|
||||||
writePointBasedSens();
|
writePointBasedSens();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::shapeSensitivitiesBase::setSuffix(const word& suffix)
|
|
||||||
{
|
|
||||||
surfaceFieldSuffix_ = suffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Foam::tmp<Foam::volVectorField>
|
Foam::tmp<Foam::volVectorField>
|
||||||
Foam::shapeSensitivitiesBase::getWallFaceSensVec()
|
Foam::ShapeSensitivitiesBase::getWallFaceSensVec()
|
||||||
{
|
{
|
||||||
if (wallFaceSensVecPtr_)
|
if (wallFaceSensVecPtr_)
|
||||||
{
|
{
|
||||||
@ -235,7 +409,7 @@ Foam::shapeSensitivitiesBase::getWallFaceSensVec()
|
|||||||
constructVolSensitivtyField<vector>
|
constructVolSensitivtyField<vector>
|
||||||
(
|
(
|
||||||
wallFaceSensVecPtr_,
|
wallFaceSensVecPtr_,
|
||||||
"faceSensVec" + surfaceFieldSuffix_
|
"faceSensVec" + suffix_
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -248,8 +422,8 @@ Foam::shapeSensitivitiesBase::getWallFaceSensVec()
|
|||||||
(
|
(
|
||||||
createZeroFieldPtr<vector>
|
createZeroFieldPtr<vector>
|
||||||
(
|
(
|
||||||
meshShape_,
|
mesh_,
|
||||||
"faceSensVec" + surfaceFieldSuffix_,
|
"faceSensVec" + suffix_,
|
||||||
dimless
|
dimless
|
||||||
).ptr()
|
).ptr()
|
||||||
);
|
);
|
||||||
@ -258,7 +432,7 @@ Foam::shapeSensitivitiesBase::getWallFaceSensVec()
|
|||||||
|
|
||||||
|
|
||||||
Foam::tmp<Foam::volScalarField>
|
Foam::tmp<Foam::volScalarField>
|
||||||
Foam::shapeSensitivitiesBase::getWallFaceSensNormal()
|
Foam::ShapeSensitivitiesBase::getWallFaceSensNormal()
|
||||||
{
|
{
|
||||||
if (wallFaceSensNormalPtr_)
|
if (wallFaceSensNormalPtr_)
|
||||||
{
|
{
|
||||||
@ -266,7 +440,7 @@ Foam::shapeSensitivitiesBase::getWallFaceSensNormal()
|
|||||||
constructVolSensitivtyField<scalar>
|
constructVolSensitivtyField<scalar>
|
||||||
(
|
(
|
||||||
wallFaceSensNormalPtr_,
|
wallFaceSensNormalPtr_,
|
||||||
"faceSensNormal" + surfaceFieldSuffix_
|
"faceSensNormal" + suffix_
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -279,8 +453,8 @@ Foam::shapeSensitivitiesBase::getWallFaceSensNormal()
|
|||||||
(
|
(
|
||||||
createZeroFieldPtr<scalar>
|
createZeroFieldPtr<scalar>
|
||||||
(
|
(
|
||||||
meshShape_,
|
mesh_,
|
||||||
"faceSensNormal" + surfaceFieldSuffix_, dimless
|
"faceSensNormal" + suffix_, dimless
|
||||||
).ptr()
|
).ptr()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -288,7 +462,7 @@ Foam::shapeSensitivitiesBase::getWallFaceSensNormal()
|
|||||||
|
|
||||||
|
|
||||||
Foam::tmp<Foam::volVectorField>
|
Foam::tmp<Foam::volVectorField>
|
||||||
Foam::shapeSensitivitiesBase::getWallFaceSensNormalVec()
|
Foam::ShapeSensitivitiesBase::getWallFaceSensNormalVec()
|
||||||
{
|
{
|
||||||
if (wallFaceSensNormalVecPtr_)
|
if (wallFaceSensNormalVecPtr_)
|
||||||
{
|
{
|
||||||
@ -296,7 +470,7 @@ Foam::shapeSensitivitiesBase::getWallFaceSensNormalVec()
|
|||||||
constructVolSensitivtyField<vector>
|
constructVolSensitivtyField<vector>
|
||||||
(
|
(
|
||||||
wallFaceSensNormalVecPtr_,
|
wallFaceSensNormalVecPtr_,
|
||||||
"faceSensNormalVec" + surfaceFieldSuffix_
|
"faceSensNormalVec" + suffix_
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -310,8 +484,8 @@ Foam::shapeSensitivitiesBase::getWallFaceSensNormalVec()
|
|||||||
(
|
(
|
||||||
createZeroFieldPtr<vector>
|
createZeroFieldPtr<vector>
|
||||||
(
|
(
|
||||||
meshShape_,
|
mesh_,
|
||||||
"faceSensNormalVec" + surfaceFieldSuffix_,
|
"faceSensNormalVec" + suffix_,
|
||||||
dimless
|
dimless
|
||||||
).ptr()
|
).ptr()
|
||||||
);
|
);
|
||||||
@ -320,51 +494,51 @@ Foam::shapeSensitivitiesBase::getWallFaceSensNormalVec()
|
|||||||
|
|
||||||
|
|
||||||
Foam::tmp<Foam::pointVectorField>
|
Foam::tmp<Foam::pointVectorField>
|
||||||
Foam::shapeSensitivitiesBase::getWallPointSensVec()
|
Foam::ShapeSensitivitiesBase::getWallPointSensVec()
|
||||||
{
|
{
|
||||||
tmp<volVectorField> tWallFaceSensVec = getWallFaceSensVec();
|
tmp<volVectorField> tWallFaceSensVec = getWallFaceSensVec();
|
||||||
volPointInterpolation volPointInter(meshShape_);
|
volPointInterpolation volPointInter(mesh_);
|
||||||
|
|
||||||
return (volPointInter.interpolate(tWallFaceSensVec));
|
return (volPointInter.interpolate(tWallFaceSensVec));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::tmp<Foam::pointScalarField>
|
Foam::tmp<Foam::pointScalarField>
|
||||||
Foam::shapeSensitivitiesBase::getWallPointSensNormal()
|
Foam::ShapeSensitivitiesBase::getWallPointSensNormal()
|
||||||
{
|
{
|
||||||
tmp<volScalarField> tWallFaceSensNormal = getWallFaceSensNormal();
|
tmp<volScalarField> tWallFaceSensNormal = getWallFaceSensNormal();
|
||||||
volPointInterpolation volPointInter(meshShape_);
|
volPointInterpolation volPointInter(mesh_);
|
||||||
|
|
||||||
return (volPointInter.interpolate(tWallFaceSensNormal));
|
return (volPointInter.interpolate(tWallFaceSensNormal));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::tmp<Foam::pointVectorField>
|
Foam::tmp<Foam::pointVectorField>
|
||||||
Foam::shapeSensitivitiesBase::getWallPointSensNormalVec()
|
Foam::ShapeSensitivitiesBase::getWallPointSensNormalVec()
|
||||||
{
|
{
|
||||||
tmp<volVectorField> tWallFaceSensNormalVec = getWallFaceSensNormalVec();
|
tmp<volVectorField> tWallFaceSensNormalVec = getWallFaceSensNormalVec();
|
||||||
volPointInterpolation volPointInter(meshShape_);
|
volPointInterpolation volPointInter(mesh_);
|
||||||
|
|
||||||
return (volPointInter.interpolate(tWallFaceSensNormalVec));
|
return (volPointInter.interpolate(tWallFaceSensNormalVec));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const Foam::boundaryVectorField&
|
const Foam::boundaryVectorField&
|
||||||
Foam::shapeSensitivitiesBase::getWallFaceSensVecBoundary() const
|
Foam::ShapeSensitivitiesBase::getWallFaceSensVecBoundary() const
|
||||||
{
|
{
|
||||||
return wallFaceSensVecPtr_();
|
return wallFaceSensVecPtr_();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const Foam::boundaryScalarField&
|
const Foam::boundaryScalarField&
|
||||||
Foam::shapeSensitivitiesBase::getWallFaceSensNormalBoundary() const
|
Foam::ShapeSensitivitiesBase::getWallFaceSensNormalBoundary() const
|
||||||
{
|
{
|
||||||
return wallFaceSensNormalPtr_();
|
return wallFaceSensNormalPtr_();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const Foam::boundaryVectorField&
|
const Foam::boundaryVectorField&
|
||||||
Foam::shapeSensitivitiesBase::getWallFaceSensNormalVecBoundary() const
|
Foam::ShapeSensitivitiesBase::getWallFaceSensNormalVecBoundary() const
|
||||||
{
|
{
|
||||||
return wallFaceSensNormalVecPtr_();
|
return wallFaceSensNormalVecPtr_();
|
||||||
}
|
}
|
||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2020 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2020 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
Copyright (C) 2019 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -26,24 +26,40 @@ License
|
|||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Class
|
Class
|
||||||
Foam::incompressible::shapeSensitivitiesBase
|
Foam::ShapeSensitivitiesBase
|
||||||
|
|
||||||
Description
|
Description
|
||||||
Base class supporting shape sensitivity derivatives
|
Base class supporting Shape sensitivity derivatives.
|
||||||
|
|
||||||
|
Reference:
|
||||||
|
\verbatim
|
||||||
|
For the FI formulation see
|
||||||
|
Kavvadias, I., Papoutsis-Kiachagias, E., & Giannakoglou, K. (2015).
|
||||||
|
On the proper treatment of grid sensitivities in continuous adjoint
|
||||||
|
methods for shape optimization.
|
||||||
|
Journal of Computational Physics, 301, 1–18.
|
||||||
|
http://doi.org/10.1016/j.jcp.2015.08.012
|
||||||
|
|
||||||
|
The ESI formulation is derived in a slightly different way than the
|
||||||
|
one described in this paper, to provide a common mathematical
|
||||||
|
formulation for both low- and high-Re meshes and to produce numerically
|
||||||
|
identical results as the FI formulation. In brief, the boundary-bound
|
||||||
|
part of the sensitivities is the patchInternalField of the tensor
|
||||||
|
multiplying grad(dxdb) in the FI formulation.
|
||||||
|
|
||||||
|
\endverbatim
|
||||||
|
|
||||||
SourceFiles
|
SourceFiles
|
||||||
shapeSensitivitiesBase.C
|
ShapeSensitivitiesBase.C
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#ifndef shapeSensitivitiesBase_H
|
#ifndef ShapeSensitivitiesBase_H
|
||||||
#define shapeSensitivitiesBase_H
|
#define ShapeSensitivitiesBase_H
|
||||||
|
|
||||||
#include "volFields.H"
|
#include "adjointSensitivity.H"
|
||||||
#include "surfaceFields.H"
|
#include "objective.H"
|
||||||
#include "dictionary.H"
|
|
||||||
#include "volPointInterpolation.H"
|
#include "volPointInterpolation.H"
|
||||||
|
|
||||||
#include "pointMesh.H"
|
#include "pointMesh.H"
|
||||||
#include "pointPatchField.H"
|
#include "pointPatchField.H"
|
||||||
#include "pointPatchFieldsFwd.H"
|
#include "pointPatchFieldsFwd.H"
|
||||||
@ -58,27 +74,29 @@ namespace Foam
|
|||||||
{
|
{
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
Class shapeSensitivitiesBase Declaration
|
Class ShapeSensitivitiesBase Declaration
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
class shapeSensitivitiesBase
|
class ShapeSensitivitiesBase
|
||||||
|
:
|
||||||
|
public adjointSensitivity
|
||||||
{
|
{
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Protected data
|
// Protected data
|
||||||
|
|
||||||
const fvMesh& meshShape_;
|
//- Patches on which to compute shape sensitivities
|
||||||
word surfaceFieldSuffix_;
|
|
||||||
bool writeAllSurfaceFiles_;
|
|
||||||
|
|
||||||
// Patches on which to compute shape sensitivities
|
|
||||||
labelHashSet sensitivityPatchIDs_;
|
labelHashSet sensitivityPatchIDs_;
|
||||||
|
|
||||||
|
//- Whether to write all surface sensitivity fields
|
||||||
|
bool writeAllSurfaceFiles_;
|
||||||
|
|
||||||
// autoPtrs for fields holding sensitivities.
|
// autoPtrs for fields holding sensitivities.
|
||||||
// Not all of them are required for each case
|
// Not all of them are required for each case
|
||||||
|
|
||||||
// Boundary sensitivities at faces. Shape opt & flow control
|
// Boundary sensitivities at faces. Shape opt & flow control
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
//- Wall face sens w.r.t. (x,y.z)
|
//- Wall face sens w.r.t. (x,y.z)
|
||||||
autoPtr<boundaryVectorField> wallFaceSensVecPtr_;
|
autoPtr<boundaryVectorField> wallFaceSensVecPtr_;
|
||||||
@ -101,6 +119,16 @@ protected:
|
|||||||
//- Normal sens as vectors
|
//- Normal sens as vectors
|
||||||
autoPtr<pointBoundaryVectorField> wallPointSensNormalVecPtr_;
|
autoPtr<pointBoundaryVectorField> wallPointSensNormalVecPtr_;
|
||||||
|
|
||||||
|
|
||||||
|
// Protected Member Functions
|
||||||
|
|
||||||
|
//- Allocate the adjoint eikonal solver
|
||||||
|
void allocateEikonalSolver();
|
||||||
|
|
||||||
|
//- Check if any of the available objective has a certain multiplier,
|
||||||
|
//- provided through a function object
|
||||||
|
bool hasMultiplier(bool (objective::*hasFunction)() const);
|
||||||
|
|
||||||
//- Constructs volField based on boundaryField and writes it
|
//- Constructs volField based on boundaryField and writes it
|
||||||
template<class Type>
|
template<class Type>
|
||||||
void constructAndWriteSensitivityField
|
void constructAndWriteSensitivityField
|
||||||
@ -138,55 +166,78 @@ protected:
|
|||||||
//- Write point-based sensitivities, if present
|
//- Write point-based sensitivities, if present
|
||||||
void writePointBasedSens() const;
|
void writePointBasedSens() const;
|
||||||
|
|
||||||
|
//- Clear surface/point fields
|
||||||
|
void clearSurfaceFields();
|
||||||
|
|
||||||
|
//- Allocate multiplier fields
|
||||||
|
void allocateMultipliers();
|
||||||
|
|
||||||
|
//- Clear multipliers
|
||||||
|
void clearMultipliers();
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
|
|
||||||
//- No copy construct
|
//- No copy construct
|
||||||
shapeSensitivitiesBase(const shapeSensitivitiesBase&) = delete;
|
ShapeSensitivitiesBase(const ShapeSensitivitiesBase&) = delete;
|
||||||
|
|
||||||
//- No copy assignment
|
//- No copy assignment
|
||||||
void operator=(const shapeSensitivitiesBase&) = delete;
|
void operator=(const ShapeSensitivitiesBase&) = delete;
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
//- Runtime type information
|
//- Runtime type information
|
||||||
TypeName("shapeSensitivitiesBase");
|
TypeName("ShapeSensitivitiesBase");
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
//- Construct from components
|
//- Construct from components
|
||||||
shapeSensitivitiesBase
|
ShapeSensitivitiesBase
|
||||||
(
|
(
|
||||||
const fvMesh& mesh,
|
const fvMesh& mesh,
|
||||||
const dictionary& dict
|
const dictionary& dict,
|
||||||
|
adjointSolver& adjointSolver
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
//- Destructor
|
//- Destructor
|
||||||
virtual ~shapeSensitivitiesBase() = default;
|
virtual ~ShapeSensitivitiesBase() = default;
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
|
//- Read dict if changed
|
||||||
|
virtual bool readDict(const dictionary& dict);
|
||||||
|
|
||||||
//- Get patch IDs on which sensitivities are computed
|
//- Get patch IDs on which sensitivities are computed
|
||||||
const labelHashSet& sensitivityPatchIDs() const;
|
inline const labelHashSet& sensitivityPatchIDs() const
|
||||||
|
{
|
||||||
|
return sensitivityPatchIDs_;
|
||||||
|
}
|
||||||
|
|
||||||
//- Overwrite sensitivityPatchIDs
|
//- Overwrite sensitivityPatchIDs
|
||||||
void setSensitivityPatchIDs(const labelHashSet& sensPatchIDs);
|
inline void setSensitivityPatchIDs(const labelHashSet& sensPatchIDs)
|
||||||
|
{
|
||||||
|
sensitivityPatchIDs_ = sensPatchIDs;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Return set of patches on which to compute direct sensitivities
|
||||||
|
virtual const labelHashSet& geometryVariationIntegrationPatches() const;
|
||||||
|
|
||||||
|
//- Accumulate sensitivity integrands
|
||||||
|
// Common function for the FI and E-SI approaches
|
||||||
|
virtual void accumulateIntegrand(const scalar dt);
|
||||||
|
|
||||||
//- Zero sensitivity fields and their constituents
|
//- Zero sensitivity fields and their constituents
|
||||||
void clearSensitivities();
|
void clearSensitivities();
|
||||||
|
|
||||||
//- Write sensitivity fields.
|
//- Write sensitivity fields.
|
||||||
// If valid, copies boundaryFields to volFields and writes them.
|
// If valid, copies boundaryFields to volFields and writes them.
|
||||||
void write();
|
virtual void write(const word& baseName = word::null);
|
||||||
|
|
||||||
//- Set suffix
|
|
||||||
void setSuffix(const word& suffix);
|
|
||||||
|
|
||||||
//- Get wall face sensitivity vectors field
|
//- Get wall face sensitivity vectors field
|
||||||
tmp<volVectorField> getWallFaceSensVec();
|
tmp<volVectorField> getWallFaceSensVec();
|
||||||
@ -229,7 +280,7 @@ public:
|
|||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
#ifdef NoRepository
|
#ifdef NoRepository
|
||||||
#include "shapeSensitivitiesBaseTemplates.C"
|
#include "ShapeSensitivitiesBaseTemplates.C"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
@ -27,7 +27,7 @@ License
|
|||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "shapeSensitivitiesBase.H"
|
#include "ShapeSensitivitiesBase.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
@ -37,7 +37,7 @@ namespace Foam
|
|||||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
void shapeSensitivitiesBase::constructAndWriteSensitivityField
|
void ShapeSensitivitiesBase::constructAndWriteSensitivityField
|
||||||
(
|
(
|
||||||
const autoPtr
|
const autoPtr
|
||||||
<
|
<
|
||||||
@ -51,12 +51,12 @@ void shapeSensitivitiesBase::constructAndWriteSensitivityField
|
|||||||
IOobject
|
IOobject
|
||||||
(
|
(
|
||||||
name,
|
name,
|
||||||
meshShape_.time().timeName(),
|
mesh_.time().timeName(),
|
||||||
meshShape_,
|
mesh_,
|
||||||
IOobject::NO_READ,
|
IOobject::NO_READ,
|
||||||
IOobject::NO_WRITE
|
IOobject::NO_WRITE
|
||||||
),
|
),
|
||||||
meshShape_,
|
mesh_,
|
||||||
dimensioned<Type>(dimless, Zero)
|
dimensioned<Type>(dimless, Zero)
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -70,7 +70,7 @@ void shapeSensitivitiesBase::constructAndWriteSensitivityField
|
|||||||
|
|
||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
void shapeSensitivitiesBase::constructAndWriteSensitivtyPointField
|
void ShapeSensitivitiesBase::constructAndWriteSensitivtyPointField
|
||||||
(
|
(
|
||||||
const autoPtr<List<Field<Type>>>& sensFieldPtr,
|
const autoPtr<List<Field<Type>>>& sensFieldPtr,
|
||||||
const word& name
|
const word& name
|
||||||
@ -81,12 +81,12 @@ void shapeSensitivitiesBase::constructAndWriteSensitivtyPointField
|
|||||||
IOobject
|
IOobject
|
||||||
(
|
(
|
||||||
name,
|
name,
|
||||||
meshShape_.time().timeName(),
|
mesh_.time().timeName(),
|
||||||
meshShape_,
|
mesh_,
|
||||||
IOobject::NO_READ,
|
IOobject::NO_READ,
|
||||||
IOobject::NO_WRITE
|
IOobject::NO_WRITE
|
||||||
),
|
),
|
||||||
pointMesh::New(meshShape_),
|
pointMesh::New(mesh_),
|
||||||
dimensioned<Type>(dimless, Zero)
|
dimensioned<Type>(dimless, Zero)
|
||||||
//fixedValuePointPatchField<Type>::typeName
|
//fixedValuePointPatchField<Type>::typeName
|
||||||
);
|
);
|
||||||
@ -109,7 +109,7 @@ void shapeSensitivitiesBase::constructAndWriteSensitivtyPointField
|
|||||||
|
|
||||||
template<class Type>
|
template<class Type>
|
||||||
tmp<GeometricField<Type, fvPatchField, volMesh>>
|
tmp<GeometricField<Type, fvPatchField, volMesh>>
|
||||||
shapeSensitivitiesBase::constructVolSensitivtyField
|
ShapeSensitivitiesBase::constructVolSensitivtyField
|
||||||
(
|
(
|
||||||
const autoPtr
|
const autoPtr
|
||||||
<
|
<
|
||||||
@ -125,12 +125,12 @@ shapeSensitivitiesBase::constructVolSensitivtyField
|
|||||||
IOobject
|
IOobject
|
||||||
(
|
(
|
||||||
name,
|
name,
|
||||||
meshShape_.time().timeName(),
|
mesh_.time().timeName(),
|
||||||
meshShape_,
|
mesh_,
|
||||||
IOobject::NO_READ,
|
IOobject::NO_READ,
|
||||||
IOobject::NO_WRITE
|
IOobject::NO_WRITE
|
||||||
),
|
),
|
||||||
meshShape_,
|
mesh_,
|
||||||
pTraits<Type>::zero
|
pTraits<Type>::zero
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@ -0,0 +1,384 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2007-2020, 2022 PCOpt/NTUA
|
||||||
|
Copyright (C) 2013-2020, 2022 FOSS GP
|
||||||
|
Copyright (C) 2019-2022 OpenCFD Ltd.
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "sensitivitySurface.H"
|
||||||
|
#include "volPointInterpolationAdjoint.H"
|
||||||
|
#include "faMatrices.H"
|
||||||
|
#include "famSup.H"
|
||||||
|
#include "famLaplacian.H"
|
||||||
|
#include "volSurfaceMapping.H"
|
||||||
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
defineTypeNameAndDebug(sensitivitySurface, 0);
|
||||||
|
addToRunTimeSelectionTable
|
||||||
|
(
|
||||||
|
adjointSensitivity,
|
||||||
|
sensitivitySurface,
|
||||||
|
dictionary
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
label sensitivitySurface::computeFaceDerivativesSize
|
||||||
|
(
|
||||||
|
const bool computeVectorFieldSize
|
||||||
|
)
|
||||||
|
{
|
||||||
|
label size(0);
|
||||||
|
for (const label patchI : sensitivityPatchIDs_)
|
||||||
|
{
|
||||||
|
const fvPatch& patch = mesh_.boundary()[patchI];
|
||||||
|
const label patchSize = patch.size();
|
||||||
|
size += label(computeVectorFieldSize ? 3*patchSize : patchSize);
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void sensitivitySurface::smoothSensitivities()
|
||||||
|
{
|
||||||
|
// Read in parameters
|
||||||
|
const label iters(dict().getOrDefault<label>("iters", 500));
|
||||||
|
const scalar tolerance(dict().getOrDefault<scalar>("tolerance", 1.e-06));
|
||||||
|
autoPtr<faMesh> aMeshPtr(nullptr);
|
||||||
|
|
||||||
|
IOobject faceLabels
|
||||||
|
(
|
||||||
|
"faceLabels",
|
||||||
|
mesh_.time().findInstance
|
||||||
|
(
|
||||||
|
mesh_.dbDir()/faMesh::meshSubDir,
|
||||||
|
"faceLabels",
|
||||||
|
IOobject::READ_IF_PRESENT
|
||||||
|
),
|
||||||
|
faMesh::meshSubDir,
|
||||||
|
mesh_,
|
||||||
|
IOobject::READ_IF_PRESENT,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
);
|
||||||
|
|
||||||
|
// If the faMesh already exists, read it
|
||||||
|
if (faceLabels.typeHeaderOk<labelIOList>(false))
|
||||||
|
{
|
||||||
|
Info<< "Reading the already constructed faMesh" << endl;
|
||||||
|
aMeshPtr.reset(new faMesh(mesh_));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Dictionary used to construct the faMesh
|
||||||
|
dictionary faMeshDefinition;
|
||||||
|
|
||||||
|
IOobject faMeshDefinitionDict
|
||||||
|
(
|
||||||
|
"faMeshDefinition",
|
||||||
|
mesh_.time().caseSystem(),
|
||||||
|
mesh_,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
);
|
||||||
|
|
||||||
|
// If the faMeshDefinitionDict exists, use it to construct the mesh
|
||||||
|
if (faMeshDefinitionDict.typeHeaderOk<IOdictionary>(false))
|
||||||
|
{
|
||||||
|
Info<< "Reading faMeshDefinition from system " << endl;
|
||||||
|
faMeshDefinition = IOdictionary(faMeshDefinitionDict);
|
||||||
|
}
|
||||||
|
// Otherwise, faMesh is generated from all patches on which we compute
|
||||||
|
// sensitivities
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Info<< "Constructing faMeshDefinition from sensitivity patches"
|
||||||
|
<< endl;
|
||||||
|
wordList polyMeshPatches(sensitivityPatchIDs_.size());
|
||||||
|
label i(0);
|
||||||
|
for (const label patchID : sensitivityPatchIDs_)
|
||||||
|
{
|
||||||
|
polyMeshPatches[i++] = mesh_.boundary()[patchID].name();
|
||||||
|
}
|
||||||
|
faMeshDefinition.add<wordList>("polyMeshPatches", polyMeshPatches);
|
||||||
|
(void)faMeshDefinition.subDictOrAdd("boundary");
|
||||||
|
Info<< faMeshDefinition << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Construct faMesh
|
||||||
|
aMeshPtr.reset(new faMesh(mesh_, faMeshDefinition));
|
||||||
|
}
|
||||||
|
faMesh& aMesh = aMeshPtr.ref();
|
||||||
|
|
||||||
|
// Physical radius of the smoothing, provided either directly or computed
|
||||||
|
// based on the average 'length' of boundary faces
|
||||||
|
const scalar Rphysical
|
||||||
|
(dict().getOrDefault<scalar>("radius", computeRadius(aMesh)));
|
||||||
|
DebugInfo
|
||||||
|
<< "Physical radius of the sensitivity smoothing "
|
||||||
|
<< Rphysical << nl << endl;
|
||||||
|
|
||||||
|
// Radius used as the diffusivity in the Helmholtz filter, computed as a
|
||||||
|
// function of the physical radius
|
||||||
|
const dimensionedScalar RpdeSqr
|
||||||
|
(
|
||||||
|
"RpdeSqr", dimArea, sqr(Rphysical/(2.*::sqrt(3.)))
|
||||||
|
);
|
||||||
|
|
||||||
|
dimensionedScalar one("1", dimless, 1.);
|
||||||
|
|
||||||
|
// Mapping engine
|
||||||
|
volSurfaceMapping vsm(aMesh);
|
||||||
|
|
||||||
|
// Source term in faMatrix needs to be an areaField
|
||||||
|
areaVectorField sens
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"sens",
|
||||||
|
mesh_.time().timeName(),
|
||||||
|
mesh_,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
aMesh,
|
||||||
|
dimensionedVector(dimless, Zero),
|
||||||
|
faPatchFieldBase::zeroGradientType()
|
||||||
|
);
|
||||||
|
|
||||||
|
// Copy sensitivities to area field
|
||||||
|
sens.primitiveFieldRef() =
|
||||||
|
vsm.mapToSurface<vector>(wallFaceSensVecPtr_());
|
||||||
|
|
||||||
|
// Initialisation of the smoothed sensitivities field based on the original
|
||||||
|
// sensitivities
|
||||||
|
areaVectorField smoothedSens("smoothedSens", sens);
|
||||||
|
for (label iter = 0; iter < iters; ++iter)
|
||||||
|
{
|
||||||
|
Info<< "Sensitivity smoothing iteration " << iter << endl;
|
||||||
|
|
||||||
|
faVectorMatrix smoothEqn
|
||||||
|
(
|
||||||
|
fam::Sp(one, smoothedSens)
|
||||||
|
- fam::laplacian(RpdeSqr, smoothedSens)
|
||||||
|
==
|
||||||
|
sens
|
||||||
|
);
|
||||||
|
|
||||||
|
smoothEqn.relax();
|
||||||
|
|
||||||
|
const scalar residual(mag(smoothEqn.solve().initialResidual()));
|
||||||
|
|
||||||
|
DebugInfo
|
||||||
|
<< "Max smoothSens " << gMax(mag(smoothedSens)()) << endl;
|
||||||
|
|
||||||
|
// Print execution time
|
||||||
|
mesh_.time().printExecutionTime(Info);
|
||||||
|
|
||||||
|
// Check convergence
|
||||||
|
if (residual < tolerance)
|
||||||
|
{
|
||||||
|
Info<< "\n***Reached smoothing equation convergence limit, "
|
||||||
|
"iteration " << iter << "***\n\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transfer smooth sensitivity field to wallFaceSensVecPtr_ for defining
|
||||||
|
// derivatives_
|
||||||
|
vsm.mapToVolume(smoothedSens, wallFaceSensVecPtr_());
|
||||||
|
|
||||||
|
// Write normal, regularised sensitivities to file
|
||||||
|
volScalarField volSmoothedSens
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"smoothedSurfaceSens" + suffix_,
|
||||||
|
mesh_.time().timeName(),
|
||||||
|
mesh_,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
mesh_,
|
||||||
|
dimensionedScalar(dimless, Zero)
|
||||||
|
);
|
||||||
|
areaVectorField nf(aMesh.faceAreaNormals());
|
||||||
|
nf.normalise();
|
||||||
|
areaScalarField smoothedSensNormal(smoothedSens & nf);
|
||||||
|
vsm.mapToVolume(smoothedSensNormal, volSmoothedSens.boundaryFieldRef());
|
||||||
|
volSmoothedSens.write();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
scalar sensitivitySurface::computeRadius(const faMesh& aMesh)
|
||||||
|
{
|
||||||
|
scalar averageArea(gAverage(aMesh.S().field()));
|
||||||
|
const Vector<label>& geometricD = mesh_.geometricD();
|
||||||
|
const boundBox& bounds = mesh_.bounds();
|
||||||
|
forAll(geometricD, iDir)
|
||||||
|
{
|
||||||
|
if (geometricD[iDir] == -1)
|
||||||
|
{
|
||||||
|
averageArea /= bounds.span()[iDir];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scalar mult = dict().getOrDefault<scalar>("meanRadiusMultiplier", 10);
|
||||||
|
|
||||||
|
return mult*pow(averageArea, scalar(1)/scalar(mesh_.nGeometricD() - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
sensitivitySurface::sensitivitySurface
|
||||||
|
(
|
||||||
|
const fvMesh& mesh,
|
||||||
|
const dictionary& dict,
|
||||||
|
adjointSolver& adjointSolver
|
||||||
|
)
|
||||||
|
:
|
||||||
|
sensitivitySurfacePoints(mesh, dict, adjointSolver),
|
||||||
|
smoothSensitivities_(dict.getOrDefault("smoothSensitivities", false)),
|
||||||
|
returnVectorField_
|
||||||
|
(dict.getOrDefault<bool>("returnVectorField", true))
|
||||||
|
//finalResultIncludesArea_
|
||||||
|
// (dict.getOrDefault<bool>("finalResultIncludesArea", false))
|
||||||
|
{
|
||||||
|
// Allocate boundary field pointers
|
||||||
|
wallFaceSensVecPtr_.reset(createZeroBoundaryPtr<vector>(mesh_));
|
||||||
|
wallFaceSensNormalPtr_.reset(createZeroBoundaryPtr<scalar>(mesh_));
|
||||||
|
wallFaceSensNormalVecPtr_.reset(createZeroBoundaryPtr<vector>(mesh_));
|
||||||
|
|
||||||
|
derivatives_.setSize(computeFaceDerivativesSize(returnVectorField_), Zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void sensitivitySurface::read()
|
||||||
|
{
|
||||||
|
sensitivitySurfacePoints::read();
|
||||||
|
smoothSensitivities_ = dict().getOrDefault("smoothSensitivities", false);
|
||||||
|
returnVectorField_ =
|
||||||
|
dict().getOrDefault<bool>("returnVectorField", true);
|
||||||
|
//finalResultIncludesArea_ =
|
||||||
|
// dict().getOrDefault<bool>("finalResultIncludesArea", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void sensitivitySurface::assembleSensitivities
|
||||||
|
(
|
||||||
|
autoPtr<designVariables>& designVars
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Compute point-based sensitivities
|
||||||
|
sensitivitySurfacePoints::assembleSensitivities(designVars);
|
||||||
|
|
||||||
|
// Transfer point sensitivities to point field
|
||||||
|
vectorField pointSens(mesh_.nPoints(), Zero);
|
||||||
|
for (const label patchI : sensitivityPatchIDs_)
|
||||||
|
{
|
||||||
|
const polyPatch& pp = mesh_.boundaryMesh()[patchI];
|
||||||
|
const labelList& meshPoints = pp.meshPoints();
|
||||||
|
forAll(meshPoints, ppi)
|
||||||
|
{
|
||||||
|
pointSens[meshPoints[ppi]] = wallPointSensVecPtr_()[patchI][ppi];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vectorField face-sensitivities
|
||||||
|
vectorField faceVecSens(computeFaceDerivativesSize(false), Zero);
|
||||||
|
|
||||||
|
// Map sensitivities from points to faces
|
||||||
|
volPointInterpolationAdjoint interpolation(mesh_);
|
||||||
|
interpolation.interpolateSensitivitiesField
|
||||||
|
(pointSens, faceVecSens, sensitivityPatchIDs_);
|
||||||
|
|
||||||
|
// Transfer non-regularised sensitivities to wallFaceSens* fields and write
|
||||||
|
label nPassedFaces(0);
|
||||||
|
for (const label patchI : sensitivityPatchIDs_)
|
||||||
|
{
|
||||||
|
const fvPatch& patch = mesh_.boundary()[patchI];
|
||||||
|
tmp<vectorField> nf = patch.nf();
|
||||||
|
wallFaceSensVecPtr_()[patchI] =
|
||||||
|
SubField<vector>(faceVecSens, patch.size(), nPassedFaces)
|
||||||
|
/patch.magSf();
|
||||||
|
wallFaceSensNormalPtr_()[patchI] = wallFaceSensVecPtr_()[patchI] & nf();
|
||||||
|
wallFaceSensNormalVecPtr_()[patchI] =
|
||||||
|
wallFaceSensNormalPtr_()[patchI]*nf;
|
||||||
|
nPassedFaces += patch.size();
|
||||||
|
}
|
||||||
|
write();
|
||||||
|
|
||||||
|
// Regularise sensitivities if necessary
|
||||||
|
if (smoothSensitivities_)
|
||||||
|
{
|
||||||
|
smoothSensitivities();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure we have the correct sensitivities size
|
||||||
|
derivatives_.setSize(computeFaceDerivativesSize(returnVectorField_), Zero);
|
||||||
|
nPassedFaces = 0;
|
||||||
|
for (const label patchI : sensitivityPatchIDs_)
|
||||||
|
{
|
||||||
|
const fvPatch& patch = mesh_.boundary()[patchI];
|
||||||
|
const vectorField nf(patch.nf());
|
||||||
|
if (returnVectorField_)
|
||||||
|
{
|
||||||
|
const Vector<label>& sd = mesh_.solutionD();
|
||||||
|
forAll(patch, fI)
|
||||||
|
{
|
||||||
|
const label gfI = nPassedFaces + fI;
|
||||||
|
const vector& fSens = wallFaceSensVecPtr_()[patchI][fI];
|
||||||
|
derivatives_[3*gfI ] = scalar(sd[0] == -1 ? 0 : fSens.x());
|
||||||
|
derivatives_[3*gfI + 1] = scalar(sd[1] == -1 ? 0 : fSens.y());
|
||||||
|
derivatives_[3*gfI + 2] = scalar(sd[2] == -1 ? 0 : fSens.z());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
forAll(patch, fI)
|
||||||
|
{
|
||||||
|
derivatives_[nPassedFaces + fI]
|
||||||
|
= wallFaceSensVecPtr_()[patchI][fI] & nf[fI];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nPassedFaces += patch.size();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2021 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2021 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
Copyright (C) 2019 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -26,7 +26,7 @@ License
|
|||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Class
|
Class
|
||||||
Foam::incompressible::sensitivitySurface
|
Foam::sensitivitySurface
|
||||||
|
|
||||||
Description
|
Description
|
||||||
Calculation of adjoint based sensitivities at wall faces
|
Calculation of adjoint based sensitivities at wall faces
|
||||||
@ -60,11 +60,7 @@ SourceFiles
|
|||||||
#ifndef sensitivitySurfaceIncompressible_H
|
#ifndef sensitivitySurfaceIncompressible_H
|
||||||
#define sensitivitySurfaceIncompressible_H
|
#define sensitivitySurfaceIncompressible_H
|
||||||
|
|
||||||
#include "adjointSensitivityIncompressible.H"
|
#include "sensitivitySurfacePoints.H"
|
||||||
#include "shapeSensitivitiesBase.H"
|
|
||||||
#include "adjointEikonalSolverIncompressible.H"
|
|
||||||
#include "adjointMeshMovementSolverIncompressible.H"
|
|
||||||
#include "deltaBoundary.H"
|
|
||||||
#include "faMesh.H"
|
#include "faMesh.H"
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
@ -72,75 +68,31 @@ SourceFiles
|
|||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace incompressible
|
|
||||||
{
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
Class sensitivitySurface Declaration
|
Class sensitivitySurface Declaration
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
class sensitivitySurface
|
class sensitivitySurface
|
||||||
:
|
:
|
||||||
public adjointSensitivity,
|
public sensitivitySurfacePoints
|
||||||
public shapeSensitivitiesBase
|
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Protected data
|
// Protected data
|
||||||
|
|
||||||
|
//- Smooth sensitivity derivatives based on a surface Laplace solver
|
||||||
//- Include surface area in sens computation
|
|
||||||
bool includeSurfaceArea_;
|
|
||||||
|
|
||||||
//- Include the adjoint pressure term in sens computation
|
|
||||||
bool includePressureTerm_;
|
|
||||||
|
|
||||||
//- Include the term containing the grad of the stress at the boundary
|
|
||||||
bool includeGradStressTerm_;
|
|
||||||
|
|
||||||
//- Include the transpose part of the adjoint stresses
|
|
||||||
bool includeTransposeStresses_;
|
|
||||||
|
|
||||||
//- Use snGrad in the transpose part of the adjoint stresses
|
|
||||||
bool useSnGradInTranposeStresses_;
|
|
||||||
|
|
||||||
//- Include the term from the deviatoric part of the stresses
|
|
||||||
bool includeDivTerm_;
|
|
||||||
|
|
||||||
//- Include distance variation in sens computation
|
|
||||||
bool includeDistance_;
|
|
||||||
|
|
||||||
//- Include mesh movement variation in sens computation
|
|
||||||
bool includeMeshMovement_;
|
|
||||||
|
|
||||||
//- Include terms directly emerging from the objective function
|
|
||||||
bool includeObjective_;
|
|
||||||
|
|
||||||
//- Write geometric info for use by external programs
|
|
||||||
bool writeGeometricInfo_;
|
|
||||||
|
|
||||||
//- Smooth sensitivity derivatives based on the computation of the
|
|
||||||
//- 'Sobolev gradient'
|
|
||||||
bool smoothSensitivities_;
|
bool smoothSensitivities_;
|
||||||
|
|
||||||
autoPtr<adjointEikonalSolver> eikonalSolver_;
|
//- Return the complete vector of sensitivities
|
||||||
|
bool returnVectorField_;
|
||||||
|
|
||||||
autoPtr<adjointMeshMovementSolver> meshMovementSolver_;
|
//bool finalResultIncludesArea_;
|
||||||
|
|
||||||
// Export face normal and face centre for use by external users
|
|
||||||
autoPtr<volVectorField> nfOnPatchPtr_;
|
|
||||||
autoPtr<volVectorField> SfOnPatchPtr_;
|
|
||||||
autoPtr<volVectorField> CfOnPatchPtr_;
|
|
||||||
|
|
||||||
|
|
||||||
// Protected Member Functions
|
// Protected Member Functions
|
||||||
|
|
||||||
//- Add sensitivities from dSd/db and dnf/db computed at points and
|
//- Compute the size of the return field
|
||||||
//- mapped to faces
|
label computeFaceDerivativesSize(const bool computeVectorFieldSize);
|
||||||
void addGeometricSens();
|
|
||||||
|
|
||||||
//- Set suffix name for sensitivity fields
|
|
||||||
void setSuffixName();
|
|
||||||
|
|
||||||
//- Smooth sensitivity derivatives based on the computation of the
|
//- Smooth sensitivity derivatives based on the computation of the
|
||||||
//- 'Sobolev gradient'
|
//- 'Sobolev gradient'
|
||||||
@ -175,7 +127,7 @@ public:
|
|||||||
(
|
(
|
||||||
const fvMesh& mesh,
|
const fvMesh& mesh,
|
||||||
const dictionary& dict,
|
const dictionary& dict,
|
||||||
incompressibleAdjointSolver& adjointSolver
|
adjointSolver& adjointSolver
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@ -188,55 +140,20 @@ public:
|
|||||||
//- Read controls and update solver pointers if necessary
|
//- Read controls and update solver pointers if necessary
|
||||||
void read();
|
void read();
|
||||||
|
|
||||||
//- Read dict if changed
|
//- Assemble sensitivities
|
||||||
virtual bool readDict(const dictionary& dict);
|
virtual void assembleSensitivities
|
||||||
|
(
|
||||||
//- Compute the number of faces on sensitivityPatchIDs_
|
autoPtr<designVariables>& designVars
|
||||||
void computeDerivativesSize();
|
);
|
||||||
|
|
||||||
//- Accumulate sensitivity integrands
|
|
||||||
virtual void accumulateIntegrand(const scalar dt);
|
|
||||||
|
|
||||||
//- Assemble sensitivities
|
|
||||||
virtual void assembleSensitivities();
|
|
||||||
|
|
||||||
//- Zero sensitivity fields and their constituents
|
|
||||||
virtual void clearSensitivities();
|
|
||||||
|
|
||||||
//- Get adjoint eikonal solver
|
|
||||||
autoPtr<adjointEikonalSolver>& getAdjointEikonalSolver();
|
|
||||||
|
|
||||||
//- Write sensitivity maps
|
|
||||||
virtual void write(const word& baseName = word::null);
|
|
||||||
|
|
||||||
// Inline getters and setters
|
|
||||||
|
|
||||||
//- Get access to the includeObjective bool
|
|
||||||
inline bool getIncludeObjective() const;
|
|
||||||
|
|
||||||
//- Get access to the includeSurfaceArea bool
|
|
||||||
inline bool getIncludeSurfaceArea() const;
|
|
||||||
|
|
||||||
//- Set includeObjective bool
|
|
||||||
inline void setIncludeObjective(const bool includeObjective);
|
|
||||||
|
|
||||||
//- Set includeSurfaceArea bool
|
|
||||||
inline void setIncludeSurfaceArea(const bool includeSurfaceArea);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
} // End namespace incompressible
|
|
||||||
} // End namespace Foam
|
} // End namespace Foam
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
#include "sensitivitySurfaceIncompressibleI.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// ************************************************************************* //
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,560 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2007-2020, 2022 PCOpt/NTUA
|
||||||
|
Copyright (C) 2013-2020, 2022 FOSS GP
|
||||||
|
Copyright (C) 2019-2022 OpenCFD Ltd.
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "sensitivitySurfacePoints.H"
|
||||||
|
#include "deltaBoundary.H"
|
||||||
|
#include "designVariables.H"
|
||||||
|
#include "syncTools.H"
|
||||||
|
#include "symmetryFvPatch.H"
|
||||||
|
#include "symmetryPlaneFvPatch.H"
|
||||||
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
defineTypeNameAndDebug(sensitivitySurfacePoints, 1);
|
||||||
|
addToRunTimeSelectionTable
|
||||||
|
(
|
||||||
|
adjointSensitivity,
|
||||||
|
sensitivitySurfacePoints,
|
||||||
|
dictionary
|
||||||
|
);
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
labelHashSet sensitivitySurfacePoints::populateExtendedIDs() const
|
||||||
|
{
|
||||||
|
// Populate extendedPatchIDs
|
||||||
|
label pI(0);
|
||||||
|
labelList extendedPatchIDs(mesh_.boundary().size(), -1);
|
||||||
|
forAll(mesh_.boundary(), patchI)
|
||||||
|
{
|
||||||
|
const fvPatch& pp = mesh_.boundary()[patchI];
|
||||||
|
bool isSymmetry
|
||||||
|
(isA<symmetryFvPatch>(pp) || isA<symmetryPlaneFvPatch>(pp));
|
||||||
|
if (!isA<coupledFvPatch>(pp) && !isA<emptyFvPatch>(pp) && !isSymmetry)
|
||||||
|
{
|
||||||
|
extendedPatchIDs[pI++] = patchI;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
extendedPatchIDs.setSize(pI);
|
||||||
|
return labelHashSet(extendedPatchIDs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void sensitivitySurfacePoints::setSuffixName()
|
||||||
|
{
|
||||||
|
word suffix(adjointMeshMovementSolver_ ? "ESI" : "SI");
|
||||||
|
suffix = suffix + word(dict().getOrDefault<word>("suffix", word::null));
|
||||||
|
setSuffix(adjointSolver_.solverName() + suffix);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void sensitivitySurfacePoints::finalisePointSensitivities()
|
||||||
|
{
|
||||||
|
// List with mesh faces. Global addressing
|
||||||
|
const faceList& faces = mesh_.faces();
|
||||||
|
|
||||||
|
// Geometry differentiation engine
|
||||||
|
deltaBoundary dBoundary(mesh_);
|
||||||
|
|
||||||
|
for (const label patchI : extendedPatchIDs_)
|
||||||
|
{
|
||||||
|
const fvPatch& patch = mesh_.boundary()[patchI];
|
||||||
|
vectorField nf(patch.nf());
|
||||||
|
|
||||||
|
// Point sens result for patch
|
||||||
|
vectorField& pointPatchSens = wallPointSensVecPtr_()[patchI];
|
||||||
|
|
||||||
|
// Face sens for patch
|
||||||
|
vectorField facePatchSens = dxdbMult_()[patchI];
|
||||||
|
if (dxdbDirectMult_)
|
||||||
|
{
|
||||||
|
facePatchSens += dxdbDirectMult_()[patchI];
|
||||||
|
}
|
||||||
|
if (bcDxDbMult_)
|
||||||
|
{
|
||||||
|
facePatchSens += bcDxDbMult_()[patchI];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Correspondance of local point addressing to global point addressing
|
||||||
|
const labelList& meshPoints = patch.patch().meshPoints();
|
||||||
|
|
||||||
|
// Each local patch point belongs to these local patch faces
|
||||||
|
// (local numbering)
|
||||||
|
const labelListList& patchPointFaces = patch.patch().pointFaces();
|
||||||
|
|
||||||
|
// Index of first face in patch
|
||||||
|
const label patchStartIndex = patch.start();
|
||||||
|
|
||||||
|
// Loop over patch points.
|
||||||
|
// Collect contributions from each boundary face this point belongs to
|
||||||
|
forAll(meshPoints, ppI)
|
||||||
|
{
|
||||||
|
const labelList& pointFaces = patchPointFaces[ppI];
|
||||||
|
forAll(pointFaces, pfI)
|
||||||
|
{
|
||||||
|
label localFaceIndex = pointFaces[pfI];
|
||||||
|
label globalFaceIndex = patchStartIndex + localFaceIndex;
|
||||||
|
const face& faceI = faces[globalFaceIndex];
|
||||||
|
|
||||||
|
// Point coordinates. All indices in global numbering
|
||||||
|
pointField p(faceI.points(mesh_.points()));
|
||||||
|
tensorField p_d(faceI.size(), Zero);
|
||||||
|
forAll(faceI, facePointI)
|
||||||
|
{
|
||||||
|
if (faceI[facePointI] == meshPoints[ppI])
|
||||||
|
{
|
||||||
|
p_d[facePointI] = tensor::I;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tensorField deltaNormals =
|
||||||
|
dBoundary.makeFaceCentresAndAreas_d(p, p_d);
|
||||||
|
|
||||||
|
if (isSymmetryPoint_[meshPoints[ppI]])
|
||||||
|
{
|
||||||
|
const vector& n = symmPointNormal_[meshPoints[ppI]];
|
||||||
|
deltaNormals =
|
||||||
|
//0.5*(deltaNormals + transform(I - 2.0*sqr(n), deltaNormals));
|
||||||
|
(deltaNormals + transform(I - 2.0*sqr(n), deltaNormals));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Element [0] is the variation in the face center
|
||||||
|
// (dxFace/dxPoint)
|
||||||
|
const tensor& deltaCf = deltaNormals[0];
|
||||||
|
pointPatchSens[ppI] += facePatchSens[localFaceIndex] & deltaCf;
|
||||||
|
|
||||||
|
// Term multiplying d(Sf)/d(point displacement) and
|
||||||
|
// d(nf)/d(point displacement)
|
||||||
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
// Element [1] is the variation in the (dimensional) normal
|
||||||
|
if (dSfdbMult_)
|
||||||
|
{
|
||||||
|
const tensor& deltaSf = deltaNormals[1];
|
||||||
|
pointPatchSens[ppI] +=
|
||||||
|
dSfdbMult_()[patchI][localFaceIndex] & deltaSf;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Element [2] is the variation in the unit normal
|
||||||
|
if (dnfdbMult_)
|
||||||
|
{
|
||||||
|
const tensor& deltaNf = deltaNormals[2];
|
||||||
|
pointPatchSens[ppI] +=
|
||||||
|
dnfdbMult_()[patchI][localFaceIndex] & deltaNf;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void sensitivitySurfacePoints::constructGlobalPointNormalsAndAreas
|
||||||
|
(
|
||||||
|
vectorField& pointNormals,
|
||||||
|
scalarField& pointMagSf
|
||||||
|
)
|
||||||
|
{
|
||||||
|
for (const label patchI : extendedPatchIDs_)
|
||||||
|
{
|
||||||
|
const fvPatch& patch = mesh_.boundary()[patchI];
|
||||||
|
const scalarField& magSf = patch.magSf();
|
||||||
|
vectorField nf(patch.nf());
|
||||||
|
|
||||||
|
// Correspondance of local point addressing to global point addressing
|
||||||
|
const labelList& meshPoints = patch.patch().meshPoints();
|
||||||
|
|
||||||
|
// Each local patch point belongs to these local patch faces
|
||||||
|
// (local numbering)
|
||||||
|
const labelListList& patchPointFaces = patch.patch().pointFaces();
|
||||||
|
|
||||||
|
// Loop over patch points
|
||||||
|
forAll(meshPoints, ppI)
|
||||||
|
{
|
||||||
|
const labelList& pointFaces = patchPointFaces[ppI];
|
||||||
|
forAll(pointFaces, pfI)
|
||||||
|
{
|
||||||
|
const label localFaceIndex = pointFaces[pfI];
|
||||||
|
|
||||||
|
// Accumulate information for point normals
|
||||||
|
pointNormals[meshPoints[ppI]] += nf[localFaceIndex];
|
||||||
|
pointMagSf[meshPoints[ppI]] += magSf[localFaceIndex];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
syncTools::syncPointList
|
||||||
|
(
|
||||||
|
mesh_,
|
||||||
|
pointNormals,
|
||||||
|
plusEqOp<vector>(),
|
||||||
|
vector::zero
|
||||||
|
);
|
||||||
|
syncTools::syncPointList
|
||||||
|
(
|
||||||
|
mesh_,
|
||||||
|
pointMagSf,
|
||||||
|
plusEqOp<scalar>(),
|
||||||
|
scalar(0)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (writeGeometricInfo_)
|
||||||
|
{
|
||||||
|
pointScalarField MagSf
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"pointMagSf",
|
||||||
|
mesh_.time().timeName(),
|
||||||
|
mesh_,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
pointMesh::New(mesh_),
|
||||||
|
dimensionedScalar(dimless, Zero)
|
||||||
|
);
|
||||||
|
pointVectorField Nf
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"pointNf",
|
||||||
|
mesh_.time().timeName(),
|
||||||
|
mesh_,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
pointMesh::New(mesh_),
|
||||||
|
dimensionedVector(dimless, Zero)
|
||||||
|
);
|
||||||
|
MagSf.primitiveFieldRef() = pointMagSf;
|
||||||
|
Nf.primitiveFieldRef() = pointNormals;
|
||||||
|
Nf.primitiveFieldRef().normalise();
|
||||||
|
MagSf.write();
|
||||||
|
Nf.write();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void sensitivitySurfacePoints::computePointDerivativesSize()
|
||||||
|
{
|
||||||
|
// Allocate appropriate space for sensitivities
|
||||||
|
label nTotalPoints(0);
|
||||||
|
for (const label patchI : sensitivityPatchIDs_)
|
||||||
|
{
|
||||||
|
nTotalPoints += mesh_.boundaryMesh()[patchI].nPoints();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Derivatives for all (x,y,z) components of the displacement
|
||||||
|
derivatives_ = scalarField(3*nTotalPoints, Zero);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
sensitivitySurfacePoints::sensitivitySurfacePoints
|
||||||
|
(
|
||||||
|
const fvMesh& mesh,
|
||||||
|
const dictionary& dict,
|
||||||
|
adjointSolver& adjointSolver
|
||||||
|
)
|
||||||
|
:
|
||||||
|
sensitivityShapeESI(mesh, dict, adjointSolver),
|
||||||
|
writeGeometricInfo_(false),
|
||||||
|
includeSurfaceArea_(false),
|
||||||
|
isSymmetryPoint_(mesh.nPoints(), false),
|
||||||
|
symmPointNormal_(mesh.nPoints(), Zero),
|
||||||
|
extendedPatchIDs_(populateExtendedIDs())
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
{
|
||||||
|
Info<< "Extended sensitivity patches " << nl;
|
||||||
|
for (const label patchI : extendedPatchIDs_)
|
||||||
|
{
|
||||||
|
Info<< mesh_.boundary()[patchI].name() << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
read();
|
||||||
|
setSuffixName();
|
||||||
|
|
||||||
|
// Allocate boundary field pointer
|
||||||
|
wallPointSensVecPtr_.reset(createZeroBoundaryPointFieldPtr<vector>(mesh_));
|
||||||
|
wallPointSensNormalPtr_.reset
|
||||||
|
(
|
||||||
|
createZeroBoundaryPointFieldPtr<scalar>(mesh_)
|
||||||
|
);
|
||||||
|
wallPointSensNormalVecPtr_.reset
|
||||||
|
(
|
||||||
|
createZeroBoundaryPointFieldPtr<vector>(mesh_)
|
||||||
|
);
|
||||||
|
|
||||||
|
computePointDerivativesSize();
|
||||||
|
|
||||||
|
// Populate symmetry patches
|
||||||
|
forAll(mesh_.boundary(), patchI)
|
||||||
|
{
|
||||||
|
const fvPatch& pp = mesh_.boundary()[patchI];
|
||||||
|
bool isSymmetry
|
||||||
|
(isA<symmetryFvPatch>(pp) || isA<symmetryPlaneFvPatch>(pp));
|
||||||
|
if (isSymmetry)
|
||||||
|
{
|
||||||
|
const labelList& meshPoints = pp.patch().meshPoints();
|
||||||
|
const vectorField& pointNormals = pp.patch().pointNormals();
|
||||||
|
forAll(meshPoints, pI)
|
||||||
|
{
|
||||||
|
const label pointi = meshPoints[pI];
|
||||||
|
isSymmetryPoint_[pointi] = true;
|
||||||
|
symmPointNormal_[pointi] = pointNormals[pI];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void sensitivitySurfacePoints::read()
|
||||||
|
{
|
||||||
|
writeGeometricInfo_ =
|
||||||
|
dict().getOrDefault<bool>("writeGeometricInfo", false);
|
||||||
|
// Point sensitivities do not include the surface area by default
|
||||||
|
includeSurfaceArea_ =
|
||||||
|
dict().getOrDefault<bool>("includeSurfaceArea", false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool sensitivitySurfacePoints::readDict(const dictionary& dict)
|
||||||
|
{
|
||||||
|
if (sensitivityShapeESI::readDict(dict))
|
||||||
|
{
|
||||||
|
read();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Foam::labelHashSet&
|
||||||
|
Foam::sensitivitySurfacePoints::geometryVariationIntegrationPatches() const
|
||||||
|
{
|
||||||
|
return extendedPatchIDs_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void sensitivitySurfacePoints::assembleSensitivities
|
||||||
|
(
|
||||||
|
autoPtr<designVariables>& designVars
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Make sure we have the proper size for the sensitivities
|
||||||
|
computePointDerivativesSize();
|
||||||
|
|
||||||
|
// Assemble the multipliers of dxdbFace, as in the ESI approach
|
||||||
|
computeDxDbMult();
|
||||||
|
|
||||||
|
// Geometric (or "direct") sensitivities are better computed directly on
|
||||||
|
// the points. Compute them and add the ones that depend on dxFace/dxPoint
|
||||||
|
finalisePointSensitivities();
|
||||||
|
|
||||||
|
// polyPatch::pointNormals will give the wrong result for points
|
||||||
|
// belonging to multiple patches or patch-processorPatch intersections.
|
||||||
|
// Keeping a mesh-wide field to allow easy reduction using syncTools.
|
||||||
|
// A bit expensive? Better way?
|
||||||
|
vectorField pointNormals(mesh_.nPoints(), Zero);
|
||||||
|
scalarField pointMagSf(mesh_.nPoints(), Zero);
|
||||||
|
constructGlobalPointNormalsAndAreas(pointNormals, pointMagSf);
|
||||||
|
|
||||||
|
// Do parallel communications to avoid wrong values at processor boundaries
|
||||||
|
// Global field for accumulation
|
||||||
|
vectorField pointSensGlobal(mesh_.nPoints(), Zero);
|
||||||
|
for (const label patchI : extendedPatchIDs_)
|
||||||
|
{
|
||||||
|
const labelList& meshPoints = mesh_.boundaryMesh()[patchI].meshPoints();
|
||||||
|
forAll(meshPoints, ppI)
|
||||||
|
{
|
||||||
|
const label globaPointI = meshPoints[ppI];
|
||||||
|
pointSensGlobal[globaPointI] += wallPointSensVecPtr_()[patchI][ppI];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Remove components normal to symmetry planes
|
||||||
|
forAll(mesh_.boundary(), patchI)
|
||||||
|
{
|
||||||
|
const fvPatch& patch = mesh_.boundary()[patchI];
|
||||||
|
if (isA<symmetryFvPatch>(patch) || isA<symmetryPlaneFvPatch>(patch))
|
||||||
|
{
|
||||||
|
// Deliberately using local point normals instead of the global ones,
|
||||||
|
// to get the direction normal to the symmetry plane itself
|
||||||
|
const vectorField& pn = patch.patch().pointNormals();
|
||||||
|
const labelList& meshPoints = patch.patch().meshPoints();
|
||||||
|
forAll(meshPoints, pI)
|
||||||
|
{
|
||||||
|
const label gpI = meshPoints[pI];
|
||||||
|
pointSensGlobal[gpI] -= wallPointSensVecPtr_()[patchI][pI];
|
||||||
|
pointSensGlobal[gpI] -=
|
||||||
|
(pointSensGlobal[gpI] & pn[pI])*pn[pI];
|
||||||
|
pointSensGlobal[gpI] *= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Accumulate dJ/dx_i
|
||||||
|
syncTools::syncPointList
|
||||||
|
(
|
||||||
|
mesh_,
|
||||||
|
pointSensGlobal,
|
||||||
|
plusEqOp<vector>(),
|
||||||
|
vector::zero
|
||||||
|
);
|
||||||
|
|
||||||
|
// Transfer back to local fields
|
||||||
|
for (const label patchI : extendedPatchIDs_)
|
||||||
|
{
|
||||||
|
const labelList& meshPoints =
|
||||||
|
mesh_.boundaryMesh()[patchI].meshPoints();
|
||||||
|
wallPointSensVecPtr_()[patchI].map(pointSensGlobal, meshPoints);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compute normal sens and append to return field
|
||||||
|
label nPassedDVs(0);
|
||||||
|
const Vector<label>& sd = mesh_.solutionD();
|
||||||
|
for (const label patchI : sensitivityPatchIDs_)
|
||||||
|
{
|
||||||
|
const polyPatch& patch = mesh_.boundaryMesh()[patchI];
|
||||||
|
//if (patch.size()>0)
|
||||||
|
{
|
||||||
|
const labelList& meshPoints = patch.meshPoints();
|
||||||
|
|
||||||
|
// Avoid storing unit point normals in the global list since we
|
||||||
|
// might divide multiple times with the number of faces belonging
|
||||||
|
// to the point. Instead do the division locally, per patch use
|
||||||
|
vectorField patchPointNormals(pointNormals, meshPoints);
|
||||||
|
patchPointNormals.normalise();
|
||||||
|
if (!includeSurfaceArea_)
|
||||||
|
{
|
||||||
|
wallPointSensVecPtr_()[patchI] /=
|
||||||
|
scalarField(pointMagSf, meshPoints);
|
||||||
|
}
|
||||||
|
wallPointSensNormalPtr_()[patchI] =
|
||||||
|
wallPointSensVecPtr_()[patchI] & patchPointNormals;
|
||||||
|
wallPointSensNormalVecPtr_()[patchI] =
|
||||||
|
wallPointSensNormalPtr_()[patchI] *patchPointNormals;
|
||||||
|
|
||||||
|
forAll(patch.localPoints(), pi)
|
||||||
|
{
|
||||||
|
const label gpi = nPassedDVs + pi;
|
||||||
|
const vector& pSens = wallPointSensVecPtr_()[patchI][pi];
|
||||||
|
derivatives_[3*gpi ] = scalar(sd[0] == -1 ? 0 : pSens.x());
|
||||||
|
derivatives_[3*gpi + 1] = scalar(sd[1] == -1 ? 0 : pSens.y());
|
||||||
|
derivatives_[3*gpi + 2] = scalar(sd[2] == -1 ? 0 : pSens.z());
|
||||||
|
}
|
||||||
|
nPassedDVs += patch.nPoints();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write derivative fields
|
||||||
|
write();
|
||||||
|
|
||||||
|
// Get processed sensitivities from designVariables, if present
|
||||||
|
if (designVars)
|
||||||
|
{
|
||||||
|
adjointSensitivity::assembleSensitivities(designVars);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void sensitivitySurfacePoints::write(const word& baseName)
|
||||||
|
{
|
||||||
|
adjointSensitivity::write();
|
||||||
|
ShapeSensitivitiesBase::write();
|
||||||
|
|
||||||
|
if (writeGeometricInfo_)
|
||||||
|
{
|
||||||
|
volVectorField nfOnPatch
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"nfOnPatch",
|
||||||
|
mesh_.time().timeName(),
|
||||||
|
mesh_,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh_,
|
||||||
|
Zero
|
||||||
|
);
|
||||||
|
|
||||||
|
volVectorField SfOnPatch
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"SfOnPatch",
|
||||||
|
mesh_.time().timeName(),
|
||||||
|
mesh_,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh_,
|
||||||
|
Zero
|
||||||
|
);
|
||||||
|
|
||||||
|
volVectorField CfOnPatch
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"CfOnPatch",
|
||||||
|
mesh_.time().timeName(),
|
||||||
|
mesh_,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh_,
|
||||||
|
Zero
|
||||||
|
);
|
||||||
|
for (const label patchI : sensitivityPatchIDs_)
|
||||||
|
{
|
||||||
|
const fvPatch& patch = mesh_.boundary()[patchI];
|
||||||
|
nfOnPatch.boundaryFieldRef()[patchI] = patch.nf();
|
||||||
|
SfOnPatch.boundaryFieldRef()[patchI] = patch.Sf();
|
||||||
|
CfOnPatch.boundaryFieldRef()[patchI] = patch.Cf();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -26,99 +26,62 @@ License
|
|||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
Class
|
Class
|
||||||
Foam::incompressible::sensitivitySurfacePoints
|
Foam::sensitivitySurfacePoints
|
||||||
|
|
||||||
Description
|
Description
|
||||||
Calculation of adjoint based sensitivities at wall points
|
Calculation of adjoint-based sensitivities at wall points using the
|
||||||
|
E-SI formulation
|
||||||
|
|
||||||
SourceFiles
|
SourceFiles
|
||||||
sensitivitySurfacePoints.C
|
sensitivitySurfacePoints.C
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#ifndef sensitivitySurfacePointsIncompressible_H
|
#ifndef sensitivitySurfacePoints_H
|
||||||
#define sensitivitySurfacePointsIncompressible_H
|
#define sensitivitySurfacePoints_H
|
||||||
|
|
||||||
#include "adjointSensitivityIncompressible.H"
|
#include "sensitivityShapeESI.H"
|
||||||
#include "shapeSensitivitiesBase.H"
|
|
||||||
#include "adjointEikonalSolverIncompressible.H"
|
|
||||||
#include "adjointMeshMovementSolverIncompressible.H"
|
|
||||||
#include "deltaBoundary.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
|
|
||||||
namespace incompressible
|
|
||||||
{
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
Class sensitivitySurfacePoints Declaration
|
Class sensitivitySurfacePoints Declaration
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
class sensitivitySurfacePoints
|
class sensitivitySurfacePoints
|
||||||
:
|
:
|
||||||
public adjointSensitivity,
|
public sensitivityShapeESI
|
||||||
public shapeSensitivitiesBase
|
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
// Protected data
|
// Protected data
|
||||||
|
|
||||||
|
//- Write geometric info for use by external programs
|
||||||
|
bool writeGeometricInfo_;
|
||||||
|
|
||||||
//- Include surface area in sens computation
|
//- Include surface area in sens computation
|
||||||
bool includeSurfaceArea_;
|
bool includeSurfaceArea_;
|
||||||
|
|
||||||
//- Include the adjoint pressure term in sens computation
|
//- Is point belonging to a symmetry{Plane}
|
||||||
bool includePressureTerm_;
|
boolList isSymmetryPoint_;
|
||||||
|
|
||||||
//- Include the term containing the grad of the stress at the boundary
|
//- Local point normal per symmetry point
|
||||||
bool includeGradStressTerm_;
|
vectorField symmPointNormal_;;
|
||||||
|
|
||||||
//- Include the transpose part of the adjoint stresses
|
//- Extended patchIDs
|
||||||
bool includeTransposeStresses_;
|
// Sensitivities from patches adjacent to the sensitivityPatchIDs_
|
||||||
|
// should also be taken into consideration in order to compute the
|
||||||
//- Use snGrad in the transpose part of the adjoint stresses
|
// correct values at points in their interfaces
|
||||||
bool useSnGradInTranposeStresses_;
|
labelHashSet extendedPatchIDs_;
|
||||||
|
|
||||||
//- Include the term from the deviatoric part of the stresses
|
|
||||||
bool includeDivTerm_;
|
|
||||||
|
|
||||||
//- Include distance variation in sens computation
|
|
||||||
bool includeDistance_;
|
|
||||||
|
|
||||||
//- Include mesh movement variation in sens computation
|
|
||||||
bool includeMeshMovement_;
|
|
||||||
|
|
||||||
//- Include terms directly emerging from the objective function
|
|
||||||
bool includeObjective_;
|
|
||||||
|
|
||||||
autoPtr<adjointEikonalSolver> eikonalSolver_;
|
|
||||||
|
|
||||||
autoPtr<adjointMeshMovementSolver> meshMovementSolver_;
|
|
||||||
|
|
||||||
//- The face-based part of the sensitivities
|
|
||||||
// i.e. terms that multiply dxFace/dxPoint.
|
|
||||||
// Sensitivities DO include locale surface area, to get
|
|
||||||
// the correct weighting from the contributions of various faces.
|
|
||||||
// Normalized at the end.
|
|
||||||
autoPtr<boundaryVectorField> wallFaceSens_;
|
|
||||||
|
|
||||||
//- Multipliers of d(Sf)/db and d(nf)/db
|
|
||||||
autoPtr<boundaryVectorField> dSfdbMult_;
|
|
||||||
autoPtr<boundaryVectorField> dnfdbMult_;
|
|
||||||
|
|
||||||
|
|
||||||
// Protected Member Functions
|
// Protected Member Functions
|
||||||
|
|
||||||
//- Read controls and update solver pointers if necessary
|
//- Set suffix name for sensitivity fields
|
||||||
void read();
|
labelHashSet populateExtendedIDs() const;
|
||||||
|
|
||||||
//- Add terms related to post-processing PDEs
|
|
||||||
//- (i.e. adjoint Eikonal, adjoint mesh movement)
|
|
||||||
//- and add local face area
|
|
||||||
void finaliseFaceMultiplier();
|
|
||||||
|
|
||||||
//- Converts face sensitivities to point sensitivities and adds the
|
//- Converts face sensitivities to point sensitivities and adds the
|
||||||
//- ones directly computed in points (i.e. dSf/db and dnf/db).
|
//- ones directly computed in points (i.e. dSf/db and dnf/db).
|
||||||
@ -134,6 +97,9 @@ protected:
|
|||||||
//- Set suffix name for sensitivity fields
|
//- Set suffix name for sensitivity fields
|
||||||
void setSuffixName();
|
void setSuffixName();
|
||||||
|
|
||||||
|
//- Allocate the proper size for the point-based sensitivities
|
||||||
|
void computePointDerivativesSize();
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@ -159,7 +125,7 @@ public:
|
|||||||
(
|
(
|
||||||
const fvMesh& mesh,
|
const fvMesh& mesh,
|
||||||
const dictionary& dict,
|
const dictionary& dict,
|
||||||
incompressibleAdjointSolver& adjointSolver
|
adjointSolver& adjointSolver
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
@ -169,25 +135,29 @@ public:
|
|||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
//- Read dict if changed
|
//- Read controls and update solver pointers if necessary
|
||||||
virtual bool readDict(const dictionary& dict);
|
void read();
|
||||||
|
|
||||||
//- Accumulate sensitivity integrands
|
//- Read dict if changed
|
||||||
virtual void accumulateIntegrand(const scalar dt);
|
virtual bool readDict(const dictionary& dict);
|
||||||
|
|
||||||
//- Assemble sensitivities
|
//- Return set of patches on which to compute direct sensitivities
|
||||||
virtual void assembleSensitivities();
|
virtual const labelHashSet& geometryVariationIntegrationPatches() const;
|
||||||
|
|
||||||
//- Zero sensitivity fields and their constituents
|
//- Assemble sensitivities
|
||||||
virtual void clearSensitivities();
|
virtual void assembleSensitivities
|
||||||
|
(
|
||||||
|
autoPtr<designVariables>& designVars
|
||||||
|
);
|
||||||
|
|
||||||
virtual void write(const word& baseName = word::null);
|
//- Write sensitivity fields.
|
||||||
|
// If valid, copies boundaryFields to pointFields and writes them.
|
||||||
|
virtual void write(const word& baseName = word::null);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
} // End namespace incompressible
|
|
||||||
} // End namespace Foam
|
} // End namespace Foam
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
@ -1,183 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | www.openfoam.com
|
|
||||||
\\/ M anipulation |
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
Copyright (C) 2007-2021 PCOpt/NTUA
|
|
||||||
Copyright (C) 2013-2021 FOSS GP
|
|
||||||
Copyright (C) 2019-2020 OpenCFD Ltd.
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
License
|
|
||||||
This file is part of OpenFOAM.
|
|
||||||
|
|
||||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "FIBaseIncompressible.H"
|
|
||||||
#include "addToRunTimeSelectionTable.H"
|
|
||||||
#include "fvOptions.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
|
|
||||||
namespace incompressible
|
|
||||||
{
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
defineTypeNameAndDebug(FIBase, 0);
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
|
||||||
|
|
||||||
void FIBase::read()
|
|
||||||
{
|
|
||||||
includeDistance_ =
|
|
||||||
dict_.getOrDefault<bool>
|
|
||||||
(
|
|
||||||
"includeDistance",
|
|
||||||
adjointVars_.adjointTurbulence().ref().includeDistance()
|
|
||||||
);
|
|
||||||
|
|
||||||
// Allocate distance solver if needed
|
|
||||||
if (includeDistance_ && !eikonalSolver_)
|
|
||||||
{
|
|
||||||
eikonalSolver_.reset
|
|
||||||
(
|
|
||||||
new adjointEikonalSolver
|
|
||||||
(
|
|
||||||
mesh_,
|
|
||||||
dict_,
|
|
||||||
primalVars_.RASModelVariables(),
|
|
||||||
adjointVars_,
|
|
||||||
sensitivityPatchIDs_
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
FIBase::FIBase
|
|
||||||
(
|
|
||||||
const fvMesh& mesh,
|
|
||||||
const dictionary& dict,
|
|
||||||
incompressibleAdjointSolver& adjointSolver
|
|
||||||
)
|
|
||||||
:
|
|
||||||
shapeSensitivities(mesh, dict, adjointSolver),
|
|
||||||
gradDxDbMult_
|
|
||||||
(
|
|
||||||
IOobject
|
|
||||||
(
|
|
||||||
"gradDxDbMult",
|
|
||||||
mesh_.time().timeName(),
|
|
||||||
mesh_,
|
|
||||||
IOobject::NO_READ,
|
|
||||||
IOobject::NO_WRITE
|
|
||||||
),
|
|
||||||
mesh_,
|
|
||||||
dimensionedTensor(sqr(dimLength)/pow3(dimTime), Zero)
|
|
||||||
),
|
|
||||||
divDxDbMult_(mesh_.nCells(), Zero),
|
|
||||||
optionsDxDbMult_(mesh_.nCells(), Zero),
|
|
||||||
|
|
||||||
includeDistance_(false),
|
|
||||||
eikonalSolver_(nullptr)
|
|
||||||
{
|
|
||||||
read();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
bool FIBase::readDict(const dictionary& dict)
|
|
||||||
{
|
|
||||||
if (sensitivity::readDict(dict))
|
|
||||||
{
|
|
||||||
if (eikonalSolver_)
|
|
||||||
{
|
|
||||||
eikonalSolver_().readDict(dict);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FIBase::accumulateIntegrand(const scalar dt)
|
|
||||||
{
|
|
||||||
// Accumulate multiplier of grad(dxdb)
|
|
||||||
gradDxDbMult_ += computeGradDxDbMultiplier()().T()*dt;
|
|
||||||
|
|
||||||
// Accumulate multiplier of div(dxdb)
|
|
||||||
PtrList<objective>& functions(objectiveManager_.getObjectiveFunctions());
|
|
||||||
for (objective& func : functions)
|
|
||||||
{
|
|
||||||
if (func.hasDivDxDbMult())
|
|
||||||
{
|
|
||||||
divDxDbMult_ +=
|
|
||||||
func.weight()*func.divDxDbMultiplier().primitiveField()*dt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Terms from fvOptions
|
|
||||||
fv::options::New(this->mesh_).postProcessSens
|
|
||||||
(
|
|
||||||
optionsDxDbMult_, adjointVars_.solverName()
|
|
||||||
);
|
|
||||||
|
|
||||||
// Accumulate source for the adjoint to the eikonal equation
|
|
||||||
if (includeDistance_)
|
|
||||||
{
|
|
||||||
eikonalSolver_->accumulateIntegrand(dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Accumulate direct sensitivities
|
|
||||||
accumulateDirectSensitivityIntegrand(dt);
|
|
||||||
|
|
||||||
// Accumulate sensitivities due to boundary conditions
|
|
||||||
accumulateBCSensitivityIntegrand(dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void FIBase::clearSensitivities()
|
|
||||||
{
|
|
||||||
gradDxDbMult_ = dimensionedTensor(gradDxDbMult_.dimensions(), Zero);
|
|
||||||
divDxDbMult_ = Zero;
|
|
||||||
optionsDxDbMult_ = vector::zero;
|
|
||||||
|
|
||||||
if (includeDistance_)
|
|
||||||
{
|
|
||||||
eikonalSolver_->reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
shapeSensitivities::clearSensitivities();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
} // End namespace incompressible
|
|
||||||
} // End namespace Foam
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -1,165 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | www.openfoam.com
|
|
||||||
\\/ M anipulation |
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
Copyright (C) 2007-2020 PCOpt/NTUA
|
|
||||||
Copyright (C) 2013-2020 FOSS GP
|
|
||||||
Copyright (C) 2019-2020 OpenCFD Ltd.
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
License
|
|
||||||
This file is part of OpenFOAM.
|
|
||||||
|
|
||||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "SIBaseIncompressible.H"
|
|
||||||
#include "addToRunTimeSelectionTable.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
|
|
||||||
namespace incompressible
|
|
||||||
{
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
defineTypeNameAndDebug(SIBase, 0);
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
|
||||||
|
|
||||||
void SIBase::read()
|
|
||||||
{
|
|
||||||
surfaceSensitivity_.read();
|
|
||||||
includeObjective_ =
|
|
||||||
dict().getOrDefault<bool>("includeObjectiveContribution", true);
|
|
||||||
writeSensitivityMap_ =
|
|
||||||
dict().getOrDefault<bool>("writeSensitivityMap", false);
|
|
||||||
|
|
||||||
// If includeObjective is set to true both here and in the surface
|
|
||||||
// sensitivities, set the one in the latter to false to avoid double
|
|
||||||
// contributions
|
|
||||||
bool surfSensIncludeObjective(surfaceSensitivity_.getIncludeObjective());
|
|
||||||
if (includeObjective_ && surfSensIncludeObjective)
|
|
||||||
{
|
|
||||||
WarningInFunction
|
|
||||||
<< "includeObjectiveContribution set to true in both "
|
|
||||||
<< "surfaceSensitivities and the parameterization options" << nl
|
|
||||||
<< "This will lead to double contributions " << nl
|
|
||||||
<< "Disabling the former"
|
|
||||||
<< endl;
|
|
||||||
surfaceSensitivity_.setIncludeObjective(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure surface area is included in the sensitivity map
|
|
||||||
surfaceSensitivity_.setIncludeSurfaceArea(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
SIBase::SIBase
|
|
||||||
(
|
|
||||||
const fvMesh& mesh,
|
|
||||||
const dictionary& dict,
|
|
||||||
incompressibleAdjointSolver& adjointSolver
|
|
||||||
)
|
|
||||||
:
|
|
||||||
shapeSensitivities(mesh, dict, adjointSolver),
|
|
||||||
surfaceSensitivity_
|
|
||||||
(
|
|
||||||
mesh,
|
|
||||||
// Ideally, subOrEmptyDict would be used.
|
|
||||||
// Since we need a recursive search in shapeSensitivities though
|
|
||||||
// and the dict returned by subOrEmptyDict (if found)
|
|
||||||
// does not know its parent, optionalSubDict is used
|
|
||||||
dict.optionalSubDict("surfaceSensitivities"),
|
|
||||||
adjointSolver
|
|
||||||
),
|
|
||||||
includeObjective_(true),
|
|
||||||
writeSensitivityMap_(true)
|
|
||||||
{
|
|
||||||
read();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
bool SIBase::readDict(const dictionary& dict)
|
|
||||||
{
|
|
||||||
if (sensitivity::readDict(dict))
|
|
||||||
{
|
|
||||||
surfaceSensitivity_.readDict
|
|
||||||
(
|
|
||||||
dict.optionalSubDict("surfaceSensitivities")
|
|
||||||
);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SIBase::accumulateIntegrand(const scalar dt)
|
|
||||||
{
|
|
||||||
// Accumulate multiplier of dxFace/db
|
|
||||||
surfaceSensitivity_.accumulateIntegrand(dt);
|
|
||||||
|
|
||||||
// Accumulate direct sensitivities
|
|
||||||
if (includeObjective_)
|
|
||||||
{
|
|
||||||
accumulateDirectSensitivityIntegrand(dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Accumulate sensitivities due to boundary conditions
|
|
||||||
accumulateBCSensitivityIntegrand(dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SIBase::clearSensitivities()
|
|
||||||
{
|
|
||||||
surfaceSensitivity_.clearSensitivities();
|
|
||||||
shapeSensitivities::clearSensitivities();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const sensitivitySurface& SIBase::getSurfaceSensitivities() const
|
|
||||||
{
|
|
||||||
return surfaceSensitivity_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void SIBase::write(const word& baseName)
|
|
||||||
{
|
|
||||||
shapeSensitivities::write(baseName);
|
|
||||||
if (writeSensitivityMap_)
|
|
||||||
{
|
|
||||||
surfaceSensitivity_.write(baseName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
} // End namespace incompressible
|
|
||||||
} // End namespace Foam
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -1,219 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | www.openfoam.com
|
|
||||||
\\/ M anipulation |
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
Copyright (C) 2007-2022 PCOpt/NTUA
|
|
||||||
Copyright (C) 2013-2022 FOSS GP
|
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
License
|
|
||||||
This file is part of OpenFOAM.
|
|
||||||
|
|
||||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Class
|
|
||||||
Foam::incompressible::adjointSensitivity
|
|
||||||
|
|
||||||
Description
|
|
||||||
Abstract base class for adjoint-based sensitivities in incompressible flows
|
|
||||||
|
|
||||||
Reference:
|
|
||||||
\verbatim
|
|
||||||
For the FI and ESI formulations
|
|
||||||
Kavvadias, I., Papoutsis-Kiachagias, E., & Giannakoglou, K. (2015).
|
|
||||||
On the proper treatment of grid sensitivities in continuous adjoint
|
|
||||||
methods for shape optimization.
|
|
||||||
Journal of Computational Physics, 301, 1–18.
|
|
||||||
http://doi.org/10.1016/j.jcp.2015.08.012
|
|
||||||
|
|
||||||
For the SI formulation
|
|
||||||
Papoutsis-Kiachagias, E. M., & Giannakoglou, K. C. (2014).
|
|
||||||
Continuous Adjoint Methods for Turbulent Flows, Applied to Shape
|
|
||||||
and Topology Optimization: Industrial Applications.
|
|
||||||
Archives of Computational Methods in Engineering, 23(2), 255–299.
|
|
||||||
http://doi.org/10.1007/s11831-014-9141-9
|
|
||||||
\endverbatim
|
|
||||||
|
|
||||||
SourceFiles
|
|
||||||
adjointSensitivity.C
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#ifndef adjointSensitivityIncompressible_H
|
|
||||||
#define adjointSensitivityIncompressible_H
|
|
||||||
|
|
||||||
#include "sensitivity.H"
|
|
||||||
#include "incompressibleVars.H"
|
|
||||||
#include "incompressibleAdjointVars.H"
|
|
||||||
#include "wallFvPatch.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
|
|
||||||
// Forward declaration
|
|
||||||
class incompressibleAdjointSolver;
|
|
||||||
|
|
||||||
namespace incompressible
|
|
||||||
{
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
Class adjointSensitivity Declaration
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
class adjointSensitivity
|
|
||||||
:
|
|
||||||
public sensitivity
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
|
|
||||||
// Protected data
|
|
||||||
|
|
||||||
scalarField derivatives_;
|
|
||||||
incompressibleAdjointSolver& adjointSolver_;
|
|
||||||
const incompressibleVars& primalVars_;
|
|
||||||
incompressibleAdjointVars& adjointVars_;
|
|
||||||
objectiveManager& objectiveManager_;
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
// Private Member Functions
|
|
||||||
|
|
||||||
//- No copy construct
|
|
||||||
adjointSensitivity(const adjointSensitivity&) = delete;
|
|
||||||
|
|
||||||
//- No copy assignment
|
|
||||||
void operator=(const adjointSensitivity&) = delete;
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
//- Runtime type information
|
|
||||||
TypeName("adjointSensitivity");
|
|
||||||
|
|
||||||
|
|
||||||
// Declare run-time constructor selection table
|
|
||||||
|
|
||||||
declareRunTimeSelectionTable
|
|
||||||
(
|
|
||||||
autoPtr,
|
|
||||||
adjointSensitivity,
|
|
||||||
dictionary,
|
|
||||||
(
|
|
||||||
const fvMesh& mesh,
|
|
||||||
const dictionary& dict,
|
|
||||||
incompressibleAdjointSolver& adjointSolver
|
|
||||||
),
|
|
||||||
(
|
|
||||||
mesh,
|
|
||||||
dict,
|
|
||||||
adjointSolver
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
|
||||||
|
|
||||||
//- Construct from components
|
|
||||||
adjointSensitivity
|
|
||||||
(
|
|
||||||
const fvMesh& mesh,
|
|
||||||
const dictionary& dict,
|
|
||||||
incompressibleAdjointSolver& adjointSolver
|
|
||||||
);
|
|
||||||
|
|
||||||
// Selectors
|
|
||||||
|
|
||||||
//- Return a reference to the selected turbulence model
|
|
||||||
static autoPtr<adjointSensitivity> New
|
|
||||||
(
|
|
||||||
const fvMesh& mesh,
|
|
||||||
const dictionary& dict,
|
|
||||||
incompressibleAdjointSolver& adjointSolver
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
//- Destructor
|
|
||||||
virtual ~adjointSensitivity() = default;
|
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
|
||||||
|
|
||||||
//- Get primal variables
|
|
||||||
inline const incompressibleVars& primalVars() const
|
|
||||||
{
|
|
||||||
return primalVars_;
|
|
||||||
}
|
|
||||||
|
|
||||||
//- Get adjoint variables
|
|
||||||
inline const incompressibleAdjointVars& adjointVars() const
|
|
||||||
{
|
|
||||||
return adjointVars_;
|
|
||||||
}
|
|
||||||
|
|
||||||
//- Get adjoint solver
|
|
||||||
inline const incompressibleAdjointSolver& adjointSolver() const
|
|
||||||
{
|
|
||||||
return adjointSolver_;
|
|
||||||
}
|
|
||||||
|
|
||||||
//- Accumulate sensitivity integrands
|
|
||||||
// Corresponds to the flow and adjoint part of the sensitivities
|
|
||||||
virtual void accumulateIntegrand(const scalar dt) = 0;
|
|
||||||
|
|
||||||
//- Assemble sensitivities
|
|
||||||
// Adds the geometric part of the sensitivities
|
|
||||||
virtual void assembleSensitivities() = 0;
|
|
||||||
|
|
||||||
//- Calculates and returns sensitivity fields.
|
|
||||||
// Used with optimisation libraries
|
|
||||||
virtual const scalarField& calculateSensitivities();
|
|
||||||
|
|
||||||
//- Returns the sensitivity fields
|
|
||||||
// Assumes it has already been updated/computed
|
|
||||||
const scalarField& getSensitivities() const;
|
|
||||||
|
|
||||||
//- Zero sensitivity fields and their constituents
|
|
||||||
virtual void clearSensitivities();
|
|
||||||
|
|
||||||
//- Write sensitivity fields.
|
|
||||||
// If valid, copies boundaryFields to volFields and writes them.
|
|
||||||
// Virtual to be reimplemented by control points-based methods
|
|
||||||
// (Bezier, RBF) which do not need to write fields
|
|
||||||
virtual void write(const word& baseName = word::null);
|
|
||||||
|
|
||||||
//- Compute the volTensorField multiplying grad(dxdb) for
|
|
||||||
//- the volume-based approach to compute shape sensitivity derivatives
|
|
||||||
tmp<volTensorField> computeGradDxDbMultiplier();
|
|
||||||
|
|
||||||
//- Compute source term for adjoint mesh movement equation
|
|
||||||
tmp<volVectorField> adjointMeshMovementSource();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
} // End namespace incompressible
|
|
||||||
} // End namespace Foam
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -1,247 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | www.openfoam.com
|
|
||||||
\\/ M anipulation |
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
Copyright (C) 2007-2020 PCOpt/NTUA
|
|
||||||
Copyright (C) 2013-2020 FOSS GP
|
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
License
|
|
||||||
This file is part of OpenFOAM.
|
|
||||||
|
|
||||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "sensitivityBezierIncompressible.H"
|
|
||||||
#include "addToRunTimeSelectionTable.H"
|
|
||||||
#include "IOmanip.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
|
|
||||||
namespace incompressible
|
|
||||||
{
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
defineTypeNameAndDebug(sensitivityBezier, 0);
|
|
||||||
addToRunTimeSelectionTable
|
|
||||||
(
|
|
||||||
adjointSensitivity,
|
|
||||||
sensitivityBezier,
|
|
||||||
dictionary
|
|
||||||
);
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
sensitivityBezier::sensitivityBezier
|
|
||||||
(
|
|
||||||
const fvMesh& mesh,
|
|
||||||
const dictionary& dict,
|
|
||||||
incompressibleAdjointSolver& adjointSolver
|
|
||||||
)
|
|
||||||
:
|
|
||||||
SIBase(mesh, dict, adjointSolver),
|
|
||||||
//Bezier_(mesh, dict), // AJH Read locally?
|
|
||||||
Bezier_(mesh, mesh.lookupObject<IOdictionary>("optimisationDict")),
|
|
||||||
sens_(Bezier_.nBezier(), Zero),
|
|
||||||
flowSens_(Bezier_.nBezier(), Zero),
|
|
||||||
dSdbSens_(Bezier_.nBezier(), Zero),
|
|
||||||
dndbSens_(Bezier_.nBezier(), Zero),
|
|
||||||
dxdbDirectSens_(Bezier_.nBezier(), Zero),
|
|
||||||
bcSens_(Bezier_.nBezier(), Zero),
|
|
||||||
derivativesFolder_("optimisation"/type() + "Derivatives")
|
|
||||||
{
|
|
||||||
derivatives_ = scalarField(3*Bezier_.nBezier(), Zero);
|
|
||||||
// Create folder to store sensitivities
|
|
||||||
mkDir(derivativesFolder_);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
void sensitivityBezier::assembleSensitivities()
|
|
||||||
{
|
|
||||||
// Assemble the sensitivity map
|
|
||||||
// Solves for the post-processing equations and adds their contribution to
|
|
||||||
// the sensitivity map
|
|
||||||
surfaceSensitivity_.assembleSensitivities();
|
|
||||||
|
|
||||||
forAll(sens_, iCP)
|
|
||||||
{
|
|
||||||
// Face-based summation. More robust since the result is independent of
|
|
||||||
// the number of processors (does not hold for a point-based summation)
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
// Interpolate parameterization info to faces
|
|
||||||
tmp<tensorField> tdxidXj = Bezier_.dxdbFace(patchI, iCP);
|
|
||||||
const tensorField& dxidXj = tdxidXj();
|
|
||||||
|
|
||||||
// Patch sensitivity map
|
|
||||||
const vectorField& patchSensMap =
|
|
||||||
surfaceSensitivity_.getWallFaceSensVecBoundary()[patchI];
|
|
||||||
flowSens_[iCP] += gSum(patchSensMap & dxidXj);
|
|
||||||
|
|
||||||
if (includeObjective_)
|
|
||||||
{
|
|
||||||
// Contribution from objective function
|
|
||||||
// term from delta( n dS ) / delta b and
|
|
||||||
// term from delta( n ) / delta b
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
tmp<tensorField> tdSdb
|
|
||||||
(
|
|
||||||
Bezier_.dndbBasedSensitivities(patchI, iCP)
|
|
||||||
);
|
|
||||||
const tensorField& dSdb = tdSdb();
|
|
||||||
dSdbSens_[iCP] += gSum(dSfdbMult_()[patchI] & dSdb);
|
|
||||||
|
|
||||||
tmp<tensorField> tdndb
|
|
||||||
(
|
|
||||||
Bezier_.dndbBasedSensitivities(patchI, iCP, false)
|
|
||||||
);
|
|
||||||
const tensorField& dndb = tdndb();
|
|
||||||
dndbSens_[iCP] += gSum((dnfdbMult_()[patchI] & dndb));
|
|
||||||
|
|
||||||
// Contribution from objective function
|
|
||||||
// term from delta( x ) / delta b
|
|
||||||
// Only for objectives directly including
|
|
||||||
// x, like moments
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
dxdbDirectSens_[iCP] +=
|
|
||||||
gSum((dxdbDirectMult_()[patchI] & dxidXj));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sensitivities from boundary conditions
|
|
||||||
bcSens_[iCP] += gSum(bcDxDbMult_()[patchI] & dxidXj);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sens_ = flowSens_ + dSdbSens_ + dndbSens_ + dxdbDirectSens_ + bcSens_;
|
|
||||||
|
|
||||||
// Transform sensitivities to scalarField in order to cooperate with
|
|
||||||
// updateMethod
|
|
||||||
label nBezier = Bezier_.nBezier();
|
|
||||||
forAll(sens_, cpI)
|
|
||||||
{
|
|
||||||
derivatives_[cpI] = sens_[cpI].x();
|
|
||||||
derivatives_[cpI + nBezier] = sens_[cpI].y();
|
|
||||||
derivatives_[cpI + 2*nBezier] = sens_[cpI].z();
|
|
||||||
const boolList& confineXmovement = Bezier_.confineXmovement();
|
|
||||||
const boolList& confineYmovement = Bezier_.confineYmovement();
|
|
||||||
const boolList& confineZmovement = Bezier_.confineZmovement();
|
|
||||||
if (confineXmovement[cpI])
|
|
||||||
{
|
|
||||||
derivatives_[cpI] *= scalar(0);
|
|
||||||
flowSens_[cpI].x() = Zero;
|
|
||||||
dSdbSens_[cpI].x() = Zero;
|
|
||||||
dndbSens_[cpI].x() = Zero;
|
|
||||||
dxdbDirectSens_[cpI].x() = Zero;
|
|
||||||
bcSens_[cpI].x() = Zero;
|
|
||||||
}
|
|
||||||
if (confineYmovement[cpI])
|
|
||||||
{
|
|
||||||
derivatives_[cpI + nBezier] *= scalar(0);
|
|
||||||
flowSens_[cpI].y() = Zero;
|
|
||||||
dSdbSens_[cpI].y() = Zero;
|
|
||||||
dndbSens_[cpI].y() = Zero;
|
|
||||||
dxdbDirectSens_[cpI].y() = Zero;
|
|
||||||
bcSens_[cpI].y() = Zero;
|
|
||||||
}
|
|
||||||
if (confineZmovement[cpI])
|
|
||||||
{
|
|
||||||
derivatives_[cpI + 2*nBezier] *= scalar(0);
|
|
||||||
flowSens_[cpI].z() = Zero;
|
|
||||||
dSdbSens_[cpI].z() = Zero;
|
|
||||||
dndbSens_[cpI].z() = Zero;
|
|
||||||
dxdbDirectSens_[cpI].z() = Zero;
|
|
||||||
bcSens_[cpI].z() = Zero;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void sensitivityBezier::clearSensitivities()
|
|
||||||
{
|
|
||||||
sens_ = Zero;
|
|
||||||
flowSens_ = Zero;
|
|
||||||
dSdbSens_ = Zero;
|
|
||||||
dndbSens_ = Zero;
|
|
||||||
dxdbDirectSens_ = Zero;
|
|
||||||
bcSens_ = Zero;
|
|
||||||
|
|
||||||
SIBase::clearSensitivities();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void sensitivityBezier::write(const word& baseName)
|
|
||||||
{
|
|
||||||
Info<< "Writing control point sensitivities to file" << endl;
|
|
||||||
// Write sensitivity map
|
|
||||||
SIBase::write(baseName);
|
|
||||||
// Write control point sensitivities
|
|
||||||
if (Pstream::master())
|
|
||||||
{
|
|
||||||
OFstream derivFile
|
|
||||||
(
|
|
||||||
derivativesFolder_/
|
|
||||||
baseName + adjointVars_.solverName() + mesh_.time().timeName()
|
|
||||||
);
|
|
||||||
unsigned int widthDV = max(int(name(sens_.size()).size()), int(3));
|
|
||||||
unsigned int width = IOstream::defaultPrecision() + 7;
|
|
||||||
derivFile
|
|
||||||
<< setw(widthDV) << "#dv" << " "
|
|
||||||
<< setw(width) << "total" << " "
|
|
||||||
<< setw(width) << "flow" << " "
|
|
||||||
<< setw(width) << "dSdb" << " "
|
|
||||||
<< setw(width) << "dndb" << " "
|
|
||||||
<< setw(width) << "dxdbDirect" << " "
|
|
||||||
<< setw(width) << "dvdb" << endl;
|
|
||||||
label nDV = derivatives_.size();
|
|
||||||
label nBezier = Bezier_.nBezier();
|
|
||||||
const boolListList& confineMovement = Bezier_.confineMovement();
|
|
||||||
label lastActive(-1);
|
|
||||||
for (label iDV = 0; iDV < nDV; iDV++)
|
|
||||||
{
|
|
||||||
label iCP = iDV%nBezier;
|
|
||||||
label idir = iDV/nBezier;
|
|
||||||
if (!confineMovement[idir][iCP])
|
|
||||||
{
|
|
||||||
if (iDV!=lastActive + 1) derivFile << "\n";
|
|
||||||
lastActive = iDV;
|
|
||||||
derivFile
|
|
||||||
<< setw(widthDV) << iDV << " "
|
|
||||||
<< setw(width) << derivatives_[iDV] << " "
|
|
||||||
<< setw(width) << flowSens_[iCP].component(idir) << " "
|
|
||||||
<< setw(width) << dSdbSens_[iCP].component(idir) << " "
|
|
||||||
<< setw(width) << dndbSens_[iCP].component(idir) << " "
|
|
||||||
<< setw(width) << dxdbDirectSens_[iCP].component(idir) << " "
|
|
||||||
<< setw(width) << bcSens_[iCP].component(idir)
|
|
||||||
<< endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
} // End namespace incompressible
|
|
||||||
} // End namespace Foam
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -1,136 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | www.openfoam.com
|
|
||||||
\\/ M anipulation |
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
Copyright (C) 2007-2020 PCOpt/NTUA
|
|
||||||
Copyright (C) 2013-2020 FOSS GP
|
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
License
|
|
||||||
This file is part of OpenFOAM.
|
|
||||||
|
|
||||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Class
|
|
||||||
Foam::incompressible::sensitivityBezier
|
|
||||||
|
|
||||||
Description
|
|
||||||
Calculation of adjoint based sensitivities for Bezier control points
|
|
||||||
|
|
||||||
SourceFiles
|
|
||||||
sensitivityBezier.C
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#ifndef Foam_sensitivityBezierIncompressible_H
|
|
||||||
#define Foam_sensitivityBezierIncompressible_H
|
|
||||||
|
|
||||||
#include "primitiveFieldsFwd.H"
|
|
||||||
#include "volFieldsFwd.H"
|
|
||||||
#include "pointFieldsFwd.H"
|
|
||||||
#include "surfaceFieldsFwd.H"
|
|
||||||
#include "volPointInterpolation.H"
|
|
||||||
#include "SIBaseIncompressible.H"
|
|
||||||
#include "primitivePatchInterpolation.H"
|
|
||||||
#include "deltaBoundary.H"
|
|
||||||
#include "Bezier.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
|
|
||||||
namespace incompressible
|
|
||||||
{
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
Class sensitivityBezier Declaration
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
class sensitivityBezier
|
|
||||||
:
|
|
||||||
public SIBase
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
|
|
||||||
// Protected data
|
|
||||||
|
|
||||||
Bezier Bezier_;
|
|
||||||
|
|
||||||
vectorField sens_;
|
|
||||||
vectorField flowSens_;
|
|
||||||
vectorField dSdbSens_;
|
|
||||||
vectorField dndbSens_;
|
|
||||||
vectorField dxdbDirectSens_;
|
|
||||||
vectorField bcSens_;
|
|
||||||
|
|
||||||
fileName derivativesFolder_;
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
// Private Member Functions
|
|
||||||
|
|
||||||
//- No copy construct
|
|
||||||
sensitivityBezier(const sensitivityBezier&) = delete;
|
|
||||||
|
|
||||||
//- No copy assignment
|
|
||||||
void operator=(const sensitivityBezier&) = delete;
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
//- Runtime type information
|
|
||||||
TypeName("Bezier");
|
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
|
||||||
|
|
||||||
//- Construct from components
|
|
||||||
sensitivityBezier
|
|
||||||
(
|
|
||||||
const fvMesh& mesh,
|
|
||||||
const dictionary& dict,
|
|
||||||
incompressibleAdjointSolver& adjointSolver
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
//- Destructor
|
|
||||||
virtual ~sensitivityBezier() = default;
|
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
|
||||||
|
|
||||||
//- Assemble sensitivities
|
|
||||||
virtual void assembleSensitivities();
|
|
||||||
|
|
||||||
//- Zero sensitivity fields and their constituents
|
|
||||||
virtual void clearSensitivities();
|
|
||||||
|
|
||||||
//- Write sensitivities to file
|
|
||||||
virtual void write(const word& baseName = word::null);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
} // End namespace incompressible
|
|
||||||
} // End namespace Foam
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@ -1,368 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | www.openfoam.com
|
|
||||||
\\/ M anipulation |
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
Copyright (C) 2007-2020 PCOpt/NTUA
|
|
||||||
Copyright (C) 2013-2020 FOSS GP
|
|
||||||
Copyright (C) 2019-2020 OpenCFD Ltd.
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
License
|
|
||||||
This file is part of OpenFOAM.
|
|
||||||
|
|
||||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "sensitivityBezierFIIncompressible.H"
|
|
||||||
#include "addToRunTimeSelectionTable.H"
|
|
||||||
#include "IOmanip.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
|
|
||||||
namespace incompressible
|
|
||||||
{
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
defineTypeNameAndDebug(sensitivityBezierFI, 0);
|
|
||||||
addToRunTimeSelectionTable
|
|
||||||
(
|
|
||||||
adjointSensitivity, sensitivityBezierFI, dictionary
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
void sensitivityBezierFI::read()
|
|
||||||
{
|
|
||||||
// Laplace solution controls
|
|
||||||
const dictionary dxdbDict = dict_.subOrEmptyDict("dxdbSolver");
|
|
||||||
meshMovementIters_ = dxdbDict.getOrDefault<label>("iters", 1000);
|
|
||||||
meshMovementResidualLimit_ =
|
|
||||||
dxdbDict.getOrDefault<scalar>("tolerance", 1.e-07);
|
|
||||||
|
|
||||||
// Read variables related to the adjoint eikonal solver
|
|
||||||
FIBase::read();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
tmp<volVectorField> sensitivityBezierFI::solveMeshMovementEqn
|
|
||||||
(
|
|
||||||
const label iCP,
|
|
||||||
const label idir
|
|
||||||
)
|
|
||||||
{
|
|
||||||
read();
|
|
||||||
tmp<volVectorField> tm(new volVectorField("m", dxdb_));
|
|
||||||
volVectorField& m = tm.ref();
|
|
||||||
|
|
||||||
// SOLVE FOR DXDB
|
|
||||||
//~~~~~~~~~~~~~~~~
|
|
||||||
// set boundary conditions
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
// interpolate parameterization info to faces
|
|
||||||
tmp<vectorField> tdxidXjFace = Bezier_.dxdbFace(patchI, iCP, idir);
|
|
||||||
const vectorField& dxidXjFace = tdxidXjFace();
|
|
||||||
|
|
||||||
m.boundaryFieldRef()[patchI] == dxidXjFace;
|
|
||||||
}
|
|
||||||
|
|
||||||
// iterate the adjoint to the eikonal equation
|
|
||||||
for (label iter = 0; iter < meshMovementIters_; iter++)
|
|
||||||
{
|
|
||||||
Info<< "Mesh Movement Propagation(direction, CP), ("
|
|
||||||
<< idir << ", " << iCP << "), Iteration : "<< iter << endl;
|
|
||||||
|
|
||||||
fvVectorMatrix mEqn
|
|
||||||
(
|
|
||||||
fvm::laplacian(m)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Scalar residual = max(mEqn.solve().initialResidual());
|
|
||||||
scalar residual = mag(mEqn.solve().initialResidual());
|
|
||||||
|
|
||||||
Info<< "Max dxdb " << gMax(mag(m)()) << endl;
|
|
||||||
|
|
||||||
mesh_.time().printExecutionTime(Info);
|
|
||||||
|
|
||||||
// Check convergence
|
|
||||||
if (residual < meshMovementResidualLimit_)
|
|
||||||
{
|
|
||||||
Info<< "\n***Reached dxdb convergence limit, iteration " << iter
|
|
||||||
<< "***\n\n";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return tm;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
sensitivityBezierFI::sensitivityBezierFI
|
|
||||||
(
|
|
||||||
const fvMesh& mesh,
|
|
||||||
const dictionary& dict,
|
|
||||||
incompressibleAdjointSolver& adjointSolver
|
|
||||||
)
|
|
||||||
:
|
|
||||||
FIBase(mesh, dict, adjointSolver),
|
|
||||||
//Bezier_(mesh, dict), // AJH Read locally?
|
|
||||||
Bezier_(mesh, mesh.lookupObject<IOdictionary>("optimisationDict")),
|
|
||||||
flowSens_(3*Bezier_.nBezier(), Zero),
|
|
||||||
dSdbSens_(3*Bezier_.nBezier(), Zero),
|
|
||||||
dndbSens_(3*Bezier_.nBezier(), Zero),
|
|
||||||
dxdbDirectSens_(3*Bezier_.nBezier(), Zero),
|
|
||||||
dVdbSens_(3*Bezier_.nBezier(), Zero),
|
|
||||||
distanceSens_(3*Bezier_.nBezier(), Zero),
|
|
||||||
optionsSens_(3*Bezier_.nBezier(), Zero),
|
|
||||||
bcSens_(3*Bezier_.nBezier(), Zero),
|
|
||||||
|
|
||||||
derivativesFolder_("optimisation"/type() + "Derivatives"),
|
|
||||||
|
|
||||||
meshMovementIters_(-1),
|
|
||||||
meshMovementResidualLimit_(1.e-7),
|
|
||||||
dxdb_
|
|
||||||
(
|
|
||||||
variablesSet::autoCreateMeshMovementField
|
|
||||||
(
|
|
||||||
mesh,
|
|
||||||
"mTilda",
|
|
||||||
dimensionSet(dimLength)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
{
|
|
||||||
read();
|
|
||||||
|
|
||||||
derivatives_ = scalarField(3*Bezier_.nBezier(), Zero),
|
|
||||||
// Create folder to store sensitivities
|
|
||||||
mkDir(derivativesFolder_);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
void sensitivityBezierFI::assembleSensitivities()
|
|
||||||
{
|
|
||||||
// Adjoint to the eikonal equation
|
|
||||||
autoPtr<volTensorField> distanceSensPtr(nullptr);
|
|
||||||
if (includeDistance_)
|
|
||||||
{
|
|
||||||
// Solver equation
|
|
||||||
eikonalSolver_->solve();
|
|
||||||
|
|
||||||
// Allocate memory and compute grad(dxdb) multiplier
|
|
||||||
distanceSensPtr.reset
|
|
||||||
(
|
|
||||||
createZeroFieldPtr<tensor>
|
|
||||||
(
|
|
||||||
mesh_,
|
|
||||||
"distanceSensPtr",
|
|
||||||
dimensionSet(0, 2, -3, 0, 0, 0, 0)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
distanceSensPtr() = eikonalSolver_->getFISensitivityTerm()().T();
|
|
||||||
}
|
|
||||||
|
|
||||||
const label nBezier = Bezier_.nBezier();
|
|
||||||
const label nDVs = 3*nBezier;
|
|
||||||
for (label iDV = 0; iDV < nDVs; iDV++)
|
|
||||||
{
|
|
||||||
label iCP = iDV%nBezier;
|
|
||||||
label idir = iDV/nBezier;
|
|
||||||
if
|
|
||||||
(
|
|
||||||
(idir == 0 && Bezier_.confineXmovement()[iCP])
|
|
||||||
|| (idir == 1 && Bezier_.confineYmovement()[iCP])
|
|
||||||
|| (idir == 2 && Bezier_.confineZmovement()[iCP])
|
|
||||||
)
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Flow term
|
|
||||||
// ~~~~~~~~~~~
|
|
||||||
// compute dxdb and its grad
|
|
||||||
tmp<volVectorField> tm = solveMeshMovementEqn(iCP, idir);
|
|
||||||
const volVectorField& m = tm();
|
|
||||||
volTensorField gradDxDb(fvc::grad(m, "grad(dxdb)"));
|
|
||||||
|
|
||||||
flowSens_[iDV] =
|
|
||||||
gSum
|
|
||||||
(
|
|
||||||
(gradDxDb.primitiveField() && gradDxDbMult_.primitiveField())
|
|
||||||
* mesh_.V()
|
|
||||||
);
|
|
||||||
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
// Contribution from objective function
|
|
||||||
// term from delta(n dS)/delta b and
|
|
||||||
// term from delta(n)/delta b
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
tmp<vectorField> tdSdb =
|
|
||||||
Bezier_.dndbBasedSensitivities(patchI, iCP, idir);
|
|
||||||
const vectorField& dSdb = tdSdb();
|
|
||||||
tmp<vectorField> tdndb =
|
|
||||||
Bezier_.dndbBasedSensitivities(patchI, iCP, idir, false);
|
|
||||||
const vectorField& dndb = tdndb();
|
|
||||||
dSdbSens_[iDV] += gSum(dSfdbMult_()[patchI] & dSdb);
|
|
||||||
dndbSens_[iDV] += gSum(dnfdbMult_()[patchI] & dndb);
|
|
||||||
|
|
||||||
// Contribution from objective function
|
|
||||||
// term from delta( x ) / delta b
|
|
||||||
// Only for objectives directly including
|
|
||||||
// x, like moments
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
tmp<vectorField> tdxdbFace =
|
|
||||||
Bezier_.dxdbFace(patchI, iCP, idir);
|
|
||||||
const vectorField& dxdbFace = tdxdbFace();
|
|
||||||
dxdbDirectSens_[iDV] +=
|
|
||||||
gSum(dxdbDirectMult_()[patchI] & dxdbFace);
|
|
||||||
|
|
||||||
// Contribution from boundary conditions
|
|
||||||
bcSens_[iDV] += gSum(bcDxDbMult_()[patchI] & dxdbFace);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Contribution from delta (V) / delta b
|
|
||||||
// For objectives defined as volume integrals only
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
dVdbSens_[iDV] =
|
|
||||||
gSum
|
|
||||||
(
|
|
||||||
divDxDbMult_
|
|
||||||
* fvc::div(m)().primitiveField()
|
|
||||||
* mesh_.V()
|
|
||||||
);
|
|
||||||
|
|
||||||
// Distance dependent term
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
if (includeDistance_)
|
|
||||||
{
|
|
||||||
distanceSens_[iDV] =
|
|
||||||
gSum
|
|
||||||
(
|
|
||||||
(
|
|
||||||
distanceSensPtr().primitiveField()
|
|
||||||
&& gradDxDb.primitiveField()
|
|
||||||
)
|
|
||||||
*mesh_.V()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Terms from fvOptions
|
|
||||||
optionsSens_[iDV] +=
|
|
||||||
gSum((optionsDxDbMult_ & m.primitiveField())*mesh_.V());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sum contributions
|
|
||||||
derivatives_ =
|
|
||||||
flowSens_
|
|
||||||
+ dSdbSens_
|
|
||||||
+ dndbSens_
|
|
||||||
+ dxdbDirectSens_
|
|
||||||
+ dVdbSens_
|
|
||||||
+ distanceSens_
|
|
||||||
+ optionsSens_
|
|
||||||
+ bcSens_;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void sensitivityBezierFI::clearSensitivities()
|
|
||||||
{
|
|
||||||
flowSens_ = Zero;
|
|
||||||
dSdbSens_ = Zero;
|
|
||||||
dndbSens_ = Zero;
|
|
||||||
dxdbDirectSens_ = Zero;
|
|
||||||
dVdbSens_ = Zero;
|
|
||||||
distanceSens_ = Zero;
|
|
||||||
optionsSens_ = Zero;
|
|
||||||
bcSens_ = Zero;
|
|
||||||
|
|
||||||
FIBase::clearSensitivities();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void sensitivityBezierFI::write(const word& baseName)
|
|
||||||
{
|
|
||||||
Info<< "Writing control point sensitivities to file" << endl;
|
|
||||||
if (Pstream::master())
|
|
||||||
{
|
|
||||||
OFstream derivFile
|
|
||||||
(
|
|
||||||
derivativesFolder_/
|
|
||||||
baseName + adjointVars_.solverName() + mesh_.time().timeName()
|
|
||||||
);
|
|
||||||
unsigned int widthDV = max(int(name(flowSens_.size()).size()), int(3));
|
|
||||||
unsigned int width = IOstream::defaultPrecision() + 7;
|
|
||||||
derivFile
|
|
||||||
<< setw(widthDV) << "#dv" << " "
|
|
||||||
<< setw(width) << "total" << " "
|
|
||||||
<< setw(width) << "flow" << " "
|
|
||||||
<< setw(width) << "dSdb" << " "
|
|
||||||
<< setw(width) << "dndb" << " "
|
|
||||||
<< setw(width) << "dxdbDirect" << " "
|
|
||||||
<< setw(width) << "dVdb" << " "
|
|
||||||
<< setw(width) << "distance" << " "
|
|
||||||
<< setw(width) << "options" << " "
|
|
||||||
<< setw(width) << "dvdb" << endl;
|
|
||||||
const label nDVs = derivatives_.size();
|
|
||||||
const label nBezier = Bezier_.nBezier();
|
|
||||||
const boolListList& confineMovement = Bezier_.confineMovement();
|
|
||||||
label lastActive(-1);
|
|
||||||
|
|
||||||
for (label iDV = 0; iDV < nDVs; iDV++)
|
|
||||||
{
|
|
||||||
const label iCP(iDV%nBezier);
|
|
||||||
const label idir(iDV/nBezier);
|
|
||||||
if (!confineMovement[idir][iCP])
|
|
||||||
{
|
|
||||||
if (iDV!=lastActive + 1)
|
|
||||||
{
|
|
||||||
derivFile << "\n";
|
|
||||||
}
|
|
||||||
lastActive = iDV;
|
|
||||||
derivFile
|
|
||||||
<< setw(widthDV) << iDV << " "
|
|
||||||
<< setw(width) << derivatives_[iDV] << " "
|
|
||||||
<< setw(width) << flowSens_[iDV] << " "
|
|
||||||
<< setw(width) << dSdbSens_[iDV] << " "
|
|
||||||
<< setw(width) << dndbSens_[iDV] << " "
|
|
||||||
<< setw(width) << dxdbDirectSens_[iDV] << " "
|
|
||||||
<< setw(width) << dVdbSens_[iDV] << " "
|
|
||||||
<< setw(width) << distanceSens_[iDV] << " "
|
|
||||||
<< setw(width) << optionsSens_[iDV] << " "
|
|
||||||
<< setw(width) << bcSens_[iDV] << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
} // End namespace incompressible
|
|
||||||
} // End namespace Foam
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -1,168 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | www.openfoam.com
|
|
||||||
\\/ M anipulation |
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
Copyright (C) 2007-2020 PCOpt/NTUA
|
|
||||||
Copyright (C) 2013-2020 FOSS GP
|
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
License
|
|
||||||
This file is part of OpenFOAM.
|
|
||||||
|
|
||||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Class
|
|
||||||
Foam::incompressible::sensitivityBezierFI
|
|
||||||
|
|
||||||
Description
|
|
||||||
Calculation of adjoint based sensitivities for Bezier control points
|
|
||||||
using the FI appoach
|
|
||||||
|
|
||||||
SourceFiles
|
|
||||||
sensitivityBezierFI.C
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#ifndef sensitivityBezierFIIncompressible_H
|
|
||||||
#define sensitivityBezierFIIncompressible_H
|
|
||||||
|
|
||||||
#include "primitiveFieldsFwd.H"
|
|
||||||
#include "volFieldsFwd.H"
|
|
||||||
#include "pointFieldsFwd.H"
|
|
||||||
#include "surfaceFieldsFwd.H"
|
|
||||||
#include "volPointInterpolation.H"
|
|
||||||
#include "FIBaseIncompressible.H"
|
|
||||||
#include "primitivePatchInterpolation.H"
|
|
||||||
#include "deltaBoundary.H"
|
|
||||||
#include "Bezier.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
|
|
||||||
namespace incompressible
|
|
||||||
{
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
Class sensitivityBezierFI Declaration
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
class sensitivityBezierFI
|
|
||||||
:
|
|
||||||
public FIBase
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
|
|
||||||
// Protected data
|
|
||||||
Bezier Bezier_;
|
|
||||||
|
|
||||||
//- Flow related term
|
|
||||||
scalarField flowSens_;
|
|
||||||
|
|
||||||
//- Term depending on delta(n dS)/delta b
|
|
||||||
scalarField dSdbSens_;
|
|
||||||
|
|
||||||
//- Term depending on delta(n)/delta b
|
|
||||||
scalarField dndbSens_;
|
|
||||||
|
|
||||||
//- Term depending on delta(x)/delta b for objectives that directly
|
|
||||||
//- depend on x
|
|
||||||
scalarField dxdbDirectSens_;
|
|
||||||
|
|
||||||
//- Term depending on delta(V)/delta b
|
|
||||||
scalarField dVdbSens_;
|
|
||||||
|
|
||||||
//- Term depending on distance differentiation
|
|
||||||
scalarField distanceSens_;
|
|
||||||
|
|
||||||
//- Term depending on fvOptions
|
|
||||||
scalarField optionsSens_;
|
|
||||||
|
|
||||||
//- Term depending on the differenation of boundary conditions
|
|
||||||
scalarField bcSens_;
|
|
||||||
|
|
||||||
fileName derivativesFolder_;
|
|
||||||
|
|
||||||
label meshMovementIters_;
|
|
||||||
scalar meshMovementResidualLimit_;
|
|
||||||
volVectorField dxdb_;
|
|
||||||
|
|
||||||
void read();
|
|
||||||
|
|
||||||
tmp<volVectorField> solveMeshMovementEqn
|
|
||||||
(
|
|
||||||
const label iCP,
|
|
||||||
const label idir
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
// Private Member Functions
|
|
||||||
|
|
||||||
//- No copy construct
|
|
||||||
sensitivityBezierFI(const sensitivityBezierFI&) = delete;
|
|
||||||
|
|
||||||
//- No copy assignment
|
|
||||||
void operator=(const sensitivityBezierFI&) = delete;
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
//- Runtime type information
|
|
||||||
TypeName("BezierFI");
|
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
|
||||||
|
|
||||||
//- Construct from components
|
|
||||||
sensitivityBezierFI
|
|
||||||
(
|
|
||||||
const fvMesh& mesh,
|
|
||||||
const dictionary& dict,
|
|
||||||
incompressibleAdjointSolver& adjointSolver
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
//- Destructor
|
|
||||||
virtual ~sensitivityBezierFI() = default;
|
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
|
||||||
|
|
||||||
//- Assemble sensitivities
|
|
||||||
virtual void assembleSensitivities();
|
|
||||||
|
|
||||||
//- Zero sensitivity fields and their constituents
|
|
||||||
virtual void clearSensitivities();
|
|
||||||
|
|
||||||
//- Write sensitivities to file
|
|
||||||
virtual void write(const word& baseName = word::null);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
} // End namespace incompressible
|
|
||||||
} // End namespace Foam
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -1,946 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | www.openfoam.com
|
|
||||||
\\/ M anipulation |
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
Copyright (C) 2007-2021 PCOpt/NTUA
|
|
||||||
Copyright (C) 2013-2021 FOSS GP
|
|
||||||
Copyright (C) 2019-2020 OpenCFD Ltd.
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
License
|
|
||||||
This file is part of OpenFOAM.
|
|
||||||
|
|
||||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "sensitivitySurfaceIncompressible.H"
|
|
||||||
#include "incompressibleAdjointSolver.H"
|
|
||||||
#include "primitivePatchInterpolation.H"
|
|
||||||
#include "syncTools.H"
|
|
||||||
#include "addToRunTimeSelectionTable.H"
|
|
||||||
#include "faMatrices.H"
|
|
||||||
#include "famSup.H"
|
|
||||||
#include "famLaplacian.H"
|
|
||||||
#include "volSurfaceMapping.H"
|
|
||||||
#include "fixedValueFaPatchFields.H"
|
|
||||||
#include "zeroGradientFaPatchFields.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
|
|
||||||
namespace incompressible
|
|
||||||
{
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
defineTypeNameAndDebug(sensitivitySurface, 1);
|
|
||||||
addToRunTimeSelectionTable
|
|
||||||
(
|
|
||||||
adjointSensitivity,
|
|
||||||
sensitivitySurface,
|
|
||||||
dictionary
|
|
||||||
);
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
|
||||||
|
|
||||||
void sensitivitySurface::addGeometricSens()
|
|
||||||
{
|
|
||||||
if (includeObjective_)
|
|
||||||
{
|
|
||||||
// Grab objective refs
|
|
||||||
PtrList<objective>& functions
|
|
||||||
(objectiveManager_.getObjectiveFunctions());
|
|
||||||
// Compute sens for all points in parameterized patches.
|
|
||||||
// Interfacing points will be accumulated later
|
|
||||||
autoPtr<pointBoundaryVectorField> pointSensdSdb
|
|
||||||
(
|
|
||||||
createZeroBoundaryPointFieldPtr<vector>(mesh_)
|
|
||||||
);
|
|
||||||
autoPtr<pointBoundaryVectorField> pointSensdndb
|
|
||||||
(
|
|
||||||
createZeroBoundaryPointFieldPtr<vector>(mesh_)
|
|
||||||
);
|
|
||||||
// Geometric (or "direct") sensitivities are better computed directly
|
|
||||||
// on the points
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
const fvPatch& patch = mesh_.boundary()[patchI];
|
|
||||||
const vectorField nf(patch.nf());
|
|
||||||
|
|
||||||
// point sens result for patch
|
|
||||||
vectorField& patchdSdb = pointSensdSdb()[patchI];
|
|
||||||
vectorField& patchdndb = pointSensdndb()[patchI];
|
|
||||||
|
|
||||||
vectorField dSdbMultiplierTot(patch.size(), Zero);
|
|
||||||
vectorField dndbMultiplierTot(patch.size(), Zero);
|
|
||||||
for (auto& fun : functions)
|
|
||||||
{
|
|
||||||
dSdbMultiplierTot += fun.weight()*fun.dSdbMultiplier(patchI);
|
|
||||||
dndbMultiplierTot += fun.weight()*fun.dndbMultiplier(patchI);
|
|
||||||
}
|
|
||||||
// Correspondence of local point addressing to global point
|
|
||||||
// addressing
|
|
||||||
const labelList& meshPoints = patch.patch().meshPoints();
|
|
||||||
// List with mesh faces. Global addressing
|
|
||||||
const faceList& faces = mesh_.faces();
|
|
||||||
// Each local patch point belongs to these local patch faces
|
|
||||||
// (local numbering)
|
|
||||||
const labelListList& patchPointFaces = patch.patch().pointFaces();
|
|
||||||
// index of first face in patch
|
|
||||||
const label patchStartIndex = patch.start();
|
|
||||||
// geometry differentiation engine
|
|
||||||
deltaBoundary dBoundary(mesh_);
|
|
||||||
// Loop over patch points.
|
|
||||||
// Collect contributions from each boundary face this point
|
|
||||||
// belongs to
|
|
||||||
forAll(meshPoints, ppI)
|
|
||||||
{
|
|
||||||
const labelList& pointFaces = patchPointFaces[ppI];
|
|
||||||
for (label localFaceIndex : pointFaces)
|
|
||||||
{
|
|
||||||
label globalFaceIndex = patchStartIndex + localFaceIndex;
|
|
||||||
const face& faceI = faces[globalFaceIndex];
|
|
||||||
// Point coordinates. All indices in global numbering
|
|
||||||
const pointField p(faceI.points(mesh_.points()));
|
|
||||||
tensorField p_d(faceI.size(), Zero);
|
|
||||||
forAll(faceI, facePointI)
|
|
||||||
{
|
|
||||||
if (faceI[facePointI] == meshPoints[ppI])
|
|
||||||
{
|
|
||||||
p_d[facePointI] = tensor::I;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
const tensorField deltaNormals
|
|
||||||
(
|
|
||||||
dBoundary.makeFaceCentresAndAreas_d(p, p_d)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Element [1] is the variation in the (dimensional) normal
|
|
||||||
const tensor& deltaSf = deltaNormals[1];
|
|
||||||
patchdSdb[ppI] +=
|
|
||||||
dSdbMultiplierTot[localFaceIndex] & deltaSf;
|
|
||||||
|
|
||||||
// Element [2] is the variation in the unit normal
|
|
||||||
const tensor& deltaNf = deltaNormals[2];
|
|
||||||
patchdndb[ppI] +=
|
|
||||||
dndbMultiplierTot[localFaceIndex] & deltaNf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Do parallel communications to avoid wrong values at processor
|
|
||||||
// boundaries
|
|
||||||
vectorField dSdbGlobal(mesh_.nPoints(), Zero);
|
|
||||||
vectorField dndbGlobal(mesh_.nPoints(), Zero);
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
const labelList& meshPoints =
|
|
||||||
mesh_.boundaryMesh()[patchI].meshPoints();
|
|
||||||
forAll(meshPoints, ppI)
|
|
||||||
{
|
|
||||||
const label globaPointI = meshPoints[ppI];
|
|
||||||
dSdbGlobal[globaPointI] += pointSensdSdb()[patchI][ppI];
|
|
||||||
dndbGlobal[globaPointI] += pointSensdndb()[patchI][ppI];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Accumulate over processors
|
|
||||||
syncTools::syncPointList
|
|
||||||
(
|
|
||||||
mesh_, dSdbGlobal, plusEqOp<vector>(), vector::zero
|
|
||||||
);
|
|
||||||
syncTools::syncPointList
|
|
||||||
(
|
|
||||||
mesh_, dndbGlobal, plusEqOp<vector>(), vector::zero
|
|
||||||
);
|
|
||||||
// Transfer back to local fields and map to faces
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
const fvPatch& patch = mesh_.boundary()[patchI];
|
|
||||||
const labelList& meshPoints = patch.patch().meshPoints();
|
|
||||||
const scalarField& magSf = patch.magSf();
|
|
||||||
pointSensdSdb()[patchI].map(dSdbGlobal, meshPoints);
|
|
||||||
pointSensdndb()[patchI].map(dndbGlobal, meshPoints);
|
|
||||||
// Map dSf/dx and dnf/dx term from points to faces. Ideally, all
|
|
||||||
// sensitivities should be computed at points rather than faces.
|
|
||||||
PrimitivePatchInterpolation<polyPatch> patchInter(patch.patch());
|
|
||||||
vectorField dSdbFace
|
|
||||||
(
|
|
||||||
patchInter.pointToFaceInterpolate(pointSensdSdb()[patchI])
|
|
||||||
);
|
|
||||||
// dSdb already contains the face area. Divide with it to make it
|
|
||||||
// compatible with the rest of the terms
|
|
||||||
dSdbFace /= magSf;
|
|
||||||
|
|
||||||
tmp<vectorField> tdndbFace =
|
|
||||||
patchInter.pointToFaceInterpolate(pointSensdndb()[patchI]);
|
|
||||||
const vectorField& dndbFace = tdndbFace();
|
|
||||||
|
|
||||||
// Add to sensitivity fields
|
|
||||||
wallFaceSensVecPtr_()[patchI] += dSdbFace + dndbFace;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void sensitivitySurface::setSuffixName()
|
|
||||||
{
|
|
||||||
word suffix(dict().getOrDefault<word>("suffix", word::null));
|
|
||||||
// Determine suffix for fields holding the sens
|
|
||||||
if (includeMeshMovement_)
|
|
||||||
{
|
|
||||||
shapeSensitivitiesBase::setSuffix
|
|
||||||
(
|
|
||||||
adjointVars_.solverName() + "ESI" + suffix
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
shapeSensitivitiesBase::setSuffix
|
|
||||||
(
|
|
||||||
adjointVars_.solverName() + "SI" + suffix
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void sensitivitySurface::smoothSensitivities()
|
|
||||||
{
|
|
||||||
// Read in parameters
|
|
||||||
const label iters(dict().getOrDefault<label>("iters", 500));
|
|
||||||
const scalar tolerance(dict().getOrDefault<scalar>("tolerance", 1.e-06));
|
|
||||||
autoPtr<faMesh> aMeshPtr(nullptr);
|
|
||||||
|
|
||||||
IOobject faceLabels
|
|
||||||
(
|
|
||||||
"faceLabels",
|
|
||||||
mesh_.time().findInstance
|
|
||||||
(
|
|
||||||
mesh_.dbDir()/faMesh::meshSubDir,
|
|
||||||
"faceLabels",
|
|
||||||
IOobject::READ_IF_PRESENT
|
|
||||||
),
|
|
||||||
faMesh::meshSubDir,
|
|
||||||
mesh_,
|
|
||||||
IOobject::READ_IF_PRESENT,
|
|
||||||
IOobject::NO_WRITE
|
|
||||||
);
|
|
||||||
|
|
||||||
// If the faMesh already exists, read it
|
|
||||||
if (faceLabels.typeHeaderOk<labelIOList>(false))
|
|
||||||
{
|
|
||||||
Info<< "Reading the already constructed faMesh" << endl;
|
|
||||||
aMeshPtr.reset(new faMesh(mesh_));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Dictionary used to construct the faMesh
|
|
||||||
dictionary faMeshDefinition;
|
|
||||||
|
|
||||||
IOobject faMeshDefinitionDict
|
|
||||||
(
|
|
||||||
"faMeshDefinition",
|
|
||||||
mesh_.time().caseSystem(),
|
|
||||||
mesh_,
|
|
||||||
IOobject::MUST_READ,
|
|
||||||
IOobject::NO_WRITE
|
|
||||||
);
|
|
||||||
|
|
||||||
// If the faMeshDefinitionDict exists, use it to construct the mesh
|
|
||||||
if (faMeshDefinitionDict.typeHeaderOk<IOdictionary>(false))
|
|
||||||
{
|
|
||||||
Info<< "Reading faMeshDefinition from system " << endl;
|
|
||||||
faMeshDefinition = IOdictionary(faMeshDefinitionDict);
|
|
||||||
}
|
|
||||||
// Otherwise, faMesh is generated from all patches on which we compute
|
|
||||||
// sensitivities
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Info<< "Constructing faMeshDefinition from sensitivity patches"
|
|
||||||
<< endl;
|
|
||||||
wordList polyMeshPatches(sensitivityPatchIDs_.size());
|
|
||||||
label i(0);
|
|
||||||
for (const label patchID : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
polyMeshPatches[i++] = mesh_.boundary()[patchID].name();
|
|
||||||
}
|
|
||||||
faMeshDefinition.add<wordList>("polyMeshPatches", polyMeshPatches);
|
|
||||||
(void)faMeshDefinition.subDictOrAdd("boundary");
|
|
||||||
}
|
|
||||||
|
|
||||||
// Construct faMesh
|
|
||||||
aMeshPtr.reset(new faMesh(mesh_, faMeshDefinition));
|
|
||||||
}
|
|
||||||
faMesh& aMesh = aMeshPtr.ref();
|
|
||||||
|
|
||||||
// Physical radius of the smoothing, provided either directly or computed
|
|
||||||
// based on the average 'length' of boundary faces
|
|
||||||
const scalar Rphysical
|
|
||||||
(dict().getOrDefault<scalar>("radius", computeRadius(aMesh)));
|
|
||||||
DebugInfo
|
|
||||||
<< "Physical radius of the sensitivity smoothing "
|
|
||||||
<< Rphysical << nl << endl;
|
|
||||||
|
|
||||||
// Radius used as the diffusivity in the Helmholtz filter, computed as a
|
|
||||||
// function of the physical radius
|
|
||||||
const dimensionedScalar RpdeSqr
|
|
||||||
(
|
|
||||||
"RpdeSqr", dimArea, sqr(Rphysical/(2.*::sqrt(3.)))
|
|
||||||
);
|
|
||||||
|
|
||||||
dimensionedScalar one("1", dimless, 1.);
|
|
||||||
|
|
||||||
// Mapping engine
|
|
||||||
const volSurfaceMapping vsm(aMesh);
|
|
||||||
|
|
||||||
// Source term in faMatrix needs to be an areaField
|
|
||||||
areaScalarField sens
|
|
||||||
(
|
|
||||||
IOobject
|
|
||||||
(
|
|
||||||
"sens",
|
|
||||||
mesh_.time().timeName(),
|
|
||||||
mesh_,
|
|
||||||
IOobject::NO_READ,
|
|
||||||
IOobject::NO_WRITE
|
|
||||||
),
|
|
||||||
aMesh,
|
|
||||||
dimensionedScalar(dimless, Zero),
|
|
||||||
faPatchFieldBase::zeroGradientType()
|
|
||||||
);
|
|
||||||
|
|
||||||
// Copy sensitivities to area field
|
|
||||||
sens.primitiveFieldRef() =
|
|
||||||
vsm.mapToSurface<scalar>(wallFaceSensNormalPtr_());
|
|
||||||
|
|
||||||
// Initialisation of the smoothed sensitivities field based on the original
|
|
||||||
// sensitivities
|
|
||||||
areaScalarField smoothedSens("smoothedSens", sens);
|
|
||||||
for (label iter = 0; iter < iters; ++iter)
|
|
||||||
{
|
|
||||||
Info<< "Sensitivity smoothing iteration " << iter << endl;
|
|
||||||
|
|
||||||
faScalarMatrix smoothEqn
|
|
||||||
(
|
|
||||||
fam::Sp(one, smoothedSens)
|
|
||||||
- fam::laplacian(RpdeSqr, smoothedSens)
|
|
||||||
==
|
|
||||||
sens
|
|
||||||
);
|
|
||||||
|
|
||||||
smoothEqn.relax();
|
|
||||||
|
|
||||||
const scalar residual(mag(smoothEqn.solve().initialResidual()));
|
|
||||||
|
|
||||||
DebugInfo
|
|
||||||
<< "Max smoothSens " << gMax(mag(smoothedSens)()) << endl;
|
|
||||||
|
|
||||||
// Print execution time
|
|
||||||
mesh_.time().printExecutionTime(Info);
|
|
||||||
|
|
||||||
// Check convergence
|
|
||||||
if (residual < tolerance)
|
|
||||||
{
|
|
||||||
Info<< "\n***Reached smoothing equation convergence limit, "
|
|
||||||
"iteration " << iter << "***\n\n";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Field used to write the smoothed sensitivity field to file
|
|
||||||
volScalarField volSmoothedSens
|
|
||||||
(
|
|
||||||
IOobject
|
|
||||||
(
|
|
||||||
"smoothedSurfaceSens" + surfaceFieldSuffix_,
|
|
||||||
mesh_.time().timeName(),
|
|
||||||
mesh_,
|
|
||||||
IOobject::NO_READ,
|
|
||||||
IOobject::NO_WRITE
|
|
||||||
),
|
|
||||||
mesh_,
|
|
||||||
dimensionedScalar(dimless, Zero)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Transfer result back to volField and write
|
|
||||||
vsm.mapToVolume(smoothedSens, volSmoothedSens.boundaryFieldRef());
|
|
||||||
volSmoothedSens.write();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
scalar sensitivitySurface::computeRadius(const faMesh& aMesh)
|
|
||||||
{
|
|
||||||
scalar averageArea(gAverage(aMesh.S().field()));
|
|
||||||
const Vector<label>& geometricD = mesh_.geometricD();
|
|
||||||
const boundBox& bounds = mesh_.bounds();
|
|
||||||
forAll(geometricD, iDir)
|
|
||||||
{
|
|
||||||
if (geometricD[iDir] == -1)
|
|
||||||
{
|
|
||||||
averageArea /= bounds.span()[iDir];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scalar mult = dict().getOrDefault<scalar>("meanRadiusMultiplier", 10);
|
|
||||||
|
|
||||||
return mult*pow(averageArea, scalar(1)/scalar(mesh_.nGeometricD() - 1));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
sensitivitySurface::sensitivitySurface
|
|
||||||
(
|
|
||||||
const fvMesh& mesh,
|
|
||||||
const dictionary& dict,
|
|
||||||
incompressibleAdjointSolver& adjointSolver
|
|
||||||
)
|
|
||||||
:
|
|
||||||
adjointSensitivity(mesh, dict, adjointSolver),
|
|
||||||
shapeSensitivitiesBase(mesh, dict),
|
|
||||||
includeSurfaceArea_(false),
|
|
||||||
includePressureTerm_(false),
|
|
||||||
includeGradStressTerm_(false),
|
|
||||||
includeTransposeStresses_(false),
|
|
||||||
useSnGradInTranposeStresses_(false),
|
|
||||||
includeDivTerm_(false),
|
|
||||||
includeDistance_(false),
|
|
||||||
includeMeshMovement_(false),
|
|
||||||
includeObjective_(false),
|
|
||||||
writeGeometricInfo_(false),
|
|
||||||
smoothSensitivities_(false),
|
|
||||||
eikonalSolver_(nullptr),
|
|
||||||
meshMovementSolver_(nullptr),
|
|
||||||
|
|
||||||
nfOnPatchPtr_(nullptr),
|
|
||||||
SfOnPatchPtr_(nullptr),
|
|
||||||
CfOnPatchPtr_(nullptr)
|
|
||||||
{
|
|
||||||
read();
|
|
||||||
setSuffixName();
|
|
||||||
|
|
||||||
// Allocate boundary field pointer
|
|
||||||
wallFaceSensVecPtr_.reset(createZeroBoundaryPtr<vector>(mesh_));
|
|
||||||
wallFaceSensNormalPtr_.reset(createZeroBoundaryPtr<scalar>(mesh_));
|
|
||||||
wallFaceSensNormalVecPtr_.reset(createZeroBoundaryPtr<vector>(mesh_));
|
|
||||||
|
|
||||||
// Allocate fields to contain geometric info
|
|
||||||
if (writeGeometricInfo_)
|
|
||||||
{
|
|
||||||
nfOnPatchPtr_.reset
|
|
||||||
(
|
|
||||||
new volVectorField
|
|
||||||
(
|
|
||||||
IOobject
|
|
||||||
(
|
|
||||||
"nfOnPatch",
|
|
||||||
mesh.time().timeName(),
|
|
||||||
mesh,
|
|
||||||
IOobject::NO_READ,
|
|
||||||
IOobject::AUTO_WRITE
|
|
||||||
),
|
|
||||||
mesh,
|
|
||||||
vector::zero
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
SfOnPatchPtr_.reset
|
|
||||||
(
|
|
||||||
new volVectorField
|
|
||||||
(
|
|
||||||
IOobject
|
|
||||||
(
|
|
||||||
"SfOnPatch",
|
|
||||||
mesh.time().timeName(),
|
|
||||||
mesh,
|
|
||||||
IOobject::NO_READ,
|
|
||||||
IOobject::AUTO_WRITE
|
|
||||||
),
|
|
||||||
mesh,
|
|
||||||
vector::zero
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
CfOnPatchPtr_.reset
|
|
||||||
(
|
|
||||||
new volVectorField
|
|
||||||
(
|
|
||||||
IOobject
|
|
||||||
(
|
|
||||||
"CfOnPatch",
|
|
||||||
mesh.time().timeName(),
|
|
||||||
mesh,
|
|
||||||
IOobject::NO_READ,
|
|
||||||
IOobject::AUTO_WRITE
|
|
||||||
),
|
|
||||||
mesh,
|
|
||||||
vector::zero
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allocate appropriate space for the sensitivity field
|
|
||||||
computeDerivativesSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
void sensitivitySurface::read()
|
|
||||||
{
|
|
||||||
includeSurfaceArea_ =
|
|
||||||
dict().getOrDefault<bool>("includeSurfaceArea", true);
|
|
||||||
includePressureTerm_ =
|
|
||||||
dict().getOrDefault<bool>("includePressure", true);
|
|
||||||
includeGradStressTerm_ =
|
|
||||||
dict().getOrDefault<bool>("includeGradStressTerm", true);
|
|
||||||
includeTransposeStresses_ =
|
|
||||||
dict().getOrDefault<bool>("includeTransposeStresses", true);
|
|
||||||
useSnGradInTranposeStresses_ =
|
|
||||||
dict().getOrDefault<bool>("useSnGradInTranposeStresses", false);
|
|
||||||
includeDivTerm_ = dict().getOrDefault<bool>("includeDivTerm", false);
|
|
||||||
includeDistance_ =
|
|
||||||
dict().getOrDefault<bool>
|
|
||||||
(
|
|
||||||
"includeDistance",
|
|
||||||
adjointVars_.adjointTurbulence().ref().includeDistance()
|
|
||||||
);
|
|
||||||
includeMeshMovement_ =
|
|
||||||
dict().getOrDefault<bool>("includeMeshMovement", true);
|
|
||||||
includeObjective_ =
|
|
||||||
dict().getOrDefault<bool>("includeObjectiveContribution", true);
|
|
||||||
writeGeometricInfo_ =
|
|
||||||
dict().getOrDefault<bool>("writeGeometricInfo", false);
|
|
||||||
smoothSensitivities_ =
|
|
||||||
dict().getOrDefault<bool>("smoothSensitivities", false);
|
|
||||||
|
|
||||||
// Allocate new solvers if necessary
|
|
||||||
if (includeDistance_ && !eikonalSolver_)
|
|
||||||
{
|
|
||||||
eikonalSolver_.reset
|
|
||||||
(
|
|
||||||
new adjointEikonalSolver
|
|
||||||
(
|
|
||||||
mesh_,
|
|
||||||
dict_,
|
|
||||||
primalVars_.RASModelVariables(),
|
|
||||||
adjointVars_,
|
|
||||||
sensitivityPatchIDs_
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (includeMeshMovement_ && !meshMovementSolver_)
|
|
||||||
{
|
|
||||||
meshMovementSolver_.reset
|
|
||||||
(
|
|
||||||
new adjointMeshMovementSolver
|
|
||||||
(
|
|
||||||
mesh_,
|
|
||||||
dict_,
|
|
||||||
*this,
|
|
||||||
sensitivityPatchIDs_,
|
|
||||||
eikonalSolver_
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool sensitivitySurface::readDict(const dictionary& dict)
|
|
||||||
{
|
|
||||||
if (sensitivity::readDict(dict))
|
|
||||||
{
|
|
||||||
if (eikonalSolver_)
|
|
||||||
{
|
|
||||||
eikonalSolver_().readDict(dict);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (meshMovementSolver_)
|
|
||||||
{
|
|
||||||
meshMovementSolver_().readDict(dict);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void sensitivitySurface::computeDerivativesSize()
|
|
||||||
{
|
|
||||||
label nFaces(0);
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
nFaces += mesh_.boundary()[patchI].size();
|
|
||||||
}
|
|
||||||
derivatives_.setSize(nFaces);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void sensitivitySurface::accumulateIntegrand(const scalar dt)
|
|
||||||
{
|
|
||||||
// Grab references
|
|
||||||
const volScalarField& p = primalVars_.p();
|
|
||||||
const volVectorField& U = primalVars_.U();
|
|
||||||
|
|
||||||
const volScalarField& pa = adjointVars_.pa();
|
|
||||||
const volVectorField& Ua = adjointVars_.Ua();
|
|
||||||
autoPtr<incompressibleAdjoint::adjointRASModel>& adjointTurbulence =
|
|
||||||
adjointVars_.adjointTurbulence();
|
|
||||||
|
|
||||||
// Accumulate source for additional post-processing PDEs, if necessary
|
|
||||||
if (includeDistance_)
|
|
||||||
{
|
|
||||||
eikonalSolver_->accumulateIntegrand(dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (includeMeshMovement_)
|
|
||||||
{
|
|
||||||
meshMovementSolver_->accumulateIntegrand(dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Terms from the adjoint turbulence model
|
|
||||||
const boundaryVectorField& adjointTMsensitivities =
|
|
||||||
adjointTurbulence->wallShapeSensitivities();
|
|
||||||
|
|
||||||
DebugInfo
|
|
||||||
<< " Calculating adjoint sensitivity. " << endl;
|
|
||||||
|
|
||||||
tmp<volScalarField> tnuEff = adjointTurbulence->nuEff();
|
|
||||||
const volScalarField& nuEff = tnuEff.ref();
|
|
||||||
|
|
||||||
// Sensitivities do not include locale surface area by default.
|
|
||||||
// The part of the sensitivities that multiplies dxFace/db follows
|
|
||||||
|
|
||||||
// Deal with the stress part first since it's the most awkward in terms
|
|
||||||
// of memory managment
|
|
||||||
if (includeGradStressTerm_)
|
|
||||||
{
|
|
||||||
// Terms corresponding to contributions from converting delta
|
|
||||||
// to thetas are added through the corresponding adjoint
|
|
||||||
// boundary conditions instead of grabbing contributions from
|
|
||||||
// the objective function. Useful to have a unified
|
|
||||||
// formulation for low- and high-re meshes
|
|
||||||
|
|
||||||
tmp<volVectorField> tgradp = fvc::grad(p);
|
|
||||||
const volVectorField& gradp = tgradp.ref();
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
const fvPatch& patch = mesh_.boundary()[patchI];
|
|
||||||
tmp<vectorField> tnf = patch.nf();
|
|
||||||
const fvPatchVectorField& Uab = Ua.boundaryField()[patchI];
|
|
||||||
wallFaceSensVecPtr_()[patchI] -=
|
|
||||||
(Uab & tnf)*gradp.boundaryField()[patchI]*dt;
|
|
||||||
}
|
|
||||||
tgradp.clear();
|
|
||||||
|
|
||||||
// We only need to modify the boundaryField of gradU locally.
|
|
||||||
// If grad(U) is cached then
|
|
||||||
// a. The .ref() call fails since the tmp is initialised from a
|
|
||||||
// const ref
|
|
||||||
// b. we would be changing grad(U) for all other places in the code
|
|
||||||
// that need it
|
|
||||||
// So, always allocate new memory and avoid registering the new field
|
|
||||||
tmp<volTensorField> tgradU =
|
|
||||||
volTensorField::New("gradULocal", fvc::grad(U));
|
|
||||||
volTensorField::Boundary& gradUbf = tgradU.ref().boundaryFieldRef();
|
|
||||||
|
|
||||||
// Explicitly correct the boundary gradient to get rid of the
|
|
||||||
// tangential component
|
|
||||||
forAll(mesh_.boundary(), patchI)
|
|
||||||
{
|
|
||||||
const fvPatch& patch = mesh_.boundary()[patchI];
|
|
||||||
if (isA<wallFvPatch>(patch))
|
|
||||||
{
|
|
||||||
tmp<vectorField> tnf = mesh_.boundary()[patchI].nf();
|
|
||||||
gradUbf[patchI] = tnf*U.boundaryField()[patchI].snGrad();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp<volSymmTensorField> tstress = nuEff*twoSymm(tgradU);
|
|
||||||
const volSymmTensorField& stress = tstress.cref();
|
|
||||||
autoPtr<volVectorField> ptemp
|
|
||||||
(Foam::createZeroFieldPtr<vector>(mesh_, "temp", sqr(dimVelocity)));
|
|
||||||
volVectorField& temp = ptemp.ref();
|
|
||||||
for (label idir = 0; idir < pTraits<vector>::nComponents; ++idir)
|
|
||||||
{
|
|
||||||
unzipRow(stress, idir, temp);
|
|
||||||
volTensorField gradStressDir(fvc::grad(temp));
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
const fvPatch& patch = mesh_.boundary()[patchI];
|
|
||||||
tmp<vectorField> tnf = patch.nf();
|
|
||||||
const fvPatchVectorField& Uab = Ua.boundaryField()[patchI];
|
|
||||||
wallFaceSensVecPtr_()[patchI] +=
|
|
||||||
(
|
|
||||||
Uab.component(idir)
|
|
||||||
*(gradStressDir.boundaryField()[patchI] & tnf)
|
|
||||||
)*dt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transpose part of the adjoint stresses
|
|
||||||
// Dealt with separately to deallocate gradUa as soon as possible
|
|
||||||
if (includeTransposeStresses_)
|
|
||||||
{
|
|
||||||
tmp<volTensorField> tgradUa = fvc::grad(Ua);
|
|
||||||
const volTensorField::Boundary& gradUabf =
|
|
||||||
tgradUa.cref().boundaryField();
|
|
||||||
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
const fvPatch& patch = mesh_.boundary()[patchI];
|
|
||||||
tmp<vectorField> tnf = patch.nf();
|
|
||||||
const vectorField& nf = tnf();
|
|
||||||
vectorField gradUaNf
|
|
||||||
(
|
|
||||||
useSnGradInTranposeStresses_
|
|
||||||
? (Ua.boundaryField()[patchI].snGrad() & nf)*nf
|
|
||||||
: (gradUabf[patchI] & nf)
|
|
||||||
);
|
|
||||||
wallFaceSensVecPtr_()[patchI] -=
|
|
||||||
nuEff.boundaryField()[patchI]
|
|
||||||
*(gradUaNf & U.boundaryField()[patchI].snGrad())*nf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
const fvPatch& patch = mesh_.boundary()[patchI];
|
|
||||||
tmp<vectorField> tnf = patch.nf();
|
|
||||||
const vectorField& nf = tnf();
|
|
||||||
|
|
||||||
// Includes spurious tangential gradU part. Deprecated
|
|
||||||
/*
|
|
||||||
vectorField stressAndPressureTerm =
|
|
||||||
(
|
|
||||||
- (
|
|
||||||
Ua.boundaryField()[patchI].snGrad()
|
|
||||||
+ (gradUa.boundaryField()[patchI] & nf)
|
|
||||||
) * nuEff.boundaryField()[patchI]
|
|
||||||
+ pa.boundaryField()[patchI] *nf
|
|
||||||
) & gradU.boundaryField()[patchI].T();
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Adjoint stress term
|
|
||||||
vectorField stressTerm
|
|
||||||
(
|
|
||||||
- (
|
|
||||||
Ua.boundaryField()[patchI].snGrad()
|
|
||||||
& U.boundaryField()[patchI].snGrad()
|
|
||||||
)
|
|
||||||
* nuEff.boundaryField()[patchI]
|
|
||||||
* nf
|
|
||||||
);
|
|
||||||
|
|
||||||
if (includeDivTerm_)
|
|
||||||
{
|
|
||||||
stressTerm +=
|
|
||||||
scalar(1./3.)*nuEff.boundaryField()[patchI]
|
|
||||||
* (
|
|
||||||
((Ua.boundaryField()[patchI].snGrad() &nf)*nf)
|
|
||||||
& U.boundaryField()[patchI].snGrad()
|
|
||||||
)
|
|
||||||
* nf;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adjoint pressure terms
|
|
||||||
vectorField pressureTerm(patch.size(), Zero);
|
|
||||||
if (includePressureTerm_)
|
|
||||||
{
|
|
||||||
pressureTerm =
|
|
||||||
(
|
|
||||||
(nf*pa.boundaryField()[patchI])
|
|
||||||
& U.boundaryField()[patchI].snGrad()
|
|
||||||
)* nf;
|
|
||||||
}
|
|
||||||
|
|
||||||
PtrList<objective>& functions
|
|
||||||
(objectiveManager_.getObjectiveFunctions());
|
|
||||||
|
|
||||||
// Term from objectives including x directly (e.g. moments)
|
|
||||||
vectorField dxdbMultiplierTot(pressureTerm.size(), Zero);
|
|
||||||
if (includeObjective_)
|
|
||||||
{
|
|
||||||
forAll(functions, funcI)
|
|
||||||
{
|
|
||||||
dxdbMultiplierTot +=
|
|
||||||
functions[funcI].weight()
|
|
||||||
* (
|
|
||||||
functions[funcI].dxdbDirectMultiplier(patchI)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill in sensitivity fields
|
|
||||||
wallFaceSensVecPtr_()[patchI] +=
|
|
||||||
(
|
|
||||||
stressTerm
|
|
||||||
+ pressureTerm
|
|
||||||
+ adjointTMsensitivities[patchI]
|
|
||||||
+ dxdbMultiplierTot
|
|
||||||
)*dt;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add terms from physics other than the typical incompressible flow eqns
|
|
||||||
adjointSolver_.additionalSensitivityMapTerms
|
|
||||||
(wallFaceSensVecPtr_(), sensitivityPatchIDs_, dt);
|
|
||||||
|
|
||||||
// Add the sensitivity part corresponding to changes of the normal vector
|
|
||||||
// Computed at points and mapped to faces
|
|
||||||
addGeometricSens();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void sensitivitySurface::assembleSensitivities()
|
|
||||||
{
|
|
||||||
// Update geometric fields for use by external users
|
|
||||||
if (writeGeometricInfo_)
|
|
||||||
{
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
const fvPatch& patch = mesh_.boundary()[patchI];
|
|
||||||
tmp<vectorField> tnf = patch.nf();
|
|
||||||
const vectorField& nf = tnf();
|
|
||||||
const vectorField& Sf = patch.Sf();
|
|
||||||
const vectorField& Cf = patch.Cf();
|
|
||||||
|
|
||||||
nfOnPatchPtr_().boundaryFieldRef()[patchI] = nf;
|
|
||||||
SfOnPatchPtr_().boundaryFieldRef()[patchI] = Sf;
|
|
||||||
CfOnPatchPtr_().boundaryFieldRef()[patchI] = Cf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Solve extra equations if necessary
|
|
||||||
// Solved using accumulated sources over time
|
|
||||||
autoPtr<boundaryVectorField> distanceSensPtr(nullptr);
|
|
||||||
if (includeDistance_)
|
|
||||||
{
|
|
||||||
eikonalSolver_->solve();
|
|
||||||
distanceSensPtr.reset(createZeroBoundaryPtr<vector>(mesh_));
|
|
||||||
const boundaryVectorField& sens =
|
|
||||||
eikonalSolver_->distanceSensitivities();
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
distanceSensPtr()[patchI] = sens[patchI];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
autoPtr<boundaryVectorField> meshMovementSensPtr(nullptr);
|
|
||||||
if (includeMeshMovement_)
|
|
||||||
{
|
|
||||||
meshMovementSolver_->solve();
|
|
||||||
meshMovementSensPtr.reset(createZeroBoundaryPtr<vector>(mesh_));
|
|
||||||
const boundaryVectorField& sens =
|
|
||||||
meshMovementSolver_->meshMovementSensitivities();
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
meshMovementSensPtr()[patchI] = sens[patchI];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// Project to normal face vector
|
|
||||||
label nPassedFaces(0);
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
const fvPatch& patch = mesh_.boundary()[patchI];
|
|
||||||
tmp<vectorField> tnf(patch.nf());
|
|
||||||
const vectorField& nf = tnf();
|
|
||||||
|
|
||||||
// Distance related terms
|
|
||||||
if (includeDistance_)
|
|
||||||
{
|
|
||||||
wallFaceSensVecPtr_()[patchI] += distanceSensPtr()[patchI];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mesh movement related terms
|
|
||||||
if (includeMeshMovement_)
|
|
||||||
{
|
|
||||||
wallFaceSensVecPtr_()[patchI] += meshMovementSensPtr()[patchI];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (includeSurfaceArea_)
|
|
||||||
{
|
|
||||||
wallFaceSensVecPtr_()[patchI] *= patch.magSf();
|
|
||||||
}
|
|
||||||
|
|
||||||
wallFaceSensNormalPtr_()[patchI] = wallFaceSensVecPtr_()[patchI] & nf;
|
|
||||||
wallFaceSensNormalVecPtr_()[patchI] =
|
|
||||||
wallFaceSensNormalPtr_()[patchI] * nf;
|
|
||||||
|
|
||||||
forAll(patch, fI)
|
|
||||||
{
|
|
||||||
derivatives_[nPassedFaces + fI]
|
|
||||||
= wallFaceSensNormalPtr_()[patchI][fI];
|
|
||||||
}
|
|
||||||
nPassedFaces += patch.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Smooth sensitivities if needed
|
|
||||||
if (smoothSensitivities_)
|
|
||||||
{
|
|
||||||
smoothSensitivities();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void sensitivitySurface::clearSensitivities()
|
|
||||||
{
|
|
||||||
// Reset terms in post-processing PDEs
|
|
||||||
if (includeDistance_)
|
|
||||||
{
|
|
||||||
eikonalSolver_->reset();
|
|
||||||
}
|
|
||||||
if (includeMeshMovement_)
|
|
||||||
{
|
|
||||||
meshMovementSolver_->reset();
|
|
||||||
}
|
|
||||||
// Reset sensitivity fields
|
|
||||||
adjointSensitivity::clearSensitivities();
|
|
||||||
shapeSensitivitiesBase::clearSensitivities();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
autoPtr<adjointEikonalSolver>& sensitivitySurface::getAdjointEikonalSolver()
|
|
||||||
{
|
|
||||||
return eikonalSolver_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void sensitivitySurface::write(const word& baseName)
|
|
||||||
{
|
|
||||||
setSuffixName();
|
|
||||||
adjointSensitivity::write();
|
|
||||||
shapeSensitivitiesBase::write();
|
|
||||||
|
|
||||||
if (writeGeometricInfo_)
|
|
||||||
{
|
|
||||||
nfOnPatchPtr_().write();
|
|
||||||
SfOnPatchPtr_().write();
|
|
||||||
CfOnPatchPtr_().write();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
} // End namespace Foam
|
|
||||||
} // End namespace incompressible
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -1,773 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | www.openfoam.com
|
|
||||||
\\/ M anipulation |
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
Copyright (C) 2007-2020, 2022 PCOpt/NTUA
|
|
||||||
Copyright (C) 2013-2020, 2022 FOSS GP
|
|
||||||
Copyright (C) 2019-2022 OpenCFD Ltd.
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
License
|
|
||||||
This file is part of OpenFOAM.
|
|
||||||
|
|
||||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "sensitivitySurfacePointsIncompressible.H"
|
|
||||||
#include "incompressibleAdjointSolver.H"
|
|
||||||
#include "addToRunTimeSelectionTable.H"
|
|
||||||
#include "syncTools.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
|
|
||||||
namespace incompressible
|
|
||||||
{
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
defineTypeNameAndDebug(sensitivitySurfacePoints, 0);
|
|
||||||
addToRunTimeSelectionTable
|
|
||||||
(
|
|
||||||
adjointSensitivity,
|
|
||||||
sensitivitySurfacePoints,
|
|
||||||
dictionary
|
|
||||||
);
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
|
||||||
|
|
||||||
void sensitivitySurfacePoints::read()
|
|
||||||
{
|
|
||||||
includeSurfaceArea_ =
|
|
||||||
dict().getOrDefault<bool>("includeSurfaceArea", false);
|
|
||||||
includePressureTerm_ =
|
|
||||||
dict().getOrDefault<bool>("includePressure", true);
|
|
||||||
includeGradStressTerm_ =
|
|
||||||
dict().getOrDefault<bool>("includeGradStressTerm", true);
|
|
||||||
includeTransposeStresses_ =
|
|
||||||
dict().getOrDefault<bool>("includeTransposeStresses", true);
|
|
||||||
useSnGradInTranposeStresses_ =
|
|
||||||
dict().getOrDefault<bool>("useSnGradInTranposeStresses", false);
|
|
||||||
includeDivTerm_ =
|
|
||||||
dict().getOrDefault<bool>("includeDivTerm", false);
|
|
||||||
includeDistance_ =
|
|
||||||
dict().getOrDefault<bool>
|
|
||||||
(
|
|
||||||
"includeDistance",
|
|
||||||
adjointVars_.adjointTurbulence().ref().includeDistance()
|
|
||||||
);
|
|
||||||
includeMeshMovement_ =
|
|
||||||
dict().getOrDefault<bool>("includeMeshMovement", true);
|
|
||||||
includeObjective_ =
|
|
||||||
dict().getOrDefault<bool>("includeObjectiveContribution", true);
|
|
||||||
|
|
||||||
// Allocate new solvers if necessary
|
|
||||||
if (includeDistance_ && !eikonalSolver_)
|
|
||||||
{
|
|
||||||
eikonalSolver_.reset
|
|
||||||
(
|
|
||||||
new adjointEikonalSolver
|
|
||||||
(
|
|
||||||
mesh_,
|
|
||||||
dict(),
|
|
||||||
primalVars_.RASModelVariables(),
|
|
||||||
adjointVars_,
|
|
||||||
sensitivityPatchIDs_
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (includeMeshMovement_ && !meshMovementSolver_)
|
|
||||||
{
|
|
||||||
meshMovementSolver_.reset
|
|
||||||
(
|
|
||||||
new adjointMeshMovementSolver
|
|
||||||
(
|
|
||||||
mesh_,
|
|
||||||
dict(),
|
|
||||||
*this,
|
|
||||||
sensitivityPatchIDs_,
|
|
||||||
eikonalSolver_
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void sensitivitySurfacePoints::finaliseFaceMultiplier()
|
|
||||||
{
|
|
||||||
// Solve extra equations if necessary
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
autoPtr<boundaryVectorField> distanceSensPtr(nullptr);
|
|
||||||
if (includeDistance_)
|
|
||||||
{
|
|
||||||
eikonalSolver_->solve();
|
|
||||||
distanceSensPtr.reset(createZeroBoundaryPtr<vector>(mesh_));
|
|
||||||
const boundaryVectorField& sens =
|
|
||||||
eikonalSolver_->distanceSensitivities();
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
distanceSensPtr()[patchI] = sens[patchI];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
autoPtr<boundaryVectorField> meshMovementSensPtr(nullptr);
|
|
||||||
if (includeMeshMovement_)
|
|
||||||
{
|
|
||||||
meshMovementSolver_->solve();
|
|
||||||
meshMovementSensPtr.reset(createZeroBoundaryPtr<vector>(mesh_));
|
|
||||||
const boundaryVectorField& sens =
|
|
||||||
meshMovementSolver_->meshMovementSensitivities();
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
meshMovementSensPtr()[patchI] = sens[patchI];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add to other terms multiplying dxFace/dxPoints
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
const fvPatch& patch = mesh_.boundary()[patchI];
|
|
||||||
tmp<vectorField> tnf = patch.nf();
|
|
||||||
const scalarField& magSf = patch.magSf();
|
|
||||||
// Distance related terms
|
|
||||||
if (includeDistance_)
|
|
||||||
{
|
|
||||||
wallFaceSens_()[patchI] += distanceSensPtr()[patchI];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Mesh movement related terms
|
|
||||||
if (includeMeshMovement_)
|
|
||||||
{
|
|
||||||
wallFaceSens_()[patchI] += meshMovementSensPtr()[patchI];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add local face area
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~
|
|
||||||
// Sensitivities DO include locale surface area, to get
|
|
||||||
// the correct weighting from the contributions of various faces.
|
|
||||||
// Normalized at the end.
|
|
||||||
// dSfdbMult already includes the local area. No need to re-multiply
|
|
||||||
wallFaceSens_()[patchI] *= magSf;
|
|
||||||
dnfdbMult_()[patchI] *= magSf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void sensitivitySurfacePoints::finalisePointSensitivities()
|
|
||||||
{
|
|
||||||
// Geometric (or "direct") sensitivities are better computed directly on
|
|
||||||
// the points. Compute them and add the ones that depend on dxFace/dxPoint
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
const fvPatch& patch = mesh_.boundary()[patchI];
|
|
||||||
vectorField nf(patch.nf());
|
|
||||||
|
|
||||||
// Point sens result for patch
|
|
||||||
vectorField& pointPatchSens = wallPointSensVecPtr_()[patchI];
|
|
||||||
|
|
||||||
// Face sens for patch
|
|
||||||
const vectorField& facePatchSens = wallFaceSens_()[patchI];
|
|
||||||
|
|
||||||
// Geometry variances
|
|
||||||
const vectorField& dSfdbMultPatch = dSfdbMult_()[patchI];
|
|
||||||
const vectorField& dnfdbMultPatch = dnfdbMult_()[patchI];
|
|
||||||
|
|
||||||
// Correspondance of local point addressing to global point addressing
|
|
||||||
const labelList& meshPoints = patch.patch().meshPoints();
|
|
||||||
|
|
||||||
// List with mesh faces. Global addressing
|
|
||||||
const faceList& faces = mesh_.faces();
|
|
||||||
|
|
||||||
// Each local patch point belongs to these local patch faces
|
|
||||||
// (local numbering)
|
|
||||||
const labelListList& patchPointFaces = patch.patch().pointFaces();
|
|
||||||
|
|
||||||
// Index of first face in patch
|
|
||||||
const label patchStartIndex = patch.start();
|
|
||||||
|
|
||||||
// Geometry differentiation engine
|
|
||||||
deltaBoundary dBoundary(mesh_);
|
|
||||||
|
|
||||||
// Loop over patch points.
|
|
||||||
// Collect contributions from each boundary face this point belongs to
|
|
||||||
forAll(meshPoints, ppI)
|
|
||||||
{
|
|
||||||
const labelList& pointFaces = patchPointFaces[ppI];
|
|
||||||
forAll(pointFaces, pfI)
|
|
||||||
{
|
|
||||||
label localFaceIndex = pointFaces[pfI];
|
|
||||||
label globalFaceIndex = patchStartIndex + localFaceIndex;
|
|
||||||
const face& faceI = faces[globalFaceIndex];
|
|
||||||
|
|
||||||
// Point coordinates. All indices in global numbering
|
|
||||||
pointField p(faceI.points(mesh_.points()));
|
|
||||||
tensorField p_d(faceI.size(), Zero);
|
|
||||||
forAll(faceI, facePointI)
|
|
||||||
{
|
|
||||||
if (faceI[facePointI] == meshPoints[ppI])
|
|
||||||
{
|
|
||||||
p_d[facePointI] = tensor::I;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tensorField deltaNormals =
|
|
||||||
dBoundary.makeFaceCentresAndAreas_d(p, p_d);
|
|
||||||
|
|
||||||
// Element [0] is the variation in the face center
|
|
||||||
// (dxFace/dxPoint)
|
|
||||||
const tensor& deltaCf = deltaNormals[0];
|
|
||||||
pointPatchSens[ppI] += facePatchSens[localFaceIndex] & deltaCf;
|
|
||||||
|
|
||||||
// Term multiplying d(Sf)/d(point displacement) and
|
|
||||||
// d(nf)/d(point displacement)
|
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
if (includeObjective_)
|
|
||||||
{
|
|
||||||
// Element [1] is the variation in the (dimensional) normal
|
|
||||||
const tensor& deltaSf = deltaNormals[1];
|
|
||||||
pointPatchSens[ppI] +=
|
|
||||||
dSfdbMultPatch[localFaceIndex] & deltaSf;
|
|
||||||
|
|
||||||
// Element [2] is the variation in the unit normal
|
|
||||||
const tensor& deltaNf = deltaNormals[2];
|
|
||||||
pointPatchSens[ppI] +=
|
|
||||||
dnfdbMultPatch[localFaceIndex] & deltaNf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void sensitivitySurfacePoints::constructGlobalPointNormalsAndAreas
|
|
||||||
(
|
|
||||||
vectorField& pointNormals,
|
|
||||||
scalarField& pointMagSf
|
|
||||||
)
|
|
||||||
{
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
const fvPatch& patch = mesh_.boundary()[patchI];
|
|
||||||
const scalarField& magSf = patch.magSf();
|
|
||||||
vectorField nf(patch.nf());
|
|
||||||
|
|
||||||
// Correspondance of local point addressing to global point addressing
|
|
||||||
const labelList& meshPoints = patch.patch().meshPoints();
|
|
||||||
|
|
||||||
// Each local patch point belongs to these local patch faces
|
|
||||||
// (local numbering)
|
|
||||||
const labelListList& patchPointFaces = patch.patch().pointFaces();
|
|
||||||
|
|
||||||
// Loop over patch points
|
|
||||||
forAll(meshPoints, ppI)
|
|
||||||
{
|
|
||||||
const labelList& pointFaces = patchPointFaces[ppI];
|
|
||||||
forAll(pointFaces, pfI)
|
|
||||||
{
|
|
||||||
const label localFaceIndex = pointFaces[pfI];
|
|
||||||
|
|
||||||
// Accumulate information for point normals
|
|
||||||
pointNormals[meshPoints[ppI]] += nf[localFaceIndex];
|
|
||||||
pointMagSf[meshPoints[ppI]] += magSf[localFaceIndex];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
syncTools::syncPointList
|
|
||||||
(
|
|
||||||
mesh_,
|
|
||||||
pointNormals,
|
|
||||||
plusEqOp<vector>(),
|
|
||||||
vector::zero
|
|
||||||
);
|
|
||||||
syncTools::syncPointList
|
|
||||||
(
|
|
||||||
mesh_,
|
|
||||||
pointMagSf,
|
|
||||||
plusEqOp<scalar>(),
|
|
||||||
scalar(0)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void sensitivitySurfacePoints::setSuffixName()
|
|
||||||
{
|
|
||||||
word suffix(dict().getOrDefault<word>("suffix", word::null));
|
|
||||||
// Determine suffix for fields holding the sens
|
|
||||||
if (includeMeshMovement_)
|
|
||||||
{
|
|
||||||
shapeSensitivitiesBase::setSuffix
|
|
||||||
(
|
|
||||||
adjointVars_.solverName() + "ESI" + suffix
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
shapeSensitivitiesBase::setSuffix
|
|
||||||
(
|
|
||||||
adjointVars_.solverName() + "SI" + suffix
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
sensitivitySurfacePoints::sensitivitySurfacePoints
|
|
||||||
(
|
|
||||||
const fvMesh& mesh,
|
|
||||||
const dictionary& dict,
|
|
||||||
incompressibleAdjointSolver& adjointSolver
|
|
||||||
)
|
|
||||||
:
|
|
||||||
adjointSensitivity(mesh, dict, adjointSolver),
|
|
||||||
shapeSensitivitiesBase(mesh, dict),
|
|
||||||
includeSurfaceArea_(false),
|
|
||||||
includePressureTerm_(false),
|
|
||||||
includeGradStressTerm_(false),
|
|
||||||
includeTransposeStresses_(false),
|
|
||||||
useSnGradInTranposeStresses_(false),
|
|
||||||
includeDivTerm_(false),
|
|
||||||
includeDistance_(false),
|
|
||||||
includeMeshMovement_(false),
|
|
||||||
includeObjective_(false),
|
|
||||||
eikonalSolver_(nullptr),
|
|
||||||
meshMovementSolver_(nullptr),
|
|
||||||
wallFaceSens_(createZeroBoundaryPtr<vector>(mesh_)),
|
|
||||||
dSfdbMult_(createZeroBoundaryPtr<vector>(mesh_)),
|
|
||||||
dnfdbMult_(createZeroBoundaryPtr<vector>(mesh_))
|
|
||||||
|
|
||||||
{
|
|
||||||
read();
|
|
||||||
|
|
||||||
// Allocate boundary field pointer
|
|
||||||
wallPointSensVecPtr_.reset(createZeroBoundaryPointFieldPtr<vector>(mesh_));
|
|
||||||
wallPointSensNormalPtr_.reset
|
|
||||||
(
|
|
||||||
createZeroBoundaryPointFieldPtr<scalar>(mesh_)
|
|
||||||
);
|
|
||||||
wallPointSensNormalVecPtr_.reset
|
|
||||||
(
|
|
||||||
createZeroBoundaryPointFieldPtr<vector>(mesh_)
|
|
||||||
);
|
|
||||||
|
|
||||||
// Allocate appropriate space for sensitivities
|
|
||||||
label nTotalPoints(0);
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
nTotalPoints += mesh_.boundaryMesh()[patchI].nPoints();
|
|
||||||
}
|
|
||||||
reduce(nTotalPoints, sumOp<label>());
|
|
||||||
|
|
||||||
// Derivatives for all (x,y,z) components of the displacement are kept
|
|
||||||
derivatives_ = scalarField(3*nTotalPoints, Zero);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
bool sensitivitySurfacePoints::readDict(const dictionary& dict)
|
|
||||||
{
|
|
||||||
if (sensitivity::readDict(dict))
|
|
||||||
{
|
|
||||||
if (eikonalSolver_)
|
|
||||||
{
|
|
||||||
eikonalSolver_().readDict(dict);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (meshMovementSolver_)
|
|
||||||
{
|
|
||||||
meshMovementSolver_().readDict(dict);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void sensitivitySurfacePoints::accumulateIntegrand(const scalar dt)
|
|
||||||
{
|
|
||||||
// Grab references
|
|
||||||
const volScalarField& p = primalVars_.p();
|
|
||||||
const volVectorField& U = primalVars_.U();
|
|
||||||
|
|
||||||
const volScalarField& pa = adjointVars_.pa();
|
|
||||||
const volVectorField& Ua = adjointVars_.Ua();
|
|
||||||
autoPtr<incompressibleAdjoint::adjointRASModel>& adjointTurbulence =
|
|
||||||
adjointVars_.adjointTurbulence();
|
|
||||||
|
|
||||||
// Solve extra equations if necessary
|
|
||||||
if (includeDistance_)
|
|
||||||
{
|
|
||||||
eikonalSolver_->accumulateIntegrand(dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (includeMeshMovement_)
|
|
||||||
{
|
|
||||||
meshMovementSolver_->accumulateIntegrand(dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Terms from the adjoint turbulence model
|
|
||||||
const boundaryVectorField& adjointTMsensitivities =
|
|
||||||
adjointTurbulence->wallShapeSensitivities();
|
|
||||||
|
|
||||||
// Objective references
|
|
||||||
PtrList<objective>& functions(objectiveManager_.getObjectiveFunctions());
|
|
||||||
|
|
||||||
DebugInfo
|
|
||||||
<< " Calculating adjoint sensitivity. " << endl;
|
|
||||||
|
|
||||||
tmp<volScalarField> tnuEff = adjointTurbulence->nuEff();
|
|
||||||
const volScalarField& nuEff = tnuEff.ref();
|
|
||||||
|
|
||||||
// Deal with the stress part first since it's the most awkward in terms
|
|
||||||
// of memory managment
|
|
||||||
if (includeGradStressTerm_)
|
|
||||||
{
|
|
||||||
// Terms corresponding to contributions from converting delta
|
|
||||||
// to thetas are added through the corresponding adjoint
|
|
||||||
// boundary conditions instead of grabbing contributions from
|
|
||||||
// the objective function. Useful to have a unified
|
|
||||||
// formulation for low- and high-re meshes
|
|
||||||
|
|
||||||
tmp<volVectorField> tgradp = fvc::grad(p);
|
|
||||||
const volVectorField& gradp = tgradp.ref();
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
const fvPatch& patch = mesh_.boundary()[patchI];
|
|
||||||
tmp<vectorField> tnf = patch.nf();
|
|
||||||
const fvPatchVectorField& Uab = Ua.boundaryField()[patchI];
|
|
||||||
wallFaceSens_()[patchI] -=
|
|
||||||
(Uab & tnf)*gradp.boundaryField()[patchI]*dt;
|
|
||||||
}
|
|
||||||
tgradp.clear();
|
|
||||||
|
|
||||||
// We only need to modify the boundaryField of gradU locally.
|
|
||||||
// If grad(U) is cached then
|
|
||||||
// a. The .ref() call fails since the tmp is initialised from a
|
|
||||||
// const ref
|
|
||||||
// b. we would be changing grad(U) for all other places in the code
|
|
||||||
// that need it
|
|
||||||
// So, always allocate new memory and avoid registering the new field
|
|
||||||
tmp<volTensorField> tgradU =
|
|
||||||
volTensorField::New("gradULocal", fvc::grad(U));
|
|
||||||
volTensorField::Boundary& gradUbf = tgradU.ref().boundaryFieldRef();
|
|
||||||
|
|
||||||
// Explicitly correct the boundary gradient to get rid of the
|
|
||||||
// tangential component
|
|
||||||
forAll(mesh_.boundary(), patchI)
|
|
||||||
{
|
|
||||||
const fvPatch& patch = mesh_.boundary()[patchI];
|
|
||||||
if (isA<wallFvPatch>(patch))
|
|
||||||
{
|
|
||||||
tmp<vectorField> tnf = mesh_.boundary()[patchI].nf();
|
|
||||||
gradUbf[patchI] = tnf*U.boundaryField()[patchI].snGrad();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tmp<volSymmTensorField> tstress = nuEff*twoSymm(tgradU);
|
|
||||||
const volSymmTensorField& stress = tstress.cref();
|
|
||||||
autoPtr<volVectorField> ptemp
|
|
||||||
(Foam::createZeroFieldPtr<vector>(mesh_, "temp", sqr(dimVelocity)));
|
|
||||||
volVectorField& temp = ptemp.ref();
|
|
||||||
for (label idir = 0; idir < pTraits<vector>::nComponents; ++idir)
|
|
||||||
{
|
|
||||||
unzipRow(stress, idir, temp);
|
|
||||||
volTensorField gradStressDir(fvc::grad(temp));
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
const fvPatch& patch = mesh_.boundary()[patchI];
|
|
||||||
tmp<vectorField> tnf = patch.nf();
|
|
||||||
const fvPatchVectorField& Uab = Ua.boundaryField()[patchI];
|
|
||||||
wallFaceSens_()[patchI] +=
|
|
||||||
(
|
|
||||||
Uab.component(idir)
|
|
||||||
*(gradStressDir.boundaryField()[patchI] & tnf)
|
|
||||||
)*dt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Transpose part of the adjoint stresses
|
|
||||||
// Dealt with separately to deallocate gradUa as soon as possible
|
|
||||||
if (includeTransposeStresses_)
|
|
||||||
{
|
|
||||||
tmp<volTensorField> tgradUa = fvc::grad(Ua);
|
|
||||||
const volTensorField::Boundary& gradUabf =
|
|
||||||
tgradUa.cref().boundaryField();
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
const fvPatch& patch = mesh_.boundary()[patchI];
|
|
||||||
tmp<vectorField> tnf = patch.nf();
|
|
||||||
const vectorField& nf = tnf();
|
|
||||||
vectorField gradUaNf
|
|
||||||
(
|
|
||||||
useSnGradInTranposeStresses_
|
|
||||||
? (Ua.boundaryField()[patchI].snGrad() & nf)*nf
|
|
||||||
: (gradUabf[patchI] & nf)
|
|
||||||
);
|
|
||||||
wallFaceSens_()[patchI] -=
|
|
||||||
nuEff.boundaryField()[patchI]
|
|
||||||
*(gradUaNf & U.boundaryField()[patchI].snGrad())*tnf;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// The face-based part of the sensitivities, i.e. terms that multiply
|
|
||||||
// dxFace/dxPoint.
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
const fvPatch& patch = mesh_.boundary()[patchI];
|
|
||||||
tmp<vectorField> tnf = patch.nf();
|
|
||||||
const vectorField& nf = tnf();
|
|
||||||
|
|
||||||
// Adjoint stress term
|
|
||||||
// vectorField stressTerm
|
|
||||||
// (
|
|
||||||
// -(nf & DUa.boundaryField()[patchI])
|
|
||||||
// *nuEff.boundaryField()[patchI]
|
|
||||||
// & gradU.boundaryField()[patchI].T();
|
|
||||||
// )
|
|
||||||
|
|
||||||
vectorField stressTerm
|
|
||||||
(
|
|
||||||
- (
|
|
||||||
Ua.boundaryField()[patchI].snGrad()
|
|
||||||
& U.boundaryField()[patchI].snGrad()
|
|
||||||
)
|
|
||||||
* nuEff.boundaryField()[patchI]
|
|
||||||
* nf
|
|
||||||
);
|
|
||||||
|
|
||||||
if (includeDivTerm_)
|
|
||||||
{
|
|
||||||
stressTerm +=
|
|
||||||
scalar(1./3.)*nuEff.boundaryField()[patchI]
|
|
||||||
* (
|
|
||||||
((Ua.boundaryField()[patchI].snGrad() &nf)*nf)
|
|
||||||
& U.boundaryField()[patchI].snGrad()
|
|
||||||
)
|
|
||||||
*nf;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Adjoint pressure terms
|
|
||||||
vectorField pressureTerm(patch.size(), Zero);
|
|
||||||
if (includePressureTerm_)
|
|
||||||
{
|
|
||||||
pressureTerm =
|
|
||||||
(
|
|
||||||
(nf*pa.boundaryField()[patchI])
|
|
||||||
& U.boundaryField()[patchI].snGrad()
|
|
||||||
)
|
|
||||||
*nf;
|
|
||||||
}
|
|
||||||
|
|
||||||
vectorField dxdbMultiplierTot(patch.size(), Zero);
|
|
||||||
if (includeObjective_)
|
|
||||||
{
|
|
||||||
// Term from objectives multiplying dxdb
|
|
||||||
forAll(functions, funcI)
|
|
||||||
{
|
|
||||||
const scalar wei = functions[funcI].weight();
|
|
||||||
// dt added in wallFaceSens_
|
|
||||||
dxdbMultiplierTot +=
|
|
||||||
wei*functions[funcI].dxdbDirectMultiplier(patchI);
|
|
||||||
|
|
||||||
// Fill in multipliers of d(Sf)/db and d(nf)/db
|
|
||||||
dSfdbMult_()[patchI] +=
|
|
||||||
wei*dt*functions[funcI].dSdbMultiplier(patchI);
|
|
||||||
dnfdbMult_()[patchI] +=
|
|
||||||
wei*dt*functions[funcI].dndbMultiplier(patchI);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill in dxFace/dxPoint multiplier.
|
|
||||||
// Missing geometric contributions which are directly computed on the
|
|
||||||
// points
|
|
||||||
wallFaceSens_()[patchI] +=
|
|
||||||
(
|
|
||||||
stressTerm
|
|
||||||
+ pressureTerm
|
|
||||||
+ adjointTMsensitivities[patchI]
|
|
||||||
+ dxdbMultiplierTot
|
|
||||||
)*dt;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add terms from physics other than the typical incompressible flow eqns
|
|
||||||
adjointSolver_.additionalSensitivityMapTerms
|
|
||||||
(wallFaceSens_(), sensitivityPatchIDs_, dt);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void sensitivitySurfacePoints::assembleSensitivities()
|
|
||||||
{
|
|
||||||
// Add remaining parts to term multiplying dxFace/dxPoints
|
|
||||||
// Solves for post-processing PDEs
|
|
||||||
finaliseFaceMultiplier();
|
|
||||||
|
|
||||||
// Geometric (or "direct") sensitivities are better computed directly on
|
|
||||||
// the points. Compute them and add the ones that depend on dxFace/dxPoint
|
|
||||||
finalisePointSensitivities();
|
|
||||||
|
|
||||||
// polyPatch::pointNormals will give the wrong result for points
|
|
||||||
// belonging to multiple patches or patch-processorPatch intersections.
|
|
||||||
// Keeping a mesh-wide field to allow easy reduction using syncTools.
|
|
||||||
// A bit expensive? Better way?
|
|
||||||
vectorField pointNormals(mesh_.nPoints(), Zero);
|
|
||||||
scalarField pointMagSf(mesh_.nPoints(), Zero);
|
|
||||||
constructGlobalPointNormalsAndAreas(pointNormals, pointMagSf);
|
|
||||||
|
|
||||||
// Do parallel communications to avoid wrong values at processor boundaries
|
|
||||||
// Global field for accumulation
|
|
||||||
vectorField pointSensGlobal(mesh_.nPoints(), Zero);
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
const labelList& meshPoints = mesh_.boundaryMesh()[patchI].meshPoints();
|
|
||||||
forAll(meshPoints, ppI)
|
|
||||||
{
|
|
||||||
const label globaPointI = meshPoints[ppI];
|
|
||||||
pointSensGlobal[globaPointI] +=
|
|
||||||
wallPointSensVecPtr_()[patchI][ppI];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Accumulate dJ/dx_i
|
|
||||||
syncTools::syncPointList
|
|
||||||
(
|
|
||||||
mesh_,
|
|
||||||
pointSensGlobal,
|
|
||||||
plusEqOp<vector>(),
|
|
||||||
vector::zero
|
|
||||||
);
|
|
||||||
|
|
||||||
// Transfer back to local fields
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
const labelList& meshPoints =
|
|
||||||
mesh_.boundaryMesh()[patchI].meshPoints();
|
|
||||||
wallPointSensVecPtr_()[patchI].map(pointSensGlobal, meshPoints);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Compute normal sens and append to return field
|
|
||||||
label nPassedDVs(0);
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
const polyPatch& patch = mesh_.boundaryMesh()[patchI];
|
|
||||||
List<scalarField> procPatchSens(Pstream::nProcs());
|
|
||||||
//if (patch.size()>0)
|
|
||||||
{
|
|
||||||
const labelList& meshPoints = patch.meshPoints();
|
|
||||||
|
|
||||||
// Avoid storing unit point normals in the global list since we
|
|
||||||
// might divide multiple times with the number of faces belonging
|
|
||||||
// to the point. Instead do the division locally, per patch use
|
|
||||||
vectorField patchPointNormals(pointNormals, meshPoints);
|
|
||||||
patchPointNormals /= mag(patchPointNormals) + VSMALL;
|
|
||||||
if (!includeSurfaceArea_)
|
|
||||||
{
|
|
||||||
wallPointSensVecPtr_()[patchI] /=
|
|
||||||
scalarField(pointMagSf, meshPoints);
|
|
||||||
}
|
|
||||||
wallPointSensNormalPtr_()[patchI] =
|
|
||||||
wallPointSensVecPtr_()[patchI]
|
|
||||||
& patchPointNormals;
|
|
||||||
wallPointSensNormalVecPtr_()[patchI] =
|
|
||||||
wallPointSensNormalPtr_()[patchI]
|
|
||||||
*patchPointNormals;
|
|
||||||
|
|
||||||
// 1. Gather sens from all processors for this patch and communicate
|
|
||||||
// them back. Potentially large memory overhead but the rest of the
|
|
||||||
// code structure assumes that all procs know all sensitivity
|
|
||||||
// derivatives
|
|
||||||
//
|
|
||||||
// 2. Transfer vectorial sensitivities to scalarField.
|
|
||||||
// Needed since the normal point vector is wrongly computed at patch
|
|
||||||
// boundaries and cannot be used to reconstruct a vectorial movement
|
|
||||||
// from just its normal component
|
|
||||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
||||||
|
|
||||||
procPatchSens[Pstream::myProcNo()].setSize
|
|
||||||
(
|
|
||||||
3*wallPointSensNormalVecPtr_()[patchI].size()
|
|
||||||
);
|
|
||||||
scalarField& patchScalarSens = procPatchSens[Pstream::myProcNo()];
|
|
||||||
forAll(wallPointSensNormalVecPtr_()[patchI], ptI)
|
|
||||||
{
|
|
||||||
patchScalarSens[3*ptI] =
|
|
||||||
wallPointSensNormalVecPtr_()[patchI][ptI].x();
|
|
||||||
patchScalarSens[3*ptI + 1] =
|
|
||||||
wallPointSensNormalVecPtr_()[patchI][ptI].y();
|
|
||||||
patchScalarSens[3*ptI + 2] =
|
|
||||||
wallPointSensNormalVecPtr_()[patchI][ptI].z();
|
|
||||||
}
|
|
||||||
Pstream::allGatherList(procPatchSens);
|
|
||||||
|
|
||||||
forAll(procPatchSens, procI)
|
|
||||||
{
|
|
||||||
const scalarField& procSens = procPatchSens[procI];
|
|
||||||
forAll(procSens, dvI)
|
|
||||||
{
|
|
||||||
derivatives_[nPassedDVs + dvI] = procSens[dvI];
|
|
||||||
}
|
|
||||||
nPassedDVs += procSens.size();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void sensitivitySurfacePoints::clearSensitivities()
|
|
||||||
{
|
|
||||||
// Reset terms in post-processing PDEs
|
|
||||||
if (includeDistance_)
|
|
||||||
{
|
|
||||||
eikonalSolver_->reset();
|
|
||||||
}
|
|
||||||
if (includeMeshMovement_)
|
|
||||||
{
|
|
||||||
meshMovementSolver_->reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset local fields to zero
|
|
||||||
wallFaceSens_() = vector::zero;
|
|
||||||
dSfdbMult_() = vector::zero;
|
|
||||||
dnfdbMult_() = vector::zero;
|
|
||||||
|
|
||||||
// Reset sensitivity fields
|
|
||||||
adjointSensitivity::clearSensitivities();
|
|
||||||
shapeSensitivitiesBase::clearSensitivities();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void sensitivitySurfacePoints::write(const word& baseName)
|
|
||||||
{
|
|
||||||
setSuffixName();
|
|
||||||
adjointSensitivity::write();
|
|
||||||
shapeSensitivitiesBase::write();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
} // End namespace Foam
|
|
||||||
} // End namespace incompressible
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -1,346 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | www.openfoam.com
|
|
||||||
\\/ M anipulation |
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
Copyright (C) 2007-2020 PCOpt/NTUA
|
|
||||||
Copyright (C) 2013-2020 FOSS GP
|
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
License
|
|
||||||
This file is part of OpenFOAM.
|
|
||||||
|
|
||||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "sensitivityVolBSplinesIncompressible.H"
|
|
||||||
#include "addToRunTimeSelectionTable.H"
|
|
||||||
#include "IOmanip.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
|
|
||||||
namespace incompressible
|
|
||||||
{
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
defineTypeNameAndDebug(sensitivityVolBSplines, 0);
|
|
||||||
addToRunTimeSelectionTable
|
|
||||||
(
|
|
||||||
adjointSensitivity,
|
|
||||||
sensitivityVolBSplines,
|
|
||||||
dictionary
|
|
||||||
);
|
|
||||||
|
|
||||||
// * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
void sensitivityVolBSplines::computeObjectiveContributions()
|
|
||||||
{
|
|
||||||
if (includeObjective_)
|
|
||||||
{
|
|
||||||
label passedCPs = 0;
|
|
||||||
PtrList<NURBS3DVolume>& boxes = volBSplinesBase_.boxesRef();
|
|
||||||
forAll(boxes, iNURB)
|
|
||||||
{
|
|
||||||
label nb = boxes[iNURB].getControlPoints().size();
|
|
||||||
for (label cpI = 0; cpI < nb; cpI++)
|
|
||||||
{
|
|
||||||
vector dSdbSensCP(Zero);
|
|
||||||
vector dndbSensCP(Zero);
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
tensorField dSdb
|
|
||||||
(
|
|
||||||
boxes[iNURB].dndbBasedSensitivities(patchI, cpI)
|
|
||||||
);
|
|
||||||
dSdbSensCP += gSum(dSfdbMult_()[patchI] & dSdb);
|
|
||||||
|
|
||||||
tensorField dndb
|
|
||||||
(
|
|
||||||
boxes[iNURB].dndbBasedSensitivities
|
|
||||||
(
|
|
||||||
patchI,
|
|
||||||
cpI,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
);
|
|
||||||
dndbSensCP += gSum((dnfdbMult_()[patchI] & dndb));
|
|
||||||
}
|
|
||||||
dSdbSens_[passedCPs + cpI] = dSdbSensCP;
|
|
||||||
dndbSens_[passedCPs + cpI] = dndbSensCP;
|
|
||||||
}
|
|
||||||
passedCPs += nb;
|
|
||||||
}
|
|
||||||
volBSplinesBase_.boundControlPointMovement(dSdbSens_);
|
|
||||||
volBSplinesBase_.boundControlPointMovement(dndbSens_);
|
|
||||||
|
|
||||||
passedCPs = 0;
|
|
||||||
forAll(boxes, iNURB)
|
|
||||||
{
|
|
||||||
vectorField sensDxDbDirect =
|
|
||||||
boxes[iNURB].computeControlPointSensitivities
|
|
||||||
(
|
|
||||||
dxdbDirectMult_(),
|
|
||||||
sensitivityPatchIDs_.toc()
|
|
||||||
);
|
|
||||||
|
|
||||||
// Transfer to global list
|
|
||||||
forAll(sensDxDbDirect, cpI)
|
|
||||||
{
|
|
||||||
dxdbDirectSens_[passedCPs + cpI] = sensDxDbDirect[cpI];
|
|
||||||
}
|
|
||||||
passedCPs += sensDxDbDirect.size();
|
|
||||||
}
|
|
||||||
volBSplinesBase_.boundControlPointMovement(dxdbDirectSens_);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void sensitivityVolBSplines::computeBCContributions()
|
|
||||||
{
|
|
||||||
label passedCPs = 0;
|
|
||||||
PtrList<NURBS3DVolume>& boxes = volBSplinesBase_.boxesRef();
|
|
||||||
forAll(boxes, iNURB)
|
|
||||||
{
|
|
||||||
vectorField sensBcsDxDb =
|
|
||||||
boxes[iNURB].computeControlPointSensitivities
|
|
||||||
(
|
|
||||||
bcDxDbMult_(),
|
|
||||||
sensitivityPatchIDs_.toc()
|
|
||||||
);
|
|
||||||
|
|
||||||
// Transfer to global list
|
|
||||||
forAll(sensBcsDxDb, cpI)
|
|
||||||
{
|
|
||||||
bcSens_[passedCPs + cpI] = sensBcsDxDb[cpI];
|
|
||||||
}
|
|
||||||
passedCPs += sensBcsDxDb.size();
|
|
||||||
}
|
|
||||||
volBSplinesBase_.boundControlPointMovement(bcSens_);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
sensitivityVolBSplines::sensitivityVolBSplines
|
|
||||||
(
|
|
||||||
const fvMesh& mesh,
|
|
||||||
const dictionary& dict,
|
|
||||||
incompressibleAdjointSolver& adjointSolver
|
|
||||||
)
|
|
||||||
:
|
|
||||||
SIBase(mesh, dict, adjointSolver),
|
|
||||||
volBSplinesBase_
|
|
||||||
(
|
|
||||||
const_cast<volBSplinesBase&>(volBSplinesBase::New(mesh))
|
|
||||||
),
|
|
||||||
|
|
||||||
flowSens_(0),
|
|
||||||
dSdbSens_(0),
|
|
||||||
dndbSens_(0),
|
|
||||||
dxdbDirectSens_(0),
|
|
||||||
bcSens_(0),
|
|
||||||
|
|
||||||
derivativesFolder_("optimisation"/type() + "Derivatives")
|
|
||||||
{
|
|
||||||
// No boundary field pointers need to be allocated
|
|
||||||
const label nCPs(volBSplinesBase_.getTotalControlPointsNumber());
|
|
||||||
derivatives_ = scalarField(3*nCPs, Zero);
|
|
||||||
flowSens_ = vectorField(nCPs, Zero);
|
|
||||||
dSdbSens_ = vectorField(nCPs, Zero);
|
|
||||||
dndbSens_ = vectorField(nCPs, Zero);
|
|
||||||
dxdbDirectSens_ = vectorField(nCPs, Zero);
|
|
||||||
bcSens_ = vectorField(nCPs, Zero);
|
|
||||||
|
|
||||||
// Create folder to store sensitivities
|
|
||||||
mkDir(derivativesFolder_);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
void sensitivityVolBSplines::assembleSensitivities()
|
|
||||||
{
|
|
||||||
// Assemble the sensitivity map
|
|
||||||
// Solves for the post-processing equations and adds their contribution to
|
|
||||||
// the sensitivity map
|
|
||||||
surfaceSensitivity_.assembleSensitivities();
|
|
||||||
|
|
||||||
// Finalise sensitivities including dxFace/db
|
|
||||||
const boundaryVectorField& faceSens =
|
|
||||||
surfaceSensitivity_.getWallFaceSensVecBoundary();
|
|
||||||
|
|
||||||
label passedCPs(0);
|
|
||||||
PtrList<NURBS3DVolume>& boxes = volBSplinesBase_.boxesRef();
|
|
||||||
forAll(boxes, iNURB)
|
|
||||||
{
|
|
||||||
vectorField sens =
|
|
||||||
boxes[iNURB].computeControlPointSensitivities
|
|
||||||
(
|
|
||||||
faceSens,
|
|
||||||
sensitivityPatchIDs_.toc()
|
|
||||||
);
|
|
||||||
// Transfer to global list
|
|
||||||
forAll(sens, cpI)
|
|
||||||
{
|
|
||||||
flowSens_[passedCPs + cpI] = sens[cpI];
|
|
||||||
}
|
|
||||||
passedCPs += sens.size();
|
|
||||||
}
|
|
||||||
volBSplinesBase_.boundControlPointMovement(flowSens_);
|
|
||||||
|
|
||||||
// Contribution from objective function
|
|
||||||
// Note:
|
|
||||||
// includeObjectiveContribution has to be set to false (false by default)
|
|
||||||
// in surfaceSensitivity, in order to avoid computing this term twice.
|
|
||||||
// Optionally avoided altogether if includeObjectiveContribution is set to
|
|
||||||
// false for sensitivityVolBSplines
|
|
||||||
computeObjectiveContributions();
|
|
||||||
|
|
||||||
computeBCContributions();
|
|
||||||
|
|
||||||
// Transform sensitivites to scalarField in order to cooperate with
|
|
||||||
// updateMethod
|
|
||||||
forAll(flowSens_, cpI)
|
|
||||||
{
|
|
||||||
derivatives_[3*cpI] =
|
|
||||||
flowSens_[cpI].x()
|
|
||||||
+ dSdbSens_[cpI].x()
|
|
||||||
+ dndbSens_[cpI].x()
|
|
||||||
+ dxdbDirectSens_[cpI].x()
|
|
||||||
+ bcSens_[cpI].x();
|
|
||||||
derivatives_[3*cpI + 1] =
|
|
||||||
flowSens_[cpI].y()
|
|
||||||
+ dSdbSens_[cpI].y()
|
|
||||||
+ dndbSens_[cpI].y()
|
|
||||||
+ dxdbDirectSens_[cpI].y()
|
|
||||||
+ bcSens_[cpI].y();
|
|
||||||
derivatives_[3*cpI + 2] =
|
|
||||||
flowSens_[cpI].z()
|
|
||||||
+ dSdbSens_[cpI].z()
|
|
||||||
+ dndbSens_[cpI].z()
|
|
||||||
+ dxdbDirectSens_[cpI].z()
|
|
||||||
+ bcSens_[cpI].z();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void sensitivityVolBSplines::clearSensitivities()
|
|
||||||
{
|
|
||||||
flowSens_ = vector::zero;
|
|
||||||
dSdbSens_ = vector::zero;
|
|
||||||
dndbSens_ = vector::zero;
|
|
||||||
dxdbDirectSens_ = vector::zero;
|
|
||||||
bcSens_ = vector::zero;
|
|
||||||
|
|
||||||
SIBase::clearSensitivities();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void sensitivityVolBSplines::write(const word& baseName)
|
|
||||||
{
|
|
||||||
Info<< "Writing control point sensitivities to file" << endl;
|
|
||||||
// Write sensitivity map
|
|
||||||
SIBase::write(baseName);
|
|
||||||
// Write control point sensitivities
|
|
||||||
if (Pstream::master())
|
|
||||||
{
|
|
||||||
OFstream derivFile
|
|
||||||
(
|
|
||||||
derivativesFolder_/
|
|
||||||
baseName + adjointVars_.solverName() + mesh_.time().timeName()
|
|
||||||
);
|
|
||||||
unsigned int widthDV =
|
|
||||||
max(int(Foam::name(derivatives_.size()).size()), int(3));
|
|
||||||
unsigned int width = IOstream::defaultPrecision() + 7;
|
|
||||||
derivFile
|
|
||||||
<< setw(widthDV) << "#cp" << " "
|
|
||||||
<< setw(width) << "total::x"<< " "
|
|
||||||
<< setw(width) << "total::y"<< " "
|
|
||||||
<< setw(width) << "total::z"<< " "
|
|
||||||
<< setw(width) << "flow::x" << " "
|
|
||||||
<< setw(width) << "flow::y" << " "
|
|
||||||
<< setw(width) << "flow::z" << " "
|
|
||||||
<< setw(width) << "dSdb::x" << " "
|
|
||||||
<< setw(width) << "dSdb::y" << " "
|
|
||||||
<< setw(width) << "dSdb::z" << " "
|
|
||||||
<< setw(width) << "dndb::x" << " "
|
|
||||||
<< setw(width) << "dndb::y" << " "
|
|
||||||
<< setw(width) << "dndb::z" << " "
|
|
||||||
<< setw(width) << "dxdbDirect::x" << " "
|
|
||||||
<< setw(width) << "dxdbDirect::y" << " "
|
|
||||||
<< setw(width) << "dxdbDirect::z" << " "
|
|
||||||
<< setw(width) << "dvdb::x" << " "
|
|
||||||
<< setw(width) << "dvdb::y" << " "
|
|
||||||
<< setw(width) << "dvdb::z" << endl;
|
|
||||||
|
|
||||||
label passedCPs(0);
|
|
||||||
label lastActive(-1);
|
|
||||||
PtrList<NURBS3DVolume>& boxes = volBSplinesBase_.boxesRef();
|
|
||||||
forAll(boxes, iNURB)
|
|
||||||
{
|
|
||||||
label nb = boxes[iNURB].getControlPoints().size();
|
|
||||||
const boolList& activeCPs = boxes[iNURB].getActiveCPs();
|
|
||||||
for (label iCP = 0; iCP < nb; iCP++)
|
|
||||||
{
|
|
||||||
if (activeCPs[iCP])
|
|
||||||
{
|
|
||||||
label globalCP = passedCPs + iCP;
|
|
||||||
if (globalCP!=lastActive + 1)
|
|
||||||
{
|
|
||||||
derivFile << "\n";
|
|
||||||
}
|
|
||||||
lastActive = globalCP;
|
|
||||||
|
|
||||||
derivFile
|
|
||||||
<< setw(widthDV) << globalCP << " "
|
|
||||||
<< setw(width) << derivatives_[3*globalCP] << " "
|
|
||||||
<< setw(width) << derivatives_[3*globalCP + 1] << " "
|
|
||||||
<< setw(width) << derivatives_[3*globalCP + 2] << " "
|
|
||||||
<< setw(width) << flowSens_[globalCP].x() << " "
|
|
||||||
<< setw(width) << flowSens_[globalCP].y() << " "
|
|
||||||
<< setw(width) << flowSens_[globalCP].z() << " "
|
|
||||||
<< setw(width) << dSdbSens_[globalCP].x() << " "
|
|
||||||
<< setw(width) << dSdbSens_[globalCP].y() << " "
|
|
||||||
<< setw(width) << dSdbSens_[globalCP].z() << " "
|
|
||||||
<< setw(width) << dndbSens_[globalCP].x() << " "
|
|
||||||
<< setw(width) << dndbSens_[globalCP].y() << " "
|
|
||||||
<< setw(width) << dndbSens_[globalCP].z() << " "
|
|
||||||
<< setw(width) << dxdbDirectSens_[globalCP].x() << " "
|
|
||||||
<< setw(width) << dxdbDirectSens_[globalCP].y() << " "
|
|
||||||
<< setw(width) << dxdbDirectSens_[globalCP].z() << " "
|
|
||||||
<< setw(width) << bcSens_[globalCP].x() << " "
|
|
||||||
<< setw(width) << bcSens_[globalCP].y() << " "
|
|
||||||
<< setw(width) << bcSens_[globalCP].z()
|
|
||||||
<< endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
passedCPs += nb;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
} // End namespace incompressible
|
|
||||||
} // End namespace Foam
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -1,148 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | www.openfoam.com
|
|
||||||
\\/ M anipulation |
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
Copyright (C) 2007-2020 PCOpt/NTUA
|
|
||||||
Copyright (C) 2013-2020 FOSS GP
|
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
License
|
|
||||||
This file is part of OpenFOAM.
|
|
||||||
|
|
||||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Class
|
|
||||||
Foam::incompressible::sensitivityVolBSplines
|
|
||||||
|
|
||||||
Description
|
|
||||||
Calculation of adjoint based sensitivities at vol B-Splines control points
|
|
||||||
using the SI or e-SI approach (determined by surface sensitivities)
|
|
||||||
|
|
||||||
SourceFiles
|
|
||||||
sensitivityVolBSplines.C
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#ifndef sensitivityVolBSplinesIncompressible_H
|
|
||||||
#define sensitivityVolBSplinesIncompressible_H
|
|
||||||
|
|
||||||
#include "SIBaseIncompressible.H"
|
|
||||||
#include "volBSplinesBase.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
|
|
||||||
namespace incompressible
|
|
||||||
{
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
Class sensitivityVolBSplines Declaration
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
class sensitivityVolBSplines
|
|
||||||
:
|
|
||||||
public SIBase
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
|
|
||||||
// Protected data
|
|
||||||
|
|
||||||
//- Reference to underlaying volumetric B-Splines morpher
|
|
||||||
volBSplinesBase& volBSplinesBase_;
|
|
||||||
|
|
||||||
//- Flow related term
|
|
||||||
vectorField flowSens_;
|
|
||||||
|
|
||||||
//- Term depending on delta(n dS)/delta b
|
|
||||||
vectorField dSdbSens_;
|
|
||||||
|
|
||||||
//- Term depending on delta (n)/delta b
|
|
||||||
vectorField dndbSens_;
|
|
||||||
|
|
||||||
//- Term depending on dxdb for objective functions directly depending
|
|
||||||
//- on x
|
|
||||||
vectorField dxdbDirectSens_;
|
|
||||||
|
|
||||||
//- Term dependng on the differentiation of boundary conditions
|
|
||||||
vectorField bcSens_;
|
|
||||||
|
|
||||||
fileName derivativesFolder_;
|
|
||||||
|
|
||||||
|
|
||||||
// Protected Member Functions
|
|
||||||
|
|
||||||
void computeObjectiveContributions();
|
|
||||||
void computeBCContributions();
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
// Private Member Functions
|
|
||||||
|
|
||||||
//- No copy construct
|
|
||||||
sensitivityVolBSplines(const sensitivityVolBSplines&) = delete;
|
|
||||||
|
|
||||||
//- No copy assignment
|
|
||||||
void operator=(const sensitivityVolBSplines&) = delete;
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
//- Runtime type information
|
|
||||||
TypeName("volumetricBSplines");
|
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
|
||||||
|
|
||||||
//- Construct from components
|
|
||||||
sensitivityVolBSplines
|
|
||||||
(
|
|
||||||
const fvMesh& mesh,
|
|
||||||
const dictionary& dict,
|
|
||||||
incompressibleAdjointSolver& adjointSolver
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
//- Destructor
|
|
||||||
virtual ~sensitivityVolBSplines() = default;
|
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
|
||||||
|
|
||||||
//- Assemble sensitivities
|
|
||||||
virtual void assembleSensitivities();
|
|
||||||
|
|
||||||
//- Zero sensitivity fields and their constituents
|
|
||||||
virtual void clearSensitivities();
|
|
||||||
|
|
||||||
//- Write sensitivities to file
|
|
||||||
virtual void write(const word& baseName = word::null);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
} // End namespace incompressible
|
|
||||||
} // End namespace Foam
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -1,409 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | www.openfoam.com
|
|
||||||
\\/ M anipulation |
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
Copyright (C) 2007-2021 PCOpt/NTUA
|
|
||||||
Copyright (C) 2013-2021 FOSS GP
|
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
License
|
|
||||||
This file is part of OpenFOAM.
|
|
||||||
|
|
||||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "sensitivityVolBSplinesFIIncompressible.H"
|
|
||||||
#include "pointVolInterpolation.H"
|
|
||||||
#include "IOmanip.H"
|
|
||||||
#include "addToRunTimeSelectionTable.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
|
|
||||||
namespace incompressible
|
|
||||||
{
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
defineTypeNameAndDebug(sensitivityVolBSplinesFI, 0);
|
|
||||||
addToRunTimeSelectionTable
|
|
||||||
(
|
|
||||||
adjointSensitivity,
|
|
||||||
sensitivityVolBSplinesFI,
|
|
||||||
dictionary
|
|
||||||
);
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
sensitivityVolBSplinesFI::sensitivityVolBSplinesFI
|
|
||||||
(
|
|
||||||
const fvMesh& mesh,
|
|
||||||
const dictionary& dict,
|
|
||||||
incompressibleAdjointSolver& adjointSolver
|
|
||||||
)
|
|
||||||
:
|
|
||||||
FIBase(mesh, dict, adjointSolver),
|
|
||||||
volBSplinesBase_
|
|
||||||
(
|
|
||||||
const_cast<volBSplinesBase&>(volBSplinesBase::New(mesh))
|
|
||||||
),
|
|
||||||
flowSens_(0),
|
|
||||||
dSdbSens_(0),
|
|
||||||
dndbSens_(0),
|
|
||||||
dxdbDirectSens_(0),
|
|
||||||
dVdbSens_(0),
|
|
||||||
distanceSens_(0),
|
|
||||||
optionsSens_(0),
|
|
||||||
bcSens_(0),
|
|
||||||
|
|
||||||
derivativesFolder_("optimisation"/type() + "Derivatives")
|
|
||||||
{
|
|
||||||
// No boundary field pointers need to be allocated
|
|
||||||
|
|
||||||
label nCPs = volBSplinesBase_.getTotalControlPointsNumber();
|
|
||||||
derivatives_ = scalarField(3*nCPs, Zero);
|
|
||||||
flowSens_ = vectorField(nCPs, Zero);
|
|
||||||
dSdbSens_ = vectorField(nCPs, Zero);
|
|
||||||
dndbSens_ = vectorField(nCPs, Zero);
|
|
||||||
dxdbDirectSens_ = vectorField(nCPs, Zero);
|
|
||||||
dVdbSens_ = vectorField(nCPs, Zero);
|
|
||||||
distanceSens_ = vectorField(nCPs, Zero);
|
|
||||||
optionsSens_ = vectorField(nCPs, Zero);
|
|
||||||
bcSens_ = vectorField(nCPs, Zero);
|
|
||||||
|
|
||||||
// Create folder to store sensitivities
|
|
||||||
mkDir(derivativesFolder_);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
void sensitivityVolBSplinesFI::assembleSensitivities()
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
addProfiling
|
|
||||||
(
|
|
||||||
sensitivityVolBSplinesFI,
|
|
||||||
"sensitivityVolBSplinesFI::assembleSensitivities"
|
|
||||||
);
|
|
||||||
*/
|
|
||||||
read();
|
|
||||||
|
|
||||||
// Interpolation engine
|
|
||||||
pointVolInterpolation volPointInter(pointMesh::New(mesh_), mesh_);
|
|
||||||
|
|
||||||
// Adjoint to the eikonal equation
|
|
||||||
autoPtr<volTensorField> distanceSensPtr(nullptr);
|
|
||||||
if (includeDistance_)
|
|
||||||
{
|
|
||||||
// Solver equation
|
|
||||||
eikonalSolver_->solve();
|
|
||||||
|
|
||||||
// Allocate memory and compute grad(dxdb) multiplier
|
|
||||||
distanceSensPtr.reset
|
|
||||||
(
|
|
||||||
createZeroFieldPtr<tensor>
|
|
||||||
(
|
|
||||||
mesh_,
|
|
||||||
"distanceSensPtr",
|
|
||||||
dimensionSet(0, 2, -3, 0, 0, 0, 0)
|
|
||||||
)
|
|
||||||
);
|
|
||||||
distanceSensPtr() = eikonalSolver_->getFISensitivityTerm()().T();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Integration
|
|
||||||
label passedCPs(0);
|
|
||||||
PtrList<NURBS3DVolume>& boxes = volBSplinesBase_.boxesRef();
|
|
||||||
forAll(boxes, iNURB)
|
|
||||||
{
|
|
||||||
const label nb(boxes[iNURB].getControlPoints().size());
|
|
||||||
vectorField boxSensitivities(nb, Zero);
|
|
||||||
|
|
||||||
vectorField dxdbSens = boxes[iNURB].computeControlPointSensitivities
|
|
||||||
(
|
|
||||||
dxdbDirectMult_(),
|
|
||||||
sensitivityPatchIDs_.toc()
|
|
||||||
);
|
|
||||||
|
|
||||||
vectorField bcSens = boxes[iNURB].computeControlPointSensitivities
|
|
||||||
(
|
|
||||||
bcDxDbMult_(),
|
|
||||||
sensitivityPatchIDs_.toc()
|
|
||||||
);
|
|
||||||
|
|
||||||
for (label cpI = 0; cpI < nb; cpI++)
|
|
||||||
{
|
|
||||||
label globalCP = passedCPs + cpI;
|
|
||||||
|
|
||||||
// Parameterization info
|
|
||||||
tmp<volTensorField> tvolDxDbI
|
|
||||||
(
|
|
||||||
volPointInter.interpolate(boxes[iNURB].getDxDb(cpI))
|
|
||||||
);
|
|
||||||
const volTensorField& volDxDbI = tvolDxDbI();
|
|
||||||
|
|
||||||
// Chain rule used to get dx/db at cells
|
|
||||||
// Gives practically the same results at a much higher CPU cost
|
|
||||||
/*
|
|
||||||
tmp<volTensorField> tvolDxDbI(boxes[iNURB].getDxCellsDb(cpI));
|
|
||||||
volTensorField& volDxDbI = tvolDxDbI.ref();
|
|
||||||
*/
|
|
||||||
|
|
||||||
const tensorField& gradDxDbMultInt = gradDxDbMult_.primitiveField();
|
|
||||||
for (label idir = 0; idir < pTraits<vector>::nComponents; ++idir)
|
|
||||||
{
|
|
||||||
// Gradient of parameterization info
|
|
||||||
auto ttemp =
|
|
||||||
tmp<volVectorField>::New
|
|
||||||
(
|
|
||||||
IOobject
|
|
||||||
(
|
|
||||||
"dxdb",
|
|
||||||
mesh_.time().timeName(),
|
|
||||||
mesh_,
|
|
||||||
IOobject::NO_READ,
|
|
||||||
IOobject::NO_WRITE
|
|
||||||
),
|
|
||||||
mesh_,
|
|
||||||
dimensionedVector(dimless, Zero)
|
|
||||||
);
|
|
||||||
volVectorField& temp = ttemp.ref();
|
|
||||||
unzipCol(volDxDbI, vector::components(idir), temp);
|
|
||||||
|
|
||||||
volTensorField gradDxDb(fvc::grad(temp));
|
|
||||||
// Volume integral terms
|
|
||||||
flowSens_[globalCP].component(idir) = gSum
|
|
||||||
(
|
|
||||||
(gradDxDbMultInt && gradDxDb.primitiveField())
|
|
||||||
*mesh_.V()
|
|
||||||
);
|
|
||||||
|
|
||||||
if (includeDistance_)
|
|
||||||
{
|
|
||||||
const tensorField& distSensInt =
|
|
||||||
distanceSensPtr().primitiveField();
|
|
||||||
distanceSens_[globalCP].component(idir) =
|
|
||||||
gSum
|
|
||||||
(
|
|
||||||
(distSensInt && gradDxDb.primitiveField())
|
|
||||||
*mesh_.V()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Contribution from objective function term from
|
|
||||||
// delta( n dS ) / delta b and
|
|
||||||
// delta ( x ) / delta b
|
|
||||||
// for objectives directly depending on x
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
tensorField dSdb
|
|
||||||
(
|
|
||||||
boxes[iNURB].dndbBasedSensitivities(patchI, cpI)
|
|
||||||
);
|
|
||||||
dSdbSens_[globalCP] += gSum(dSfdbMult_()[patchI] & dSdb);
|
|
||||||
tensorField dndb
|
|
||||||
(
|
|
||||||
boxes[iNURB].dndbBasedSensitivities(patchI, cpI, false)
|
|
||||||
);
|
|
||||||
dndbSens_[globalCP] += gSum((dnfdbMult_()[patchI] & dndb));
|
|
||||||
}
|
|
||||||
|
|
||||||
// Contribution from delta (V) / delta b
|
|
||||||
// For objectives defined as volume integrals only
|
|
||||||
dVdbSens_[globalCP] +=
|
|
||||||
gSum
|
|
||||||
(
|
|
||||||
divDxDbMult_
|
|
||||||
*fvc::div(T(volDxDbI))().primitiveField()
|
|
||||||
*mesh_.V()
|
|
||||||
);
|
|
||||||
|
|
||||||
// Terms from fvOptions
|
|
||||||
optionsSens_[globalCP] +=
|
|
||||||
gSum((optionsDxDbMult_ & volDxDbI.primitiveField())*mesh_.V());
|
|
||||||
|
|
||||||
// dxdbSens storage
|
|
||||||
dxdbDirectSens_[globalCP] = dxdbSens[cpI];
|
|
||||||
|
|
||||||
// bcSens storage
|
|
||||||
bcSens_[globalCP] = bcSens[cpI];
|
|
||||||
|
|
||||||
boxSensitivities[cpI] =
|
|
||||||
flowSens_[globalCP]
|
|
||||||
+ dSdbSens_[globalCP]
|
|
||||||
+ dndbSens_[globalCP]
|
|
||||||
+ dVdbSens_[globalCP]
|
|
||||||
+ distanceSens_[globalCP]
|
|
||||||
+ dxdbDirectSens_[globalCP]
|
|
||||||
+ optionsSens_[globalCP]
|
|
||||||
+ bcSens_[globalCP];
|
|
||||||
}
|
|
||||||
|
|
||||||
// Zero sensitivities in non-active design variables
|
|
||||||
boxes[iNURB].boundControlPointMovement(boxSensitivities);
|
|
||||||
|
|
||||||
// Transfer sensitivities to global list
|
|
||||||
for (label cpI = 0; cpI < nb; cpI++)
|
|
||||||
{
|
|
||||||
label globalCP = passedCPs + cpI;
|
|
||||||
derivatives_[3*globalCP] = boxSensitivities[cpI].x();
|
|
||||||
derivatives_[3*globalCP + 1] = boxSensitivities[cpI].y();
|
|
||||||
derivatives_[3*globalCP + 2] = boxSensitivities[cpI].z();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Increment number of passed sensitivities
|
|
||||||
passedCPs += nb;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Zero non-active sensitivity components.
|
|
||||||
// For consistent output only, does not affect optimisation
|
|
||||||
volBSplinesBase_.boundControlPointMovement(flowSens_);
|
|
||||||
volBSplinesBase_.boundControlPointMovement(dSdbSens_);
|
|
||||||
volBSplinesBase_.boundControlPointMovement(dndbSens_);
|
|
||||||
volBSplinesBase_.boundControlPointMovement(dVdbSens_);
|
|
||||||
volBSplinesBase_.boundControlPointMovement(distanceSens_);
|
|
||||||
volBSplinesBase_.boundControlPointMovement(dxdbDirectSens_);
|
|
||||||
volBSplinesBase_.boundControlPointMovement(optionsSens_);
|
|
||||||
volBSplinesBase_.boundControlPointMovement(bcSens_);
|
|
||||||
|
|
||||||
//profiling::writeNow();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void sensitivityVolBSplinesFI::clearSensitivities()
|
|
||||||
{
|
|
||||||
flowSens_ = vector::zero;
|
|
||||||
dSdbSens_ = vector::zero;
|
|
||||||
dndbSens_ = vector::zero;
|
|
||||||
dxdbDirectSens_ = vector::zero;
|
|
||||||
dVdbSens_ = vector::zero;
|
|
||||||
distanceSens_ = vector::zero;
|
|
||||||
optionsSens_ = vector::zero;
|
|
||||||
bcSens_ = vector::zero;
|
|
||||||
|
|
||||||
FIBase::clearSensitivities();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void sensitivityVolBSplinesFI::write(const word& baseName)
|
|
||||||
{
|
|
||||||
Info<< "Writing control point sensitivities to file" << endl;
|
|
||||||
if (Pstream::master())
|
|
||||||
{
|
|
||||||
OFstream derivFile
|
|
||||||
(
|
|
||||||
derivativesFolder_/
|
|
||||||
baseName + adjointVars_.solverName() + mesh_.time().timeName()
|
|
||||||
);
|
|
||||||
unsigned int widthDV
|
|
||||||
(
|
|
||||||
max(int(Foam::name(flowSens_.size()).size()), int(3))
|
|
||||||
);
|
|
||||||
unsigned int width = IOstream::defaultPrecision() + 7;
|
|
||||||
derivFile
|
|
||||||
<< setw(widthDV) << "#cp" << " "
|
|
||||||
<< setw(width) << "total::x" << " "
|
|
||||||
<< setw(width) << "total::y" << " "
|
|
||||||
<< setw(width) << "total::z" << " "
|
|
||||||
<< setw(width) << "flow::x" << " "
|
|
||||||
<< setw(width) << "flow::y" << " "
|
|
||||||
<< setw(width) << "flow::z" << " "
|
|
||||||
<< setw(width) << "dSdb::x" << " "
|
|
||||||
<< setw(width) << "dSdb::y" << " "
|
|
||||||
<< setw(width) << "dSdb::z" << " "
|
|
||||||
<< setw(width) << "dndb::x" << " "
|
|
||||||
<< setw(width) << "dndb::y" << " "
|
|
||||||
<< setw(width) << "dndb::z" << " "
|
|
||||||
<< setw(width) << "dxdbDirect::x" << " "
|
|
||||||
<< setw(width) << "dxdbDirect::y" << " "
|
|
||||||
<< setw(width) << "dxdbDirect::z" << " "
|
|
||||||
<< setw(width) << "dVdb::x" << " "
|
|
||||||
<< setw(width) << "dVdb::y" << " "
|
|
||||||
<< setw(width) << "dVdb::z" << " "
|
|
||||||
<< setw(width) << "distance::x" << " "
|
|
||||||
<< setw(width) << "distance::y" << " "
|
|
||||||
<< setw(width) << "distance::z" << " "
|
|
||||||
<< setw(width) << "options::x" << " "
|
|
||||||
<< setw(width) << "options::y" << " "
|
|
||||||
<< setw(width) << "options::z" << " "
|
|
||||||
<< setw(width) << "dvdb::x" << " "
|
|
||||||
<< setw(width) << "dvdb::y" << " "
|
|
||||||
<< setw(width) << "dvdb::z" << endl;
|
|
||||||
|
|
||||||
label passedCPs(0);
|
|
||||||
label lastActive(-1);
|
|
||||||
PtrList<NURBS3DVolume>& boxes = volBSplinesBase_.boxesRef();
|
|
||||||
forAll(boxes, iNURB)
|
|
||||||
{
|
|
||||||
label nb = boxes[iNURB].getControlPoints().size();
|
|
||||||
const boolList& activeCPs = boxes[iNURB].getActiveCPs();
|
|
||||||
for (label iCP = 0; iCP < nb; iCP++)
|
|
||||||
{
|
|
||||||
if (activeCPs[iCP])
|
|
||||||
{
|
|
||||||
label globalCP = passedCPs + iCP;
|
|
||||||
if (globalCP!=lastActive + 1) derivFile << "\n";
|
|
||||||
lastActive = globalCP;
|
|
||||||
|
|
||||||
derivFile
|
|
||||||
<< setw(widthDV) << globalCP << " "
|
|
||||||
<< setw(width) << derivatives_[3*globalCP] << " "
|
|
||||||
<< setw(width) << derivatives_[3*globalCP + 1] << " "
|
|
||||||
<< setw(width) << derivatives_[3*globalCP + 2] << " "
|
|
||||||
<< setw(width) << flowSens_[globalCP].x() << " "
|
|
||||||
<< setw(width) << flowSens_[globalCP].y() << " "
|
|
||||||
<< setw(width) << flowSens_[globalCP].z() << " "
|
|
||||||
<< setw(width) << dSdbSens_[globalCP].x() << " "
|
|
||||||
<< setw(width) << dSdbSens_[globalCP].y() << " "
|
|
||||||
<< setw(width) << dSdbSens_[globalCP].z() << " "
|
|
||||||
<< setw(width) << dndbSens_[globalCP].x() << " "
|
|
||||||
<< setw(width) << dndbSens_[globalCP].y() << " "
|
|
||||||
<< setw(width) << dndbSens_[globalCP].z() << " "
|
|
||||||
<< setw(width) << dxdbDirectSens_[globalCP].x() << " "
|
|
||||||
<< setw(width) << dxdbDirectSens_[globalCP].y() << " "
|
|
||||||
<< setw(width) << dxdbDirectSens_[globalCP].z() << " "
|
|
||||||
<< setw(width) << dVdbSens_[globalCP].x() << " "
|
|
||||||
<< setw(width) << dVdbSens_[globalCP].y() << " "
|
|
||||||
<< setw(width) << dVdbSens_[globalCP].z() << " "
|
|
||||||
<< setw(width) << distanceSens_[globalCP].x() << " "
|
|
||||||
<< setw(width) << distanceSens_[globalCP].y() << " "
|
|
||||||
<< setw(width) << distanceSens_[globalCP].z() << " "
|
|
||||||
<< setw(width) << optionsSens_[globalCP].x() << " "
|
|
||||||
<< setw(width) << optionsSens_[globalCP].y() << " "
|
|
||||||
<< setw(width) << optionsSens_[globalCP].z() << " "
|
|
||||||
<< setw(width) << bcSens_[globalCP].x() << " "
|
|
||||||
<< setw(width) << bcSens_[globalCP].y() << " "
|
|
||||||
<< setw(width) << bcSens_[globalCP].z() << endl;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
passedCPs += nb;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
} // End namespace incompressible
|
|
||||||
} // End namespace Foam
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -1,151 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | www.openfoam.com
|
|
||||||
\\/ M anipulation |
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
Copyright (C) 2007-2020 PCOpt/NTUA
|
|
||||||
Copyright (C) 2013-2020 FOSS GP
|
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
License
|
|
||||||
This file is part of OpenFOAM.
|
|
||||||
|
|
||||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Class
|
|
||||||
Foam::incompressible::sensitivityVolBSplinesFI
|
|
||||||
|
|
||||||
Description
|
|
||||||
Calculation of adjoint based sensitivities at vol B-Splines control points
|
|
||||||
using the FI approach.
|
|
||||||
|
|
||||||
SourceFiles
|
|
||||||
sensitivityVolBSplinesFI.C
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#ifndef sensitivityVolBSplinesFIIncompressible_H
|
|
||||||
#define sensitivityVolBSplinesFIIncompressible_H
|
|
||||||
|
|
||||||
#include "FIBaseIncompressible.H"
|
|
||||||
#include "volBSplinesBase.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
|
|
||||||
namespace incompressible
|
|
||||||
{
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
Class sensitivityVolBSplinesFI Declaration
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
class sensitivityVolBSplinesFI
|
|
||||||
:
|
|
||||||
public FIBase
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
|
|
||||||
// Protected data
|
|
||||||
|
|
||||||
//- Reference to underlaying volumetric B-Splines morpher
|
|
||||||
volBSplinesBase& volBSplinesBase_;
|
|
||||||
|
|
||||||
//- Flow related term
|
|
||||||
vectorField flowSens_;
|
|
||||||
|
|
||||||
//- Term depending on delta(n dS)/delta b
|
|
||||||
vectorField dSdbSens_;
|
|
||||||
|
|
||||||
//- Term depending on delta(n)/delta b
|
|
||||||
vectorField dndbSens_;
|
|
||||||
|
|
||||||
//- Term depending on delta(x)/delta b for objectives that directly
|
|
||||||
//- depend on x
|
|
||||||
vectorField dxdbDirectSens_;
|
|
||||||
|
|
||||||
//- Term depending on delta(V)/delta b
|
|
||||||
vectorField dVdbSens_;
|
|
||||||
|
|
||||||
//- Term depending on distance differentiation
|
|
||||||
vectorField distanceSens_;
|
|
||||||
|
|
||||||
//- Term depending on fvOptions
|
|
||||||
vectorField optionsSens_;
|
|
||||||
|
|
||||||
//- Term depending on the differentiation of boundary conditions
|
|
||||||
vectorField bcSens_;
|
|
||||||
|
|
||||||
fileName derivativesFolder_;
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
// Private Member Functions
|
|
||||||
|
|
||||||
//- No copy construct
|
|
||||||
sensitivityVolBSplinesFI(const sensitivityVolBSplinesFI&) = delete;
|
|
||||||
|
|
||||||
//- No copy assignment
|
|
||||||
void operator=(const sensitivityVolBSplinesFI&) = delete;
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
//- Runtime type information
|
|
||||||
TypeName("volumetricBSplinesFI");
|
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
|
||||||
|
|
||||||
//- Construct from components
|
|
||||||
sensitivityVolBSplinesFI
|
|
||||||
(
|
|
||||||
const fvMesh& mesh,
|
|
||||||
const dictionary& dict,
|
|
||||||
incompressibleAdjointSolver& adjointSolver
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
//- Destructor
|
|
||||||
virtual ~sensitivityVolBSplinesFI() = default;
|
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
|
||||||
|
|
||||||
//- Assemble sensitivities
|
|
||||||
virtual void assembleSensitivities();
|
|
||||||
|
|
||||||
//- Zero sensitivity fields and their constituents
|
|
||||||
virtual void clearSensitivities();
|
|
||||||
|
|
||||||
//- Write sensitivities to file
|
|
||||||
virtual void write(const word& baseName = word::null);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
} // End namespace incompressible
|
|
||||||
} // End namespace Foam
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -1,176 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | www.openfoam.com
|
|
||||||
\\/ M anipulation |
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
Copyright (C) 2020 PCOpt/NTUA
|
|
||||||
Copyright (C) 2020 FOSS GP
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
License
|
|
||||||
This file is part of OpenFOAM.
|
|
||||||
|
|
||||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#include "shapeSensitivitiesIncompressible.H"
|
|
||||||
#include "adjointBoundaryConditions.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
|
|
||||||
namespace incompressible
|
|
||||||
{
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
defineTypeNameAndDebug(shapeSensitivities, 0);
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
|
||||||
|
|
||||||
void shapeSensitivities::accumulateDirectSensitivityIntegrand(const scalar dt)
|
|
||||||
{
|
|
||||||
// Accumulate direct sensitivities
|
|
||||||
PtrList<objective>& functions = objectiveManager_.getObjectiveFunctions();
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
const scalarField magSfDt(mesh_.boundary()[patchI].magSf()*dt);
|
|
||||||
for (objective& func : functions)
|
|
||||||
{
|
|
||||||
const scalar wei(func.weight());
|
|
||||||
dSfdbMult_()[patchI] += wei*func.dSdbMultiplier(patchI)*dt;
|
|
||||||
dnfdbMult_()[patchI] += wei*func.dndbMultiplier(patchI)*magSfDt;
|
|
||||||
dxdbDirectMult_()[patchI] +=
|
|
||||||
wei*func.dxdbDirectMultiplier(patchI)*magSfDt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void shapeSensitivities::accumulateBCSensitivityIntegrand(const scalar dt)
|
|
||||||
{
|
|
||||||
// Avoid updating the event number to keep consistency with cases caching
|
|
||||||
// gradUa
|
|
||||||
auto& UaBoundary = adjointVars_.Ua().boundaryFieldRef(false);
|
|
||||||
tmp<boundaryVectorField> DvDbMult(dvdbMult());
|
|
||||||
|
|
||||||
// Accumulate sensitivities due to boundary conditions
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
const scalarField magSfDt(mesh_.boundary()[patchI].magSf()*dt);
|
|
||||||
fvPatchVectorField& Uab = UaBoundary[patchI];
|
|
||||||
if (isA<adjointVectorBoundaryCondition>(Uab))
|
|
||||||
{
|
|
||||||
bcDxDbMult_()[patchI] +=
|
|
||||||
(
|
|
||||||
DvDbMult()[patchI]
|
|
||||||
& refCast<adjointVectorBoundaryCondition>(Uab).dxdbMult()
|
|
||||||
)*magSfDt;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
tmp<boundaryVectorField> shapeSensitivities::dvdbMult() const
|
|
||||||
{
|
|
||||||
tmp<boundaryVectorField>
|
|
||||||
tres(createZeroBoundaryPtr<vector>(meshShape_).ptr());
|
|
||||||
boundaryVectorField& res = tres.ref();
|
|
||||||
|
|
||||||
// Grab references
|
|
||||||
const volScalarField& pa = adjointVars_.pa();
|
|
||||||
const volVectorField& Ua = adjointVars_.Ua();
|
|
||||||
const autoPtr<incompressibleAdjoint::adjointRASModel>& adjointTurbulence =
|
|
||||||
adjointVars_.adjointTurbulence();
|
|
||||||
|
|
||||||
// Fields needed to calculate adjoint sensitivities
|
|
||||||
const autoPtr<incompressible::RASModelVariables>&
|
|
||||||
turbVars = primalVars_.RASModelVariables();
|
|
||||||
const singlePhaseTransportModel& lamTransp = primalVars_.laminarTransport();
|
|
||||||
volScalarField nuEff(lamTransp.nu() + turbVars->nutRef());
|
|
||||||
tmp<volTensorField> tgradUa = fvc::grad(Ua);
|
|
||||||
const volTensorField::Boundary& gradUabf = tgradUa.cref().boundaryField();
|
|
||||||
|
|
||||||
for (const label patchI : sensitivityPatchIDs_)
|
|
||||||
{
|
|
||||||
const fvPatch& patch = meshShape_.boundary()[patchI];
|
|
||||||
tmp<vectorField> tnf = patch.nf();
|
|
||||||
const vectorField& nf = tnf();
|
|
||||||
|
|
||||||
res[patchI] =
|
|
||||||
(
|
|
||||||
nuEff.boundaryField()[patchI]
|
|
||||||
* (
|
|
||||||
Ua.boundaryField()[patchI].snGrad()
|
|
||||||
+ (gradUabf[patchI] & nf)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
- (nf*pa.boundaryField()[patchI])
|
|
||||||
+ adjointTurbulence().adjointMomentumBCSource()[patchI];
|
|
||||||
}
|
|
||||||
|
|
||||||
return tres;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
shapeSensitivities::shapeSensitivities
|
|
||||||
(
|
|
||||||
const fvMesh& mesh,
|
|
||||||
const dictionary& dict,
|
|
||||||
incompressibleAdjointSolver& adjointSolver
|
|
||||||
)
|
|
||||||
:
|
|
||||||
adjointSensitivity(mesh, dict, adjointSolver),
|
|
||||||
shapeSensitivitiesBase(mesh, dict),
|
|
||||||
dSfdbMult_(createZeroBoundaryPtr<vector>(mesh_)),
|
|
||||||
dnfdbMult_(createZeroBoundaryPtr<vector>(mesh_)),
|
|
||||||
dxdbDirectMult_(createZeroBoundaryPtr<vector>(mesh_)),
|
|
||||||
bcDxDbMult_(createZeroBoundaryPtr<vector>(mesh_))
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
void shapeSensitivities::clearSensitivities()
|
|
||||||
{
|
|
||||||
dSfdbMult_() = vector::zero;
|
|
||||||
dnfdbMult_() = vector::zero;
|
|
||||||
dxdbDirectMult_() = vector::zero;
|
|
||||||
bcDxDbMult_() = vector::zero;
|
|
||||||
|
|
||||||
adjointSensitivity::clearSensitivities();
|
|
||||||
shapeSensitivitiesBase::clearSensitivities();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void shapeSensitivities::write(const word& baseName)
|
|
||||||
{
|
|
||||||
adjointSensitivity::write(baseName);
|
|
||||||
shapeSensitivitiesBase::write();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
} // End namespace incompressible
|
|
||||||
} // End namespace Foam
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -1,141 +0,0 @@
|
|||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
========= |
|
|
||||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
|
||||||
\\ / O peration |
|
|
||||||
\\ / A nd | www.openfoam.com
|
|
||||||
\\/ M anipulation |
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
Copyright (C) 2020 PCOpt/NTUA
|
|
||||||
Copyright (C) 2020 FOSS GP
|
|
||||||
-------------------------------------------------------------------------------
|
|
||||||
License
|
|
||||||
This file is part of OpenFOAM.
|
|
||||||
|
|
||||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
|
||||||
under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 3 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
||||||
for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Class
|
|
||||||
Foam::incompressible::shapeSensitivitiesBase
|
|
||||||
|
|
||||||
Description
|
|
||||||
Base class supporting shape sensitivity derivatives for
|
|
||||||
incompressible flows
|
|
||||||
|
|
||||||
SourceFiles
|
|
||||||
shapeSensitivitiesBase.C
|
|
||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
#ifndef shapeSensitivitiesIncompressible_H
|
|
||||||
#define shapeSensitivitiesIncompressible_H
|
|
||||||
|
|
||||||
#include "adjointSensitivityIncompressible.H"
|
|
||||||
#include "shapeSensitivitiesBase.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
namespace incompressible
|
|
||||||
{
|
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
|
||||||
Class shapeSensitivities Declaration
|
|
||||||
\*---------------------------------------------------------------------------*/
|
|
||||||
|
|
||||||
class shapeSensitivities
|
|
||||||
:
|
|
||||||
public adjointSensitivity,
|
|
||||||
public shapeSensitivitiesBase
|
|
||||||
{
|
|
||||||
protected:
|
|
||||||
|
|
||||||
// Protected data
|
|
||||||
|
|
||||||
//- Fields related to direct sensitivities
|
|
||||||
autoPtr<boundaryVectorField> dSfdbMult_;
|
|
||||||
autoPtr<boundaryVectorField> dnfdbMult_;
|
|
||||||
autoPtr<boundaryVectorField> dxdbDirectMult_;
|
|
||||||
autoPtr<boundaryVectorField> bcDxDbMult_;
|
|
||||||
|
|
||||||
|
|
||||||
// Protected Member Fuctions
|
|
||||||
|
|
||||||
//- Accumulate direct sensitivities
|
|
||||||
virtual void accumulateDirectSensitivityIntegrand(const scalar dt);
|
|
||||||
|
|
||||||
//- Accumulate sensitivities enamating from the boundary conditions
|
|
||||||
virtual void accumulateBCSensitivityIntegrand(const scalar dt);
|
|
||||||
|
|
||||||
//- Compute multiplier of dv_i/db
|
|
||||||
tmp<boundaryVectorField> dvdbMult() const;
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
// Private Member Functions
|
|
||||||
|
|
||||||
//- No copy construct
|
|
||||||
shapeSensitivities(const shapeSensitivities&) = delete;
|
|
||||||
|
|
||||||
//- No copy assignment
|
|
||||||
void operator=(const shapeSensitivities&) = delete;
|
|
||||||
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
//- Runtime type information
|
|
||||||
TypeName("shapeSensitivities");
|
|
||||||
|
|
||||||
|
|
||||||
// Constructors
|
|
||||||
|
|
||||||
//- Construct from components
|
|
||||||
shapeSensitivities
|
|
||||||
(
|
|
||||||
const fvMesh& mesh,
|
|
||||||
const dictionary& dict,
|
|
||||||
incompressibleAdjointSolver& adjointSolver
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
//- Destructor
|
|
||||||
virtual ~shapeSensitivities() = default;
|
|
||||||
|
|
||||||
|
|
||||||
// Member Functions
|
|
||||||
|
|
||||||
//- Accumulate sensitivity integrands
|
|
||||||
virtual void accumulateIntegrand(const scalar dt) = 0;
|
|
||||||
|
|
||||||
//- Assemble sensitivities
|
|
||||||
virtual void assembleSensitivities() = 0;
|
|
||||||
|
|
||||||
//- Zero sensitivity fields and their constituents
|
|
||||||
virtual void clearSensitivities();
|
|
||||||
|
|
||||||
//- Write sensitivity fields.
|
|
||||||
virtual void write(const word& baseName = word::null);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
} // End namespace incompressible
|
|
||||||
} // End namespace Foam
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// ************************************************************************* //
|
|
||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2019 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019-2020 OpenCFD Ltd.
|
Copyright (C) 2019-2020 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -48,18 +48,13 @@ Foam::sensitivity::sensitivity
|
|||||||
:
|
:
|
||||||
mesh_(mesh),
|
mesh_(mesh),
|
||||||
dict_(dict),
|
dict_(dict),
|
||||||
|
writeFieldSens_(dict.getOrDefault<bool>("writeFieldSens", false)),
|
||||||
fieldSensPtr_(nullptr)
|
fieldSensPtr_(nullptr)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
const Foam::dictionary& Foam::sensitivity::dict() const
|
|
||||||
{
|
|
||||||
return dict_;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool Foam::sensitivity::readDict(const dictionary& dict)
|
bool Foam::sensitivity::readDict(const dictionary& dict)
|
||||||
{
|
{
|
||||||
dict_ = dict;
|
dict_ = dict;
|
||||||
@ -68,15 +63,9 @@ bool Foam::sensitivity::readDict(const dictionary& dict)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Foam::sensitivity::computeDerivativesSize()
|
|
||||||
{
|
|
||||||
// Does nothing
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Foam::sensitivity::write(const word& baseName)
|
void Foam::sensitivity::write(const word& baseName)
|
||||||
{
|
{
|
||||||
if (fieldSensPtr_)
|
if (fieldSensPtr_ && writeFieldSens_)
|
||||||
{
|
{
|
||||||
fieldSensPtr_->write();
|
fieldSensPtr_->write();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,8 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2019 FOSS GP
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
Copyright (C) 2019 OpenCFD Ltd.
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
@ -57,6 +57,9 @@ SourceFiles
|
|||||||
namespace Foam
|
namespace Foam
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Forward declaration
|
||||||
|
class designVariables;
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------*\
|
/*---------------------------------------------------------------------------*\
|
||||||
Class sensitivity Declaration
|
Class sensitivity Declaration
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
@ -69,14 +72,13 @@ protected:
|
|||||||
|
|
||||||
const fvMesh& mesh_;
|
const fvMesh& mesh_;
|
||||||
dictionary dict_;
|
dictionary dict_;
|
||||||
|
bool writeFieldSens_;
|
||||||
|
|
||||||
// Field sensitivities. Topology optimisation
|
// Field sensitivities. Topology optimisation
|
||||||
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
autoPtr<volScalarField> fieldSensPtr_;
|
autoPtr<volScalarField> fieldSensPtr_;
|
||||||
|
|
||||||
|
|
||||||
// Protected Member Functions
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Private Member Functions
|
// Private Member Functions
|
||||||
@ -108,27 +110,40 @@ public:
|
|||||||
|
|
||||||
// Member Functions
|
// Member Functions
|
||||||
|
|
||||||
|
//- Return reference to mesh
|
||||||
|
inline const fvMesh& mesh() const
|
||||||
|
{
|
||||||
|
return mesh_;
|
||||||
|
}
|
||||||
|
|
||||||
//- Return the construction dictionary
|
//- Return the construction dictionary
|
||||||
const dictionary& dict() const;
|
inline const dictionary& dict() const
|
||||||
|
{
|
||||||
|
return
|
||||||
|
dict_.optionalSubDict(mesh_.name()).
|
||||||
|
optionalSubDict("sensitivities");
|
||||||
|
}
|
||||||
|
|
||||||
//- Read dictionary if changed
|
//- Read dictionary if changed
|
||||||
virtual bool readDict(const dictionary& dict);
|
virtual bool readDict(const dictionary& dict);
|
||||||
|
|
||||||
//- Compute design variables number. Does nothing in the base
|
//- Calculates and returns sensitivity field
|
||||||
// Used to get the correct design variables number when
|
virtual const scalarField& calculateSensitivities
|
||||||
// setSensitivityPatchIDs are not set in the constructor
|
(
|
||||||
virtual void computeDerivativesSize();
|
autoPtr<designVariables>& designVars
|
||||||
|
) = 0;
|
||||||
|
|
||||||
//- Calculates and returns sensitivity fields.
|
//- Get the fieldSensPtr
|
||||||
// Used with optimisation libraries
|
inline const autoPtr<volScalarField>& fieldSensPtr() const
|
||||||
virtual const scalarField& calculateSensitivities() = 0;
|
{
|
||||||
|
return fieldSensPtr_;
|
||||||
|
}
|
||||||
|
|
||||||
//- Write sensitivity fields.
|
//- Write sensitivity fields.
|
||||||
// If valid, copies boundaryFields to volFields and writes them.
|
// If valid, copies boundaryFields to volFields and writes them.
|
||||||
// Virtual to be reimplemented by control points-based methods
|
// Virtual to be reimplemented by control points-based methods
|
||||||
// (Bezier, RBF) which do not need to write fields
|
// (Bezier, RBF) which do not need to write fields
|
||||||
virtual void write(const word& baseName = word::null);
|
virtual void write(const word& baseName = word::null);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,281 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "designVariables.H"
|
||||||
|
#include "adjointSensitivity.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
defineTypeNameAndDebug(designVariables, 0);
|
||||||
|
defineRunTimeSelectionTable(designVariables, designVariables);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::designVariables::readBounds
|
||||||
|
(
|
||||||
|
autoPtr<scalar> lowerBoundPtr,
|
||||||
|
autoPtr<scalar> upperBoundPtr
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Read lower bounds for the design variables, if present
|
||||||
|
if (dict_.found("lowerBounds"))
|
||||||
|
{
|
||||||
|
scalarField lowerBounds(dict_.get<scalarField>("lowerBounds"));
|
||||||
|
if (lowerBounds.size() != getVars().size())
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "Inconsistent dimensions for lowerBounds ("
|
||||||
|
<< lowerBounds.size()
|
||||||
|
<< ") and design variables ("
|
||||||
|
<< getVars().size() << ")"
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
lowerBounds_.reset(new scalarField(lowerBounds));
|
||||||
|
}
|
||||||
|
else if (dict_.found("lowerBound"))
|
||||||
|
{
|
||||||
|
scalar lowerBound(dict_.get<scalar>("lowerBound"));
|
||||||
|
lowerBounds_.reset(new scalarField(getVars().size(), lowerBound));
|
||||||
|
}
|
||||||
|
else if (lowerBoundPtr.valid())
|
||||||
|
{
|
||||||
|
lowerBounds_.reset(new scalarField(getVars().size(), lowerBoundPtr()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Read upper bounds for the design variables, if present
|
||||||
|
if (dict_.found("upperBounds"))
|
||||||
|
{
|
||||||
|
scalarField upperBounds(dict_.get<scalarField>("upperBounds"));
|
||||||
|
if (upperBounds.size() != getVars().size())
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "Inconsistent dimensions for upperBounds ("
|
||||||
|
<< upperBounds.size()
|
||||||
|
<< ") and design variables ("
|
||||||
|
<< getVars().size() << ")"
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
upperBounds_.reset(new scalarField(upperBounds));
|
||||||
|
}
|
||||||
|
else if (dict_.found("upperBound"))
|
||||||
|
{
|
||||||
|
scalar upperBound(dict_.get<scalar>("upperBound"));
|
||||||
|
upperBounds_.reset(new scalarField(getVars().size(), upperBound));
|
||||||
|
}
|
||||||
|
else if (upperBoundPtr.valid())
|
||||||
|
{
|
||||||
|
upperBounds_.reset(new scalarField(getVars().size(), upperBoundPtr()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::designVariables::designVariables
|
||||||
|
(
|
||||||
|
fvMesh& mesh,
|
||||||
|
const dictionary& dict
|
||||||
|
)
|
||||||
|
:
|
||||||
|
scalarField(0),
|
||||||
|
mesh_(mesh),
|
||||||
|
dict_(dict),
|
||||||
|
activeDesignVariables_(0),
|
||||||
|
oldDesignVariables_(nullptr),
|
||||||
|
maxInitChange_(nullptr),
|
||||||
|
lowerBounds_(nullptr),
|
||||||
|
upperBounds_(nullptr)
|
||||||
|
{
|
||||||
|
// Read max initial change of design variables if present
|
||||||
|
if (dict.found("maxInitChange"))
|
||||||
|
{
|
||||||
|
maxInitChange_.reset(new scalar(dict_.get<scalar>("maxInitChange")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::designVariables::designVariables
|
||||||
|
(
|
||||||
|
fvMesh& mesh,
|
||||||
|
const dictionary& dict,
|
||||||
|
const label size
|
||||||
|
)
|
||||||
|
:
|
||||||
|
scalarField(size, Zero),
|
||||||
|
mesh_(mesh),
|
||||||
|
dict_(dict),
|
||||||
|
activeDesignVariables_(0),
|
||||||
|
oldDesignVariables_(nullptr),
|
||||||
|
maxInitChange_(nullptr),
|
||||||
|
lowerBounds_(nullptr),
|
||||||
|
upperBounds_(nullptr)
|
||||||
|
{
|
||||||
|
// Read max initial change of design variables if present
|
||||||
|
if (dict.found("maxInitChange"))
|
||||||
|
{
|
||||||
|
maxInitChange_.reset(new scalar(dict_.get<scalar>("maxInitChange")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::autoPtr<Foam::designVariables> Foam::designVariables::New
|
||||||
|
(
|
||||||
|
fvMesh& mesh,
|
||||||
|
const dictionary& dict
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!dict.found("type"))
|
||||||
|
{
|
||||||
|
return autoPtr<designVariables>(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
const word modelType(dict.get<word>("type"));
|
||||||
|
|
||||||
|
Info<< "designVariables type : " << modelType << endl;
|
||||||
|
|
||||||
|
auto cstrIter = designVariablesConstructorTablePtr_->cfind(modelType);
|
||||||
|
|
||||||
|
if (!cstrIter.found())
|
||||||
|
{
|
||||||
|
FatalErrorInLookup
|
||||||
|
(
|
||||||
|
"designVariables",
|
||||||
|
modelType,
|
||||||
|
*designVariablesConstructorTablePtr_
|
||||||
|
) << exit(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
return autoPtr<designVariables>(cstrIter()(mesh, dict));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
bool Foam::designVariables::readDict(const dictionary& dict)
|
||||||
|
{
|
||||||
|
dict_ = dict;
|
||||||
|
|
||||||
|
if (dict.found("maxInitChange"))
|
||||||
|
{
|
||||||
|
maxInitChange_.reset(new scalar(dict_.get<scalar>("maxInitChange")));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Foam::scalarField& Foam::designVariables::getVars() const
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::scalarField& Foam::designVariables::getVars()
|
||||||
|
{
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::designVariables::storeDesignVariables()
|
||||||
|
{
|
||||||
|
if (!oldDesignVariables_)
|
||||||
|
{
|
||||||
|
oldDesignVariables_.reset(new scalarField(getVars().size(), Zero));
|
||||||
|
}
|
||||||
|
|
||||||
|
oldDesignVariables_.ref() = getVars();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::designVariables::resetDesignVariables()
|
||||||
|
{
|
||||||
|
DebugInfo
|
||||||
|
<< "Reseting design variables" << endl;
|
||||||
|
getVars() = (oldDesignVariables_());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::designVariables::postProcessSens
|
||||||
|
(
|
||||||
|
scalarField& objectiveSens,
|
||||||
|
PtrList<scalarField>& constraintSens,
|
||||||
|
const wordList& adjointSolversNames,
|
||||||
|
bool isMaster
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Does nothing in base
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::designVariables::evolveNumber()
|
||||||
|
{
|
||||||
|
// Does nothing in base
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::designVariables::setInitialValues()
|
||||||
|
{
|
||||||
|
// Does nothing in base
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::designVariables::addFvOptions
|
||||||
|
(
|
||||||
|
const PtrList<primalSolver>& primalSolver,
|
||||||
|
const PtrList<adjointSolverManager>& adjointSolverManagers
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Does nothing in base
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tmp<Foam::scalarField> Foam::designVariables::constraintValues()
|
||||||
|
{
|
||||||
|
return tmp<scalarField>(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::PtrList<Foam::scalarField> Foam::designVariables::constraintDerivatives()
|
||||||
|
{
|
||||||
|
return PtrList<scalarField>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::designVariables::writeDesignVars()
|
||||||
|
{
|
||||||
|
// Does nothing in base
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,282 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::designVariables
|
||||||
|
|
||||||
|
Description
|
||||||
|
Abstract base class for defining design variables.
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
designVariables.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef designVariables_H
|
||||||
|
#define designVariables_H
|
||||||
|
|
||||||
|
#include "fvMesh.H"
|
||||||
|
#include "volFieldsFwd.H"
|
||||||
|
#include "volFields.H"
|
||||||
|
#include "dictionary.H"
|
||||||
|
#include "primalSolver.H"
|
||||||
|
#include "adjointSolverManager.H"
|
||||||
|
#include "adjointSensitivity.H"
|
||||||
|
#include "runTimeSelectionTables.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
class adjointSensitivity;
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class designVariables Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class designVariables
|
||||||
|
:
|
||||||
|
public scalarField
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// Protected data
|
||||||
|
|
||||||
|
fvMesh& mesh_;
|
||||||
|
dictionary dict_;
|
||||||
|
|
||||||
|
//- Which of the design variables will be updated
|
||||||
|
labelList activeDesignVariables_;
|
||||||
|
|
||||||
|
//- Copy of old design variables. Usefull when performing line-search
|
||||||
|
autoPtr<scalarField> oldDesignVariables_;
|
||||||
|
|
||||||
|
//- Maximum design variables' change in the first optimisation cycle
|
||||||
|
// Used when eta is not used in updateMethod
|
||||||
|
autoPtr<scalar> maxInitChange_;
|
||||||
|
|
||||||
|
//- Lower bounds of the design variables
|
||||||
|
autoPtr<scalarField> lowerBounds_;
|
||||||
|
|
||||||
|
//- Upper bounds of the design variables
|
||||||
|
autoPtr<scalarField> upperBounds_;
|
||||||
|
|
||||||
|
|
||||||
|
// Protected Member Functions
|
||||||
|
|
||||||
|
//- Read bounds for design variables, if present
|
||||||
|
void readBounds
|
||||||
|
(
|
||||||
|
autoPtr<scalar> lowerBoundPtr = nullptr,
|
||||||
|
autoPtr<scalar> upperBoundPtr = nullptr
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
//- Disallow default bitwise copy construct
|
||||||
|
designVariables(const designVariables&) = delete;
|
||||||
|
|
||||||
|
//- Disallow default bitwise assignment
|
||||||
|
void operator=(const designVariables&) = delete;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
TypeName("designVariables");
|
||||||
|
|
||||||
|
|
||||||
|
// Declare run-time constructor selection table
|
||||||
|
|
||||||
|
declareRunTimeNewSelectionTable
|
||||||
|
(
|
||||||
|
autoPtr,
|
||||||
|
designVariables,
|
||||||
|
designVariables,
|
||||||
|
(
|
||||||
|
fvMesh& mesh,
|
||||||
|
const dictionary& dict
|
||||||
|
),
|
||||||
|
(mesh, dict)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct from dictionary
|
||||||
|
designVariables
|
||||||
|
(
|
||||||
|
fvMesh& mesh,
|
||||||
|
const dictionary& dict
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Construct from dictionary and size
|
||||||
|
designVariables
|
||||||
|
(
|
||||||
|
fvMesh& mesh,
|
||||||
|
const dictionary& dict,
|
||||||
|
const label size
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Selectors
|
||||||
|
|
||||||
|
//- Return a reference to the selected design variables
|
||||||
|
static autoPtr<designVariables> New
|
||||||
|
(
|
||||||
|
fvMesh& mesh,
|
||||||
|
const dictionary& dict
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
//- Destructor
|
||||||
|
virtual ~designVariables() = default;
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
//- Read dictionary if changed
|
||||||
|
virtual bool readDict(const dictionary& dict);
|
||||||
|
|
||||||
|
//- Get the design variables
|
||||||
|
// Defaults to *this.
|
||||||
|
// Virtual for potential overriding from derived classes
|
||||||
|
virtual const scalarField& getVars() const;
|
||||||
|
|
||||||
|
//- Get the design variables
|
||||||
|
// Defaults to *this.
|
||||||
|
// Virtual for potential overriding from derived classes
|
||||||
|
virtual scalarField& getVars();
|
||||||
|
|
||||||
|
//- Update design variables based on a given correction
|
||||||
|
// Translates the scalarField of corrections to a meaningful
|
||||||
|
// update of the design variables
|
||||||
|
virtual void update(scalarField& correction) = 0;
|
||||||
|
|
||||||
|
//- Store design variables, as the starting point for line search
|
||||||
|
virtual void storeDesignVariables();
|
||||||
|
|
||||||
|
//- Reset to the starting point of line search
|
||||||
|
virtual void resetDesignVariables();
|
||||||
|
|
||||||
|
//- Compute eta if not set in the first step
|
||||||
|
virtual scalar computeEta(scalarField& correction) = 0;
|
||||||
|
|
||||||
|
//- Whether to use global sum when computing matrix-vector products
|
||||||
|
//- in update methods
|
||||||
|
// Depends on whether the design variables are common for all
|
||||||
|
// processors (e.g. volumetric B-Splines control points) or distributed
|
||||||
|
// across them (e.g. topology optimisation)
|
||||||
|
virtual bool globalSum() const = 0;
|
||||||
|
|
||||||
|
//- Return list of active design variables
|
||||||
|
inline const labelList& activeDesignVariables() const;
|
||||||
|
|
||||||
|
//- Check whether the max. initial change of the design variables has
|
||||||
|
//- been set
|
||||||
|
inline bool isMaxInitChangeSet() const;
|
||||||
|
|
||||||
|
//- Set maxInitChange
|
||||||
|
inline void setMaxInitChange(const scalar maxInitChange);
|
||||||
|
|
||||||
|
//- Trigger the recomputation of eta by updateMethod
|
||||||
|
inline virtual bool resetEta() const;
|
||||||
|
|
||||||
|
//- Get min bounds for the design variables
|
||||||
|
inline const autoPtr<scalarField>& lowerBounds() const;
|
||||||
|
|
||||||
|
//- Get max bounds for the design variables
|
||||||
|
inline const autoPtr<scalarField>& upperBounds() const;
|
||||||
|
|
||||||
|
//- Get min bounds for the design variables
|
||||||
|
inline scalarField& lowerBoundsRef();
|
||||||
|
|
||||||
|
//- Get max bounds for the design variables
|
||||||
|
inline scalarField& upperBoundsRef();
|
||||||
|
|
||||||
|
//- Post process sensitivities if needed
|
||||||
|
virtual void postProcessSens
|
||||||
|
(
|
||||||
|
scalarField& objectiveSens,
|
||||||
|
PtrList<scalarField>& constraintSens,
|
||||||
|
const wordList& adjointSolversNames,
|
||||||
|
bool isMaster
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Assemble sensitivity derivatives, by combining the part related
|
||||||
|
//- to the primal and adjoint solution with the part related to the
|
||||||
|
//- design variables
|
||||||
|
virtual tmp<scalarField> assembleSensitivities
|
||||||
|
(
|
||||||
|
adjointSensitivity& sens
|
||||||
|
) = 0;
|
||||||
|
|
||||||
|
//- For design variables with a dynamic character (i.e. changing
|
||||||
|
//- number), perform the evolution
|
||||||
|
virtual void evolveNumber();
|
||||||
|
|
||||||
|
//- Set initial values of the design variables
|
||||||
|
// For design variables sets that need to be initialised after the
|
||||||
|
// construction of the primal fields.
|
||||||
|
// Does nothing in base
|
||||||
|
virtual void setInitialValues();
|
||||||
|
|
||||||
|
//- Add fvOptions depending on the design variables
|
||||||
|
virtual void addFvOptions
|
||||||
|
(
|
||||||
|
const PtrList<primalSolver>& primalSolver,
|
||||||
|
const PtrList<adjointSolverManager>& adjointSolverManagers
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Design variables might add constraints related to themselves
|
||||||
|
//- (e.g. linear combinations of the design variables)
|
||||||
|
//- Return the values and gradients of these constraints
|
||||||
|
virtual tmp<scalarField> constraintValues();
|
||||||
|
virtual PtrList<scalarField> constraintDerivatives();
|
||||||
|
|
||||||
|
//- Write useful quantities to files
|
||||||
|
virtual void writeDesignVars();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#include "designVariablesI.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -5,9 +5,8 @@
|
|||||||
\\ / A nd | www.openfoam.com
|
\\ / A nd | www.openfoam.com
|
||||||
\\/ M anipulation |
|
\\/ M anipulation |
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Copyright (C) 2007-2019 PCOpt/NTUA
|
Copyright (C) 2021 PCOpt/NTUA
|
||||||
Copyright (C) 2013-2019 FOSS GP
|
Copyright (C) 2021 FOSS GP
|
||||||
Copyright (C) 2019 OpenCFD Ltd.
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
License
|
License
|
||||||
This file is part of OpenFOAM.
|
This file is part of OpenFOAM.
|
||||||
@ -27,48 +26,56 @@ License
|
|||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "optMeshMovementNULL.H"
|
|
||||||
#include "addToRunTimeSelectionTable.H"
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
namespace Foam
|
|
||||||
{
|
|
||||||
defineTypeNameAndDebug(optMeshMovementNULL, 0);
|
|
||||||
addToRunTimeSelectionTable
|
|
||||||
(
|
|
||||||
optMeshMovement,
|
|
||||||
optMeshMovementNULL,
|
|
||||||
dictionary
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
|
||||||
|
|
||||||
Foam::optMeshMovementNULL::optMeshMovementNULL
|
|
||||||
(
|
|
||||||
fvMesh& mesh,
|
|
||||||
const dictionary& dict,
|
|
||||||
const labelList& patchIDs
|
|
||||||
)
|
|
||||||
:
|
|
||||||
optMeshMovement(mesh, dict, patchIDs)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||||
|
|
||||||
void Foam::optMeshMovementNULL::moveMesh()
|
inline const Foam::labelList&
|
||||||
|
Foam::designVariables::activeDesignVariables() const
|
||||||
{
|
{
|
||||||
// Do nothing
|
return activeDesignVariables_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Foam::scalar
|
bool Foam::designVariables::isMaxInitChangeSet() const
|
||||||
Foam::optMeshMovementNULL::computeEta(const scalarField& correction)
|
|
||||||
{
|
{
|
||||||
return scalar(0);
|
return maxInitChange_.valid();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::designVariables::setMaxInitChange(const scalar maxInitChange)
|
||||||
|
{
|
||||||
|
maxInitChange_.reset(new scalar(maxInitChange));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::designVariables::resetEta() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Foam::autoPtr<Foam::scalarField>&
|
||||||
|
Foam::designVariables::lowerBounds() const
|
||||||
|
{
|
||||||
|
return lowerBounds_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Foam::autoPtr<Foam::scalarField>&
|
||||||
|
Foam::designVariables::upperBounds() const
|
||||||
|
{
|
||||||
|
return upperBounds_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::scalarField& Foam::designVariables::lowerBoundsRef()
|
||||||
|
{
|
||||||
|
return lowerBounds_.ref();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::scalarField& Foam::designVariables::upperBoundsRef()
|
||||||
|
{
|
||||||
|
return upperBounds_.ref();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,289 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "BezierDesignVariables.H"
|
||||||
|
#include "IOmanip.H"
|
||||||
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
defineTypeNameAndDebug(BezierDesignVariables, 0);
|
||||||
|
addToRunTimeSelectionTable
|
||||||
|
(
|
||||||
|
shapeDesignVariables,
|
||||||
|
BezierDesignVariables,
|
||||||
|
dictionary
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::BezierDesignVariables::readBounds
|
||||||
|
(
|
||||||
|
autoPtr<scalar> lowerBoundPtr,
|
||||||
|
autoPtr<scalar> upperBoundPtr
|
||||||
|
)
|
||||||
|
{
|
||||||
|
designVariables::readBounds(lowerBoundPtr, upperBoundPtr);
|
||||||
|
|
||||||
|
if (dict_.found("lowerCPBounds"))
|
||||||
|
{
|
||||||
|
vector lowerCPBounds(dict_.get<vector>("lowerCPBounds"));
|
||||||
|
lowerBounds_.reset(new scalarField(getVars().size(), Zero));
|
||||||
|
setBounds(lowerBounds_, lowerCPBounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dict_.found("upperCPBounds"))
|
||||||
|
{
|
||||||
|
vector upperCPBounds(dict_.get<vector>("upperCPBounds"));
|
||||||
|
upperBounds_.reset(new scalarField(getVars().size(), Zero));
|
||||||
|
setBounds(upperBounds_, upperCPBounds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::BezierDesignVariables::setBounds
|
||||||
|
(
|
||||||
|
autoPtr<scalarField>& bounds,
|
||||||
|
const vector& cpBounds
|
||||||
|
)
|
||||||
|
{
|
||||||
|
bounds.reset(new scalarField(getVars().size(), Zero));
|
||||||
|
const label nCPs(bezier_.nBezier());
|
||||||
|
for (label iCP = 0; iCP < nCPs; ++iCP)
|
||||||
|
{
|
||||||
|
bounds()[iCP] = cpBounds.x();
|
||||||
|
bounds()[nCPs + iCP] = cpBounds.y();
|
||||||
|
bounds()[2*nCPs + iCP] = cpBounds.z();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tmp<Foam::vectorField>
|
||||||
|
Foam::BezierDesignVariables::computeBoundaryDisplacement
|
||||||
|
(
|
||||||
|
const scalarField& correction
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Reset boundary movement field
|
||||||
|
dx_.primitiveFieldRef() = Zero;
|
||||||
|
|
||||||
|
// Compute boundary movement using the derivatives of grid nodes
|
||||||
|
// wrt to the Bezier control points and the correction
|
||||||
|
const label nCPs(bezier_.nBezier());
|
||||||
|
auto tcpMovement(tmp<vectorField>::New(nCPs, Zero));
|
||||||
|
vectorField& cpMovement = tcpMovement.ref();
|
||||||
|
const boolListList& confineMovement = bezier_.confineMovement();
|
||||||
|
|
||||||
|
forAll(cpMovement, cpI)
|
||||||
|
{
|
||||||
|
if (!confineMovement[0][cpI])
|
||||||
|
{
|
||||||
|
cpMovement[cpI].x() = correction[cpI];
|
||||||
|
}
|
||||||
|
if (!confineMovement[1][cpI])
|
||||||
|
{
|
||||||
|
cpMovement[cpI].y() = correction[nCPs + cpI];
|
||||||
|
}
|
||||||
|
if (!confineMovement[2][cpI])
|
||||||
|
{
|
||||||
|
cpMovement[cpI].z() = correction[2*nCPs + cpI];
|
||||||
|
}
|
||||||
|
|
||||||
|
dx_ += (bezier_.dxidXj()[cpI] & cpMovement[cpI]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return tcpMovement;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::BezierDesignVariables::decomposeVarID
|
||||||
|
(
|
||||||
|
label& cpI,
|
||||||
|
label& dir,
|
||||||
|
const label varID
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
const label nBezier = bezier_.nBezier();
|
||||||
|
cpI = varID%nBezier;
|
||||||
|
dir = varID/nBezier;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::BezierDesignVariables::BezierDesignVariables
|
||||||
|
(
|
||||||
|
fvMesh& mesh,
|
||||||
|
const dictionary& dict
|
||||||
|
)
|
||||||
|
:
|
||||||
|
shapeDesignVariables(mesh, dict),
|
||||||
|
bezier_
|
||||||
|
(
|
||||||
|
mesh,
|
||||||
|
IOdictionary
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"optimisationDict",
|
||||||
|
mesh_.time().globalPath()/"system",
|
||||||
|
mesh,
|
||||||
|
IOobject::MUST_READ,
|
||||||
|
IOobject::NO_WRITE,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
dx_
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"dx",
|
||||||
|
mesh_.time().timeName(),
|
||||||
|
mesh_,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE
|
||||||
|
),
|
||||||
|
pointMesh::New(mesh_),
|
||||||
|
dimensionedVector(dimless, Zero)
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Set the size of the design variables field
|
||||||
|
scalarField::setSize(3*bezier_.nBezier(), Zero);
|
||||||
|
|
||||||
|
// Set the active design variables
|
||||||
|
activeDesignVariables_ = bezier_.getActiveDesignVariables();
|
||||||
|
|
||||||
|
// Read bounds
|
||||||
|
readBounds();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
void Foam::BezierDesignVariables::update(scalarField& correction)
|
||||||
|
{
|
||||||
|
// Translate the correction field to control point movements
|
||||||
|
computeBoundaryDisplacement(correction);
|
||||||
|
|
||||||
|
// Transfer movement to the displacementMethod
|
||||||
|
displMethodPtr_->setMotionField(dx_);
|
||||||
|
|
||||||
|
// Update the design variables
|
||||||
|
scalarField::operator+=(correction);
|
||||||
|
|
||||||
|
// Do the actual mesh movement
|
||||||
|
moveMesh();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::scalar Foam::BezierDesignVariables::computeEta(scalarField& correction)
|
||||||
|
{
|
||||||
|
// Transfer the correction field to control point movement
|
||||||
|
computeBoundaryDisplacement(correction);
|
||||||
|
|
||||||
|
const scalar maxDisplacement(max(mag(dx_)).value());
|
||||||
|
|
||||||
|
Info<< "maxAllowedDisplacement/maxDisplacement at the boundary\t"
|
||||||
|
<< maxInitChange_() << "/" << maxDisplacement << endl;
|
||||||
|
|
||||||
|
const scalar eta = maxInitChange_()/maxDisplacement;
|
||||||
|
Info<< "Setting eta value to " << eta << endl;
|
||||||
|
correction *= eta;
|
||||||
|
|
||||||
|
return eta;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Foam::BezierDesignVariables::globalSum() const
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tmp<Foam::vectorField> Foam::BezierDesignVariables::dxdbFace
|
||||||
|
(
|
||||||
|
const label patchI,
|
||||||
|
const label varID
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
label cpI(-1), dir(-1);
|
||||||
|
decomposeVarID(cpI, dir, varID);
|
||||||
|
return bezier_.dxdbFace(patchI, cpI, dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tmp<Foam::vectorField> Foam::BezierDesignVariables::dndb
|
||||||
|
(
|
||||||
|
const label patchI,
|
||||||
|
const label varID
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
label cpI(-1), dir(-1);
|
||||||
|
decomposeVarID(cpI, dir, varID);
|
||||||
|
return bezier_.dndbBasedSensitivities(patchI, cpI, dir, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tmp<Foam::vectorField> Foam::BezierDesignVariables::dSdb
|
||||||
|
(
|
||||||
|
const label patchI,
|
||||||
|
const label varID
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
label cpI(-1), dir(-1);
|
||||||
|
decomposeVarID(cpI, dir, varID);
|
||||||
|
return bezier_.dndbBasedSensitivities(patchI, cpI, dir, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tmp<Foam::volVectorField>
|
||||||
|
Foam::BezierDesignVariables::dCdb(const label varID) const
|
||||||
|
{
|
||||||
|
label cpI(-1), dir(-1);
|
||||||
|
decomposeVarID(cpI, dir, varID);
|
||||||
|
label patchI(-1);
|
||||||
|
// There is no mechanism in place to identify the parametertised patch.
|
||||||
|
// Look over all patches and grab one with a non-zero dxdb
|
||||||
|
for (const label pI : parametertisedPatches_)
|
||||||
|
{
|
||||||
|
tmp<vectorField> dxdbFace = bezier_.dxdbFace(pI, cpI, dir);
|
||||||
|
if (gSum(mag(dxdbFace)) > SMALL)
|
||||||
|
{
|
||||||
|
patchI = pI;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return solveMeshMovementEqn(patchI, varID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,172 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::BezierDesignVariables
|
||||||
|
|
||||||
|
Description
|
||||||
|
Bezier design variables for shape optimisation
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
BezierDesignVariables.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef BezierDesignVariables_H
|
||||||
|
#define BezierDesignVariables_H
|
||||||
|
|
||||||
|
#include "shapeDesignVariables.H"
|
||||||
|
#include "Bezier.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class BezierDesignVariables Decleration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class BezierDesignVariables
|
||||||
|
:
|
||||||
|
public shapeDesignVariables
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// Protected Data Members
|
||||||
|
|
||||||
|
//- The Bezier control points and auxiliary functions
|
||||||
|
Bezier bezier_;
|
||||||
|
|
||||||
|
//- Boundary movement due to the change in Bezier control points
|
||||||
|
pointVectorField dx_;
|
||||||
|
|
||||||
|
|
||||||
|
// Protected Member Functions
|
||||||
|
|
||||||
|
//- Read bounds for design variables, if present
|
||||||
|
void readBounds
|
||||||
|
(
|
||||||
|
autoPtr<scalar> lowerBoundPtr = nullptr,
|
||||||
|
autoPtr<scalar> upperBoundPtr = nullptr
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Set uniform bounds for all control points
|
||||||
|
void setBounds(autoPtr<scalarField>& bounds, const vector& cpBounds);
|
||||||
|
|
||||||
|
//- Transform the correction of design variables to control points'
|
||||||
|
//- movement
|
||||||
|
tmp<vectorField> computeBoundaryDisplacement
|
||||||
|
(
|
||||||
|
const scalarField& correction
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Decompose varID to cpID and direction
|
||||||
|
void decomposeVarID(label& cpI, label& dir, const label varID) const;
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
//- No copy construct
|
||||||
|
BezierDesignVariables(const BezierDesignVariables&) = delete;
|
||||||
|
|
||||||
|
//- No copy assignment
|
||||||
|
void operator=(const BezierDesignVariables&) = delete;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
TypeName("Bezier");
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct from components
|
||||||
|
BezierDesignVariables
|
||||||
|
(
|
||||||
|
fvMesh& mesh,
|
||||||
|
const dictionary& dict
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
//- Destructor
|
||||||
|
virtual ~BezierDesignVariables() = default;
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
//- Update design variables based on a given correction
|
||||||
|
virtual void update(scalarField& correction);
|
||||||
|
|
||||||
|
//- Compute eta if not set in the first step
|
||||||
|
virtual scalar computeEta(scalarField& correction);
|
||||||
|
|
||||||
|
//- Whether to use global sum when computing matrix-vector products
|
||||||
|
// in update methods
|
||||||
|
virtual bool globalSum() const;
|
||||||
|
|
||||||
|
|
||||||
|
// Fields related to sensitivity computations
|
||||||
|
|
||||||
|
//- Get dxdb for given design variable and patch
|
||||||
|
virtual tmp<vectorField> dxdbFace
|
||||||
|
(
|
||||||
|
const label patchI,
|
||||||
|
const label varID
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Get dndb for given design variable and patch
|
||||||
|
virtual tmp<vectorField> dndb
|
||||||
|
(
|
||||||
|
const label patchI,
|
||||||
|
const label varID
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Get dSdb for given design variable and patch
|
||||||
|
virtual tmp<vectorField> dSdb
|
||||||
|
(
|
||||||
|
const label patchI,
|
||||||
|
const label varID
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Get dCdb for given design variable.
|
||||||
|
// Used for FI-based sensitivities
|
||||||
|
virtual tmp<volVectorField> dCdb(const label varID) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,510 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "shapeDesignVariables.H"
|
||||||
|
#include "cellQuality.H"
|
||||||
|
#include "createZeroField.H"
|
||||||
|
#include "addToRunTimeSelectionTable.H"
|
||||||
|
#include "volFieldsFwd.H"
|
||||||
|
#include "adjointEikonalSolver.H"
|
||||||
|
#include "IOmanip.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
defineTypeNameAndDebug(shapeDesignVariables, 0);
|
||||||
|
defineRunTimeSelectionTable(shapeDesignVariables, dictionary);
|
||||||
|
addToRunTimeSelectionTable
|
||||||
|
(
|
||||||
|
designVariables,
|
||||||
|
shapeDesignVariables,
|
||||||
|
designVariables
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::label Foam::shapeDesignVariables::sensSize() const
|
||||||
|
{
|
||||||
|
return size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Foam::labelList& Foam::shapeDesignVariables::activeSensitivities() const
|
||||||
|
{
|
||||||
|
return activeDesignVariables_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tmp<Foam::volVectorField>
|
||||||
|
Foam::shapeDesignVariables::solveMeshMovementEqn
|
||||||
|
(
|
||||||
|
const label patchI,
|
||||||
|
const label varID
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
const dictionary dxdbDict = dict_.subOrEmptyDict("dxdbSolver");
|
||||||
|
const label iters = dxdbDict.getOrDefault<label>("iters", 1000);
|
||||||
|
const scalar tolerance =
|
||||||
|
dxdbDict.getOrDefault<scalar>("tolerance", 1.e-07);
|
||||||
|
tmp<volVectorField> tm
|
||||||
|
(
|
||||||
|
tmp<volVectorField>::New
|
||||||
|
(
|
||||||
|
variablesSet::autoCreateMeshMovementField
|
||||||
|
(
|
||||||
|
mesh_,
|
||||||
|
"m",
|
||||||
|
dimensionSet(dimLength)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
volVectorField& m = tm.ref();
|
||||||
|
|
||||||
|
// Solve for dxdb
|
||||||
|
//~~~~~~~~~~~~~~~~
|
||||||
|
m.boundaryFieldRef()[patchI] == dxdbFace(patchI, varID);
|
||||||
|
|
||||||
|
// Iterate the direct differentiation of the grid displacement equation
|
||||||
|
for (label iter = 0; iter < iters; ++iter)
|
||||||
|
{
|
||||||
|
Info<< "Mesh Movement Propagation for varID" << varID
|
||||||
|
<< ", Iteration : "<< iter << endl;
|
||||||
|
|
||||||
|
fvVectorMatrix mEqn
|
||||||
|
(
|
||||||
|
fvm::laplacian(m)
|
||||||
|
);
|
||||||
|
|
||||||
|
scalar residual = mag(mEqn.solve().initialResidual());
|
||||||
|
|
||||||
|
DebugInfo
|
||||||
|
<< "Max dxdb " << gMax(mag(m)()) << endl;
|
||||||
|
|
||||||
|
mesh_.time().printExecutionTime(Info);
|
||||||
|
|
||||||
|
// Check convergence
|
||||||
|
if (residual < tolerance)
|
||||||
|
{
|
||||||
|
Info<< "\n***Reached dxdb convergence limit, iteration " << iter
|
||||||
|
<< "***\n\n";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tm;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::shapeDesignVariables::allocateSensFields()
|
||||||
|
{
|
||||||
|
if (dxdbVolSens_.empty())
|
||||||
|
{
|
||||||
|
dxdbVolSens_.setSize(sensSize(), Zero);
|
||||||
|
dxdbSurfSens_.setSize(sensSize(), Zero);
|
||||||
|
dSdbSens_.setSize(sensSize(), Zero);
|
||||||
|
dndbSens_.setSize(sensSize(), Zero);
|
||||||
|
dxdbDirectSens_.setSize(sensSize(), Zero);
|
||||||
|
dVdbSens_.setSize(sensSize(), Zero);
|
||||||
|
distanceSens_.setSize(sensSize(), Zero);
|
||||||
|
optionsSens_.setSize(sensSize(), Zero);
|
||||||
|
bcSens_.setSize(sensSize(), Zero);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::shapeDesignVariables::zeroSensFields()
|
||||||
|
{
|
||||||
|
dxdbVolSens_ = Zero;
|
||||||
|
dxdbSurfSens_ = Zero;
|
||||||
|
dSdbSens_ = Zero;
|
||||||
|
dndbSens_ = Zero;
|
||||||
|
dxdbDirectSens_ = Zero;
|
||||||
|
dVdbSens_ = Zero;
|
||||||
|
distanceSens_ = Zero;
|
||||||
|
optionsSens_ = Zero;
|
||||||
|
bcSens_ = Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::shapeDesignVariables::shapeDesignVariables
|
||||||
|
(
|
||||||
|
fvMesh& mesh,
|
||||||
|
const dictionary& dict
|
||||||
|
)
|
||||||
|
:
|
||||||
|
designVariables(mesh, dict),
|
||||||
|
parametertisedPatches_
|
||||||
|
(
|
||||||
|
mesh_.boundaryMesh().patchSet(dict.get<wordRes>("patches"))
|
||||||
|
),
|
||||||
|
displMethodPtr_
|
||||||
|
(
|
||||||
|
displacementMethod::New(mesh_, parametertisedPatches_.toc())
|
||||||
|
),
|
||||||
|
pointsInit_(nullptr),
|
||||||
|
writeEachMesh_(dict.getOrDefault<bool>("writeEachMesh", true)),
|
||||||
|
dxdbVolSens_(),
|
||||||
|
dxdbSurfSens_(),
|
||||||
|
dSdbSens_(),
|
||||||
|
dndbSens_(),
|
||||||
|
dxdbDirectSens_(),
|
||||||
|
dVdbSens_(),
|
||||||
|
distanceSens_(),
|
||||||
|
optionsSens_(),
|
||||||
|
bcSens_(),
|
||||||
|
derivativesFolder_
|
||||||
|
(
|
||||||
|
word("optimisation")/word("derivatives")
|
||||||
|
/word(mesh.name() == polyMesh::defaultRegion ? word() : mesh.name())
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!parametertisedPatches_.size())
|
||||||
|
{
|
||||||
|
FatalErrorInFunction
|
||||||
|
<< "None of the provided parameterised patches is valid"
|
||||||
|
<< endl
|
||||||
|
<< exit(FatalError);
|
||||||
|
}
|
||||||
|
mkDir(derivativesFolder_);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
Foam::autoPtr<Foam::shapeDesignVariables> Foam::shapeDesignVariables::New
|
||||||
|
(
|
||||||
|
fvMesh& mesh,
|
||||||
|
const dictionary& dict
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const word modelType(dict.get<word>("shapeType"));
|
||||||
|
|
||||||
|
Info<< "shapeDesignVariables type : " << modelType << endl;
|
||||||
|
|
||||||
|
auto cstrIter = dictionaryConstructorTablePtr_->cfind(modelType);
|
||||||
|
|
||||||
|
if (!cstrIter.found())
|
||||||
|
{
|
||||||
|
FatalErrorInLookup
|
||||||
|
(
|
||||||
|
"shapeType",
|
||||||
|
modelType,
|
||||||
|
*dictionaryConstructorTablePtr_
|
||||||
|
) << exit(FatalError);
|
||||||
|
}
|
||||||
|
|
||||||
|
return autoPtr<shapeDesignVariables>(cstrIter()(mesh, dict));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
bool Foam::shapeDesignVariables::readDict(const dictionary& dict)
|
||||||
|
{
|
||||||
|
if (designVariables::readDict(dict))
|
||||||
|
{
|
||||||
|
parametertisedPatches_ =
|
||||||
|
mesh_.boundaryMesh().patchSet(dict.get<wordRes>("patches"));
|
||||||
|
displMethodPtr_->setPatchIDs(parametertisedPatches_.toc());
|
||||||
|
|
||||||
|
writeEachMesh_ =
|
||||||
|
dict.getOrDefault<bool>("writeEachMesh", true);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::shapeDesignVariables::storeDesignVariables()
|
||||||
|
{
|
||||||
|
designVariables::storeDesignVariables();
|
||||||
|
|
||||||
|
if (!pointsInit_)
|
||||||
|
{
|
||||||
|
pointsInit_.reset(new pointField(mesh_.nPoints(), Zero));
|
||||||
|
}
|
||||||
|
pointsInit_() = mesh_.points();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::shapeDesignVariables::resetDesignVariables()
|
||||||
|
{
|
||||||
|
designVariables::resetDesignVariables();
|
||||||
|
mesh_.movePoints(pointsInit_());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::shapeDesignVariables::moveMesh()
|
||||||
|
{
|
||||||
|
// Move mesh
|
||||||
|
displMethodPtr_->update();
|
||||||
|
|
||||||
|
if (writeEachMesh_)
|
||||||
|
{
|
||||||
|
Info<< " Writing new mesh points for mesh region "
|
||||||
|
<< mesh_.name() << endl;
|
||||||
|
pointIOField points
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"points",
|
||||||
|
mesh_.pointsInstance(),
|
||||||
|
mesh_.meshSubDir,
|
||||||
|
mesh_,
|
||||||
|
IOobject::NO_READ,
|
||||||
|
IOobject::NO_WRITE,
|
||||||
|
false
|
||||||
|
),
|
||||||
|
mesh_.points()
|
||||||
|
);
|
||||||
|
points.write();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check mesh quality
|
||||||
|
mesh_.checkMesh(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tmp<Foam::scalarField> Foam::shapeDesignVariables::assembleSensitivities
|
||||||
|
(
|
||||||
|
adjointSensitivity& adjointSens
|
||||||
|
)
|
||||||
|
{
|
||||||
|
// Return field
|
||||||
|
tmp<scalarField> tsens(tmp<scalarField>::New(sensSize(), Zero));
|
||||||
|
scalarField& sens = tsens.ref();
|
||||||
|
|
||||||
|
// Reset sensitivity components to zero
|
||||||
|
allocateSensFields();
|
||||||
|
zeroSensFields();
|
||||||
|
|
||||||
|
// Grab multipliers from the adjoint sensitivities
|
||||||
|
const autoPtr<volTensorField>& gradDxDbMult = adjointSens.gradDxDbMult();
|
||||||
|
const autoPtr<scalarField>& divDxDbMult = adjointSens.divDxDbMult();
|
||||||
|
const autoPtr<boundaryVectorField>& dxdbMult = adjointSens.dxdbMult();
|
||||||
|
const autoPtr<boundaryVectorField>& dSdbMult = adjointSens.dSfdbMult();
|
||||||
|
const autoPtr<boundaryVectorField>& dndbMult = adjointSens.dnfdbMult();
|
||||||
|
const autoPtr<boundaryVectorField>& dxdbDirectMult =
|
||||||
|
adjointSens.dxdbDirectMult();
|
||||||
|
const autoPtr<boundaryVectorField>& bcDxDbmult = adjointSens.bcDxDbMult();
|
||||||
|
const autoPtr<vectorField>& optionsDxDbMult = adjointSens.optionsDxDbMult();
|
||||||
|
const volScalarField::Internal& V = mesh_.V();
|
||||||
|
autoPtr<adjointEikonalSolver>& eikonalSolver =
|
||||||
|
adjointSens.getAdjointEikonalSolver();
|
||||||
|
|
||||||
|
autoPtr<volTensorField> distanceSens(nullptr);
|
||||||
|
if (adjointSens.includeDistance())
|
||||||
|
{
|
||||||
|
distanceSens.reset
|
||||||
|
(
|
||||||
|
new volTensorField(eikonalSolver->getFISensitivityTerm())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loop over active design variables only
|
||||||
|
for (const label varI : activeSensitivities())
|
||||||
|
{
|
||||||
|
// FI approach, integrate terms including variations of the grid
|
||||||
|
// sensitivities
|
||||||
|
if (adjointSens.computeDxDbInternalField())
|
||||||
|
{
|
||||||
|
// Parameterization info
|
||||||
|
tmp<volVectorField> tvolDxDbI = dCdb(varI);
|
||||||
|
const volVectorField& volDxDbI = tvolDxDbI();
|
||||||
|
tmp<volTensorField> gradDxDb = fvc::grad(volDxDbI);
|
||||||
|
|
||||||
|
// Contributions from the adjoint-related part
|
||||||
|
dxdbVolSens_[varI] = gSum((gradDxDbMult() && gradDxDb())*V);
|
||||||
|
|
||||||
|
// Contributions from the distance related part
|
||||||
|
if (adjointSens.includeDistance())
|
||||||
|
{
|
||||||
|
distanceSens_[varI] = gSum((distanceSens() && gradDxDb)*V);
|
||||||
|
}
|
||||||
|
// Contributions from the multiplier of divDxDb
|
||||||
|
if (divDxDbMult)
|
||||||
|
{
|
||||||
|
dVdbSens_[varI] +=
|
||||||
|
gSum(divDxDbMult()*fvc::div(volDxDbI)().primitiveField()*V);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contributions from fvOptions
|
||||||
|
optionsSens_[varI] +=
|
||||||
|
gSum((optionsDxDbMult() & volDxDbI.primitiveField())*V);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Contribution from boundary terms
|
||||||
|
// Most of them (with the expection of dxdbMult) exist in both the
|
||||||
|
// FI and E-SI approaches
|
||||||
|
for (const label patchI : parametertisedPatches_)
|
||||||
|
{
|
||||||
|
if (dSdbMult)
|
||||||
|
{
|
||||||
|
tmp<vectorField> pdSdb = dSdb(patchI, varI);
|
||||||
|
dSdbSens_[varI] += gSum(dSdbMult()[patchI] & pdSdb);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dndbMult)
|
||||||
|
{
|
||||||
|
tmp<vectorField> pdndb = dndb(patchI, varI);
|
||||||
|
dndbSens_[varI] += gSum((dndbMult()[patchI] & pdndb));
|
||||||
|
}
|
||||||
|
|
||||||
|
tmp<vectorField> pdxdb = dxdbFace(patchI, varI);
|
||||||
|
// Main contribution in the E-SI approach
|
||||||
|
if (dxdbMult)
|
||||||
|
{
|
||||||
|
dxdbSurfSens_[varI] += gSum(dxdbMult()[patchI] & pdxdb());
|
||||||
|
}
|
||||||
|
if (dxdbDirectMult)
|
||||||
|
{
|
||||||
|
dxdbDirectSens_[varI] +=
|
||||||
|
gSum((dxdbDirectMult()[patchI] & pdxdb()));
|
||||||
|
}
|
||||||
|
if (bcDxDbmult)
|
||||||
|
{
|
||||||
|
bcSens_[varI] += gSum((bcDxDbmult()[patchI] & pdxdb()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sens =
|
||||||
|
dxdbVolSens_ + dxdbSurfSens_ + dSdbSens_ + dndbSens_ + dxdbDirectSens_
|
||||||
|
+ dVdbSens_ + distanceSens_ + optionsSens_ + bcSens_;
|
||||||
|
|
||||||
|
writeSensitivities(sens, adjointSens);
|
||||||
|
|
||||||
|
return tsens;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Foam::shapeDesignVariables::writeSensitivities
|
||||||
|
(
|
||||||
|
const scalarField& sens,
|
||||||
|
const adjointSensitivity& adjointSens
|
||||||
|
)
|
||||||
|
{
|
||||||
|
OFstream derivFile
|
||||||
|
(
|
||||||
|
derivativesFolder_/
|
||||||
|
type() + adjointSens.getAdjointSolver().solverName()
|
||||||
|
+ adjointSens.getSuffix() + mesh_.time().timeName()
|
||||||
|
);
|
||||||
|
unsigned int widthDV = max(int(name(dxdbVolSens_.size()).size()), int(6));
|
||||||
|
unsigned int width = IOstream::defaultPrecision() + 7;
|
||||||
|
derivFile
|
||||||
|
<< setw(widthDV) << "#varID" << " "
|
||||||
|
<< setw(width) << "total"<< " "
|
||||||
|
<< setw(width) << "dxdbVol" << " "
|
||||||
|
<< setw(width) << "dxdbSurf" << " "
|
||||||
|
<< setw(width) << "dSdb" << " "
|
||||||
|
<< setw(width) << "dndb" << " "
|
||||||
|
<< setw(width) << "dxdbDirect" << " "
|
||||||
|
<< setw(width) << "dVdb" << " "
|
||||||
|
<< setw(width) << "distance" << " "
|
||||||
|
<< setw(width) << "options" << " "
|
||||||
|
<< setw(width) << "dvdb" << endl;
|
||||||
|
|
||||||
|
for (const label varI : activeSensitivities())
|
||||||
|
{
|
||||||
|
derivFile
|
||||||
|
<< setw(widthDV) << varI << " "
|
||||||
|
<< setw(width) << sens[varI] << " "
|
||||||
|
<< setw(width) << dxdbVolSens_[varI] << " "
|
||||||
|
<< setw(width) << dxdbSurfSens_[varI] << " "
|
||||||
|
<< setw(width) << dSdbSens_[varI] << " "
|
||||||
|
<< setw(width) << dndbSens_[varI] << " "
|
||||||
|
<< setw(width) << dxdbDirectSens_[varI] << " "
|
||||||
|
<< setw(width) << dVdbSens_[varI] << " "
|
||||||
|
<< setw(width) << distanceSens_[varI] << " "
|
||||||
|
<< setw(width) << optionsSens_[varI] << " "
|
||||||
|
<< setw(width) << bcSens_[varI] << " "
|
||||||
|
<< endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tmp<Foam::vectorField> Foam::shapeDesignVariables::dxdbVol
|
||||||
|
(
|
||||||
|
const label varID
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
// Deliberately returning a zero-sized field
|
||||||
|
return tmp<vectorField>::New(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tmp<Foam::vectorField> Foam::shapeDesignVariables::dxdbFace
|
||||||
|
(
|
||||||
|
const label patchI,
|
||||||
|
const label varID
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
NotImplemented;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tmp<Foam::vectorField> Foam::shapeDesignVariables::dndb
|
||||||
|
(
|
||||||
|
const label patchI,
|
||||||
|
const label varID
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
NotImplemented;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tmp<Foam::vectorField> Foam::shapeDesignVariables::dSdb
|
||||||
|
(
|
||||||
|
const label patchI,
|
||||||
|
const label varID
|
||||||
|
) const
|
||||||
|
{
|
||||||
|
NotImplemented;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Foam::tmp<Foam::volVectorField>
|
||||||
|
Foam::shapeDesignVariables::dCdb(const label varID) const
|
||||||
|
{
|
||||||
|
NotImplemented;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -0,0 +1,296 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | www.openfoam.com
|
||||||
|
\\/ M anipulation |
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Copyright (C) 2007-2023 PCOpt/NTUA
|
||||||
|
Copyright (C) 2013-2023 FOSS GP
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
License
|
||||||
|
This file is part of OpenFOAM.
|
||||||
|
|
||||||
|
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||||
|
under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Class
|
||||||
|
Foam::shapeDesignVariables
|
||||||
|
|
||||||
|
Description
|
||||||
|
Abstract base class for defining design variables for shape optimisation.
|
||||||
|
|
||||||
|
SourceFiles
|
||||||
|
shapeDesignVariables.C
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef shapeDesignVariables_H
|
||||||
|
#define shapeDesignVariables_H
|
||||||
|
|
||||||
|
#include "designVariables.H"
|
||||||
|
#include "displacementMethod.H"
|
||||||
|
#include "runTimeSelectionTables.H"
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
Class shapeDesignVariables Declaration
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
class shapeDesignVariables
|
||||||
|
:
|
||||||
|
public designVariables
|
||||||
|
{
|
||||||
|
protected:
|
||||||
|
|
||||||
|
// Protected data
|
||||||
|
|
||||||
|
//- Patches to be moved by the design variables
|
||||||
|
labelHashSet parametertisedPatches_;
|
||||||
|
|
||||||
|
//- Mesh movement mechanism
|
||||||
|
autoPtr<displacementMethod> displMethodPtr_;
|
||||||
|
|
||||||
|
//- Store old points. Useful for line search
|
||||||
|
autoPtr<pointField> pointsInit_;
|
||||||
|
|
||||||
|
//- Write the mesh points irrespective of whether this is a write time
|
||||||
|
bool writeEachMesh_;
|
||||||
|
|
||||||
|
// Auxiliary fields keeping track of the various sensitiity components
|
||||||
|
|
||||||
|
//- Flow related term.
|
||||||
|
// Term including grad(dxdb) in the volume integrals of the FI
|
||||||
|
// formulation
|
||||||
|
scalarField dxdbVolSens_;
|
||||||
|
|
||||||
|
//- Flow related term.
|
||||||
|
// Main term in the E-SI formulation. Is the surface intergral
|
||||||
|
// emerging after performing the Gauss-divergence theorem on the
|
||||||
|
// FI-based sensitivities
|
||||||
|
scalarField dxdbSurfSens_;
|
||||||
|
|
||||||
|
//- Term depending on delta(n dS)/delta b
|
||||||
|
scalarField dSdbSens_;
|
||||||
|
|
||||||
|
//- Term depending on delta(n)/delta b
|
||||||
|
scalarField dndbSens_;
|
||||||
|
|
||||||
|
//- Term depending on delta(x)/delta b for objectives that directly
|
||||||
|
//- depend on x
|
||||||
|
scalarField dxdbDirectSens_;
|
||||||
|
|
||||||
|
//- Term depending on delta(V)/delta b
|
||||||
|
scalarField dVdbSens_;
|
||||||
|
|
||||||
|
//- Term depending on distance differentiation
|
||||||
|
scalarField distanceSens_;
|
||||||
|
|
||||||
|
//- Term depending on fvOptions
|
||||||
|
scalarField optionsSens_;
|
||||||
|
|
||||||
|
//- Term depending on the differenation of boundary conditions
|
||||||
|
scalarField bcSens_;
|
||||||
|
|
||||||
|
//- Name of the sensitivity derivatives folder
|
||||||
|
fileName derivativesFolder_;
|
||||||
|
|
||||||
|
|
||||||
|
// Protected Member Functions
|
||||||
|
|
||||||
|
//- Size of the sensitivity derivatives.
|
||||||
|
// Might be different than this->size() in some cases
|
||||||
|
virtual label sensSize() const;
|
||||||
|
|
||||||
|
//- Active variables for which to compute sensitivities
|
||||||
|
// Might be different than this->activeDesignVariables_ in some cases
|
||||||
|
virtual const labelList& activeSensitivities() const;
|
||||||
|
|
||||||
|
//- Compute dxdb at the mesh cell centers by solving a Laplace PDE
|
||||||
|
virtual tmp<volVectorField> solveMeshMovementEqn
|
||||||
|
(
|
||||||
|
const label patchI,
|
||||||
|
const label varID
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Allocate the fields assosiated with the computation of sensitivities
|
||||||
|
// Not allocated in the constructor since the size of the design
|
||||||
|
// variables is usually not known there
|
||||||
|
void allocateSensFields();
|
||||||
|
|
||||||
|
//- Zero the fields assosiated with the computation of sensitivities
|
||||||
|
void zeroSensFields();
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// Private Member Functions
|
||||||
|
|
||||||
|
//- Disallow default bitwise copy construct
|
||||||
|
shapeDesignVariables(const shapeDesignVariables&) = delete;
|
||||||
|
|
||||||
|
//- Disallow default bitwise assignment
|
||||||
|
void operator=(const shapeDesignVariables&) = delete;
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
//- Runtime type information
|
||||||
|
TypeName("shape");
|
||||||
|
|
||||||
|
|
||||||
|
// Declare run-time constructor selection table
|
||||||
|
|
||||||
|
declareRunTimeSelectionTable
|
||||||
|
(
|
||||||
|
autoPtr,
|
||||||
|
shapeDesignVariables,
|
||||||
|
dictionary,
|
||||||
|
(
|
||||||
|
fvMesh& mesh,
|
||||||
|
const dictionary& dict
|
||||||
|
),
|
||||||
|
(mesh, dict)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct from components
|
||||||
|
shapeDesignVariables
|
||||||
|
(
|
||||||
|
fvMesh& mesh,
|
||||||
|
const dictionary& dict
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// Selectors
|
||||||
|
|
||||||
|
//- Construct and return the selected shapeDesignVariables
|
||||||
|
static autoPtr<shapeDesignVariables> New
|
||||||
|
(
|
||||||
|
fvMesh& mesh,
|
||||||
|
const dictionary& dict
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
//- Destructor
|
||||||
|
virtual ~shapeDesignVariables() = default;
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
//- Read dictionary if changed
|
||||||
|
virtual bool readDict(const dictionary& dict);
|
||||||
|
|
||||||
|
//- Update design variables based on a given correction.
|
||||||
|
// Translates the scalarField of corrections to a meaningful
|
||||||
|
// update of the design variables
|
||||||
|
virtual void update(scalarField& correction) = 0;
|
||||||
|
|
||||||
|
//- Store design variables, as the starting point for line search
|
||||||
|
virtual void storeDesignVariables();
|
||||||
|
|
||||||
|
//- Reset to starting point of line search
|
||||||
|
virtual void resetDesignVariables();
|
||||||
|
|
||||||
|
//- Compute eta if not set in the first step
|
||||||
|
virtual scalar computeEta(scalarField& correction) = 0;
|
||||||
|
|
||||||
|
//- Whether to use global sum when computing matrix-vector products
|
||||||
|
//- in update methods
|
||||||
|
// Depends on whether the design variables are common for all
|
||||||
|
// processors (e.g. volumetric B-Splines control points) or distributed
|
||||||
|
// across them (e.g. topology optimisation)
|
||||||
|
virtual bool globalSum() const = 0;
|
||||||
|
|
||||||
|
// Functions related to mesh movement
|
||||||
|
|
||||||
|
//- Move mesh based on displacementMethod
|
||||||
|
virtual void moveMesh();
|
||||||
|
|
||||||
|
//- Patches affected by the parameterisation
|
||||||
|
inline const labelHashSet& getPatches() const
|
||||||
|
{
|
||||||
|
return parametertisedPatches_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Return displacementMethod
|
||||||
|
inline autoPtr<displacementMethod>& returnDisplacementMethod()
|
||||||
|
{
|
||||||
|
return displMethodPtr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Fields related to sensitivity computations
|
||||||
|
|
||||||
|
//- Add part of sensitivity derivatives related to geometry
|
||||||
|
//- variations
|
||||||
|
virtual tmp<scalarField> assembleSensitivities
|
||||||
|
(
|
||||||
|
adjointSensitivity& adjointSens
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Write final sensitivity derivatives to files
|
||||||
|
virtual void writeSensitivities
|
||||||
|
(
|
||||||
|
const scalarField& sens,
|
||||||
|
const adjointSensitivity& adjointSens
|
||||||
|
);
|
||||||
|
|
||||||
|
//- Get dxdb for all mesh points
|
||||||
|
virtual tmp<vectorField> dxdbVol
|
||||||
|
(
|
||||||
|
const label varID
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Get dxdb for a given design variable and patch
|
||||||
|
virtual tmp<vectorField> dxdbFace
|
||||||
|
(
|
||||||
|
const label patchI,
|
||||||
|
const label varID
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Get dndb for a given design variable and patch
|
||||||
|
virtual tmp<vectorField> dndb
|
||||||
|
(
|
||||||
|
const label patchI,
|
||||||
|
const label varID
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Get dSdb for a given design variable and patch
|
||||||
|
virtual tmp<vectorField> dSdb
|
||||||
|
(
|
||||||
|
const label patchI,
|
||||||
|
const label varID
|
||||||
|
) const;
|
||||||
|
|
||||||
|
//- Get dCdb for a given design variable.
|
||||||
|
// Used for FI-based sensitivities
|
||||||
|
virtual tmp<volVectorField> dCdb(const label varID) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user