/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2012-2017 OpenFOAM Foundation
Copyright (C) 2020 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see .
\*---------------------------------------------------------------------------*/
#include "conformationSurfaces.H"
#include "conformalVoronoiMesh.H"
#include "triSurface.H"
#include "searchableSurfaceFeatures.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(conformationSurfaces, 0);
}
// * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * * //
void Foam::conformationSurfaces::hasBoundedVolume
(
List& referenceVolumeTypes
) const
{
vector sum(Zero);
label totalTriangles = 0;
forAll(surfaces_, s)
{
const searchableSurface& surface(allGeometry_[surfaces_[s]]);
if
(
surface.hasVolumeType()
&& (
normalVolumeTypes_[regionOffset_[s]]
!= extendedFeatureEdgeMesh::BOTH
)
)
{
pointField pts(1, locationInMesh_);
List vTypes
(
pts.size(),
volumeType::UNKNOWN
);
surface.getVolumeType(pts, vTypes);
referenceVolumeTypes[s] = vTypes[0];
Info<< " is " << referenceVolumeTypes[s].str()
<< " surface " << surface.name()
<< endl;
}
if (isA(surface))
{
const triSurface& triSurf = refCast(surface);
const pointField& surfPts = triSurf.points();
Info<< " Checking " << surface.name() << endl;
label nBaffles = 0;
Info<< " Index = " << surfaces_[s] << endl;
Info<< " Offset = " << regionOffset_[s] << endl;
for (const labelledTri& f : triSurf)
{
const label patchID = f.region() + regionOffset_[s];
// Don't include baffle surfaces in the calculation
if
(
normalVolumeTypes_[patchID]
!= extendedFeatureEdgeMesh::BOTH
)
{
sum += f.areaNormal(surfPts);
}
else
{
++nBaffles;
}
}
Info<< " has " << nBaffles << " baffles out of "
<< triSurf.size() << " triangles" << nl;
totalTriangles += triSurf.size();
}
}
Info<< " Sum of all the surface normals (if near zero, surface is"
<< " probably closed):" << nl
<< " Note: Does not include baffle surfaces in calculation" << nl
<< " Sum = " << sum/(totalTriangles + SMALL) << nl
<< " mag(Sum) = " << mag(sum)/(totalTriangles + SMALL)
<< endl;
}
void Foam::conformationSurfaces::readFeatures
(
const label surfI,
const dictionary& featureDict,
const word& surfaceName,
label& featureIndex
)
{
const word featureMethod =
featureDict.getOrDefault("featureMethod", "none");
if (featureMethod == "extendedFeatureEdgeMesh")
{
fileName feMeshName
(
featureDict.get("extendedFeatureEdgeMesh")
);
Info<< " features: " << feMeshName << endl;
features_.set
(
featureIndex,
new extendedFeatureEdgeMesh
(
IOobject
(
feMeshName,
runTime_.time().constant(),
"extendedFeatureEdgeMesh",
runTime_.time(),
IOobject::MUST_READ,
IOobject::NO_WRITE
)
)
);
featureIndex++;
}
else if (featureMethod == "extractFeatures")
{
const searchableSurface& surface = allGeometry_[surfaces_[surfI]];
Info<< " features: " << surface.name()
<< " of type " << surface.type()
<< ", id: " << featureIndex << endl;
autoPtr ssFeatures
(
searchableSurfaceFeatures::New(surface, featureDict)
);
if (ssFeatures().hasFeatures())
{
features_.set
(
featureIndex,
ssFeatures().features()
);
featureIndex++;
}
else
{
WarningInFunction
<< surface.name() << " of type "
<< surface.type() << " does not have features"
<< endl;
}
}
else if (featureMethod == "none")
{
// Currently nothing to do
}
else
{
FatalErrorInFunction
<< "No valid featureMethod found for surface " << surfaceName
<< nl << "Use \"extendedFeatureEdgeMesh\" "
<< "or \"extractFeatures\"."
<< exit(FatalError);
}
}
void Foam::conformationSurfaces::readFeatures
(
const dictionary& featureDict,
const word& surfaceName,
label& featureIndex
)
{
const word featureMethod =
featureDict.getOrDefault("featureMethod", "none");
if (featureMethod == "extendedFeatureEdgeMesh")
{
fileName feMeshName
(
featureDict.get("extendedFeatureEdgeMesh")
);
Info<< " features: " << feMeshName << ", id: " << featureIndex
<< endl;
features_.set
(
featureIndex,
new extendedFeatureEdgeMesh
(
IOobject
(
feMeshName,
runTime_.time().constant(),
"extendedFeatureEdgeMesh",
runTime_.time(),
IOobject::MUST_READ,
IOobject::NO_WRITE
)
)
);
featureIndex++;
}
else if (featureMethod == "none")
{
// Currently nothing to do
}
else
{
FatalErrorInFunction
<< "No valid featureMethod found for surface " << surfaceName
<< nl << "Use \"extendedFeatureEdgeMesh\" "
<< "or \"extractFeatures\"."
<< exit(FatalError);
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::conformationSurfaces::conformationSurfaces
(
const Time& runTime,
Random& rndGen,
const searchableSurfaces& allGeometry,
const dictionary& surfaceConformationDict
)
:
runTime_(runTime),
rndGen_(rndGen),
allGeometry_(allGeometry),
features_(),
locationInMesh_(surfaceConformationDict.get("locationInMesh")),
surfaces_(),
allGeometryToSurfaces_(),
normalVolumeTypes_(),
patchNames_(),
surfZones_(),
regionOffset_(),
patchInfo_(),
globalBounds_(),
referenceVolumeTypes_(0)
{
const dictionary& surfacesDict
(
surfaceConformationDict.subDict("geometryToConformTo")
);
const dictionary& additionalFeaturesDict
(
surfaceConformationDict.subDict("additionalFeatures")
);
// Wildcard specification : loop over all surface, all regions
// and try to find a match.
// Count number of surfaces.
label surfI = 0;
for (const word& geomName : allGeometry_.names())
{
if (surfacesDict.found(geomName))
{
++surfI;
}
}
const label nAddFeat = additionalFeaturesDict.size();
Info<< nl << "Reading geometryToConformTo" << endl;
allGeometryToSurfaces_.setSize(allGeometry_.size(), -1);
normalVolumeTypes_.setSize(surfI);
surfaces_.setSize(surfI);
surfZones_.setSize(surfI);
// Features may be attached to host surfaces or independent
features_.setSize(surfI + nAddFeat);
label featureI = 0;
regionOffset_.setSize(surfI, 0);
PtrList globalPatchInfo(surfI);
List