ENH: New adjont shape optimisation functionality

The adjoint library is enhanced with new functionality enabling
automated shape optimisation loops.  A parameterisation scheme based on
volumetric B-Splines is introduced, the control points of which act as
the design variables in the optimisation loop [1, 2].  The control
points of the volumetric B-Splines boxes can be defined in either
Cartesian or cylindrical coordinates.

The entire loop (solution of the flow and adjoint equations, computation
of sensitivity derivatives, update of the design variables and mesh) is
run within adjointOptimisationFoam. A number of methods to update the
design variables are implemented, including popular Quasi-Newton methods
like BFGS and methods capable of handling constraints like loop using
the SQP or constraint projection.

The software was developed by PCOpt/NTUA and FOSS GP, with contributions from

Dr. Evangelos Papoutsis-Kiachagias,
Konstantinos Gkaragounis,
Professor Kyriakos Giannakoglou,
Andy Heather

[1] E.M. Papoutsis-Kiachagias, N. Magoulas, J. Mueller, C. Othmer,
K.C.  Giannakoglou: 'Noise Reduction in Car Aerodynamics using a
Surrogate Objective Function and the Continuous  Adjoint Method with
Wall Functions', Computers & Fluids, 122:223-232, 2015

[2] E. M. Papoutsis-Kiachagias, V. G. Asouti, K. C. Giannakoglou,
K.  Gkagkas, S. Shimokawa, E. Itakura: ‘Multi-point aerodynamic shape
optimization of cars based on continuous adjoint’, Structural and
Multidisciplinary Optimization, 59(2):675–694, 2019
This commit is contained in:
Vaggelis Papoutsis
2019-12-11 20:33:37 +02:00
committed by Andrew Heather
parent eb4fec371a
commit b863254308
608 changed files with 36342 additions and 1193 deletions

View File

@ -55,10 +55,6 @@ int main(int argc, char *argv[])
for (om++; !om.end(); om++)
{
Info<< "* * * * * * * * * * * * * * * * * * *" << endl;
Info<< "Time = " << runTime.timeName() << endl;
Info<< "* * * * * * * * * * * * * * * * * * *" << endl;
if (om.update())
{
// Update design variables and solve all primal equations

View File

@ -0,0 +1,3 @@
cumulativeDisplacement.C
EXE = $(FOAM_APPBIN)/cumulativeDisplacement

View File

@ -0,0 +1,11 @@
EXE_INC = \
-I$(LIB_SRC)/dynamicMesh/dynamicFvMesh/lnInclude \
-I$(LIB_SRC)/dynamicMesh/dynamicMesh/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/finiteVolume/lnInclude
EXE_LIBS = \
-ldynamicFvMesh \
-ldynamicMesh \
-lmeshTools \
-lfiniteVolume

View File

@ -0,0 +1,16 @@
pointField points0
(
pointIOField
(
IOobject
(
"points",
mesh.time().constant(),
polyMesh::meshSubDir,
mesh,
IOobject::MUST_READ,
IOobject::NO_WRITE,
false
)
)
);

View File

@ -0,0 +1,161 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Application
cumulativeDisplacement
Description
Computes and writes the difference between the mesh points in each time
instance and the ones in the constant folder. Additionally, the projection
of this difference to the normal point vectors of the initial mesh is also
written
\*---------------------------------------------------------------------------*/
#include "fvCFD.H"
#include "emptyFvPatch.H"
#include "coupledFvPatch.H"
#include "pointMesh.H"
#include "pointPatchField.H"
#include "pointPatchFieldsFwd.H"
#include "syncTools.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
timeSelector::addOptions();
#include "addRegionOption.H"
#include "setRootCase.H"
#include "createTime.H"
instantList timeDirs = timeSelector::select0(runTime, args);
#include "createNamedMesh.H"
#include "createFields.H"
// 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(), vector::zero);
for (const fvPatch& patch : mesh.boundary())
{
// Each local patch point belongs to these local patch faces.
// Local numbering
const labelListList& patchPointFaces = patch.patch().pointFaces();
if (!isA<coupledFvPatch>(patch) && !isA<emptyFvPatch>(patch))
{
const labelList& meshPoints = patch.patch().meshPoints();
const vectorField nf(patch.nf());
forAll(meshPoints, ppI)
{
const labelList& pointFaces = patchPointFaces[ppI];
forAll(pointFaces, pfI)
{
const label& localFaceIndex = pointFaces[pfI];
pointNormals[meshPoints[ppI]] += nf[localFaceIndex];
}
}
}
}
// Sum from all processors
syncTools::syncPointList
(
mesh, pointNormals, plusEqOp<vector>(), vector::zero
);
pointNormals /= mag(pointNormals) + VSMALL;
forAll(timeDirs, timeI)
{
runTime.setTime(timeDirs[timeI], timeI);
Info<< "Time = " << runTime.timeName() << endl;
mesh.readUpdate();
const pointMesh& pMesh(pointMesh::New(mesh));
// Point displacement projected to the
// unit point normal of the initial geometry
pointScalarField normalDisplacement
(
IOobject
(
"normalDisplacement",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
pMesh,
dimensionedScalar(dimless, Zero)
);
// Point displacement as a vector
pointVectorField displacement
(
IOobject
(
"displacement",
runTime.timeName(),
mesh,
IOobject::NO_READ,
IOobject::AUTO_WRITE
),
pMesh,
dimensionedVector(dimless, Zero)
);
Info<< "Calculating cumulative mesh movement for time "
<< runTime.timeName() << endl;
// Normal displacement
const pointField& meshPoints = mesh.points();
forAll(mesh.boundary(), pI)
{
const polyPatch& patch = mesh.boundaryMesh()[pI];
const labelList& localPoints = patch.meshPoints();
forAll(localPoints, ppI)
{
label pointI = localPoints[ppI];
normalDisplacement[pointI] =
(meshPoints[pointI] - points0[pointI])
& pointNormals[pointI];
}
}
normalDisplacement.write();
// Vectorial displacement
displacement.primitiveFieldRef() = meshPoints - points0;
displacement.write();
}
// Print execution time
mesh.time().printExecutionTime(Info);
Info<< "End\n" << endl;
return(0);
}
// ************************************************************************* //

View File

@ -0,0 +1,3 @@
writeActiveDesignVariables.C
EXE = $(FOAM_APPBIN)/writeActiveDesignVariables

View File

@ -0,0 +1,14 @@
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

View File

@ -0,0 +1,110 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
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())
{
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
(
IOstream::ASCII,
IOstream::currentVersion,
IOstream::UNCOMPRESSED,
true
);
Info<< "End\n" << endl;
return 0;
}
// ************************************************************************* //

View File

@ -0,0 +1,3 @@
writeMorpherCPs.C
EXE = $(FOAM_APPBIN)/writeMorpherCPs

View File

@ -0,0 +1,13 @@
EXE_INC = \
-I$(LIB_SRC)/finiteVolume/lnInclude \
-I$(LIB_SRC)/meshTools/lnInclude \
-I$(LIB_SRC)/finiteVolume/cfdTools \
-I$(LIB_SRC)/optimisation/adjointOptimisation/adjoint/lnInclude
EXE_LIBS = \
-lfiniteVolume \
-lmeshTools \
-lfvOptions \
-ldynamicMesh \
-lfvMotionSolvers \
-ladjointOptimisation

View File

@ -0,0 +1,83 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Application
writeMorpherCPs
Description
Writes the NURBS3DVolume control points corresponding to dynamicMeshDict
to csv files. Parametric coordinates are not computed.
\*---------------------------------------------------------------------------*/
#include "fvCFD.H"
#include "NURBS3DVolume.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
int main(int argc, char *argv[])
{
#include "setRootCase.H"
#include "createTime.H"
#include "createMesh.H"
IOdictionary dict
(
IOobject
(
"dynamicMeshDict",
mesh.time().constant(),
mesh,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::NO_WRITE
)
);
const dictionary& coeffDict =
dict.subDict("volumetricBSplinesMotionSolverCoeffs");
wordList controlBoxes(coeffDict.get<wordList>("controlBoxes"));
forAll(controlBoxes, iNURB)
{
// Creating an object writes the control points in the
// constructor
NURBS3DVolume::New
(
coeffDict.subDict(controlBoxes[iNURB]),
mesh,
false // do not compute parametric coordinates
);
}
Info<< "End\n" << endl;
return 0;
}
// ************************************************************************* //

View File

@ -52,6 +52,9 @@ pointCells::pointCells
:
zeroATCcells(mesh, dict)
{
boolList isZeroed(mesh_.nCells(), false);
labelList zeroedIDs(mesh_.nCells(), -1);
label i(0);
forAll(mesh_.boundary(), patchI)
{
const fvPatch& patch = mesh_.boundary()[patchI];
@ -65,7 +68,14 @@ pointCells::pointCells
for (const label pointI : meshPoints)
{
const labelList& pointCells = mesh_.pointCells()[pointI];
zeroATCcells_.append(pointCells);
for (const label cellI : pointCells)
{
if (!isZeroed[cellI])
{
zeroedIDs[i++] = cellI;
isZeroed[cellI] = true;
}
}
}
}
}
@ -76,14 +86,22 @@ pointCells::pointCells
if (zoneID != -1)
{
const labelList& zoneCells = mesh_.cellZones()[zoneID];
zeroATCcells_.append(zoneCells);
for (const label cellI : zoneCells)
{
if (!isZeroed[cellI])
{
zeroedIDs[i++] = cellI;
isZeroed[cellI] = true;
}
}
}
}
/*
zeroedIDs.setSize(i);
zeroATCcells_ = zeroedIDs;
label size = zeroATCcells_.size();
reduce(size, sumOp<label>());
Info<< "Zeroing ATC on "<< size << " cells" << nl << endl;
*/
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -16,6 +16,7 @@ solvers/variablesSet/incompressibleAdjoint/incompressibleAdjointVars.C
solvers/solverControl/solverControl/solverControl.C
solvers/solverControl/SIMPLEControl/SIMPLEControl/SIMPLEControl.C
solvers/solverControl/SIMPLEControl/singleRun/SIMPLEControlSingleRun.C
solvers/solverControl/SIMPLEControl/optimisation/SIMPLEControlOpt.C
/* SOLVERS */
solvers/solver/solver.C
@ -52,6 +53,8 @@ objectives/incompressible/objectiveIncompressible/objectiveIncompressible.C
objectives/incompressible/objectiveForce/objectiveForce.C
objectives/incompressible/objectiveMoment/objectiveMoment.C
objectives/incompressible/objectivePtLosses/objectivePtLosses.C
objectives/incompressible/objectiveForceTarget/objectiveForceTarget.C
objectives/incompressible/objectivePartialVolume/objectivePartialVolume.C
/* OBJECTIVE MANAGER*/
objectiveManager/objectiveManager/objectiveManager.C
@ -87,8 +90,39 @@ adjointBoundaryConditions/adjointOutletVelocityFlux/adjointOutletVelocityFluxFvP
/* DELTA BOUNDARY */
deltaBoundary/deltaBoundary.C
/* NURBS */
NURBS=parameterization/NURBS
$(NURBS)/NURBSbasis/NURBSbasis.C
$(NURBS)/NURBS3DCurve/NURBS3DCurve.C
$(NURBS)/NURBS3DSurface/NURBS3DSurface.C
$(NURBS)/NURBS3DVolume/NURBS3DVolume/NURBS3DVolume.C
$(NURBS)/NURBS3DVolume/cartesian/NURBS3DVolumeCartesian.C
$(NURBS)/NURBS3DVolume/cylindrical/NURBS3DVolumeCylindrical.C
$(NURBS)/NURBS3DVolume/volBSplinesBase/volBSplinesBase.C
/* BEZIER */
parameterization/Bezier/Bezier.C
/* MOTION SOLVERS */
dynamicMesh/motionSolver/volumetricBSplinesMotionSolver/volumetricBSplinesMotionSolver.C
dynamicMesh/motionSolver/elasticityMotionSolver/elasticityMotionSolver.C
dynamicMesh/motionSolver/laplacianMotionSolver/laplacianMotionSolver.C
/* DISPLACEMENT METHOD */
displacementMethod/displacementMethod/displacementMethod.C
displacementMethod/displacementMethodvolumetricBSplinesMotionSolver/displacementMethodvolumetricBSplinesMotionSolver.C
displacementMethod/displacementMethoddisplacementLaplacian/displacementMethoddisplacementLaplacian.C
displacementMethod/displacementMethodvelocityLaplacian/displacementMethodvelocityLaplacian.C
displacementMethod/displacementMethodelasticityMotionSolver/displacementMethodelasticityMotionSolver.C
displacementMethod/displacementMethodlaplacianMotionSolver/displacementMethodlaplacianMotionSolver.C
/* INTERPOLATION SCHEMES */
interpolation/pointVolInterpolation/pointVolInterpolation.C
/* ADJOINT SENSITIVITY */
optimisation/adjointSensitivity/sensitivity/sensitivity.C
optimisation/adjointSensitivity/shapeSensitivitiesBase/shapeSensitivitiesBase.C
incoSens=optimisation/adjointSensitivity/incompressible
$(incoSens)/adjointSensitivity/adjointSensitivityIncompressible.C
$(incoSens)/adjointEikonalSolver/adjointEikonalSolverIncompressible.C
@ -96,21 +130,49 @@ $(incoSens)/adjointMeshMovementSolver/adjointMeshMovementSolverIncompressible.C
$(incoSens)/sensitivitySurface/sensitivitySurfaceIncompressible.C
$(incoSens)/sensitivitySurfacePoints/sensitivitySurfacePointsIncompressible.C
$(incoSens)/sensitivityMultiple/sensitivityMultipleIncompressible.C
$(incoSens)/SIBase/SIBaseIncompressible.C
$(incoSens)/FIBase/FIBaseIncompressible.C
$(incoSens)/sensitivityVolBSplines/sensitivityVolBSplinesIncompressible.C
$(incoSens)/sensitivityVolBSplinesFI/sensitivityVolBSplinesFIIncompressible.C
$(incoSens)/sensitivityBezier/sensitivityBezierIncompressible.C
$(incoSens)/sensitivityBezierFI/sensitivityBezierFIIncompressible.C
/* LINE SEARCH */
optimisation/lineSearch/lineSearch/lineSearch.C
optimisation/lineSearch/ArmijoConditions/ArmijoConditions.C
optimisation/lineSearch/stepUpdate/stepUpdate/stepUpdate.C
optimisation/lineSearch/stepUpdate/bisection/bisection.C
optimisation/lineSearch/stepUpdate/quadratic/quadratic.C
/* UPDATE METHOD */
optimisation/updateMethod/updateMethod/updateMethod.C
optimisation/updateMethod/constrainedOptimisationMethod/constrainedOptimisationMethod.C
updateMethod=optimisation/updateMethod/
$(updateMethod)/updateMethod/updateMethod.C
$(updateMethod)/constrainedOptimisationMethod/constrainedOptimisationMethod.C
$(updateMethod)/steepestDescent/steepestDescent.C
$(updateMethod)/BFGS/BFGS.C
$(updateMethod)/DBFGS/DBFGS.C
$(updateMethod)/LBFGS/LBFGS.C
$(updateMethod)/SR1/SR1.C
$(updateMethod)/conjugateGradient/conjugateGradient.C
$(updateMethod)/constraintProjection/constraintProjection.C
$(updateMethod)/SQP/SQP.C
/* OPT MESH MOVEMENT */
optMeshMovement=optimisation/optMeshMovement
$(optMeshMovement)/optMeshMovement/optMeshMovement.C
$(optMeshMovement)/optMeshMovementVolumetricBSplines/optMeshMovementVolumetricBSplines.C
$(optMeshMovement)/optMeshMovementVolumetricBSplinesExternalMotionSolver/optMeshMovementVolumetricBSplinesExternalMotionSolver.C
$(optMeshMovement)/optMeshMovementBezier/optMeshMovementBezier.C
$(optMeshMovement)/optMeshMovementNULL/optMeshMovementNULL.C
/* OPTIMIZATION TYPE */
incoOptType=optimisation/optimisationType/incompressible
$(incoOptType)/optimisationType/optimisationTypeIncompressible.C
$(incoOptType)/shapeOptimisation/shapeOptimisationIncompressible.C
/* OPTIMIZATION MANAGER */
optimisation/optimisationManager/optimisationManager/optimisationManager.C
optimisation/optimisationManager/singleRun/singleRun.C
optimisation/optimisationManager/steadyOptimisation/steadyOptimisation.C
LIB = $(FOAM_LIBBIN)/libadjointOptimisation

View File

