/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2023 PCOpt/NTUA
Copyright (C) 2023 FOSS GP
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see .
\*---------------------------------------------------------------------------*/
#include "adjointNull.H"
#include "findRefCell.H"
#include "constrainHbyA.H"
#include "adjustPhi.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(adjointNull, 0);
addToRunTimeSelectionTable
(
adjointSolver,
adjointNull,
adjointSolver
);
}
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
void Foam::adjointNull::preCalculateSensitivities()
{
adjointSensitivity_->accumulateIntegrand(scalar(1));
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::adjointNull::adjointNull
(
fvMesh& mesh,
const word& managerType,
const dictionary& dict,
const word& primalSolverName,
const word& solverName
)
:
adjointSolver
(
mesh,
managerType,
dict,
primalSolverName,
solverName
)
{
allocateSensitivities();
}
// * * * * * * * * * * * * * * * * * Selectors * * * * * * * * * * * * * * * //
Foam::autoPtr Foam::adjointNull::New
(
fvMesh& mesh,
const word& managerType,
const dictionary& dict,
const word& primalSolverName,
const word& solverName
)
{
return autoPtr
(
new adjointNull
(
mesh,
managerType,
dict,
primalSolverName,
solverName
)
);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
const Foam::word Foam::adjointNull::simulationType() const
{
return word("null");
}
Foam::dimensionSet Foam::adjointNull::maDimensions() const
{
return pow3(dimLength/dimTime);
}
void Foam::adjointNull::solveIter()
{
// Does nothing
}
void Foam::adjointNull::solve()
{
// Does nothing
}
bool Foam::adjointNull::loop()
{
return false;
}
void Foam::adjointNull::updatePrimalBasedQuantities()
{
// Update objective function related quantities
objectiveManager_.updateAndWrite();
}
void Foam::adjointNull::accumulateGradDxDbMultiplier
(
volTensorField& gradDxDbMult,
const scalar dt
)
{
tmp tsens
(
tmp::New
(
IOobject
(
"flowTerm",
mesh_.time().timeName(),
mesh_,
IOobject::NO_READ,
IOobject::NO_WRITE
),
mesh_,
dimensionedTensor(sqr(dimLength)/pow3(dimTime), Zero),
fvPatchFieldBase::zeroGradientType()
)
);
volTensorField& sens = tsens.ref();
PtrList& functions = objectiveManager_.getObjectiveFunctions();
for (objective& objI : functions)
{
if (objI.hasGradDxDbMult())
{
sens += objI.weight()*objI.gradDxDbMultiplier();
}
}
sens.correctBoundaryConditions();
gradDxDbMult += sens.T()*dt;
}
void Foam::adjointNull::accumulateDivDxDbMultiplier
(
autoPtr& divDxDbMult,
const scalar dt
)
{
PtrList& functions = objectiveManager_.getObjectiveFunctions();
for (objective& func : functions)
{
if (func.hasDivDxDbMult())
{
divDxDbMult() +=
func.weight()*func.divDxDbMultiplier().primitiveField()*dt;
}
}
}
void Foam::adjointNull::accumulateGeometryVariationsMultipliers
(
autoPtr& dSfdbMult,
autoPtr& dnfdbMult,
autoPtr& dxdbDirectMult,
autoPtr& pointDxDbDirectMult,
const labelHashSet& sensitivityPatchIDs,
const scalar dt
)
{
PtrList& 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());
if (func.hasdSdbMult())
{
dSfdbMult()[patchI] += wei*func.dSdbMultiplier(patchI)*dt;
}
if (func.hasdndbMult())
{
dnfdbMult()[patchI] += wei*func.dndbMultiplier(patchI)*magSfDt;
}
if (func.hasdxdbDirectMult())
{
dxdbDirectMult()[patchI] +=
wei*func.dxdbDirectMultiplier(patchI)*magSfDt;
}
}
}
}
void Foam::adjointNull::topOSensMultiplier
(
scalarField& betaMult,
const word& designVariablesName,
const scalar dt
)
{
// Terms resulting directly from the objective function
PtrList& functions = objectiveManager_.getObjectiveFunctions();
for (objective& objI : functions)
{
const scalar weight = objI.weight();
if (objI.hasdJdb())
{
betaMult += weight*objI.dJdb()*dt;
}
if (objI.hasdJdbField())
{
SubField betaSens(objI.dJdbField(), mesh_.nCells(), 0);
betaMult += weight*betaSens*dt;
}
}
}
// ************************************************************************* //