/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2011-2024 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
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 "meshRefinement.H"
#include "volMesh.H"
#include "volFields.H"
#include "surfaceMesh.H"
#include "syncTools.H"
#include "Time.H"
#include "refinementHistory.H"
#include "refinementSurfaces.H"
#include "refinementFeatures.H"
#include "decompositionMethod.H"
#include "regionSplit.H"
#include "fvMeshDistribute.H"
#include "indirectPrimitivePatch.H"
#include "polyTopoChange.H"
#include "removeCells.H"
#include "polyDistributionMap.H"
#include "localPointRegion.H"
#include "pointMesh.H"
#include "pointFields.H"
#include "slipPointPatchFields.H"
#include "fixedValuePointPatchFields.H"
#include "calculatedPointPatchFields.H"
#include "cyclicSlipPointPatchFields.H"
#include "processorPointPatch.H"
#include "globalIndex.H"
#include "meshTools.H"
#include "OFstream.H"
#include "geomDecomp.H"
#include "Random.H"
#include "searchableSurfaces.H"
#include "treeBoundBox.H"
#include "fvMeshTools.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(meshRefinement, 0);
template<>
const char* Foam::NamedEnum
<
Foam::meshRefinement::IOdebugType,
5
>::names[] =
{
"mesh",
"intersections",
"featureSeeds",
"attraction",
"layerInfo"
};
template<>
const char* Foam::NamedEnum
<
Foam::meshRefinement::IOoutputType,
1
>::names[] =
{
"layerInfo"
};
template<>
const char* Foam::NamedEnum
<
Foam::meshRefinement::IOwriteType,
5
>::names[] =
{
"mesh",
"noRefinement",
"scalarLevels",
"layerSets",
"layerFields"
};
}
const Foam::NamedEnum
Foam::meshRefinement::IOdebugTypeNames;
const Foam::NamedEnum
Foam::meshRefinement::IOoutputTypeNames;
const Foam::NamedEnum
Foam::meshRefinement::IOwriteTypeNames;
Foam::meshRefinement::writeType Foam::meshRefinement::writeLevel_;
Foam::meshRefinement::outputType Foam::meshRefinement::outputLevel_;
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::meshRefinement::calcNeighbourData
(
labelList& neiLevel,
pointField& neiCc
) const
{
const labelList& cellLevel = meshCutter_.cellLevel();
const pointField& cellCentres = mesh_.cellCentres();
const label nBoundaryFaces = mesh_.nFaces() - mesh_.nInternalFaces();
if (neiLevel.size() != nBoundaryFaces || neiCc.size() != nBoundaryFaces)
{
FatalErrorInFunction
<< nBoundaryFaces << " neiLevel:" << neiLevel.size()
<< abort(FatalError);
}
const polyBoundaryMesh& patches = mesh_.boundaryMesh();
labelHashSet addedPatchIDSet(meshedPatches());
forAll(patches, patchi)
{
const polyPatch& pp = patches[patchi];
const labelUList& faceCells = pp.faceCells();
const vectorField::subField faceCentres = pp.faceCentres();
const vectorField::subField faceAreas = pp.faceAreas();
label bFacei = pp.start() - mesh_.nInternalFaces();
if (pp.coupled())
{
forAll(faceCells, i)
{
neiLevel[bFacei] = cellLevel[faceCells[i]];
neiCc[bFacei] = cellCentres[faceCells[i]];
bFacei++;
}
}
else if (addedPatchIDSet.found(patchi))
{
// Face was introduced from cell-cell intersection. Try to
// reconstruct other side cell(centre). Three possibilities:
// - cells same size.
// - preserved cell smaller. Not handled.
// - preserved cell larger.
forAll(faceCells, i)
{
// Extrapolate the face centre.
const vector fn = faceAreas[i]/(mag(faceAreas[i]) + vSmall);
const label own = faceCells[i];
const label ownLevel = cellLevel[own];
const label faceLevel = meshCutter_.faceLevel(pp.start() + i);
// Normal distance from face centre to cell centre
scalar d = ((faceCentres[i] - cellCentres[own]) & fn);
if (faceLevel > ownLevel)
{
// Other cell more refined. Adjust normal distance
d *= 0.5;
}
neiLevel[bFacei] = faceLevel;
// Calculate other cell centre by extrapolation
neiCc[bFacei] = faceCentres[i] + d*fn;
bFacei++;
}
}
else
{
forAll(faceCells, i)
{
neiLevel[bFacei] = cellLevel[faceCells[i]];
neiCc[bFacei] = faceCentres[i];
bFacei++;
}
}
}
// Swap coupled boundaries. Apply separation to cc since is coordinate.
syncTools::swapBoundaryFacePositions(mesh_, neiCc);
syncTools::swapBoundaryFaceList(mesh_, neiLevel);
}
void Foam::meshRefinement::updateIntersections(const labelList& changedFaces)
{
const pointField& cellCentres = mesh_.cellCentres();
// Stats on edges to test. Count proc faces only once.
PackedBoolList isMasterFace(syncTools::getMasterFaces(mesh_));
{
label nMasterFaces = 0;
forAll(isMasterFace, facei)
{
if (isMasterFace.get(facei) == 1)
{
nMasterFaces++;
}
}
reduce(nMasterFaces, sumOp