@ -0,0 +1,136 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "displacementMethod.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(displacementMethod, 0);
defineRunTimeSelectionTable(displacementMethod, dictionary);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::displacementMethod::displacementMethod
(
fvMesh& mesh,
const labelList& patchIDs
)
:
mesh_(mesh),
patchIDs_(patchIDs),
motionPtr_(motionSolver::New(mesh_)),
maxDisplacement_(SMALL)
{}
// * * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * //
Foam::autoPtr<Foam::displacementMethod> Foam::displacementMethod::New
(
fvMesh& mesh,
const labelList& patchIDs
)
{
// To ensure that displacement method has the same
// type as the motion solver, construct it based on its name
IOdictionary dynamicMeshDict
(
IOobject
(
"dynamicMeshDict",
mesh.time().constant(),
mesh,
IOobject::MUST_READ,
IOobject::NO_WRITE,
false
)
);
word motionSolverName(dynamicMeshDict.get<word>("solver"));
word modelType("displacementMethod" + motionSolverName);
Info<< "displacementMethod type : " << modelType << endl;
auto cstrIter = dictionaryConstructorTablePtr_->cfind(modelType);
if (!cstrIter.found())
{
FatalIOErrorInLookup
(
dynamicMeshDict,
"solver",
modelType,
*dictionaryConstructorTablePtr_
) << exit(FatalError);
}
return autoPtr<displacementMethod>(cstrIter()(mesh, patchIDs));
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * //
void Foam::displacementMethod::boundControlField(vectorField& controlField)
{
// Does nothing in base
}
Foam::autoPtr<Foam::motionSolver>& Foam::displacementMethod::getMotionSolver()
{
return motionPtr_;
}
Foam::scalar Foam::displacementMethod::getMaxDisplacement() const
{
return maxDisplacement_;
}
void Foam::displacementMethod::update()
{
scalar timeBef = mesh_.time().elapsedCpuTime();
// Compute max mesh movement
tmp<pointField> tnewPoints = motionPtr_->newPoints();
Info<< "Max mesh movement magnitude "
<< gMax(mag(tnewPoints() - mesh_.points())) << endl;
// Update mesh as in dynamicFvMesh
mesh_.movePoints(tnewPoints());
scalar timeAft = mesh_.time().elapsedCpuTime();
Info<< "Mesh movement took " << timeAft - timeBef << " seconds" << endl;
mesh_.moving(false);
}
// ************************************************************************* //

View File

@ -0,0 +1,171 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Class
Foam::displacementMethod
Description
Abstract base class for displacement methods, which are a set or
wrapper classes allowing to change the driving force of mesh motion solvers
SourceFiles
displacementMethod.C
\*---------------------------------------------------------------------------*/
#ifndef displacementMethod_H
#define displacementMethod_H
#include "fvm.H"
#include "fvc.H"
#include "runTimeSelectionTables.H"
#include "addToRunTimeSelectionTable.H"
#include "motionSolver.H"
#include "volPointInterpolation.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class displacementMethod Declaration
\*---------------------------------------------------------------------------*/
class displacementMethod
{
protected:
// Protected data
fvMesh& mesh_;
//- IDs of the patches to be moved
const labelList& patchIDs_;
autoPtr<motionSolver> motionPtr_;
scalar maxDisplacement_;
private:
// Private Member Functions
//- Disallow default bitwise copy construct
displacementMethod(const displacementMethod&) = delete;
//- Disallow default bitwise assignment
void operator=(const displacementMethod&) = delete;
public:
//- Runtime type information
TypeName("displacementMethod");
// Declare run-time constructor selection table
declareRunTimeSelectionTable
(
autoPtr,
displacementMethod,
dictionary,
(
fvMesh& mesh,
const labelList& patchIDs
),
(mesh, patchIDs)
);
// Constructors
//- Construct from components
displacementMethod
(
fvMesh& mesh,
const labelList& patchIDs
);
// Selectors
//- Return a reference to the selected turbulence model
static autoPtr<displacementMethod> New
(
fvMesh& mesh,
const labelList& patchIDs
);
//- Destructor
virtual ~displacementMethod() = default;
// Member Functions
//- Set motion filed related to model based on given motion
virtual void setMotionField(const pointVectorField& pointMovement) = 0;
//- Set motion filed related to model based on given motion
virtual void setMotionField(const volVectorField& cellMovement) = 0;
//- Set control field as a vectorField. For methods working with
//- parameters (RBF etc)
virtual void setControlField(const vectorField& controlField) = 0;
//- Set control field as a vectorField. For methods working with
//- parameters (RBF etc)
virtual void setControlField(const scalarField& controlField) = 0;
//- Bound control field in certain directions etc. For methods working
//- with parameters (RBF etc)
//- does nothing by default
virtual void boundControlField(vectorField& controlField);
//- Get access to motionSolver
autoPtr<motionSolver>& getMotionSolver();
//- Get max displacement
scalar getMaxDisplacement() const;
//- Update mesh
void update();
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,192 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "displacementMethoddisplacementLaplacian.H"
#include "displacementLaplacianFvMotionSolver.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
defineTypeNameAndDebug(displacementMethoddisplacementLaplacian, 1);
addToRunTimeSelectionTable
(
displacementMethod,
displacementMethoddisplacementLaplacian,
dictionary
);
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
displacementMethoddisplacementLaplacian::displacementMethoddisplacementLaplacian
(
fvMesh& mesh,
const labelList& patchIDs
)
:
displacementMethod(mesh, patchIDs),
pointDisplacement_
(
refCast<displacementLaplacianFvMotionSolver>
(
motionPtr_()
).pointDisplacement()
),
cellDisplacement_
(
refCast<displacementLaplacianFvMotionSolver>
(
motionPtr_()
).cellDisplacement()
),
/*
// Getting a reference from the database is dangerous since multiple
// fields with the same name might be registered
pointDisplacement_
(
const_cast<pointVectorField&>
(
mesh_.lookupObject<pointVectorField>("pointDisplacement")
)
),
cellDisplacement_
(
const_cast<volVectorField&>
(
mesh_.lookupObject<volVectorField>("cellDisplacement")
)
),
*/
resetFields_
(
IOdictionary
(
IOobject
(
"dynamicMeshDict",
mesh.time().constant(),
mesh,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::AUTO_WRITE,
false
)
).subDict("displacementLaplacianCoeffs").lookupOrDefault<bool>
(
"resetFields",
true
)
)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void displacementMethoddisplacementLaplacian::setMotionField
(
const pointVectorField& pointMovement
)
{
Info<< "Reseting mesh motion fields to zero " << endl;
if (resetFields_)
{
pointDisplacement_.primitiveFieldRef() = vector::zero;
cellDisplacement_.primitiveFieldRef() = vector::zero;
cellDisplacement_.correctBoundaryConditions();
}
// Set boundary mesh movement and calculate
// max current boundary displacement
for (label patchI : patchIDs_)
{
// Set boundary field. Needed for the motionSolver class
pointDisplacement_.boundaryFieldRef()[patchI] ==
pointMovement.boundaryField()[patchI].patchInternalField()();
// Set boundary field values as seen from the internalField!
// Needed for determining the max displacement
pointDisplacement_.boundaryFieldRef()[patchI].setInInternalField
(
pointDisplacement_.primitiveFieldRef(),
pointMovement.boundaryField()[patchI].patchInternalField()()
);
// Find max value
maxDisplacement_ =
max
(
maxDisplacement_,
gMax
(
mag
(
pointDisplacement_.boundaryField()[patchI].
patchInternalField()
)
)
);
}
}
void displacementMethoddisplacementLaplacian::setMotionField
(
const volVectorField& cellMovement
)
{
NotImplemented;
}
void displacementMethoddisplacementLaplacian::setControlField
(
const vectorField& controlField
)
{
NotImplemented;
}
void displacementMethoddisplacementLaplacian::setControlField
(
const scalarField& controlField
)
{
NotImplemented;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,128 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Class
Foam::displacementMethoddisplacementLaplacian
Description
Wrapper class for the displacementLaplacian motion solver
SourceFiles
displacementMethoddisplacementLaplacian.C
\*---------------------------------------------------------------------------*/
#ifndef displacementMethoddisplacementLaplacian_H
#define displacementMethoddisplacementLaplacian_H
#include "displacementMethod.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class displacementMethoddisplacementLaplacian Declaration
\*---------------------------------------------------------------------------*/
class displacementMethoddisplacementLaplacian
:
public displacementMethod
{
protected:
// Protected data
pointVectorField& pointDisplacement_;
volVectorField& cellDisplacement_;
bool resetFields_;
private:
// Private Member Functions
//- Disallow default bitwise copy construct
displacementMethoddisplacementLaplacian
(
const displacementMethoddisplacementLaplacian&
) = delete;
//- Disallow default bitwise assignment
void operator=(const displacementMethoddisplacementLaplacian&) = delete;
public:
//- Runtime type information
TypeName("displacementMethoddisplacementLaplacian");
// Constructors
//- Construct from components
displacementMethoddisplacementLaplacian
(
fvMesh& mesh,
const labelList& patchIDs
);
//- Destructor
virtual ~displacementMethoddisplacementLaplacian() = default;
// Member Functions
//- Set motion filed related to model based on given motion
void setMotionField(const pointVectorField& pointMovement);
//- Set motion filed related to model based on given motion
void setMotionField(const volVectorField& cellMovement);
//- Set control field as a vectorField. For methods working with
//- parameters (RBF etc)
void setControlField(const vectorField& controlField);
//- Set control field as a vectorField. For methods working with
//- parameters (RBF etc)
void setControlField(const scalarField& controlField);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,215 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "displacementMethodelasticityMotionSolver.H"
#include "elasticityMotionSolver.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
defineTypeNameAndDebug(displacementMethodelasticityMotionSolver, 1);
addToRunTimeSelectionTable
(
displacementMethod,
displacementMethodelasticityMotionSolver,
dictionary
);
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
displacementMethodelasticityMotionSolver::
displacementMethodelasticityMotionSolver
(
fvMesh& mesh,
const labelList& patchIDs
)
:
displacementMethod(mesh, patchIDs),
pointMotionU_(refCast<elasticityMotionSolver>(motionPtr_()).pointMotionU()),
cellMotionU_(refCast<elasticityMotionSolver>(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_
(
IOdictionary
(
IOobject
(
"dynamicMeshDict",
mesh.time().constant(),
mesh,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::AUTO_WRITE,
false
)
).subDict("elasticityMotionSolverCoeffs").lookupOrDefault<bool>
(
"resetFields",
true
)
)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void displacementMethodelasticityMotionSolver::setMotionField
(
const pointVectorField& pointMovement
)
{
if (resetFields_)
{
pointMotionU_.primitiveFieldRef() = vector::zero;
cellMotionU_.primitiveFieldRef() = vector::zero;
cellMotionU_.correctBoundaryConditions();
}
maxDisplacement_ = SMALL;
// Update the boundary conditions of the pointField in order to make
// sure that the boundary will move according to the initial BCs
// without the interferance of the volPointInterpolation in the elasticityMotionSolver
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()
)
)
);
}
// update the volField boundary conditions, used for the elasticity PDEs solution
const pointField& points = mesh_.points();
for (label patchI : patchIDs_)
{
const polyPatch& patch = mesh_.boundaryMesh()[patchI];
fvPatchVectorField& bField = cellMotionU_.boundaryFieldRef()[patchI];
forAll(patch, fI)
{
bField[fI] = patch[fI].average(points, pointMovement);
}
}
}
void displacementMethodelasticityMotionSolver::setMotionField
(
const volVectorField& cellMovement
)
{
auto cellMotionUbf = cellMotionU_.boundaryFieldRef();
// Set boundary mesh movement and calculate
// max current boundary displacement
forAll(patchIDs_, pI)
{
label patchI = patchIDs_[pI];
// Set boundary field. Needed for the motionSolver class
cellMotionUbf[patchI] == cellMovement.boundaryField()[patchI];
// Find max value
maxDisplacement_ =
max
(
maxDisplacement_,
gMax
(
mag(cellMotionUbf[patchI])
)
);
}
}
void displacementMethodelasticityMotionSolver::setControlField
(
const vectorField& controlField
)
{
NotImplemented;
}
void displacementMethodelasticityMotionSolver::setControlField
(
const scalarField& controlField
)
{
NotImplemented;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,132 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Class
Foam::displacementMethodelasticityMotionSolver
Description
Wrapper class for the elasticityMotionSolver motion solver
SourceFiles
displacementMethodelasticityMotionSolver.C
\*---------------------------------------------------------------------------*/
#ifndef displacementMethodelasticityMotionSolver_H
#define displacementMethodelasticityMotionSolver_H
#include "displacementMethod.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class displacementMethodelasticityMotionSolver Declaration
\*---------------------------------------------------------------------------*/
class displacementMethodelasticityMotionSolver
:
public displacementMethod
{
protected:
// Protected data
pointVectorField& pointMotionU_;
volVectorField& cellMotionU_;
bool resetFields_;
private:
// Private Member Functions
//- Disallow default bitwise copy construct
displacementMethodelasticityMotionSolver
(
const displacementMethodelasticityMotionSolver&
) = delete;
//- Disallow default bitwise assignment
void operator=
(
const displacementMethodelasticityMotionSolver&
) = delete;
public:
//- Runtime type information
TypeName("displacementMethodelasticityMotionSolver");
// Constructors
//- Construct from components
displacementMethodelasticityMotionSolver
(
fvMesh& mesh,
const labelList& patchIDs
);
//- Destructor
virtual ~displacementMethodelasticityMotionSolver() = default;
// Member Functions
//- Set motion filed related to model based on given motion
void setMotionField(const pointVectorField& pointMovement);
//- Set motion filed related to model based on given motion
void setMotionField(const volVectorField& cellMovement);
//- Set control field as a vectorField. For methods working with
//- parameters (RBF etc)
void setControlField(const vectorField& controlField);
//- Set control field as a vectorField. For methods working with
//- parameters (RBF etc)
void setControlField(const scalarField& controlField);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,199 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "displacementMethodlaplacianMotionSolver.H"
#include "laplacianMotionSolver.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
defineTypeNameAndDebug(displacementMethodlaplacianMotionSolver, 1);
addToRunTimeSelectionTable
(
displacementMethod,
displacementMethodlaplacianMotionSolver,
dictionary
);
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
displacementMethodlaplacianMotionSolver::displacementMethodlaplacianMotionSolver
(
fvMesh& mesh,
const labelList& patchIDs
)
:
displacementMethod(mesh, patchIDs),
pointMotionU_(refCast<laplacianMotionSolver>(motionPtr_()).pointMotionU()),
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_
(
IOdictionary
(
IOobject
(
"dynamicMeshDict",
mesh.time().constant(),
mesh,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::AUTO_WRITE,
false
)
).subDict("laplacianMotionSolverCoeffs").lookupOrDefault<bool>
(
"resetFields",
true
)
)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void displacementMethodlaplacianMotionSolver::setMotionField
(
const pointVectorField& pointMovement
)
{
if (resetFields_)
{
pointMotionU_.primitiveFieldRef() = vector::zero;
cellMotionU_.primitiveFieldRef() = vector::zero;
cellMotionU_.correctBoundaryConditions();
}
// 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()
)
)
);
}
}
void displacementMethodlaplacianMotionSolver::setMotionField
(
const volVectorField& cellMovement
)
{
NotImplemented;
/*
// Set boundary mesh movement and calculate max current boundary
// displacement
forAll(patchIDs_, pI)
{
label patchI = patchIDs_[pI];
cellMotionU_.boundaryField()[patchI] ==
cellMovement.boundaryField()[patchI];
// Find max value
maxDisplacement_ =
max
(
maxDisplacement_,
gMax
(
mag(cellMovement.boundaryField()[patchI])
)
);
}
*/
}
void displacementMethodlaplacianMotionSolver::setControlField
(
const vectorField& controlField
)
{
NotImplemented;
}
void displacementMethodlaplacianMotionSolver::setControlField
(
const scalarField& controlField
)
{
NotImplemented;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,129 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Class
Foam::displacementMethodlaplacianMotionSolver
Description
Wrapper class for the velocityLaplacian motion solver
SourceFiles
displacementMethodlaplacianMotionSolver.C
\*---------------------------------------------------------------------------*/
#ifndef displacementMethodlaplacianMotionSolver_H
#define displacementMethodlaplacianMotionSolver_H
#include "displacementMethod.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class displacementMethodlaplacianMotionSolver Declaration
\*---------------------------------------------------------------------------*/
class displacementMethodlaplacianMotionSolver
:
public displacementMethod
{
protected:
// Protected data
pointVectorField& pointMotionU_;
volVectorField& cellMotionU_;
bool resetFields_;
private:
// Private Member Functions
//- Disallow default bitwise copy construct
displacementMethodlaplacianMotionSolver
(
const displacementMethodlaplacianMotionSolver&
) = delete;
//- Disallow default bitwise assignment
void operator=(const displacementMethodlaplacianMotionSolver&) = delete;
public:
//- Runtime type information
TypeName("displacementMethodlaplacianMotionSolver");
// Constructors
//- Construct from components
displacementMethodlaplacianMotionSolver
(
fvMesh& mesh,
const labelList& patchIDs
);
//- Destructor
virtual ~displacementMethodlaplacianMotionSolver() = default;
// Member Functions
//- Set motion filed related to model based on given motion
void setMotionField(const pointVectorField& pointMovement);
//- Set motion filed related to model based on given motion
void setMotionField(const volVectorField& cellMovement);
//- Set control field as a vectorField. For methods working with
//- parameters (RBF etc)
void setControlField(const vectorField& controlField);
//- Set control field as a vectorField. For methods working with
//- parameters (RBF etc)
void setControlField(const scalarField& controlField);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,207 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "displacementMethodvelocityLaplacian.H"
#include "velocityLaplacianFvMotionSolver.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
defineTypeNameAndDebug(displacementMethodvelocityLaplacian, 1);
addToRunTimeSelectionTable
(
displacementMethod,
displacementMethodvelocityLaplacian,
dictionary
);
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
displacementMethodvelocityLaplacian::displacementMethodvelocityLaplacian
(
fvMesh& mesh,
const labelList& patchIDs
)
:
displacementMethod(mesh, patchIDs),
pointMotionU_
(
refCast<velocityLaplacianFvMotionSolver>(motionPtr_()).pointMotionU()
),
cellMotionU_
(
refCast<velocityLaplacianFvMotionSolver>(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_
(
IOdictionary
(
IOobject
(
"dynamicMeshDict",
mesh.time().constant(),
mesh,
IOobject::MUST_READ_IF_MODIFIED,
IOobject::AUTO_WRITE,
false
)
).subDict("velocityLaplacianCoeffs").lookupOrDefault<bool>
(
"resetFields",
true
)
)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void displacementMethodvelocityLaplacian::setMotionField
(
const pointVectorField& pointMovement
)
{
if (resetFields_)
{
pointMotionU_.primitiveFieldRef() = vector::zero;
cellMotionU_.primitiveFieldRef() = vector::zero;
cellMotionU_.correctBoundaryConditions();
}
// 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()
)
)
);
}
}
void displacementMethodvelocityLaplacian::setMotionField
(
const volVectorField& cellMovement
)
{
NotImplemented;
/*
// Set boundary mesh movement and calculate max current boundary
// displacement
forAll(patchIDs_, pI)
{
label patchI = patchIDs_[pI];
cellMotionU_.boundaryField()[patchI] ==
cellMovement.boundaryField()[patchI];
// Find max value
maxDisplacement_ =
max
(
maxDisplacement_,
gMax
(
mag(cellMovement.boundaryField()[patchI])
)
);
}
*/
}
void displacementMethodvelocityLaplacian::setControlField
(
const vectorField& controlField
)
{
NotImplemented;
}
void displacementMethodvelocityLaplacian::setControlField
(
const scalarField& controlField
)
{
NotImplemented;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,130 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Class
Foam::displacementMethodvelocityLaplacian
Description
Wrapper class for the velocityLaplacian motion solver
SourceFiles
displacementMethodvelocityLaplacian.C
\*---------------------------------------------------------------------------*/
#ifndef displacementMethodvelocityLaplacian_H
#define displacementMethodvelocityLaplacian_H
#include "displacementMethod.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class displacementMethodvelocityLaplacian Declaration
\*---------------------------------------------------------------------------*/
class displacementMethodvelocityLaplacian
:
public displacementMethod
{
protected:
// Protected data
pointVectorField& pointMotionU_;
volVectorField& cellMotionU_;
bool resetFields_;
private:
// Private Member Functions
//- Disallow default bitwise copy construct
displacementMethodvelocityLaplacian
(
const displacementMethodvelocityLaplacian&
) = delete;
//- Disallow default bitwise assignment
void operator=(const displacementMethodvelocityLaplacian&) = delete;
public:
//- Runtime type information
TypeName("displacementMethodvelocityLaplacian");
// Constructors
//- Construct from components
displacementMethodvelocityLaplacian
(
fvMesh& mesh,
const labelList& patchIDs
);
//- Destructor
virtual ~displacementMethodvelocityLaplacian() = default;
// Member Functions
//- Set motion filed related to model based on given motion
void setMotionField(const pointVectorField& pointMovement);
//- Set motion filed related to model based on given motion
void setMotionField(const volVectorField& cellMovement);
//- Set control field as a vectorField. For methods working with
//- parameters (RBF etc)
void setControlField(const vectorField& controlField);
//- Set control field as a vectorField. For methods working with
//- parameters (RBF etc)
void setControlField(const scalarField& controlField);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,119 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "displacementMethodvolumetricBSplinesMotionSolver.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
defineTypeNameAndDebug(displacementMethodvolumetricBSplinesMotionSolver, 0);
addToRunTimeSelectionTable
(
displacementMethod,
displacementMethodvolumetricBSplinesMotionSolver,
dictionary
);
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
displacementMethodvolumetricBSplinesMotionSolver::
displacementMethodvolumetricBSplinesMotionSolver
(
fvMesh& mesh,
const labelList& patchIDs
)
:
displacementMethod(mesh, patchIDs)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void displacementMethodvolumetricBSplinesMotionSolver::setMotionField
(
const pointVectorField& pointMovement
)
{
NotImplemented;
}
void displacementMethodvolumetricBSplinesMotionSolver::setMotionField
(
const volVectorField& cellMovement
)
{
NotImplemented;
}
void displacementMethodvolumetricBSplinesMotionSolver::setControlField
(
const vectorField& controlField
)
{
// refCast motionSolver to volumetricBSplinesMotionSolver in order to pass
// control points movement. Safe since the motionSolver can only be an
// volumetricBSplinesMotionSolver
refCast<volumetricBSplinesMotionSolver>
(motionPtr_()).setControlPointsMovement(controlField);
}
void displacementMethodvolumetricBSplinesMotionSolver::setControlField
(
const scalarField& controlField
)
{
NotImplemented;
}
void displacementMethodvolumetricBSplinesMotionSolver::boundControlField
(
vectorField& controlField
)
{
// refCast motionSolver to volumetricBSplinesMotionSolver in order to bound
// control points movement. Safe since the motionSolver can only be an
// volumetricBSplinesMotionSolver
refCast<volumetricBSplinesMotionSolver>
(motionPtr_()).boundControlPointsMovement(controlField);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,127 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Class
Foam::displacementMethodvolumetricBSplinesMotionSolver
Description
Wrapper class for the volumetricBSplinesMotionSolver motion solver
SourceFiles
displacementMethodvolumetricBSplinesMotionSolver.C
\*---------------------------------------------------------------------------*/
#ifndef displacementMethodvolumetricBSplinesMotionSolver_H
#define displacementMethodvolumetricBSplinesMotionSolver_H
#include "displacementMethod.H"
#include "volumetricBSplinesMotionSolver.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class displacementMethodvolumetricBSplinesMotionSolver Declaration
\*---------------------------------------------------------------------------*/
class displacementMethodvolumetricBSplinesMotionSolver
:
public displacementMethod
{
private:
// Private Member Functions
//- Disallow default bitwise copy construct
displacementMethodvolumetricBSplinesMotionSolver
(
const displacementMethodvolumetricBSplinesMotionSolver&
) = delete;
//- Disallow default bitwise assignment
void operator=
(
const displacementMethodvolumetricBSplinesMotionSolver&
) = delete;
public:
//- Runtime type information
TypeName("displacementMethodvolumetricBSplinesMotionSolver");
// Constructors
//- Construct from components
displacementMethodvolumetricBSplinesMotionSolver
(
fvMesh& mesh,
const labelList& patchIDs
);
//- Destructor
virtual ~displacementMethodvolumetricBSplinesMotionSolver() = default;
// Member Functions
//- Set motion filed related to model based on given motion
void setMotionField(const pointVectorField& pointMovement);
//- Set motion filed related to model based on given motion
void setMotionField(const volVectorField& cellMovement);
//- Set control field as a vectorField. For methods working with
//- parameters (RBF etc)
void setControlField(const vectorField& controlField);
//- Set control field as a vectorField. For methods working with
//- parameters (RBF etc)
void setControlField(const scalarField& controlField);
//- Bound control field in certain directions etc. For methods working
//- with parameters (RBF etc)
void boundControlField(vectorField& controlField);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,271 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "elasticityMotionSolver.H"
#include "motionInterpolation.H"
#include "wallDist.H"
#include "fixedValuePointPatchFields.H"
#include "fvMatrices.H"
#include "fvcDiv.H"
#include "fvmDiv.H"
#include "fvmDiv.H"
#include "fvmLaplacian.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(elasticityMotionSolver, 1);
addToRunTimeSelectionTable
(
motionSolver,
elasticityMotionSolver,
dictionary
);
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
void Foam::elasticityMotionSolver::setBoundaryConditions()
{
// Adjust boundary conditions based on the steps to be executed
forAll(pointMotionU_.boundaryField(), patchI)
{
pointPatchVectorField& pointBCs =
pointMotionU_.boundaryFieldRef()[patchI];
if (isA<fixedValuePointPatchVectorField>(pointBCs))
{
auto& fixedValueBCs =
refCast<fixedValuePointPatchVectorField>(pointBCs);
fixedValueBCs == fixedValueBCs/scalar(nSteps_);
}
}
// Copy boundary conditions to internalField
// Needed for interpolation to faces
pointMotionU_.boundaryFieldRef().updateCoeffs();
// Interpolate boundary conditions from points to faces
forAll(cellMotionU_.boundaryField(), pI)
{
fvPatchVectorField& bField = cellMotionU_.boundaryFieldRef()[pI];
if (isA<fixedValueFvPatchVectorField>(bField))
{
const pointField& points = fvMesh_.points();
const polyPatch& patch = mesh().boundaryMesh()[pI];
forAll(bField, fI)
{
bField[fI] = patch[fI].average(points, pointMotionU_);
}
}
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::elasticityMotionSolver::elasticityMotionSolver
(
const polyMesh& mesh,
const IOdictionary& dict
)
:
motionSolver(mesh, dict, typeName),
fvMesh_
(
const_cast<fvMesh&>
(
refCast<const fvMesh>(mesh)
)
),
pointMotionU_
(
IOobject
(
"pointMotionU",
mesh.time().timeName(),
mesh,
IOobject::READ_IF_PRESENT,
IOobject::AUTO_WRITE
),
pointMesh::New(mesh),
dimensionedVector(dimless, Zero),
fixedValuePointPatchVectorField::typeName
),
cellMotionU_
(
IOobject
(
"cellMotionU",
mesh.time().timeName(),
mesh,
IOobject::READ_IF_PRESENT,
IOobject::AUTO_WRITE
),
fvMesh_,
dimensionedVector
(
"cellMotionU",
pointMotionU_.dimensions(),
vector::zero
),
pointMotionU_.boundaryField().types()
),
interpolationPtr_
(
coeffDict().found("interpolation")
? motionInterpolation::New(fvMesh_, coeffDict().lookup("interpolation"))
: motionInterpolation::New(fvMesh_)
),
E_
(
IOobject
(
"mu",
mesh.time().timeName(),
mesh,
IOobject::NO_READ,
IOobject::NO_WRITE
),
fvMesh_,
dimensionedScalar(dimless, Zero),
zeroGradientFvPatchScalarField::typeName
),
exponent_(this->coeffDict().get<scalar>("exponent")),
nSteps_(this->coeffDict().get<label>("steps")),
nIters_(this->coeffDict().get<label>("iters")),
tolerance_(this->coeffDict().get<scalar>("tolerance"))
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::tmp<Foam::pointField> Foam::elasticityMotionSolver::curPoints() const
{
tmp<pointField> tnewPoints(new pointField(mesh().points()));
return tnewPoints;
}
void Foam::elasticityMotionSolver::solve()
{
// Re-init to zero
cellMotionU_.primitiveFieldRef() = vector::zero;
// Adjust boundary conditions based on the number of steps to be executed
// and interpolate to faces
setBoundaryConditions();
// Solve the elasticity equations in a stepped manner
for (label istep = 0; istep < nSteps_; ++istep)
{
Info<< "Step " << istep << endl;
// Update diffusivity
const scalarField& vols = mesh().cellVolumes();
E_.primitiveFieldRef() = 1./pow(vols, exponent_);
E_.correctBoundaryConditions();
for (label iter = 0; iter < nIters_; ++iter)
{
Info<< "Iteration " << iter << endl;
cellMotionU_.storePrevIter();
fvVectorMatrix dEqn
(
fvm::laplacian(2*E_, cellMotionU_)
+ fvc::div(2*E_*T(fvc::grad(cellMotionU_)))
- fvc::div(E_*fvc::div(cellMotionU_)*tensor::I)
);
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 for step "
<< istep
<< " iteration " << iter << "***\n\n";
break;
}
}
// Interpolate from cells to points
interpolationPtr_->interpolate(cellMotionU_, pointMotionU_);
vectorField newPoints
(
mesh().points() + pointMotionU_.primitiveFieldRef()
);
// Move points and check mesh
fvMesh_.movePoints(newPoints);
fvMesh_.checkMesh(true);
if (debug)
{
Info<< " Writing new mesh points " << endl;
pointIOField points
(
IOobject
(
"points",
mesh().pointsInstance(),
mesh().meshSubDir,
mesh(),
IOobject::NO_READ,
IOobject::NO_WRITE
),
mesh().points()
);
points.write();
}
}
}
void Foam::elasticityMotionSolver::movePoints(const pointField&)
{
// Do nothing
}
void Foam::elasticityMotionSolver::updateMesh(const mapPolyMesh&)
{
// Do nothing
}
// ************************************************************************* //

View File

@ -0,0 +1,183 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Class
Foam::elasticityMotionSolver
Description
Mesh deformation based on the linear elasticity equations.
The boundary displacement is set as a boundary condition
on the pointMotionU field.
Reference:
\verbatim
Dwight, R. P., (2009).
Robust Mesh Deformation using the Linear Elasticity Equations.
Computational Fluid Dynamics 2006, 401-406.
Springer Berlin Heidelberg.
\endverbatim
SourceFiles
elasticityMotionSolver.C
\*---------------------------------------------------------------------------*/
#ifndef elasticityMotionSolver_H
#define elasticityMotionSolver_H
#include "motionSolver.H"
#include "volFields.H"
#include "pointFields.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward class declarations
class motionInterpolation;
class mapPolyMesh;
/*---------------------------------------------------------------------------*\
Class elasticityMotionSolver Declaration
\*---------------------------------------------------------------------------*/
class elasticityMotionSolver
:
public motionSolver
{
protected:
// Protected data
//- Since the mesh deformation is broken down to multiple steps,
//- mesh points need to be moved here.
//- Hence, the non-const mesh reference
fvMesh& fvMesh_;
pointVectorField pointMotionU_;
volVectorField cellMotionU_;
//- Interpolation used to transfer cell displacement to the points
autoPtr<motionInterpolation> interpolationPtr_;
//- Inverse cell volume diffusivity
volScalarField E_;
//- Exponent to stiffen highly morphed cells
scalar exponent_;
//- Intermidiate steps to solve the PDEs
label nSteps_;
//- Number of laplacian iterations per solution step
label nIters_;
//- Residual threshold
scalar tolerance_;
// Protected Member Functions
//- Set boundary condtions 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 Member Functions
//- No copy construct
elasticityMotionSolver(const elasticityMotionSolver&) = delete;
//- No copy assignment
void operator=(const elasticityMotionSolver&) = delete;
public:
//- Runtime type information
TypeName("elasticityMotionSolver");
// Constructors
//- Construct from mesh and dictionary
elasticityMotionSolver
(
const polyMesh& mesh,
const IOdictionary& dict
);
//- Destructor
virtual ~elasticityMotionSolver() = default;
// Member Functions
//- 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. Mesh is actually moved in solve()
virtual tmp<pointField> curPoints() const;
//- Solve for motion.
// Does the actual mesh displacement here, since it is broken down
// into multiple steps
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 "elasticityMotionSolverI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,60 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline Foam::pointVectorField& Foam::elasticityMotionSolver::pointMotionU()
{
return pointMotionU_;
}
inline const Foam::pointVectorField&
Foam::elasticityMotionSolver::pointMotionU() const
{
return pointMotionU_;
}
inline Foam::volVectorField& Foam::elasticityMotionSolver::cellMotionU()
{
return cellMotionU_;
}
inline const Foam::volVectorField&
Foam::elasticityMotionSolver::cellMotionU() const
{
return cellMotionU_;
}
// ************************************************************************* //

View File

@ -0,0 +1,189 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "laplacianMotionSolver.H"
#include "motionInterpolation.H"
#include "addToRunTimeSelectionTable.H"
#include "fvmLaplacian.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(laplacianMotionSolver, 1);
addToRunTimeSelectionTable
(
motionSolver,
laplacianMotionSolver,
dictionary
);
}
// * * * * * * * * * * * * 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 * * * * * * * * * * * * * * //
Foam::laplacianMotionSolver::laplacianMotionSolver
(
const polyMesh& mesh,
const IOdictionary& dict
)
:
motionSolver(mesh, dict, typeName),
fvMotionSolver(mesh),
pointMotionU_
(
IOobject
(
"pointMotionU",
mesh.time().timeName(),
mesh,
IOobject::READ_IF_PRESENT,
IOobject::AUTO_WRITE
),
pointMesh::New(mesh),
dimensionedVector(dimless, Zero),
fixedValuePointPatchVectorField::typeName
),
cellMotionU_
(
IOobject
(
"cellMotionU",
mesh.time().timeName(),
mesh,
IOobject::READ_IF_PRESENT,
IOobject::AUTO_WRITE
),
fvMesh_,
dimensionedVector
(
"cellMotionU",
pointMotionU_.dimensions(),
vector::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"))
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::tmp<Foam::pointField> Foam::laplacianMotionSolver::curPoints() const
{
interpolationPtr_->interpolate
(
cellMotionU_,
pointMotionU_
);
tmp<vectorField> tcurPoints
(
fvMesh_.points() + pointMotionU_.internalField()
);
twoDCorrectPoints(tcurPoints.ref());
return tcurPoints;
}
void Foam::laplacianMotionSolver::solve()
{
setBoundaryConditions();
// Iteratively solve the Laplace equation, to account for non-orthogonality
for (label iter = 0; iter < nIters_; ++iter)
{
Info<< "Iteration " << iter << endl;
fvVectorMatrix dEqn
(
fvm::laplacian(cellMotionU_)
);
scalar residual = mag(dEqn.solve().initialResidual());
// Print execution time
fvMesh_.time().printExecutionTime(Info);
// Check convergence
if (residual < tolerance_)
{
Info<< "\n***Reached mesh movement convergence limit at"
<< " iteration " << iter << "***\n\n";
break;
}
}
}
void Foam::laplacianMotionSolver::movePoints(const pointField&)
{
// Do nothing
}
void Foam::laplacianMotionSolver::updateMesh(const mapPolyMesh&)
{
// Do nothing
}
// ************************************************************************* //

View File

@ -0,0 +1,167 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Class
Foam::laplacianMotionSolver
Description
Similar to velocityLaplacian but iteratively solves the mesh displacement
PDEs to account for non-orthogonality.
The boundary displacement is set as a boundary condition
on pointMotionU; the latter is generated automatically if not found.
Assumes uniform diffusivity
SourceFiles
laplacianMotionSolver.C
\*---------------------------------------------------------------------------*/
#ifndef laplacianMotionSolver_H
#define laplacianMotionSolver_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 laplacianMotionSolver Declaration
\*---------------------------------------------------------------------------*/
class laplacianMotionSolver
:
public motionSolver,
public fvMotionSolver
{
protected:
// Protected data
mutable pointVectorField pointMotionU_;
volVectorField cellMotionU_;
//- Interpolation used to transfer cell displacement to the points
autoPtr<motionInterpolation> interpolationPtr_;
//- Number of laplacian iterations per solution step
label nIters_;
//- Residual threshold
scalar tolerance_;
// Protected Member Functions
//- Set boundary condtions 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 Member Functions
//- Disallow default bitwise copy construct
laplacianMotionSolver(const laplacianMotionSolver&) = delete;
//- Disallow default bitwise assignment
void operator=(const laplacianMotionSolver&) = delete;
public:
//- Runtime type information
TypeName("laplacianMotionSolver");
// Constructors
//- Construct from mesh and dictionary
laplacianMotionSolver
(
const polyMesh& mesh,
const IOdictionary& dict
);
//- Destructor
virtual ~laplacianMotionSolver() = default;
// Member Functions
//- 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 "laplacianMotionSolverI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,61 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline Foam::pointVectorField& Foam::laplacianMotionSolver::pointMotionU()
{
return pointMotionU_;
}
inline const Foam::pointVectorField&
Foam::laplacianMotionSolver::pointMotionU() const
{
return pointMotionU_;
}
inline Foam::volVectorField& Foam::laplacianMotionSolver::cellMotionU()
{
return cellMotionU_;
}
inline const Foam::volVectorField&
Foam::laplacianMotionSolver::cellMotionU() const
{
return cellMotionU_;
}
// ************************************************************************* //

View File

@ -0,0 +1,154 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "volumetricBSplinesMotionSolver.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(volumetricBSplinesMotionSolver, 0);
addToRunTimeSelectionTable
(
motionSolver,
volumetricBSplinesMotionSolver,
dictionary
);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::volumetricBSplinesMotionSolver::volumetricBSplinesMotionSolver
(
const polyMesh& mesh,
const IOdictionary& dict
)
:
motionSolver(mesh, dict, typeName),
volBSplinesBase_
(
const_cast<volBSplinesBase&>
(
volBSplinesBase::New(refCast<fvMesh>(const_cast<polyMesh&>(mesh)))
)
),
controlPointsMovement_
(
volBSplinesBase_.getTotalControlPointsNumber(),
vector::zero
)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::tmp<Foam::pointField>
Foam::volumetricBSplinesMotionSolver::curPoints() const
{
tmp<vectorField> tPointMovement(new vectorField(mesh().points()));
vectorField& pointMovement = tPointMovement.ref();
label pastControlPoints(0);
PtrList<NURBS3DVolume>& boxes = volBSplinesBase_.boxesRef();
forAll(boxes, iNURB)
{
const label nb = boxes[iNURB].getControlPoints().size();
vectorField localControlPointsMovement(nb, vector::zero);
forAll(localControlPointsMovement, iCP)
{
localControlPointsMovement[iCP] =
controlPointsMovement_[pastControlPoints + iCP];
}
tmp<vectorField>
partialMovement
(
boxes[iNURB].computeNewPoints
(
localControlPointsMovement
)
);
pointMovement += partialMovement() - mesh().points();
pastControlPoints += nb;
}
return tPointMovement;
}
void Foam::volumetricBSplinesMotionSolver::solve()
{
// Do nothing
}
void Foam::volumetricBSplinesMotionSolver::movePoints(const pointField&)
{
// Do nothing
}
void Foam::volumetricBSplinesMotionSolver::updateMesh(const mapPolyMesh&)
{
// Do nothing
}
void Foam::volumetricBSplinesMotionSolver::setControlPointsMovement
(
const vectorField& controlPointsMovement
)
{
if (controlPointsMovement_.size() != controlPointsMovement.size())
{
FatalErrorInFunction
<< "Attempting to replace controlPointsMovement with a set of "
<< "different size"
<< exit(FatalError);
}
controlPointsMovement_ = controlPointsMovement;
}
void Foam::volumetricBSplinesMotionSolver::boundControlPointsMovement
(
vectorField& controlPointsMovement
)
{
volBSplinesBase_.boundControlPointsMovement(controlPointsMovement);
}
// ************************************************************************* //

View File

@ -0,0 +1,145 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Class
Foam::volumetricBSplinesMotionSolver
Description
A mesh motion solver based on volumetric B-Splines
SourceFiles
volumetricBSplinesMotionSolver.C
\*---------------------------------------------------------------------------*/
#ifndef volumetricBSplinesMotionSolver_H
#define volumetricBSplinesMotionSolver_H
#include "motionSolver.H"
#include "volBSplinesBase.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
class mapPolyMesh;
/*---------------------------------------------------------------------------*\
Class volumetricBSplinesMotionSolver Declaration
\*---------------------------------------------------------------------------*/
class volumetricBSplinesMotionSolver
:
public motionSolver
{
protected:
// Protected data
//- Reference to the underlaying volumetric B-Splines base
volBSplinesBase& volBSplinesBase_;
//- Movement of the control points
vectorField controlPointsMovement_;
//- Number of control boxes
wordList controlBoxes_;
//- List with volumetric B-splines boxes. No overlapping is supported
mutable List<autoPtr<NURBS3DVolume>> volume_;
//- Number of control boxes
label nBoxes_;
private:
// Private Member Functions
//- Disallow default bitwise copy construct
volumetricBSplinesMotionSolver
(
const volumetricBSplinesMotionSolver&
) = delete;
//- Disallow default bitwise assignment
void operator=(const volumetricBSplinesMotionSolver&) = delete;
public:
//- Runtime type information
TypeName("volumetricBSplinesMotionSolver");
// Constructors
//- Construct from mesh and dictionary
volumetricBSplinesMotionSolver
(
const polyMesh& mesh,
const IOdictionary& dict
);
//- Destructor
virtual ~volumetricBSplinesMotionSolver() = default;
// Member Functions
//- Return point location obtained from the current motion field
virtual tmp<pointField> curPoints() const;
//- Solve for motion/ Does nothing
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&);
//- Set control points movement
void setControlPointsMovement(const vectorField& controlPointsMovement);
//- Bound control points movement
void boundControlPointsMovement(vectorField& controlPointsMovement);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,138 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) Wikki Ltd
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 "pointVolInterpolation.H"
#include "volFields.H"
#include "pointFields.H"
#include "primitiveMesh.H"
#include "emptyFvPatch.H"
#include "globalMeshData.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class Type>
void Foam::pointVolInterpolation::interpolate
(
const GeometricField<Type, pointPatchField, pointMesh>& pf,
GeometricField<Type, fvPatchField, volMesh>& vf
) const
{
DebugInFunction
<< "interpolating field from points to cells"
<< endl;
const FieldField<Field, scalar>& weights = volWeights();
const labelListList& cellPoints = vf.mesh().cellPoints();
// Multiply pointField by weighting factor matrix to create volField
forAll(cellPoints, cellI)
{
vf[cellI] = pTraits<Type>::zero;
const labelList& curCellPoints = cellPoints[cellI];
forAll(curCellPoints, cellPointI)
{
vf[cellI] +=
weights[cellI][cellPointI]*pf[curCellPoints[cellPointI]];
}
}
// Interpolate patch values: over-ride the internal values for the points
// on the patch with the interpolated point values from the faces
const fvBoundaryMesh& bm = vMesh().boundary();
const PtrList<primitivePatchInterpolation>& pi = patchInterpolators();
forAll(bm, patchI)
{
// If the patch is empty, skip it
if (bm[patchI].type() != emptyFvPatch::typeName)
{
vf.boundaryFieldRef()[patchI] =
pi[patchI].pointToFaceInterpolate
(
pf.boundaryField()[patchI].patchInternalField()
);
}
}
vf.correctBoundaryConditions();
DebugInFunction
<< "finished interpolating field from points to cells"
<< endl;
}
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh>>
Foam::pointVolInterpolation::interpolate
(
const GeometricField<Type, pointPatchField, pointMesh>& pf
) const
{
// Construct tmp<pointField>
tmp<GeometricField<Type, fvPatchField, volMesh>> tvf
(
new GeometricField<Type, fvPatchField, volMesh>
(
IOobject
(
"pointVolInterpolate(" + pf.name() + ')',
pf.instance(),
pf.db()
),
vMesh(),
pf.dimensions()
)
);
// Perform interpolation
interpolate(pf, tvf.ref());
return tvf;
}
template<class Type>
Foam::tmp<Foam::GeometricField<Type, Foam::fvPatchField, Foam::volMesh>>
Foam::pointVolInterpolation::interpolate
(
const tmp<GeometricField<Type, pointPatchField, pointMesh>>& tpf
) const
{
// Construct tmp<volField>
tmp<GeometricField<Type, fvPatchField, volMesh>> tvf =
interpolate(tpf());
tpf.clear();
return tvf;
}
// ************************************************************************* //

View File

@ -0,0 +1,225 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) Wikki Ltd
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 "pointVolInterpolation.H"
#include "fvMesh.H"
#include "pointFields.H"
#include "volFields.H"
#include "emptyFvPatch.H"
#include "SubField.H"
#include "demandDrivenData.H"
#include "globalMeshData.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(pointVolInterpolation, 0);
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::pointVolInterpolation::makeWeights() const
{
if (volWeightsPtr_)
{
FatalErrorInFunction
<< "weighting factors already calculated"
<< abort(FatalError);
}
if (debug)
{
Info<< "pointVolInterpolation::makeWeights() : "
<< "constructing weighting factors"
<< endl;
}
const pointField& points = vMesh().points();
const labelListList& cellPoints = vMesh().cellPoints();
const vectorField& cellCentres = vMesh().cellCentres();
// Allocate storage for weighting factors
volWeightsPtr_ = new FieldField<Field, scalar>(cellCentres.size());
FieldField<Field, scalar>& weightingFactors = *volWeightsPtr_;
forAll(weightingFactors, pointi)
{
weightingFactors.set
(
pointi,
new scalarField(cellPoints[pointi].size())
);
}
// Calculate inverse distances between points and cell centres
// and store in weighting factor array
forAll(cellCentres, cellI)
{
const labelList& curCellPoints = cellPoints[cellI];
forAll(curCellPoints, cellPointI)
{
weightingFactors[cellI][cellPointI] = 1.0/
mag
(
cellCentres[cellI] - points[curCellPoints[cellPointI]]
);
}
}
scalarField pointVolSumWeights(cellCentres.size(), Zero);
// Calculate weighting factors using inverse distance weighting
forAll(cellCentres, cellI)
{
const labelList& curCellPoints = cellPoints[cellI];
forAll(curCellPoints, cellPointI)
{
pointVolSumWeights[cellI] += weightingFactors[cellI][cellPointI];
}
}
forAll(cellCentres, cellI)
{
const labelList& curCellPoints = cellPoints[cellI];
forAll(curCellPoints, cellPointI)
{
weightingFactors[cellI][cellPointI] /= pointVolSumWeights[cellI];
}
}
if (debug)
{
Info<< "pointVolInterpolation::makeWeights() : "
<< "finished constructing weighting factors"
<< endl;
}
}
// Do what is neccessary if the mesh has changed topology
void Foam::pointVolInterpolation::clearAddressing() const
{
deleteDemandDrivenData(patchInterpolatorsPtr_);
}
// Do what is neccessary if the mesh has moved
void Foam::pointVolInterpolation::clearGeom() const
{
deleteDemandDrivenData(volWeightsPtr_);
}
const Foam::PtrList<Foam::primitivePatchInterpolation>&
Foam::pointVolInterpolation::patchInterpolators() const
{
if (!patchInterpolatorsPtr_)
{
const fvBoundaryMesh& bdry = vMesh().boundary();
patchInterpolatorsPtr_ =
new PtrList<primitivePatchInterpolation>(bdry.size());
forAll(bdry, patchI)
{
patchInterpolatorsPtr_->set
(
patchI,
new primitivePatchInterpolation(bdry[patchI].patch())
);
}
}
return *patchInterpolatorsPtr_;
}
// * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * //
Foam::pointVolInterpolation::pointVolInterpolation
(
const pointMesh& pm,
const fvMesh& vm
)
:
pointMesh_(pm),
fvMesh_(vm),
volWeightsPtr_(nullptr),
patchInterpolatorsPtr_(nullptr)
{}
// * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * * //
Foam::pointVolInterpolation::~pointVolInterpolation()
{
clearAddressing();
clearGeom();
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
// Return point weights
const Foam::FieldField<Foam::Field, Foam::scalar>&
Foam::pointVolInterpolation::volWeights() const
{
// If weighting factor array not present then construct
if (!volWeightsPtr_)
{
makeWeights();
}
return *volWeightsPtr_;
}
// Do what is neccessary if the mesh has moved
void Foam::pointVolInterpolation::updateTopology()
{
clearAddressing();
clearGeom();
}
// Do what is neccessary if the mesh has moved
bool Foam::pointVolInterpolation::movePoints()
{
clearGeom();
return true;
}
// ************************************************************************* //

View File

@ -0,0 +1,183 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) Wikki Ltd
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::pointVolInterpolation
Description
SourceFiles
pointVolInterpolation.C
pointVolInterpolate.C
\*---------------------------------------------------------------------------*/
#ifndef pointVolInterpolation_H
#define pointVolInterpolation_H
#include "primitiveFieldsFwd.H"
#include "primitivePatchInterpolation.H"
#include "volFieldsFwd.H"
#include "pointFieldsFwd.H"
#include "scalarList.H"
#include "tmp.H"
#include "className.H"
#include "FieldFields.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
class fvMesh;
class pointMesh;
/*---------------------------------------------------------------------------*\
Class pointVolInterpolation Declaration
\*---------------------------------------------------------------------------*/
class pointVolInterpolation
{
// Private data
const pointMesh& pointMesh_;
const fvMesh& fvMesh_;
//- Interpolation scheme weighting factor array.
mutable FieldField<Field, scalar>* volWeightsPtr_;
//- Primitive patch interpolators
mutable PtrList<primitivePatchInterpolation>* patchInterpolatorsPtr_;
// Private member functions
//- Return patch interpolators
const PtrList<primitivePatchInterpolation>& patchInterpolators() const;
//- Construct point weighting factors
void makeWeights() const;
//- Clear addressing
void clearAddressing() const;
//- Clear geometry
void clearGeom() const;
protected:
const pointMesh& pMesh() const
{
return pointMesh_;
}
const fvMesh& vMesh() const
{
return fvMesh_;
}
public:
// Declare name of the class and it's debug switch
ClassName("pointVolInterpolation");
// Constructors
//- Constructor given pointMesh and fvMesh.
pointVolInterpolation(const pointMesh&, const fvMesh&);
// Destructor
~pointVolInterpolation();
// Member functions
// Access
//- Return reference to weights arrays.
// This also constructs the weighting factors if neccessary.
const FieldField<Field, scalar>& volWeights() const;
// Edit
//- Update mesh topology using the morph engine
void updateTopology();
//- Correct weighting factors for moving mesh.
bool movePoints();
// Interpolation functions
//- Interpolate from pointField to volField
// using inverse distance weighting
template<class Type>
void interpolate
(
const GeometricField<Type, pointPatchField, pointMesh>&,
GeometricField<Type, fvPatchField, volMesh>&
) const;
//- Interpolate pointField returning volField
// using inverse distance weighting
template<class Type>
tmp<GeometricField<Type, fvPatchField, volMesh>> interpolate
(
const GeometricField<Type, pointPatchField, pointMesh>&
) const;
//- Interpolate tmp<pointField> returning volField
// using inverse distance weighting
template<class Type>
tmp<GeometricField<Type, fvPatchField, volMesh>> interpolate
(
const tmp<GeometricField<Type, pointPatchField, pointMesh>>&
) const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
# include "pointVolInterpolate.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -171,12 +171,40 @@ void objectiveManager::update()
}
void objectiveManager::updateOrNullify()
{
//- Update contributions to adjoint if true, otherwise return nulls
for (objective& obj : objectives_)
{
if (obj.isWithinIntegrationTime())
{
obj.update();
}
else
{
obj.nullify();
}
}
}
void objectiveManager::incrementIntegrationTimes(const scalar timeSpan)
{
// Update start and end integration times by adding the timeSpan
// of the optimisation cycle
for (objective& obj : objectives_)
{
obj.incrementIntegrationTimes(timeSpan);
}
}
scalar objectiveManager::print()
{
scalar objValue(Zero);
for (objective& obj : objectives_)
{
scalar cost = obj.J();
scalar cost = obj.JCycle();
scalar weight = obj.weight();
objValue += weight*cost;
@ -236,6 +264,21 @@ const word& objectiveManager::primalSolverName() const
}
void objectiveManager::checkIntegrationTimes() const
{
for (const objective& obj : objectives_)
{
if (!obj.hasIntegrationStartTime() || !obj.hasIntegrationEndTime())
{
FatalErrorInFunction()
<< "Objective function " << obj.objectiveName()
<< " does not have a defined integration start or end time "
<< exit(FatalError);
}
}
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam

View File

@ -136,6 +136,12 @@ public:
//- Update objective function related values
void update();
//- Update contributions to adjoint if true, otherwise return nulls
void updateOrNullify();
//- Increment integration times by the optimisation cycle time-span
void incrementIntegrationTimes(const scalar timeSpan);
//- Print to screen
scalar print();
@ -161,6 +167,9 @@ public:
//- Return name of the primalSolver
const word& primalSolverName() const;
//- Check integration times for unsteady runs
void checkIntegrationTimes() const;
//- Add contribution to adjoint momentum PDEs
virtual void addUaEqnSource(fvVectorMatrix& UaEqn) = 0;

View File

@ -0,0 +1,110 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "objectiveForceTarget.H"
#include "addToRunTimeSelectionTable.H"
#include "IOmanip.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace objectives
{
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
defineTypeNameAndDebug(objectiveForceTarget, 0);
addToRunTimeSelectionTable
(
objectiveIncompressible,
objectiveForceTarget,
dictionary
);
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
objectiveForceTarget::objectiveForceTarget
(
const fvMesh& mesh,
const dictionary& dict,
const word& adjointSolverName,
const word& primalSolverName
)
:
objectiveForce(mesh, dict, adjointSolverName, primalSolverName),
force_(Zero),
target_(dict.get<scalar>("target"))
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
scalar objectiveForceTarget::J()
{
force_ = objectiveForce::J();
J_ = force_ - target_;
return J_;
}
void objectiveForceTarget::write() const
{
if (Pstream::master())
{
// File is opened only upon invocation of the write function
// in order to avoid various instantiations of the same objective
// opening the same file
unsigned int width = IOstream::defaultPrecision() + 5;
if (objFunctionFilePtr_.empty())
{
setObjectiveFilePtr();
objFunctionFilePtr_()
<< setw(3) << "#" << " "
<< setw(width) << "J" << " "
<< setw(width) << "Force" << " "
<< setw(width) << "Target" << endl;
};
objFunctionFilePtr_()
<< setw(3) << mesh_.time().value() << " "
<< setw(width) << J_ << " "
<< setw(width) << force_ << " "
<< setw(width) << target_ << endl;
}
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace objectives
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,108 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Class
Foam::objectives::objectiveForceTarget
Description
SourceFiles
objectiveForceTarget.C
\*---------------------------------------------------------------------------*/
#ifndef objectiveForceTarget_H
#define objectiveForceTarget_H
#include "objectiveForce.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace objectives
{
/*---------------------------------------------------------------------------*\
Class objectiveForceTarget Declaration
\*---------------------------------------------------------------------------*/
class objectiveForceTarget
:
public objectiveForce
{
// Private data
scalar force_;
scalar target_;
public:
//- Runtime type information
TypeName("forceTarget");
// Constructors
//- Construct from components
objectiveForceTarget
(
const fvMesh& mesh,
const dictionary& dict,
const word& adjointSolverName,
const word& primalSolverName
);
//- Destructor
virtual ~objectiveForceTarget() = default;
// Member Functions
//- Return the objective function value
scalar J();
//- Write objective value
void write() const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace objectives
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -63,7 +63,7 @@ objectiveIncompressible::objectiveIncompressible
vars_
(
mesh.lookupObject<incompressiblePrimalSolver>(primalSolverName).
getVars()
getIncoVars()
),
// Initialize pointers to nullptr.
@ -421,6 +421,67 @@ void objectiveIncompressible::update()
}
void objectiveIncompressible::nullify()
{
if (!nullified_)
{
if (hasdJdv())
{
dJdvPtr_() == dimensionedVector(dJdvPtr_().dimensions(), Zero);
}
if (hasdJdp())
{
dJdpPtr_() == dimensionedScalar(dJdpPtr_().dimensions(), Zero);
}
if (hasdJdT())
{
dJdTPtr_() == dimensionedScalar(dJdTPtr_().dimensions(), Zero);
}
if (hasdJdTMVar1())
{
dJdTMvar1Ptr_() ==
dimensionedScalar(dJdTMvar1Ptr_().dimensions(), Zero);
}
if (hasdJdTMVar2())
{
dJdTMvar2Ptr_() ==
dimensionedScalar(dJdTMvar2Ptr_().dimensions(), Zero);
}
if (hasBoundarydJdv())
{
bdJdvPtr_() == vector::zero;
}
if (hasBoundarydJdvn())
{
bdJdvnPtr_() == scalar(0);
}
if (hasBoundarydJdvt())
{
bdJdvtPtr_() == vector::zero;
}
if (hasBoundarydJdp())
{
bdJdpPtr_() == vector::zero;
}
if (hasBoundarydJdT())
{
bdJdTPtr_() == scalar(0);
}
if (hasBoundarydJdTMVar1())
{
bdJdTMvar1Ptr_() == scalar(0);
}
if (hasBoundarydJdTMVar2())
{
bdJdTMvar2Ptr_() == scalar(0);
}
// Nullify geometric fields and sets nullified_ to true
objective::nullify();
}
}
void objectiveIncompressible::write() const
{
objective::write();

View File

@ -226,7 +226,10 @@ public:
const boundaryScalarField& boundarydJdTMvar2();
//- Update objective function derivatives
void update();
virtual void update();
//- Update objective function derivatives
virtual void nullify();
//- Update vol and boundary fields and derivatives
// Do nothing in the base. The relevant ones should be overwritten
@ -303,18 +306,18 @@ public:
virtual void write() const;
//- Inline functions for checking whether pointers are set or not
inline bool hasdJdv();
inline bool hasdJdp();
inline bool hasdJdT();
inline bool hasdJdTMVar1();
inline bool hasdJdTMVar2();
inline bool hasBoundarydJdv();
inline bool hasBoundarydJdvn();
inline bool hasBoundarydJdvt();
inline bool hasBoundarydJdp();
inline bool hasBoundarydJdT();
inline bool hasBoundarydJdTMVar1();
inline bool hasBoundarydJdTMVar2();
inline bool hasdJdv() const;
inline bool hasdJdp() const;
inline bool hasdJdT() const;
inline bool hasdJdTMVar1() const;
inline bool hasdJdTMVar2() const;
inline bool hasBoundarydJdv() const;
inline bool hasBoundarydJdvn() const;
inline bool hasBoundarydJdvt() const;
inline bool hasBoundarydJdp() const;
inline bool hasBoundarydJdT() const;
inline bool hasBoundarydJdTMVar1() const;
inline bool hasBoundarydJdTMVar2() const;
};

View File

@ -30,73 +30,73 @@ License
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline bool Foam::objectiveIncompressible::hasdJdv()
inline bool Foam::objectiveIncompressible::hasdJdv() const
{
return dJdvPtr_.valid();
}
inline bool Foam::objectiveIncompressible::hasdJdp()
inline bool Foam::objectiveIncompressible::hasdJdp() const
{
return dJdpPtr_.valid();
}
inline bool Foam::objectiveIncompressible::hasdJdT()
inline bool Foam::objectiveIncompressible::hasdJdT() const
{
return dJdTPtr_.valid();
}
inline bool Foam::objectiveIncompressible::hasdJdTMVar1()
inline bool Foam::objectiveIncompressible::hasdJdTMVar1() const
{
return dJdTMvar1Ptr_.valid();
}
inline bool Foam::objectiveIncompressible::hasdJdTMVar2()
inline bool Foam::objectiveIncompressible::hasdJdTMVar2() const
{
return dJdTMvar2Ptr_.valid();
}
inline bool Foam::objectiveIncompressible::hasBoundarydJdv()
inline bool Foam::objectiveIncompressible::hasBoundarydJdv() const
{
return bdJdvPtr_.valid();
}
inline bool Foam::objectiveIncompressible::hasBoundarydJdvn()
inline bool Foam::objectiveIncompressible::hasBoundarydJdvn() const
{
return bdJdvnPtr_.valid();
}
inline bool Foam::objectiveIncompressible::hasBoundarydJdvt()
inline bool Foam::objectiveIncompressible::hasBoundarydJdvt() const
{
return bdJdvtPtr_.valid();
}
inline bool Foam::objectiveIncompressible::hasBoundarydJdp()
inline bool Foam::objectiveIncompressible::hasBoundarydJdp() const
{
return bdJdpPtr_.valid();
}
inline bool Foam::objectiveIncompressible::hasBoundarydJdT()
inline bool Foam::objectiveIncompressible::hasBoundarydJdT() const
{
return bdJdTPtr_.valid();
}
inline bool Foam::objectiveIncompressible::hasBoundarydJdTMVar1()
inline bool Foam::objectiveIncompressible::hasBoundarydJdTMVar1() const
{
return bdJdTMvar1Ptr_.valid();
}
inline bool Foam::objectiveIncompressible::hasBoundarydJdTMVar2()
inline bool Foam::objectiveIncompressible::hasBoundarydJdTMVar2() const
{
return bdJdTMvar2Ptr_.valid();
}

View File

@ -0,0 +1,168 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "objectivePartialVolume.H"
#include "createZeroField.H"
#include "IOmanip.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace objectives
{
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
defineTypeNameAndDebug(objectivePartialVolume, 1);
addToRunTimeSelectionTable
(
objectiveIncompressible,
objectivePartialVolume,
dictionary
);
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
objectivePartialVolume::objectivePartialVolume
(
const fvMesh& mesh,
const dictionary& dict,
const word& adjointSolverName,
const word& primalSolverName
)
:
objectiveIncompressible(mesh, dict, adjointSolverName, primalSolverName),
initVol_(Zero),
objectivePatches_
(
mesh_.boundaryMesh().patchSet
(
wordReList(dict.get<wordRes>("patches"))
)
)
{
// Read target volume if present. Else use the current one as a target
if (dict.found("initialVolume"))
{
initVol_ = dict.get<scalar>("initialVolume");
}
else
{
const scalar oneThird(1.0/3.0);
forAllConstIters(objectivePatches_, iter)
{
label patchI = iter.key();
const fvPatch& patch = mesh_.boundary()[patchI];
initVol_ -= oneThird*gSum(patch.Sf() & patch.Cf());
}
}
// Allocate boundary field pointers
bdxdbDirectMultPtr_.reset(createZeroBoundaryPtr<vector>(mesh_));
bdSdbMultPtr_.reset(createZeroBoundaryPtr<vector>(mesh_));
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
scalar objectivePartialVolume::J()
{
J_ = Zero;
const scalar oneThird(1.0/3.0);
forAllConstIters(objectivePatches_, iter)
{
label patchI = iter.key();
const fvPatch& patch = mesh_.boundary()[patchI];
J_ -= oneThird*gSum(patch.Sf() & patch.Cf());
}
J_ -= initVol_;
J_ /= initVol_;
return J_;
}
void objectivePartialVolume::update_dxdbDirectMultiplier()
{
const scalar oneThird(1.0/3.0);
forAllConstIter(labelHashSet, objectivePatches_, iter)
{
label pI = iter.key();
const fvPatch& patch = mesh_.boundary()[pI];
tmp<vectorField> tnf = patch.nf();
const vectorField& nf = tnf();
bdxdbDirectMultPtr_()[pI] = -oneThird*nf/initVol_;
}
}
void objectivePartialVolume::update_dSdbMultiplier()
{
const scalar oneThird(1.0/3.0);
forAllConstIter(labelHashSet, objectivePatches_, iter)
{
label pI = iter.key();
const fvPatch& patch = mesh_.boundary()[pI];
bdSdbMultPtr_()[pI] = -oneThird*patch.Cf()/initVol_;
}
}
void objectivePartialVolume::write() const
{
if (Pstream::master())
{
// File is opened only upon invocation of the write function
// in order to avoid various instantiations of the same objective
// opening the same file
unsigned int width = IOstream::defaultPrecision() + 6;
if (objFunctionFilePtr_.empty())
{
setObjectiveFilePtr();
objFunctionFilePtr_() << setw(4) << "#" << " ";
objFunctionFilePtr_() << setw(width) << "(V - VInit)/VInit" << " ";
objFunctionFilePtr_() << setw(width) << "VInit" << endl;
}
objFunctionFilePtr_() << setw(4) << mesh_.time().value() << " ";
objFunctionFilePtr_() << setw(width) << J_ << " ";
objFunctionFilePtr_() << setw(width) << initVol_ << endl;
}
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace objectives
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,115 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Class
Foam::objectives::objectivePartialVolume
Description
SourceFiles
objectivePartialVolume.C
\*---------------------------------------------------------------------------*/
#ifndef objectivePartialVolume_H
#define objectivePartialVolume_H
#include "objectiveIncompressible.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace objectives
{
/*---------------------------------------------------------------------------*\
Class objectivePartialVolume Declaration
\*---------------------------------------------------------------------------*/
class objectivePartialVolume
:
public objectiveIncompressible
{
// Private data
scalar initVol_;
labelHashSet objectivePatches_;
public:
//- Runtime type information
TypeName("partialVolume");
// Constructors
//- from components
objectivePartialVolume
(
const fvMesh& mesh,
const dictionary& dict,
const word& adjointSolverName,
const word& primalSolverName
);
//- Destructor
virtual ~objectivePartialVolume() = default;
// Member Functions
//- Return the objective function value
scalar J();
//- Update d (x) / db multiplier. Surface and volume-based sensitivity
//- term
void update_dxdbDirectMultiplier();
//- Update d (normal dS) / db multiplier. Surface and volume-based
//- sensitivity term
void update_dSdbMultiplier();
//- Write objective function history
void write() const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace objectivePartialVolume
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -112,11 +112,15 @@ objective::objective
primalSolverName_(primalSolverName),
objectiveName_(dict.dictName()),
computeMeanFields_(false), // is reset in derived classes
nullified_(false),
J_(Zero),
JMean_(Zero),
weight_(Zero),
integrationStartTimePtr_(nullptr),
integrationEndTimePtr_(nullptr),
// Initialize pointers to nullptr.
// Not all of them are required for each objective function.
// Each child should allocate whatever is needed.
@ -138,6 +142,37 @@ objective::objective
meanValueFilePtr_(nullptr)
{
makeFolder();
// Read integration start and end times, if present.
// For unsteady runs only
if (dict.found("integrationStartTime"))
{
integrationStartTimePtr_.reset
(
new scalar(dict.get<scalar>("integrationStartTime"))
);
}
if (dict.found("integrationEndTime"))
{
integrationEndTimePtr_.reset
(
new scalar(dict.get<scalar>("integrationEndTime"))
);
}
// Read JMean from dictionary, if present
IOobject headObjectiveIODict
(
"objectiveDict",
mesh_.time().timeName(),
"uniform",
mesh_,
IOobject::READ_IF_PRESENT,
IOobject::NO_WRITE
);
if (headObjectiveIODict.typeHeaderOk<IOdictionary>(false))
{
JMean_ = IOdictionary(headObjectiveIODict).get<scalar>("JMean");
}
}
@ -187,6 +222,21 @@ bool objective::readDict(const dictionary& dict)
}
scalar objective::JCycle() const
{
scalar J(J_);
if
(
computeMeanFields_
|| (hasIntegrationStartTime() && hasIntegrationEndTime())
)
{
J = JMean_;
}
return J;
}
void objective::updateNormalizationFactor()
{
// Does nothing in base
@ -210,12 +260,71 @@ void objective::accumulateJMean(solverControl& solverControl)
}
void objective::accumulateJMean()
{
if (hasIntegrationStartTime() && hasIntegrationEndTime())
{
const scalar time = mesh_.time().value();
if (isWithinIntegrationTime())
{
const scalar dt = mesh_.time().deltaT().value();
const scalar elapsedTime = time - integrationStartTimePtr_();
const scalar denom = elapsedTime + dt;
JMean_ = (JMean_*elapsedTime + J_*dt)/denom;
}
}
else
{
FatalErrorInFunction
<< "Unallocated integration start or end time"
<< exit(FatalError);
}
}
scalar objective::weight() const
{
return weight_;
}
bool objective::isWithinIntegrationTime() const
{
if (hasIntegrationStartTime() && hasIntegrationEndTime())
{
const scalar time = mesh_.time().value();
return
(
time >= integrationStartTimePtr_()
&& time <= integrationEndTimePtr_()
);
}
else
{
FatalErrorInFunction
<< "Unallocated integration start or end time"
<< exit(FatalError);
}
return false;
}
void objective::incrementIntegrationTimes(const scalar timeSpan)
{
if (hasIntegrationStartTime() && hasIntegrationEndTime())
{
integrationStartTimePtr_() += timeSpan;
integrationEndTimePtr_() += timeSpan;
}
else
{
FatalErrorInFunction
<< "Unallocated integration start or end time"
<< exit(FatalError);
}
}
const volScalarField& objective::dJdb()
{
if (dJdbPtr_.empty())
@ -426,6 +535,61 @@ const volTensorField& objective::gradDxDbMultiplier()
}
void objective::nullify()
{
if (!nullified_)
{
if (hasdJdb())
{
dJdbPtr_() == dimensionedScalar(dJdbPtr_().dimensions(), Zero);
}
if (hasBoundarydJdb())
{
bdJdbPtr_() == vector::zero;
}
if (hasdSdbMult())
{
bdSdbMultPtr_() == vector::zero;
}
if (hasdndbMult())
{
bdndbMultPtr_() == vector::zero;
}
if (hasdxdbMult())
{
bdxdbMultPtr_() == vector::zero;
}
if (hasdxdbDirectMult())
{
bdxdbDirectMultPtr_() == vector::zero;
}
if (hasBoundaryEdgeContribution())
{
for (Field<vectorField>& field : bEdgeContribution_())
{
field = vector::zero;
}
}
if (hasBoundarydJdStress())
{
bdJdStressPtr_() == tensor::zero;
}
if (hasDivDxDbMult())
{
divDxDbMultPtr_() ==
dimensionedScalar(divDxDbMultPtr_().dimensions(), Zero);
}
if (hasGradDxDbMult())
{
gradDxDbMultPtr_() ==
dimensionedTensor(gradDxDbMultPtr_().dimensions(), Zero);
}
nullified_ = true;
}
}
void objective::write() const
{
if (Pstream::master())
@ -465,7 +629,12 @@ void objective::writeMeanValue() const
if (Pstream::master())
{
// Write mean value if necessary
if (computeMeanFields_)
// Covers both steady and unsteady runs
if
(
computeMeanFields_
|| (hasIntegrationStartTime() && hasIntegrationEndTime())
)
{
// File is opened only upon invocation of the write function
// in order to avoid various instantiations of the same objective
@ -479,6 +648,22 @@ void objective::writeMeanValue() const
<< mesh_.time().value() << tab << JMean_ << endl;
}
}
// Write mean value under time/uniform, to allow for lineSearch to work
// appropriately in continuation runs, when field averaging is used
IOdictionary objectiveDict
(
IOobject
(
"objectiveDict",
mesh_.time().timeName(),
"uniform",
mesh_,
IOobject::NO_READ,
IOobject::NO_WRITE
)
);
objectiveDict.add<scalar>("JMean", JMean_);
objectiveDict.regIOobject::write();
}

View File

@ -69,12 +69,17 @@ protected:
const word primalSolverName_;
const word objectiveName_;
bool computeMeanFields_;
bool nullified_;
// Objective function value and weight
scalar J_;
scalar JMean_; //average value
scalar weight_;
// Objective integration start and end times (for unsteady flows)
autoPtr<scalar> integrationStartTimePtr_;
autoPtr<scalar> integrationEndTimePtr_;
// Contribution to field sensitivity derivatives
// Topology optimisation
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@ -219,15 +224,30 @@ public:
virtual bool readDict(const dictionary& dict);
//- Return the objective function value
//- Return the instantaneous objective function value
virtual scalar J() = 0;
//- Return the mean objective function value, if it exists,
//- otherwise the mean one
scalar JCycle() const;
//- Accumulate contribution for the mean objective value
// For steady-state runs
void accumulateJMean(solverControl& solverControl);
//- Accumulate contribution for the mean objective value
// For unsteady runs
void accumulateJMean();
//- Return the objective function weight
scalar weight() const;
//- Check whether this is an objective integration time
bool isWithinIntegrationTime() const;
//- Increment integration times
void incrementIntegrationTimes(const scalar timeSpan);
//- Contribution to field sensitivities
const volScalarField& dJdb();
@ -286,6 +306,9 @@ public:
//- Update objective function derivatives
virtual void update() = 0;
//- Nullify adjoint contributions
virtual void nullify();
//- Update normalization factors, for objectives in
//- which the factor is not known a priori
virtual void updateNormalizationFactor();
@ -338,16 +361,20 @@ public:
// Inline functions for checking whether pointers are set or not
inline const word& objectiveName() const;
inline bool hasdJdb();
inline bool hasBoundarydJdb();
inline bool hasdSdbMult();
inline bool hasdndbMult();
inline bool hasdxdbMult();
inline bool hasdxdbDirectMult();
inline bool hasBoundaryEdgeContribution();
inline bool hasBoundarydJdStress();
inline bool hasDivDxDbMult();
inline bool hasGradDxDbMult();
inline bool hasdJdb() const;
inline bool hasBoundarydJdb() const;
inline bool hasdSdbMult() const;
inline bool hasdndbMult() const;
inline bool hasdxdbMult() const;
inline bool hasdxdbDirectMult() const;
inline bool hasBoundaryEdgeContribution() const;
inline bool hasBoundarydJdStress() const;
inline bool hasDivDxDbMult() const;
inline bool hasGradDxDbMult() const;
// Inline functions for checking whether integration times are set
inline bool hasIntegrationStartTime() const;
inline bool hasIntegrationEndTime() const;
};

View File

@ -36,64 +36,75 @@ inline const Foam::word& Foam::objective::objectiveName() const
}
inline bool Foam::objective::hasdJdb()
inline bool Foam::objective::hasdJdb() const
{
return dJdbPtr_.valid();
}
inline bool Foam::objective::hasBoundarydJdb()
inline bool Foam::objective::hasBoundarydJdb() const
{
return bdJdbPtr_.valid();
}
inline bool Foam::objective::hasdSdbMult()
inline bool Foam::objective::hasdSdbMult() const
{
return bdSdbMultPtr_.valid();
}
inline bool Foam::objective::hasdndbMult()
inline bool Foam::objective::hasdndbMult() const
{
return bdndbMultPtr_.valid();
}
inline bool Foam::objective::hasdxdbMult()
inline bool Foam::objective::hasdxdbMult() const
{
return bdxdbMultPtr_.valid();
}
inline bool Foam::objective::hasdxdbDirectMult()
inline bool Foam::objective::hasdxdbDirectMult() const
{
return bdxdbDirectMultPtr_.valid();
}
inline bool Foam::objective::hasBoundaryEdgeContribution()
inline bool Foam::objective::hasBoundaryEdgeContribution() const
{
return bEdgeContribution_.valid();
}
inline bool Foam::objective::hasDivDxDbMult()
inline bool Foam::objective::hasDivDxDbMult() const
{
return divDxDbMultPtr_.valid();
}
inline bool Foam::objective::hasGradDxDbMult()
inline bool Foam::objective::hasGradDxDbMult() const
{
return gradDxDbMultPtr_.valid();
}
inline bool Foam::objective::hasBoundarydJdStress()
inline bool Foam::objective::hasBoundarydJdStress() const
{
return bdJdStressPtr_.valid();
}
inline bool Foam::objective::hasIntegrationStartTime() const
{
return integrationStartTimePtr_.valid();
}
inline bool Foam::objective::hasIntegrationEndTime() const
{
return integrationEndTimePtr_.valid();
}
// ************************************************************************* //

View File

@ -0,0 +1,214 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "FIBaseIncompressible.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace incompressible
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
defineTypeNameAndDebug(FIBase, 0);
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
void FIBase::read()
{
includeDistance_ =
dict_.lookupOrDefault<bool>
(
"includeDistance",
adjointVars_.adjointTurbulence().ref().includeDistance()
);
// Allocate distance solver if needed
if (includeDistance_ && eikonalSolver_.empty())
{
eikonalSolver_.reset
(
new adjointEikonalSolver
(
mesh_,
dict_,
primalVars_.RASModelVariables(),
adjointVars_.adjointTurbulence(),
sensitivityPatchIDs_
)
);
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
FIBase::FIBase
(
const fvMesh& mesh,
const dictionary& dict,
incompressibleVars& primalVars,
incompressibleAdjointVars& adjointVars,
objectiveManager& objectiveManager,
fv::optionAdjointList& fvOptionsAdjoint
)
:
adjointSensitivity
(
mesh,
dict,
primalVars,
adjointVars,
objectiveManager,
fvOptionsAdjoint
),
shapeSensitivitiesBase(mesh, dict),
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(), vector::zero),
dSfdbMult_(createZeroBoundaryPtr<vector>(mesh_)),
dnfdbMult_(createZeroBoundaryPtr<vector>(mesh_)),
dxdbDirectMult_(createZeroBoundaryPtr<vector>(mesh_)),
includeDistance_(false),
eikonalSolver_(nullptr)
{
read();
};
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool FIBase::readDict(const dictionary& dict)
{
if (sensitivity::readDict(dict))
{
if (eikonalSolver_.valid())
{
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)
{
divDxDbMult_ +=
func.weight()*func.divDxDbMultiplier().primitiveField()*dt;
}
// Terms from fvOptions
for (fv::optionAdjoint& optionAdj : fvOptionsAdjoint_)
{
optionsDxDbMult_ +=
optionAdj.dxdbMult(adjointVars_)().primitiveField()*dt;
}
// Accumulate source for the adjoint to the eikonal equation
if (includeDistance_)
{
eikonalSolver_->accumulateIntegrand(dt);
}
// Accumulate direct sensitivities
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 FIBase::clearSensitivities()
{
gradDxDbMult_ = dimensionedTensor(gradDxDbMult_.dimensions(), Zero);
divDxDbMult_ = Zero;
optionsDxDbMult_ = vector::zero;
dSfdbMult_() = vector::zero;
dnfdbMult_() = vector::zero;
dxdbDirectMult_() = vector::zero;
if (includeDistance_)
{
eikonalSolver_->reset();
}
adjointSensitivity::clearSensitivities();
shapeSensitivitiesBase::clear();
}
void FIBase::write(const word& baseName)
{
adjointSensitivity::write(baseName);
shapeSensitivitiesBase::write();
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace incompressible
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,158 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Class
Foam::incompressible::FIBase
Description
Base class for Field Integral-based sensitivity derivatives
SourceFiles
FIBase.C
\*---------------------------------------------------------------------------*/
#ifndef FIBaseIncompressible_H
#define FIBaseIncompressible_H
#include "adjointSensitivityIncompressible.H"
#include "shapeSensitivitiesBase.H"
#include "adjointEikonalSolverIncompressible.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace incompressible
{
/*---------------------------------------------------------------------------*\
Class FIBase Declaration
\*---------------------------------------------------------------------------*/
class FIBase
:
public adjointSensitivity,
public shapeSensitivitiesBase
{
protected:
// Protected data
//- grad(dx/db) multiplier
volTensorField gradDxDbMult_;
//- div(dx/db) multiplier
scalarField divDxDbMult_;
//- dx/db multiplier coming from fvOptions
vectorField optionsDxDbMult_;
//- Fields related to direct sensitivities
autoPtr<boundaryVectorField> dSfdbMult_;
autoPtr<boundaryVectorField> dnfdbMult_;
autoPtr<boundaryVectorField> dxdbDirectMult_;
//- Include distance variation in sens computation
bool includeDistance_;
//- Adjoint eikonal equation solver
autoPtr<adjointEikonalSolver> eikonalSolver_;
// Protected Member Functions
//- Read options and update solver pointers if necessary
void read();
private:
// Private Member Functions
//- Disallow default bitwise copy construct
FIBase(const FIBase&) = delete;
//- Disallow default bitwise assignment
void operator=(const FIBase&) = delete;
public:
//- Runtime type information
TypeName("volumetricBSplinesFI");
// Constructors
//- Construct from components
FIBase
(
const fvMesh& mesh,
const dictionary& dict,
incompressibleVars& primalVars,
incompressibleAdjointVars& adjointVars,
objectiveManager& objectiveManager,
fv::optionAdjointList& fvOptionsAdjoint
);
//- Destructor
virtual ~FIBase() = default;
// Member Functions
//- Read dict if changed
virtual bool readDict(const dictionary& dict);
//- Accumulate sensitivity integrands
virtual void accumulateIntegrand(const scalar dt);
//- 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
// ************************************************************************* //

View File

@ -0,0 +1,188 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "SIBaseIncompressible.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace incompressible
{
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
defineTypeNameAndDebug(SIBase, 0);
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
void SIBase::read()
{
surfaceSensitivity_.read();
includeObjective_ =
dict().lookupOrDefault<bool>("includeObjectiveContribution", true);
// 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,
incompressibleVars& primalVars,
incompressibleAdjointVars& adjointVars,
objectiveManager& objectiveManager,
fv::optionAdjointList& fvOptionsAdjoint
)
:
adjointSensitivity
(
mesh,
dict,
primalVars,
adjointVars,
objectiveManager,
fvOptionsAdjoint
),
shapeSensitivitiesBase(mesh, dict),
surfaceSensitivity_
(
mesh,
// Ideally, subOrEmptyDict would be used.
// Since we need a recursive search in shapeSensitivitiesBase though
// and the dict returned by subOrEmptyDict (if found)
// does not know its parent, optionalSubDict is used
dict.optionalSubDict("surfaceSensitivities"),
primalVars,
adjointVars,
objectiveManager,
fvOptionsAdjoint
),
dSfdbMult_(createZeroBoundaryPtr<vector>(mesh_)),
dnfdbMult_(createZeroBoundaryPtr<vector>(mesh_)),
dxdbDirectMult_(createZeroBoundaryPtr<vector>(mesh_)),
includeObjective_(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_)
{
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 SIBase::clearSensitivities()
{
surfaceSensitivity_.clearSensitivities();
dSfdbMult_() = vector::zero;
dnfdbMult_() = vector::zero;
dxdbDirectMult_() = vector::zero;
adjointSensitivity::clearSensitivities();
shapeSensitivitiesBase::clear();
}
void SIBase::write(const word& baseName)
{
adjointSensitivity::write(baseName);
shapeSensitivitiesBase::write();
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace incompressible
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,148 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Class
Foam::incompressible::SIBase
Description
Base class for Surface Integral-based sensitivity derivatives
SourceFiles
SIBase.C
\*---------------------------------------------------------------------------*/
#ifndef SIBaseIncompressible_H
#define SIBaseIncompressible_H
#include "adjointSensitivityIncompressible.H"
#include "shapeSensitivitiesBase.H"
#include "sensitivitySurfaceIncompressible.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace incompressible
{
/*---------------------------------------------------------------------------*\
Class SIBase Declaration
\*---------------------------------------------------------------------------*/
class SIBase
:
public adjointSensitivity,
public shapeSensitivitiesBase
{
protected:
// Protected data
//- Surface sensitivities
sensitivitySurface surfaceSensitivity_;
//- Fields related to direct sensitivities
autoPtr<boundaryVectorField> dSfdbMult_;
autoPtr<boundaryVectorField> dnfdbMult_;
autoPtr<boundaryVectorField> dxdbDirectMult_;
bool includeObjective_;
// Protected Member Fuctions
//- Read options from dict
void read();
private:
// Private Member Functions
//- Disallow default bitwise copy construct
SIBase(const SIBase&) = delete;
//- Disallow default bitwise assignment
void operator=(const SIBase&) = delete;
public:
//- Runtime type information
TypeName("volumetricBSplinesFI");
// Constructors
//- Construct from components
SIBase
(
const fvMesh& mesh,
const dictionary& dict,
incompressibleVars& primalVars,
incompressibleAdjointVars& adjointVars,
objectiveManager& objectiveManager,
fv::optionAdjointList& fvOptionsAdjoint
);
//- Destructor
virtual ~SIBase() = default;
// Member Functions
//- Read dict if changed
virtual bool readDict(const dictionary& dict);
//- Accumulate sensitivity integrands
virtual void accumulateIntegrand(const scalar dt);
//- 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
// ************************************************************************* //

View File

@ -115,7 +115,7 @@ adjointEikonalSolver::adjointEikonalSolver
const dictionary& dict,
const autoPtr<incompressible::RASModelVariables>& RASModelVars,
autoPtr<Foam::incompressibleAdjoint::adjointRASModel>& adjointTurbulence,
const labelList& sensitivityPatchIDs
const labelHashSet& sensitivityPatchIDs
)
:
mesh_(mesh),
@ -141,6 +141,19 @@ adjointEikonalSolver::adjointEikonalSolver
dimensionedScalar(sqr(dimLength)/pow3(dimTime), Zero),
patchTypes()
),
source_
(
IOobject
(
"sourceEikonal",
mesh_.time().timeName(),
mesh_,
IOobject::NO_READ,
IOobject::NO_WRITE
),
mesh_,
dimensionedScalar(dimLength/pow3(dimTime), Zero)
),
distanceSensPtr_(createZeroBoundaryPtr<vector>(mesh_))
{
read();
@ -157,6 +170,13 @@ bool adjointEikonalSolver::readDict(const dictionary& dict)
}
void adjointEikonalSolver::accumulateIntegrand(const scalar dt)
{
// Accumulate integrand from the current time step
source_ += adjointTurbulence_->distanceSensitivities()*dt;
}
void adjointEikonalSolver::solve()
{
read();
@ -164,11 +184,6 @@ void adjointEikonalSolver::solve()
// Primal distance field
const volScalarField& d = RASModelVars_().d();
// Populate the source term. Not dependent from da, so only
// need to update it once per optimisation cycle
tmp<volScalarField> tsource = adjointTurbulence_->distanceSensitivities();
const volScalarField& source = tsource();
// Convecting flux
tmp<surfaceScalarField> tyPhi = computeYPhi();
const surfaceScalarField& yPhi = tyPhi();
@ -185,7 +200,7 @@ void adjointEikonalSolver::solve()
2*fvm::div(-yPhi, da_)
+ fvm::SuSp(-epsilon_*fvc::laplacian(d), da_)
- epsilon_*fvm::laplacian(d, da_)
+ source
+ source_
);
daEqn.relax();
@ -208,6 +223,13 @@ void adjointEikonalSolver::solve()
}
void adjointEikonalSolver::reset()
{
source_ == dimensionedScalar(source_.dimensions(), Zero);
distanceSensPtr_() = vector::zero;
}
boundaryVectorField& adjointEikonalSolver::distanceSensitivities()
{
Info<< "Calculating distance sensitivities " << endl;

View File

@ -170,7 +170,7 @@ protected:
autoPtr<Foam::incompressibleAdjoint::adjointRASModel>&
adjointTurbulence_;
const labelList& sensitivityPatchIDs_;
const labelHashSet& sensitivityPatchIDs_;
label nEikonalIters_;
@ -182,6 +182,8 @@ protected:
volScalarField da_;
volScalarField source_;
//- Wall face sens w.r.t. (x,y.z)
autoPtr<boundaryVectorField> distanceSensPtr_;
@ -215,7 +217,7 @@ public:
const autoPtr<incompressible::RASModelVariables>& RASModelVars,
autoPtr<Foam::incompressibleAdjoint::adjointRASModel>&
adjointTurbulence,
const labelList& sensitivityPatchIDs
const labelHashSet& sensitivityPatchIDs
);
// Destructor
@ -228,9 +230,15 @@ public:
//- Read dict if changed
virtual bool readDict(const dictionary& dict);
//- Accumulate source term
void accumulateIntegrand(const scalar dt);
//- Calculate the adjoint distance field
void solve();
//- Reset source term
void reset();
//- Return the sensitivity term depending on da
boundaryVectorField& distanceSensitivities();

View File

@ -58,7 +58,7 @@ adjointMeshMovementSolver::adjointMeshMovementSolver
const fvMesh& mesh,
const dictionary& dict,
Foam::incompressible::adjointSensitivity& adjointSensitivity,
const labelList& sensitivityPatchIDs,
const labelHashSet& sensitivityPatchIDs,
const autoPtr<adjointEikonalSolver>& adjointEikonalSolverPtr
)
:
@ -77,6 +77,19 @@ adjointMeshMovementSolver::adjointMeshMovementSolver
dimensionSet(pow3(dimLength/dimTime))
)
),
source_
(
IOobject
(
"sourceAdjointMeshMovement",
mesh_.time().timeName(),
mesh_,
IOobject::NO_READ,
IOobject::NO_WRITE
),
mesh_,
dimensionedVector(dimLength/pow3(dimTime), Zero)
),
meshMovementSensPtr_(createZeroBoundaryPtr<vector>(mesh_)),
adjointEikonalSolverPtr_(adjointEikonalSolverPtr)
{
@ -94,24 +107,28 @@ bool adjointMeshMovementSolver::readDict(const dictionary& dict)
}
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()
{
read();
// Compute source term
tmp<volVectorField> tsource
(
adjointSensitivity_.adjointMeshMovementSource()
);
volVectorField& source = tsource.ref();
// Add source from the adjoint eikonal equation
if (adjointEikonalSolverPtr_.valid())
{
source -=
source_ -=
fvc::div(adjointEikonalSolverPtr_().getFISensitivityTerm()().T());
}
// Iterate the adjoint to the eikonal equation
// Iterate the adjoint to the mesh movement equation
for (label iter = 0; iter < nLaplaceIters_; iter++)
{
Info<< "Adjoint Mesh Movement Iteration: " << iter << endl;
@ -119,7 +136,7 @@ void adjointMeshMovementSolver::solve()
fvVectorMatrix maEqn
(
fvm::laplacian(ma_)
+ source
+ source_
);
maEqn.boundaryManipulate(ma_.boundaryFieldRef());
@ -145,6 +162,13 @@ void adjointMeshMovementSolver::solve()
}
void adjointMeshMovementSolver::reset()
{
source_ == dimensionedVector(source_.dimensions(), Zero);
meshMovementSensPtr_() = vector::zero;
}
boundaryVectorField& adjointMeshMovementSolver::meshMovementSensitivities()
{
Info<< "Calculating mesh movement sensitivities " << endl;

View File

@ -75,10 +75,11 @@ protected:
const fvMesh& mesh_;
dictionary dict_;
Foam::incompressible::adjointSensitivity& adjointSensitivity_;
const labelList& sensitivityPatchIDs_;
const labelHashSet& sensitivityPatchIDs_;
label nLaplaceIters_;
scalar tolerance_;
volVectorField ma_;
volVectorField source_;
//- Wall face sens w.r.t.(x, y.z) //wall face sens w.r.t. (x,y.z)
autoPtr<boundaryVectorField> meshMovementSensPtr_;
@ -113,7 +114,7 @@ public:
const fvMesh& mesh,
const dictionary& dict,
Foam::incompressible::adjointSensitivity& adjointSensitivity,
const labelList& sensitivityPatchIDs,
const labelHashSet& sensitivityPatchIDs,
const autoPtr<adjointEikonalSolver>& adjointEikonalSolverPtr
);
@ -126,9 +127,15 @@ public:
//- Read dict if changed
virtual bool readDict(const dictionary& dict);
//- Accumulate source term
void accumulateIntegrand(const scalar dt);
//- Calculate the adjoint distance field
void solve();
//- Reset source term
void reset();
//- Return the sensitivity term depending on da
boundaryVectorField& meshMovementSensitivities();

View File

@ -58,7 +58,8 @@ adjointSensitivity::adjointSensitivity
fv::optionAdjointList& fvOptionsAdjoint
)
:
sensitivity(mesh, dict, objectiveManager.adjointSolverName()),
sensitivity(mesh, dict),
derivatives_(0),
primalVars_(primalVars),
adjointVars_(adjointVars),
objectiveManager_(objectiveManager),
@ -112,6 +113,24 @@ autoPtr<adjointSensitivity> adjointSensitivity::New
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * //
const scalarField& adjointSensitivity::calculateSensitivities()
{
assembleSensitivities();
write(type());
return derivatives_;
}
void adjointSensitivity::clearSensitivities()
{
derivatives_ = scalar(0);
if (fieldSensPtr_.valid())
{
fieldSensPtr_().primitiveFieldRef() = scalar(0);
}
}
void adjointSensitivity::write(const word& baseName)
{
sensitivity::write(baseName);
@ -276,29 +295,6 @@ tmp<volTensorField> adjointSensitivity::computeGradDxDbMultiplier()
// Term 7, term from objective functions
+ objectiveContributions;
// Correct boundary conditions for the flow term.
// Needed since the div of this term is often used
forAll(mesh_.boundary(), pI)
{
const fvPatch& patch = mesh_.boundary()[pI];
bool isSensPatch(false);
forAll(sensitivityPatchIDs_, pJ)
{
label patchJ = sensitivityPatchIDs_[pJ];
if (patchJ == pI)
{
isSensPatch = true;
break;
}
}
if (!isSensPatch && !isA<coupledFvPatch>(patch))
{
flowTerm.boundaryFieldRef()[pI] =
tensorField(patch.size(), tensor::zero);
}
}
flowTerm.correctBoundaryConditions();
return (tflowTerm);
@ -331,6 +327,12 @@ tmp<volVectorField> adjointSensitivity::adjointMeshMovementSource()
source -= fvc::div(gradDxDbMult.T());
// Terms from fvOptions
forAll(fvOptionsAdjoint_, oI)
{
source += fvOptionsAdjoint_[oI].dxdbMult(adjointVars_);
}
return (tadjointMeshMovementSource);
}

View File

@ -83,6 +83,7 @@ protected:
// Protected data
scalarField derivatives_;
incompressibleVars& primalVars_;
incompressibleAdjointVars& adjointVars_;
objectiveManager& objectiveManager_;
@ -165,9 +166,20 @@ public:
// Member Functions
//- 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() = 0;
virtual const scalarField& calculateSensitivities();
//- Zero sensitivity fields and their constituents
virtual void clearSensitivities();
//- Write sensitivity fields.
// If valid, copies boundaryFields to volFields and writes them.

View File

@ -0,0 +1,245 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "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,
incompressibleVars& primalVars,
incompressibleAdjointVars& adjointVars,
objectiveManager& objectiveManager,
fv::optionAdjointList& fvOptionsAdjoint
)
:
SIBase
(
mesh,
dict,
primalVars,
adjointVars,
objectiveManager,
fvOptionsAdjoint
),
//Bezier_(mesh, dict), // AJH Read locally?
Bezier_(mesh, mesh.lookupObject<IOdictionary>("optimisationDict")),
sens_(Bezier_.nBezier(), vector::zero),
flowSens_(Bezier_.nBezier(), vector::zero),
dSdbSens_(Bezier_.nBezier(), vector::zero),
dndbSens_(Bezier_.nBezier(), vector::zero),
dxdbDirectSens_(Bezier_.nBezier(), vector::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));
}
}
}
sens_ = flowSens_ + dSdbSens_ + dndbSens_ + dxdbDirectSens_;
// 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;
}
if (confineYmovement[cpI])
{
derivatives_[cpI + nBezier] *= scalar(0);
flowSens_[cpI].y() = Zero;
dSdbSens_[cpI].y() = Zero;
dndbSens_[cpI].y() = Zero;
dxdbDirectSens_[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;
}
}
}
void sensitivityBezier::clearSensitivities()
{
sens_ = vector::zero;
flowSens_ = vector::zero;
dSdbSens_ = vector::zero;
dndbSens_ = vector::zero;
dxdbDirectSens_ = vector::zero;
SIBase::clearSensitivities();
}
void sensitivityBezier::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(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" << 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)
<< endl;
}
}
}
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace incompressible
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,140 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Class
Foam::incompressible::sensitivityBezier
Description
Calculation of adjoint based sensitivities for Bezier control points
SourceFiles
sensitivityBezier.C
\*---------------------------------------------------------------------------*/
#ifndef sensitivityBezierIncompressible_H
#define sensitivityBezierIncompressible_H
#include "primitiveFieldsFwd.H"
#include "volFieldsFwd.H"
#include "pointFieldsFwd.H"
#include "surfaceFieldsFwd.H"
#include "volPointInterpolation.H"
#include "SIBaseIncompressible.H"
#include "PrimitivePatchInterpolation.H"
#include "PrimitivePatch.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_;
fileName derivativesFolder_;
private:
// Private Member Functions
//- Disallow default bitwise copy construct
sensitivityBezier(const sensitivityBezier&) = delete;
//- Disallow default bitwise assignment
void operator=(const sensitivityBezier&) = delete;
public:
//- Runtime type information
TypeName("Bezier");
// Constructors
//- Construct from components
sensitivityBezier
(
const fvMesh& mesh,
const dictionary& dict,
incompressibleVars& primalVars,
incompressibleAdjointVars& adjointVars,
objectiveManager& objectiveManager,
fv::optionAdjointList& fvOptionsAdjoint
);
//- 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

View File

@ -0,0 +1,366 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "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.lookupOrDefault<label>("iters", 1000);
meshMovementResidualLimit_ =
dxdbDict.lookupOrDefault<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,
incompressibleVars& primalVars,
incompressibleAdjointVars& adjointVars,
objectiveManager& objectiveManager,
fv::optionAdjointList& fvOptionsAdjoint
)
:
FIBase
(
mesh,
dict,
primalVars,
adjointVars,
objectiveManager,
fvOptionsAdjoint
),
//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),
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 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_;
}
}
void sensitivityBezierFI::clearSensitivities()
{
flowSens_ = Zero;
dSdbSens_ = Zero;
dndbSens_ = Zero;
dxdbDirectSens_ = Zero;
dVdbSens_ = Zero;
distanceSens_ = Zero;
optionsSens_ = 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" << 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++)
{
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_[iDV] << " "
<< setw(width) << dSdbSens_[iDV] << " "
<< setw(width) << dndbSens_[iDV] << " "
<< setw(width) << dxdbDirectSens_[iDV] << " "
<< setw(width) << dVdbSens_[iDV] << " "
<< setw(width) << distanceSens_[iDV] << endl;
}
}
}
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace incompressible
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,169 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
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_;
fileName derivativesFolder_;
label meshMovementIters_;
scalar meshMovementResidualLimit_;
volVectorField dxdb_;
void read();
tmp<volVectorField> solveMeshMovementEqn
(
const label iCP,
const label idir
);
private:
// Private Member Functions
//- Disallow default bitwise copy construct
sensitivityBezierFI(const sensitivityBezierFI&) = delete;
//- Disallow default bitwise assignment
void operator=(const sensitivityBezierFI&) = delete;
public:
//- Runtime type information
TypeName("BezierFI");
// Constructors
//- Construct from components
sensitivityBezierFI
(
const fvMesh& mesh,
const dictionary& dict,
incompressibleVars& primalVars,
incompressibleAdjointVars& adjointVars,
objectiveManager& objectiveManager,
fv::optionAdjointList& fvOptionsAdjoint
);
//- 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
// ************************************************************************* //

View File

@ -70,8 +70,7 @@ sensitivityMultiple::sensitivityMultiple
fvOptionsAdjoint
),
sensTypes_(dict.subDict("sensTypes").toc()),
sens_(sensTypes_.size()),
derivatives_(0)
sens_(sensTypes_.size())
{
forAll(sensTypes_, sI)
{
@ -113,16 +112,43 @@ bool sensitivityMultiple::readDict(const dictionary& dict)
}
void sensitivityMultiple::accumulateIntegrand(const scalar dt)
{
forAll(sens_, sI)
{
sens_[sI].accumulateIntegrand(dt);
}
}
void sensitivityMultiple::assembleSensitivities()
{
forAll(sens_, sI)
{
sens_[sI].assembleSensitivities();
}
}
const scalarField& sensitivityMultiple::calculateSensitivities()
{
forAll(sens_, sI)
{
Info<< "Computing sensitivities " << sensTypes_[sI] << endl;
sens_[sI].calculateSensitivities();
derivatives_ = sens_[sI].calculateSensitivities();
}
write(type());
return (derivatives_);
return derivatives_;
}
void sensitivityMultiple::clearSensitivities()
{
forAll(sens_, sI)
{
sens_[sI].clearSensitivities();
}
}

View File

@ -66,8 +66,6 @@ protected:
PtrList<adjointSensitivity> sens_;
scalarField derivatives_;
private:
@ -109,9 +107,18 @@ public:
//- Read dict if changed
virtual bool readDict(const dictionary& dict);
//- Accumulate sensitivity integrands
virtual void accumulateIntegrand(const scalar dt);
//- Assemble sensitivities
virtual void assembleSensitivities();
//- Calculates sensitivities at wall surface points
const scalarField& calculateSensitivities();
//- Zero sensitivity fields and their constituents
virtual void clearSensitivities();
//- Write sensitivities to file
virtual void write(const word& baseName = word::null);
};

View File

@ -50,63 +50,7 @@ addToRunTimeSelectionTable
dictionary
);
// * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * * //
void sensitivitySurface::read()
{
includeSurfaceArea_ =
dict().lookupOrDefault<bool>("includeSurfaceArea", true);
includePressureTerm_ =
dict().lookupOrDefault<bool>("includePressure", true);
includeGradStressTerm_ =
dict().lookupOrDefault<bool>("includeGradStressTerm", true);
includeTransposeStresses_ =
dict().lookupOrDefault<bool>("includeTransposeStresses", true);
includeDivTerm_ = dict().lookupOrDefault<bool>("includeDivTerm", false);
includeDistance_ =
dict().lookupOrDefault<bool>
(
"includeDistance",
adjointVars_.adjointTurbulence().ref().includeDistance()
);
includeMeshMovement_ =
dict().lookupOrDefault<bool>("includeMeshMovement", true);
includeObjective_ =
dict().lookupOrDefault<bool>("includeObjectiveContribution", true);
writeGeometricInfo_ =
dict().lookupOrDefault<bool>("writeGeometricInfo", false);
// Allocate new solvers if necessary
if (includeDistance_ && eikonalSolver_.empty())
{
eikonalSolver_.reset
(
new adjointEikonalSolver
(
mesh_,
dict_,
primalVars_.RASModelVariables(),
adjointVars_.adjointTurbulence(),
sensitivityPatchIDs_
)
);
}
if (includeMeshMovement_ && meshMovementSolver_.empty())
{
meshMovementSolver_.reset
(
new adjointMeshMovementSolver
(
mesh_,
dict_,
*this,
sensitivityPatchIDs_,
eikonalSolver_
)
);
}
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
void sensitivitySurface::addGeometricSens()
{
@ -127,9 +71,8 @@ void sensitivitySurface::addGeometricSens()
);
// Geometric (or "direct") sensitivities are better computed directly
// on the points
forAll(sensitivityPatchIDs_, pI)
for (const label patchI : sensitivityPatchIDs_)
{
const label patchI = sensitivityPatchIDs_[pI];
const fvPatch& patch = mesh_.boundary()[patchI];
vectorField nf(patch.nf());
@ -200,9 +143,8 @@ void sensitivitySurface::addGeometricSens()
// boundaries
vectorField dSdbGlobal(mesh_.nPoints(), vector::zero);
vectorField dndbGlobal(mesh_.nPoints(), vector::zero);
forAll(sensitivityPatchIDs_, pI)
for (const label patchI : sensitivityPatchIDs_)
{
const label patchI = sensitivityPatchIDs_[pI];
const labelList& meshPoints =
mesh_.boundaryMesh()[patchI].meshPoints();
forAll(meshPoints, ppI)
@ -222,9 +164,8 @@ void sensitivitySurface::addGeometricSens()
mesh_, dndbGlobal, plusEqOp<vector>(), vector::zero
);
// Transfer back to local fields and map to faces
forAll(sensitivityPatchIDs_, pI)
for (const label patchI : sensitivityPatchIDs_)
{
const label patchI = sensitivityPatchIDs_[pI];
const fvPatch& patch = mesh_.boundary()[patchI];
const labelList& meshPoints = patch.patch().meshPoints();
const scalarField& magSf = patch.magSf();
@ -252,6 +193,20 @@ void sensitivitySurface::addGeometricSens()
}
void sensitivitySurface::setSuffixName()
{
// Determine suffix for fields holding the sens
if (includeMeshMovement_)
{
shapeSensitivitiesBase::setSuffix(adjointVars_.solverName() + "ESI");
}
else
{
shapeSensitivitiesBase::setSuffix(adjointVars_.solverName() + "SI");
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
sensitivitySurface::sensitivitySurface
@ -273,7 +228,7 @@ sensitivitySurface::sensitivitySurface
objectiveManager,
fvOptionsAdjoint
),
derivatives_(0),
shapeSensitivitiesBase(mesh, dict),
includeSurfaceArea_(false),
includePressureTerm_(false),
includeGradStressTerm_(false),
@ -291,6 +246,7 @@ sensitivitySurface::sensitivitySurface
CfOnPatchPtr_(nullptr)
{
read();
setSuffixName();
// Allocate boundary field pointer
wallFaceSensVecPtr_.reset(createZeroBoundaryPtr<vector>(mesh_));
@ -359,6 +315,62 @@ sensitivitySurface::sensitivitySurface
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void sensitivitySurface::read()
{
includeSurfaceArea_ =
dict().lookupOrDefault<bool>("includeSurfaceArea", true);
includePressureTerm_ =
dict().lookupOrDefault<bool>("includePressure", true);
includeGradStressTerm_ =
dict().lookupOrDefault<bool>("includeGradStressTerm", true);
includeTransposeStresses_ =
dict().lookupOrDefault<bool>("includeTransposeStresses", true);
includeDivTerm_ = dict().lookupOrDefault<bool>("includeDivTerm", false);
includeDistance_ =
dict().lookupOrDefault<bool>
(
"includeDistance",
adjointVars_.adjointTurbulence().ref().includeDistance()
);
includeMeshMovement_ =
dict().lookupOrDefault<bool>("includeMeshMovement", true);
includeObjective_ =
dict().lookupOrDefault<bool>("includeObjectiveContribution", true);
writeGeometricInfo_ =
dict().lookupOrDefault<bool>("writeGeometricInfo", false);
// Allocate new solvers if necessary
if (includeDistance_ && eikonalSolver_.empty())
{
eikonalSolver_.reset
(
new adjointEikonalSolver
(
mesh_,
dict_,
primalVars_.RASModelVariables(),
adjointVars_.adjointTurbulence(),
sensitivityPatchIDs_
)
);
}
if (includeMeshMovement_ && meshMovementSolver_.empty())
{
meshMovementSolver_.reset
(
new adjointMeshMovementSolver
(
mesh_,
dict_,
*this,
sensitivityPatchIDs_,
eikonalSolver_
)
);
}
}
bool sensitivitySurface::readDict(const dictionary& dict)
{
if (sensitivity::readDict(dict))
@ -383,16 +395,15 @@ bool sensitivitySurface::readDict(const dictionary& dict)
void sensitivitySurface::computeDerivativesSize()
{
label nFaces(0);
forAll(sensitivityPatchIDs_, pI)
for (const label patchI : sensitivityPatchIDs_)
{
const label patchI = sensitivityPatchIDs_[pI];
nFaces += mesh_.boundary()[patchI].size();
}
derivatives_.setSize(nFaces);
}
const scalarField& sensitivitySurface::calculateSensitivities()
void sensitivitySurface::accumulateIntegrand(const scalar dt)
{
// Grab references
const volScalarField& p = primalVars_.p();
@ -403,27 +414,6 @@ const scalarField& sensitivitySurface::calculateSensitivities()
autoPtr<incompressibleAdjoint::adjointRASModel>& adjointTurbulence =
adjointVars_.adjointTurbulence();
// Restore to zero
derivatives_ = Zero;
// Update geometric fields for use by external users
if (writeGeometricInfo_)
{
forAll(sensitivityPatchIDs_, pI)
{
const label patchI = sensitivityPatchIDs_[pI];
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;
}
}
Info<< " Calculating auxilary quantities " << endl;
// Fields needed to calculate adjoint sensitivities
const autoPtr<incompressible::RASModelVariables>&
@ -479,38 +469,23 @@ const scalarField& sensitivitySurface::calculateSensitivities()
volTensorField gradStressY(fvc::grad(stressYPtr()));
volTensorField gradStressZ(fvc::grad(stressZPtr()));
// Solve extra equations if necessary
autoPtr<boundaryVectorField> distanceSensPtr(nullptr);
// Accumulate source for additional post-processing PDEs, if necessary
if (includeDistance_)
{
eikonalSolver_->solve();
distanceSensPtr.reset(createZeroBoundaryPtr<vector>(mesh_));
const boundaryVectorField& sens =
eikonalSolver_->distanceSensitivities();
for (const label patchI : sensitivityPatchIDs_)
{
distanceSensPtr()[patchI] = sens[patchI];
}
eikonalSolver_->accumulateIntegrand(dt);
}
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];
}
meshMovementSolver_->accumulateIntegrand(dt);
}
// Terms from the adjoint turbulence model
const boundaryVectorField& adjointTMsensitivities =
adjointTurbulence->wallShapeSensitivities();
Info<< " Calculating adjoint sensitivity. " << endl;
DebugInfo
<< " Calculating adjoint sensitivity. " << endl;
// Sensitivities do not include locale surface area by default.
// Part of the sensitivities that multiplies dxFace/db
@ -598,20 +573,6 @@ const scalarField& sensitivitySurface::calculateSensitivities()
)* nf;
}
// Distance related terms
vectorField distanceTerm(pressureTerm.size(), vector::zero);
if (includeDistance_)
{
distanceTerm = distanceSensPtr()[patchI];
}
// Mesh movement related terms
vectorField meshMovementTerm(pressureTerm.size(), vector::zero);
if (includeMeshMovement_)
{
meshMovementTerm = meshMovementSensPtr()[patchI];
}
PtrList<objective>& functions
(objectiveManager_.getObjectiveFunctions());
@ -630,19 +591,69 @@ const scalarField& sensitivitySurface::calculateSensitivities()
}
// Fill in sensitivity fields
wallFaceSensVecPtr_()[patchI] =
wallFaceSensVecPtr_()[patchI] +=
(
stressTerm
+ gradStressTerm
+ pressureTerm
+ distanceTerm
+ meshMovementTerm
+ adjointTMsensitivities[patchI]
+ dxdbMultiplierTot;
+ dxdbMultiplierTot
)*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);
@ -651,11 +662,22 @@ const scalarField& sensitivitySurface::calculateSensitivities()
const fvPatch& patch = mesh_.boundary()[patchI];
tmp<vectorField> tnf(patch.nf());
const vectorField& nf = tnf();
const scalarField& magSf = patch.magSf();
// Distance related terms
if (includeDistance_)
{
wallFaceSensVecPtr_()[patchI] += distanceSensPtr()[patchI];
}
// Mesh movement related terms
if (includeMeshMovement_)
{
wallFaceSensVecPtr_()[patchI] += meshMovementSensPtr()[patchI];
}
if (includeSurfaceArea_)
{
wallFaceSensVecPtr_()[patchI] *= magSf;
wallFaceSensVecPtr_()[patchI] *= patch.magSf();
}
wallFaceSensNormalPtr_()[patchI] = wallFaceSensVecPtr_()[patchI] & nf;
@ -669,11 +691,23 @@ const scalarField& sensitivitySurface::calculateSensitivities()
}
nPassedFaces += patch.size();
}
}
// Write sens fields
write(type());
return (derivatives_);
void sensitivitySurface::clearSensitivities()
{
// Reset terms in post-processing PDEs
if (includeDistance_)
{
eikonalSolver_->reset();
}
if (includeMeshMovement_)
{
meshMovementSolver_->reset();
}
// Reset sensitivity fields
adjointSensitivity::clearSensitivities();
shapeSensitivitiesBase::clear();
}
@ -685,16 +719,9 @@ autoPtr<adjointEikonalSolver>& sensitivitySurface::getAdjointEikonalSolver()
void sensitivitySurface::write(const word& baseName)
{
// Determine suffix for fields holding the sens
if (includeMeshMovement_)
{
surfaceFieldSuffix_ = word("ESI");
}
else
{
surfaceFieldSuffix_ = word("SI");
}
setSuffixName();
adjointSensitivity::write();
shapeSensitivitiesBase::write();
if (writeGeometricInfo_)
{

View File

@ -41,6 +41,7 @@ SourceFiles
#define sensitivitySurfaceIncompressible_H
#include "adjointSensitivityIncompressible.H"
#include "shapeSensitivitiesBase.H"
#include "adjointEikonalSolverIncompressible.H"
#include "adjointMeshMovementSolverIncompressible.H"
#include "deltaBoundary.H"
@ -54,19 +55,18 @@ namespace incompressible
{
/*---------------------------------------------------------------------------*\
Class sensitivitySurface Declaration
Class sensitivitySurface Declaration
\*---------------------------------------------------------------------------*/
class sensitivitySurface
:
public adjointSensitivity
public adjointSensitivity,
public shapeSensitivitiesBase
{
protected:
// Protected data
//- Scalar normal sens
scalarField derivatives_;
//- Include surface area in sens computation
bool includeSurfaceArea_;
@ -107,13 +107,13 @@ protected:
// Protected Member Functions
//- Read controls and update solver pointers if necessary
void read();
//- Add sensitivities from dSd/db and dnf/db computed at points and
//- mapped to faces
void addGeometricSens();
//- Set suffix name for sensitivity fields
void setSuffixName();
private:
@ -152,19 +152,44 @@ public:
// Member Functions
//- Read controls and update solver pointers if necessary
void read();
//- Read dict if changed
virtual bool readDict(const dictionary& dict);
//- Compute the number of faces on sensitivityPatchIDs_
void computeDerivativesSize();
//- Calculates sensitivities at wall surface points
const scalarField& calculateSensitivities();
//- 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 geters 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);
};
@ -175,6 +200,10 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "sensitivitySurfaceIncompressibleI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,71 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2019 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
| Copyright (C) 2007-2019 PCOpt/NTUA
| Copyright (C) 2013-2019 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/>.
\*---------------------------------------------------------------------------*/
namespace Foam
{
namespace incompressible
{
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline bool sensitivitySurface::getIncludeObjective() const
{
return includeObjective_;
}
inline bool sensitivitySurface::getIncludeSurfaceArea() const
{
return includeSurfaceArea_;
}
inline void sensitivitySurface::setIncludeObjective
(
const bool includeObjective
)
{
includeObjective_ = includeObjective;
}
inline void sensitivitySurface::setIncludeSurfaceArea
(
const bool includeSurfaceArea
)
{
includeSurfaceArea_ = includeSurfaceArea;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace incompressible
} // End namespace Foam

View File

@ -49,7 +49,7 @@ addToRunTimeSelectionTable
dictionary
);
// * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * * //
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
void sensitivitySurfacePoints::read()
{
@ -107,6 +107,217 @@ void sensitivitySurfacePoints::read()
}
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(), tensor::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()
{
// Determine suffix for fields holding the sens
if (includeMeshMovement_)
{
shapeSensitivitiesBase::setSuffix(adjointVars_.solverName() + "ESI");
}
else
{
shapeSensitivitiesBase::setSuffix(adjointVars_.solverName() + "SI");
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
sensitivitySurfacePoints::sensitivitySurfacePoints
@ -128,7 +339,7 @@ sensitivitySurfacePoints::sensitivitySurfacePoints
objectiveManager,
fvOptionsAdjoint
),
derivatives_(0),
shapeSensitivitiesBase(mesh, dict),
includeSurfaceArea_(false),
includePressureTerm_(false),
includeGradStressTerm_(false),
@ -138,7 +349,11 @@ sensitivitySurfacePoints::sensitivitySurfacePoints
includeMeshMovement_(false),
includeObjective_(false),
eikonalSolver_(nullptr),
meshMovementSolver_(nullptr)
meshMovementSolver_(nullptr),
wallFaceSens_(createZeroBoundaryPtr<vector>(mesh_)),
dSfdbMult_(createZeroBoundaryPtr<vector>(mesh_)),
dnfdbMult_(createZeroBoundaryPtr<vector>(mesh_))
{
read();
@ -189,7 +404,7 @@ bool sensitivitySurfacePoints::readDict(const dictionary& dict)
}
const scalarField& sensitivitySurfacePoints::calculateSensitivities()
void sensitivitySurfacePoints::accumulateIntegrand(const scalar dt)
{
// Grab references
const volScalarField& p = primalVars_.p();
@ -200,16 +415,8 @@ const scalarField& sensitivitySurfacePoints::calculateSensitivities()
autoPtr<incompressibleAdjoint::adjointRASModel>& adjointTurbulence =
adjointVars_.adjointTurbulence();
// Restore to zero
derivatives_ = Zero;
forAll(mesh_.boundary(), patchI)
{
wallPointSensVecPtr_()[patchI] = vector::zero;
wallPointSensNormalPtr_()[patchI] = Zero;
wallPointSensNormalVecPtr_()[patchI] = vector::zero;
}
Info<< " Calculating auxilary quantities " << endl;
DebugInfo
<< " Calculating auxilary quantities " << endl;
// Fields needed to calculate adjoint sensitivities
volScalarField nuEff(adjointTurbulence->nuEff());
@ -262,31 +469,16 @@ const scalarField& sensitivitySurfacePoints::calculateSensitivities()
volTensorField gradStressY(fvc::grad(stressYPtr()));
volTensorField gradStressZ(fvc::grad(stressZPtr()));
// solve extra equations if necessary
autoPtr<boundaryVectorField> distanceSensPtr(nullptr);
// Solve extra equations if necessary
if (includeDistance_)
{
eikonalSolver_->solve();
distanceSensPtr.reset(createZeroBoundaryPtr<vector>(mesh_));
const boundaryVectorField& sens =
eikonalSolver_->distanceSensitivities();
for (const label patchI : sensitivityPatchIDs_)
{
distanceSensPtr()[patchI] = sens[patchI];
}
eikonalSolver_->accumulateIntegrand(dt);
}
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];
}
meshMovementSolver_->accumulateIntegrand(dt);
}
// Terms from the adjoint turbulence model
@ -296,23 +488,16 @@ const scalarField& sensitivitySurfacePoints::calculateSensitivities()
// Objective references
PtrList<objective>& functions(objectiveManager_.getObjectiveFunctions());
Info<< " Calculating adjoint sensitivity. " << endl;
DebugInfo
<< " Calculating adjoint sensitivity. " << endl;
// 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
(
createZeroBoundaryPtr<vector>(mesh_)
);
// dxFace/dxPoint.
for (const label patchI : sensitivityPatchIDs_)
{
const fvPatch& patch = mesh_.boundary()[patchI];
tmp<vectorField> tnf = patch.nf();
const vectorField& nf = tnf();
const scalarField& magSf = patch.magSf();
// Adjoint stress term
// vectorField stressTerm
@ -387,49 +572,49 @@ const scalarField& sensitivitySurfacePoints::calculateSensitivities()
*nf;
}
// Distance related terms
vectorField distanceTerm(pressureTerm.size(), vector::zero);
if (includeDistance_)
{
distanceTerm = distanceSensPtr()[patchI];
}
// Mesh movement related terms
vectorField meshMovementTerm(pressureTerm.size(), vector::zero);
if (includeMeshMovement_)
{
meshMovementTerm = meshMovementSensPtr()[patchI];
}
vectorField dxdbMultiplierTot
(
mesh_.boundary()[patchI].size(), vector::zero
);
vectorField dxdbMultiplierTot(patch.size(), vector::zero);
if (includeObjective_)
{
// Term from objectives multiplying dxdb
forAll(functions, funcI)
{
const scalar wei = functions[funcI].weight();
// dt added in wallFaceSens_
dxdbMultiplierTot +=
functions[funcI].weight()
* functions[funcI].dxdbDirectMultiplier(patchI);
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] =
wallFaceSens_()[patchI] +=
(
stressTerm
+ gradStressTerm
+ pressureTerm
+ distanceTerm
+ meshMovementTerm
+ adjointTMsensitivities[patchI]
+ dxdbMultiplierTot;
wallFaceSens()[patchI] *= magSf;
+ dxdbMultiplierTot
)*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.
@ -437,104 +622,10 @@ const scalarField& sensitivitySurfacePoints::calculateSensitivities()
// A bit expensive? Better way?
vectorField pointNormals(mesh_.nPoints(), vector::zero);
scalarField pointMagSf(mesh_.nPoints(), Zero);
// 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];
const scalarField& magSf = patch.magSf();
vectorField nf(patch.nf());
// Point sens result for patch
vectorField& pointPatchSens = wallPointSensVecPtr_()[patchI];
// Face sens for patch
const vectorField& facePatchSens = wallFaceSens()[patchI];
vectorField dSdbMultiplierTot(patch.size(), vector::zero);
vectorField dndbMultiplierTot(patch.size(), vector::zero);
forAll(functions, funcI)
{
dSdbMultiplierTot +=
functions[funcI].weight() //includes surface by itself
*functions[funcI].dSdbMultiplier(patchI);
dndbMultiplierTot +=
functions[funcI].weight()
*functions[funcI].dndbMultiplier(patchI)
*magSf;
}
// 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(), tensor::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] +=
dSdbMultiplierTot[localFaceIndex] & deltaSf;
// Element [2] is the variation in the unit normal
const tensor& deltaNf = deltaNormals[2];
pointPatchSens[ppI] +=
dndbMultiplierTot[localFaceIndex] & deltaNf;
}
// Accumulate information for point normals
pointNormals[meshPoints[ppI]] += nf[localFaceIndex];
pointMagSf[meshPoints[ppI]] += magSf[localFaceIndex];
}
}
}
constructGlobalPointNormalsAndAreas(pointNormals, pointMagSf);
// Do parallel communications to avoid wrong values at processor boundaries
// - global field for accumulation
// Global field for accumulation
vectorField pointSensGlobal(mesh_.nPoints(), vector::zero);
for (const label patchI : sensitivityPatchIDs_)
{
@ -547,7 +638,7 @@ const scalarField& sensitivitySurfacePoints::calculateSensitivities()
}
}
// Accumulate dJ/dx_i, pointNormals and pointFaces number
// Accumulate dJ/dx_i
syncTools::syncPointList
(
mesh_,
@ -555,20 +646,6 @@ const scalarField& sensitivitySurfacePoints::calculateSensitivities()
plusEqOp<vector>(),
vector::zero
);
syncTools::syncPointList
(
mesh_,
pointNormals,
plusEqOp<vector>(),
vector::zero
);
syncTools::syncPointList
(
mesh_,
pointMagSf,
plusEqOp<scalar>(),
scalar(0)
);
// Transfer back to local fields
for (const label patchI : sensitivityPatchIDs_)
@ -588,7 +665,7 @@ const scalarField& sensitivitySurfacePoints::calculateSensitivities()
{
const labelList& meshPoints = patch.meshPoints();
// avoid storing unit point normals in the global list since we
// 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);
@ -644,26 +721,37 @@ const scalarField& sensitivitySurfacePoints::calculateSensitivities()
}
}
}
}
// Write sens fields
write(type());
return (derivatives_);
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::clear();
}
void sensitivitySurfacePoints::write(const word& baseName)
{
//determine suffix for fields holding the sens
if (includeMeshMovement_)
{
surfaceFieldSuffix_ = "ESI";
}
else
{
surfaceFieldSuffix_ = "SI";
}
setSuffixName();
adjointSensitivity::write();
shapeSensitivitiesBase::write();
}

