/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 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 . \*---------------------------------------------------------------------------*/ #include "faceMapper.H" #include "polyMesh.H" #include "mapPolyMesh.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // void Foam::faceMapper::calcAddressing() const { if ( directAddrPtr_ || interpAddrPtr_ || weightsPtr_ || insertedObjectsPtr_ ) { FatalErrorInFunction << "Addressing already calculated." << abort(FatalError); } if (direct()) { // Direct addressing, no weights // Restrict addressing list to contain only live faces directAddrPtr_ = std::make_unique ( labelList::subList(mpm_.faceMap(), mapperLen_) ); auto& directAddr = *directAddrPtr_; insertedObjectsPtr_ = std::make_unique(); auto& inserted = *insertedObjectsPtr_; // The nInsertedObjects_ already counted in the constructor if (nInsertedObjects_) { inserted.resize(nInsertedObjects_); label nInserted = 0; forAll(directAddr, i) { if (directAddr[i] < 0) { // Found inserted directAddr[i] = 0; inserted[nInserted] = i; ++nInserted; // TBD: check (nInsertedObjects_ < nInserted)? #ifdef FULLDEBUG if (nInsertedObjects_ < nInserted) { FatalErrorInFunction << "Unexpected insert of more than " << nInsertedObjects_ << " items\n" << abort(FatalError); } #endif } } // TBD: check (nInserted < nInsertedObjects_)? #ifdef FULLDEBUG if (nInserted < nInsertedObjects_) { WarningInFunction << "Found " << nInserted << " instead of " << nInsertedObjects_ << " items to insert\n"; } #endif // The resize should be unnecessary inserted.resize(nInserted); } } else { // Interpolative addressing interpAddrPtr_ = std::make_unique(mapperLen_); auto& addr = *interpAddrPtr_; weightsPtr_ = std::make_unique(mapperLen_); auto& wght = *weightsPtr_; // Set the addressing and uniform weight const auto setAddrWeights = [&] ( const List& maps, const char * const nameOfMap ) { for (const objectMap& map : maps) { // Get index, addressing const label facei = map.index(); const labelList& mo = map.masterObjects(); if (mo.empty()) continue; // safety if (addr[facei].size()) { FatalErrorInFunction << "Master face " << facei << " already mapped, cannot apply " << nameOfMap << flatOutput(mo) << abort(FatalError); } // Map from masters, uniform weights addr[facei] = mo; wght[facei] = scalarList(mo.size(), 1.0/mo.size()); } }; setAddrWeights(mpm_.facesFromPointsMap(), "point faces"); setAddrWeights(mpm_.facesFromEdgesMap(), "edge faces"); setAddrWeights(mpm_.facesFromFacesMap(), "face faces"); // Do mapped faces. // - may already have been set, so check if addressing still empty(). { const labelList& map = mpm_.faceMap(); // NB: faceMap can be longer than nFaces() for (label facei = 0; facei < mapperLen_; ++facei) { const label mappedi = map[facei]; if (mappedi >= 0 && addr[facei].empty()) { // Mapped from a single face addr[facei].resize(1, mappedi); wght[facei].resize(1, 1.0); } } } // Grab inserted faces (for them the size of addressing is still zero) insertedObjectsPtr_ = std::make_unique(); auto& inserted = *insertedObjectsPtr_; // The nInsertedObjects_ already counted in the constructor if (nInsertedObjects_) { inserted.resize(nInsertedObjects_); label nInserted = 0; forAll(addr, i) { if (addr[i].empty()) { // Mapped from dummy face 0 addr[i].resize(1, 0); wght[i].resize(1, 1.0); inserted[nInserted] = i; ++nInserted; // TBD: check (nInsertedObjects_ < nInserted)? #ifdef FULLDEBUG if (nInsertedObjects_ < nInserted) { FatalErrorInFunction << "Unexpected insert of more than " << nInsertedObjects_ << " items\n" << abort(FatalError); } #endif } } // TBD: check (nInserted < nInsertedObjects_)? #ifdef FULLDEBUG if (nInserted < nInsertedObjects_) { WarningInFunction << "Found " << nInserted << " instead of " << nInsertedObjects_ << " items to insert\n"; } #endif // The resize should be unnecessary inserted.resize(nInserted); } } } // void Foam::faceMapper::clearOut() // { // directAddrPtr_.reset(nullptr); // interpAddrPtr_.reset(nullptr); // weightsPtr_.reset(nullptr); // insertedObjectsPtr_.reset(nullptr); // } // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::faceMapper::faceMapper(const mapPolyMesh& mpm) : mpm_(mpm), mapperLen_(mpm.mesh().nFaces()), nInsertedObjects_(0), direct_ ( // Mapping without interpolation? mpm.facesFromPointsMap().empty() && mpm.facesFromEdgesMap().empty() && mpm.facesFromFacesMap().empty() ) { const auto& directMap = mpm_.faceMap(); if (!mapperLen_) { // Empty mesh direct_ = true; nInsertedObjects_ = 0; } else if (direct_) { // Number of inserted faces (-ve values) nInsertedObjects_ = std::count_if ( directMap.cbegin(), directMap.cbegin(mapperLen_), [](label i) { return (i < 0); } ); } else { // Check if there are inserted faces with no owner // (check all lists) bitSet unmapped(mapperLen_, true); unmapped.unset(directMap); // direct mapped for (const auto& map : mpm_.facesFromPointsMap()) { if (!map.empty()) unmapped.unset(map.index()); } for (const auto& map : mpm_.facesFromEdgesMap()) { if (!map.empty()) unmapped.unset(map.index()); } for (const auto& map : mpm_.facesFromFacesMap()) { if (!map.empty()) unmapped.unset(map.index()); } nInsertedObjects_ = label(unmapped.count()); } } // * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // Foam::faceMapper::~faceMapper() {} // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // Foam::label Foam::faceMapper::size() const { return mapperLen_; } Foam::label Foam::faceMapper::sizeBeforeMapping() const { return mpm_.nOldFaces(); } Foam::label Foam::faceMapper::internalSizeBeforeMapping() const { return mpm_.nOldInternalFaces(); } const Foam::labelUList& Foam::faceMapper::directAddressing() const { if (!direct()) { FatalErrorInFunction << "Requested direct addressing for an interpolative mapper." << abort(FatalError); } if (!insertedObjects()) { // No inserted faces. Re-use faceMap return mpm_.faceMap(); } else { if (!directAddrPtr_) { calcAddressing(); } return *directAddrPtr_; } } const Foam::labelListList& Foam::faceMapper::addressing() const { if (direct()) { FatalErrorInFunction << "Requested interpolative addressing for a direct mapper." << abort(FatalError); } if (!interpAddrPtr_) { calcAddressing(); } return *interpAddrPtr_; } const Foam::scalarListList& Foam::faceMapper::weights() const { if (direct()) { FatalErrorInFunction << "Requested interpolative weights for a direct mapper." << abort(FatalError); } if (!weightsPtr_) { calcAddressing(); } return *weightsPtr_; } const Foam::labelList& Foam::faceMapper::insertedObjectLabels() const { if (!insertedObjectsPtr_) { if (!nInsertedObjects_) { // No inserted objects will be created return labelList::null(); } calcAddressing(); } return *insertedObjectsPtr_; } const Foam::labelHashSet& Foam::faceMapper::flipFaceFlux() const { return mpm_.flipFaceFlux(); } Foam::label Foam::faceMapper::nOldInternalFaces() const { return mpm_.nOldInternalFaces(); } const Foam::labelList& Foam::faceMapper::oldPatchStarts() const { return mpm_.oldPatchStarts(); } const Foam::labelList& Foam::faceMapper::oldPatchSizes() const { return mpm_.oldPatchSizes(); } // ************************************************************************* //