/*---------------------------------------------------------------------------*\ ========= | \\ / 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 . \*---------------------------------------------------------------------------*/ #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 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 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(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); } // ************************************************************************* //