View File

@ -41,6 +41,7 @@ SourceFiles
#define sensitivitySurfacePointsIncompressible_H
#include "adjointSensitivityIncompressible.H"
#include "shapeSensitivitiesBase.H"
#include "adjointEikonalSolverIncompressible.H"
#include "adjointMeshMovementSolverIncompressible.H"
#include "deltaBoundary.H"
@ -59,14 +60,13 @@ namespace incompressible
class sensitivitySurfacePoints
:
public adjointSensitivity
public adjointSensitivity,
public shapeSensitivitiesBase
{
protected:
// Protected data
//- Scalar normal sens
scalarField derivatives_;
//- Include surface area in sens computation
bool includeSurfaceArea_;
@ -96,12 +96,42 @@ protected:
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
//- Read controls and update solver pointers if necessary
void read();
//- 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
//- ones directly computed in points (i.e. dSf/db and dnf/db).
void finalisePointSensitivities();
//- Construct globally correct point normals and point areas
void constructGlobalPointNormalsAndAreas
(
vectorField& pointNormals,
scalarField& pointMagSf
);
//- Set suffix name for sensitivity fields
void setSuffixName();
private:
@ -143,8 +173,14 @@ public:
//- Read dict if changed
virtual bool readDict(const dictionary& dict);
//- Calculates sensitivities at wall surface points
const scalarField& calculateSensitivities();
//- Accumulate sensitivity integrands
virtual void accumulateIntegrand(const scalar dt);
//- Assemble sensitivities
virtual void assembleSensitivities();
//- Zero sensitivity fields and their constituents
virtual void clearSensitivities();
virtual void write(const word& baseName = word::null);
};

