mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: Added new createViewFactors utility
Creates view factors for the view factor radiation model.
User-selectable models:
- raySearchEngine: model to generate rays, i.e. face-to-face connections
- viewFactorModel: model to compute the view factors
For visualisation, use:
- Write the view factors as a volume field
writeViewFactors yes;
- Write the rays using OBJ format:
writeRays yes; // default = no
Participating patches must be in the \c vewFactorWall group, i.e. using the
\c inGroups entry of the "\<case\>/polyMesh/boundary" file.
\verbatim
myPatch
{
type wall;
inGroups 2(wall viewFactorWall);
...
}
\endverbatim
Reads:
- <constant>/viewFactorsDict : main controls
- <constant>/finalAgglom : agglomeration addressing (from faceAgglomerate)
Generates:
- <constant>/F : view factors (matrix)
- <constant>/mapDist : map used for parallel running
- <constant>/globalFaceFaces : face addressing
This commit is contained in:
committed by
Kutalmis Bercin
parent
7c45670c8b
commit
ab5f6dbf41
11
applications/utilities/preProcessing/createViewFactors/Allwmake
Executable file
11
applications/utilities/preProcessing/createViewFactors/Allwmake
Executable file
@ -0,0 +1,11 @@
|
||||
#!/bin/sh
|
||||
cd "${0%/*}" || exit # Run from this directory
|
||||
|
||||
. "$WM_PROJECT_DIR"/wmake/scripts/AllwmakeParseArguments
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
|
||||
wmake $targetType viewFactorModels
|
||||
wmake $targetType createViewFactors
|
||||
|
||||
#------------------------------------------------------------------------------
|
||||
@ -0,0 +1,3 @@
|
||||
createViewFactors.C
|
||||
|
||||
EXE = $(FOAM_APPBIN)/createViewFactors
|
||||
@ -0,0 +1,7 @@
|
||||
EXE_INC = \
|
||||
-I../viewFactorModels/lnInclude \
|
||||
-I$(LIB_SRC)/finiteVolume/lnInclude
|
||||
|
||||
EXE_LIBS = \
|
||||
-lviewFactorModels \
|
||||
-lfiniteVolume
|
||||
@ -0,0 +1,165 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2023 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Application
|
||||
createViewFactors
|
||||
|
||||
Group
|
||||
grpPreProcessingUtilities
|
||||
|
||||
Description
|
||||
Creates view factors to be used in the view-factor radiation model.
|
||||
|
||||
Operands:
|
||||
\table
|
||||
Operand | Type | Location
|
||||
input | dictionary | \<constant\>/viewFactorsDict
|
||||
input | dictionary | \<constant\>/finalAgglom
|
||||
output | scalarListList | \<constant\>/F
|
||||
output | mapDistribute | \<constant\>/mapDist
|
||||
output | labelListList | \<constant\>/globalFaceFaces
|
||||
output | volScalarField | \<time\>/viewVectorField
|
||||
output | OBJ | allVisibleFaces.obj
|
||||
\endtable
|
||||
|
||||
where the dictionaries mean:
|
||||
\table
|
||||
Dictionary | Description
|
||||
viewFactorsDict | Main-control dictionary
|
||||
finalAgglom | (Optional) Agglomeration addressing (from faceAgglomerate)
|
||||
F | View factors (matrix)
|
||||
mapDist | Map used for parallel running
|
||||
globalFaceFaces | Face addressing
|
||||
viewVectorField | View factors as a volume field
|
||||
allVisibleFaces.obj | The visualisation of the rays
|
||||
\endtable
|
||||
|
||||
Usage
|
||||
Minimal example in \c <constant>/viewFactorsDict:
|
||||
\verbatim
|
||||
// Inherited entries
|
||||
raySearchEngine <word>;
|
||||
agglomerate <bool>;
|
||||
nRayPerFace <label>;
|
||||
writeViewFactors <bool>;
|
||||
writeRays <bool>;
|
||||
...
|
||||
\endverbatim
|
||||
|
||||
where the entries mean:
|
||||
\table
|
||||
Property | Description | Type | Reqd | Deflt
|
||||
raySearchEngine | Ray search engine type | word | yes | -
|
||||
agglomerate | Flag to agglomeration | bool | yes | -
|
||||
nRayPerFace | Number of rays issued per face | label | yes | -
|
||||
writeViewFactors | Flag to write the view factor field | bool | yes |-
|
||||
writeRays | Flag to write the ray geometry | bool | no | false
|
||||
\endtable
|
||||
|
||||
Options for the \c raySearchEngine entry:
|
||||
\verbatim
|
||||
voxel | Ray search engine discretising space into uniform voxels
|
||||
\endverbatim
|
||||
|
||||
The inherited entries are elaborated in:
|
||||
- \link viewFactorModel.H \endlink
|
||||
- \link raySearchEngine.H \endlink
|
||||
|
||||
Note
|
||||
|
||||
- Participating patches must be in the \c vewFactorWall group, i.e. using the
|
||||
\c inGroups entry of the "\<case\>/polyMesh/boundary" file.
|
||||
|
||||
\verbatim
|
||||
myPatch
|
||||
{
|
||||
type wall;
|
||||
inGroups 2(wall viewFactorWall);
|
||||
...
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
Reads:
|
||||
|
||||
- <constant>/viewFactorsDict : main controls
|
||||
- <constant>/finalAgglom : agglomeration addressing (from faceAgglomerate)
|
||||
|
||||
|
||||
Generates:
|
||||
|
||||
- <constant>/F : view factors (matrix)
|
||||
- <constant>/mapDist : map used for parallel running
|
||||
- <constant>/globalFaceFaces : face addressing
|
||||
|
||||
SeeAlso
|
||||
- Foam::VF::raySearchEngine
|
||||
- Foam::VE::viewFactorModel
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "argList.H"
|
||||
#include "Time.H"
|
||||
#include "fvMesh.H"
|
||||
#include "viewFactorModel.H"
|
||||
|
||||
using namespace Foam;
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#include "addRegionOption.H"
|
||||
#include "setRootCase.H"
|
||||
#include "createTime.H"
|
||||
#include "createNamedMesh.H"
|
||||
|
||||
IOdictionary dict
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"viewFactorsDict",
|
||||
runTime.constant(),
|
||||
mesh,
|
||||
IOobject::MUST_READ
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
// Calculate the view factors
|
||||
auto modelPtr = VF::viewFactorModel::New(mesh, dict);
|
||||
|
||||
modelPtr->calculate();
|
||||
|
||||
Info<< nl;
|
||||
|
||||
runTime.printExecutionTime(Info);
|
||||
|
||||
Info<< "End\n" << endl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,12 @@
|
||||
raySearchEngine/raySearchEngine/raySearchEngine.C
|
||||
raySearchEngine/raySearchEngine/raySearchEngineNew.C
|
||||
raySearchEngine/voxel/voxelRaySearchEngine.C
|
||||
/* raySearchEngine/nonUniformVoxel/nonUniformVoxelRaySearchEngine.C */
|
||||
/* raySearchEngine/allToAll/allToAllRaySearchEngine.C */
|
||||
viewFactorModel/viewFactorModel/viewFactorModel.C
|
||||
viewFactorModel/viewFactorModel/viewFactorModelNew.C
|
||||
viewFactorModel/viewFactor2AI/viewFactor2AI.C
|
||||
viewFactorModel/viewFactor2LI/viewFactor2LI.C
|
||||
viewFactorModel/viewFactorHottel/viewFactorHottel.C
|
||||
|
||||
LIB = $(FOAM_LIBBIN)/libviewFactorModels
|
||||
@ -0,0 +1,14 @@
|
||||
EXE_INC = \
|
||||
-I$(LIB_SRC)/finiteVolume/lnInclude \
|
||||
-I$(LIB_SRC)/surfMesh/lnInclude \
|
||||
-I$(LIB_SRC)/meshTools/lnInclude \
|
||||
-I$(LIB_SRC)/parallel/distributed/lnInclude \
|
||||
-I$(LIB_SRC)/fileFormats/lnInclude
|
||||
|
||||
EXE_LIBS = \
|
||||
-lfiniteVolume \
|
||||
-lsurfMesh \
|
||||
-lmeshTools \
|
||||
-ldistributed \
|
||||
-lradiationModels \
|
||||
-lfileFormats
|
||||
@ -0,0 +1,620 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2023-2024 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "raySearchEngine.H"
|
||||
#include "surfaceFields.H"
|
||||
#include "volFields.H"
|
||||
#include "meshTools.H"
|
||||
|
||||
using namespace Foam::constant;
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace VF
|
||||
{
|
||||
defineTypeNameAndDebug(raySearchEngine, 0);
|
||||
defineRunTimeSelectionTable(raySearchEngine, mesh);
|
||||
|
||||
const label raySearchEngine::maxDynListLength = 1000000000;
|
||||
}
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::VF::raySearchEngine::check
|
||||
(
|
||||
const labelList& nVisibleFaceFaces
|
||||
)
|
||||
{
|
||||
label nRay = 0;
|
||||
label nFaceMin = labelMax;
|
||||
label nFaceMax = labelMin;
|
||||
for (const label n : nVisibleFaceFaces)
|
||||
{
|
||||
nFaceMin = min(nFaceMin, n);
|
||||
nFaceMax = max(nFaceMax, n);
|
||||
nRay += n;
|
||||
}
|
||||
|
||||
const label nFace = nVisibleFaceFaces.size();
|
||||
const label nGlobalRays = returnReduce(nRay, sumOp<label>());
|
||||
|
||||
if (nGlobalRays == 0)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "No rays identified - view factors will not be calculated"
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
const label globalNFacesMin = returnReduce(nFaceMin, minOp<label>());
|
||||
const label globalNFacesMax = returnReduce(nFaceMax, maxOp<label>());
|
||||
const label nGlobalFaces = returnReduce(nFace, sumOp<label>());
|
||||
const scalar avgFaces = nGlobalRays/scalar(nGlobalFaces);
|
||||
|
||||
Info<< "\nRay summary:" << nl
|
||||
<< " Number of rays: " << nGlobalRays << nl
|
||||
<< " Number of rays-per-face (min, max, average): ("
|
||||
<< globalNFacesMin << ", "
|
||||
<< globalNFacesMax << ", "
|
||||
<< avgFaces << ")" << endl;
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::VF::raySearchEngine::closestPointIndex
|
||||
(
|
||||
const point& p0,
|
||||
const List<point>& pts
|
||||
)
|
||||
{
|
||||
label pointi = -1;
|
||||
|
||||
scalar distSqr = GREAT;
|
||||
forAll(pts, pti)
|
||||
{
|
||||
const scalar d2 = magSqr(pts[pti] - p0);
|
||||
if (d2 < distSqr)
|
||||
{
|
||||
pointi = pti;
|
||||
distSqr = d2;
|
||||
}
|
||||
}
|
||||
|
||||
return pointi;
|
||||
}
|
||||
|
||||
|
||||
void Foam::VF::raySearchEngine::createAgglomeration(const IOobject& io)
|
||||
{
|
||||
Info<< "\nFace agglomeration: active" << nl
|
||||
<< " Reading file " << io.name() << endl;
|
||||
|
||||
// Read agglomeration map
|
||||
const labelListIOList finalAgglom(io);
|
||||
|
||||
Info<< " Creating coarse mesh" << nl;
|
||||
|
||||
agglomMeshPtr_.reset
|
||||
(
|
||||
new singleCellFvMesh
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
IOobject::scopedName("agglom", mesh_.name()),
|
||||
mesh_.time().timeName(),
|
||||
mesh_.time(),
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE
|
||||
),
|
||||
mesh_,
|
||||
finalAgglom
|
||||
)
|
||||
);
|
||||
|
||||
const auto& coarseMesh = agglomMeshPtr_();
|
||||
|
||||
|
||||
// Calculate total number of fine and coarse faces
|
||||
|
||||
nCoarseFace_ = 0;
|
||||
nFace_ = 0;
|
||||
|
||||
const polyBoundaryMesh& finePatches = mesh_.boundaryMesh();
|
||||
const polyBoundaryMesh& coarsePatches = coarseMesh.boundaryMesh();
|
||||
|
||||
for (const label patchi : patchIDs_)
|
||||
{
|
||||
nCoarseFace_ += coarsePatches[patchi].size();
|
||||
nFace_ += finePatches[patchi].size();
|
||||
}
|
||||
|
||||
Info<< "\nTotal number of coarse faces: "
|
||||
<< returnReduce(nCoarseFace_, sumOp<label>())
|
||||
<< endl;
|
||||
|
||||
Info<< "\nTotal number of fine faces: "
|
||||
<< returnReduce(nFace_, sumOp<label>())
|
||||
<< endl;
|
||||
|
||||
// Collect local Cf, Sf, agglom index on coarse mesh
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
DynamicList<point> localCf(nCoarseFace_);
|
||||
DynamicList<vector> localSf(nCoarseFace_);
|
||||
DynamicList<label> localAgg(nCoarseFace_);
|
||||
|
||||
for (const label patchi : patchIDs_)
|
||||
{
|
||||
const labelList& agglom = finalAgglom[patchi];
|
||||
|
||||
if (agglom.empty()) continue;
|
||||
|
||||
label nAgglom = max(agglom) + 1;
|
||||
const labelListList coarseToFine(invertOneToMany(nAgglom, agglom));
|
||||
const labelList& coarsePatchFace = coarseMesh.patchFaceMap()[patchi];
|
||||
|
||||
const pointField& coarseCf = coarseMesh.Cf().boundaryField()[patchi];
|
||||
const vectorField& coarseSf = coarseMesh.Sf().boundaryField()[patchi];
|
||||
|
||||
const polyPatch& pp = finePatches[patchi];
|
||||
patchAreas_[patchi] += sum(coarseMesh.magSf().boundaryField()[patchi]);
|
||||
|
||||
forAll(coarseCf, facei)
|
||||
{
|
||||
const label coarseFacei = coarsePatchFace[facei];
|
||||
const label agglomi = coarseFacei + coarsePatches[patchi].start();
|
||||
|
||||
// Construct single coarse face
|
||||
const labelList& fineFaces = coarseToFine[coarseFacei];
|
||||
uindirectPrimitivePatch cf
|
||||
(
|
||||
UIndirectList<face>(pp, fineFaces),
|
||||
pp.points()
|
||||
);
|
||||
|
||||
// Collect all points (vertices, face centres)
|
||||
const label nFaces = cf.faceCentres().size();
|
||||
const label nPoints = cf.localPoints().size();
|
||||
List<point> allPoints(nFaces + nPoints);
|
||||
SubList<point>(allPoints, nFaces) = cf.faceCentres();
|
||||
SubList<point>(allPoints, nPoints, nFaces) = cf.localPoints();
|
||||
|
||||
// Coarse face centre set to closest point
|
||||
const label pti = closestPointIndex(coarseCf[facei], allPoints);
|
||||
|
||||
if (pti != -1)
|
||||
{
|
||||
localCf.push_back(allPoints[pti]);
|
||||
localSf.push_back(coarseSf[facei]);
|
||||
localAgg.push_back(agglomi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Info<< "\nAssembled coarse patch data" << endl;
|
||||
|
||||
// Distribute local coarse Cf and Sf for shooting rays
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
allCf_[Pstream::myProcNo()].transfer(localCf);
|
||||
allSf_[Pstream::myProcNo()].transfer(localSf);
|
||||
allAgg_[Pstream::myProcNo()].transfer(localAgg);
|
||||
|
||||
Pstream::allGatherList(allCf_);
|
||||
Pstream::allGatherList(allSf_);
|
||||
Pstream::allGatherList(allAgg_);
|
||||
|
||||
Pstream::listCombineGather(patchAreas_, plusEqOp<scalar>());
|
||||
Pstream::broadcast(patchAreas_);
|
||||
|
||||
globalNumbering_ = globalIndex(nCoarseFace_);
|
||||
}
|
||||
|
||||
|
||||
void Foam::VF::raySearchEngine::createGeometry()
|
||||
{
|
||||
DynamicList<point> localCf(mesh_.nBoundaryFaces());
|
||||
DynamicList<vector> localSf(mesh_.nBoundaryFaces());
|
||||
|
||||
const auto& pbm = mesh_.boundaryMesh();
|
||||
|
||||
for (const label patchi : patchIDs_)
|
||||
{
|
||||
localCf.push_back(pbm[patchi].faceCentres());
|
||||
localSf.push_back(pbm[patchi].faceAreas());
|
||||
|
||||
patchAreas_[patchi] += sum(mesh_.magSf().boundaryField()[patchi]);
|
||||
}
|
||||
|
||||
Info<< "\nAssembled patch data" << endl;
|
||||
|
||||
nFace_ = localCf.size();
|
||||
nCoarseFace_ = -1;
|
||||
|
||||
allCf_[Pstream::myProcNo()].transfer(localCf);
|
||||
allSf_[Pstream::myProcNo()].transfer(localSf);
|
||||
|
||||
Pstream::allGatherList(allCf_);
|
||||
Pstream::allGatherList(allSf_);
|
||||
|
||||
Pstream::listCombineGather(patchAreas_, plusEqOp<scalar>());
|
||||
Pstream::broadcast(patchAreas_);
|
||||
|
||||
globalNumbering_ = globalIndex(nFace_);
|
||||
}
|
||||
|
||||
|
||||
void Foam::VF::raySearchEngine::createParallelAddressing
|
||||
(
|
||||
labelList& rayEndFace
|
||||
) const
|
||||
{
|
||||
// Construct compact numbering
|
||||
// - return map from remote to compact indices
|
||||
// (per processor (!= myProcNo) a map from remote index to compact index)
|
||||
// - construct distribute map
|
||||
// - renumber rayEndFace into compact addressing
|
||||
|
||||
DebugInfo << "\nCreating map distribute" << endl;
|
||||
|
||||
List<Map<label>> compactMap(Pstream::nProcs());
|
||||
mapPtr_.reset(new mapDistribute(globalNumbering_, rayEndFace, compactMap));
|
||||
|
||||
DebugInfo << "\nCreating compact-to-global addressing" << endl;
|
||||
|
||||
// Invert compactMap (from processor+localface to compact) to go
|
||||
// from compact to processor+localface (expressed as a globalIndex)
|
||||
compactToGlobal_.resize_nocopy(mapPtr_->constructSize());
|
||||
|
||||
// Local indices first
|
||||
// Note: are not in compactMap
|
||||
for (label i = 0; i < globalNumbering_.localSize(); ++i)
|
||||
{
|
||||
compactToGlobal_[i] = globalNumbering_.toGlobal(i);
|
||||
}
|
||||
|
||||
forAll(compactMap, proci)
|
||||
{
|
||||
const Map<label>& localToCompactMap = compactMap[proci];
|
||||
|
||||
forAllConstIters(localToCompactMap, iter)
|
||||
{
|
||||
compactToGlobal_[*iter] =
|
||||
globalNumbering_.toGlobal(proci, iter.key());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::coordSystem::cartesian Foam::VF::raySearchEngine::createCoordSystem
|
||||
(
|
||||
const point& origin,
|
||||
const vector& dir
|
||||
) const
|
||||
{
|
||||
vector axis(Zero);
|
||||
|
||||
for (direction d=0; d<3; ++d)
|
||||
{
|
||||
axis = dir^tensor::I.col(d);
|
||||
|
||||
// Remove empty direction for 2D
|
||||
if (mesh_.nSolutionD() == 2)
|
||||
{
|
||||
meshTools::constrainDirection(mesh_, mesh_.solutionD(), axis);
|
||||
}
|
||||
|
||||
if (magSqr(axis) > 0)
|
||||
{
|
||||
axis.normalise();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return coordSystem::cartesian(origin, dir, axis);
|
||||
}
|
||||
|
||||
|
||||
Foam::tmp<Foam::pointField> Foam::VF::raySearchEngine::createHemiPoints
|
||||
(
|
||||
const label nRayPerFace
|
||||
) const
|
||||
{
|
||||
auto themiPts = tmp<pointField>::New(nRayPerFace);
|
||||
auto& hemiPts = themiPts.ref();
|
||||
|
||||
const label nPoints = hemiPts.size();
|
||||
|
||||
if (mesh_.nSolutionD() == 3)
|
||||
{
|
||||
// Point in range -1 < x < 1; -1 < y < 1; 0 < z 1
|
||||
|
||||
forAll(hemiPts, pointi)
|
||||
{
|
||||
const scalar phi = Foam::acos(1 - (pointi + 0.5)/nPoints);
|
||||
const scalar theta =
|
||||
mathematical::pi*(1 + Foam::sqrt(5.0))*(pointi + 0.5);
|
||||
|
||||
hemiPts[pointi] =
|
||||
vector
|
||||
(
|
||||
Foam::cos(theta)*Foam::sin(phi),
|
||||
Foam::sin(theta)*Foam::sin(phi),
|
||||
Foam::cos(phi)
|
||||
);
|
||||
}
|
||||
}
|
||||
else if (mesh_.nSolutionD() == 2)
|
||||
{
|
||||
// Point in range -1 < x < 1; y = 0; 0 < z < 1; _\|/_
|
||||
|
||||
forAll(hemiPts, pointi)
|
||||
{
|
||||
const scalar theta = mathematical::pi*(pointi+0.5)/nPoints;
|
||||
hemiPts[pointi] = vector(Foam::cos(theta), 0, Foam::sin(theta));
|
||||
}
|
||||
}
|
||||
|
||||
return themiPts;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::VF::raySearchEngine::raySearchEngine
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
mesh_(mesh),
|
||||
mapPtr_(nullptr),
|
||||
compactToGlobal_(),
|
||||
globalNumbering_(),
|
||||
patchGroup_(dict.getOrDefault<word>("patchGroup", "viewFactorWall")),
|
||||
patchIDs_(mesh_.boundaryMesh().indices(patchGroup_)),
|
||||
patchAreas_(mesh_.boundaryMesh().nNonProcessor(), Zero),
|
||||
agglomerate_(dict.get<bool>("agglomerate")),
|
||||
agglomMeshPtr_(nullptr),
|
||||
nFace_(-1),
|
||||
nCoarseFace_(-1),
|
||||
allCf_(UPstream::nProcs()),
|
||||
allSf_(UPstream::nProcs()),
|
||||
allAgg_(UPstream::nProcs())
|
||||
{
|
||||
Info<< "\nParticipating patches:" << endl;
|
||||
|
||||
forAll(patchIDs_, i)
|
||||
{
|
||||
const label patchi = patchIDs_[i];
|
||||
Info<< " " << i << ": " << mesh_.boundaryMesh()[patchi].name()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
const word agglomName(dict.getOrDefault<word>("agglom", "finalAgglom"));
|
||||
|
||||
IOobject agglomIO
|
||||
(
|
||||
agglomName,
|
||||
mesh_.facesInstance(),
|
||||
mesh_,
|
||||
IOobject::MUST_READ
|
||||
);
|
||||
|
||||
|
||||
if (agglomerate_)
|
||||
{
|
||||
// Sets allCf_, allSf_, allAgg_ based on coarse mesh
|
||||
// Sets nFace_, nCoarseFace_
|
||||
createAgglomeration(agglomIO);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check for presence of finalAgglom - will cause problems in later
|
||||
// calculations with viewFactor radiation model
|
||||
if (agglomIO.typeHeaderOk<labelListIOList>())
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Found agglomeration file: " << agglomIO.objectPath() << nl
|
||||
<< " This is inconsistent with the view factor calculation "
|
||||
<< "and should be removed" << nl << endl;
|
||||
}
|
||||
|
||||
// Sets allCf_, allSf_ based on fine mesh
|
||||
// Sets nFace_; nCoarseFace_ remains unset (-1)
|
||||
createGeometry();
|
||||
}
|
||||
|
||||
globalNumbering_ =
|
||||
nCoarseFace_ == -1 ? globalIndex(nFace_) : globalIndex(nCoarseFace_);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::VF::raySearchEngine::correct
|
||||
(
|
||||
labelListList& visibleFaceFaces
|
||||
) const
|
||||
{
|
||||
labelList rayStartFace;
|
||||
labelList rayEndFace;
|
||||
shootRays(rayStartFace, rayEndFace);
|
||||
|
||||
const label nFace = nParticipatingFaces();
|
||||
|
||||
// Calculate number of visible faces from each local start face
|
||||
labelList nVisibleFaceFaces(nFace, Zero);
|
||||
for (const label facei : rayStartFace)
|
||||
{
|
||||
++nVisibleFaceFaces[facei];
|
||||
}
|
||||
|
||||
check(nVisibleFaceFaces);
|
||||
|
||||
createParallelAddressing(rayEndFace);
|
||||
|
||||
// Set visible face-faces
|
||||
|
||||
// visibleFaceFaces has:
|
||||
// (local face, local viewed face) = compact viewed face
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
visibleFaceFaces.resize_nocopy(nFace);
|
||||
forAll(nVisibleFaceFaces, facei)
|
||||
{
|
||||
visibleFaceFaces[facei].resize_nocopy(nVisibleFaceFaces[facei]);
|
||||
}
|
||||
|
||||
nVisibleFaceFaces = 0;
|
||||
forAll(rayStartFace, i)
|
||||
{
|
||||
const label facei = rayStartFace[i];
|
||||
const label sloti = rayEndFace[i];
|
||||
visibleFaceFaces[facei][nVisibleFaceFaces[facei]++] = sloti;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Foam::VF::raySearchEngine::compactAddressing
|
||||
(
|
||||
const mapDistribute& map,
|
||||
pointField& compactCf,
|
||||
vectorField& compactSf,
|
||||
List<List<vector>>& compactFineSf,
|
||||
List<List<point>>& compactFineCf,
|
||||
DynamicList<List<point>>& compactPoints,
|
||||
DynamicList<label>& compactPatchId
|
||||
) const
|
||||
{
|
||||
compactCf.resize_nocopy(map.constructSize());
|
||||
compactSf.resize_nocopy(map.constructSize());
|
||||
compactFineSf.resize_nocopy(map.constructSize());
|
||||
compactFineCf.resize_nocopy(map.constructSize());
|
||||
compactPoints.setCapacity(map.constructSize());
|
||||
compactPatchId.setCapacity(map.constructSize());
|
||||
|
||||
// Insert my local values area and centre values
|
||||
if (agglomMeshPtr_)
|
||||
{
|
||||
SubList<vector>(compactSf, nCoarseFace_) = allSf_[Pstream::myProcNo()];
|
||||
SubList<point>(compactCf, nCoarseFace_) = allCf_[Pstream::myProcNo()];
|
||||
|
||||
const auto& coarseMesh = agglomMeshPtr_();
|
||||
const auto& coarsePatches = coarseMesh.boundaryMesh();
|
||||
const auto& coarseFaces = coarseMesh.faces();
|
||||
const auto& coarsePoints = coarseMesh.points();
|
||||
|
||||
const auto& finalAgglom = coarseMesh.patchFaceAgglomeration();
|
||||
|
||||
// Insert my fine local values per coarse face
|
||||
label sloti = 0;
|
||||
for (const label patchi : patchIDs_)
|
||||
{
|
||||
const auto& fineCfp = mesh_.Cf().boundaryField()[patchi];
|
||||
const auto& fineSfp = mesh_.Sf().boundaryField()[patchi];
|
||||
const labelList& agglom = finalAgglom[patchi];
|
||||
|
||||
if (agglom.empty()) continue;
|
||||
|
||||
const label nAgglom = max(agglom) + 1;
|
||||
const labelListList coarseToFine = invertOneToMany(nAgglom, agglom);
|
||||
const labelList& coarsePatchFace =
|
||||
coarseMesh.patchFaceMap()[patchi];
|
||||
|
||||
const label coarseStart = coarsePatches[patchi].start();
|
||||
|
||||
forAll(coarseToFine, coarsei)
|
||||
{
|
||||
compactPatchId.push_back(patchi);
|
||||
|
||||
const vectorField localPoints
|
||||
(
|
||||
coarsePoints,
|
||||
coarseFaces[coarseStart + coarsei]
|
||||
);
|
||||
compactPoints.push_back(localPoints);
|
||||
|
||||
const label coarseFacei = coarsePatchFace[coarsei];
|
||||
const labelList& fineFaces = coarseToFine[coarseFacei];
|
||||
|
||||
List<point>& fineCf = compactFineCf[sloti];
|
||||
fineCf.resize_nocopy(fineFaces.size());
|
||||
fineCf = UIndirectList<point>(fineCfp, fineFaces);
|
||||
|
||||
List<vector>& fineSf = compactFineSf[sloti];
|
||||
fineSf.resize_nocopy(fineFaces.size());
|
||||
fineSf = UIndirectList<vector>(fineSfp, fineFaces);
|
||||
|
||||
++sloti;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SubList<vector>(compactSf, nFace_) = allSf_[Pstream::myProcNo()];
|
||||
SubList<point>(compactCf, nFace_) = allCf_[Pstream::myProcNo()];
|
||||
|
||||
const auto& patches = mesh_.boundaryMesh();
|
||||
const faceList& faces = mesh_.faces();
|
||||
|
||||
label sloti = 0;
|
||||
|
||||
for (const label patchi : patchIDs_)
|
||||
{
|
||||
const auto& Sfp = mesh_.Sf().boundaryField()[patchi];
|
||||
const auto& Cfp = mesh_.Cf().boundaryField()[patchi];
|
||||
|
||||
const polyPatch& pp = patches[patchi];
|
||||
|
||||
forAll(pp, facei)
|
||||
{
|
||||
compactPatchId.push_back(patchi);
|
||||
|
||||
const auto& fpts = faces[facei + pp.start()];
|
||||
compactPoints.push_back(List<point>(mesh_.points(), fpts));
|
||||
|
||||
compactFineCf[sloti] = List<point>({Cfp[facei]});
|
||||
compactFineSf[sloti] = List<vector>({Sfp[facei]});
|
||||
++sloti;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Do all swapping
|
||||
map.distribute(compactSf);
|
||||
map.distribute(compactCf);
|
||||
map.distribute(compactFineCf);
|
||||
map.distribute(compactFineSf);
|
||||
map.distribute(compactPoints);
|
||||
map.distribute(compactPatchId);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,289 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2023-2024 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::VF::raySearchEngine
|
||||
|
||||
Description
|
||||
Base class for ray search engines
|
||||
|
||||
Participating patches must be in the \c viewFactorWall group, i.e. using the
|
||||
\c inGroups entry of the "\<case\>/polyMesh/boundary" file.
|
||||
|
||||
\verbatim
|
||||
myPatch
|
||||
{
|
||||
type wall;
|
||||
inGroups 2(wall viewFactorWall);
|
||||
...
|
||||
}
|
||||
\endverbatim
|
||||
|
||||
Face agglomeration can be employed, created using the \c faceAgglomerate
|
||||
utility. The file name to be read can be user-defined:
|
||||
|
||||
\verbatim
|
||||
// Name of agglomeration file; default = finalAgglom
|
||||
agglom finalAgglom;
|
||||
\endverbatim
|
||||
|
||||
SourceFiles
|
||||
raySearchEngine.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_vf_raySearchEngine_H
|
||||
#define Foam_vf_raySearchEngine_H
|
||||
|
||||
#include "cartesianCS.H"
|
||||
#include "mapDistribute.H"
|
||||
#include "singleCellFvMesh.H"
|
||||
#include "runTimeSelectionTables.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
namespace VF
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class raySearchEngine Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class raySearchEngine
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected Data
|
||||
|
||||
//- Reference to the mesh
|
||||
const fvMesh& mesh_;
|
||||
|
||||
//- Parallel map
|
||||
mutable autoPtr<mapDistribute> mapPtr_;
|
||||
|
||||
//- Compact to global addressing
|
||||
mutable labelList compactToGlobal_;
|
||||
|
||||
//- Global numbering
|
||||
globalIndex globalNumbering_;
|
||||
|
||||
//- Name of patch group to identify participating patches
|
||||
const word patchGroup_;
|
||||
|
||||
//- List of participating patch IDs
|
||||
labelList patchIDs_;
|
||||
|
||||
//- Patch areas
|
||||
scalarList patchAreas_;
|
||||
|
||||
//- Agglomeration flag
|
||||
bool agglomerate_;
|
||||
|
||||
//- Agglomerated mesh representation
|
||||
autoPtr<singleCellFvMesh> agglomMeshPtr_;
|
||||
|
||||
//- Number of original faces
|
||||
label nFace_;
|
||||
|
||||
//- Number of coarse faces
|
||||
label nCoarseFace_;
|
||||
|
||||
//- List of all face centres per processor
|
||||
List<pointField> allCf_;
|
||||
|
||||
//- List of all face areas per processor
|
||||
List<vectorField> allSf_;
|
||||
|
||||
//- List of all face agglomeration index per processor
|
||||
List<labelField> allAgg_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
static void check(const labelList& nVisibleFaceFaces);
|
||||
|
||||
static label closestPointIndex
|
||||
(
|
||||
const point& p0,
|
||||
const List<point>& pts
|
||||
);
|
||||
|
||||
//- Create patch geometry based on the original mesh
|
||||
void createGeometry();
|
||||
|
||||
//- Create parallel addressing - map, compact-to-global
|
||||
void createParallelAddressing(labelList& rayEndFace) const;
|
||||
|
||||
//- Create Cartesian co-ordinate system
|
||||
coordSystem::cartesian createCoordSystem
|
||||
(
|
||||
const point& origin,
|
||||
const vector& dir
|
||||
) const;
|
||||
|
||||
//- Create patch geometry based on the agglomerated mesh
|
||||
void createAgglomeration(const IOobject& io);
|
||||
|
||||
//- Create a set of points describing a hemisphere
|
||||
// Note: origin is (0 0 0)
|
||||
tmp<pointField> createHemiPoints(const label nRayPerFace) const;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
static const label maxDynListLength;
|
||||
|
||||
//- Run-time type information
|
||||
TypeName("raySearchEngine");
|
||||
|
||||
//- Selection table
|
||||
declareRunTimeSelectionTable
|
||||
(
|
||||
autoPtr,
|
||||
raySearchEngine,
|
||||
mesh,
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const dictionary& dict
|
||||
),
|
||||
(mesh, dict)
|
||||
);
|
||||
|
||||
//- Selector
|
||||
static autoPtr<raySearchEngine> New
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const dictionary& dict
|
||||
);
|
||||
|
||||
|
||||
// Generated Methods
|
||||
|
||||
//- No copy construct
|
||||
raySearchEngine(const raySearchEngine&) = delete;
|
||||
|
||||
//- No copy assignment
|
||||
void operator=(const raySearchEngine&) = delete;
|
||||
|
||||
|
||||
//- Constructor
|
||||
raySearchEngine(const fvMesh& mesh, const dictionary& dict);
|
||||
|
||||
//- Destructor
|
||||
virtual ~raySearchEngine() = default;
|
||||
|
||||
|
||||
// Public Member Functions
|
||||
|
||||
// Access
|
||||
|
||||
//- Reference to the mesh
|
||||
inline const fvMesh& mesh() const noexcept;
|
||||
|
||||
//- Parallel map
|
||||
inline const mapDistribute& map() const;
|
||||
|
||||
//- Compact to global addressing
|
||||
inline const labelList& compactToGlobal() const noexcept;
|
||||
|
||||
//- Global numbering
|
||||
inline const globalIndex& globalNumbering() const noexcept;
|
||||
|
||||
//- List of participating patch IDs
|
||||
inline const labelList& patchIDs() const noexcept;
|
||||
|
||||
//- Patch areas
|
||||
inline const scalarList& patchAreas() const noexcept;
|
||||
|
||||
//- Number of participating faces
|
||||
inline label nParticipatingFaces() const;
|
||||
|
||||
//- List of all face centres per processor
|
||||
inline const List<pointField>& allCf() const noexcept;
|
||||
|
||||
//- List of all face areas per processor
|
||||
inline const List<vectorField>& allSf() const noexcept;
|
||||
|
||||
//- List of all face agglomeration index per processor
|
||||
inline const List<labelField>& allAgg() const noexcept;
|
||||
|
||||
|
||||
// Main calculation functions
|
||||
|
||||
//- Shoot rays; returns lists of ray start and end faces
|
||||
virtual void shootRays
|
||||
(
|
||||
labelList& rayStartFaceOut,
|
||||
labelList& rayEndFaceOut
|
||||
) const = 0;
|
||||
|
||||
//- Correct
|
||||
virtual void correct(labelListList& visibleFaceFaces) const;
|
||||
|
||||
//- Create compact addressing
|
||||
void compactAddressing
|
||||
(
|
||||
const mapDistribute& map,
|
||||
pointField& compactCf,
|
||||
vectorField& compactSf,
|
||||
List<List<vector>>& compactFineSf,
|
||||
List<List<point>>& compactFineCf,
|
||||
DynamicList<List<point>>& compactPoints,
|
||||
DynamicList<label>& compactPatchId
|
||||
) const;
|
||||
|
||||
//- Interpolate field
|
||||
template<class Type>
|
||||
void interpolate
|
||||
(
|
||||
GeometricField<Type, fvPatchField, volMesh>& fld,
|
||||
const List<List<Type>>& values
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace VF
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#include "raySearchEngineI.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#ifdef NoRepository
|
||||
#include "raySearchEngineTemplates.C"
|
||||
#endif
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,101 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2023-2024 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
const Foam::fvMesh& Foam::VF::raySearchEngine::mesh() const noexcept
|
||||
{
|
||||
return mesh_;
|
||||
}
|
||||
|
||||
|
||||
const Foam::mapDistribute& Foam::VF::raySearchEngine::map() const
|
||||
{
|
||||
if (!mapPtr_)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "mapDistribute has not been set"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
return mapPtr_;
|
||||
}
|
||||
|
||||
|
||||
const Foam::labelList&
|
||||
Foam::VF::raySearchEngine::compactToGlobal() const noexcept
|
||||
{
|
||||
return compactToGlobal_;
|
||||
}
|
||||
|
||||
|
||||
const Foam::globalIndex&
|
||||
Foam::VF::raySearchEngine::globalNumbering() const noexcept
|
||||
{
|
||||
return globalNumbering_;
|
||||
}
|
||||
|
||||
|
||||
const Foam::labelList& Foam::VF::raySearchEngine::patchIDs() const noexcept
|
||||
{
|
||||
return patchIDs_;
|
||||
}
|
||||
|
||||
|
||||
const Foam::scalarList& Foam::VF::raySearchEngine::patchAreas() const noexcept
|
||||
{
|
||||
return patchAreas_;
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::VF::raySearchEngine::nParticipatingFaces() const
|
||||
{
|
||||
if (nCoarseFace_ == -1) return nFace_;
|
||||
return nCoarseFace_;
|
||||
}
|
||||
|
||||
|
||||
const Foam::List<Foam::pointField>&
|
||||
Foam::VF::raySearchEngine::allCf() const noexcept
|
||||
{
|
||||
return allCf_;
|
||||
}
|
||||
|
||||
|
||||
const Foam::List<Foam::vectorField>&
|
||||
Foam::VF::raySearchEngine::allSf() const noexcept
|
||||
{
|
||||
return allSf_;
|
||||
}
|
||||
|
||||
|
||||
const Foam::List<Foam::labelField>&
|
||||
Foam::VF::raySearchEngine::allAgg() const noexcept
|
||||
{
|
||||
return allAgg_;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,59 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2023-2024 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "raySearchEngine.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::autoPtr<Foam::VF::raySearchEngine> Foam::VF::raySearchEngine::New
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const dictionary& dict
|
||||
)
|
||||
{
|
||||
const word modelType(dict.get<word>("raySearchEngine"));
|
||||
|
||||
Info<< "Selecting " << typeName << ": " << modelType << endl;
|
||||
|
||||
auto* ctorPtr = meshConstructorTable(modelType);
|
||||
|
||||
if (!ctorPtr)
|
||||
{
|
||||
FatalIOErrorInLookup
|
||||
(
|
||||
dict,
|
||||
typeName,
|
||||
modelType,
|
||||
*meshConstructorTablePtr_
|
||||
) << exit(FatalIOError);
|
||||
}
|
||||
|
||||
return autoPtr<raySearchEngine>(ctorPtr(mesh, dict));
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,86 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2023-2024 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
template<class Type>
|
||||
void Foam::VF::raySearchEngine::interpolate
|
||||
(
|
||||
GeometricField<Type, fvPatchField, volMesh>& fld,
|
||||
const List<List<Type>>& values
|
||||
) const
|
||||
{
|
||||
label compacti = 0;
|
||||
|
||||
auto& vfbf = fld.boundaryFieldRef();
|
||||
|
||||
if (agglomMeshPtr_)
|
||||
{
|
||||
const auto& coarseMesh = agglomMeshPtr_();
|
||||
const auto& finalAgglom = coarseMesh.patchFaceAgglomeration();
|
||||
|
||||
for (const label patchi : patchIDs_)
|
||||
{
|
||||
const labelList& agglom = finalAgglom[patchi];
|
||||
|
||||
if (agglom.empty()) continue;
|
||||
|
||||
label nAgglom = max(agglom) + 1;
|
||||
const labelListList coarseToFine(invertOneToMany(nAgglom, agglom));
|
||||
const labelList& coarsePatchFace =
|
||||
coarseMesh.patchFaceMap()[patchi];
|
||||
|
||||
forAll(coarseToFine, i)
|
||||
{
|
||||
const label coarseFacei = coarsePatchFace[i];
|
||||
const labelList& fineFaces = coarseToFine[coarseFacei];
|
||||
const Type sumValues = sum(values[compacti]);
|
||||
|
||||
for (const label fineFacei : fineFaces)
|
||||
{
|
||||
vfbf[patchi][fineFacei] = sumValues;
|
||||
}
|
||||
|
||||
++compacti;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
label compacti = 0;
|
||||
for (const label patchi : patchIDs_)
|
||||
{
|
||||
auto& vfp = vfbf[patchi];
|
||||
|
||||
for (Type& vfi : vfp)
|
||||
{
|
||||
vfi = sum(values[compacti++]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,948 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2023-2024 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "voxelRaySearchEngine.H"
|
||||
#include "processorPolyPatch.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace VF
|
||||
{
|
||||
defineTypeNameAndDebug(voxel, 0);
|
||||
addToRunTimeSelectionTable(raySearchEngine, voxel, mesh);
|
||||
}
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::VF::voxel::setTriangulation(const fvMesh& mesh)
|
||||
{
|
||||
Info<< "\nCreating triangulated surface" << endl;
|
||||
|
||||
// Storage for surfaceMesh. Size estimate.
|
||||
DynamicList<labelledTri> triangles(mesh.nBoundaryFaces());
|
||||
DynamicList<label> globalFaces(mesh.nBoundaryFaces());
|
||||
label nFace = 0;
|
||||
|
||||
const auto& pbm = mesh.boundaryMesh();
|
||||
|
||||
forAll(patchIDs_, i)
|
||||
{
|
||||
const label patchi = patchIDs_[i];
|
||||
const polyPatch& patch = pbm[patchi];
|
||||
const pointField& points = patch.points();
|
||||
|
||||
for (const face& f : patch)
|
||||
{
|
||||
label nTri = 0;
|
||||
faceList triFaces(f.nTriangles(points));
|
||||
f.triangles(points, nTri, triFaces);
|
||||
|
||||
const label globalFacei =
|
||||
globalNumbering_.toGlobal(Pstream::myProcNo(), nFace++);
|
||||
|
||||
for (const face& f : triFaces)
|
||||
{
|
||||
triangles.push_back(labelledTri(f[0], f[1], f[2], i));
|
||||
globalFaces.push_back(globalFacei);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
triToGlobalFace_.transfer(globalFaces);
|
||||
|
||||
Info<< " Total number of triangles: "
|
||||
<< returnReduce(triangles.size(), sumOp<label>())
|
||||
<< endl;
|
||||
|
||||
triangles.shrink();
|
||||
surface_ = triSurface(triangles, mesh.points());
|
||||
surface_.compactPoints();
|
||||
}
|
||||
|
||||
|
||||
Foam::labelList Foam::VF::voxel::setFaceVertexHits
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const labelList& patchIDs
|
||||
)
|
||||
{
|
||||
labelList vertHits(mesh.points().size(), Zero);
|
||||
|
||||
if (mesh.nSolutionD() == 3)
|
||||
{
|
||||
const auto& pbm = mesh.boundaryMesh();
|
||||
|
||||
// Create a new triangulation based on the surface agglomeration
|
||||
for (const label patchI : patchIDs)
|
||||
{
|
||||
const polyPatch& patch = pbm[patchI];
|
||||
for (const face& f : patch)
|
||||
{
|
||||
for (const label fpi : f)
|
||||
{
|
||||
++vertHits[fpi];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& pp : pbm)
|
||||
{
|
||||
const labelList& meshPts = pp.meshPoints();
|
||||
|
||||
if (pp.size())
|
||||
{
|
||||
if (isA<processorPolyPatch>(pp))
|
||||
{
|
||||
// Add all processor patch points
|
||||
for (const label pi : meshPts)
|
||||
{
|
||||
++vertHits[pi];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add boundary points
|
||||
|
||||
const auto& bndyPts = pp.boundaryPoints();
|
||||
|
||||
for (const label pi : bndyPts)
|
||||
{
|
||||
++vertHits[meshPts[pi]];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return vertHits;
|
||||
}
|
||||
|
||||
|
||||
void Foam::VF::voxel::setCoarseTriangulation(const fvMesh& mesh)
|
||||
{
|
||||
Info<< "\nCreating triangulated surface" << endl;
|
||||
|
||||
|
||||
// Filter out fine mesh points along coarse mesh faces
|
||||
|
||||
|
||||
// Storage for surfaceMesh. Size estimate.
|
||||
DynamicList<labelledTri> triangles(mesh.nBoundaryFaces());
|
||||
DynamicList<label> globalFaces(mesh.nBoundaryFaces());
|
||||
labelList vertHits = setFaceVertexHits(mesh, patchIDs_);
|
||||
|
||||
|
||||
// Only simplifying edges for 3D
|
||||
const label nVertMin = mesh.nSolutionD() == 3 ? 2 : 0;
|
||||
|
||||
label nInvalid = 0;
|
||||
label nFace = 0;
|
||||
|
||||
const auto& pbm = mesh.boundaryMesh();
|
||||
|
||||
for (const label patchi : patchIDs_)
|
||||
{
|
||||
const polyPatch& patch = pbm[patchi];
|
||||
const pointField& points = patch.points();
|
||||
|
||||
for (const face& f : patch)
|
||||
{
|
||||
DynamicList<label> faceVerts;
|
||||
for (const label fpi : f)
|
||||
{
|
||||
if (vertHits[fpi] > nVertMin)
|
||||
{
|
||||
faceVerts.push_back(fpi);
|
||||
}
|
||||
}
|
||||
|
||||
if (faceVerts.size() < 3)
|
||||
{
|
||||
++nInvalid;
|
||||
continue;
|
||||
}
|
||||
|
||||
label nTri = 0;
|
||||
const face reducedFace(faceVerts);
|
||||
faceList triFaces(reducedFace.nTriangles(points));
|
||||
reducedFace.triangles(points, nTri, triFaces);
|
||||
|
||||
const label globalFacei =
|
||||
globalNumbering_.toGlobal(Pstream::myProcNo(), nFace++);
|
||||
|
||||
for (const face& f : triFaces)
|
||||
{
|
||||
triangles.push_back(labelledTri(f[0], f[1], f[2], patchi));
|
||||
globalFaces.push_back(globalFacei);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
triToGlobalFace_.transfer(globalFaces);
|
||||
|
||||
Info<< " Total number of triangles: "
|
||||
<< returnReduce(triangles.size(), sumOp<label>())
|
||||
<< "\n Number of invalid (removed) triangles: "
|
||||
<< returnReduce(nInvalid, sumOp<label>())
|
||||
<< endl;
|
||||
|
||||
triangles.shrink();
|
||||
surface_ = triSurface(triangles, mesh.points());
|
||||
surface_.compactPoints();
|
||||
}
|
||||
|
||||
|
||||
void Foam::VF::voxel::broadcast()
|
||||
{
|
||||
// Every processor has whole surface
|
||||
const globalIndex globalFaceIdx(globalIndex::gatherOnly{}, surface_.size());
|
||||
const globalIndex globalPointIdx
|
||||
(
|
||||
globalIndex::gatherOnly{},
|
||||
surface_.points().size()
|
||||
);
|
||||
|
||||
List<labelledTri> globalSurfaceTris(globalFaceIdx.gather(surface_));
|
||||
pointField globalSurfacePoints(globalPointIdx.gather(surface_.points()));
|
||||
List<label> globalTriToGlobalFace(globalFaceIdx.gather(triToGlobalFace_));
|
||||
|
||||
|
||||
for (const label proci : globalPointIdx.allProcs())
|
||||
{
|
||||
const label offset = globalPointIdx.localStart(proci);
|
||||
|
||||
if (offset)
|
||||
{
|
||||
for
|
||||
(
|
||||
labelledTri& tri
|
||||
: globalSurfaceTris.slice(globalFaceIdx.range(proci))
|
||||
)
|
||||
{
|
||||
tri[0] += offset;
|
||||
tri[1] += offset;
|
||||
tri[2] += offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
surface_ =
|
||||
triSurface
|
||||
(
|
||||
std::move(globalSurfaceTris),
|
||||
std::move(globalSurfacePoints)
|
||||
);
|
||||
|
||||
Pstream::broadcast(surface_);
|
||||
|
||||
triToGlobalFace_ = std::move(globalTriToGlobalFace);
|
||||
Pstream::broadcast(triToGlobalFace_);
|
||||
}
|
||||
|
||||
|
||||
Foam::pointHit Foam::VF::voxel::rayTriIntersect
|
||||
(
|
||||
const label trii,
|
||||
const point& origin,
|
||||
const vector& direction
|
||||
) const
|
||||
{
|
||||
// Note: origin was made relative to voxel mesh on entry to hit function
|
||||
// - need to convert back into global position to be consistent with
|
||||
// triangles for intersection tests
|
||||
|
||||
const auto& ind = surface_[trii];
|
||||
const auto& pts = surface_.points();
|
||||
|
||||
// Note: flipped orientation of triangle (into domain) so that we can use
|
||||
// visibility check when performing ray-triangle intersections
|
||||
const triPointRef tri(pts[ind[0]], pts[ind[2]], pts[ind[1]]);
|
||||
|
||||
static scalar tolerance = 1e-6;
|
||||
|
||||
return
|
||||
tri.intersection
|
||||
(
|
||||
globalPosition(origin),
|
||||
direction,
|
||||
intersection::VISIBLE,
|
||||
tolerance
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
void Foam::VF::voxel::writeBox
|
||||
(
|
||||
OBJstream& os,
|
||||
bool lines,
|
||||
const boundBox& bb
|
||||
) const
|
||||
{
|
||||
os.write(treeBoundBox(bb), lines);
|
||||
}
|
||||
|
||||
|
||||
void Foam::VF::voxel::writeVoxels(const word& fName) const
|
||||
{
|
||||
if (!UPstream::master()) return;
|
||||
|
||||
OBJstream os(fName);
|
||||
Info<< "Writing voxels to " << os.name() << endl;
|
||||
|
||||
boundBox bb;
|
||||
const bool lines = true;
|
||||
for (label i = 0; i < nijk_[0]; ++i)
|
||||
{
|
||||
for (label j = 0; j < nijk_[1]; ++j)
|
||||
{
|
||||
for (label k = 0; k < nijk_[2]; ++k)
|
||||
{
|
||||
bb.min() = voxelMin(i, j, k);
|
||||
bb.max() = voxelMax(i, j, k);
|
||||
writeBox(os, lines, bb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Info<< "- done" << endl;
|
||||
}
|
||||
|
||||
|
||||
void Foam::VF::voxel::writeTriBoundBoxes(const word& fName) const
|
||||
{
|
||||
if (!UPstream::master()) return;
|
||||
|
||||
OBJstream os(fName);
|
||||
Info<< "Writing triangle boundBoxes to " << os.name() << endl;
|
||||
|
||||
const bool lines = true;
|
||||
for (const auto& voxeli : objects_)
|
||||
{
|
||||
for (const label trii : voxeli)
|
||||
{
|
||||
writeBox(os, lines, objectBbs_[trii]);
|
||||
}
|
||||
}
|
||||
|
||||
Info<< "- done" << endl;
|
||||
}
|
||||
|
||||
|
||||
void Foam::VF::voxel::writeHitObjects
|
||||
(
|
||||
const label voxeli,
|
||||
const point& origin,
|
||||
const vector& dir
|
||||
) const
|
||||
{
|
||||
OBJstream os("voxel_" + Foam::name(voxeli) + ".obj");
|
||||
|
||||
// Write voxel
|
||||
labelVector ijk = this->ijk(voxeli);
|
||||
|
||||
boundBox voxelBb;
|
||||
voxelBb.min() = voxelMin(ijk[0], ijk[1], ijk[2]);
|
||||
voxelBb.max() = voxelMax(ijk[0], ijk[1], ijk[2]);
|
||||
|
||||
writeBox(os, true, voxelBb);
|
||||
|
||||
for (const auto& trii : objects_[voxeli])
|
||||
{
|
||||
writeBox(os, true, objectBbs_[trii]);
|
||||
|
||||
const auto& ind = surface_[trii];
|
||||
const auto& pts = surface_.points();
|
||||
const triPointRef tri(pts[ind[0]], pts[ind[1]], pts[ind[2]]);
|
||||
os.write(tri, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::pointIndexHit Foam::VF::voxel::hitObject
|
||||
(
|
||||
const label voxeli,
|
||||
const point& origin,
|
||||
const vector& dir,
|
||||
const vector& t,
|
||||
const scalar minDistance
|
||||
) const
|
||||
{
|
||||
if (objects_[voxeli].empty()) return pointIndexHit();
|
||||
|
||||
// boundBox rayBb;
|
||||
// rayBb.add(origin);
|
||||
// rayBb.add(origin + dir*(dir & t));
|
||||
|
||||
label triHiti = -1;
|
||||
//rayBb.add(origin + dir);
|
||||
//rayBb.inflate(0.01);
|
||||
|
||||
if (debug > 2)
|
||||
{
|
||||
writeHitObjects(voxeli, origin, dir);
|
||||
}
|
||||
|
||||
// Determine all triangles that intersect with ray
|
||||
// - only keep nearest hit
|
||||
|
||||
pointHit closestHit;
|
||||
for (const auto& trii : objects_[voxeli])
|
||||
{
|
||||
// Only perform ray/tri intersection if bound boxes intersect
|
||||
//if (objectBbs_[trii].overlaps(rayBb))
|
||||
{
|
||||
pointHit pi = rayTriIntersect(trii, origin, dir);
|
||||
|
||||
if
|
||||
(
|
||||
pi.hit()
|
||||
&& (
|
||||
pi.distance() > minDistance
|
||||
&& pi.distance() < closestHit.distance()
|
||||
)
|
||||
)
|
||||
{
|
||||
triHiti = trii;
|
||||
closestHit = pi;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return pointIndexHit(closestHit, triHiti);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::VF::voxel::voxel(const fvMesh& mesh, const dictionary& dict)
|
||||
:
|
||||
raySearchEngine(mesh, dict),
|
||||
bb0_(),
|
||||
span0_(Zero),
|
||||
nijk_(Zero),
|
||||
dxyz_(Zero),
|
||||
nRayPerFace_(dict.get<label>("nRayPerFace")),
|
||||
nTriPerVoxelMax_(dict.getOrDefault<label>("nTriPerVoxelMax", 50)),
|
||||
depthMax_(dict.getOrDefault<label>("depthMax", 5)),
|
||||
objects_(),
|
||||
objectBbs_()
|
||||
{
|
||||
if (agglomMeshPtr_)
|
||||
{
|
||||
setCoarseTriangulation(*agglomMeshPtr_);
|
||||
}
|
||||
else
|
||||
{
|
||||
setTriangulation(mesh);
|
||||
}
|
||||
|
||||
broadcast();
|
||||
|
||||
objectBbs_.resize_nocopy(surface_.size());
|
||||
|
||||
bb0_.add(surface_.points());
|
||||
bb0_.inflate(0.01);
|
||||
span0_ = bb0_.span();
|
||||
|
||||
{
|
||||
scalar maxDx = span0_.x();
|
||||
scalar maxDy = span0_.y();
|
||||
scalar maxDz = span0_.z();
|
||||
|
||||
const label refDn = 8;
|
||||
scalar maxDim = max(maxDx, max(maxDy, maxDz));
|
||||
|
||||
setVoxelDims
|
||||
(
|
||||
refDn*maxDx/maxDim,
|
||||
refDn*maxDy/maxDim,
|
||||
refDn*maxDz/maxDim
|
||||
);
|
||||
|
||||
objects_.resize_nocopy(nVoxel());
|
||||
}
|
||||
|
||||
label depth = 0;
|
||||
label trii = 0;
|
||||
voxelise(objects_, trii, depth);
|
||||
|
||||
Info<< "\nCreated voxel mesh: " << nijk_ << endl;
|
||||
|
||||
if ((debug > 3) && UPstream::master())
|
||||
{
|
||||
writeVoxels("voxels.obj");
|
||||
writeTriBoundBoxes("triBoundBoxes.obj");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::VF::voxel::refineObjects
|
||||
(
|
||||
List<DynamicList<label>>& objects,
|
||||
const label triMax
|
||||
)
|
||||
{
|
||||
refineVoxelDims();
|
||||
|
||||
if (debug > 2) Pout<< "Refining voxels: n=" << nijk_ << endl;
|
||||
|
||||
List<DynamicList<label>> objectsNew(objects.size()*8);
|
||||
|
||||
for (label trii = 0; trii <= triMax; ++trii)
|
||||
{
|
||||
addBbToVoxels(objectBbs_[trii], trii, objectsNew);
|
||||
}
|
||||
|
||||
objects.transfer(objectsNew);
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::VF::voxel::addBbToVoxels
|
||||
(
|
||||
const boundBox& bb,
|
||||
const label trii,
|
||||
List<DynamicList<label>>& objects
|
||||
) const
|
||||
{
|
||||
//Pout<< "addBbToVoxels: trii=" << trii << " n=" << nijk_ << endl;
|
||||
|
||||
const point minbb(localPosition(bb.min()));
|
||||
const label i0 = max(0, floor(minbb.x()/dxyz_[0]));
|
||||
const label j0 = max(0, floor(minbb.y()/dxyz_[1]));
|
||||
const label k0 = max(0, floor(minbb.z()/dxyz_[2]));
|
||||
|
||||
const point maxbb(localPosition(bb.max()));
|
||||
const label i1 = min(nijk_[0], ceil(maxbb.x()/dxyz_[0]));
|
||||
const label j1 = min(nijk_[1], ceil(maxbb.y()/dxyz_[1]));
|
||||
const label k1 = min(nijk_[2], ceil(maxbb.z()/dxyz_[2]));
|
||||
|
||||
label nTriMax = 0;
|
||||
|
||||
for (label ii = i0; ii < i1; ++ii)
|
||||
{
|
||||
for (label jj = j0; jj < j1; ++jj)
|
||||
{
|
||||
for (label kk = k0; kk < k1; ++kk)
|
||||
{
|
||||
const label voxeli = this->voxeli(ii, jj, kk);
|
||||
|
||||
objects[voxeli].push_back(trii);
|
||||
nTriMax = max(nTriMax, objects[voxeli].size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nTriMax;
|
||||
}
|
||||
|
||||
|
||||
void Foam::VF::voxel::voxelise
|
||||
(
|
||||
List<DynamicList<label>>& objects,
|
||||
const label trii0,
|
||||
const label depth
|
||||
)
|
||||
{
|
||||
if (debug > 2)
|
||||
{
|
||||
Pout<< "voxelise - start at tri=" << trii0
|
||||
<< " depth=" << depth
|
||||
<< endl;
|
||||
}
|
||||
|
||||
const auto& points = surface_.points();
|
||||
|
||||
for (label trii = trii0; trii < surface_.size(); ++trii)
|
||||
{
|
||||
// Triangle bounding box
|
||||
boundBox bb(points, surface_[trii]);
|
||||
bb.inflate(0.01);
|
||||
objectBbs_[trii] = bb;
|
||||
|
||||
const label nVoxelMax = addBbToVoxels(bb, trii, objects);
|
||||
|
||||
// Number of triangles per voxel - if exceed limit, refine voxels...
|
||||
if (nVoxelMax > nTriPerVoxelMax_ && depth < depthMax_)
|
||||
{
|
||||
refineObjects(objects, trii);
|
||||
voxelise(objects, trii + 1, depth + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::pointIndexHit Foam::VF::voxel::hit
|
||||
(
|
||||
const label tri0,
|
||||
const vector& direction0
|
||||
) const
|
||||
{
|
||||
if (tri0 > surface_.size()-1)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Index tri0 out of bounds: " << tri0
|
||||
<< ". Surface size: " << surface_.size()
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
return hit(surface_.faceCentres()[tri0], direction0);
|
||||
}
|
||||
|
||||
|
||||
Foam::pointIndexHit Foam::VF::voxel::hit
|
||||
(
|
||||
const point& origin0,
|
||||
const vector& direction0
|
||||
) const
|
||||
{
|
||||
// Initialise return value
|
||||
pointIndexHit hitInfo;
|
||||
|
||||
const point origin(localPosition(origin0));
|
||||
|
||||
if (cmptMin(origin) < 0)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Point located outside voxel mesh"
|
||||
<< " - possible coarsening problem?"
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
if (magSqr(direction0) < ROOTVSMALL)
|
||||
{
|
||||
WarningInFunction
|
||||
<< "Supplied direction has zero size"
|
||||
<< endl;
|
||||
|
||||
return hitInfo;
|
||||
}
|
||||
|
||||
const vector dir(normalised(direction0));
|
||||
|
||||
labelVector ijk(Zero);
|
||||
labelVector step(Zero);
|
||||
vector tDelta(vector::max);
|
||||
vector tMax(vector::max);
|
||||
|
||||
for (direction d = 0; d < 3; ++d)
|
||||
{
|
||||
ijk[d] = floor(origin[d]/dxyz_[d]);
|
||||
step[d] = sign0(dir[d]);
|
||||
if (step[d] != 0)
|
||||
{
|
||||
tDelta[d] = mag(dxyz_[d]/dir[d]);
|
||||
|
||||
scalar voxelMax = (1 + ijk[d] - neg(dir[d]))*dxyz_[d];
|
||||
tMax[d] = (voxelMax - origin[d])/dir[d];
|
||||
}
|
||||
}
|
||||
|
||||
if (debug > 2)
|
||||
{
|
||||
Info<< "surfBb:" << boundBox(surface_.points())
|
||||
<< " bb:" << bb0_
|
||||
<< " origin" << origin0
|
||||
<< " voxel_origin:" << origin
|
||||
<< " ijk:" << ijk
|
||||
<< " step:" << step
|
||||
<< " dxyz:" << dxyz_
|
||||
<< " tDelta:" << tDelta
|
||||
<< " tMax:" << tMax
|
||||
<< endl;
|
||||
}
|
||||
|
||||
auto traverse = [&](const label i)
|
||||
{
|
||||
ijk[i] += step[i];
|
||||
if (outOfBounds(ijk, i)) return false;
|
||||
tMax[i] += tDelta[i];
|
||||
return true;
|
||||
};
|
||||
|
||||
|
||||
while (true)
|
||||
{
|
||||
const label voxeli = this->voxeli(ijk);
|
||||
|
||||
if (debug > 2)
|
||||
{
|
||||
Info<< "ijk:" << ijk
|
||||
<< " voxeli:" << voxeli
|
||||
<< " t:" << tMax
|
||||
<< " objs:" << objects_[voxeli].size()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
hitInfo = hitObject(voxeli, origin, dir, tMax);
|
||||
|
||||
if (hitInfo.hit())
|
||||
{
|
||||
// Valid hit
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (tMax[0] < tMax[1] && tMax[0] < tMax[2])
|
||||
{
|
||||
if (!traverse(0)) break;
|
||||
}
|
||||
else if (tMax[1] < tMax[2])
|
||||
{
|
||||
if (!traverse(1)) break;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!traverse(2)) break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return hitInfo;
|
||||
}
|
||||
|
||||
|
||||
void Foam::VF::voxel::shootRays
|
||||
(
|
||||
labelList& rayStartFaceOut,
|
||||
labelList& rayEndFaceOut
|
||||
) const
|
||||
{
|
||||
(void)mesh_.time().cpuTimeIncrement();
|
||||
|
||||
const pointField& myFc = allCf_[Pstream::myProcNo()];
|
||||
const vectorField& myArea = allSf_[Pstream::myProcNo()];
|
||||
|
||||
const label nTotalRays = myFc.size()*nRayPerFace_;
|
||||
if (nTotalRays > maxDynListLength)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Dynamic list needs more capacity to support " << nRayPerFace_
|
||||
<< " rays per face (" << nTotalRays << "). "
|
||||
<< "Limit set by maxDynListLength: " << maxDynListLength
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
DynamicList<label> rayStartFace(nTotalRays);
|
||||
DynamicList<label> rayEndFace(rayStartFace.size());
|
||||
|
||||
DynamicList<label> endFacei(nTotalRays);
|
||||
DynamicList<label> startFacei(nTotalRays);
|
||||
|
||||
const pointField hemi(createHemiPoints(nRayPerFace_));
|
||||
|
||||
Info<< "\nShooting rays" << endl;
|
||||
|
||||
const scalar nDiv = 10;
|
||||
const label nStep = floor(myFc.size()/nDiv);
|
||||
labelHashSet localFaceHits;
|
||||
|
||||
for (label stepi=0; stepi<nDiv; ++stepi)
|
||||
{
|
||||
const label step0 = stepi*nStep;
|
||||
const label step1 = stepi == nDiv - 1 ? myFc.size() : (stepi+1)*nStep;
|
||||
|
||||
for (label i = step0; i < step1; ++i)
|
||||
{
|
||||
// Info<< "i/N = " << i << "/" << (myFc.size()-1)
|
||||
// << " step0:" << step0 << " step1:" << step1
|
||||
// << endl;
|
||||
|
||||
localFaceHits.clear();
|
||||
|
||||
const point& origin = myFc[i];
|
||||
const vector dir(-normalised(myArea[i]));
|
||||
|
||||
const coordSystem::cartesian cs = createCoordSystem(origin, dir);
|
||||
|
||||
const vectorField pts(cs.transformPoint(hemi));
|
||||
|
||||
for (const auto& p : pts)
|
||||
{
|
||||
const pointIndexHit hitInfo = hit(origin, p-origin);
|
||||
|
||||
if (hitInfo.hit())
|
||||
{
|
||||
label hitFacei = triToGlobalFace_[hitInfo.index()];
|
||||
|
||||
if (localFaceHits.insert(hitFacei))
|
||||
{
|
||||
endFacei.push_back(hitFacei);
|
||||
startFacei.push_back(i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Miss
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const label globalStepi = returnReduce(stepi, minOp<label>()) + 1;
|
||||
|
||||
Info<< " " << globalStepi/nDiv*100 << "% complete" << endl;
|
||||
}
|
||||
|
||||
|
||||
// Ensure all rays are unique/filter out duplicates
|
||||
// - add symmetric connections for non-self-intersecting rays
|
||||
|
||||
if (UPstream::parRun())
|
||||
{
|
||||
edgeHashSet uniqueRays;
|
||||
List<DynamicList<label>> remoteStartFace(Pstream::nProcs());
|
||||
List<DynamicList<label>> remoteEndFace(Pstream::nProcs());
|
||||
|
||||
const labelList globalStartFaceIDs
|
||||
(
|
||||
globalNumbering_.toGlobal(startFacei)
|
||||
);
|
||||
|
||||
forAll(globalStartFaceIDs, rayi)
|
||||
{
|
||||
label start = globalStartFaceIDs[rayi];
|
||||
label end = endFacei[rayi];
|
||||
|
||||
const label endProci = globalNumbering_.whichProcID(end);
|
||||
|
||||
if (start > end) Swap(start, end);
|
||||
|
||||
if (uniqueRays.insert(edge(start, end)))
|
||||
{
|
||||
if (endProci != UPstream::myProcNo())
|
||||
{
|
||||
// Convert local face into global face and vice-versa
|
||||
remoteStartFace[endProci].push_back(start);
|
||||
remoteEndFace[endProci].push_back(end);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PstreamBuffers pBufs(Pstream::commsTypes::nonBlocking);
|
||||
|
||||
// Send remote data
|
||||
for (const int domain : Pstream::allProcs())
|
||||
{
|
||||
if (domain != Pstream::myProcNo())
|
||||
{
|
||||
UOPstream str(domain, pBufs);
|
||||
str << remoteStartFace[domain]
|
||||
<< remoteEndFace[domain];
|
||||
}
|
||||
}
|
||||
|
||||
pBufs.finishedSends();
|
||||
|
||||
// Consume
|
||||
for (const int domain : Pstream::allProcs())
|
||||
{
|
||||
if (domain != Pstream::myProcNo())
|
||||
{
|
||||
UIPstream is(domain, pBufs);
|
||||
is >> remoteStartFace[domain]
|
||||
>> remoteEndFace[domain];
|
||||
|
||||
forAll(remoteStartFace[domain], i)
|
||||
{
|
||||
const label start = remoteStartFace[domain][i];
|
||||
const label end = remoteEndFace[domain][i];
|
||||
uniqueRays.insert(edge(start, end));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Populate ray addressing based on uniqueRays
|
||||
for (const edge& e : uniqueRays)
|
||||
{
|
||||
const label start = e.first();
|
||||
const label end = e.second();
|
||||
|
||||
bool sameFace = start == end;
|
||||
|
||||
if (globalNumbering_.isLocal(start))
|
||||
{
|
||||
// Ray originates from this processor
|
||||
const label localStart = globalNumbering_.toLocal(start);
|
||||
|
||||
rayStartFace.append(localStart);
|
||||
rayEndFace.append(end);
|
||||
}
|
||||
|
||||
if (!sameFace && globalNumbering_.isLocal(end))
|
||||
{
|
||||
// Ray hits this processor
|
||||
// - add symmetric ray from end->start
|
||||
const label localEnd = globalNumbering_.toLocal(end);
|
||||
|
||||
rayStartFace.append(localEnd);
|
||||
rayEndFace.append(start);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Populate ray addressing based on uniqueRays
|
||||
|
||||
edgeHashSet uniqueRays;
|
||||
|
||||
forAll(startFacei, rayi)
|
||||
{
|
||||
label start = startFacei[rayi];
|
||||
label end = endFacei[rayi];
|
||||
|
||||
if (start > end) Swap(start, end);
|
||||
|
||||
if (uniqueRays.insert(edge(start, end)))
|
||||
{
|
||||
rayStartFace.append(start);
|
||||
rayEndFace.append(end);
|
||||
|
||||
if (start != end)
|
||||
{
|
||||
// Add symmetric ray from end->start
|
||||
rayStartFace.append(end);
|
||||
rayEndFace.append(start);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rayStartFaceOut.transfer(rayStartFace);
|
||||
rayEndFaceOut.transfer(rayEndFace);
|
||||
|
||||
Info<< " Time taken: " << mesh_.time().cpuTimeIncrement() << " s"
|
||||
<< endl;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,284 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2023-2024 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::VF::voxel
|
||||
|
||||
Description
|
||||
Ray search engine based on discretising space into uniform voxels
|
||||
|
||||
Voxels are refined using 2x2x2 refinement.
|
||||
|
||||
The number of rays per face is supplied by the user, whereby rays are
|
||||
issued uniformly across a hemisphere.
|
||||
|
||||
Usage
|
||||
Minimal example by using \c <constant>/viewFactorsDict:
|
||||
\verbatim
|
||||
// Mandatory entries
|
||||
nRayPerFace <label>;
|
||||
|
||||
// Optional entries
|
||||
nTriPerVoxelMax <label>;
|
||||
depthMax <label>;
|
||||
|
||||
// Inherited entries
|
||||
...
|
||||
\endverbatim
|
||||
|
||||
where the entries mean:
|
||||
\table
|
||||
Property | Description | Type | Reqd | Deflt
|
||||
nRayPerFace | Number of rays issued per face | label | yes | -
|
||||
nRayPerFace | Target number of triangles per voxel | label | no | 50
|
||||
depthMax | Maximum voxel refinement depth | label | no | 5
|
||||
\endtable
|
||||
|
||||
The inherited entries are elaborated in:
|
||||
- \link raySearchEngine.H \endlink
|
||||
|
||||
SourceFiles
|
||||
voxelRaySearchEngine.C
|
||||
|
||||
SeeAlso
|
||||
- Foam::VF::raySearchEngine
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_vf_voxelRaySearchEngine_H
|
||||
#define Foam_vf_voxelRaySearchEngine_H
|
||||
|
||||
#include "raySearchEngine.H"
|
||||
#include "labelVector.H"
|
||||
#include "OBJstream.H"
|
||||
#include "pointIndexHit.H"
|
||||
#include "triSurface.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
namespace VF
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class voxel Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class voxel
|
||||
:
|
||||
public raySearchEngine
|
||||
{
|
||||
// Private Data
|
||||
|
||||
//- Triangulation of view factor patches
|
||||
triSurface surface_;
|
||||
|
||||
//- Triangle to mesh face addressing
|
||||
labelList triToGlobalFace_;
|
||||
|
||||
//- Surface bounding box
|
||||
boundBox bb0_;
|
||||
|
||||
//- Span of surface bounding box
|
||||
vector span0_;
|
||||
|
||||
//- Voxel discretisation
|
||||
labelVector nijk_;
|
||||
|
||||
//- Voxel dimensions
|
||||
vector dxyz_;
|
||||
|
||||
//- Number of rays issued per face
|
||||
const label nRayPerFace_;
|
||||
|
||||
//- Maximum number of triangles per voxel (trigger to refine voxels)
|
||||
const label nTriPerVoxelMax_;
|
||||
|
||||
//- Maximum depth of voxel refinement. Note: voxels are refined 2x2x2
|
||||
const label depthMax_;
|
||||
|
||||
//- List of triangle per voxel
|
||||
List<DynamicList<label>> objects_;
|
||||
|
||||
//- List of triangle bounding boxes
|
||||
List<boundBox> objectBbs_;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
inline bool outOfBounds(const labelVector& ijk, const label dir) const;
|
||||
|
||||
inline point localPosition(const vector& globalPosition) const;
|
||||
|
||||
inline point globalPosition(const vector& localPosition) const;
|
||||
|
||||
inline void setVoxelDims(const label i, const label j, const label k);
|
||||
|
||||
inline void refineVoxelDims();
|
||||
|
||||
inline point voxelMin
|
||||
(
|
||||
const label i,
|
||||
const label j,
|
||||
const label k
|
||||
) const;
|
||||
|
||||
inline point voxelMax
|
||||
(
|
||||
const label i,
|
||||
const label j,
|
||||
const label k
|
||||
) const;
|
||||
|
||||
inline constexpr label sign0(const scalar x) const;
|
||||
|
||||
//- Set triangulation based on original mesh
|
||||
void setTriangulation(const fvMesh& mesh);
|
||||
|
||||
//- Set the participating face vertices when simplifying edges
|
||||
static labelList setFaceVertexHits
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const labelList& patchIDs
|
||||
);
|
||||
|
||||
//- Set triangulation based on agglomeration
|
||||
void setCoarseTriangulation(const fvMesh& mesh);
|
||||
|
||||
//- Broadcast triangulation across all procs
|
||||
void broadcast();
|
||||
|
||||
void refineObjects
|
||||
(
|
||||
List<DynamicList<label>>& objects,
|
||||
const label triMax
|
||||
);
|
||||
|
||||
label addBbToVoxels
|
||||
(
|
||||
const boundBox& bb,
|
||||
const label trii,
|
||||
List<DynamicList<label>>& objects
|
||||
) const;
|
||||
|
||||
void voxelise
|
||||
(
|
||||
List<DynamicList<label>>& objects,
|
||||
const label trii0,
|
||||
const label depth
|
||||
);
|
||||
|
||||
pointHit rayTriIntersect
|
||||
(
|
||||
const label trii,
|
||||
const point& origin,
|
||||
const vector& direction
|
||||
) const;
|
||||
|
||||
pointIndexHit hitObject
|
||||
(
|
||||
const label voxeli,
|
||||
const point& origin,
|
||||
const vector& direction,
|
||||
const vector& t,
|
||||
const scalar minDistance = 1e-6
|
||||
) const;
|
||||
|
||||
void writeBox
|
||||
(
|
||||
OBJstream& os,
|
||||
bool lines,
|
||||
const boundBox& bb
|
||||
) const;
|
||||
|
||||
void writeVoxels(const word& fName) const;
|
||||
|
||||
void writeTriBoundBoxes(const word& fName) const;
|
||||
|
||||
void writeHitObjects
|
||||
(
|
||||
const label voxeli,
|
||||
const point& origin,
|
||||
const vector& dir
|
||||
) const;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("voxel");
|
||||
|
||||
//- Constructor
|
||||
voxel(const fvMesh& mesh, const dictionary& dict);
|
||||
|
||||
//- Destructor
|
||||
virtual ~voxel() = default;
|
||||
|
||||
|
||||
// Public Member Functions
|
||||
|
||||
inline labelVector nijk() const noexcept;
|
||||
|
||||
inline label nVoxel() const noexcept;
|
||||
|
||||
inline label voxeli(const labelVector ijk) const noexcept;
|
||||
|
||||
inline label voxeli
|
||||
(
|
||||
const label i,
|
||||
const label j,
|
||||
const label k
|
||||
) const noexcept;
|
||||
|
||||
inline labelVector ijk(const label voxeli) const noexcept;
|
||||
|
||||
pointIndexHit hit(const point& origin, const vector& dir) const;
|
||||
|
||||
pointIndexHit hit(const label tri0, const vector& dir) const;
|
||||
|
||||
virtual void shootRays
|
||||
(
|
||||
labelList& rayStartFaceOut,
|
||||
labelList& rayEndFaceOut
|
||||
) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace VF
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#include "voxelRaySearchEngineI.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,155 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2023-2024 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
bool Foam::VF::voxel::outOfBounds
|
||||
(
|
||||
const labelVector& ijk,
|
||||
const label dir
|
||||
) const
|
||||
{
|
||||
return (ijk[dir] < 0 || ijk[dir] >= nijk_[dir]);
|
||||
};
|
||||
|
||||
|
||||
Foam::point Foam::VF::voxel::localPosition(const vector& globalPosition) const
|
||||
{
|
||||
return globalPosition - bb0_.min();
|
||||
}
|
||||
|
||||
|
||||
Foam::point Foam::VF::voxel::globalPosition(const vector& localPosition) const
|
||||
{
|
||||
return bb0_.min() + localPosition;
|
||||
}
|
||||
|
||||
|
||||
void Foam::VF::voxel::setVoxelDims(const label i, const label j, const label k)
|
||||
{
|
||||
nijk_[0] = max(1, i);
|
||||
nijk_[1] = max(1, j);
|
||||
nijk_[2] = max(1, k);
|
||||
|
||||
dxyz_[0] = span0_[0]/nijk_[0];
|
||||
dxyz_[1] = span0_[1]/nijk_[1];
|
||||
dxyz_[2] = span0_[2]/nijk_[2];
|
||||
}
|
||||
|
||||
|
||||
void Foam::VF::voxel::refineVoxelDims()
|
||||
{
|
||||
nijk_ *= 2;
|
||||
|
||||
// Do not refine empty direction for 2D
|
||||
const auto& solutionD = mesh_.solutionD();
|
||||
for (direction d=0; d<3; ++d)
|
||||
{
|
||||
if (solutionD[d] == -1)
|
||||
{
|
||||
nijk_[d] = 1;
|
||||
}
|
||||
}
|
||||
|
||||
setVoxelDims(nijk_[0], nijk_[1], nijk_[2]);
|
||||
}
|
||||
|
||||
|
||||
Foam::point Foam::VF::voxel::voxelMin
|
||||
(
|
||||
const label i,
|
||||
const label j,
|
||||
const label k
|
||||
) const
|
||||
{
|
||||
return point(i*dxyz_[0], j*dxyz_[1], k*dxyz_[2]);
|
||||
}
|
||||
|
||||
|
||||
Foam::point Foam::VF::voxel::voxelMax
|
||||
(
|
||||
const label i,
|
||||
const label j,
|
||||
const label k
|
||||
) const
|
||||
{
|
||||
return voxelMin(i+1, j+1, k+1);
|
||||
}
|
||||
|
||||
|
||||
constexpr Foam::label Foam::VF::voxel::sign0(const scalar x) const
|
||||
{
|
||||
if (x > 0) return 1;
|
||||
if (x < 0) return -1;
|
||||
return 0;
|
||||
};
|
||||
|
||||
|
||||
Foam::labelVector Foam::VF::voxel::nijk() const noexcept
|
||||
{
|
||||
return nijk_;
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::VF::voxel::nVoxel() const noexcept
|
||||
{
|
||||
return nijk_[0]*nijk_[1]*nijk_[2];
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::VF::voxel::voxeli
|
||||
(
|
||||
const labelVector ijk
|
||||
) const noexcept
|
||||
{
|
||||
return voxeli(ijk[0], ijk[1], ijk[2]);
|
||||
}
|
||||
|
||||
|
||||
Foam::label Foam::VF::voxel::voxeli
|
||||
(
|
||||
const label i,
|
||||
const label j,
|
||||
const label k
|
||||
) const noexcept
|
||||
{
|
||||
return i + (nijk_[0]*(j + (nijk_[1]*k)));
|
||||
}
|
||||
|
||||
|
||||
Foam::labelVector Foam::VF::voxel::ijk(const label voxeli) const noexcept
|
||||
{
|
||||
const label nx = nijk_[0];
|
||||
const label ny = nijk_[1];
|
||||
|
||||
const label i = voxeli%nx;
|
||||
const label k = voxeli/nx/ny;
|
||||
const label j = (voxeli/nx)%ny;
|
||||
|
||||
return labelVector(i, j, k);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,138 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2023-2024 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "viewFactor2AI.H"
|
||||
#include "mathematicalConstants.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
using namespace Foam::constant;
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace VF
|
||||
{
|
||||
defineTypeNameAndDebug(viewFactor2AI, 0);
|
||||
addToRunTimeSelectionTable(viewFactorModel, viewFactor2AI, mesh);
|
||||
}
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::scalar Foam::VF::viewFactor2AI::calculateFij
|
||||
(
|
||||
const point& xi,
|
||||
const point& xj,
|
||||
const vector& dAi,
|
||||
const vector& dAj
|
||||
)
|
||||
{
|
||||
const vector r(xj - xi);
|
||||
const scalar rMag = mag(r);
|
||||
const scalar dAiMag(mag(dAi));
|
||||
const scalar dAjMag(mag(dAj));
|
||||
|
||||
if (rMag > SMALL && dAiMag > SMALL && dAjMag > SMALL)
|
||||
{
|
||||
const vector nr(r/rMag);
|
||||
const vector ni(dAi/dAiMag);
|
||||
const vector nj(dAj/dAjMag);
|
||||
|
||||
const scalar Fij =
|
||||
-(nr & ni)*(nr & nj)/sqr(rMag)*dAjMag*dAiMag/mathematical::pi;
|
||||
|
||||
if (Fij > 0) return Fij;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Foam::scalarListList Foam::VF::viewFactor2AI::calculate
|
||||
(
|
||||
const labelListList& visibleFaceFaces,
|
||||
const pointField& compactCf,
|
||||
const vectorField& compactSf,
|
||||
const List<List<vector>>& compactFineSf,
|
||||
const List<List<point>>& compactFineCf,
|
||||
const DynamicList<List<point>>& compactPoints,
|
||||
const DynamicList<label>& compactPatchId
|
||||
) const
|
||||
{
|
||||
// Fill local view factor matrix
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
scalarListList Fij(visibleFaceFaces.size());
|
||||
|
||||
forAll(visibleFaceFaces, facei)
|
||||
{
|
||||
if (debug > 1)
|
||||
{
|
||||
Pout<< "facei:" << facei << "/" << visibleFaceFaces.size()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
const labelList& visibleFaces = visibleFaceFaces[facei];
|
||||
|
||||
Fij[facei].resize(visibleFaces.size(), Zero);
|
||||
|
||||
const point& dCi = compactCf[facei];
|
||||
const vector& Ai = compactSf[facei];
|
||||
const scalar magAi = mag(Ai);
|
||||
|
||||
if (magAi < SMALL) continue;
|
||||
|
||||
forAll(visibleFaces, visibleFacei)
|
||||
{
|
||||
const label sloti = visibleFaces[visibleFacei];
|
||||
const point& dCj = compactCf[sloti];
|
||||
const vector& Aj = compactSf[sloti];
|
||||
|
||||
const scalar Fij2AI = calculateFij(dCi, dCj, Ai, Aj);
|
||||
|
||||
Fij[facei][visibleFacei] = Fij2AI/magAi;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return Fij;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::VF::viewFactor2AI::viewFactor2AI
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
viewFactorModel(mesh, dict)
|
||||
{}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,117 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2023-2024 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::VF::viewFactor2AI
|
||||
|
||||
Description
|
||||
Computes view factors according to the double area integral (2AI) method.
|
||||
|
||||
Usage
|
||||
Minimal example in \c <constant>/viewFactorsDict:
|
||||
\verbatim
|
||||
// Inherited entries
|
||||
...
|
||||
\endverbatim
|
||||
|
||||
The inherited entries are elaborated in:
|
||||
- \link viewFactorModel.H \endlink
|
||||
|
||||
SourceFiles
|
||||
viewFactorModel.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_vf_viewFactor2AI_H
|
||||
#define Foam_vf_viewFactor2AI_H
|
||||
|
||||
#include "viewFactorModel.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
namespace VF
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class viewFactor2AI Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class viewFactor2AI
|
||||
:
|
||||
public viewFactorModel
|
||||
{
|
||||
|
||||
protected:
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Calculate view factor using the double-area integral
|
||||
static scalar calculateFij
|
||||
(
|
||||
const point& xi,
|
||||
const point& xj,
|
||||
const vector& dAi,
|
||||
const vector& dAj
|
||||
);
|
||||
|
||||
//- Calculate
|
||||
virtual scalarListList calculate
|
||||
(
|
||||
const labelListList& visibleFaceFaces,
|
||||
const pointField& compactCf,
|
||||
const vectorField& compactSf,
|
||||
const List<List<vector>>& compactFineSf,
|
||||
const List<List<point>>& compactFineCf,
|
||||
const DynamicList<List<point>>& compactPoints,
|
||||
const DynamicList<label>& compactPatchId
|
||||
) const;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("viewFactor2AI");
|
||||
|
||||
//- Constructor
|
||||
viewFactor2AI(const fvMesh& mesh, const dictionary& dict);
|
||||
|
||||
//- Destructor
|
||||
virtual ~viewFactor2AI() = default;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace VF
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,141 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2023-2024 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "viewFactor2LI.H"
|
||||
#include "mathematicalConstants.H"
|
||||
#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
using namespace Foam::constant;
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace VF
|
||||
{
|
||||
defineTypeNameAndDebug(viewFactor2LI, 0);
|
||||
addToRunTimeSelectionTable(viewFactorModel, viewFactor2LI, mesh);
|
||||
}
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::scalar Foam::VF::viewFactor2LI::calculateFij
|
||||
(
|
||||
const List<point>& lPoints,
|
||||
const List<point>& rPoints,
|
||||
const scalar alpha
|
||||
)
|
||||
{
|
||||
scalar Fij = 0;
|
||||
|
||||
forAll(lPoints, i)
|
||||
{
|
||||
// Edge vector and centroid of edge i
|
||||
const vector si(lPoints[i] - lPoints.rcValue(i));
|
||||
const point ci(0.5*(lPoints[i] + lPoints.rcValue(i)));
|
||||
|
||||
forAll(rPoints, j)
|
||||
{
|
||||
// Edge vector and centroid of edge j
|
||||
const vector sj(rPoints[j] - rPoints.rcValue(j));
|
||||
const point cj(0.5*(rPoints[j] + rPoints.rcValue(j)));
|
||||
|
||||
vector r(ci - cj);
|
||||
if (mag(r) < SMALL)
|
||||
{
|
||||
r = alpha*si;
|
||||
}
|
||||
|
||||
Fij += (si & sj)*Foam::log(r & r);
|
||||
}
|
||||
}
|
||||
|
||||
return max(0, 0.25*Fij/mathematical::pi);
|
||||
}
|
||||
|
||||
|
||||
Foam::scalarListList Foam::VF::viewFactor2LI::calculate
|
||||
(
|
||||
const labelListList& visibleFaceFaces,
|
||||
const pointField& compactCf,
|
||||
const vectorField& compactSf,
|
||||
const List<List<vector>>& compactFineSf,
|
||||
const List<List<point>>& compactFineCf,
|
||||
const DynamicList<List<point>>& compactPoints,
|
||||
const DynamicList<label>& compactPatchId
|
||||
) const
|
||||
{
|
||||
// Fill local view factor matrix
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
scalarListList Fij(visibleFaceFaces.size());
|
||||
|
||||
forAll(visibleFaceFaces, facei)
|
||||
{
|
||||
if (debug > 1)
|
||||
{
|
||||
Pout<< "facei:" << facei << "/" << visibleFaceFaces.size()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
const labelList& visibleFaces = visibleFaceFaces[facei];
|
||||
|
||||
Fij[facei].resize(visibleFaces.size(), Zero);
|
||||
|
||||
const vector& Ai = compactSf[facei];
|
||||
const scalar magAi = mag(Ai);
|
||||
|
||||
forAll(visibleFaces, visibleFacei)
|
||||
{
|
||||
const label sloti = visibleFaces[visibleFacei];
|
||||
const List<point>& lPoints = compactPoints[facei];
|
||||
const List<point>& rPoints = compactPoints[sloti];
|
||||
|
||||
const scalar Fij2LI = calculateFij(lPoints, rPoints, alpha_);
|
||||
|
||||
Fij[facei][visibleFacei] = Fij2LI/magAi;
|
||||
}
|
||||
}
|
||||
|
||||
return Fij;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::VF::viewFactor2LI::viewFactor2LI
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
viewFactorModel(mesh, dict),
|
||||
alpha_(dict.getOrDefault("alpha", 0.21))
|
||||
{}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,130 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2023-2024 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::VF::viewFactor2LI
|
||||
|
||||
Description
|
||||
Computes view factors according to the double line integral (2LI) method.
|
||||
|
||||
Usage
|
||||
Minimal example in \c <constant>/viewFactorsDict:
|
||||
\verbatim
|
||||
// Optional entries
|
||||
alpha <scalar>;
|
||||
|
||||
// Inherited entries
|
||||
...
|
||||
\endverbatim
|
||||
|
||||
where the entries mean:
|
||||
\table
|
||||
Property | Description | Type | Reqd | Deflt
|
||||
alpha | Perturbation for common edges | scalar | no | 0.21
|
||||
\endtable
|
||||
|
||||
The inherited entries are elaborated in:
|
||||
- \link viewFactorModel.H \endlink
|
||||
|
||||
SourceFiles
|
||||
viewFactorModel.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_vf_viewFactor2LI_H
|
||||
#define Foam_vf_viewFactor2LI_H
|
||||
|
||||
#include "viewFactorModel.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
namespace VF
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class viewFactor2LI Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class viewFactor2LI
|
||||
:
|
||||
public viewFactorModel
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected Data
|
||||
|
||||
//- Perturbation for common edges; default = 0.21
|
||||
const scalar alpha_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Calculate view factor using the double-area integral
|
||||
static scalar calculateFij
|
||||
(
|
||||
const List<point>& lPoints,
|
||||
const List<point>& rPoints,
|
||||
const scalar alpha
|
||||
);
|
||||
|
||||
//- Calculate
|
||||
virtual scalarListList calculate
|
||||
(
|
||||
const labelListList& visibleFaceFaces,
|
||||
const pointField& compactCf,
|
||||
const vectorField& compactSf,
|
||||
const List<List<vector>>& compactFineSf,
|
||||
const List<List<point>>& compactFineCf,
|
||||
const DynamicList<List<point>>& compactPoints,
|
||||
const DynamicList<label>& compactPatchId
|
||||
) const;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("viewFactor2LI");
|
||||
|
||||
//- Constructor
|
||||
viewFactor2LI(const fvMesh& mesh, const dictionary& dict);
|
||||
|
||||
//- Destructor
|
||||
virtual ~viewFactor2LI() = default;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace VF
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,153 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2023-2024 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "viewFactorHottel.H"
|
||||
#include "mathematicalConstants.H"
|
||||
#include "fvMesh.H"
|
||||
#include "meshTools.H"
|
||||
//#include "addToRunTimeSelectionTable.H"
|
||||
|
||||
using namespace Foam::constant;
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace VF
|
||||
{
|
||||
defineTypeNameAndDebug(viewFactorHottel, 0);
|
||||
// addToRunTimeSelectionTable(viewFactorModel, viewFactorHottel, mesh);
|
||||
}
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
Foam::scalar Foam::VF::viewFactorHottel::calculateFij
|
||||
(
|
||||
const point& p0,
|
||||
const point& p1,
|
||||
const point& p2,
|
||||
const point& p3
|
||||
)
|
||||
{
|
||||
return 0.5*(mag(p2-p1) + mag(p3-p0) - mag(p2-p0) - mag(p3-p1));
|
||||
}
|
||||
|
||||
|
||||
Foam::scalarListList Foam::VF::viewFactorHottel::calculate
|
||||
(
|
||||
const labelListList& visibleFaceFaces,
|
||||
const pointField& compactCf,
|
||||
const vectorField& compactSf,
|
||||
const List<List<vector>>& compactFineSf,
|
||||
const List<List<point>>& compactFineCf,
|
||||
const DynamicList<List<point>>& compactPoints,
|
||||
const DynamicList<label>& compactPatchId
|
||||
) const
|
||||
{
|
||||
// Fill local view factor matrix
|
||||
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
scalarListList Fij(visibleFaceFaces.size());
|
||||
|
||||
forAll(visibleFaceFaces, facei)
|
||||
{
|
||||
if (debug > 1)
|
||||
{
|
||||
Pout<< "facei:" << facei << "/" << visibleFaceFaces.size()
|
||||
<< endl;
|
||||
}
|
||||
|
||||
const labelList& visibleFaces = visibleFaceFaces[facei];
|
||||
|
||||
Fij[facei].resize_nocopy(visibleFaces.size());
|
||||
|
||||
const point& dCi = compactCf[facei];
|
||||
const vector& Ai = compactSf[facei];
|
||||
const scalar magAi = mag(Ai);
|
||||
|
||||
const vector d1((Ai/magAi) ^ emptyDir_);
|
||||
const vector l1(0.5*magAi/w_*d1);
|
||||
const point p0(dCi + l1);
|
||||
const point p1(dCi - l1);
|
||||
|
||||
forAll(visibleFaces, visibleFacei)
|
||||
{
|
||||
const label sloti = visibleFaces[visibleFacei];
|
||||
|
||||
const point& dCj = compactCf[sloti];
|
||||
const vector& Aj = compactSf[sloti];
|
||||
const scalar magAj = mag(Aj);
|
||||
|
||||
const vector d2((Aj/magAj) ^ emptyDir_);
|
||||
const vector l2(0.5*magAj/w_*d2);
|
||||
const point p2(dCj - l2);
|
||||
const point p3(dCj + l2);
|
||||
|
||||
const scalar FijH = calculateFij(p0, p1, p2, p3);
|
||||
|
||||
Fij[facei][visibleFacei] = FijH/(magAi/w_);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return Fij;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::VF::viewFactorHottel::viewFactorHottel
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
viewFactorModel(mesh, dict),
|
||||
emptyDir_(vector::one),
|
||||
w_(0)
|
||||
{
|
||||
if (mesh.nSolutionD() != 2)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Hottel crossed strings method only applicable to 2D cases"
|
||||
<< exit(FatalError);
|
||||
}
|
||||
|
||||
meshTools::constrainDirection(mesh, mesh.solutionD(), emptyDir_);
|
||||
emptyDir_ = vector::one - emptyDir_;
|
||||
emptyDir_.normalise();
|
||||
|
||||
// 2D width - assume slab
|
||||
// TODO: warn wedge/axisymmetric?
|
||||
w_ = mesh.bounds().span() & emptyDir_;
|
||||
|
||||
Info<< "\nEmpty direction: " << emptyDir_
|
||||
<< "\nWidth: " << w_ << endl;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,135 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2023-2024 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Class
|
||||
Foam::VF::viewFactorHottel
|
||||
|
||||
Description
|
||||
Computes view factors according to Hottel's crossed strings method.
|
||||
|
||||
Reference:
|
||||
\verbatim
|
||||
Hottel, H. C., & Saforim, A. F. (1967).
|
||||
Radiative transfer.
|
||||
McGraw-Hill Book Company, New York.
|
||||
\endverbatim
|
||||
|
||||
Usage
|
||||
Minimal example in \c <constant>/viewFactorsDict:
|
||||
\verbatim
|
||||
// Inherited entries
|
||||
...
|
||||
\endverbatim
|
||||
|
||||
The inherited entries are elaborated in:
|
||||
- \link viewFactorModel.H \endlink
|
||||
|
||||
Note
|
||||
Only applicable to 2D cases
|
||||
|
||||
SourceFiles
|
||||
viewFactorModel.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_vf_viewFactorHottel_H
|
||||
#define Foam_vf_viewFactorHottel_H
|
||||
|
||||
#include "viewFactorModel.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
namespace VF
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class viewFactorHottel Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class viewFactorHottel
|
||||
:
|
||||
public viewFactorModel
|
||||
{
|
||||
// Private Data
|
||||
|
||||
//- Mesh empty direction
|
||||
vector emptyDir_;
|
||||
|
||||
//- Mesh 2D width
|
||||
scalar w_;
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Calculate view factor using the double-area integral
|
||||
static scalar calculateFij
|
||||
(
|
||||
const point& p0,
|
||||
const point& p1,
|
||||
const point& p2,
|
||||
const point& p3
|
||||
);
|
||||
|
||||
//- Calculate
|
||||
virtual scalarListList calculate
|
||||
(
|
||||
const labelListList& visibleFaceFaces,
|
||||
const pointField& compactCf,
|
||||
const vectorField& compactSf,
|
||||
const List<List<vector>>& compactFineSf,
|
||||
const List<List<point>>& compactFineCf,
|
||||
const DynamicList<List<point>>& compactPoints,
|
||||
const DynamicList<label>& compactPatchId
|
||||
) const;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("viewFactorHottel");
|
||||
|
||||
//- Constructor
|
||||
viewFactorHottel(const fvMesh& mesh, const dictionary& dict);
|
||||
|
||||
//- Destructor
|
||||
virtual ~viewFactorHottel() = default;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace VF
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,290 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2023-2024 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "viewFactorModel.H"
|
||||
#include "raySearchEngine.H"
|
||||
#include "OBJstream.H"
|
||||
#include "volFields.H"
|
||||
#include "IOmapDistribute.H"
|
||||
#include "scalarListIOList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace VF
|
||||
{
|
||||
defineTypeNameAndDebug(viewFactorModel, 0);
|
||||
defineRunTimeSelectionTable(viewFactorModel, mesh);
|
||||
}
|
||||
}
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
|
||||
void Foam::VF::viewFactorModel::writeRays
|
||||
(
|
||||
const fileName& fName,
|
||||
const pointField& compactCf,
|
||||
const labelListList& visibleFaceFaces
|
||||
)
|
||||
{
|
||||
OBJstream str(fName);
|
||||
|
||||
Pout<< "Writing rays to " << str.name() << endl;
|
||||
|
||||
forAll(visibleFaceFaces, facei)
|
||||
{
|
||||
const labelList& visibleSlots = visibleFaceFaces[facei];
|
||||
|
||||
for (const label sloti : visibleSlots)
|
||||
{
|
||||
str.write(linePointRef(compactCf[facei], compactCf[sloti]));
|
||||
}
|
||||
}
|
||||
|
||||
str.flush();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::VF::viewFactorModel::viewFactorModel
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const dictionary& dict
|
||||
)
|
||||
:
|
||||
mesh_(mesh),
|
||||
searchEnginePtr_(raySearchEngine::New(mesh, dict)),
|
||||
writeViewFactors_(dict.get<bool>("writeViewFactors")),
|
||||
writeRays_(dict.getOrDefault<bool>("writeRays", false))
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::VF::viewFactorModel::~viewFactorModel()
|
||||
{}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::VF::viewFactorModel::calculate()
|
||||
{
|
||||
const auto& searchEngine = *searchEnginePtr_;
|
||||
|
||||
labelListList visibleFaceFaces;
|
||||
searchEngine.correct(visibleFaceFaces);
|
||||
const auto& map = searchEngine.map();
|
||||
|
||||
// Construct data in compact addressing
|
||||
// Compact addressing has all local data, followed by remote contributions
|
||||
|
||||
pointField compactCf;
|
||||
vectorField compactSf;
|
||||
List<List<vector>> compactFineSf;
|
||||
List<List<point>> compactFineCf;
|
||||
DynamicList<List<point>> compactPoints;
|
||||
DynamicList<label> compactPatchId;
|
||||
|
||||
searchEngine.compactAddressing
|
||||
(
|
||||
map,
|
||||
compactCf,
|
||||
compactSf,
|
||||
compactFineSf,
|
||||
compactFineCf,
|
||||
compactPoints,
|
||||
compactPatchId
|
||||
);
|
||||
|
||||
if (writeRays_)
|
||||
{
|
||||
// Write all rays between visible faces using .OBJ format
|
||||
|
||||
writeRays
|
||||
(
|
||||
mesh_.time().path()/"allVisibleFaces.obj",
|
||||
compactCf,
|
||||
visibleFaceFaces
|
||||
);
|
||||
}
|
||||
|
||||
(void)mesh_.time().cpuTimeIncrement();
|
||||
|
||||
Info<< "\nCalculating view factors" << endl;
|
||||
|
||||
scalarListIOList Fij
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"F",
|
||||
mesh_.facesInstance(),
|
||||
mesh_,
|
||||
IOobject::NO_READ
|
||||
),
|
||||
calculate
|
||||
(
|
||||
visibleFaceFaces,
|
||||
compactCf,
|
||||
compactSf,
|
||||
compactFineSf,
|
||||
compactFineCf,
|
||||
compactPoints,
|
||||
compactPatchId
|
||||
)
|
||||
);
|
||||
|
||||
const label totalPatches = mesh_.boundaryMesh().nNonProcessor();
|
||||
|
||||
// Matrix sum in j(Fij) for each i
|
||||
// Note: if enclosure sum should = 1
|
||||
scalarSquareMatrix viewFactorPatch(totalPatches, Zero);
|
||||
|
||||
forAll(visibleFaceFaces, startFacei)
|
||||
{
|
||||
const scalar magAi = mag(compactSf[startFacei]);
|
||||
|
||||
const labelList& visibleSlots = visibleFaceFaces[startFacei];
|
||||
const label patchi = compactPatchId[startFacei];
|
||||
|
||||
forAll(visibleSlots, visSloti)
|
||||
{
|
||||
const label sloti = visibleSlots[visSloti];
|
||||
const label patchj = compactPatchId[sloti];
|
||||
|
||||
viewFactorPatch[patchi][patchj] += Fij[startFacei][visSloti]*magAi;
|
||||
}
|
||||
}
|
||||
|
||||
reduce(viewFactorPatch, sumOp<scalarSquareMatrix>());
|
||||
|
||||
const scalarList patchArea = searchEngine.patchAreas();
|
||||
|
||||
|
||||
if (UPstream::master())
|
||||
{
|
||||
Info<< "\nPatch view factor contributions:" << nl << endl;
|
||||
|
||||
scalar vfSum = 0;
|
||||
|
||||
const auto& patchIDs = searchEngine.patchIDs();
|
||||
const auto& patches = mesh_.boundaryMesh();
|
||||
|
||||
for (const label patchi : patchIDs)
|
||||
{
|
||||
Info<< " Patch " << patchi << ": " << patches[patchi].name()
|
||||
<< endl;
|
||||
|
||||
scalar vfPatch = 0;
|
||||
for (const label patchj: patchIDs)
|
||||
{
|
||||
scalar vf = viewFactorPatch[patchi][patchj]/patchArea[patchi];
|
||||
vfPatch += vf;
|
||||
|
||||
Info<< " F" << patchi << patchj << ": " << vf << endl;
|
||||
}
|
||||
|
||||
Info<< " Sum: " << vfPatch << nl << endl;
|
||||
|
||||
vfSum += vfPatch;
|
||||
}
|
||||
|
||||
Info<< "Sum(all patches) = " << vfSum << endl;
|
||||
}
|
||||
|
||||
// Write view factors matrix in list-list form
|
||||
Info<< "\nWriting view factor matrix" << endl;
|
||||
Fij.write();
|
||||
|
||||
if (writeViewFactors_)
|
||||
{
|
||||
Info<< "\nWriting view factor field" << endl;
|
||||
|
||||
auto tviewFactorField =
|
||||
volScalarField::New
|
||||
(
|
||||
"viewFactorField",
|
||||
mesh_,
|
||||
dimensionedScalar(dimless, Zero)
|
||||
);
|
||||
|
||||
auto& viewFactorField = tviewFactorField.ref();
|
||||
|
||||
searchEngine.interpolate(viewFactorField, Fij);
|
||||
|
||||
viewFactorField.write();
|
||||
}
|
||||
|
||||
|
||||
// Create globalFaceFaces needed to insert view factors
|
||||
// in F to the global matrix Fmatrix
|
||||
{
|
||||
labelListIOList IOglobalFaceFaces
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"globalFaceFaces",
|
||||
mesh_.facesInstance(),
|
||||
mesh_,
|
||||
IOobject::NO_READ
|
||||
),
|
||||
visibleFaceFaces.size()
|
||||
);
|
||||
|
||||
forAll(IOglobalFaceFaces, facei)
|
||||
{
|
||||
IOglobalFaceFaces[facei] = renumber
|
||||
(
|
||||
searchEngine.compactToGlobal(),
|
||||
visibleFaceFaces[facei]
|
||||
);
|
||||
}
|
||||
|
||||
IOglobalFaceFaces.write();
|
||||
}
|
||||
|
||||
// Write parallel map
|
||||
{
|
||||
IOmapDistribute IOmapDist
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"mapDist",
|
||||
mesh_.facesInstance(),
|
||||
mesh_,
|
||||
IOobject::NO_READ
|
||||
),
|
||||
std::move(map)
|
||||
);
|
||||
|
||||
IOmapDist.write();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,185 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2023-2024 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
Namespace
|
||||
Foam::VF
|
||||
|
||||
Description
|
||||
A namespace for various \c viewFactor model implementations.
|
||||
|
||||
Class
|
||||
Foam::VF::viewFactorModel
|
||||
|
||||
Description
|
||||
A base class for \c viewFactor models.
|
||||
|
||||
Usage
|
||||
Minimal example in \c <constant>/viewFactorsDict:
|
||||
\verbatim
|
||||
// Mandatory entries
|
||||
writeViewFactors <bool>;
|
||||
|
||||
// Optional entries
|
||||
writeRays <bool>;
|
||||
\endverbatim
|
||||
|
||||
where the entries mean:
|
||||
\table
|
||||
Property | Description | Type | Reqd | Deflt
|
||||
writeViewFactors | Flag to write the view factor field | bool | yes | -
|
||||
writeRays | Flag to write the ray geometry | bool | no | false
|
||||
\endtable
|
||||
|
||||
SourceFiles
|
||||
viewFactorModel.C
|
||||
viewFactorModelNew.C
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_vf_viewFactorModel_H
|
||||
#define Foam_vf_viewFactorModel_H
|
||||
|
||||
#include "autoPtr.H"
|
||||
#include "pointField.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward Declarations
|
||||
class fvMesh;
|
||||
|
||||
namespace VF
|
||||
{
|
||||
|
||||
// Forward Declarations
|
||||
class raySearchEngine;
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class viewFactorModel Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class viewFactorModel
|
||||
{
|
||||
protected:
|
||||
|
||||
// Protected Data
|
||||
|
||||
//- Reference to the mesh database
|
||||
const fvMesh& mesh_;
|
||||
|
||||
//- Run-time selectable ray search engine
|
||||
autoPtr<raySearchEngine> searchEnginePtr_;
|
||||
|
||||
//- Flag to write the view factor field
|
||||
bool writeViewFactors_;
|
||||
|
||||
//- Flag to write the ray geometry
|
||||
bool writeRays_;
|
||||
|
||||
|
||||
// Protected Member Functions
|
||||
|
||||
//- Write ray geometry to file
|
||||
static void writeRays
|
||||
(
|
||||
const fileName& fName,
|
||||
const pointField& compactCf,
|
||||
const labelListList& visibleFaceFaces
|
||||
);
|
||||
|
||||
//- Calculate the view factors using run-time selectable model
|
||||
virtual scalarListList calculate
|
||||
(
|
||||
const labelListList& visibleFaceFaces,
|
||||
const pointField& compactCoarseCf,
|
||||
const vectorField& compactCoarseSf,
|
||||
const List<List<vector>>& compactFineSf,
|
||||
const List<List<point>>& compactFineCf,
|
||||
const DynamicList<List<point>>& compactPoints,
|
||||
const DynamicList<label>& compactPatchId
|
||||
) const = 0;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("viewFactorModel");
|
||||
|
||||
//- Selection table
|
||||
declareRunTimeSelectionTable
|
||||
(
|
||||
autoPtr,
|
||||
viewFactorModel,
|
||||
mesh,
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const dictionary& dict
|
||||
),
|
||||
(mesh, dict)
|
||||
);
|
||||
|
||||
//- Selector
|
||||
static autoPtr<viewFactorModel> New
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const dictionary& dict
|
||||
);
|
||||
|
||||
|
||||
// Generated Methods
|
||||
|
||||
//- No copy construct
|
||||
viewFactorModel(const viewFactorModel&) = delete;
|
||||
|
||||
//- No copy assignment
|
||||
void operator=(const viewFactorModel&) = delete;
|
||||
|
||||
|
||||
//- Constructor
|
||||
viewFactorModel(const fvMesh& mesh, const dictionary& dict);
|
||||
|
||||
//- Destructor
|
||||
virtual ~viewFactorModel();
|
||||
|
||||
|
||||
// Public Member Functions
|
||||
|
||||
//- Calculate the view factors
|
||||
virtual void calculate();
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace VF
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -0,0 +1,72 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2023-2024 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "viewFactorModel.H"
|
||||
#include "viewFactorHottel.H"
|
||||
#include "fvMesh.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
Foam::autoPtr<Foam::VF::viewFactorModel> Foam::VF::viewFactorModel::New
|
||||
(
|
||||
const fvMesh& mesh,
|
||||
const dictionary& dict
|
||||
)
|
||||
{
|
||||
// Intercept 2D cases
|
||||
if (mesh.nSolutionD() == 2)
|
||||
{
|
||||
Info<< "Selecting " << typeName << ": " << viewFactorHottel::typeName
|
||||
<< " for 2D cases" << nl << endl;
|
||||
return autoPtr<viewFactorModel>(new viewFactorHottel(mesh, dict));
|
||||
}
|
||||
|
||||
|
||||
// 3D cases - use run-time selection
|
||||
|
||||
const word modelType(dict.get<word>("viewFactorModel"));
|
||||
|
||||
Info<< "Selecting " << typeName << ": " << modelType << endl;
|
||||
|
||||
auto* ctorPtr = meshConstructorTable(modelType);
|
||||
|
||||
if (!ctorPtr)
|
||||
{
|
||||
FatalIOErrorInLookup
|
||||
(
|
||||
dict,
|
||||
typeName,
|
||||
modelType,
|
||||
*meshConstructorTablePtr_
|
||||
) << exit(FatalIOError);
|
||||
}
|
||||
|
||||
return autoPtr<viewFactorModel>(ctorPtr(mesh, dict));
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
Reference in New Issue
Block a user