mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: minor update in levelSet-based topology optimisation,
to keep the regularised design variables and the signed distance in different fields
This commit is contained in:
committed by
Andrew Heather
parent
1f7fb08060
commit
46757d12ec
@ -26,7 +26,6 @@ License
|
|||||||
|
|
||||||
\*---------------------------------------------------------------------------*/
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#include "HashSet.H"
|
|
||||||
#include "levelSetDesignVariables.H"
|
#include "levelSetDesignVariables.H"
|
||||||
#include "wallDist.H"
|
#include "wallDist.H"
|
||||||
#include "zeroGradientFvPatchField.H"
|
#include "zeroGradientFvPatchField.H"
|
||||||
@ -203,7 +202,7 @@ void levelSetDesignVariables::updateBeta()
|
|||||||
// Compute the beta field by passing the distance field through
|
// Compute the beta field by passing the distance field through
|
||||||
// a Heaviside function
|
// a Heaviside function
|
||||||
scalarField& beta = beta_.primitiveFieldRef();
|
scalarField& beta = beta_.primitiveFieldRef();
|
||||||
interpolation_->interpolate(aTilda_.primitiveField(), beta);
|
interpolation_->interpolate(signedDistances_.primitiveField(), beta);
|
||||||
beta = 1 - beta;
|
beta = 1 - beta;
|
||||||
// Apply fixed values if necessary
|
// Apply fixed values if necessary
|
||||||
applyFixedPorosityValues();
|
applyFixedPorosityValues();
|
||||||
@ -237,32 +236,38 @@ void Foam::levelSetDesignVariables::updateSignedDistances()
|
|||||||
y.primitiveFieldRef() = aTilda_.primitiveFieldRef();
|
y.primitiveFieldRef() = aTilda_.primitiveFieldRef();
|
||||||
y.correctBoundaryConditions();
|
y.correctBoundaryConditions();
|
||||||
|
|
||||||
labelList changedFaces(mesh_.nFaces(), -1);
|
changedFaces_.clear();
|
||||||
List<wallPoint> changedFacesInfo(mesh_.nFaces());
|
changedFaces_.setSize(mesh_.nFaces(), -1);
|
||||||
writeFluidSolidInterface(aTilda_, 0, changedFaces, changedFacesInfo);
|
|
||||||
|
|
||||||
List<wallPoint> allFaceInfo(mesh_.nFaces());
|
changedFacesInfo_.clear();
|
||||||
List<wallPoint> allCellInfo(mesh_.nCells());
|
changedFacesInfo_.setSize(mesh_.nFaces());
|
||||||
FaceCellWave<wallPoint> wave
|
|
||||||
|
writeFluidSolidInterface(aTilda_, 0, changedFaces_, changedFacesInfo_);
|
||||||
|
|
||||||
|
List<wallPointData<label>> allFaceInfo(mesh_.nFaces());
|
||||||
|
allCellInfo_.clear();
|
||||||
|
allCellInfo_.setSize(mesh_.nCells());
|
||||||
|
|
||||||
|
FaceCellWave<wallPointData<label>> wave
|
||||||
(
|
(
|
||||||
mesh_,
|
mesh_,
|
||||||
changedFaces,
|
changedFaces_,
|
||||||
changedFacesInfo,
|
changedFacesInfo_,
|
||||||
allFaceInfo,
|
allFaceInfo,
|
||||||
allCellInfo,
|
allCellInfo_,
|
||||||
mesh_.globalData().nTotalCells() + 1
|
mesh_.globalData().nTotalCells() + 1
|
||||||
);
|
);
|
||||||
|
|
||||||
// Transfer the distance from cellInfo to the alphaTilda field
|
// Transfer the distance from cellInfo to the alphaTilda field
|
||||||
forAll(allCellInfo, celli)
|
forAll(allCellInfo_, celli)
|
||||||
{
|
{
|
||||||
if (allCellInfo[celli].valid(wave.data()))
|
if (allCellInfo_[celli].valid(wave.data()))
|
||||||
{
|
{
|
||||||
aTilda_[celli] =
|
signedDistances_[celli] =
|
||||||
sign(aTilda_[celli])*Foam::sqrt(allCellInfo[celli].distSqr());
|
sign(aTilda_[celli])*Foam::sqrt(allCellInfo_[celli].distSqr());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
aTilda_.correctBoundaryConditions();
|
signedDistances_.correctBoundaryConditions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -281,6 +286,20 @@ levelSetDesignVariables::levelSetDesignVariables
|
|||||||
regularisation_
|
regularisation_
|
||||||
(regularisationPDE::New(mesh, dict.subDict("regularisation"), zones_)),
|
(regularisationPDE::New(mesh, dict.subDict("regularisation"), zones_)),
|
||||||
aTilda_
|
aTilda_
|
||||||
|
(
|
||||||
|
IOobject
|
||||||
|
(
|
||||||
|
"aTilda",
|
||||||
|
mesh_.time().timeName(),
|
||||||
|
mesh_,
|
||||||
|
IOobject::READ_IF_PRESENT,
|
||||||
|
IOobject::AUTO_WRITE
|
||||||
|
),
|
||||||
|
mesh_,
|
||||||
|
dimensionedScalar(dimless, Zero),
|
||||||
|
zeroGradientFvPatchField<scalar>::typeName
|
||||||
|
),
|
||||||
|
signedDistances_
|
||||||
(
|
(
|
||||||
IOobject
|
IOobject
|
||||||
(
|
(
|
||||||
@ -313,7 +332,10 @@ levelSetDesignVariables::levelSetDesignVariables
|
|||||||
),
|
),
|
||||||
fixATildaValues_(dict.getOrDefault<bool>("fixATildaValues", true)),
|
fixATildaValues_(dict.getOrDefault<bool>("fixATildaValues", true)),
|
||||||
writeAllDistanceFields_
|
writeAllDistanceFields_
|
||||||
(dict.getOrDefault<bool>("writeAllDistanceFields", false))
|
(dict.getOrDefault<bool>("writeAllDistanceFields", false)),
|
||||||
|
changedFaces_(),
|
||||||
|
changedFacesInfo_(),
|
||||||
|
allCellInfo_()
|
||||||
{
|
{
|
||||||
// Read the alpha field if present, or set it based on the distance field
|
// Read the alpha field if present, or set it based on the distance field
|
||||||
readField();
|
readField();
|
||||||
@ -382,20 +404,18 @@ void levelSetDesignVariables::update(scalarField& correction)
|
|||||||
if (writeAllDistanceFields_)
|
if (writeAllDistanceFields_)
|
||||||
{
|
{
|
||||||
writeDesignVars();
|
writeDesignVars();
|
||||||
aTilda_.rename("alphaSmoothed");
|
|
||||||
aTilda_.write();
|
aTilda_.write();
|
||||||
aTilda_.rename("signedDistances");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Make aTilda a signed distance field
|
// Compute signed distances based on aTilda
|
||||||
updateSignedDistances();
|
updateSignedDistances();
|
||||||
|
|
||||||
// Set beta based on aTilda
|
// Set beta based on the signed distances
|
||||||
updateBeta();
|
updateBeta();
|
||||||
|
|
||||||
if (writeAllDistanceFields_)
|
if (writeAllDistanceFields_)
|
||||||
{
|
{
|
||||||
aTilda_.write();
|
signedDistances_.write();
|
||||||
beta_.write();
|
beta_.write();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -411,77 +431,13 @@ void levelSetDesignVariables::update(scalarField& correction)
|
|||||||
|
|
||||||
scalar levelSetDesignVariables::computeEta(scalarField& correction)
|
scalar levelSetDesignVariables::computeEta(scalarField& correction)
|
||||||
{
|
{
|
||||||
// Back-up the old design variables and signed distances
|
const scalar maxChange(gMax(mag(correction)));
|
||||||
scalarField& dvs = getVars();
|
Info<< "maxInitChange/maxChange \t"
|
||||||
scalarField oldDVs(getVars());
|
<< maxInitChange_() << "/" << maxChange << endl;
|
||||||
scalarField oldSignedDistances(aTilda_.primitiveField());
|
const scalar eta(maxInitChange_() / maxChange);
|
||||||
|
|
||||||
// Compute the smooth alpha field corresponding to the initial variables
|
|
||||||
// Can't use current aTilda_ values since they correspond to signed
|
|
||||||
// distances at this point
|
|
||||||
scalarField oldATilda(aTilda_.primitiveField());
|
|
||||||
regularisation_->regularise
|
|
||||||
(
|
|
||||||
aTilda_, dvs, oldATilda,
|
|
||||||
true, radius_(), upperBounds_()[0], fixATildaValues_
|
|
||||||
);
|
|
||||||
|
|
||||||
// Compute the smooth alpha field corresponding to the updated variables
|
|
||||||
dvs += correction;
|
|
||||||
regularisation_->regularise
|
|
||||||
(
|
|
||||||
aTilda_, dvs, aTilda_.primitiveFieldRef(),
|
|
||||||
true, radius_(), upperBounds_()[0], fixATildaValues_
|
|
||||||
);
|
|
||||||
aTilda_.correctBoundaryConditions();
|
|
||||||
|
|
||||||
// We want to locate the min value of aTilda_ and scale the correction
|
|
||||||
// appropriately such that this min value takes on the prescribed one.
|
|
||||||
// A bit tricky in parallel since we need not only the min value but
|
|
||||||
// its cellId/processor too
|
|
||||||
|
|
||||||
const label proci = Pstream::myProcNo();
|
|
||||||
scalarList minVs(Pstream::nProcs(), pTraits<scalar>::max);
|
|
||||||
labelList minCells(Pstream::nProcs(), Zero);
|
|
||||||
|
|
||||||
scalarField diff(aTilda_.primitiveField() - oldATilda);
|
|
||||||
label minId = findMin(diff);
|
|
||||||
|
|
||||||
if (minId != -1)
|
|
||||||
{
|
|
||||||
minVs[proci] = diff[minId];
|
|
||||||
minCells[proci] = minId;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Collect info from all processors
|
|
||||||
Pstream::allGatherList(minVs);
|
|
||||||
Pstream::allGatherList(minCells);
|
|
||||||
|
|
||||||
minId = findMin(minVs);
|
|
||||||
|
|
||||||
scalar aTildaAtMinChange(Zero);
|
|
||||||
if (proci == minId)
|
|
||||||
{
|
|
||||||
const label cellId = minCells[minId];
|
|
||||||
aTildaAtMinChange = aTilda_.primitiveField()[cellId];
|
|
||||||
}
|
|
||||||
reduce(aTildaAtMinChange, sumOp<scalar>());
|
|
||||||
|
|
||||||
DebugInfo
|
|
||||||
<< "AlphaSmoothed at min(alphaSmoothedUpdate) with eta 1/"
|
|
||||||
<< "min desirable value "
|
|
||||||
<< minVs[minId] << '/' << maxInitChange_()
|
|
||||||
<< endl;
|
|
||||||
|
|
||||||
// Compute eta
|
|
||||||
const scalar eta((maxInitChange_() - aTildaAtMinChange)/minVs[minId] + 1);
|
|
||||||
Info<< "Setting eta value to " << eta << endl;
|
Info<< "Setting eta value to " << eta << endl;
|
||||||
correction *= eta;
|
correction *= eta;
|
||||||
|
|
||||||
// Restore the dvs
|
|
||||||
dvs = oldDVs;
|
|
||||||
aTilda_.primitiveFieldRef() = oldSignedDistances;
|
|
||||||
|
|
||||||
return eta;
|
return eta;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -505,7 +461,8 @@ tmp<scalarField> levelSetDesignVariables::assembleSensitivities
|
|||||||
scalarField& objectiveSens = tobjectiveSens.ref();
|
scalarField& objectiveSens = tobjectiveSens.ref();
|
||||||
|
|
||||||
// Multiply with dBetadAtilda
|
// Multiply with dBetadAtilda
|
||||||
objectiveSens *= -interpolation_->derivative(aTilda_.primitiveField());
|
objectiveSens *=
|
||||||
|
-interpolation_->derivative(signedDistances_.primitiveField());
|
||||||
|
|
||||||
// Solve the adjoint to the regularisation equation
|
// Solve the adjoint to the regularisation equation
|
||||||
regularisation_->
|
regularisation_->
|
||||||
|
|||||||
@ -92,11 +92,13 @@ protected:
|
|||||||
//- Regularisation mechanism
|
//- Regularisation mechanism
|
||||||
autoPtr<regularisationPDE> regularisation_;
|
autoPtr<regularisationPDE> regularisation_;
|
||||||
|
|
||||||
//- The regularised field that is also transformed
|
//- The regularised field
|
||||||
//- into signed distances
|
|
||||||
volScalarField aTilda_;
|
volScalarField aTilda_;
|
||||||
|
|
||||||
//- Function to transform signed distances to the indicator field beta_
|
//- The signed distances field
|
||||||
|
volScalarField signedDistances_;
|
||||||
|
|
||||||
|
//- Function to transorm signed distances to the indicator field beta_
|
||||||
autoPtr<topOInterpolationFunction> interpolation_;
|
autoPtr<topOInterpolationFunction> interpolation_;
|
||||||
|
|
||||||
//- The indicator field
|
//- The indicator field
|
||||||
@ -108,6 +110,15 @@ protected:
|
|||||||
//- Write all fields related to the distance calculation (debugging)
|
//- Write all fields related to the distance calculation (debugging)
|
||||||
bool writeAllDistanceFields_;
|
bool writeAllDistanceFields_;
|
||||||
|
|
||||||
|
//- Mesh faces acting as the source of MeshWave
|
||||||
|
labelList changedFaces_;
|
||||||
|
|
||||||
|
//- Seed distances to MeshWave and cell distances
|
||||||
|
// The data carried by each wallPoints corresponds to the origin
|
||||||
|
// mesh face ID
|
||||||
|
List<wallPointData<label>> changedFacesInfo_;
|
||||||
|
List<wallPointData<label>> allCellInfo_;
|
||||||
|
|
||||||
|
|
||||||
// Protected Member Functions
|
// Protected Member Functions
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user