View File

@ -0,0 +1,317 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "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(vector::zero);
vector dndbSensCP(vector::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;
}
boxes[iNURB].boundControlPointMovement(dSdbSens_);
boxes[iNURB].boundControlPointMovement(dndbSens_);
passedCPs += nb;
}
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];
}
boxes[iNURB].boundControlPointMovement(dxdbDirectSens_);
passedCPs += sensDxDbDirect.size();
}
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
sensitivityVolBSplines::sensitivityVolBSplines
(
const fvMesh& mesh,
const dictionary& dict,
incompressibleVars& primalVars,
incompressibleAdjointVars& adjointVars,
objectiveManager& objectiveManager,
fv::optionAdjointList& fvOptionsAdjoint
)
:
SIBase
(
mesh,
dict,
primalVars,
adjointVars,
objectiveManager,
fvOptionsAdjoint
),
volBSplinesBase_
(
const_cast<volBSplinesBase&>(volBSplinesBase::New(mesh))
),
flowSens_(0),
dSdbSens_(0),
dndbSens_(0),
dxdbDirectSens_(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, vector::zero);
dSdbSens_ = vectorField(nCPs, vector::zero);
dndbSens_ = vectorField(nCPs, vector::zero);
dxdbDirectSens_ = vectorField(nCPs, vector::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();
boxes[iNURB].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();
// 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();
derivatives_[3*cpI + 1] =
flowSens_[cpI].y()
+ dSdbSens_[cpI].y()
+ dndbSens_[cpI].y()
+ dxdbDirectSens_[cpI].y();
derivatives_[3*cpI + 2] =
flowSens_[cpI].z()
+ dSdbSens_[cpI].z()
+ dndbSens_[cpI].z()
+ dxdbDirectSens_[cpI].z();
}
}
void sensitivityVolBSplines::clearSensitivities()
{
flowSens_ = vector::zero;
dSdbSens_ = vector::zero;
dndbSens_ = vector::zero;
dxdbDirectSens_ = vector::zero;
SIBase::clearSensitivities();
}
void sensitivityVolBSplines::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(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" << 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()
<< endl;
}
}
passedCPs += nb;
}
}
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace incompressible
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,148 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
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 dependng on dxdb for objective funtions directly depending
//- on x
vectorField dxdbDirectSens_;
fileName derivativesFolder_;
// Protected Member Functions
void computeObjectiveContributions();
private:
// Private Member Functions
//- Disallow default bitwise copy construct
sensitivityVolBSplines(const sensitivityVolBSplines&) = delete;
//- Disallow default bitwise assignment
void operator=(const sensitivityVolBSplines&) = delete;
public:
//- Runtime type information
TypeName("volumetricBSplines");
// Constructors
//- Construct from components
sensitivityVolBSplines
(
const fvMesh& mesh,
const dictionary& dict,
incompressibleVars& primalVars,
incompressibleAdjointVars& adjointVars,
objectiveManager& objectiveManager,
fv::optionAdjointList& fvOptionsAdjoint
);
//- 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
// ************************************************************************* //

