/*---------------------------------------------------------------------------*\ ========= | \\ / 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 "PatchEdgeFaceWave.H" #include "polyMesh.H" #include "globalMeshData.H" #include "PatchTools.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // template < class PrimitivePatchType, class Type, class TrackingData > Foam::scalar Foam::PatchEdgeFaceWave:: propagationTol_ = 0.01; template < class PrimitivePatchType, class Type, class TrackingData > Foam::label Foam::PatchEdgeFaceWave:: dummyTrackData_ = 12345; // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // Update info for edgeI, at position pt, with information from // neighbouring face. // Updates: // - changedEdge_, changedEdges_, // - statistics: nEvals_, nUnvisitedEdges_ template < class PrimitivePatchType, class Type, class TrackingData > bool Foam::PatchEdgeFaceWave:: updateEdge ( const label edgeI, const label neighbourFacei, const Type& neighbourInfo, Type& edgeInfo ) { nEvals_++; bool wasValid = edgeInfo.valid(td_); bool propagate = edgeInfo.updateEdge ( mesh_, patch_, edgeI, neighbourFacei, neighbourInfo, propagationTol_, td_ ); if (propagate) { if (!changedEdge_[edgeI]) { changedEdge_[edgeI] = true; changedEdges_.append(edgeI); } } if (!wasValid && edgeInfo.valid(td_)) { --nUnvisitedEdges_; } return propagate; } // Update info for facei, at position pt, with information from // neighbouring edge. // Updates: // - changedFace_, changedFaces_, // - statistics: nEvals_, nUnvisitedFace_ template < class PrimitivePatchType, class Type, class TrackingData > bool Foam::PatchEdgeFaceWave:: updateFace ( const label facei, const label neighbourEdgeI, const Type& neighbourInfo, Type& faceInfo ) { nEvals_++; bool wasValid = faceInfo.valid(td_); bool propagate = faceInfo.updateFace ( mesh_, patch_, facei, neighbourEdgeI, neighbourInfo, propagationTol_, td_ ); if (propagate) { if (!changedFace_[facei]) { changedFace_[facei] = true; changedFaces_.append(facei); } } if (!wasValid && faceInfo.valid(td_)) { --nUnvisitedFaces_; } return propagate; } template < class PrimitivePatchType, class Type, class TrackingData > void Foam::PatchEdgeFaceWave:: syncEdges() { const globalMeshData& globalData = mesh_.globalData(); const mapDistribute& map = globalData.globalEdgeSlavesMap(); const PackedBoolList& cppOrientation = globalData.globalEdgeOrientation(); // Convert patch-edge data into cpp-edge data // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //- Construct with all data in consistent orientation List cppEdgeData(map.constructSize()); forAll(patchEdges_, i) { label patchEdgeI = patchEdges_[i]; label coupledEdgeI = coupledEdges_[i]; if (changedEdge_[patchEdgeI]) { const Type& data = allEdgeInfo_[patchEdgeI]; // Patch-edge data needs to be converted into coupled-edge data // (optionally flipped) and consistent in orientation with // master of coupled edge (optionally flipped) bool sameOrientation = ( sameEdgeOrientation_[i] == cppOrientation[coupledEdgeI] ); cppEdgeData[coupledEdgeI].updateEdge ( mesh_, patch_, data, sameOrientation, propagationTol_, td_ ); } } // Synchronise // ~~~~~~~~~~~ globalData.syncData ( cppEdgeData, globalData.globalEdgeSlaves(), globalData.globalEdgeTransformedSlaves(), map, globalData.globalTransforms(), updateOp ( mesh_, patch_, propagationTol_, td_ ), transformOp ( mesh_, patch_, propagationTol_, td_ ) ); // Back from cpp-edge to patch-edge data // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ forAll(patchEdges_, i) { label patchEdgeI = patchEdges_[i]; label coupledEdgeI = coupledEdges_[i]; const Type& data = cppEdgeData[coupledEdgeI]; if (data.valid(td_)) { bool sameOrientation = ( sameEdgeOrientation_[i] == cppOrientation[coupledEdgeI] ); allEdgeInfo_[patchEdgeI].updateEdge ( mesh_, patch_, data, sameOrientation, propagationTol_, td_ ); if (!changedEdge_[patchEdgeI]) { changedEdges_.append(patchEdgeI); changedEdge_[patchEdgeI] = true; } } } } // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // // Iterate, propagating changedEdgesInfo across patch, until no change (or // maxIter reached). Initial edge values specified. template < class PrimitivePatchType, class Type, class TrackingData > Foam::PatchEdgeFaceWave:: PatchEdgeFaceWave ( const polyMesh& mesh, const PrimitivePatchType& patch, const labelList& changedEdges, const List& changedEdgesInfo, UList& allEdgeInfo, UList& allFaceInfo, const label maxIter, TrackingData& td ) : mesh_(mesh), patch_(patch), allEdgeInfo_(allEdgeInfo), allFaceInfo_(allFaceInfo), td_(td), changedEdge_(patch_.nEdges()), changedEdges_(patch_.size()), changedFace_(patch_.size()), changedFaces_(patch_.size()), nEvals_(0), nUnvisitedEdges_(patch_.nEdges()), nUnvisitedFaces_(patch_.size()) { // Calculate addressing between patch_ and mesh.globalData().coupledPatch() // for ease of synchronisation PatchTools::matchEdges ( patch_, mesh_.globalData().coupledPatch(), patchEdges_, coupledEdges_, sameEdgeOrientation_ ); if (allEdgeInfo_.size() != patch_.nEdges()) { FatalErrorInFunction << "size of edgeInfo work array is not equal to the number" << " of edges in the patch" << endl << " edgeInfo :" << allEdgeInfo_.size() << endl << " patch.nEdges:" << patch_.nEdges() << exit(FatalError); } if (allFaceInfo_.size() != patch_.size()) { FatalErrorInFunction << "size of edgeInfo work array is not equal to the number" << " of faces in the patch" << endl << " faceInfo :" << allFaceInfo_.size() << endl << " patch.size:" << patch_.size() << exit(FatalError); } // Set from initial changed edges data setEdgeInfo(changedEdges, changedEdgesInfo); if (debug) { Pout<< "Seed edges : " << changedEdges_.size() << endl; } // Iterate until nothing changes label iter = iterate(maxIter); if ((maxIter > 0) && (iter >= maxIter)) { FatalErrorInFunction << "Maximum number of iterations reached. Increase maxIter." << endl << " maxIter:" << maxIter << endl << " changedEdges:" << changedEdges_.size() << endl << " changedFaces:" << changedFaces_.size() << endl << exit(FatalError); } } template < class PrimitivePatchType, class Type, class TrackingData > Foam::PatchEdgeFaceWave:: PatchEdgeFaceWave ( const polyMesh& mesh, const PrimitivePatchType& patch, UList& allEdgeInfo, UList& allFaceInfo, TrackingData& td ) : mesh_(mesh), patch_(patch), allEdgeInfo_(allEdgeInfo), allFaceInfo_(allFaceInfo), td_(td), changedEdge_(patch_.nEdges()), changedEdges_(patch_.nEdges()), changedFace_(patch_.size()), changedFaces_(patch_.size()), nEvals_(0), nUnvisitedEdges_(patch_.nEdges()), nUnvisitedFaces_(patch_.size()) { // Calculate addressing between patch_ and mesh.globalData().coupledPatch() // for ease of synchronisation PatchTools::matchEdges ( patch_, mesh_.globalData().coupledPatch(), patchEdges_, coupledEdges_, sameEdgeOrientation_ ); } // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // template < class PrimitivePatchType, class Type, class TrackingData > Foam::label Foam::PatchEdgeFaceWave:: getUnsetEdges() const { return nUnvisitedEdges_; } template < class PrimitivePatchType, class Type, class TrackingData > Foam::label Foam::PatchEdgeFaceWave:: getUnsetFaces() const { return nUnvisitedFaces_; } // Copy edge information into member data template < class PrimitivePatchType, class Type, class TrackingData > void Foam::PatchEdgeFaceWave:: setEdgeInfo ( const labelList& changedEdges, const List& changedEdgesInfo ) { forAll(changedEdges, changedEdgeI) { label edgeI = changedEdges[changedEdgeI]; bool wasValid = allEdgeInfo_[edgeI].valid(td_); // Copy info for edgeI allEdgeInfo_[edgeI] = changedEdgesInfo[changedEdgeI]; // Maintain count of unset edges if (!wasValid && allEdgeInfo_[edgeI].valid(td_)) { --nUnvisitedEdges_; } // Mark edgeI as changed, both on list and on edge itself. if (!changedEdge_[edgeI]) { changedEdge_[edgeI] = true; changedEdges_.append(edgeI); } } } // Propagate information from face to edge. Return number of edges changed. template < class PrimitivePatchType, class Type, class TrackingData > Foam::label Foam::PatchEdgeFaceWave:: faceToEdge() { changedEdges_.clear(); changedEdge_ = false; forAll(changedFaces_, changedFacei) { label facei = changedFaces_[changedFacei]; if (!changedFace_[facei]) { FatalErrorInFunction << "face " << facei << " not marked as having been changed" << nl << "This might be caused by multiple occurences of the same" << " seed edge." << abort(FatalError); } const Type& neighbourWallInfo = allFaceInfo_[facei]; // Evaluate all connected edges const labelList& fEdges = patch_.faceEdges()[facei]; forAll(fEdges, fEdgeI) { label edgeI = fEdges[fEdgeI]; Type& currentWallInfo = allEdgeInfo_[edgeI]; if (!currentWallInfo.equal(neighbourWallInfo, td_)) { updateEdge ( edgeI, facei, neighbourWallInfo, currentWallInfo ); } } } syncEdges(); if (debug) { Pout<< "Changed edges : " << changedEdges_.size() << endl; } return returnReduce(changedEdges_.size(), sumOp