openfoam/src/sampling/probes/patchProbes.C

269 lines
7.5 KiB
C

/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "patchProbes.H"
#include "volFields.H"
#include "IOmanip.H"
#include "mappedPatchBase.H"
#include "treeBoundBox.H"
#include "treeDataFace.H"
#include "addToRunTimeSelectionTable.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam
{
defineTypeNameAndDebug(patchProbes, 0);
addToRunTimeSelectionTable
(
functionObject,
patchProbes,
dictionary
);
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
void Foam::patchProbes::findElements(const fvMesh& mesh)
{
(void)mesh.tetBasePtIs();
const polyBoundaryMesh& bm = mesh.boundaryMesh();
label patchi = bm.findPatchID(patchName_);
if (patchi == -1)
{
FatalErrorInFunction
<< " Unknown patch name "
<< patchName_ << endl
<< exit(FatalError);
}
// All the info for nearest. Construct to miss
List<mappedPatchBase::nearInfo> nearest(this->size());
const polyPatch& pp = bm[patchi];
if (pp.size() > 0)
{
labelList bndFaces(pp.size());
forAll(bndFaces, i)
{
bndFaces[i] = pp.start() + i;
}
treeBoundBox overallBb(pp.points());
Random rndGen(123456);
overallBb = overallBb.extend(rndGen, 1e-4);
overallBb.min() -= point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
overallBb.max() += point(ROOTVSMALL, ROOTVSMALL, ROOTVSMALL);
const indexedOctree<treeDataFace> boundaryTree
(
treeDataFace // all information needed to search faces
(
false, // do not cache bb
mesh,
bndFaces // patch faces only
),
overallBb, // overall search domain
8, // maxLevel
10, // leafsize
3.0 // duplicity
);
forAll(probeLocations(), probei)
{
const point sample = probeLocations()[probei];
scalar span = boundaryTree.bb().mag();
pointIndexHit info = boundaryTree.findNearest
(
sample,
Foam::sqr(span)
);
if (!info.hit())
{
info = boundaryTree.findNearest
(
sample,
Foam::sqr(GREAT)
);
}
label facei = boundaryTree.shapes().faceLabels()[info.index()];
const label patchi = bm.whichPatch(facei);
if (isA<emptyPolyPatch>(bm[patchi]))
{
WarningInFunction
<< " The sample point: " << sample
<< " belongs to " << patchi
<< " which is an empty patch. This is not permitted. "
<< " This sample will not be included "
<< endl;
}
else
{
const point& fc = mesh.faceCentres()[facei];
mappedPatchBase::nearInfo sampleInfo;
sampleInfo.first() = pointIndexHit
(
true,
fc,
facei
);
sampleInfo.second().first() = magSqr(fc-sample);
sampleInfo.second().second() = Pstream::myProcNo();
nearest[probei]= sampleInfo;
}
}
}
// Find nearest.
Pstream::listCombineGather(nearest, mappedPatchBase::nearestEqOp());
Pstream::listCombineScatter(nearest);
if (debug)
{
InfoInFunction << endl;
forAll(nearest, sampleI)
{
label proci = nearest[sampleI].second().second();
label localI = nearest[sampleI].first().index();
Info<< " " << sampleI << " coord:"<< operator[](sampleI)
<< " found on processor:" << proci
<< " in local cell/face:" << localI
<< " with fc:" << nearest[sampleI].first().rawPoint() << endl;
}
}
// Extract any local faces to sample
elementList_.setSize(nearest.size(), -1);
forAll(nearest, sampleI)
{
if (nearest[sampleI].second().second() == Pstream::myProcNo())
{
// Store the face to sample
elementList_[sampleI] = nearest[sampleI].first().index();
}
}
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::patchProbes::patchProbes
(
const word& name,
const Time& t,
const dictionary& dict
)
:
probes(name, t, dict)
{
// When constructing probes above it will have called the
// probes::findElements (since the virtual mechanism not yet operating).
// Not easy to workaround (apart from feeding through flag into constructor)
// so clear out any cells found for now.
elementList_.clear();
faceList_.clear();
read(dict);
}
Foam::patchProbes::patchProbes
(
const word& name,
const objectRegistry& obr,
const dictionary& dict,
const bool loadFromFiles
)
:
probes(name, obr, dict)
{
// When constructing probes above it will have called the
// probes::findElements (since the virtual mechanism not yet operating).
// Not easy to workaround (apart from feeding through flag into constructor)
// so clear out any cells found for now.
elementList_.clear();
faceList_.clear();
read(dict);
}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
Foam::patchProbes::~patchProbes()
{}
bool Foam::patchProbes::write(const bool postProcess)
{
if (this->size() && prepare())
{
sampleAndWrite(scalarFields_);
sampleAndWrite(vectorFields_);
sampleAndWrite(sphericalTensorFields_);
sampleAndWrite(symmTensorFields_);
sampleAndWrite(tensorFields_);
sampleAndWriteSurfaceFields(surfaceScalarFields_);
sampleAndWriteSurfaceFields(surfaceVectorFields_);
sampleAndWriteSurfaceFields(surfaceSphericalTensorFields_);
sampleAndWriteSurfaceFields(surfaceSymmTensorFields_);
sampleAndWriteSurfaceFields(surfaceTensorFields_);
}
return true;
}
bool Foam::patchProbes::read(const dictionary& dict)
{
dict.lookup("patchName") >> patchName_;
return probes::read(dict);
}
// ************************************************************************* //