View File

@ -0,0 +1,415 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "sensitivityVolBSplinesFIIncompressible.H"
#include "pointVolInterpolation.H"
#include "fvOptionAdjoint.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,
incompressibleVars& primalVars,
incompressibleAdjointVars& adjointVars,
objectiveManager& objectiveManager,
fv::optionAdjointList& fvOptionsAdjoint
)
:
FIBase
(
mesh,
dict,
primalVars,
adjointVars,
objectiveManager,
fvOptionsAdjoint
),
volBSplinesBase_
(
const_cast<volBSplinesBase&>(volBSplinesBase::New(mesh))
),
flowSens_(0),
dSdbSens_(0),
dndbSens_(0),
dxdbDirectSens_(0),
dVdbSens_(0),
distanceSens_(0),
optionsSens_(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, vector::zero);
dSdbSens_ = vectorField(nCPs, vector::zero);
dndbSens_ = vectorField(nCPs, vector::zero);
dxdbDirectSens_ = vectorField(nCPs, vector::zero);
dVdbSens_ = vectorField(nCPs, vector::zero);
distanceSens_ = vectorField(nCPs, vector::zero);
optionsSens_ = vectorField(nCPs, vector::zero);
// Create folder to store sensitivities
mkDir(derivativesFolder_);
};
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void 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)
{
label nb = boxes[iNURB].getControlPoints().size();
vectorField boxSensitivities(nb, vector::zero);
vectorField dxdbSens = boxes[iNURB].computeControlPointSensitivities
(
dxdbDirectMult_(),
sensitivityPatchIDs_.toc()
);
for (label cpI = 0; cpI < nb; cpI++)
{
label globalCP = passedCPs + cpI;
// Parameterization info
tmp<pointTensorField> dxdbI(boxes[iNURB].getDxDb(cpI));
tmp<volTensorField> tvolDxDbI(volPointInter.interpolate(dxdbI));
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();
*/
// Gradient of parameterization info
volVectorField temp
(
IOobject
(
"dxdb",
mesh_.time().timeName(),
mesh_,
IOobject::NO_READ,
IOobject::NO_WRITE
),
mesh_,
vector::zero
);
temp.replace(0, volDxDbI.component(0));
temp.replace(1, volDxDbI.component(3));
temp.replace(2, volDxDbI.component(6));
volTensorField gradDxDb1(fvc::grad(temp));
temp.replace(0, volDxDbI.component(1));
temp.replace(1, volDxDbI.component(4));
temp.replace(2, volDxDbI.component(7));
volTensorField gradDxDb2(fvc::grad(temp));
temp.replace(0, volDxDbI.component(2));
temp.replace(1, volDxDbI.component(5));
temp.replace(2, volDxDbI.component(8));
volTensorField gradDxDb3(fvc::grad(temp));
// Volume integral terms
flowSens_[globalCP].x() = gSum
(
(gradDxDbMult_.primitiveField() && gradDxDb1.primitiveField())
*mesh_.V()
);
flowSens_[globalCP].y() = gSum
(
(gradDxDbMult_.primitiveField() && gradDxDb2.primitiveField())
*mesh_.V()
);
flowSens_[globalCP].z() = gSum
(
(gradDxDbMult_.primitiveField() && gradDxDb3.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()
);
// Distance dependent term
if (includeDistance_)
{
const tensorField& distSensInt =
distanceSensPtr().primitiveField();
distanceSens_[globalCP].x() =
gSum
(
(distSensInt && gradDxDb1.primitiveField())*mesh_.V()
);
distanceSens_[globalCP].y() =
gSum
(
(distSensInt && gradDxDb2.primitiveField())*mesh_.V()
);
distanceSens_[globalCP].z() =
gSum
(
(distSensInt && gradDxDb3.primitiveField()) *mesh_.V()
);
}
// Terms from fvOptions
optionsSens_[globalCP] +=
gSum((optionsDxDbMult_ & volDxDbI.primitiveField())*mesh_.V());
// dxdbSens storage
dxdbDirectSens_[globalCP] = dxdbSens[cpI];
boxSensitivities[cpI] =
flowSens_[globalCP]
+ dSdbSens_[globalCP]
+ dndbSens_[globalCP]
+ dVdbSens_[globalCP]
+ distanceSens_[globalCP]
+ dxdbDirectSens_[globalCP]
+ optionsSens_[globalCP];
}
// Zero sensitivities in non-active design variables
boxes[iNURB].boundControlPointMovement(flowSens_);
boxes[iNURB].boundControlPointMovement(dSdbSens_);
boxes[iNURB].boundControlPointMovement(dndbSens_);
boxes[iNURB].boundControlPointMovement(dVdbSens_);
boxes[iNURB].boundControlPointMovement(distanceSens_);
boxes[iNURB].boundControlPointMovement(dxdbDirectSens_);
boxes[iNURB].boundControlPointMovement(optionsSens_);
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;
}
}
void sensitivityVolBSplinesFI::clearSensitivities()
{
flowSens_ = vector::zero;
dSdbSens_ = vector::zero;
dndbSens_ = vector::zero;
dxdbDirectSens_ = vector::zero;
dVdbSens_ = vector::zero;
distanceSens_ = vector::zero;
optionsSens_ = 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" << 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() << endl;
}
}
passedCPs += nb;
}
}
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace incompressible
} // End namespace Foam
// ************************************************************************* //

