/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | Website: https://openfoam.org
\\ / A nd | Copyright (C) 2023 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 "meshingSurfaceList.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::meshingSurfaceList::mergeBoundingBoxes
(
boundBox& bb1,
const boundBox& bb2
)
{
if (bb1.volume() == 0)
{
bb1 = bb2;
return;
}
point& min1 = bb1.min();
point& max1 = bb1.max();
const point& min2 = bb2.min();
const point& max2 = bb2.max();
forAll(min1, i)
{
min1[i] = Foam::min(min1[i], min2[i]);
max1[i] = Foam::max(max1[i], max2[i]);
}
}
void Foam::meshingSurfaceList::swapExternalIndexZero(const label index)
{
if (index == 0)
{
return;
}
autoPtr s0Ptr(set(0, nullptr));
autoPtr sIndexPtr(set(index, nullptr));
set(index, s0Ptr.ptr());
set(0, sIndexPtr.ptr());
}
bool Foam::meshingSurfaceList::regionsValid
(
const wordList& specifiedRegions,
const wordList& regions,
const word& opt
)
{
if (specifiedRegions.empty())
{
return false;
}
forAll(specifiedRegions, s)
{
bool match(false);
forAll(regions, r)
{
match = (specifiedRegions[s] == regions[r]) || match;
if (match)
{
break;
}
}
if (!match)
{
FatalErrorInFunction
<< "Region '"<< specifiedRegions[s]
<< "' specified with the '" << opt
<< "' option" << nl
<< "does not match any regions in the external surface"
<< exit(FatalError);
}
}
return true;
}
void Foam::meshingSurfaceList::setSurfaceTypes
(
const List& surfaces,
const surfaceType& type
)
{
forAll(surfaces, i)
{
const word surface = fileName(surfaces[i]).lessExt();
const word surfaceType = meshingSurface::surfaceTypeNames[type];
bool match = false;
// Check if the surface name matches a surface name
forAll(*this, surfi)
{
if (surface == operator[](surfi).name())
{
// For cellZone and rotatingZone, ensure surface is closed
if
(
!operator[](surfi).closed()
&& (
type == meshingSurface::surfaceType::rotatingZone
|| type == meshingSurface::surfaceType::cellZone
)
)
{
FatalErrorInFunction
<< "Argument to '-" << surfaceType
<< "' contains the " << surfaceType << " '"
<< surface << "'" << nl
<< "which is not a closed surface."
<< exit(FatalError);
}
operator[](surfi).type() = type;
match = true;
break;
}
}
if (!match)
{
FatalErrorInFunction
<< "Argument to '-" << surfaceType
<< "' contains the " << surfaceType << " '"
<< surface << "'" << nl
<< "which does not correspond to any surfaces."
<< exit(FatalError);
}
}
}
void Foam::meshingSurfaceList::setRotatingZoneBounds()
{
forAll(*this, surfi)
{
if (operator[](surfi).type() == surfaceType::rotatingZone)
{
mergeBoundingBoxes(rzbb_, operator[](surfi).bb());
}
}
}
void Foam::meshingSurfaceList::identifyCellZones()
{
forAll(*this, i)
{
if
(
operator[](i).type() == surfaceType::external
|| operator[](i).type() == surfaceType::rotatingZone
|| operator[](i).nParts() != 1
|| !operator[](i).closed()
)
{
continue;
}
forAll(*this, j)
{
if (i == j)
{
continue;
}
if (operator[](i).bb().contains(operator[](j).bb()))
{
operator[](i).type() = surfaceType::cellZone;
continue;
}
}
}
}
void Foam::meshingSurfaceList::reportWordList(const wordList& wl)
{
forAll(wl, i)
{
Info<< wl[i];
if (i != wl.size() - 1)
{
Info<< ", ";
}
}
Info<< endl;
}
void Foam::meshingSurfaceList::reportSurfaces()
{
Info<< "Case contains the following surface geometry files:"
<< endl;
forAll(*this, i)
{
Info<< "+ " << operator[](i).name() << nl
<< " + File: " << operator[](i).file() << nl
<< " + Bounding box: " << operator[](i).bb() << nl
<< " + " << (operator[](i).closed() ? "Closed" : "Open")
<< " surface" << endl;
switch (operator[](i).type())
{
case surfaceType::external:
{
Info << " + External boundary surface" << endl;
if (!operator[](i).inletRegions().empty())
{
Info<< " + Inlet regions: ";
reportWordList(operator[](i).inletRegions());
}
if (!operator[](i).outletRegions().empty())
{
Info << " + Outlet regions: ";
reportWordList(operator[](i).outletRegions());
}
break;
}
case surfaceType::wall:
{
Info << " + Wall boundary surface" << endl;
break;
}
case surfaceType::cellZone:
{
Info << " + Cell zone surface" << endl;
break;
}
case surfaceType::rotatingZone:
{
Info << " + Rotating zone surface" << endl;
break;
}
case surfaceType::baffle:
{
Info << " + Baffle wall surface" << endl;
break;
}
}
}
Info<< endl;
}
void Foam::meshingSurfaceList::setBounds(const boundBox& bb)
{
if (bb.contains(bb_))
{
Info<< "Specified bounding box contains the overall bounding box"
<< endl;
}
else
{
WarningInFunction
<< "Specified bounding box does not contain the overall "
<< "bounding box"
<< endl;
}
if (bb.mag() > 1.5*bb_.mag())
{
Info<< "Specified bounding box is > (1.5 * overall "
<< "bounding box)" << nl
<< "**Assuming this is an external flow**"
<< endl;
operator[](0).type() = surfaceType::wall;
}
Info<< endl;
bb_ = bb;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::meshingSurfaceList::meshingSurfaceList
(
const Time& time,
const fileNameList& surfaces,
const wordList& cellZones,
const wordList& rotatingZones,
const wordList& baffles,
const boundBox& bb,
const wordList& specifiedInletRegions,
const wordList& specifiedOutletRegions
)
:
PtrList(),
bb_(),
rzbb_()
{
// Load all the surfaces and construct the bounding box
forAll(surfaces, i)
{
append(new meshingSurface(surfaces[i], time));
mergeBoundingBoxes(bb_, last().bb());
}
label externalID = 0;
forAll(surfaces, i)
{
// Test for external surface inflates the bounding box by a small factor
// to account for imprecise surface geometry files
boundBox bbInflate = operator[](i).bb();
bbInflate.inflate(1e-4);
if
(
operator[](i).closed()
&& operator[](i).nParts() == 1
&& bbInflate.contains(bb_)
)
{
externalID = i;
operator[](i).type() = surfaceType::external;
// Override any inlet and outlet regions on external boundary
// specified by the '-inletRegions' and '-outletRegions' options
const wordList& regions = operator[](i).regions();
wordList& inletRegions = operator[](i).inletRegions();
if (regionsValid(specifiedInletRegions, regions, "-inletRegions"))
{
inletRegions = specifiedInletRegions;
}
wordList& outletRegions = operator[](i).outletRegions();
if (regionsValid(specifiedOutletRegions, regions, "-outletRegions"))
{
outletRegions = specifiedOutletRegions;
}
// If inletRegions and outletRegions are both empty, set "template"
// names
if (inletRegions.empty() && outletRegions.empty())
{
inletRegions.append("");
outletRegions.append("");
}
}
}
swapExternalIndexZero(externalID);
if (!rotatingZones.empty())
{
setSurfaceTypes(rotatingZones, surfaceType::rotatingZone);
}
if (!baffles.empty())
{
setSurfaceTypes(baffles, surfaceType::baffle);
}
setRotatingZoneBounds();
if (cellZones.empty())
{
identifyCellZones();
}
else
{
setSurfaceTypes(cellZones, surfaceType::cellZone);
}
reportSurfaces();
if (bb.volume() != 0)
{
setBounds(bb);
}
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::meshingSurfaceList::~meshingSurfaceList()
{}
// ************************************************************************* //