/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2004-2010 OpenCFD Ltd. \\/ 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 "faceCoupleInfo.H" #include "polyMesh.H" #include "matchPoints.H" #include "indirectPrimitivePatch.H" #include "meshTools.H" #include "treeDataFace.H" #include "indexedOctree.H" #include "OFstream.H" // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // defineTypeNameAndDebug(Foam::faceCoupleInfo, 0); const Foam::scalar Foam::faceCoupleInfo::angleTol_ = 1E-3; // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // //- Write edges void Foam::faceCoupleInfo::writeOBJ ( const fileName& fName, const edgeList& edges, const pointField& points, const bool compact ) { OFstream str(fName); labelList pointMap(points.size(), -1); if (compact) { label newPointI = 0; forAll(edges, edgeI) { const edge& e = edges[edgeI]; forAll(e, eI) { label pointI = e[eI]; if (pointMap[pointI] == -1) { pointMap[pointI] = newPointI++; meshTools::writeOBJ(str, points[pointI]); } } } } else { forAll(points, pointI) { meshTools::writeOBJ(str, points[pointI]); } pointMap = identity(points.size()); } forAll(edges, edgeI) { const edge& e = edges[edgeI]; str<< "l " << pointMap[e[0]]+1 << ' ' << pointMap[e[1]]+1 << nl; } } //- Writes edges. void Foam::faceCoupleInfo::writeOBJ ( const fileName& fName, const pointField& points0, const pointField& points1 ) { Pout<< "Writing connections as edges to " << fName << endl; OFstream str(fName); label vertI = 0; forAll(points0, i) { meshTools::writeOBJ(str, points0[i]); vertI++; meshTools::writeOBJ(str, points1[i]); vertI++; str << "l " << vertI-1 << ' ' << vertI << nl; } } //- Writes face and point connectivity as .obj files. void Foam::faceCoupleInfo::writePointsFaces() const { const indirectPrimitivePatch& m = masterPatch(); const indirectPrimitivePatch& s = slavePatch(); const primitiveFacePatch& c = cutFaces(); // Patches { OFstream str("masterPatch.obj"); Pout<< "Writing masterPatch to " << str.name() << endl; meshTools::writeOBJ(str, m.localFaces(), m.localPoints()); } { OFstream str("slavePatch.obj"); Pout<< "Writing slavePatch to " << str.name() << endl; meshTools::writeOBJ(str, s.localFaces(), s.localPoints()); } { OFstream str("cutFaces.obj"); Pout<< "Writing cutFaces to " << str.name() << endl; meshTools::writeOBJ(str, c.localFaces(), c.localPoints()); } // Point connectivity { Pout<< "Writing cutToMasterPoints to cutToMasterPoints.obj" << endl; writeOBJ ( "cutToMasterPoints.obj", m.localPoints(), pointField(c.localPoints(), masterToCutPoints_)); } { Pout<< "Writing cutToSlavePoints to cutToSlavePoints.obj" << endl; writeOBJ ( "cutToSlavePoints.obj", s.localPoints(), pointField(c.localPoints(), slaveToCutPoints_) ); } // Face connectivity { Pout<< "Writing cutToMasterFaces to cutToMasterFaces.obj" << endl; pointField equivMasterFaces(c.size()); forAll(cutToMasterFaces(), cutFaceI) { label masterFaceI = cutToMasterFaces()[cutFaceI]; if (masterFaceI != -1) { equivMasterFaces[cutFaceI] = m[masterFaceI].centre(m.points()); } else { WarningIn("writePointsFaces()") << "No master face for cut face " << cutFaceI << " at position " << c[cutFaceI].centre(c.points()) << endl; equivMasterFaces[cutFaceI] = vector::zero; } } writeOBJ ( "cutToMasterFaces.obj", calcFaceCentres(c, cutPoints(), 0, c.size()), equivMasterFaces ); } { Pout<< "Writing cutToSlaveFaces to cutToSlaveFaces.obj" << endl; pointField equivSlaveFaces(c.size()); forAll(cutToSlaveFaces(), cutFaceI) { label slaveFaceI = cutToSlaveFaces()[cutFaceI]; equivSlaveFaces[cutFaceI] = s[slaveFaceI].centre(s.points()); } writeOBJ ( "cutToSlaveFaces.obj", calcFaceCentres(c, cutPoints(), 0, c.size()), equivSlaveFaces ); } Pout<< endl; } void Foam::faceCoupleInfo::writeEdges ( const labelList& cutToMasterEdges, const labelList& cutToSlaveEdges ) const { const indirectPrimitivePatch& m = masterPatch(); const indirectPrimitivePatch& s = slavePatch(); const primitiveFacePatch& c = cutFaces(); // Edge connectivity { OFstream str("cutToMasterEdges.obj"); Pout<< "Writing cutToMasterEdges to " << str.name() << endl; label vertI = 0; forAll(cutToMasterEdges, cutEdgeI) { if (cutToMasterEdges[cutEdgeI] != -1) { const edge& masterEdge = m.edges()[cutToMasterEdges[cutEdgeI]]; const edge& cutEdge = c.edges()[cutEdgeI]; meshTools::writeOBJ(str, m.localPoints()[masterEdge[0]]); vertI++; meshTools::writeOBJ(str, m.localPoints()[masterEdge[1]]); vertI++; meshTools::writeOBJ(str, c.localPoints()[cutEdge[0]]); vertI++; meshTools::writeOBJ(str, c.localPoints()[cutEdge[1]]); vertI++; str << "l " << vertI-3 << ' ' << vertI-2 << nl; str << "l " << vertI-3 << ' ' << vertI-1 << nl; str << "l " << vertI-3 << ' ' << vertI << nl; str << "l " << vertI-2 << ' ' << vertI-1 << nl; str << "l " << vertI-2 << ' ' << vertI << nl; str << "l " << vertI-1 << ' ' << vertI << nl; } } } { OFstream str("cutToSlaveEdges.obj"); Pout<< "Writing cutToSlaveEdges to " << str.name() << endl; label vertI = 0; labelList slaveToCut(invert(s.nEdges(), cutToSlaveEdges)); forAll(slaveToCut, edgeI) { if (slaveToCut[edgeI] != -1) { const edge& slaveEdge = s.edges()[edgeI]; const edge& cutEdge = c.edges()[slaveToCut[edgeI]]; meshTools::writeOBJ(str, s.localPoints()[slaveEdge[0]]); vertI++; meshTools::writeOBJ(str, s.localPoints()[slaveEdge[1]]); vertI++; meshTools::writeOBJ(str, c.localPoints()[cutEdge[0]]); vertI++; meshTools::writeOBJ(str, c.localPoints()[cutEdge[1]]); vertI++; str << "l " << vertI-3 << ' ' << vertI-2 << nl; str << "l " << vertI-3 << ' ' << vertI-1 << nl; str << "l " << vertI-3 << ' ' << vertI << nl; str << "l " << vertI-2 << ' ' << vertI-1 << nl; str << "l " << vertI-2 << ' ' << vertI << nl; str << "l " << vertI-1 << ' ' << vertI << nl; } } } Pout<< endl; } // Given an edgelist and a map for the points on the edges it tries to find // the corresponding patch edges. Foam::labelList Foam::faceCoupleInfo::findMappedEdges ( const edgeList& edges, const labelList& pointMap, const indirectPrimitivePatch& patch ) { labelList toPatchEdges(edges.size()); forAll(toPatchEdges, edgeI) { const edge& e = edges[edgeI]; label v0 = pointMap[e[0]]; label v1 = pointMap[e[1]]; toPatchEdges[edgeI] = meshTools::findEdge ( patch.edges(), patch.pointEdges()[v0], v0, v1 ); } return toPatchEdges; } // Detect a cut edge which originates from two boundary faces having different // polyPatches. bool Foam::faceCoupleInfo::regionEdge ( const polyMesh& slaveMesh, const label slaveEdgeI ) const { const labelList& eFaces = slavePatch().edgeFaces()[slaveEdgeI]; if (eFaces.size() == 1) { return true; } else { // Count how many different patches connected to this edge. label patch0 = -1; forAll(eFaces, i) { label faceI = eFaces[i]; label meshFaceI = slavePatch().addressing()[faceI]; label patchI = slaveMesh.boundaryMesh().whichPatch(meshFaceI); if (patch0 == -1) { patch0 = patchI; } else if (patchI != patch0) { // Found two different patches connected to this edge. return true; } } return false; } } // Find edge using pointI that is most aligned with vector between // master points. Patchdivision tells us whether or not to use // patch information to match edges. Foam::label Foam::faceCoupleInfo::mostAlignedCutEdge ( const bool report, const polyMesh& slaveMesh, const bool patchDivision, const labelList& cutToMasterEdges, const labelList& cutToSlaveEdges, const label pointI, const label edgeStart, const label edgeEnd ) const { const pointField& localPoints = cutFaces().localPoints(); const labelList& pEdges = cutFaces().pointEdges()[pointI]; if (report) { Pout<< "mostAlignedEdge : finding nearest edge among " << UIndirectList(cutFaces().edges(), pEdges)() << " connected to point " << pointI << " coord:" << localPoints[pointI] << " running between " << edgeStart << " coord:" << localPoints[edgeStart] << " and " << edgeEnd << " coord:" << localPoints[edgeEnd] << endl; } // Find the edge that gets us nearest end. label maxEdgeI = -1; scalar maxCos = -GREAT; forAll(pEdges, i) { label edgeI = pEdges[i]; if ( !( patchDivision && cutToMasterEdges[edgeI] == -1 ) || ( patchDivision && regionEdge(slaveMesh, cutToSlaveEdges[edgeI]) ) ) { const edge& e = cutFaces().edges()[edgeI]; label otherPointI = e.otherVertex(pointI); if (otherPointI == edgeEnd) { // Shortcut: found edge end point. if (report) { Pout<< " mostAlignedEdge : found end point " << edgeEnd << endl; } return edgeI; } // Get angle between edge and edge to masterEnd vector eVec(localPoints[otherPointI] - localPoints[pointI]); scalar magEVec = mag(eVec); if (magEVec < VSMALL) { WarningIn("faceCoupleInfo::mostAlignedEdge") << "Crossing zero sized edge " << edgeI << " coords:" << localPoints[otherPointI] << localPoints[pointI] << " when walking from " << localPoints[edgeStart] << " to " << localPoints[edgeEnd] << endl; return edgeI; } eVec /= magEVec; vector eToEndPoint(localPoints[edgeEnd] - localPoints[otherPointI]); eToEndPoint /= mag(eToEndPoint); scalar cosAngle = eVec & eToEndPoint; if (report) { Pout<< " edge:" << e << " points:" << localPoints[pointI] << localPoints[otherPointI] << " vec:" << eVec << " vecToEnd:" << eToEndPoint << " cosAngle:" << cosAngle << endl; } if (cosAngle > maxCos) { maxCos = cosAngle; maxEdgeI = edgeI; } } } if (maxCos > 1 - angleTol_) { return maxEdgeI; } else { return -1; } } // Construct points to split points map (in cut addressing) void Foam::faceCoupleInfo::setCutEdgeToPoints(const labelList& cutToMasterEdges) { labelListList masterToCutEdges ( invertOneToMany ( masterPatch().nEdges(), cutToMasterEdges ) ); const edgeList& cutEdges = cutFaces().edges(); // Size extra big so searching is faster cutEdgeToPoints_.resize ( masterPatch().nEdges() + slavePatch().nEdges() + cutEdges.size() ); forAll(masterToCutEdges, masterEdgeI) { const edge& masterE = masterPatch().edges()[masterEdgeI]; //Pout<< "Master:" << masterPatch().localPoints()[masterE[0]] << ' ' // << masterPatch().localPoints()[masterE[1]] << endl; const labelList& stringedEdges = masterToCutEdges[masterEdgeI]; if (stringedEdges.empty()) { FatalErrorIn ( "faceCoupleInfo::setCutEdgeToPoints" "(const labelList&)" ) << "Did not match all of master edges to cutFace edges" << nl << "First unmatched edge:" << masterEdgeI << " endPoints:" << masterPatch().localPoints()[masterE[0]] << masterPatch().localPoints()[masterE[1]] << endl << "This usually means that the slave patch is not a" << " subdivision of the master patch" << abort(FatalError); } else if (stringedEdges.size() > 1) { // String up the edges between e[0] and e[1]. Store the points // inbetween e[0] and e[1] (all in cutFaces() labels) DynamicList