00001 /*---------------------------------------------------------------------------*\ 00002 ========= | 00003 \\ / F ield | OpenFOAM: The Open Source CFD Toolbox 00004 \\ / O peration | 00005 \\ / A nd | Copyright (C) 1991-2010 OpenCFD Ltd. 00006 \\/ M anipulation | 00007 ------------------------------------------------------------------------------- 00008 License 00009 This file is part of OpenFOAM. 00010 00011 OpenFOAM is free software: you can redistribute it and/or modify it 00012 under the terms of the GNU General Public License as published by 00013 the Free Software Foundation, either version 3 of the License, or 00014 (at your option) any later version. 00015 00016 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT 00017 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 00018 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 00019 for more details. 00020 00021 You should have received a copy of the GNU General Public License 00022 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. 00023 00024 Class 00025 Foam::faceCoupleInfo 00026 00027 Description 00028 Container for information needed to couple to meshes. When constructed 00029 from two meshes and a geometric tolerance finds the corresponding 00030 boundary faces. 00031 00032 The information it keeps is the set of faces&points (cutFaces, 00033 cutPoints) that should replace a set of faces on the master 00034 (masterPatch) and a set of faces on the slave (slavePatch) 00035 00036 00037 Uses same tolerance to match faces and points on matched faces since 00038 they both originate from the same points and the tolerance usually 00039 comes from writing these points with limited precision (6 by default) 00040 00041 -# Perfect match: 00042 - one-to-one match for faces and points. 00043 - the cut is always the 'most connected' of the master and slave so 00044 multiple master or slave points might point to the same cut point. 00045 00046 @verbatim 00047 e.g. master: 00048 00049 +--+ 00050 | | 00051 | | 00052 +--+ 00053 +--+ 00054 | | 00055 | | 00056 +--+ 00057 slave: 00058 +--+ 00059 | | 00060 | | 00061 +--+ 00062 +--+ 00063 | | 00064 | | 00065 +--+ 00066 @endverbatim 00067 adding both together creates a singly connected 2x2 cavity so suddenly 00068 the duplicate master points and the duplicate slave points all become 00069 a single cut point. 00070 00071 00072 -# Subdivision match: 00073 - Can be constructed from slave being subdivision of master with the 00074 polyPatch constructor. 00075 - Does not include above shared-point detection! 00076 00077 Notes on multiple slave faces per master: 00078 00079 As long as 00080 - all master edges are present in slave 00081 - slave can have extra edges/points/faces BUT all subfaces have to have 00082 at least one point on a maste face. 00083 00084 @verbatim 00085 So master: 00086 +-------+ 00087 | | 00088 | | 00089 | | 00090 | | 00091 | | 00092 | | 00093 | | 00094 +-------+ 00095 00096 slave: 00097 +---+---+ 00098 |\ | /| 00099 | \ | / | 00100 | \|/ | 00101 +---+---+ 00102 | /|\ | 00103 | / | \ | 00104 |/ | \| 00105 +---+---+ 00106 is ok. 00107 @endverbatim 00108 00109 For this kind of matching the order is: 00110 - match cutpoint to masterpoint 00111 - find those cutEdges that align with a master edge. This gives two sets 00112 of cut edges: those that have a master equivalent ('border edges') and 00113 those that don't ('internal edges'). The border edges now divide the 00114 cutFaces into regions with the same masterFace correspondence. 00115 - find cutFaces that are fully determined by the border edges they use. 00116 - all cutFaces that are connected through an internal edge have the same 00117 master face. 00118 00119 00120 Note: matching refined faces onto master is a bit dodgy and will probably 00121 only work for unwarped faces. Also it will fail if e.g. face is split 00122 into 3x3 since then middle face has no point/edge in common with master. 00123 (problem is in face matching (findSlavesCoveringMaster), probably 00124 point/edge matching might just work) 00125 00126 00127 SourceFiles 00128 faceCoupleInfo.C 00129 00130 00131 \*---------------------------------------------------------------------------*/ 00132 00133 #ifndef faceCoupleInfo_H 00134 #define faceCoupleInfo_H 00135 00136 #include <OpenFOAM/pointField.H> 00137 #include <OpenFOAM/indirectPrimitivePatch.H> 00138 #include <OpenFOAM/primitiveFacePatch.H> 00139 00140 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 00141 00142 namespace Foam 00143 { 00144 00145 typedef HashTable<labelList, edge, Hash<edge> > edgeLookup; 00146 00147 00148 // Forward declaration of classes 00149 class face; 00150 class primitiveMesh; 00151 class polyPatch; 00152 class polyMesh; 00153 00154 /*---------------------------------------------------------------------------*\ 00155 Class faceCoupleInfo Declaration 00156 \*---------------------------------------------------------------------------*/ 00157 00158 class faceCoupleInfo 00159 { 00160 // Private data 00161 00162 //- Angle matching tolerance. 00163 static const scalar angleTol_; 00164 00165 //- Master patch 00166 autoPtr<indirectPrimitivePatch> masterPatchPtr_; 00167 00168 //- Slave patch 00169 autoPtr<indirectPrimitivePatch> slavePatchPtr_; 00170 00171 00172 //- Description of cut. 00173 // - Cut is the matching area between the slave 00174 // and the master. 00175 // - cut is the finest of master and slave. It can never be 00176 // coarser than either one of them. (so face addressing we keep is 00177 // cut-to-master and cut-to-slave) 00178 // - multiple master or slave points can end up becoming one cut point 00179 // (so point addressing we keep is master-to-cut and slave-to-cut) 00180 00181 // Cut consists of faces and points (note: could be expressed as some 00182 // kind of PrimitivePatch which holds points instead of reference to 00183 // them) 00184 // Orientation of cutFaces should be same as masterFaces! 00185 pointField cutPoints_; 00186 autoPtr<primitiveFacePatch> cutFacesPtr_; 00187 00188 //- Additional point coupling information. Is between points on 00189 // boundary of both meshes. 00190 00191 // Addressing to/from cut 00192 00193 //- master 00194 labelList cutToMasterFaces_; 00195 labelList masterToCutPoints_; 00196 00197 //- slave 00198 labelList cutToSlaveFaces_; 00199 labelList slaveToCutPoints_; 00200 00201 //- For edges originating from splitting of edges: 00202 // given the two endpoints of the unsplit edge give the list 00203 // of inbetween vertices 00204 edgeLookup cutEdgeToPoints_; 00205 00206 00207 // Private Member Functions 00208 00209 // Debugging 00210 00211 //- Calculate face centres from (subset of) faces. 00212 template<template<class> class FaceList> 00213 static pointField calcFaceCentres 00214 ( 00215 const FaceList<face>&, 00216 const pointField&, 00217 const label start, 00218 const label size 00219 ); 00220 00221 //- Write edges 00222 static void writeOBJ 00223 ( 00224 const fileName& fName, 00225 const edgeList& edges, 00226 const pointField& points, 00227 const bool compact = true 00228 ); 00229 00230 //- Write edges 00231 static void writeOBJ 00232 ( 00233 const fileName& fName, 00234 const pointField& points0, 00235 const pointField& points1 00236 ); 00237 00238 //- Write connections between corresponding points and faces 00239 // as .obj files. 00240 void writePointsFaces() const; 00241 00242 //- Write connections between corresponding edges as .obj files. 00243 void writeEdges(const labelList&, const labelList&) const; 00244 00245 00246 // Edge handling/matching 00247 00248 //- Find corresponding edges on patch when having only a map for 00249 // the points. 00250 labelList findMappedEdges 00251 ( 00252 const edgeList& edges, 00253 const labelList& pointMap, 00254 const indirectPrimitivePatch& 00255 ); 00256 00257 //- Check if edge on slavePatch corresponds to an edge between faces 00258 // in two different polyPatches on the mesh. 00259 bool regionEdge(const polyMesh&, const label slaveEdgeI) const; 00260 00261 //- Finds edge connected to point most aligned with master edge. 00262 label mostAlignedCutEdge 00263 ( 00264 const bool report, 00265 const polyMesh& slaveMesh, 00266 const bool patchDivision, 00267 const labelList& cutToMasterEdges, 00268 const labelList& cutToSlaveEdges, 00269 const label pointI, 00270 const label edgeStart, 00271 const label edgeEnd 00272 ) const; 00273 00274 //- From (many-to-one) map of cut edges to master edges determine 00275 // points inbetween. I.e. just string up the edges. Stores this 00276 // all on cutEdgeToPoints_ 00277 void setCutEdgeToPoints(const labelList& cutToMasterEdges); 00278 00279 // Face matching 00280 00281 //- Matches two faces.Determines rotation for f1 to match up 00282 // with f0, i.e. the index in f0 of 00283 // the first point of f1. 00284 static label matchFaces 00285 ( 00286 const scalar absTol, 00287 const pointField& points0, 00288 const face& f0, 00289 const pointField& points1, 00290 const face& f1, 00291 const bool sameOrientation 00292 ); 00293 00294 //- Matches points on patch to points on cut. 00295 static bool matchPointsThroughFaces 00296 ( 00297 const scalar absTol, 00298 const pointField& cutPoints, 00299 const faceList& cutFaces, 00300 const pointField& patchPoints, 00301 const faceList& patchFaces, 00302 const bool sameOrientation, 00303 00304 labelList& patchToCutPoints, // patch to (uncompacted) cut points 00305 labelList& cutToCompact, // compaction list 00306 labelList& compactToCut // compaction list 00307 ); 00308 00309 //- Returns max distance to masterF of any point on cutF. 00310 static scalar maxDistance 00311 ( 00312 const face& cutF, 00313 const pointField& cutPoints, 00314 const face& masterF, 00315 const pointField& masterPoints 00316 ); 00317 00318 //- Finds matching (boundary)face centres. 00319 // Since faces identical uses geometric match on face centres. 00320 static void findPerfectMatchingFaces 00321 ( 00322 const primitiveMesh& mesh0, 00323 const primitiveMesh& mesh1, 00324 const scalar absTol, 00325 00326 labelList& mesh0Faces, 00327 labelList& mesh1Faces 00328 ); 00329 00330 //- Find matching (boundary)faces. Matching if slave is on top of 00331 // master face (slaves is subdivision of master) 00332 static void findSlavesCoveringMaster 00333 ( 00334 const primitiveMesh& mesh0, 00335 const primitiveMesh& mesh1, 00336 const scalar absTol, 00337 00338 labelList& mesh0Faces, 00339 labelList& mesh1Faces 00340 ); 00341 00342 //- Grow cutToMasterFace across 'internal' edges. 00343 label growCutFaces(const labelList&, Map<labelList>&); 00344 00345 void checkMatch(const labelList& cutToMasterEdges) const; 00346 00347 //- Gets a list of cutFaces (that use a master edge) and the 00348 // candidate master faces. 00349 // Checks among these master faces if there is only one remaining 00350 // unmatched one. 00351 label matchEdgeFaces(const labelList&, Map<labelList>& candidates); 00352 00353 //- Gets a list of cutFaces (that use a master edge) and the 00354 // candidate master faces. 00355 // Finds most aligned master face. 00356 label geometricMatchEdgeFaces(Map<labelList>& candidates); 00357 00358 //- Used by perfectPointMatch. Determine match from cut points to 00359 // slave points (for perfect matching faces) 00360 void perfectSlavePointMatch(const scalar absTol); 00361 00362 //- Find point and edge correspondence for perfect matching faces 00363 void perfectPointMatch(const scalar absTol, const bool); 00364 00365 //- Find point and edge correspondence for slaves being subdivision of 00366 // master. 00367 void subDivisionMatch 00368 ( 00369 const polyMesh& slaveMesh, 00370 const bool patchDivision, 00371 const scalar absTol 00372 ); 00373 00374 public: 00375 00376 //- Runtime type information 00377 ClassName("faceCoupleInfo"); 00378 00379 00380 // Constructors 00381 00382 //- Construct from two meshes and absolute tolerance. 00383 // Finds out matches geometrically. No checking for nonsense match. 00384 // Tolerance is absolute one so use with care. 00385 // perfectMatch : each point/edge/face has corresponding point on other 00386 // side 00387 // if this is false then assumes slave is subdivision. 00388 // Matching then will work only for non-warped faces 00389 // since does nearest-to-face comparison with absTol. 00390 faceCoupleInfo 00391 ( 00392 const polyMesh& mesh0, 00393 const polyMesh& mesh1, 00394 const scalar absTol, 00395 const bool perfectMatch 00396 ); 00397 00398 //- Construct from meshes and subset of mesh faces 00399 // (i.e. indirectPrimitivePatch addressing) 00400 // All faces in patch are considered matched (but don't have to be 00401 // ordered) 00402 // perfectMatch : each point/edge/face has corresponding point on other 00403 // side 00404 // orderedFaces : faces in patch are ordered (so masterAddressing[i] 00405 // matches slaveAddressing[i]) 00406 // patchDivision: faces in slave mesh that originate from the 00407 // same master face have the same patch. Used by some triangulation 00408 // methods. 00409 faceCoupleInfo 00410 ( 00411 const polyMesh& masterMesh, 00412 const labelList& masterAddressing, 00413 const polyMesh& slaveMesh, 00414 const labelList& slaveAddressing, 00415 const scalar absTol, 00416 const bool perfectMatch, 00417 const bool orderedFaces, 00418 const bool patchDivision 00419 ); 00420 00421 00422 // Destructor 00423 00424 ~faceCoupleInfo(); 00425 00426 00427 00428 // Member Functions 00429 00430 //- Utility functions 00431 00432 //- Get patch face labels 00433 static labelList faceLabels(const polyPatch&); 00434 00435 //- Create Map from List 00436 static Map<label> makeMap(const labelList&); 00437 static Map<labelList> makeMap(const labelListList&); 00438 00439 00440 // Access 00441 00442 //- Addressing engine for coupled faces on mesh0 00443 const indirectPrimitivePatch& masterPatch() const 00444 { 00445 return masterPatchPtr_(); 00446 } 00447 00448 //- Addressing engine for coupled faces on mesh1 00449 const indirectPrimitivePatch& slavePatch() const 00450 { 00451 return slavePatchPtr_(); 00452 } 00453 00454 //- Addressing engine for combined set of faces. 00455 const primitiveFacePatch& cutFaces() const 00456 { 00457 return cutFacesPtr_(); 00458 } 00459 00460 //- Points for combined set of faces. 00461 const pointField& cutPoints() const 00462 { 00463 return cutPoints_; 00464 } 00465 00466 00467 // Addressing from meshes to cut and vice versa. 00468 00469 //- Master face for every face on cut. Will always be at least 00470 // one but there might be multiple cut faces pointing to the same 00471 // master 00472 const labelList& cutToMasterFaces() const 00473 { 00474 return cutToMasterFaces_; 00475 } 00476 const labelList& masterToCutPoints() const 00477 { 00478 return masterToCutPoints_; 00479 } 00480 00481 const labelList& cutToSlaveFaces() const 00482 { 00483 return cutToSlaveFaces_; 00484 } 00485 const labelList& slaveToCutPoints() const 00486 { 00487 return slaveToCutPoints_; 00488 } 00489 00490 //- From two cut points (original edge) to list of inserted 00491 // points 00492 const edgeLookup& cutEdgeToPoints() const 00493 { 00494 return cutEdgeToPoints_; 00495 } 00496 00497 }; 00498 00499 00500 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 00501 00502 } // End namespace Foam 00503 00504 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 00505 00506 #ifdef NoRepository 00507 # include <dynamicMesh/faceCoupleInfoTemplates.C> 00508 #endif 00509 00510 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // 00511 00512 #endif 00513 00514 // ************************ vim: set sw=4 sts=4 et: ************************ //