View File

@ -0,0 +1,152 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
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_;
fileName derivativesFolder_;
private:
// Private Member Functions
//- Disallow default bitwise copy construct
sensitivityVolBSplinesFI(const sensitivityVolBSplinesFI&) = delete;
//- Disallow default bitwise assignment
void operator=(const sensitivityVolBSplinesFI&) = delete;
public:
//- Runtime type information
TypeName("volumetricBSplinesFI");
// Constructors
//- Construct from components
sensitivityVolBSplinesFI
(
const fvMesh& mesh,
const dictionary& dict,
incompressibleVars& primalVars,
incompressibleAdjointVars& adjointVars,
objectiveManager& objectiveManager,
fv::optionAdjointList& fvOptionsAdjoint
);
//- 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
// ************************************************************************* //

View File

@ -38,136 +38,18 @@ namespace Foam
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
void Foam::sensitivity::writeFaceBasedSens() const
{
const word suffix(adjointSolverName_ + surfaceFieldSuffix_);
// Wall face sensitivity projected to normal
if (wallFaceSensNormalPtr_.valid())
{
constructAndWriteSensitivityField<scalar>
(
wallFaceSensNormalPtr_,
"faceSensNormal" + suffix
);
}
if (writeAllSurfaceFiles_)
{
// Wall face sensitivity vectors
if (wallFaceSensVecPtr_.valid())
{
constructAndWriteSensitivityField<vector>
(
wallFaceSensVecPtr_,
"faceSensVec" + suffix
);
}
// Normal sens as vectors
if (wallFaceSensNormalVecPtr_.valid())
{
constructAndWriteSensitivityField<vector>
(
wallFaceSensNormalVecPtr_,
"faceSensNormalVec" + suffix
);
}
}
}
void Foam::sensitivity::writePointBasedSens() const
{
const word suffix(adjointSolverName_ + surfaceFieldSuffix_);
// Wall point sensitivity projected to normal
if (wallPointSensNormalPtr_.valid())
{
constructAndWriteSensitivtyPointField<scalar>
(
wallPointSensNormalPtr_,
"pointSensNormal" + suffix
);
}
// Write point-based sensitivities, if present
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (writeAllSurfaceFiles_)
{
// Wall point sensitivity vectors
if (wallPointSensVecPtr_.valid())
{
constructAndWriteSensitivtyPointField<vector>
(
wallPointSensVecPtr_,
"pointSensVec" + suffix
);
}
// Normal point as vectors
if (wallPointSensNormalVecPtr_.valid())
{
constructAndWriteSensitivtyPointField<vector>
(
wallPointSensNormalVecPtr_,
"pointSensNormalVec" + suffix
);
}
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::sensitivity::sensitivity
(
const fvMesh& mesh,
const dictionary& dict,
const word& adjointSolverName
const dictionary& dict
)
:
mesh_(mesh),
dict_(dict),
sensitivityPatchIDs_(0),
adjointSolverName_(adjointSolverName),
surfaceFieldSuffix_(word::null),
writeAllSurfaceFiles_
(
dict.lookupOrDefault<bool>
(
"writeAllSurfaceFiles",
false
)
),
wallFaceSensVecPtr_(nullptr),
wallFaceSensNormalPtr_(nullptr),
wallFaceSensNormalVecPtr_(nullptr),
wallPointSensVecPtr_(nullptr),
wallPointSensNormalPtr_(nullptr),
wallPointSensNormalVecPtr_(nullptr),
fieldSensPtr_(nullptr)
{
labelHashSet patches
(
mesh_.boundaryMesh().patchSet(dict.get<wordRes>("patches"))
);
if (patches.empty())
{
WarningInFunction
<< "There is no patch on which to compute sensitivities. "
<< "Check optimisationDict" << nl
<< endl;
}
sensitivityPatchIDs_ = patches.toc();
};
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * //
@ -186,18 +68,6 @@ bool Foam::sensitivity::readDict(const dictionary& dict)
}
const Foam::labelList& Foam::sensitivity::sensitivityPatchIDs() const
{
return sensitivityPatchIDs_;
}
void Foam::sensitivity::setSensitivityPatchIDs(const labelList& sensPatchIDs)
{
sensitivityPatchIDs_ = sensPatchIDs;
}
void Foam::sensitivity::computeDerivativesSize()
{
// Does nothing
@ -206,10 +76,6 @@ void Foam::sensitivity::computeDerivativesSize()
void Foam::sensitivity::write(const word& baseName)
{
writeFaceBasedSens();
writePointBasedSens();
if (fieldSensPtr_.valid())
{
fieldSensPtr_().write();
@ -217,143 +83,4 @@ void Foam::sensitivity::write(const word& baseName)
}
Foam::tmp<Foam::volVectorField> Foam::sensitivity::getWallFaceSensVec()
{
if (wallFaceSensVecPtr_.valid())
{
return
constructVolSensitivtyField<vector>
(
wallFaceSensVecPtr_,
"faceSensVec" + adjointSolverName_
);
}
else
{
WarningInFunction
<< " no faceSensVec boundary field. Returning zero" << endl;
return
tmp<volVectorField>
(
createZeroFieldPtr<vector>
(
mesh_,
"faceSensVec" + adjointSolverName_,
dimless
).ptr()
);
}
}
Foam::tmp<Foam::volScalarField> Foam::sensitivity::getWallFaceSensNormal()
{
if (wallFaceSensNormalPtr_.valid())
{
return
constructVolSensitivtyField<scalar>
(
wallFaceSensNormalPtr_,
"faceSensNormal" + adjointSolverName_
);
}
else
{
WarningInFunction
<< " no wallFaceSensNormal boundary field. Returning zero" << endl;
return
tmp<volScalarField>
(
createZeroFieldPtr<scalar>
(
mesh_,
"faceSensNormal" + adjointSolverName_, dimless
).ptr()
);
}
}
Foam::tmp<Foam::volVectorField> Foam::sensitivity::getWallFaceSensNormalVec()
{
if (wallFaceSensNormalVecPtr_.valid())
{
return
constructVolSensitivtyField<vector>
(
wallFaceSensNormalVecPtr_,
"faceSensNormalVec" + adjointSolverName_
);
}
else
{
WarningInFunction
<< " no wallFaceSensNormalVec boundary field. Returning zero"
<< endl;
return
tmp<volVectorField>
(
createZeroFieldPtr<vector>
(
mesh_,
"faceSensNormalVec" + adjointSolverName_,
dimless
).ptr()
);
}
}
Foam::tmp<Foam::pointVectorField> Foam::sensitivity::getWallPointSensVec()
{
tmp<volVectorField> tWallFaceSensVec = getWallFaceSensVec();
volPointInterpolation volPointInter(mesh_);
return (volPointInter.interpolate(tWallFaceSensVec));
}
Foam::tmp<Foam::pointScalarField> Foam::sensitivity::getWallPointSensNormal()
{
tmp<volScalarField> tWallFaceSensNormal = getWallFaceSensNormal();
volPointInterpolation volPointInter(mesh_);
return (volPointInter.interpolate(tWallFaceSensNormal));
}
Foam::tmp<Foam::pointVectorField>
Foam::sensitivity::getWallPointSensNormalVec()
{
tmp<volVectorField> tWallFaceSensNormalVec = getWallFaceSensNormalVec();
volPointInterpolation volPointInter(mesh_);
return (volPointInter.interpolate(tWallFaceSensNormalVec));
}
const Foam::boundaryVectorField&
Foam::sensitivity::getWallFaceSensVecBoundary() const
{
return wallFaceSensVecPtr_();
}
const Foam::boundaryScalarField&
Foam::sensitivity::getWallFaceSensNormalBoundary() const
{
return wallFaceSensNormalPtr_();
}
const Foam::boundaryVectorField&
Foam::sensitivity::getWallFaceSensNormalVecBoundary() const
{
return wallFaceSensNormalVecPtr_();
}
// ************************************************************************* //

View File

@ -70,85 +70,13 @@ protected:
const fvMesh& mesh_;
dictionary dict_;
// Cleaner option to go for a labelHashSet. Kept this way for
// compatibility
labelList sensitivityPatchIDs_;
word adjointSolverName_;
word surfaceFieldSuffix_;
bool writeAllSurfaceFiles_;
// autoPtrs for fields holding sensitivities.
// Not all of them are required for each case
// Boundary sensitivities at faces. Shape opt & flow control
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//- Wall face sens w.r.t. (x,y.z)
autoPtr<boundaryVectorField> wallFaceSensVecPtr_;
//- Wall face sens projected to normal
autoPtr<boundaryScalarField> wallFaceSensNormalPtr_;
//- Normal sens as vectors
autoPtr<boundaryVectorField> wallFaceSensNormalVecPtr_;
// Boundary sensitivities at points. Shape opt
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//- Wall point sens w.r.t. (x,y.z)
autoPtr<pointBoundaryVectorField> wallPointSensVecPtr_;
//- Wall point sens projected to normal
autoPtr<pointBoundaryScalarField> wallPointSensNormalPtr_;
//- Normal sens as vectors
autoPtr<pointBoundaryVectorField> wallPointSensNormalVecPtr_;
//field sensitivities. Topology optimisation
// Field sensitivities. Topology optimisation
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
autoPtr<volScalarField> fieldSensPtr_;
// Protected Member Functions
//- Constructs volField based on boundaryField and writes it
template<class Type>
void constructAndWriteSensitivityField
(
const autoPtr
<
typename GeometricField<Type, fvPatchField, volMesh>::Boundary
>& sensFieldPtr,
const word& name
) const;
//- Constructs pointField based on boundaryField and writes it
template<class Type>
void constructAndWriteSensitivtyPointField
(
const autoPtr<List<Field<Type>>>& sensFieldPtr,
const word& name
) const;
//- Constructs volField based on boundaryField and writes it
template<class Type>
tmp<GeometricField<Type, fvPatchField, volMesh>>
constructVolSensitivtyField
(
const autoPtr
<
typename GeometricField<Type, fvPatchField, volMesh>::Boundary
>& sensFieldPtr,
const word& name
) const;
//- Write face-based sensitivities, if present
void writeFaceBasedSens() const;
//- Write point-based sensitivities, if present
void writePointBasedSens() const;
private:
// Private Member Functions
@ -171,8 +99,7 @@ public:
sensitivity
(
const fvMesh& mesh,
const dictionary& dict,
const word& adjointSolverName
const dictionary& dict
);
//- Destructor
@ -187,12 +114,6 @@ public:
//- Read dictionary if changed
virtual bool readDict(const dictionary& dict);
//- Get patch IDs on which sensitivities are computed
const labelList& sensitivityPatchIDs() const;
//- Overwrite sensitivityPatchIDs
void setSensitivityPatchIDs(const labelList& sensPatchIDs);
//- Compute design variables number. Does nothing in the base
// Used to get the correct design variables number when
// setSensitivityPatchIDs are not set in the constructor
@ -208,37 +129,6 @@ public:
// (Bezier, RBF) which do not need to write fields
virtual void write(const word& baseName = word::null);
//- Get wall face sensitivity vectors field
tmp<volVectorField> getWallFaceSensVec();
//- Get wall face sensitivity projected to normal field
tmp<volScalarField> getWallFaceSensNormal();
//- Get wall face normal sens as vectors field
tmp<volVectorField> getWallFaceSensNormalVec();
//- Get wall point sensitivity vectors field
// Uses volPointInterpolation
tmp<pointVectorField> getWallPointSensVec();
//- Get wall point sensitivity projected to normal field
// Uses volPointInterpolation
tmp<pointScalarField> getWallPointSensNormal();
//- Get wall point sens as vectors field
// Uses volPointInterpolation
tmp<pointVectorField> getWallPointSensNormalVec();
//- Get wall face sensitivity vectors field
virtual const boundaryVectorField& getWallFaceSensVecBoundary() const;
//- Get wall face sensitivity projected to normal field
virtual const boundaryScalarField&
getWallFaceSensNormalBoundary() const;
//- Get wall face normal sens as vectors field
virtual const boundaryVectorField&
getWallFaceSensNormalVecBoundary() const;
};
@ -248,9 +138,9 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "sensitivityTemplates.C"
#endif
//#ifdef NoRepository
// #include "sensitivityTemplates.C"
//#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -0,0 +1,373 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "shapeSensitivitiesBase.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(shapeSensitivitiesBase, 0);
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
void Foam::shapeSensitivitiesBase::writeFaceBasedSens() const
{
// Wall face sensitivity projected to normal
if (wallFaceSensNormalPtr_.valid())
{
constructAndWriteSensitivityField<scalar>
(
wallFaceSensNormalPtr_,
"faceSensNormal" + surfaceFieldSuffix_
);
}
if (writeAllSurfaceFiles_)
{
// Wall face sensitivity vectors
if (wallFaceSensVecPtr_.valid())
{
constructAndWriteSensitivityField<vector>
(
wallFaceSensVecPtr_,
"faceSensVec" + surfaceFieldSuffix_
);
}
// Normal sens as vectors
if (wallFaceSensNormalVecPtr_.valid())
{
constructAndWriteSensitivityField<vector>
(
wallFaceSensNormalVecPtr_,
"faceSensNormalVec" + surfaceFieldSuffix_
);
}
}
}
void Foam::shapeSensitivitiesBase::writePointBasedSens() const
{
// Wall point sensitivity projected to normal
if (wallPointSensNormalPtr_.valid())
{
constructAndWriteSensitivtyPointField<scalar>
(
wallPointSensNormalPtr_,
"pointSensNormal" + surfaceFieldSuffix_
);
}
// Write point-based sensitivities, if present
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
if (writeAllSurfaceFiles_)
{
// Wall point sensitivity vectors
if (wallPointSensVecPtr_.valid())
{
constructAndWriteSensitivtyPointField<vector>
(
wallPointSensVecPtr_,
"pointSensVec" + surfaceFieldSuffix_
);
}
// Normal point as vectors
if (wallPointSensNormalVecPtr_.valid())
{
constructAndWriteSensitivtyPointField<vector>
(
wallPointSensNormalVecPtr_,
"pointSensNormalVec" + surfaceFieldSuffix_
);
}
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::shapeSensitivitiesBase::shapeSensitivitiesBase
(
const fvMesh& mesh,
const dictionary& dict
)
:
meshShape_(mesh),
surfaceFieldSuffix_(word::null),
writeAllSurfaceFiles_
(
dict.lookupOrDefault<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::clear()
{
// Face-based boundary sens
if (wallFaceSensVecPtr_.valid())
{
wallFaceSensVecPtr_() = vector::zero;
}
if (wallFaceSensNormalVecPtr_.valid())
{
wallFaceSensNormalVecPtr_() = vector::zero;
}
if (wallFaceSensNormalPtr_.valid())
{
wallFaceSensNormalPtr_() = scalar(0);
}
// Point-based boundary sens
if (wallPointSensVecPtr_.valid())
{
for (vectorField& patchSens : wallPointSensVecPtr_())
{
patchSens = vector::zero;
}
}
if (wallPointSensNormalVecPtr_.valid())
{
for (vectorField& patchSens : wallPointSensNormalVecPtr_())
{
patchSens = vector::zero;
}
}
if (wallPointSensNormalPtr_.valid())
{
for (scalarField& patchSens : wallPointSensNormalPtr_())
{
patchSens = scalar(0);
}
}
}
void Foam::shapeSensitivitiesBase::write()
{
writeFaceBasedSens();
writePointBasedSens();
}
void Foam::shapeSensitivitiesBase::setSuffix(const word& suffix)
{
surfaceFieldSuffix_ = suffix;
}
Foam::tmp<Foam::volVectorField>
Foam::shapeSensitivitiesBase::getWallFaceSensVec()
{
if (wallFaceSensVecPtr_.valid())
{
return
constructVolSensitivtyField<vector>
(
wallFaceSensVecPtr_,
"faceSensVec" + surfaceFieldSuffix_
);
}
else
{
WarningInFunction
<< " no faceSensVec boundary field. Returning zero" << endl;
return
tmp<volVectorField>
(
createZeroFieldPtr<vector>
(
meshShape_,
"faceSensVec" + surfaceFieldSuffix_,
dimless
).ptr()
);
}
}
Foam::tmp<Foam::volScalarField>
Foam::shapeSensitivitiesBase::getWallFaceSensNormal()
{
if (wallFaceSensNormalPtr_.valid())
{
return
constructVolSensitivtyField<scalar>
(
wallFaceSensNormalPtr_,
"faceSensNormal" + surfaceFieldSuffix_
);
}
else
{
WarningInFunction
<< " no wallFaceSensNormal boundary field. Returning zero" << endl;
return
tmp<volScalarField>
(
createZeroFieldPtr<scalar>
(
meshShape_,
"faceSensNormal" + surfaceFieldSuffix_, dimless
).ptr()
);
}
}
Foam::tmp<Foam::volVectorField>
Foam::shapeSensitivitiesBase::getWallFaceSensNormalVec()
{
if (wallFaceSensNormalVecPtr_.valid())
{
return
constructVolSensitivtyField<vector>
(
wallFaceSensNormalVecPtr_,
"faceSensNormalVec" + surfaceFieldSuffix_
);
}
else
{
WarningInFunction
<< " no wallFaceSensNormalVec boundary field. Returning zero"
<< endl;
return
tmp<volVectorField>
(
createZeroFieldPtr<vector>
(
meshShape_,
"faceSensNormalVec" + surfaceFieldSuffix_,
dimless
).ptr()
);
}
}
Foam::tmp<Foam::pointVectorField>
Foam::shapeSensitivitiesBase::getWallPointSensVec()
{
tmp<volVectorField> tWallFaceSensVec = getWallFaceSensVec();
volPointInterpolation volPointInter(meshShape_);
return (volPointInter.interpolate(tWallFaceSensVec));
}
Foam::tmp<Foam::pointScalarField>
Foam::shapeSensitivitiesBase::getWallPointSensNormal()
{
tmp<volScalarField> tWallFaceSensNormal = getWallFaceSensNormal();
volPointInterpolation volPointInter(meshShape_);
return (volPointInter.interpolate(tWallFaceSensNormal));
}
Foam::tmp<Foam::pointVectorField>
Foam::shapeSensitivitiesBase::getWallPointSensNormalVec()
{
tmp<volVectorField> tWallFaceSensNormalVec = getWallFaceSensNormalVec();
volPointInterpolation volPointInter(meshShape_);
return (volPointInter.interpolate(tWallFaceSensNormalVec));
}
const Foam::boundaryVectorField&
Foam::shapeSensitivitiesBase::getWallFaceSensVecBoundary() const
{
return wallFaceSensVecPtr_();
}
const Foam::boundaryScalarField&
Foam::shapeSensitivitiesBase::getWallFaceSensNormalBoundary() const
{
return wallFaceSensNormalPtr_();
}
const Foam::boundaryVectorField&
Foam::shapeSensitivitiesBase::getWallFaceSensNormalVecBoundary() const
{
return wallFaceSensNormalVecPtr_();
}
// ************************************************************************* //

View File

@ -0,0 +1,240 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Class
Foam::incompressible::shapeSensitivitiesBase
Description
Base class supporting shape sensitivity derivatives
SourceFiles
shapeSensitivitiesBase.C
\*---------------------------------------------------------------------------*/
#ifndef shapeSensitivitiesBase_H
#define shapeSensitivitiesBase_H
#include "volFields.H"
#include "surfaceFields.H"
#include "dictionary.H"
#include "volPointInterpolation.H"
#include "pointMesh.H"
#include "pointPatchField.H"
#include "pointPatchFieldsFwd.H"
#include "fixedValuePointPatchField.H"
#include "boundaryFieldsFwd.H"
#include "createZeroField.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class shapeSensitivitiesBase Declaration
\*---------------------------------------------------------------------------*/
class shapeSensitivitiesBase
{
protected:
// Protected data
const fvMesh& meshShape_;
word surfaceFieldSuffix_;
bool writeAllSurfaceFiles_;
// Patches on which to compute shape sensitivities
labelHashSet sensitivityPatchIDs_;
// autoPtrs for fields holding sensitivities.
// Not all of them are required for each case
// Boundary sensitivities at faces. Shape opt & flow control
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//- Wall face sens w.r.t. (x,y.z)
autoPtr<boundaryVectorField> wallFaceSensVecPtr_;
//- Wall face sens projected to normal
autoPtr<boundaryScalarField> wallFaceSensNormalPtr_;
//- Normal sens as vectors
autoPtr<boundaryVectorField> wallFaceSensNormalVecPtr_;
// Boundary sensitivities at points. Shape opt
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//- Wall point sens w.r.t. (x,y.z)
autoPtr<pointBoundaryVectorField> wallPointSensVecPtr_;
//- Wall point sens projected to normal
autoPtr<pointBoundaryScalarField> wallPointSensNormalPtr_;
//- Normal sens as vectors
autoPtr<pointBoundaryVectorField> wallPointSensNormalVecPtr_;
//- Constructs volField based on boundaryField and writes it
template<class Type>
void constructAndWriteSensitivityField
(
const autoPtr
<
typename GeometricField<Type, fvPatchField, volMesh>::Boundary
>& sensFieldPtr,
const word& name
) const;
//- Constructs pointField based on boundaryField and writes it
template<class Type>
void constructAndWriteSensitivtyPointField
(
const autoPtr<List<Field<Type>>>& sensFieldPtr,
const word& name
) const;
//- Constructs volField based on boundaryField and writes it
template<class Type>
tmp<GeometricField<Type, fvPatchField, volMesh>>
constructVolSensitivtyField
(
const autoPtr
<
typename GeometricField<Type, fvPatchField, volMesh>::Boundary
>& sensFieldPtr,
const word& name
) const;
//- Write face-based sensitivities, if present
void writeFaceBasedSens() const;
//- Write point-based sensitivities, if present
void writePointBasedSens() const;
private:
// Private Member Functions
//- Disallow default bitwise copy construct
shapeSensitivitiesBase(const shapeSensitivitiesBase&) = delete;
//- Disallow default bitwise assignment
void operator=(const shapeSensitivitiesBase&) = delete;
public:
//- Runtime type information
TypeName("shapeSensitivitiesBase");
// Constructors
//- Construct from components
shapeSensitivitiesBase
(
const fvMesh& mesh,
const dictionary& dict
);
//- Destructor
virtual ~shapeSensitivitiesBase() = default;
// Member Functions
//- Get patch IDs on which sensitivities are computed
const labelHashSet& sensitivityPatchIDs() const;
//- Overwrite sensitivityPatchIDs
void setSensitivityPatchIDs(const labelHashSet& sensPatchIDs);
//- Zero sensitivity fields and their constituents
void clear();
//- Write sensitivity fields.
// If valid, copies boundaryFields to volFields and writes them.
void write();
//- Set suffix
void setSuffix(const word& suffix);
//- Get wall face sensitivity vectors field
tmp<volVectorField> getWallFaceSensVec();
//- Get wall face sensitivity projected to normal field
tmp<volScalarField> getWallFaceSensNormal();
//- Get wall face normal sens as vectors field
tmp<volVectorField> getWallFaceSensNormalVec();
//- Get wall point sensitivity vectors field
// Uses volPointInterpolation
tmp<pointVectorField> getWallPointSensVec();
//- Get wall point sensitivity projected to normal field
// Uses volPointInterpolation
tmp<pointScalarField> getWallPointSensNormal();
//- Get wall point sens as vectors field
// Uses volPointInterpolation
tmp<pointVectorField> getWallPointSensNormalVec();
//- Get wall face sensitivity vectors field
virtual const boundaryVectorField& getWallFaceSensVecBoundary() const;
//- Get wall face sensitivity projected to normal field
virtual const boundaryScalarField&
getWallFaceSensNormalBoundary() const;
//- Get wall face normal sens as vectors field
virtual const boundaryVectorField&
getWallFaceSensNormalVecBoundary() const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "shapeSensitivitiesBaseTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -27,7 +27,7 @@ License
\*---------------------------------------------------------------------------*/
#include "sensitivity.H"
#include "shapeSensitivitiesBase.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -37,7 +37,7 @@ namespace Foam
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
template<class Type>
void sensitivity::constructAndWriteSensitivityField
void shapeSensitivitiesBase::constructAndWriteSensitivityField
(
const autoPtr
<
@ -51,18 +51,17 @@ void sensitivity::constructAndWriteSensitivityField
IOobject
(
name,
mesh_.time().timeName(),
mesh_,
meshShape_.time().timeName(),
meshShape_,
IOobject::NO_READ,
IOobject::NO_WRITE
),
mesh_,
meshShape_,
dimensioned<Type>(dimless, Zero)
);
forAll(sensitivityPatchIDs_, pI)
for (const label patchI : sensitivityPatchIDs_)
{
const label patchI = sensitivityPatchIDs_[pI];
volSensField.boundaryFieldRef()[patchI] = sensFieldPtr()[patchI];
}
@ -71,7 +70,7 @@ void sensitivity::constructAndWriteSensitivityField
template<class Type>
void sensitivity::constructAndWriteSensitivtyPointField
void shapeSensitivitiesBase::constructAndWriteSensitivtyPointField
(
const autoPtr<List<Field<Type>>>& sensFieldPtr,
const word& name
@ -82,20 +81,20 @@ void sensitivity::constructAndWriteSensitivtyPointField
IOobject
(
name,
mesh_.time().timeName(),
mesh_,
meshShape_.time().timeName(),
meshShape_,
IOobject::NO_READ,
IOobject::NO_WRITE
),
pointMesh::New(mesh_),
pointMesh::New(meshShape_),
dimensioned<Type>(dimless, Zero)
// fixedValuePointPatchField<Type>::typeName
//fixedValuePointPatchField<Type>::typeName
);
forAll(sensitivityPatchIDs_, pI)
for (const label patchI : sensitivityPatchIDs_)
{
const label patchI = sensitivityPatchIDs_[pI];
// Paraview does not visualise values on fixedValuePointPatchFields
// Only option is to store in internalField
//pointSensField.boundaryFieldRef()[patchI] == sensFieldPtr()[patchI];
pointSensField.boundaryField()[patchI].setInInternalField
(
@ -110,7 +109,7 @@ void sensitivity::constructAndWriteSensitivtyPointField
template<class Type>
tmp<GeometricField<Type, fvPatchField, volMesh>>
sensitivity::constructVolSensitivtyField
shapeSensitivitiesBase::constructVolSensitivtyField
(
const autoPtr
<
@ -126,12 +125,12 @@ sensitivity::constructVolSensitivtyField
IOobject
(
name,
mesh_.time().timeName(),
mesh_,
meshShape_.time().timeName(),
meshShape_,
IOobject::NO_READ,
IOobject::NO_WRITE
),
mesh_,
meshShape_,
pTraits<Type>::zero
)
);

View File

@ -0,0 +1,79 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "ArmijoConditions.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(ArmijoConditions, 0);
addToRunTimeSelectionTable
(
lineSearch,
ArmijoConditions,
dictionary
);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::ArmijoConditions::ArmijoConditions
(
const dictionary& dict,
const Time& time
)
:
lineSearch(dict, time),
c1_(coeffsDict().lookupOrDefault<scalar>("c1", 1.e-4))
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * //
bool Foam::ArmijoConditions::converged()
{
Info<< "New merit function value " << newMeritValue_ << endl;
Info<< "Old merit function value " << oldMeritValue_ << endl;
Info<< "Extrapolated merit function value "
<< oldMeritValue_ + c1_*step_*directionalDeriv_ << endl;
return newMeritValue_ < oldMeritValue_ + c1_*step_*directionalDeriv_;
}
void Foam::ArmijoConditions::updateStep()
{
stepUpdate_->updateStep(step_);
Info<< "Using step " << step_ << endl;
}
// ************************************************************************* //

View File

@ -0,0 +1,127 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Class
Foam::ArmijoConditions
Description
Class satisfying the Armijo line search conditions
SourceFiles
ArmijoConditions.C
\*---------------------------------------------------------------------------*/
#ifndef ArmijoConditions_H
#define ArmijoConditions_H
#include "lineSearch.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class ArmijoConditions Declaration
\*---------------------------------------------------------------------------*/
class ArmijoConditions
:
public lineSearch
{
protected:
// Protected data
//- Multiplier of the merit function reduction computed using
//- a first-order Taylor expansion
scalar c1_;
private:
// Private Member Functions
//- Disallow default bitwise copy construct
ArmijoConditions(const ArmijoConditions&) = delete;
//- Disallow default bitwise assignment
void operator=(const ArmijoConditions&) = delete;
public:
//- Runtime type information
TypeName("ArmijoConditions");
// Declare run-time constructor selection table
declareRunTimeSelectionTable
(
autoPtr,
ArmijoConditions,
dictionary,
(
const dictionary& dict,
const Time& time
),
(dict)
);
// Constructors
//- Construct from components
ArmijoConditions(const dictionary& dict, const Time& time);
// Destructor
virtual ~ArmijoConditions() = default;
// Member Functions
//Return the correction of the design variables
virtual bool converged();
//Update step in given direction
virtual void updateStep();
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -30,19 +30,26 @@ License
#include "lineSearch.H"
#include "Time.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(lineSearch, 0);
defineRunTimeSelectionTable(lineSearch, dictionary);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
defineTypeNameAndDebug(lineSearch, 0);
defineRunTimeSelectionTable(lineSearch, dictionary);
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
const Foam::dictionary& Foam::lineSearch::coeffsDict()
{
return dict_.optionalSubDict(type() + "Coeffs");
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
lineSearch::lineSearch(const dictionary& dict, const Time& time)
Foam::lineSearch::lineSearch(const dictionary& dict, const Time& time)
:
dict_(dict),
lineSearchDict_
@ -66,11 +73,11 @@ lineSearch::lineSearch(const dictionary& dict, const Time& time)
(
lineSearchDict_.lookupOrDefault<scalar>("prevMeritDeriv", Zero)
),
initialStep_(dict.lookupOrDefault<scalar>("initialStep", 1)),
initialStep_(dict.lookupOrDefault<scalar>("initialStep", 1.)),
minStep_(dict.lookupOrDefault<scalar>("minStep", 0.3)),
step_(Zero),
iter_(lineSearchDict_.lookupOrDefault<label>("iter", 0)),
maxIters_(dict.lookupOrDefault<scalar>("maxIters", 10)),
maxIters_(dict.lookupOrDefault<label>("maxIters", 4)),
extrapolateInitialStep_
(
dict.lookupOrDefault<bool>
@ -85,7 +92,7 @@ lineSearch::lineSearch(const dictionary& dict, const Time& time)
// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * * //
autoPtr<lineSearch> lineSearch::New
Foam::autoPtr<Foam::lineSearch> Foam::lineSearch::New
(
const dictionary& dict,
const Time& time
@ -93,7 +100,7 @@ autoPtr<lineSearch> lineSearch::New
{
autoPtr<lineSearch> lineSrch(nullptr);
const word modelType(dict.getOrDefault<word>("lineSearchType", "none"));
const word modelType(dict.getOrDefault<word>("type", "none"));
Info<< "lineSearch type : " << modelType << endl;
@ -126,34 +133,34 @@ autoPtr<lineSearch> lineSearch::New
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * //
void lineSearch::setDeriv(const scalar deriv)
void Foam::lineSearch::setDeriv(const scalar deriv)
{
directionalDeriv_ = deriv;
stepUpdate_->setDeriv(deriv);
}
void lineSearch::setDirection(const scalarField& direction)
void Foam::lineSearch::setDirection(const scalarField& direction)
{
direction_ = direction;
}
void lineSearch::setNewMeritValue(const scalar value)
void Foam::lineSearch::setNewMeritValue(const scalar value)
{
newMeritValue_ = value;
stepUpdate_->setNewMeritValue(value);
}
void lineSearch::setOldMeritValue(const scalar value)
void Foam::lineSearch::setOldMeritValue(const scalar value)
{
oldMeritValue_ = value;
stepUpdate_->setOldMeritValue(value);
}
void lineSearch::reset()
void Foam::lineSearch::reset()
{
if (extrapolateInitialStep_ && iter_ != 0)
{
@ -173,44 +180,46 @@ void lineSearch::reset()
}
label lineSearch::maxIters() const
Foam::label Foam::lineSearch::maxIters() const
{
return maxIters_;
}
scalar lineSearch::step() const
Foam::scalar Foam::lineSearch::step() const
{
return step_;
}
void lineSearch::updateStep(const scalar newStep)
void Foam::lineSearch::updateStep(const scalar newStep)
{
step_ = newStep;
}
lineSearch& lineSearch::operator++()
Foam::lineSearch& Foam::lineSearch::operator++()
{
iter_++;
prevMeritDeriv_ = directionalDeriv_;
lineSearchDict_.add<scalar>("prevMeritDeriv_", prevMeritDeriv_, true);
lineSearchDict_.add<scalar>("prevMeritDeriv", prevMeritDeriv_, true);
lineSearchDict_.add<label>("iter", iter_, true);
lineSearchDict_.regIOobject::write();
lineSearchDict_.regIOobject::writeObject
(
IOstream::ASCII,
IOstream::currentVersion,
IOstream::UNCOMPRESSED,
true
);
return *this;
}
lineSearch& lineSearch::operator++(int)
Foam::lineSearch& Foam::lineSearch::operator++(int)
{
return operator++();
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -30,7 +30,7 @@ Class
Foam::lineSearch
Description
Abstract base class for optimisation methods
Abstract base class for line search methods
SourceFiles
lineSearch.C
@ -51,7 +51,7 @@ namespace Foam
{
/*---------------------------------------------------------------------------*\
Class lineSearch Declaration
Class lineSearch Declaration
\*---------------------------------------------------------------------------*/
class lineSearch
@ -60,9 +60,16 @@ protected:
// Protected data
//- Subdict within updateMethod
const dictionary dict_;
//- IOdictionary under time/uniform for continuation
IOdictionary lineSearchDict_;
//- Directional derivative of the merit function
scalar directionalDeriv_;
//- Update direction
scalarField direction_;
//- Old merit value from this opt cycle
@ -73,15 +80,37 @@ protected:
//- Merit directional deriv from the previous opt cycle
scalar prevMeritDeriv_;
//- Correction multiplier at the first step of line search
scalar initialStep_;
//- Minimum allowed correction multiplier
scalar minStep_;
//- Correction multiplier
scalar step_;
//- Inner line search iteration
label iter_;
//- Maximum line search iterations
label maxIters_;
//- Whether to extrapolate the correction multiplier for
//- this optimisation cycle based on the previous ones.
// Usefull for non-quasi Newton methods
bool extrapolateInitialStep_;
//- Mechanism to update method if line search conditions are not set
autoPtr<stepUpdate> stepUpdate_;
// Protected Member Functions
//- Optional coeffs dict
const dictionary& coeffsDict();
private:
// Private Member Functions

View File

@ -0,0 +1,64 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "bisection.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(bisection, 0);
addToRunTimeSelectionTable
(
stepUpdate,
bisection,
dictionary
);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::bisection::bisection(const dictionary& dict)
:
stepUpdate(dict),
ratio_(coeffsDict().lookupOrDefault<scalar>("ratio", 0.7))
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * //
void Foam::bisection::updateStep(scalar& step)
{
step *= ratio_;
}
// ************************************************************************* //

View File

@ -0,0 +1,107 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Class
Foam::bisection
Description
Reduces step by a given ratio
SourceFiles
bisection.C
\*---------------------------------------------------------------------------*/
#ifndef bisection_H
#define bisection_H
#include "stepUpdate.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class bisection Declaration
\*---------------------------------------------------------------------------*/
class bisection
:
public stepUpdate
{
protected:
// Protected data
scalar ratio_;
private:
// Private Member Functions
//- Disallow default bitwise copy construct
bisection(const bisection&) = delete;
//- Disallow default bitwise assignment
void operator=(const bisection&) = delete;
public:
//- Runtime type information
TypeName("bisection");
// Constructors
//- Construct from components
bisection(const dictionary& dict);
//- Destructor
virtual ~bisection() = default;
// Member Functions
// Update step in given direction
virtual void updateStep(scalar& step);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,101 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "quadratic.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(quadratic, 0);
addToRunTimeSelectionTable
(
stepUpdate,
quadratic,
dictionary
);
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::quadratic::quadratic(const dictionary& dict)
:
stepUpdate(dict),
minRatio_(coeffsDict().lookupOrDefault<scalar>("minRatio", 0.1)),
firstMeritValue_(Zero),
secondMeritValue_(Zero),
meritDerivative_(Zero)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * //
void Foam::quadratic::updateStep(scalar& step)
{
Info<< "f(0)" << firstMeritValue_ << endl;
Info<< "f(a0)" << secondMeritValue_ << endl;
Info<< "df(0)" << meritDerivative_ << endl;
Info<< "a0 " << step << endl;
scalar denom = 1./(step*step);
scalar coeff1 =
(secondMeritValue_ - meritDerivative_*step - firstMeritValue_)
* denom;
scalar tempStep = - 0.5*meritDerivative_/coeff1;
if (tempStep < minRatio_*step)
{
step = minRatio_*step;
}
else
{
step = tempStep;
}
}
void Foam::quadratic::setDeriv(const scalar deriv)
{
meritDerivative_ = deriv;
}
void Foam::quadratic::setNewMeritValue(const scalar value)
{
secondMeritValue_ = value;
}
void Foam::quadratic::setOldMeritValue(const scalar value)
{
firstMeritValue_ = value;
}
// ************************************************************************* //

View File

@ -0,0 +1,120 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Class
Foam::quadratic
Description
Fits a quadratic polynomial of the merit function as a fuction of step
and finds the "optimal" value
SourceFiles
quadratic.C
\*---------------------------------------------------------------------------*/
#ifndef quadratic_H
#define quadratic_H
#include "stepUpdate.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class quadratic Declaration
\*---------------------------------------------------------------------------*/
class quadratic
:
public stepUpdate
{
protected:
// Protected data
scalar minRatio_;
scalar firstMeritValue_;
scalar secondMeritValue_;
scalar meritDerivative_;
private:
// Private Member Functions
//- Disallow default bitwise copy construct
quadratic(const quadratic&) = delete;
//- Disallow default bitwise assignment
void operator=(const quadratic&) = delete;
public:
//- Runtime type information
TypeName("quadratic");
// Constructors
//- Construct from components
quadratic(const dictionary& dict);
//- Destructor
virtual ~quadratic() = default;
// Member Functions
//- Update step in given direction
virtual void updateStep(scalar& step);
//- Set objective derivative
virtual void setDeriv(const scalar deriv);
//- Set new merit value
virtual void setNewMeritValue(const scalar value);
//- Set old merit value
virtual void setOldMeritValue(const scalar value);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -29,19 +29,26 @@ License
#include "stepUpdate.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(stepUpdate, 0);
defineRunTimeSelectionTable(stepUpdate, dictionary);
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
defineTypeNameAndDebug(stepUpdate, 0);
defineRunTimeSelectionTable(stepUpdate, dictionary);
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
const Foam::dictionary& Foam::stepUpdate::coeffsDict()
{
return dict_.optionalSubDict(type() + "Coeffs");
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
stepUpdate::stepUpdate(const dictionary& dict)
Foam::stepUpdate::stepUpdate(const dictionary& dict)
:
dict_(dict)
{}
@ -49,14 +56,14 @@ stepUpdate::stepUpdate(const dictionary& dict)
// * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * //
autoPtr<stepUpdate> stepUpdate::New(const dictionary& dict)
Foam::autoPtr<Foam::stepUpdate> Foam::stepUpdate::New(const dictionary& dict)
{
const word modelType =
const word type =
dict.lookupOrDefault<word>("stepUpdateType", "bisection");
Info<< "stepUpdate type : " << modelType << endl;
Info<< "stepUpdate type : " << type << endl;
auto cstrIter = dictionaryConstructorTablePtr_->cfind(modelType);
auto cstrIter = dictionaryConstructorTablePtr_->cfind(type);
if (!cstrIter.found())
{
@ -64,7 +71,7 @@ autoPtr<stepUpdate> stepUpdate::New(const dictionary& dict)
(
dict,
"stepUpdate",
modelType,
type,
*dictionaryConstructorTablePtr_
) << exit(FatalIOError);
}
@ -75,32 +82,22 @@ autoPtr<stepUpdate> stepUpdate::New(const dictionary& dict)
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * //
void stepUpdate::setDeriv(const scalar deriv)
void Foam::stepUpdate::setDeriv(const scalar deriv)
{
// Does nothing in base
}
void stepUpdate::setNewMeritValue(const scalar value)
void Foam::stepUpdate::setNewMeritValue(const scalar value)
{
// Does nothing in base
}
void stepUpdate::setOldMeritValue(const scalar value)
void Foam::stepUpdate::setOldMeritValue(const scalar value)
{
// Does nothing in base
}
void stepUpdate::setInitialStep(const scalar value)
{
// Does nothing in base
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// ************************************************************************* //

View File

@ -30,7 +30,7 @@ Class
Foam::stepUpdate
Description
Abstract base class for optimisation methods
Abstract base class for step update methods used in line search
SourceFiles
stepUpdate.C
@ -49,7 +49,7 @@ namespace Foam
{
/*---------------------------------------------------------------------------*\
Class stepUpdate Declaration
Class stepUpdate Declaration
\*---------------------------------------------------------------------------*/
class stepUpdate
@ -61,6 +61,12 @@ protected:
const dictionary dict_;
// Protected Member Functions
//- Optional coeffs dict
const dictionary& coeffsDict();
private:
// Private Member Functions
@ -116,14 +122,11 @@ public:
//- Set objective derivative
virtual void setDeriv(const scalar deriv);
//- Set new objective value
//- Set new merit value
virtual void setNewMeritValue(const scalar value);
//- Set old objective value
//- Set old merit value
virtual void setOldMeritValue(const scalar value);
//- Set old objective value
virtual void setInitialStep(const scalar value);
};

View File

@ -0,0 +1,207 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "optMeshMovement.H"
#include "cellQuality.H"
#include "createZeroField.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(optMeshMovement, 0);
defineRunTimeSelectionTable(optMeshMovement, dictionary);
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
Foam::scalar Foam::optMeshMovement::getMaxAllowedDisplacement() const
{
if (maxAllowedDisplacement_.empty())
{
FatalErrorInFunction
<< "maxAllowedDisplacement requested but not set" << nl
<< exit(FatalError);
}
return maxAllowedDisplacement_();
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::optMeshMovement::optMeshMovement
(
fvMesh& mesh,
const dictionary& dict,
const labelList& patchIDs
)
:
maxAllowedDisplacement_(nullptr),
mesh_(mesh),
dict_(dict),
correction_(0),
patchIDs_(patchIDs),
pointsInit_(mesh.points()),
displMethodPtr_(displacementMethod::New(mesh_, patchIDs_)),
writeMeshQualityMetrics_
(
dict.lookupOrDefault("writeMeshQualityMetrics", false)
)
{
//- Set maxAllowedDisplacement if provided
if (dict.found("maxAllowedDisplacement"))
{
maxAllowedDisplacement_.reset
(
new scalar(dict.get<scalar>("maxAllowedDisplacement"))
);
}
}
// * * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * //
Foam::autoPtr<Foam::optMeshMovement> Foam::optMeshMovement::New
(
fvMesh& mesh,
const dictionary& dict,
const labelList& patchIDs
)
{
const word modelType(dict.get<word>("type"));
Info<< "optMeshMovement type : " << modelType << endl;
auto cstrIter = dictionaryConstructorTablePtr_->cfind(modelType);
if (!cstrIter.found())
{
FatalIOErrorInLookup
(
dict,
"type",
modelType,
*dictionaryConstructorTablePtr_
) << exit(FatalError);
}
return autoPtr<optMeshMovement>(cstrIter()(mesh, dict, patchIDs));
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * //
void Foam::optMeshMovement::setCorrection(const scalarField& correction)
{
correction_ = correction;
}
void Foam::optMeshMovement::moveMesh()
{
// Move mesh
displMethodPtr_->update();
// Check mesh quality
mesh_.checkMesh(true);
// If needed, plot mesh quality metrics
writeMeshQualityMetrics();
}
Foam::autoPtr<Foam::displacementMethod>&
Foam::optMeshMovement::returnDisplacementMethod()
{
return displMethodPtr_;
}
const Foam::labelList& Foam::optMeshMovement::getPatchIDs()
{
return patchIDs_;
}
void Foam::optMeshMovement::writeMeshQualityMetrics()
{
if (writeMeshQualityMetrics_)
{
cellQuality cellQualityEngine(mesh_);
tmp<scalarField> cellNonOrtho = cellQualityEngine.nonOrthogonality();
tmp<scalarField> cellSkewness = cellQualityEngine.skewness();
Info<< "Average, Max cell non - orthogonality " << gAverage(cellNonOrtho())
<< " " << gMax(cellNonOrtho()) << endl;
Info<< "Average, Max cell skewness " << gAverage(cellSkewness())
<< " " << gMax(cellSkewness()) << endl;
autoPtr<volScalarField> nonOrthoPtr
(
createZeroFieldPtr<scalar>(mesh_, "nonOrtho", dimless)
);
autoPtr<volScalarField> skewnessPtr
(
createZeroFieldPtr<scalar>(mesh_, "skewness", dimless)
);
nonOrthoPtr().primitiveFieldRef() = cellNonOrtho();
skewnessPtr().primitiveFieldRef() = cellSkewness();
nonOrthoPtr().write();
skewnessPtr().write();
}
}
void Foam::optMeshMovement::storeDesignVariables()
{
pointsInit_ = mesh_.points();
}
void Foam::optMeshMovement::resetDesignVariables()
{
Info<< "optMeshMovement:: reseting mesh points" << endl;
mesh_.movePoints(pointsInit_);
}
bool Foam::optMeshMovement::maxAllowedDisplacementSet() const
{
return maxAllowedDisplacement_.valid();
}
Foam::labelList Foam::optMeshMovement::getActiveDesignVariables() const
{
NotImplemented;
return labelList(0);
}
// ************************************************************************* //

View File

@ -0,0 +1,201 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Class
Foam::optMeshMovement
Description
Abstract base class for translating an update of the design variables
into mesh movement
SourceFiles
optMeshMovement.C
\*---------------------------------------------------------------------------*/
#ifndef optMeshMovement_H
#define optMeshMovement_H
#include "displacementMethod.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class optMeshMovement Declaration
\*---------------------------------------------------------------------------*/
class optMeshMovement
{
private:
// Private Member Functions
//- Max allowed boundary displacement for the first optimisation cycle
autoPtr<scalar> maxAllowedDisplacement_;
// Private Member Functions
//- Disallow default bitwise copy construct
optMeshMovement(const optMeshMovement&) = delete;
//- Disallow default bitwise assignment
void operator=(const optMeshMovement&) = delete;
protected:
// Protected data
fvMesh& mesh_;
const dictionary& dict_;
//- Correction of design variables
scalarField correction_;
//- IDs of patches to be moved
labelList patchIDs_;
//- Fall back points in case line-search is used
vectorField pointsInit_;
//- Mesh movement engine and interface for applying mesh movement
//- boundary conditions
autoPtr<displacementMethod> displMethodPtr_;
//- Whether to write the mesh quality metrics to files each time the
//- mesh is updated
bool writeMeshQualityMetrics_;
// Protected Member Functions
//- Get maxAllowedDisplacement, is set
scalar getMaxAllowedDisplacement() const;
public:
//- Runtime type information
TypeName("optMeshMovement");
// Declare run-time constructor selection table
declareRunTimeSelectionTable
(
autoPtr,
optMeshMovement,
dictionary,
(
fvMesh& mesh,
const dictionary& dict,
const labelList& patchIDs
),
(
mesh,
dict,
patchIDs
)
);
// Constructors
//- Construct from components
optMeshMovement
(
fvMesh& mesh,
const dictionary& dict,
const labelList& patchIDs
);
// Selectors
static autoPtr<optMeshMovement> New
(
fvMesh& mesh,
const dictionary& dict,
const labelList& patchIDs
);
//- Destructor
virtual ~optMeshMovement() = default;
// Member Functions
//- Set design variable correction
void setCorrection(const scalarField& correction);
//- Calculates mesh movemnt based on the correction of the design
//- variables
virtual void moveMesh();
//- Return displacementMethod
autoPtr<displacementMethod>& returnDisplacementMethod();
//- Return patchIDs
const labelList& getPatchIDs();
//- Write mesh quality metrics
void writeMeshQualityMetrics();
//- Store design variables and mesh, to act as the starting point of
//- line search
virtual void storeDesignVariables();
//- Reset to starting point of line search
virtual void resetDesignVariables();
//- Compute eta value based on max displacement
virtual scalar computeEta(const scalarField& correction) = 0;
//- Whether maxAllowedDisplacement has been set
bool maxAllowedDisplacementSet() const;
//- Return active design variables.
// Implemented only for certain parametetisations
virtual labelList getActiveDesignVariables() const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,159 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "optMeshMovementBezier.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(optMeshMovementBezier, 0);
addToRunTimeSelectionTable
(
optMeshMovement,
optMeshMovementBezier,
dictionary
);
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
void Foam::optMeshMovementBezier::computeBoundaryMovement
(
const scalarField& correction
)
{
// Re-initialize movement to zero
dx_.primitiveFieldRef() = vector::zero;
// Compute boundary mesh movement using derivatives of the control points
// and parameterization information
const label nBezier = Bezier_.nBezier();
const boolList& confineXmovement = Bezier_.confineXmovement();
const boolList& confineYmovement = Bezier_.confineYmovement();
const boolList& confineZmovement = Bezier_.confineZmovement();
vectorField actualMovement(nBezier, vector::zero);
for (label iCP = 0; iCP < nBezier; iCP++)
{
// Confine x movement
if (!confineXmovement[iCP])
{
actualMovement[iCP].x() = correction[iCP];
}
// Confine y movement
if (!confineYmovement[iCP])
{
actualMovement[iCP].y() = correction[iCP + nBezier];
}
// Confine z movement
if (!confineZmovement[iCP])
{
actualMovement[iCP].z() = correction[iCP + 2*nBezier];
}
dx_ += Bezier_.dxidXj()[iCP] & actualMovement[iCP];
}
// Add to cumulative control point change (wrong in the first optimisation
// cycle if initial eta not set)
cumulativeChange_ += actualMovement;
Info<< "Cumulative control point change " << cumulativeChange_ << endl;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::optMeshMovementBezier::optMeshMovementBezier
(
fvMesh& mesh,
const dictionary& dict,
const labelList& patchIDs
)
:
optMeshMovement(mesh, dict, patchIDs),
Bezier_(mesh, mesh.lookupObject<IOdictionary>("optimisationDict")),
dx_
(
IOobject
(
"dx",
mesh_.time().timeName(),
mesh_,
IOobject::NO_READ,
IOobject::NO_WRITE,
false
),
pointMesh::New(mesh),
dimensionedVector(dimless, Zero)
),
cumulativeChange_(Bezier_.nBezier(), vector::zero)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::optMeshMovementBezier::moveMesh()
{
// Update the boundary movement
computeBoundaryMovement(correction_);
// Set boundary movement of motion solver
displMethodPtr_->setMotionField(dx_);
// Move the mesh and check quality
optMeshMovement::moveMesh();
}
Foam::scalar
Foam::optMeshMovementBezier::computeEta(const scalarField& correction)
{
// Set unscaled correction
computeBoundaryMovement(correction);
// Get maximum boundary movement
const scalar maxDisplacement = gMax(mag(dx_.primitiveField()));
// Compute eta value
Info<< "maxAllowedDisplacement/maxDisplacement \t"
<< getMaxAllowedDisplacement() << "/" << maxDisplacement << endl;
const scalar eta = getMaxAllowedDisplacement()/maxDisplacement;
Info<< "Setting eta value to " << eta << endl;
return eta;
}
Foam::labelList Foam::optMeshMovementBezier::getActiveDesignVariables() const
{
return Bezier_.getActiveDesignVariables();
}
// ************************************************************************* //

View File

@ -0,0 +1,131 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Class
Foam::optMeshMovementBezier
Description
Converts NURBS control points update to actual mesh movement
SourceFiles
optMeshMovementBezier.C
\*---------------------------------------------------------------------------*/
#ifndef optMeshMovementBezier_H
#define optMeshMovementBezier_H
#include "optMeshMovement.H"
#include "Bezier.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class optMeshMovementBezier Declaration
\*---------------------------------------------------------------------------*/
class optMeshMovementBezier
:
public optMeshMovement
{
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
void computeBoundaryMovement(const scalarField& correction);
private:
// Private Member Functions
//- Disallow default bitwise copy construct
optMeshMovementBezier(const optMeshMovementBezier&) = delete;
//- Disallow default bitwise assignment
void operator=(const optMeshMovementBezier&) = delete;
public:
//- Runtime type information
TypeName("Bezier");
// Constructors
//- Construct from components
optMeshMovementBezier
(
fvMesh& mesh,
const dictionary& dict,
const labelList& patchIDs
);
//- Destructor
virtual ~optMeshMovementBezier() = default;
// Member Functions
//- Calculates surface mesh movement
void moveMesh();
//- Compute eta value based on max displacement
virtual scalar computeEta(const scalarField& correction);
//- Return active design variables
virtual labelList getActiveDesignVariables() const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,75 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "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 * * * * * * * * * * * * * //
void Foam::optMeshMovementNULL::moveMesh()
{
// Do nothing
}
Foam::scalar
Foam::optMeshMovementNULL::computeEta(const scalarField& correction)
{
return scalar(0);
}
// ************************************************************************* //

View File

@ -0,0 +1,107 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Class
Foam::optMeshMovementNULL
Description
A dummy optMeshMovement object
SourceFiles
optMeshMovementNULL.C
\*---------------------------------------------------------------------------*/
#ifndef optMeshMovementNULL_H
#define optMeshMovementNULL_H
#include "optMeshMovement.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class optMeshMovementNULL Declaration
\*---------------------------------------------------------------------------*/
class optMeshMovementNULL
:
public optMeshMovement
{
private:
// Private Member Functions
//- Disallow default bitwise copy construct
optMeshMovementNULL(const optMeshMovementNULL&) = delete;
//- Disallow default bitwise assignment
void operator=(const optMeshMovementNULL&) = delete;
public:
//- Runtime type information
TypeName("none");
// Constructors
//- Construct from components
optMeshMovementNULL
(
fvMesh& mesh,
const dictionary& dict,
const labelList& patchIDs
);
//- Destructor
virtual ~optMeshMovementNULL() = default;
// Member Functions
//- Calculates surface mesh movement
void moveMesh();
//- Compute eta value based on max displacement
virtual scalar computeEta(const scalarField& correction);
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,173 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "optMeshMovementVolumetricBSplines.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(optMeshMovementVolumetricBSplines, 0);
addToRunTimeSelectionTable
(
optMeshMovement,
optMeshMovementVolumetricBSplines,
dictionary
);
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
Foam::vectorField Foam::optMeshMovementVolumetricBSplines::controlPointMovement
(
const scalarField& correction
)
{
const label nControlPoints(correction.size()/3);
vectorField cpMovement(nControlPoints, vector::zero);
for (label iCP = 0; iCP < nControlPoints; ++iCP)
{
cpMovement[iCP].x() = correction[3*iCP];
cpMovement[iCP].y() = correction[3*iCP + 1];
cpMovement[iCP].z() = correction[3*iCP + 2];
}
displMethodPtr_->boundControlField(cpMovement);
return cpMovement;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::optMeshMovementVolumetricBSplines::optMeshMovementVolumetricBSplines
(
fvMesh& mesh,
const dictionary& dict,
const labelList& patchIDs
)
:
optMeshMovement(mesh, dict, patchIDs),
volBSplinesBase_
(
const_cast<volBSplinesBase&>(volBSplinesBase::New(mesh))
),
cpsInit_(volBSplinesBase_.getNumberOfBoxes())
{
PtrList<NURBS3DVolume>& boxes = volBSplinesBase_.boxesRef();
forAll(boxes, boxI)
{
cpsInit_[boxI].setSize
(
boxes[boxI].getControlPoints().size()
);
cpsInit_[boxI] = boxes[boxI].getControlPoints();
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::optMeshMovementVolumetricBSplines::moveMesh()
{
// Get controlPoint movement from correction
vectorField cpMovement = controlPointMovement(correction_);
// Set movement of the B-Splines control points
displMethodPtr_->setControlField(cpMovement);
// Move the mesh and check quality
optMeshMovement::moveMesh();
}
void Foam::optMeshMovementVolumetricBSplines::storeDesignVariables()
{
optMeshMovement::storeDesignVariables();
const PtrList<NURBS3DVolume>& boxes = volBSplinesBase_.boxes();
forAll(boxes, boxI)
{
cpsInit_[boxI] = boxes[boxI].getControlPoints();
}
}
void Foam::optMeshMovementVolumetricBSplines::resetDesignVariables()
{
// Reset mesh points
optMeshMovement::resetDesignVariables();
DebugInfo
<< "optMeshMovementVolumetricBSplines:: reseting control points"
<< endl;
PtrList<NURBS3DVolume>& boxes = volBSplinesBase_.boxesRef();
forAll(boxes, boxI)
{
boxes[boxI].setControlPoints(cpsInit_[boxI]);
}
}
Foam::scalar Foam::optMeshMovementVolumetricBSplines::computeEta
(
const scalarField& correction
)
{
const vectorField cpMovement(controlPointMovement(correction));
const scalar maxDisplacement
(
volBSplinesBase_.computeMaxBoundaryDisplacement
(
cpMovement,
patchIDs_
)
);
Info<< "maxAllowedDisplacement/maxDisplacement of boundary\t"
<< getMaxAllowedDisplacement() << "/" << maxDisplacement << endl;
scalar eta = getMaxAllowedDisplacement() / maxDisplacement;
Info<< "Setting eta value to " << eta << endl;
return eta;
}
Foam::labelList
Foam::optMeshMovementVolumetricBSplines::getActiveDesignVariables() const
{
return volBSplinesBase_.getActiveDesignVariables();
}
// ************************************************************************* //

View File

@ -0,0 +1,138 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Class
Foam::optMeshMovementVolumetricBSplines
Description
Converts NURBS volume control points update to actual mesh movement.
Internal points are also moved based on the movement of the control points
SourceFiles
optMeshMovementVolumetricBSplines.C
\*---------------------------------------------------------------------------*/
#ifndef optMeshMovementVolumetricBSplines_H
#define optMeshMovementVolumetricBSplines_H
#include "optMeshMovement.H"
#include "volBSplinesBase.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class optMeshMovementVolumetricBSplines Declaration
\*---------------------------------------------------------------------------*/
class optMeshMovementVolumetricBSplines
:
public optMeshMovement
{
protected:
// Protected data
//- Reference to underlaying volumetric B-Splines morpher
volBSplinesBase& volBSplinesBase_;
//- Backup of initial control points. Useful for line-search
List<vectorField> cpsInit_;
// Protected Fuctions
vectorField controlPointMovement(const scalarField& correction);
private:
// Private Member Functions
//- Disallow default bitwise copy construct
optMeshMovementVolumetricBSplines
(
const optMeshMovementVolumetricBSplines&
) = delete;
//- Disallow default bitwise assignment
void operator=(const optMeshMovementVolumetricBSplines&) = delete;
public:
//- Runtime type information
TypeName("volumetricBSplines");
// Constructors
//- Construct from components
optMeshMovementVolumetricBSplines
(
fvMesh& mesh,
const dictionary& dict,
const labelList& patchIDs
);
//- Destructor
virtual ~optMeshMovementVolumetricBSplines() = default;
// Member Functions
//- Calculates surface mesh movement
void moveMesh();
//- Store design variables and mesh, to act as the starting point of
//- line search
virtual void storeDesignVariables();
//- Reset to starting point of line search
virtual void resetDesignVariables();
//- Compute eta value based on max displacement
virtual scalar computeEta(const scalarField& correction);
//- Return active design variables
virtual labelList getActiveDesignVariables() const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,190 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "optMeshMovementVolumetricBSplinesExternalMotionSolver.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug
(
optMeshMovementVolumetricBSplinesExternalMotionSolver,
0
);
addToRunTimeSelectionTable
(
optMeshMovement,
optMeshMovementVolumetricBSplinesExternalMotionSolver,
dictionary
);
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
void Foam::optMeshMovementVolumetricBSplinesExternalMotionSolver::
computeBoundaryMovement
(
const scalarField& correction
)
{
const label nCPs(volBSplinesBase_.getTotalControlPointsNumber());
dx_.primitiveFieldRef() = vector::zero;
cpMovement_ = vector::zero;
for (label iCP = 0; iCP < nCPs; iCP++)
{
cpMovement_[iCP].x() = correction[3*iCP];
cpMovement_[iCP].y() = correction[3*iCP + 1];
cpMovement_[iCP].z() = correction[3*iCP + 2];
}
// Bound control point movement for non-active CPs
volBSplinesBase_.boundControlPointsMovement(cpMovement_);
// Compute boundary movement
label passedCPs(0);
PtrList<NURBS3DVolume>& boxes = volBSplinesBase_.boxesRef();
forAll(boxes, iNURB)
{
const label nb = boxes[iNURB].getControlPoints().size();
for (label cpI = 0; cpI < nb; ++cpI)
{
const label globalCP = passedCPs + cpI;
forAll(patchIDs_, pI)
{
const label patchI = patchIDs_[pI];
vectorField boundaryMovement
(
boxes[iNURB].patchDxDb(patchI, cpI)
& cpMovement_[globalCP]
);
dx_.boundaryField()[patchI].addToInternalField
(
dx_.primitiveFieldRef(),
boundaryMovement
);
}
}
// Increment number of passed sensitivities
passedCPs += nb;
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::optMeshMovementVolumetricBSplinesExternalMotionSolver::
optMeshMovementVolumetricBSplinesExternalMotionSolver
(
fvMesh& mesh,
const dictionary& dict,
const labelList& patchIDs
)
:
optMeshMovement(mesh, dict, patchIDs),
volBSplinesBase_
(
const_cast<volBSplinesBase&>(volBSplinesBase::New(mesh))
),
dx_
(
IOobject
(
"dx",
mesh.time().timeName(),
mesh,
IOobject::NO_READ,
IOobject::NO_WRITE,
false
),
pointMesh::New(mesh),
dimensionedVector(dimless, Zero)
),
cpMovement_(volBSplinesBase_.getTotalControlPointsNumber(), vector::zero)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::optMeshMovementVolumetricBSplinesExternalMotionSolver::moveMesh()
{
// Compute boundary movement
computeBoundaryMovement(correction_);
// Set boundary movement of motion solver
displMethodPtr_->setMotionField(dx_);
// Positions of control points have not changed since only the boundary dx
// has been computed.
// Use correction to update them
volBSplinesBase_.moveControlPoints(cpMovement_);
// Write control points to files
volBSplinesBase_.writeControlPoints();
// Move the mesh and check quality
optMeshMovement::moveMesh();
}
Foam::scalar
Foam::optMeshMovementVolumetricBSplinesExternalMotionSolver::computeEta
(
const scalarField& correction
)
{
computeBoundaryMovement(correction);
// Get maximum boundary movement
scalar maxDisplacement = gMax(mag(dx_.primitiveField()));
// Compute eta value
Info<< "maxAllowedDisplacement/maxDisplacement \t"
<< getMaxAllowedDisplacement() << "/" << maxDisplacement << endl;
scalar eta = getMaxAllowedDisplacement() / maxDisplacement;
Info<< "Setting eta value to " << eta << endl;
return eta;
}
Foam::labelList
Foam::optMeshMovementVolumetricBSplinesExternalMotionSolver::getActiveDesignVariables()
const
{
return volBSplinesBase_.getActiveDesignVariables();
}
// ************************************************************************* //

View File

@ -0,0 +1,138 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Class
Foam::optMeshMovementVolumetricBSplinesExternalMotionSolver
Description
Converts NURBS volume control points update to actual mesh movement.
Internal points are moved based on a motionSolver other than
volumetricBSplinesExternalMotionSolver.
SourceFiles
optMeshMovementVolumetricBSplinesExternalMotionSolver.C
\*---------------------------------------------------------------------------*/
#ifndef optMeshMovementVolumetricBSplinesExternalMotionSolver_H
#define optMeshMovementVolumetricBSplinesExternalMotionSolver_H
#include "optMeshMovement.H"
#include "volBSplinesBase.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class optMeshMovementVolumetricBSplinesExternalMotionSolver Declaration
\*---------------------------------------------------------------------------*/
class optMeshMovementVolumetricBSplinesExternalMotionSolver
:
public optMeshMovement
{
protected:
// Protected data
//- Reference to underlaying volumetric B-Splines morpher
volBSplinesBase& volBSplinesBase_;
//- Boundary movement due to change of NURBS control points
pointVectorField dx_;
//- Movement of control points
vectorField cpMovement_;
// Protected Member Functions
void computeBoundaryMovement(const scalarField& correction);
private:
// Private Member Functions
//- Disallow default bitwise copy construct
optMeshMovementVolumetricBSplinesExternalMotionSolver
(
const optMeshMovementVolumetricBSplinesExternalMotionSolver&
) = delete;
//- Disallow default bitwise assignment
void operator=
(
const optMeshMovementVolumetricBSplinesExternalMotionSolver&
) = delete;
public:
//- Runtime type information
TypeName("volumetricBSplinesExternalMotionSolver");
// Constructors
//- Construct from components
optMeshMovementVolumetricBSplinesExternalMotionSolver
(
fvMesh& mesh,
const dictionary& dict,
const labelList& patchIDs
);
//- Destructor
virtual ~optMeshMovementVolumetricBSplinesExternalMotionSolver() = default;
// Member Functions
//- Calculates surface mesh movement
void moveMesh();
//- Compute eta value based on max displacement
virtual scalar computeEta(const scalarField& correction);
//- Return active design variables
virtual labelList getActiveDesignVariables() const;
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,250 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "steadyOptimisation.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(steadyOptimisation, 0);
addToRunTimeSelectionTable
(
optimisationManager,
steadyOptimisation,
dictionary
);
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::steadyOptimisation::updateOptTypeSource()
{
forAll(primalSolvers_, pI)
{
primalSolvers_[pI].updateOptTypeSource(optType_->sourcePtr());
}
forAll(adjointSolverManagers_, asmI)
{
PtrList<adjointSolver>& adjointSolvers =
adjointSolverManagers_[asmI].adjointSolvers();
forAll(adjointSolvers, aI)
{
adjointSolvers[aI].updateOptTypeSource(optType_->sourcePtr());
}
}
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
void Foam::steadyOptimisation::lineSearchUpdate(scalarField& direction)
{
autoPtr<lineSearch>& lineSrch = optType_->getLineSearch();
// Store starting point
optType_->storeDesignVariables();
// Compute merit function before update
scalar meritFunction = optType_->computeMeritFunction();
lineSrch->setOldMeritValue(meritFunction);
// Get merit function derivative
const scalar dirDerivative =
optType_->meritFunctionDirectionalDerivative();
lineSrch->setDeriv(dirDerivative);
lineSrch->setDirection(direction);
// Reset initial step.
// Might be interpolated from previous optimisation cycles
lineSrch->reset();
// Perform line search
for (label iter = 0; iter < lineSrch->maxIters(); ++iter)
{
Info<< "\n- - - - - - - - - - - - - - -" << endl;
Info<< "Line search iteration " << iter << endl;
Info<< "- - - - - - - - - - - - - - -\n" << endl;
// Update design variables. Multiplication with line search step
// happens inside the update(direction) function
optType_->update(direction);
// Solve all primal equations
solvePrimalEquations();
// Compute and set new merit function
meritFunction = optType_->computeMeritFunction();
lineSrch->setNewMeritValue(meritFunction);
if (lineSrch->converged())
{
// If line search criteria have been met, proceed
Info<< "Line search converged in " << iter + 1
<< " iterations." << endl;
scalarField scaledCorrection(lineSrch->step()*direction);
optType_->updateOldCorrection(scaledCorrection);
optType_->write();
lineSrch()++;
break;
}
else
{
// If maximum number of iteration has been reached, continue
if (iter == lineSrch->maxIters()-1)
{
Info<< "Line search reached max. number of iterations.\n"
<< "Proceeding to the next optimisation cycle" << endl;
scalarField scaledCorrection(lineSrch->step()*direction);
optType_->updateOldCorrection(scaledCorrection);
optType_->write();
lineSrch()++;
}
// Reset to initial design variables and update step
else
{
optType_->resetDesignVariables();
lineSrch->updateStep();
}
}
}
}
void Foam::steadyOptimisation::fixedStepUpdate(scalarField& direction)
{
// Update based on fixed step
optType_->update(direction);
// If direction has been scaled (say by setting the initial eta), the
// old correction has to be updated
optType_->updateOldCorrection(direction);
optType_->write();
// Solve primal equations
solvePrimalEquations();
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::steadyOptimisation::steadyOptimisation(fvMesh& mesh)
:
optimisationManager(mesh)
{
optType_.reset
(
incompressible::optimisationType::New
(
mesh,
subDict("optimisation"),
adjointSolverManagers_
).ptr()
);
// Update source ptrs in all solvers to look at the source held in optType
// Possible problem if mesh is adapted
updateOptTypeSource();
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::optimisationManager& Foam::steadyOptimisation::operator++()
{
time_++;
if (!end())
{
Info<< "\n* * * * * * * * * * * * * * * * *" << endl;
Info<< "Optimisation cycle " << time_.value() << endl;
Info<< "* * * * * * * * * * * * * * * * *\n" << endl;
}
return *this;
}
Foam::optimisationManager& Foam::steadyOptimisation::operator++(int)
{
return operator++();
}
bool Foam::steadyOptimisation::checkEndOfLoopAndUpdate()
{
if (update())
{
optType_->update();
}
return end();
}
bool Foam::steadyOptimisation::end()
{
return time_.end();
}
bool Foam::steadyOptimisation::update()
{
return (time_.timeIndex() != 1 && !end());
}
void Foam::steadyOptimisation::updateDesignVariables()
{
// Compute direction of update
tmp<scalarField> tdirection = optType_->computeDirection();
scalarField& direction = tdirection.ref();
autoPtr<lineSearch>& lineSrch = optType_->getLineSearch();
// Update design variables using either a line-search scheme or
// a fixed-step update
if (lineSrch.valid())
{
lineSearchUpdate(direction);
}
else
{
fixedStepUpdate(direction);
}
// Reset adjoint sensitivities in all adjoint solver managers
for (adjointSolverManager& adjSolverManager : adjointSolverManagers_)
{
adjSolverManager.clearSensitivities();
}
}
// ************************************************************************* //

View File

@ -0,0 +1,132 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
Class
Foam::steadyOptimisation
Description
Iterate the optimisation cycles. For steady state opt, this coinsides
with evolving Time
SourceFiles
steadyOptimisation.C
\*---------------------------------------------------------------------------*/
#ifndef steadyOptimisation_H
#define steadyOptimisation_H
#include "optimisationManager.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class steadyOptimisation Declaration
\*---------------------------------------------------------------------------*/
class steadyOptimisation
:
public optimisationManager
{
private:
// Private Member Functions
//- Update optimisationType source for all primal and adjoint solvers
void updateOptTypeSource();
//- Disallow default bitwise copy construct
steadyOptimisation(const steadyOptimisation&) = delete;
//- Disallow default bitwise assignment
void operator=(const steadyOptimisation&) = delete;
protected:
// Protected Member Functions
//- Update design variables using a line-search
void lineSearchUpdate(scalarField& direction);
//- Update design variables using a fixed step
void fixedStepUpdate(scalarField& direction);
public:
//- Runtime type information
TypeName("steadyOptimisation");
// Constructors
//- Construct from components
steadyOptimisation(fvMesh& mesh);
// Destructor
virtual ~steadyOptimisation() = default;
// Member Functions
//- Prefix increment
virtual optimisationManager& operator++();
//- Postfix increment, this is identical to the prefix increment
virtual optimisationManager& operator++(int);
//- Return true if end of optimisation run
// Also, updates the design variables if needed
virtual bool checkEndOfLoopAndUpdate();
//- Return true if end of optimisation run
virtual bool end();
//- Whether to update the design variables
virtual bool update();
//- Do a line search to find a correction satisfying the step
//- convergence criteria
virtual void updateDesignVariables();
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

Some files were not shown because too many files have changed in this diff Show More