FreeFOAM The Cross-Platform CFD Toolkit
Hosted by SourceForge:
Get FreeFOAM at SourceForge.net.
            Fast, secure and Free Open Source software downloads

FaceCellWave.C

Go to the documentation of this file.
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 \*---------------------------------------------------------------------------*/
00025 
00026 #include "FaceCellWave.H"
00027 #include <OpenFOAM/polyMesh.H>
00028 #include <OpenFOAM/processorPolyPatch.H>
00029 #include <OpenFOAM/cyclicPolyPatch.H>
00030 #include <OpenFOAM/OPstream.H>
00031 #include <OpenFOAM/IPstream.H>
00032 #include <OpenFOAM/PstreamReduceOps.H>
00033 #include <OpenFOAM/debug.H>
00034 #include <OpenFOAM/typeInfo.H>
00035 
00036 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
00037 
00038 template <class Type>
00039 const Foam::scalar Foam::FaceCellWave<Type>::geomTol_ = 1e-6;
00040 
00041 template <class Type>
00042 Foam::scalar Foam::FaceCellWave<Type>::propagationTol_ = 0.01;
00043 
00044 // Write to ostream
00045 template <class Type>
00046 Foam::Ostream& Foam::FaceCellWave<Type>::writeFaces
00047 (
00048     const label nFaces,
00049     const labelList& faceLabels,
00050     const List<Type>& faceInfo,
00051     Ostream& os
00052 )
00053 {
00054     // Write list contents depending on data format
00055     if (os.format() == IOstream::ASCII)
00056     {
00057         os << nFaces;
00058 
00059         for(label i = 0; i < nFaces; i++)
00060         {
00061             os << ' ' << faceLabels[i];
00062         }
00063         for(label i = 0; i < nFaces; i++)
00064         {
00065             os << ' ' << faceInfo[i];
00066         }
00067     }
00068     else
00069     {
00070         os << nFaces;
00071 
00072         for(label i = 0; i < nFaces; i++)
00073         {
00074             os << faceLabels[i];
00075         }
00076         for(label i = 0; i < nFaces; i++)
00077         {
00078             os << faceInfo[i];
00079         }
00080     }
00081     return os;
00082 }
00083 
00084 
00085 // Read from istream
00086 template <class Type>
00087 Foam::Istream& Foam::FaceCellWave<Type>::readFaces
00088 (
00089     label& nFaces,
00090     labelList& faceLabels,
00091     List<Type>& faceInfo,
00092     Istream& is
00093 )
00094 {
00095     is >> nFaces;
00096 
00097     for(label i = 0; i < nFaces; i++)
00098     {
00099         is >> faceLabels[i];
00100     }
00101     for(label i = 0; i < nFaces; i++)
00102     {
00103         is >> faceInfo[i];
00104     }
00105     return is;
00106 }
00107 
00108 
00109 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00110 
00111 // Update info for cellI, at position pt, with information from
00112 // neighbouring face/cell.
00113 // Updates:
00114 //      - changedCell_, changedCells_, nChangedCells_,
00115 //      - statistics: nEvals_, nUnvisitedCells_
00116 template <class Type>
00117 bool Foam::FaceCellWave<Type>::updateCell
00118 (
00119     const label cellI,
00120     const label neighbourFaceI,
00121     const Type& neighbourInfo,
00122     const scalar tol,
00123     Type& cellInfo
00124 )
00125 {
00126     nEvals_++;
00127 
00128     bool wasValid = cellInfo.valid();
00129 
00130     bool propagate =
00131         cellInfo.updateCell
00132         (
00133             mesh_,
00134             cellI,
00135             neighbourFaceI,
00136             neighbourInfo,
00137             tol
00138         );
00139 
00140     if (propagate)
00141     {
00142         if (!changedCell_[cellI])
00143         {
00144             changedCell_[cellI] = true;
00145             changedCells_[nChangedCells_++] = cellI;
00146         }
00147     }
00148 
00149     if (!wasValid && cellInfo.valid())
00150     {
00151         --nUnvisitedCells_;
00152     }
00153 
00154     return propagate;
00155 }
00156 
00157 
00158 // Update info for faceI, at position pt, with information from
00159 // neighbouring face/cell.
00160 // Updates:
00161 //      - changedFace_, changedFaces_, nChangedFaces_,
00162 //      - statistics: nEvals_, nUnvisitedFaces_
00163 template <class Type>
00164 bool Foam::FaceCellWave<Type>::updateFace
00165 (
00166     const label faceI,
00167     const label neighbourCellI,
00168     const Type& neighbourInfo,
00169     const scalar tol,
00170     Type& faceInfo
00171 )
00172 {
00173     nEvals_++;
00174 
00175     bool wasValid = faceInfo.valid();
00176 
00177     bool propagate =
00178         faceInfo.updateFace
00179         (
00180             mesh_,
00181             faceI,
00182             neighbourCellI,
00183             neighbourInfo,
00184             tol
00185         );
00186 
00187     if (propagate)
00188     {
00189         if (!changedFace_[faceI])
00190         {
00191             changedFace_[faceI] = true;
00192             changedFaces_[nChangedFaces_++] = faceI;
00193         }
00194     }
00195 
00196     if (!wasValid && faceInfo.valid())
00197     {
00198         --nUnvisitedFaces_;
00199     }
00200 
00201     return propagate;
00202 }
00203 
00204 
00205 // Update info for faceI, at position pt, with information from
00206 // same face.
00207 // Updates:
00208 //      - changedFace_, changedFaces_, nChangedFaces_,
00209 //      - statistics: nEvals_, nUnvisitedFaces_
00210 template <class Type>
00211 bool Foam::FaceCellWave<Type>::updateFace
00212 (
00213     const label faceI,
00214     const Type& neighbourInfo,
00215     const scalar tol,
00216     Type& faceInfo
00217 )
00218 {
00219     nEvals_++;
00220 
00221     bool wasValid = faceInfo.valid();
00222 
00223     bool propagate =
00224         faceInfo.updateFace
00225         (
00226             mesh_,
00227             faceI,
00228             neighbourInfo,
00229             tol
00230         );
00231 
00232     if (propagate)
00233     {
00234         if (!changedFace_[faceI])
00235         {
00236             changedFace_[faceI] = true;
00237             changedFaces_[nChangedFaces_++] = faceI;
00238         }
00239     }
00240 
00241     if (!wasValid && faceInfo.valid())
00242     {
00243         --nUnvisitedFaces_;
00244     }
00245 
00246     return propagate;
00247 }
00248 
00249 
00250 // For debugging: check status on both sides of cyclic
00251 template <class Type>
00252 void Foam::FaceCellWave<Type>::checkCyclic(const polyPatch& patch) const
00253 {
00254     label cycOffset = patch.size()/2;
00255 
00256     for(label patchFaceI = 0; patchFaceI < cycOffset; patchFaceI++)
00257     {
00258         label i1 = patch.start() + patchFaceI;
00259         label i2 = i1 + cycOffset;
00260 
00261         if (!allFaceInfo_[i1].sameGeometry(mesh_, allFaceInfo_[i2], geomTol_))
00262         {
00263             FatalErrorIn("FaceCellWave<Type>::checkCyclic(const polyPatch&)")
00264                 << "problem: i:" << i1 << "  otheri:" << i2
00265                 << "   faceInfo:" << allFaceInfo_[i1]
00266                 << "   otherfaceInfo:" << allFaceInfo_[i2]
00267                 << abort(FatalError);
00268         }
00269 
00270         if (changedFace_[i1] != changedFace_[i2])
00271         {
00272             FatalErrorIn("FaceCellWave<Type>::checkCyclic(const polyPatch&)")
00273                 << " problem: i:" << i1 << "  otheri:" << i2
00274                 << "   faceInfo:" << allFaceInfo_[i1]
00275                 << "   otherfaceInfo:" << allFaceInfo_[i2]
00276                 << "   changedFace:" << changedFace_[i1]
00277                 << "   otherchangedFace:" << changedFace_[i2]
00278                 << abort(FatalError);
00279         }
00280     }
00281 }
00282 
00283 
00284 // Check if has cyclic patches
00285 template <class Type>
00286 bool Foam::FaceCellWave<Type>::hasCyclicPatch() const
00287 {
00288     forAll(mesh_.boundaryMesh(), patchI)
00289     {
00290         if (isA<cyclicPolyPatch>(mesh_.boundaryMesh()[patchI]))
00291         {
00292             return true;
00293         }
00294     }
00295     return false;
00296 }
00297 
00298 
00299 // Copy face information into member data
00300 template <class Type>
00301 void Foam::FaceCellWave<Type>::setFaceInfo
00302 (
00303     const labelList& changedFaces,
00304     const List<Type>& changedFacesInfo
00305 )
00306 {
00307     forAll(changedFaces, changedFaceI)
00308     {
00309         label faceI = changedFaces[changedFaceI];
00310 
00311         bool wasValid = allFaceInfo_[faceI].valid();
00312 
00313         // Copy info for faceI
00314         allFaceInfo_[faceI] = changedFacesInfo[changedFaceI];
00315 
00316         // Maintain count of unset faces
00317         if (!wasValid && allFaceInfo_[faceI].valid())
00318         {
00319             --nUnvisitedFaces_;
00320         }
00321 
00322         // Mark faceI as changed, both on list and on face itself.
00323 
00324         changedFace_[faceI] = true;
00325         changedFaces_[nChangedFaces_++] = faceI;
00326     }
00327 }
00328 
00329 
00330 // Merge face information into member data
00331 template <class Type>
00332 void Foam::FaceCellWave<Type>::mergeFaceInfo
00333 (
00334     const polyPatch& patch,
00335     const label nFaces,
00336     const labelList& changedFaces,
00337     const List<Type>& changedFacesInfo,
00338     const bool
00339 )
00340 {
00341     for(label changedFaceI = 0; changedFaceI < nFaces; changedFaceI++)
00342     {
00343         const Type& neighbourWallInfo = changedFacesInfo[changedFaceI];
00344         label patchFaceI = changedFaces[changedFaceI];
00345 
00346         label meshFaceI = patch.start() + patchFaceI;
00347 
00348         Type& currentWallInfo = allFaceInfo_[meshFaceI];
00349 
00350         if (currentWallInfo != neighbourWallInfo)
00351         {
00352             updateFace
00353             (
00354                 meshFaceI,
00355                 neighbourWallInfo,
00356                 propagationTol_,
00357                 currentWallInfo
00358             );
00359         }
00360     }
00361 }
00362 
00363 
00364 // Construct compact patchFace change arrays for a (slice of a) single patch.
00365 // changedPatchFaces in local patch numbering.
00366 // Return length of arrays.
00367 template <class Type>
00368 Foam::label Foam::FaceCellWave<Type>::getChangedPatchFaces
00369 (
00370     const polyPatch& patch,
00371     const label startFaceI,
00372     const label nFaces,
00373     labelList& changedPatchFaces,
00374     List<Type>& changedPatchFacesInfo
00375 ) const
00376 {
00377     label nChangedPatchFaces = 0;
00378 
00379     for(label i = 0; i < nFaces; i++)
00380     {
00381         label patchFaceI = i + startFaceI;
00382 
00383         label meshFaceI = patch.start() + patchFaceI;
00384 
00385         if (changedFace_[meshFaceI])
00386         {
00387             changedPatchFaces[nChangedPatchFaces] = patchFaceI;
00388             changedPatchFacesInfo[nChangedPatchFaces] = allFaceInfo_[meshFaceI];
00389             nChangedPatchFaces++;
00390         }
00391     }
00392     return nChangedPatchFaces;
00393 }
00394 
00395 
00396 // Handle leaving domain. Implementation referred to Type
00397 template <class Type>
00398 void Foam::FaceCellWave<Type>::leaveDomain
00399 (
00400     const polyPatch& patch,
00401     const label nFaces,
00402     const labelList& faceLabels,
00403     List<Type>& faceInfo
00404 ) const
00405 {
00406     const vectorField& fc = mesh_.faceCentres();
00407 
00408     for(label i = 0; i < nFaces; i++)
00409     {
00410         label patchFaceI = faceLabels[i];
00411 
00412         label meshFaceI = patch.start() + patchFaceI;
00413         faceInfo[i].leaveDomain(mesh_, patch, patchFaceI, fc[meshFaceI]);
00414     }
00415 }
00416 
00417 
00418 // Handle entering domain. Implementation referred to Type
00419 template <class Type>
00420 void Foam::FaceCellWave<Type>::enterDomain
00421 (
00422     const polyPatch& patch,
00423     const label nFaces,
00424     const labelList& faceLabels,
00425     List<Type>& faceInfo
00426 ) const
00427 {
00428     const vectorField& fc = mesh_.faceCentres();
00429 
00430     for(label i = 0; i < nFaces; i++)
00431     {
00432         label patchFaceI = faceLabels[i];
00433 
00434         label meshFaceI = patch.start() + patchFaceI;
00435         faceInfo[i].enterDomain(mesh_, patch, patchFaceI, fc[meshFaceI]);
00436     }
00437 }
00438 
00439 
00440 // Transform. Implementation referred to Type
00441 template <class Type>
00442 void Foam::FaceCellWave<Type>::transform
00443 (
00444     const tensorField& rotTensor,
00445     const label nFaces,
00446     List<Type>& faceInfo
00447 )
00448 {
00449     if (rotTensor.size() == 1)
00450     {
00451         const tensor& T = rotTensor[0];
00452 
00453         for(label faceI = 0; faceI < nFaces; faceI++)
00454         {
00455             faceInfo[faceI].transform(mesh_, T);
00456         }
00457     }
00458     else
00459     {
00460         for(label faceI = 0; faceI < nFaces; faceI++)
00461         {
00462             faceInfo[faceI].transform(mesh_, rotTensor[faceI]);
00463         }
00464     }
00465 }
00466 
00467 
00468 // Send face info to neighbour.
00469 template <class Type>
00470 void Foam::FaceCellWave<Type>::sendPatchInfo
00471 (
00472     const label neighbour,
00473     const label nFaces,
00474     const labelList& faceLabels,
00475     const List<Type>& faceInfo
00476 ) const
00477 {
00478     OPstream toNeighbour(Pstream::blocking, neighbour);
00479 
00480     writeFaces(nFaces, faceLabels, faceInfo, toNeighbour);
00481 }
00482 
00483 
00484 // Receive face info from neighbour
00485 template <class Type>
00486 Foam::label Foam::FaceCellWave<Type>::receivePatchInfo
00487 (
00488     const label neighbour,
00489     labelList& faceLabels,
00490     List<Type>& faceInfo
00491 ) const
00492 {
00493     IPstream fromNeighbour(Pstream::blocking, neighbour);
00494 
00495     label nFaces = 0;
00496     readFaces(nFaces, faceLabels, faceInfo, fromNeighbour);
00497 
00498     return nFaces;
00499 }
00500 
00501 
00502 // Offset mesh face. Used for transferring from one cyclic half to the other.
00503 template <class Type>
00504 void Foam::FaceCellWave<Type>::offset
00505 (
00506     const polyPatch&,
00507     const label cycOffset,
00508     const label nFaces,
00509     labelList& faces
00510 )
00511 {
00512     for(label faceI = 0; faceI < nFaces; faceI++)
00513     {
00514         faces[faceI] += cycOffset;
00515     }
00516 }
00517 
00518 
00519 // Tranfer all the information to/from neighbouring processors
00520 template <class Type>
00521 void Foam::FaceCellWave<Type>::handleProcPatches()
00522 {
00523     // Send all
00524 
00525     forAll(mesh_.boundaryMesh(), patchI)
00526     {
00527         const polyPatch& patch = mesh_.boundaryMesh()[patchI];
00528 
00529         if (isA<processorPolyPatch>(patch))
00530         {
00531             // Allocate buffers
00532             label nSendFaces;
00533             labelList sendFaces(patch.size());
00534             List<Type> sendFacesInfo(patch.size());
00535 
00536             // Determine which faces changed on current patch
00537             nSendFaces = getChangedPatchFaces
00538             (
00539                 patch,
00540                 0,
00541                 patch.size(),
00542                 sendFaces,
00543                 sendFacesInfo
00544             );
00545 
00546             // Adapt wallInfo for leaving domain
00547             leaveDomain
00548             (
00549                 patch,
00550                 nSendFaces,
00551                 sendFaces,
00552                 sendFacesInfo
00553             );
00554 
00555             const processorPolyPatch& procPatch =
00556                 refCast<const processorPolyPatch>(patch);
00557 
00558             if (debug)
00559             {
00560                 Pout<< " Processor patch " << patchI << ' ' << patch.name()
00561                     << " communicating with " << procPatch.neighbProcNo()
00562                     << "  Sending:" << nSendFaces
00563                     << endl;
00564             }
00565 
00566             sendPatchInfo
00567             (
00568                 procPatch.neighbProcNo(),
00569                 nSendFaces,
00570                 sendFaces,
00571                 sendFacesInfo
00572             );
00573         }
00574     }
00575 
00576     // Receive all
00577 
00578     forAll(mesh_.boundaryMesh(), patchI)
00579     {
00580         const polyPatch& patch = mesh_.boundaryMesh()[patchI];
00581 
00582         if (isA<processorPolyPatch>(patch))
00583         {
00584             const processorPolyPatch& procPatch =
00585                 refCast<const processorPolyPatch>(patch);
00586 
00587             // Allocate buffers
00588             label nReceiveFaces;
00589             labelList receiveFaces(patch.size());
00590             List<Type> receiveFacesInfo(patch.size());
00591 
00592             nReceiveFaces = receivePatchInfo
00593             (
00594                 procPatch.neighbProcNo(),
00595                 receiveFaces,
00596                 receiveFacesInfo
00597             );
00598 
00599             if (debug)
00600             {
00601                 Pout<< " Processor patch " << patchI << ' ' << patch.name()
00602                     << " communicating with " << procPatch.neighbProcNo()
00603                     << "  Receiving:" << nReceiveFaces
00604                     << endl;
00605             }
00606 
00607             // Apply transform to received data for non-parallel planes
00608             if (!procPatch.parallel())
00609             {
00610                 transform
00611                 (
00612                     procPatch.forwardT(),
00613                     nReceiveFaces,
00614                     receiveFacesInfo
00615                 );
00616             }
00617 
00618             // Adapt wallInfo for entering domain
00619             enterDomain
00620             (
00621                 patch,
00622                 nReceiveFaces,
00623                 receiveFaces,
00624                 receiveFacesInfo
00625             );
00626 
00627             // Merge received info
00628             mergeFaceInfo
00629             (
00630                 patch,
00631                 nReceiveFaces,
00632                 receiveFaces,
00633                 receiveFacesInfo,
00634                 procPatch.parallel()
00635             );
00636         }
00637     }
00638 }
00639 
00640 
00641 // Transfer information across cyclic halves.
00642 // Note: Cyclic is two patches in one: one side from 0..size/2 and other
00643 // side from size/2 .. size.
00644 template <class Type>
00645 void Foam::FaceCellWave<Type>::handleCyclicPatches()
00646 {
00647     forAll(mesh_.boundaryMesh(), patchI)
00648     {
00649         const polyPatch& patch = mesh_.boundaryMesh()[patchI];
00650 
00651         if (isA<cyclicPolyPatch>(patch))
00652         {
00653             label halfSize = patch.size()/2;
00654 
00655             // Allocate buffers
00656             label nSendFaces;
00657             labelList sendFaces(halfSize);
00658             List<Type> sendFacesInfo(halfSize);
00659 
00660             label nReceiveFaces;
00661             labelList receiveFaces(halfSize);
00662             List<Type> receiveFacesInfo(halfSize);
00663 
00664             // Half1: Determine which faces changed. Use sendFaces for storage
00665             nSendFaces = getChangedPatchFaces
00666             (
00667                 patch,
00668                 0,
00669                 halfSize,
00670                 sendFaces,
00671                 sendFacesInfo
00672             );
00673 
00674             // Half2: Determine which faces changed. Use receiveFaces_  ,,
00675             nReceiveFaces = getChangedPatchFaces
00676             (
00677                 patch,
00678                 halfSize,
00679                 halfSize,
00680                 receiveFaces,
00681                 receiveFacesInfo
00682             );
00683 
00684             //Info<< "Half1:" << endl;
00685             //writeFaces(nSendFaces, sendFaces, sendFacesInfo, Info);
00686             //Info<< endl;
00687             //
00688             //Info<< "Half2:" << endl;
00689             //writeFaces(nReceiveFaces, receiveFaces, receiveFacesInfo, Info);
00690             //Info<< endl;
00691 
00692 
00693             // Half1: Adapt wallInfo for leaving domain
00694             leaveDomain
00695             (
00696                 patch,
00697                 nSendFaces,
00698                 sendFaces,
00699                 sendFacesInfo
00700             );
00701             // Half2: Adapt wallInfo for leaving domain
00702             leaveDomain
00703             (
00704                 patch,
00705                 nReceiveFaces,
00706                 receiveFaces,
00707                 receiveFacesInfo
00708             );
00709 
00710             // Half1: 'transfer' to other side by offsetting patchFaceI
00711             offset(patch, halfSize, nSendFaces, sendFaces);
00712 
00713             // Half2: 'transfer' to other side
00714             offset(patch, -halfSize, nReceiveFaces, receiveFaces);
00715 
00716             // Apply rotation for non-parallel planes
00717             const cyclicPolyPatch& cycPatch =
00718                 refCast<const cyclicPolyPatch>(patch);
00719 
00720             if (!cycPatch.parallel())
00721             {
00722                 // sendFaces = received data from half1
00723                 transform
00724                 (
00725                     cycPatch.reverseT(),
00726                     nSendFaces,
00727                     sendFacesInfo
00728                 );
00729 
00730                 // receiveFaces = received data from half2
00731                 transform
00732                 (
00733                     cycPatch.forwardT(),
00734                     nReceiveFaces,
00735                     receiveFacesInfo
00736                 );
00737             }
00738 
00739             if (debug)
00740             {
00741                 Pout<< " Cyclic patch " << patchI << ' ' << patch.name()
00742                     << "  Changed on first half : " << nSendFaces
00743                     << "  Changed on second half : " << nReceiveFaces
00744                     << endl;
00745             }
00746 
00747             // Half1: Adapt wallInfo for entering domain
00748             enterDomain
00749             (
00750                 patch,
00751                 nSendFaces,
00752                 sendFaces,
00753                 sendFacesInfo
00754             );
00755 
00756             // Half2: Adapt wallInfo for entering domain
00757             enterDomain
00758             (
00759                 patch,
00760                 nReceiveFaces,
00761                 receiveFaces,
00762                 receiveFacesInfo
00763             );
00764 
00765             // Merge into global storage
00766             mergeFaceInfo
00767             (
00768                 patch,
00769                 nSendFaces,
00770                 sendFaces,
00771                 sendFacesInfo,
00772                 cycPatch.parallel()
00773             );
00774             // Merge into global storage
00775             mergeFaceInfo
00776             (
00777                 patch,
00778                 nReceiveFaces,
00779                 receiveFaces,
00780                 receiveFacesInfo,
00781                 cycPatch.parallel()
00782             );
00783 
00784             if (debug)
00785             {
00786                 checkCyclic(patch);
00787             }
00788         }
00789     }
00790 }
00791 
00792 
00793 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00794 
00795 // Set up only. Use setFaceInfo and iterate() to do actual calculation.
00796 template <class Type>
00797 Foam::FaceCellWave<Type>::FaceCellWave
00798 (
00799     const polyMesh& mesh,
00800     UList<Type>& allFaceInfo,
00801     UList<Type>& allCellInfo
00802 )
00803 :
00804     mesh_(mesh),
00805     allFaceInfo_(allFaceInfo),
00806     allCellInfo_(allCellInfo),
00807     changedFace_(mesh_.nFaces(), false),
00808     changedFaces_(mesh_.nFaces()),
00809     nChangedFaces_(0),
00810     changedCell_(mesh_.nCells(), false),
00811     changedCells_(mesh_.nCells()),
00812     nChangedCells_(0),
00813     hasCyclicPatches_(hasCyclicPatch()),
00814     nEvals_(0),
00815     nUnvisitedCells_(mesh_.nCells()),
00816     nUnvisitedFaces_(mesh_.nFaces()),
00817     iter_(0)
00818 {}
00819 
00820 
00821 // Iterate, propagating changedFacesInfo across mesh, until no change (or
00822 // maxIter reached). Initial cell values specified.
00823 template <class Type>
00824 Foam::FaceCellWave<Type>::FaceCellWave
00825 (
00826     const polyMesh& mesh,
00827     const labelList& changedFaces,
00828     const List<Type>& changedFacesInfo,
00829     UList<Type>& allFaceInfo,
00830     UList<Type>& allCellInfo,
00831     const label maxIter
00832 )
00833 :
00834     mesh_(mesh),
00835     allFaceInfo_(allFaceInfo),
00836     allCellInfo_(allCellInfo),
00837     changedFace_(mesh_.nFaces(), false),
00838     changedFaces_(mesh_.nFaces()),
00839     nChangedFaces_(0),
00840     changedCell_(mesh_.nCells(), false),
00841     changedCells_(mesh_.nCells()),
00842     nChangedCells_(0),
00843     hasCyclicPatches_(hasCyclicPatch()),
00844     nEvals_(0),
00845     nUnvisitedCells_(mesh_.nCells()),
00846     nUnvisitedFaces_(mesh_.nFaces()),
00847     iter_(0)
00848 {
00849     // Copy initial changed faces data
00850     setFaceInfo(changedFaces, changedFacesInfo);
00851 
00852     // Iterate until nothing changes
00853     iterate(maxIter);
00854 
00855     if ((maxIter > 0) && (iter_ >= maxIter))
00856     {
00857         FatalErrorIn
00858         (
00859             "FaceCellWave<Type>::FaceCellWave"
00860             "(const polyMesh&, const labelList&, const List<Type>,"
00861             " UList<Type>&, UList<Type>&, const label maxIter)"
00862         )
00863             << "Maximum number of iterations reached. Increase maxIter." << endl
00864             << "    maxIter:" << maxIter << endl
00865             << "    nChangedCells:" << nChangedCells_ << endl
00866             << "    nChangedFaces:" << nChangedFaces_ << endl
00867             << exit(FatalError);
00868     }
00869 }
00870 
00871 
00872 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00873 
00874 
00875 template <class Type>
00876 Foam::label Foam::FaceCellWave<Type>::getUnsetCells() const
00877 {
00878     return nUnvisitedCells_;
00879 }
00880 
00881 
00882 template <class Type>
00883 Foam::label Foam::FaceCellWave<Type>::getUnsetFaces() const
00884 {
00885     return nUnvisitedFaces_;
00886 }
00887 
00888 
00889 
00890 // Propagate cell to face
00891 template <class Type>
00892 Foam::label Foam::FaceCellWave<Type>::faceToCell()
00893 {
00894     const labelList& owner = mesh_.faceOwner();
00895     const labelList& neighbour = mesh_.faceNeighbour();
00896     label nInternalFaces = mesh_.nInternalFaces();
00897 
00898     for
00899     (
00900         label changedFaceI = 0;
00901         changedFaceI < nChangedFaces_;
00902         changedFaceI++
00903     )
00904     {
00905         label faceI = changedFaces_[changedFaceI];
00906         if (!changedFace_[faceI])
00907         {
00908             FatalErrorIn("FaceCellWave<Type>::faceToCell()")
00909                 << "Face " << faceI
00910                 << " not marked as having been changed"
00911                 << abort(FatalError);
00912         }
00913 
00914 
00915         const Type& neighbourWallInfo = allFaceInfo_[faceI];
00916 
00917         // Evaluate all connected cells
00918 
00919         // Owner
00920         label cellI = owner[faceI];
00921         Type& currentWallInfo = allCellInfo_[cellI];
00922 
00923         if (currentWallInfo != neighbourWallInfo)
00924         {
00925             updateCell
00926             (
00927                 cellI,
00928                 faceI,
00929                 neighbourWallInfo,
00930                 propagationTol_,
00931                 currentWallInfo
00932             );
00933         }
00934 
00935         // Neighbour. Hack for check if face has neighbour.
00936         if (faceI < nInternalFaces)
00937         {
00938             cellI = neighbour[faceI];
00939             Type& currentWallInfo2 = allCellInfo_[cellI];
00940 
00941             if (currentWallInfo2 != neighbourWallInfo)
00942             {
00943                 updateCell
00944                 (
00945                     cellI,
00946                     faceI,
00947                     neighbourWallInfo,
00948                     propagationTol_,
00949                     currentWallInfo2
00950                 );
00951             }
00952         }
00953 
00954         // Reset status of face
00955         changedFace_[faceI] = false;
00956     }
00957 
00958     // Handled all changed faces by now
00959     nChangedFaces_ = 0;
00960 
00961     if (debug)
00962     {
00963         Pout<< " Changed cells            : " << nChangedCells_ << endl;
00964     }
00965 
00966     // Sum nChangedCells over all procs
00967     label totNChanged = nChangedCells_;
00968 
00969     reduce(totNChanged, sumOp<label>());
00970 
00971     return totNChanged;
00972 }
00973 
00974 
00975 // Propagate cell to face
00976 template <class Type>
00977 Foam::label Foam::FaceCellWave<Type>::cellToFace()
00978 {
00979     const cellList& cells = mesh_.cells();
00980 
00981     for
00982     (
00983         label changedCellI = 0;
00984         changedCellI < nChangedCells_;
00985         changedCellI++
00986     )
00987     {
00988         label cellI = changedCells_[changedCellI];
00989         if (!changedCell_[cellI])
00990         {
00991             FatalErrorIn("FaceCellWave<Type>::cellToFace()") << "Cell " << cellI
00992                 << " not marked as having been changed"
00993                 << abort(FatalError);
00994         }
00995 
00996         const Type& neighbourWallInfo = allCellInfo_[cellI];
00997 
00998         // Evaluate all connected faces
00999 
01000         const labelList& faceLabels = cells[cellI];
01001         forAll(faceLabels, faceLabelI)
01002         {
01003             label faceI = faceLabels[faceLabelI];
01004             Type& currentWallInfo = allFaceInfo_[faceI];
01005 
01006             if (currentWallInfo != neighbourWallInfo)
01007             {
01008                 updateFace
01009                 (
01010                     faceI,
01011                     cellI,
01012                     neighbourWallInfo,
01013                     propagationTol_,
01014                     currentWallInfo
01015                 );
01016             }
01017         }
01018 
01019         // Reset status of cell
01020         changedCell_[cellI] = false;
01021     }
01022 
01023     // Handled all changed cells by now
01024     nChangedCells_ = 0;
01025 
01026     if (hasCyclicPatches_)
01027     {
01028         // Transfer changed faces across cyclic halves
01029         handleCyclicPatches();
01030     }
01031     if (Pstream::parRun())
01032     {
01033         // Transfer changed faces from neighbouring processors.
01034         handleProcPatches();
01035     }
01036 
01037     if (debug)
01038     {
01039         Pout<< " Changed faces            : " << nChangedFaces_ << endl;
01040     }
01041 
01042     // Sum nChangedFaces over all procs
01043     label totNChanged = nChangedFaces_;
01044 
01045     reduce(totNChanged, sumOp<label>());
01046 
01047     return totNChanged;
01048 }
01049 
01050 
01051 // Iterate
01052 template <class Type>
01053 Foam::label Foam::FaceCellWave<Type>::iterate(const label maxIter)
01054 {
01055     if (hasCyclicPatches_)
01056     {
01057         // Transfer changed faces across cyclic halves
01058         handleCyclicPatches();
01059     }
01060     if (Pstream::parRun())
01061     {
01062         // Transfer changed faces from neighbouring processors.
01063         handleProcPatches();
01064     }
01065 
01066     while(iter_ < maxIter)
01067     {
01068         if (debug)
01069         {
01070             Pout<< " Iteration " << iter_ << endl;
01071         }
01072 
01073         nEvals_ = 0;
01074 
01075         label nCells = faceToCell();
01076 
01077         if (debug)
01078         {
01079             Pout<< " Total changed cells      : " << nCells << endl;
01080         }
01081 
01082         if (nCells == 0)
01083         {
01084             break;
01085         }
01086 
01087         label nFaces = cellToFace();
01088 
01089         if (debug)
01090         {
01091             Pout<< " Total changed faces      : " << nFaces << nl
01092                 << " Total evaluations        : " << nEvals_ << nl
01093                 << " Remaining unvisited cells: " << nUnvisitedCells_ << nl
01094                 << " Remaining unvisited faces: " << nUnvisitedFaces_ << endl;
01095         }
01096 
01097         if (nFaces == 0)
01098         {
01099             break;
01100         }
01101 
01102         ++iter_;
01103     }
01104 
01105     return nUnvisitedCells_;
01106 }
01107 
01108 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines