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

syncToolsTemplates.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 "syncTools.H"
00027 #include <OpenFOAM/polyMesh.H>
00028 #include <OpenFOAM/processorPolyPatch.H>
00029 #include <OpenFOAM/cyclicPolyPatch.H>
00030 #include <OpenFOAM/globalMeshData.H>
00031 #include <OpenFOAM/contiguous.H>
00032 #include <OpenFOAM/transform.H>
00033 
00034 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00035 
00036 template <class T>
00037 void Foam::syncTools::separateList
00038 (
00039     const vectorField& separation,
00040     UList<T>& field
00041 )
00042 {}
00043 
00044 
00045 template <class T>
00046 void Foam::syncTools::separateList
00047 (
00048     const vectorField& separation,
00049     Map<T>& field
00050 )
00051 {}
00052 
00053 
00054 template <class T>
00055 void Foam::syncTools::separateList
00056 (
00057     const vectorField& separation,
00058     EdgeMap<T>& field
00059 )
00060 {}
00061 
00062 
00063 // Combine val with existing value at index
00064 template <class T, class CombineOp>
00065 void Foam::syncTools::combine
00066 (
00067     Map<T>& pointValues,
00068     const CombineOp& cop,
00069     const label index,
00070     const T& val
00071 )
00072 {
00073     typename Map<T>::iterator iter = pointValues.find(index);
00074 
00075     if (iter != pointValues.end())
00076     {
00077         cop(iter(), val);
00078     }
00079     else
00080     {
00081         pointValues.insert(index, val);
00082     }
00083 }
00084 
00085 
00086 // Combine val with existing value at (implicit index) e.
00087 template <class T, class CombineOp>
00088 void Foam::syncTools::combine
00089 (
00090     EdgeMap<T>& edgeValues,
00091     const CombineOp& cop,
00092     const edge& index,
00093     const T& val
00094 )
00095 {
00096     typename EdgeMap<T>::iterator iter = edgeValues.find(index);
00097 
00098     if (iter != edgeValues.end())
00099     {
00100         cop(iter(), val);
00101     }
00102     else
00103     {
00104         edgeValues.insert(index, val);
00105     }
00106 }
00107 
00108 
00109 template <class T, class CombineOp>
00110 void Foam::syncTools::syncPointMap
00111 (
00112     const polyMesh& mesh,
00113     Map<T>& pointValues,        // from mesh point label to value
00114     const CombineOp& cop,
00115     const bool applySeparation
00116 )
00117 {
00118     const polyBoundaryMesh& patches = mesh.boundaryMesh();
00119 
00120     if (!hasCouples(patches))
00121     {
00122         return;
00123     }
00124 
00125     // Is there any coupled patch with transformation?
00126     bool hasTransformation = false;
00127 
00128     if (Pstream::parRun())
00129     {
00130         // Send
00131 
00132         forAll(patches, patchI)
00133         {
00134             if
00135             (
00136                 isA<processorPolyPatch>(patches[patchI])
00137              && patches[patchI].nPoints() > 0
00138             )
00139             {
00140                 const processorPolyPatch& procPatch =
00141                     refCast<const processorPolyPatch>(patches[patchI]);
00142 
00143                 // Get data per patchPoint in neighbouring point numbers.
00144 
00145                 const labelList& meshPts = procPatch.meshPoints();
00146                 const labelList& nbrPts = procPatch.neighbPoints();
00147 
00148                 // Extract local values. Create map from nbrPoint to value.
00149                 // Note: how small initial size?
00150                 Map<T> patchInfo(meshPts.size() / 20);
00151 
00152                 forAll(meshPts, i)
00153                 {
00154                     typename Map<T>::const_iterator iter =
00155                         pointValues.find(meshPts[i]);
00156 
00157                     if (iter != pointValues.end())
00158                     {
00159                         if (nbrPts[i] >= 0)
00160                         {
00161                             patchInfo.insert(nbrPts[i], iter());
00162                         }
00163                     }
00164                 }
00165 
00166                 OPstream toNeighb(Pstream::blocking, procPatch.neighbProcNo());
00167                 toNeighb << patchInfo;
00168             }
00169         }
00170 
00171 
00172         // Receive and combine.
00173 
00174         forAll(patches, patchI)
00175         {
00176             if
00177             (
00178                 isA<processorPolyPatch>(patches[patchI])
00179              && patches[patchI].nPoints() > 0
00180             )
00181             {
00182                 const processorPolyPatch& procPatch =
00183                     refCast<const processorPolyPatch>(patches[patchI]);
00184                 checkTransform(procPatch, applySeparation);
00185 
00186                 IPstream fromNb(Pstream::blocking, procPatch.neighbProcNo());
00187                 Map<T> nbrPatchInfo(fromNb);
00188 
00189                 if (!procPatch.parallel())
00190                 {
00191                     hasTransformation = true;
00192                     transformList(procPatch.forwardT(), nbrPatchInfo);
00193                 }
00194                 else if (applySeparation && procPatch.separated())
00195                 {
00196                     hasTransformation = true;
00197                     separateList(-procPatch.separation(), nbrPatchInfo);
00198                 }
00199 
00200                 const labelList& meshPts = procPatch.meshPoints();
00201 
00202                 // Only update those values which come from neighbour
00203 
00204                 forAllConstIter
00205                 (
00206                     typename Map<T>,
00207                     nbrPatchInfo,
00208                     nbrIter
00209                 )
00210                 {
00211                     combine
00212                     (
00213                         pointValues,
00214                         cop,
00215                         meshPts[nbrIter.key()],
00216                         nbrIter()
00217                     );
00218                 }
00219             }
00220         }
00221     }
00222 
00223     // Do the cyclics.
00224     forAll(patches, patchI)
00225     {
00226         if (isA<cyclicPolyPatch>(patches[patchI]))
00227         {
00228             const cyclicPolyPatch& cycPatch =
00229                 refCast<const cyclicPolyPatch>(patches[patchI]);
00230             checkTransform(cycPatch, applySeparation);
00231 
00232             const edgeList& coupledPoints = cycPatch.coupledPoints();
00233             const labelList& meshPts = cycPatch.meshPoints();
00234 
00235             // Extract local values. Create map from nbrPoint to value.
00236             Map<T> half0Values(meshPts.size() / 20);
00237             Map<T> half1Values(meshPts.size() / 20);
00238 
00239             forAll(coupledPoints, i)
00240             {
00241                 const edge& e = coupledPoints[i];
00242 
00243                 typename Map<T>::const_iterator point0Fnd =
00244                     pointValues.find(meshPts[e[0]]);
00245 
00246                 if (point0Fnd != pointValues.end())
00247                 {
00248                     half0Values.insert(i, point0Fnd());
00249                 }
00250 
00251                 typename Map<T>::const_iterator point1Fnd =
00252                     pointValues.find(meshPts[e[1]]);
00253 
00254                 if (point1Fnd != pointValues.end())
00255                 {
00256                     half1Values.insert(i, point1Fnd());
00257                 }
00258             }
00259 
00260             if (!cycPatch.parallel())
00261             {
00262                 hasTransformation = true;
00263                 transformList(cycPatch.reverseT(), half0Values);
00264                 transformList(cycPatch.forwardT(), half1Values);
00265             }
00266             else if (applySeparation && cycPatch.separated())
00267             {
00268                 hasTransformation = true;
00269 
00270                 const vectorField& v = cycPatch.coupledPolyPatch::separation();
00271                 separateList(v, half0Values);
00272                 separateList(-v, half1Values);
00273             }
00274 
00275             forAll(coupledPoints, i)
00276             {
00277                 const edge& e = coupledPoints[i];
00278 
00279                 typename Map<T>::const_iterator half1Fnd = half1Values.find(i);
00280 
00281                 if (half1Fnd != half1Values.end())
00282                 {
00283                     combine
00284                     (
00285                         pointValues,
00286                         cop,
00287                         meshPts[e[0]],
00288                         half1Fnd()
00289                     );
00290                 }
00291 
00292                 typename Map<T>::const_iterator half0Fnd = half0Values.find(i);
00293 
00294                 if (half0Fnd != half0Values.end())
00295                 {
00296                     combine
00297                     (
00298                         pointValues,
00299                         cop,
00300                         meshPts[e[1]],
00301                         half0Fnd()
00302                     );
00303                 }
00304             }
00305         }
00306     }
00307 
00308     //- Note: hasTransformation is only used for warning messages so
00309     //  reduction not strictly nessecary.
00310     //reduce(hasTransformation, orOp<bool>());
00311 
00312     // Synchronize multiple shared points.
00313     const globalMeshData& pd = mesh.globalData();
00314 
00315     if (pd.nGlobalPoints() > 0)
00316     {
00317         if (hasTransformation)
00318         {
00319             WarningIn
00320             (
00321                 "syncTools<class T, class CombineOp>::syncPointMap"
00322                 "(const polyMesh&, Map<T>&, const CombineOp&"
00323                 ", const bool)"
00324             )   << "There are decomposed cyclics in this mesh with"
00325                 << " transformations." << endl
00326                 << "This is not supported. The result will be incorrect"
00327                 << endl;
00328         }
00329         // meshPoint per local index
00330         const labelList& sharedPtLabels = pd.sharedPointLabels();
00331         // global shared index per local index
00332         const labelList& sharedPtAddr = pd.sharedPointAddr();
00333 
00334         // Values on shared points. Keyed on global shared index.
00335         Map<T> sharedPointValues(sharedPtAddr.size());
00336 
00337 
00338         // Fill my entries in the shared points
00339         forAll(sharedPtLabels, i)
00340         {
00341             label meshPointI = sharedPtLabels[i];
00342 
00343             typename Map<T>::const_iterator fnd =
00344                 pointValues.find(meshPointI);
00345 
00346             if (fnd != pointValues.end())
00347             {
00348                 combine
00349                 (
00350                     sharedPointValues,
00351                     cop,
00352                     sharedPtAddr[i],    // index
00353                     fnd()               // value
00354                 );
00355             }
00356         }
00357 
00358         // Reduce on master.
00359 
00360         if (Pstream::parRun())
00361         {
00362             if (Pstream::master())
00363             {
00364                 // Receive the edges using shared points from the slave.
00365                 for
00366                 (
00367                     int slave=Pstream::firstSlave();
00368                     slave<=Pstream::lastSlave();
00369                     slave++
00370                 )
00371                 {
00372                     IPstream fromSlave(Pstream::blocking, slave);
00373                     Map<T> nbrValues(fromSlave);
00374 
00375                     // Merge neighbouring values with my values
00376                     forAllConstIter(typename Map<T>, nbrValues, iter)
00377                     {
00378                         combine
00379                         (
00380                             sharedPointValues,
00381                             cop,
00382                             iter.key(), // edge
00383                             iter()      // value
00384                         );
00385                     }
00386                 }
00387 
00388                 // Send back
00389                 for
00390                 (
00391                     int slave=Pstream::firstSlave();
00392                     slave<=Pstream::lastSlave();
00393                     slave++
00394                 )
00395                 {
00396                     OPstream toSlave(Pstream::blocking, slave);
00397                     toSlave << sharedPointValues;
00398                 }
00399             }
00400             else
00401             {
00402                 // Send to master
00403                 {
00404                     OPstream toMaster
00405                     (
00406                         Pstream::blocking,
00407                         Pstream::masterNo()
00408                     );
00409                     toMaster << sharedPointValues;
00410                 }
00411                 // Receive merged values
00412                 {
00413                     IPstream fromMaster
00414                     (
00415                         Pstream::blocking,
00416                         Pstream::masterNo()
00417                     );
00418                     fromMaster >> sharedPointValues;
00419                 }
00420             }
00421         }
00422 
00423 
00424         // Merge sharedPointValues (keyed on sharedPointAddr) into
00425         // pointValues (keyed on mesh points).
00426 
00427         // Map from global shared index to meshpoint
00428         Map<label> sharedToMeshPoint(2*sharedPtAddr.size());
00429         forAll(sharedPtAddr, i)
00430         {
00431             sharedToMeshPoint.insert(sharedPtAddr[i], sharedPtLabels[i]);
00432         }
00433 
00434         forAllConstIter(Map<label>, sharedToMeshPoint, iter)
00435         {
00436             // Do I have a value for my shared point
00437             typename Map<T>::const_iterator sharedFnd =
00438                 sharedPointValues.find(iter.key());
00439 
00440             if (sharedFnd != sharedPointValues.end())
00441             {
00442                 combine
00443                 (
00444                     pointValues,
00445                     cop,
00446                     iter(),     // index
00447                     sharedFnd() // value
00448                 );
00449             }
00450         }
00451     }
00452 }
00453 
00454 
00455 template <class T, class CombineOp>
00456 void Foam::syncTools::syncEdgeMap
00457 (
00458     const polyMesh& mesh,
00459     EdgeMap<T>& edgeValues,
00460     const CombineOp& cop,
00461     const bool applySeparation
00462 )
00463 {
00464     const polyBoundaryMesh& patches = mesh.boundaryMesh();
00465 
00466     if (!hasCouples(patches))
00467     {
00468         return;
00469     }
00470 
00471 
00472     // Do synchronisation without constructing globalEdge addressing
00473     // (since this constructs mesh edge addressing)
00474 
00475 
00476     // Swap proc patch info
00477     // ~~~~~~~~~~~~~~~~~~~~
00478 
00479     if (Pstream::parRun())
00480     {
00481         // Send
00482 
00483         forAll(patches, patchI)
00484         {
00485             if
00486             (
00487                 isA<processorPolyPatch>(patches[patchI])
00488              && patches[patchI].nEdges() > 0
00489             )
00490             {
00491                 const processorPolyPatch& procPatch =
00492                     refCast<const processorPolyPatch>(patches[patchI]);
00493 
00494                 // Get data per patch edge in neighbouring edge.
00495 
00496                 const edgeList& edges = procPatch.edges();
00497                 const labelList& meshPts = procPatch.meshPoints();
00498                 const labelList& nbrPts = procPatch.neighbPoints();
00499 
00500                 EdgeMap<T> patchInfo(edges.size() / 20);
00501 
00502                 forAll(edges, i)
00503                 {
00504                     const edge& e = edges[i];
00505                     const edge meshEdge(meshPts[e[0]], meshPts[e[1]]);
00506 
00507                     typename EdgeMap<T>::const_iterator iter =
00508                         edgeValues.find(meshEdge);
00509 
00510                     if (iter != edgeValues.end())
00511                     {
00512                         const edge nbrEdge(nbrPts[e[0]], nbrPts[e[1]]);
00513 
00514                         if (nbrEdge[0] >= 0 && nbrEdge[1] >= 0)
00515                         {
00516                             patchInfo.insert(nbrEdge, iter());
00517                         }
00518                     }
00519                 }
00520 
00521                 OPstream toNeighb(Pstream::blocking, procPatch.neighbProcNo());
00522                 toNeighb << patchInfo;
00523             }
00524         }
00525 
00526 
00527         // Receive and combine.
00528 
00529         forAll(patches, patchI)
00530         {
00531             if
00532             (
00533                 isA<processorPolyPatch>(patches[patchI])
00534              && patches[patchI].nEdges() > 0
00535             )
00536             {
00537                 const processorPolyPatch& procPatch =
00538                     refCast<const processorPolyPatch>(patches[patchI]);
00539                 checkTransform(procPatch, applySeparation);
00540 
00541                 const labelList& meshPts = procPatch.meshPoints();
00542 
00543                 IPstream fromNbr(Pstream::blocking, procPatch.neighbProcNo());
00544                 EdgeMap<T> nbrPatchInfo(fromNbr);
00545 
00546                 if (!procPatch.parallel())
00547                 {
00548                     transformList(procPatch.forwardT(), nbrPatchInfo);
00549                 }
00550                 else if (applySeparation && procPatch.separated())
00551                 {
00552                     separateList(-procPatch.separation(), nbrPatchInfo);
00553                 }
00554 
00555                 // Only update those values which come from neighbour
00556 
00557                 forAllConstIter
00558                 (
00559                     typename EdgeMap<T>,
00560                     nbrPatchInfo,
00561                     nbrIter
00562                 )
00563                 {
00564                     const edge& e = nbrIter.key();
00565                     const edge meshEdge(meshPts[e[0]], meshPts[e[1]]);
00566 
00567                     combine
00568                     (
00569                         edgeValues,
00570                         cop,
00571                         meshEdge,   // edge
00572                         nbrIter()   // value
00573                     );
00574                 }
00575             }
00576         }
00577     }
00578 
00579 
00580     // Swap cyclic info
00581     // ~~~~~~~~~~~~~~~~
00582 
00583     forAll(patches, patchI)
00584     {
00585         if (isA<cyclicPolyPatch>(patches[patchI]))
00586         {
00587             const cyclicPolyPatch& cycPatch =
00588                 refCast<const cyclicPolyPatch>(patches[patchI]);
00589             checkTransform(cycPatch, applySeparation);
00590 
00591             const edgeList& coupledEdges = cycPatch.coupledEdges();
00592             const labelList& meshPts = cycPatch.meshPoints();
00593             const edgeList& edges = cycPatch.edges();
00594 
00595             // Extract local values. Create map from nbrPoint to value.
00596             Map<T> half0Values(meshPts.size() / 20);
00597             Map<T> half1Values(meshPts.size() / 20);
00598 
00599             forAll(coupledEdges, i)
00600             {
00601                 const edge& twoEdges = coupledEdges[i];
00602 
00603                 {
00604                     const edge& e0 = edges[twoEdges[0]];
00605                     const edge meshEdge0(meshPts[e0[0]], meshPts[e0[1]]);
00606 
00607                     typename EdgeMap<T>::const_iterator iter =
00608                         edgeValues.find(meshEdge0);
00609 
00610                     if (iter != edgeValues.end())
00611                     {
00612                         half0Values.insert(i, iter());
00613                     }
00614                 }
00615                 {
00616                     const edge& e1 = edges[twoEdges[1]];
00617                     const edge meshEdge1(meshPts[e1[0]], meshPts[e1[1]]);
00618 
00619                     typename EdgeMap<T>::const_iterator iter =
00620                         edgeValues.find(meshEdge1);
00621 
00622                     if (iter != edgeValues.end())
00623                     {
00624                         half1Values.insert(i, iter());
00625                     }
00626                 }
00627             }
00628 
00629 
00630             // Transform
00631 
00632             if (!cycPatch.parallel())
00633             {
00634                 transformList(cycPatch.reverseT(), half0Values);
00635                 transformList(cycPatch.forwardT(), half1Values);
00636             }
00637             else if (applySeparation && cycPatch.separated())
00638             {
00639                 const vectorField& v = cycPatch.coupledPolyPatch::separation();
00640                 separateList(v, half0Values);
00641                 separateList(-v, half1Values);
00642             }
00643 
00644 
00645             // Extract and combine information
00646 
00647             forAll(coupledEdges, i)
00648             {
00649                 const edge& twoEdges = coupledEdges[i];
00650 
00651                 typename Map<T>::const_iterator half1Fnd =
00652                     half1Values.find(i);
00653 
00654                 if (half1Fnd != half1Values.end())
00655                 {
00656                     const edge& e0 = edges[twoEdges[0]];
00657                     const edge meshEdge0(meshPts[e0[0]], meshPts[e0[1]]);
00658 
00659                     combine
00660                     (
00661                         edgeValues,
00662                         cop,
00663                         meshEdge0,  // edge
00664                         half1Fnd()  // value
00665                     );
00666                 }
00667 
00668                 typename Map<T>::const_iterator half0Fnd =
00669                     half0Values.find(i);
00670                 if (half0Fnd != half0Values.end())
00671                 {
00672                     const edge& e1 = edges[twoEdges[1]];
00673                     const edge meshEdge1(meshPts[e1[0]], meshPts[e1[1]]);
00674 
00675                     combine
00676                     (
00677                         edgeValues,
00678                         cop,
00679                         meshEdge1,  // edge
00680                         half0Fnd()  // value
00681                     );
00682                 }
00683             }
00684         }
00685     }
00686 
00687     // Synchronize multiple shared points.
00688     // Problem is that we don't want to construct shared edges so basically
00689     // we do here like globalMeshData but then using sparse edge representation
00690     // (EdgeMap instead of mesh.edges())
00691 
00692     const globalMeshData& pd = mesh.globalData();
00693     const labelList& sharedPtAddr = pd.sharedPointAddr();
00694     const labelList& sharedPtLabels = pd.sharedPointLabels();
00695 
00696     // 1. Create map from meshPoint to globalShared index.
00697     Map<label> meshToShared(2*sharedPtLabels.size());
00698     forAll(sharedPtLabels, i)
00699     {
00700         meshToShared.insert(sharedPtLabels[i], sharedPtAddr[i]);
00701     }
00702 
00703     // Values on shared points. From two sharedPtAddr indices to a value.
00704     EdgeMap<T> sharedEdgeValues(meshToShared.size());
00705 
00706     // From shared edge to mesh edge. Used for merging later on.
00707     EdgeMap<edge> potentialSharedEdge(meshToShared.size());
00708 
00709     // 2. Find any edges using two global shared points. These will always be
00710     // on the outside of the mesh. (though might not be on coupled patch
00711     // if is single edge and not on coupled face)
00712     // Store value (if any) on sharedEdgeValues
00713     for (label faceI = mesh.nInternalFaces(); faceI < mesh.nFaces(); faceI++)
00714     {
00715         const face& f = mesh.faces()[faceI];
00716 
00717         forAll(f, fp)
00718         {
00719             label v0 = f[fp];
00720             label v1 = f[f.fcIndex(fp)];
00721 
00722             Map<label>::const_iterator v0Fnd = meshToShared.find(v0);
00723 
00724             if (v0Fnd != meshToShared.end())
00725             {
00726                 Map<label>::const_iterator v1Fnd = meshToShared.find(v1);
00727 
00728                 if (v1Fnd != meshToShared.end())
00729                 {
00730                     const edge meshEdge(v0, v1);
00731 
00732                     // edge in shared point labels
00733                     const edge sharedEdge(v0Fnd(), v1Fnd());
00734 
00735                     // Store mesh edge as a potential shared edge.
00736                     potentialSharedEdge.insert(sharedEdge, meshEdge);
00737 
00738                     typename EdgeMap<T>::const_iterator edgeFnd =
00739                         edgeValues.find(meshEdge);
00740 
00741                     if (edgeFnd != edgeValues.end())
00742                     {
00743                         // edge exists in edgeValues. See if already in map
00744                         // (since on same processor, e.g. cyclic)
00745                         combine
00746                         (
00747                             sharedEdgeValues,
00748                             cop,
00749                             sharedEdge, // edge
00750                             edgeFnd()   // value
00751                         );
00752                     }
00753                 }
00754             }
00755         }
00756     }
00757 
00758 
00759     // Now sharedEdgeValues will contain per potential sharedEdge the value.
00760     // (potential since an edge having two shared points is not nessecary a
00761     //  shared edge).
00762     // Reduce this on the master.
00763 
00764     if (Pstream::parRun())
00765     {
00766         if (Pstream::master())
00767         {
00768             // Receive the edges using shared points from the slave.
00769             for
00770             (
00771                 int slave=Pstream::firstSlave();
00772                 slave<=Pstream::lastSlave();
00773                 slave++
00774             )
00775             {
00776                 IPstream fromSlave(Pstream::blocking, slave);
00777                 EdgeMap<T> nbrValues(fromSlave);
00778 
00779                 // Merge neighbouring values with my values
00780                 forAllConstIter(typename EdgeMap<T>, nbrValues, iter)
00781                 {
00782                     combine
00783                     (
00784                         sharedEdgeValues,
00785                         cop,
00786                         iter.key(), // edge
00787                         iter()      // value
00788                     );
00789                 }
00790             }
00791 
00792             // Send back
00793             for
00794             (
00795                 int slave=Pstream::firstSlave();
00796                 slave<=Pstream::lastSlave();
00797                 slave++
00798             )
00799             {
00800 
00801                 OPstream toSlave(Pstream::blocking, slave);
00802                 toSlave << sharedEdgeValues;
00803             }
00804         }
00805         else
00806         {
00807             // Send to master
00808             {
00809                 OPstream toMaster(Pstream::blocking, Pstream::masterNo());
00810                 toMaster << sharedEdgeValues;
00811             }
00812             // Receive merged values
00813             {
00814                 IPstream fromMaster(Pstream::blocking, Pstream::masterNo());
00815                 fromMaster >> sharedEdgeValues;
00816             }
00817         }
00818     }
00819 
00820 
00821     // Merge sharedEdgeValues (keyed on sharedPointAddr) into edgeValues
00822     // (keyed on mesh points).
00823 
00824     // Loop over all my shared edges.
00825     forAllConstIter(typename EdgeMap<edge>, potentialSharedEdge, iter)
00826     {
00827         const edge& sharedEdge = iter.key();
00828         const edge& meshEdge = iter();
00829 
00830         // Do I have a value for the shared edge?
00831         typename EdgeMap<T>::const_iterator sharedFnd =
00832             sharedEdgeValues.find(sharedEdge);
00833 
00834         if (sharedFnd != sharedEdgeValues.end())
00835         {
00836             combine
00837             (
00838                 edgeValues,
00839                 cop,
00840                 meshEdge,       // edge
00841                 sharedFnd()     // value
00842             );
00843         }
00844     }
00845 }
00846 
00847 
00848 template <class T, class CombineOp>
00849 void Foam::syncTools::syncPointList
00850 (
00851     const polyMesh& mesh,
00852     UList<T>& pointValues,
00853     const CombineOp& cop,
00854     const T& nullValue,
00855     const bool applySeparation
00856 )
00857 {
00858     if (pointValues.size() != mesh.nPoints())
00859     {
00860         FatalErrorIn
00861         (
00862             "syncTools<class T, class CombineOp>::syncPointList"
00863             "(const polyMesh&, UList<T>&, const CombineOp&, const T&"
00864             ", const bool)"
00865         )   << "Number of values " << pointValues.size()
00866             << " is not equal to the number of points in the mesh "
00867             << mesh.nPoints() << abort(FatalError);
00868     }
00869 
00870     const polyBoundaryMesh& patches = mesh.boundaryMesh();
00871 
00872     if (!hasCouples(patches))
00873     {
00874         return;
00875     }
00876 
00877     // Is there any coupled patch with transformation?
00878     bool hasTransformation = false;
00879 
00880     if (Pstream::parRun())
00881     {
00882         // Send
00883 
00884         forAll(patches, patchI)
00885         {
00886             if
00887             (
00888                 isA<processorPolyPatch>(patches[patchI])
00889              && patches[patchI].nPoints() > 0
00890             )
00891             {
00892                 const processorPolyPatch& procPatch =
00893                     refCast<const processorPolyPatch>(patches[patchI]);
00894 
00895                 // Get data per patchPoint in neighbouring point numbers.
00896                 List<T> patchInfo(procPatch.nPoints(), nullValue);
00897 
00898                 const labelList& meshPts = procPatch.meshPoints();
00899                 const labelList& nbrPts = procPatch.neighbPoints();
00900 
00901                 forAll(nbrPts, pointI)
00902                 {
00903                     label nbrPointI = nbrPts[pointI];
00904                     if (nbrPointI >= 0 && nbrPointI < patchInfo.size())
00905                     {
00906                         patchInfo[nbrPointI] = pointValues[meshPts[pointI]];
00907                     }
00908                 }
00909 
00910                 OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo());
00911                 toNbr << patchInfo;
00912             }
00913         }
00914 
00915 
00916         // Receive and combine.
00917 
00918         forAll(patches, patchI)
00919         {
00920             if
00921             (
00922                 isA<processorPolyPatch>(patches[patchI])
00923              && patches[patchI].nPoints() > 0
00924             )
00925             {
00926                 const processorPolyPatch& procPatch =
00927                     refCast<const processorPolyPatch>(patches[patchI]);
00928                 checkTransform(procPatch, applySeparation);
00929 
00930                 List<T> nbrPatchInfo(procPatch.nPoints());
00931                 {
00932                     // We do not know the number of points on the other side
00933                     // so cannot use Pstream::read.
00934                     IPstream fromNbr
00935                     (
00936                         Pstream::blocking,
00937                         procPatch.neighbProcNo()
00938                     );
00939                     fromNbr >> nbrPatchInfo;
00940                 }
00941                 // Null any value which is not on neighbouring processor
00942                 nbrPatchInfo.setSize(procPatch.nPoints(), nullValue);
00943 
00944                 if (!procPatch.parallel())
00945                 {
00946                     hasTransformation = true;
00947                     transformList(procPatch.forwardT(), nbrPatchInfo);
00948                 }
00949                 else if (applySeparation && procPatch.separated())
00950                 {
00951                     hasTransformation = true;
00952                     separateList(-procPatch.separation(), nbrPatchInfo);
00953                 }
00954 
00955                 const labelList& meshPts = procPatch.meshPoints();
00956 
00957                 forAll(meshPts, pointI)
00958                 {
00959                     label meshPointI = meshPts[pointI];
00960                     cop(pointValues[meshPointI], nbrPatchInfo[pointI]);
00961                 }
00962             }
00963         }
00964     }
00965 
00966     // Do the cyclics.
00967     forAll(patches, patchI)
00968     {
00969         if (isA<cyclicPolyPatch>(patches[patchI]))
00970         {
00971             const cyclicPolyPatch& cycPatch =
00972                 refCast<const cyclicPolyPatch>(patches[patchI]);
00973 
00974             checkTransform(cycPatch, applySeparation);
00975 
00976             const edgeList& coupledPoints = cycPatch.coupledPoints();
00977             const labelList& meshPts = cycPatch.meshPoints();
00978 
00979             List<T> half0Values(coupledPoints.size());
00980             List<T> half1Values(coupledPoints.size());
00981 
00982             forAll(coupledPoints, i)
00983             {
00984                 const edge& e = coupledPoints[i];
00985 
00986                 label point0 = meshPts[e[0]];
00987                 label point1 = meshPts[e[1]];
00988 
00989                 half0Values[i] = pointValues[point0];
00990                 half1Values[i] = pointValues[point1];
00991             }
00992 
00993             if (!cycPatch.parallel())
00994             {
00995                 hasTransformation = true;
00996                 transformList(cycPatch.reverseT(), half0Values);
00997                 transformList(cycPatch.forwardT(), half1Values);
00998             }
00999             else if (applySeparation && cycPatch.separated())
01000             {
01001                 hasTransformation = true;
01002                 const vectorField& v = cycPatch.coupledPolyPatch::separation();
01003                 separateList(v, half0Values);
01004                 separateList(-v, half1Values);
01005             }
01006 
01007             forAll(coupledPoints, i)
01008             {
01009                 const edge& e = coupledPoints[i];
01010 
01011                 label point0 = meshPts[e[0]];
01012                 label point1 = meshPts[e[1]];
01013 
01014                 cop(pointValues[point0], half1Values[i]);
01015                 cop(pointValues[point1], half0Values[i]);
01016             }
01017         }
01018     }
01019 
01020     //- Note: hasTransformation is only used for warning messages so
01021     //  reduction not strictly nessecary.
01022     //reduce(hasTransformation, orOp<bool>());
01023 
01024     // Synchronize multiple shared points.
01025     const globalMeshData& pd = mesh.globalData();
01026 
01027     if (pd.nGlobalPoints() > 0)
01028     {
01029         if (hasTransformation)
01030         {
01031             WarningIn
01032             (
01033                 "syncTools<class T, class CombineOp>::syncPointList"
01034                 "(const polyMesh&, UList<T>&, const CombineOp&, const T&"
01035                 ", const bool)"
01036             )   << "There are decomposed cyclics in this mesh with"
01037                 << " transformations." << endl
01038                 << "This is not supported. The result will be incorrect"
01039                 << endl;
01040         }
01041 
01042 
01043         // Values on shared points.
01044         List<T> sharedPts(pd.nGlobalPoints(), nullValue);
01045 
01046         forAll(pd.sharedPointLabels(), i)
01047         {
01048             label meshPointI = pd.sharedPointLabels()[i];
01049             // Fill my entries in the shared points
01050             sharedPts[pd.sharedPointAddr()[i]] = pointValues[meshPointI];
01051         }
01052 
01053         // Combine on master.
01054         Pstream::listCombineGather(sharedPts, cop);
01055         Pstream::listCombineScatter(sharedPts);
01056 
01057         // Now we will all have the same information. Merge it back with
01058         // my local information.
01059         forAll(pd.sharedPointLabels(), i)
01060         {
01061             label meshPointI = pd.sharedPointLabels()[i];
01062             pointValues[meshPointI] = sharedPts[pd.sharedPointAddr()[i]];
01063         }
01064     }
01065 }
01066 
01067 
01068 template <class T, class CombineOp>
01069 void Foam::syncTools::syncPointList
01070 (
01071     const polyMesh& mesh,
01072     const labelList& meshPoints,
01073     UList<T>& pointValues,
01074     const CombineOp& cop,
01075     const T& nullValue,
01076     const bool applySeparation
01077 )
01078 {
01079     if (pointValues.size() != meshPoints.size())
01080     {
01081         FatalErrorIn
01082         (
01083             "syncTools<class T, class CombineOp>::syncPointList"
01084             "(const polyMesh&, const labelList&, UList<T>&, const CombineOp&"
01085             ", const T&, const bool)"
01086         )   << "Number of values " << pointValues.size()
01087             << " is not equal to the number of points "
01088             << meshPoints.size() << abort(FatalError);
01089     }
01090 
01091     if (!hasCouples(mesh.boundaryMesh()))
01092     {
01093         return;
01094     }
01095 
01096     List<T> meshValues(mesh.nPoints(), nullValue);
01097 
01098     forAll(meshPoints, i)
01099     {
01100         meshValues[meshPoints[i]] = pointValues[i];
01101     }
01102 
01103     syncTools::syncPointList
01104     (
01105         mesh,
01106         meshValues,
01107         cop,            // combine op
01108         nullValue,      // null value
01109         applySeparation // separation
01110     );
01111 
01112     forAll(meshPoints, i)
01113     {
01114         pointValues[i] = meshValues[meshPoints[i]];
01115     }
01116 }
01117 
01118 
01119 template <class T, class CombineOp>
01120 void Foam::syncTools::syncEdgeList
01121 (
01122     const polyMesh& mesh,
01123     UList<T>& edgeValues,
01124     const CombineOp& cop,
01125     const T& nullValue,
01126     const bool applySeparation
01127 )
01128 {
01129     if (edgeValues.size() != mesh.nEdges())
01130     {
01131         FatalErrorIn
01132         (
01133             "syncTools<class T, class CombineOp>::syncEdgeList"
01134             "(const polyMesh&, UList<T>&, const CombineOp&, const T&"
01135             ", const bool)"
01136         )   << "Number of values " << edgeValues.size()
01137             << " is not equal to the number of edges in the mesh "
01138             << mesh.nEdges() << abort(FatalError);
01139     }
01140 
01141     const polyBoundaryMesh& patches = mesh.boundaryMesh();
01142 
01143     if (!hasCouples(patches))
01144     {
01145         return;
01146     }
01147 
01148     // Is there any coupled patch with transformation?
01149     bool hasTransformation = false;
01150 
01151     if (Pstream::parRun())
01152     {
01153         // Send
01154 
01155         forAll(patches, patchI)
01156         {
01157             if
01158             (
01159                 isA<processorPolyPatch>(patches[patchI])
01160              && patches[patchI].nEdges() > 0
01161             )
01162             {
01163                 const processorPolyPatch& procPatch =
01164                     refCast<const processorPolyPatch>(patches[patchI]);
01165 
01166                 const labelList& meshEdges = procPatch.meshEdges();
01167                 const labelList& neighbEdges = procPatch.neighbEdges();
01168 
01169                 // Get region per patch edge in neighbouring edge numbers.
01170                 List<T> patchInfo(procPatch.nEdges(), nullValue);
01171 
01172                 forAll(neighbEdges, edgeI)
01173                 {
01174                     label nbrEdgeI = neighbEdges[edgeI];
01175 
01176                     if (nbrEdgeI >= 0 && nbrEdgeI < patchInfo.size())
01177                     {
01178                         patchInfo[nbrEdgeI] = edgeValues[meshEdges[edgeI]];
01179                     }
01180                 }
01181 
01182                 OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo());
01183                 toNbr << patchInfo;
01184             }
01185         }
01186 
01187         // Receive and combine.
01188 
01189         forAll(patches, patchI)
01190         {
01191             if
01192             (
01193                 isA<processorPolyPatch>(patches[patchI])
01194              && patches[patchI].nEdges() > 0
01195             )
01196             {
01197                 const processorPolyPatch& procPatch =
01198                     refCast<const processorPolyPatch>(patches[patchI]);
01199 
01200                 checkTransform(procPatch, applySeparation);
01201 
01202                 const labelList& meshEdges = procPatch.meshEdges();
01203 
01204                 // Receive from neighbour. Is per patch edge the region of the
01205                 // neighbouring patch edge.
01206                 List<T> nbrPatchInfo(procPatch.nEdges());
01207 
01208                 {
01209                     IPstream fromNeighb
01210                     (
01211                         Pstream::blocking,
01212                         procPatch.neighbProcNo()
01213                     );
01214                     fromNeighb >> nbrPatchInfo;
01215                 }
01216                 // Null any value which is not on neighbouring processor
01217                 nbrPatchInfo.setSize(procPatch.nEdges(), nullValue);
01218 
01219                 if (!procPatch.parallel())
01220                 {
01221                     hasTransformation = true;
01222                     transformList(procPatch.forwardT(), nbrPatchInfo);
01223                 }
01224                 else if (applySeparation && procPatch.separated())
01225                 {
01226                     hasTransformation = true;
01227                     separateList(-procPatch.separation(), nbrPatchInfo);
01228                 }
01229 
01230                 forAll(meshEdges, edgeI)
01231                 {
01232                     label meshEdgeI = meshEdges[edgeI];
01233 
01234                     cop(edgeValues[meshEdgeI], nbrPatchInfo[edgeI]);
01235                 }
01236             }
01237         }
01238     }
01239 
01240     // Do the cyclics.
01241     forAll(patches, patchI)
01242     {
01243         if (isA<cyclicPolyPatch>(patches[patchI]))
01244         {
01245             const cyclicPolyPatch& cycPatch =
01246                 refCast<const cyclicPolyPatch>(patches[patchI]);
01247 
01248             checkTransform(cycPatch, applySeparation);
01249 
01250             const edgeList& coupledEdges = cycPatch.coupledEdges();
01251             const labelList& meshEdges = cycPatch.meshEdges();
01252 
01253             List<T> half0Values(coupledEdges.size());
01254             List<T> half1Values(coupledEdges.size());
01255 
01256             forAll(coupledEdges, i)
01257             {
01258                 const edge& e = coupledEdges[i];
01259 
01260                 label meshEdge0 = meshEdges[e[0]];
01261                 label meshEdge1 = meshEdges[e[1]];
01262 
01263                 half0Values[i] = edgeValues[meshEdge0];
01264                 half1Values[i] = edgeValues[meshEdge1];
01265             }
01266 
01267             if (!cycPatch.parallel())
01268             {
01269                 hasTransformation = true;
01270                 transformList(cycPatch.reverseT(), half0Values);
01271                 transformList(cycPatch.forwardT(), half1Values);
01272             }
01273             else if (applySeparation && cycPatch.separated())
01274             {
01275                 hasTransformation = true;
01276 
01277                 const vectorField& v = cycPatch.coupledPolyPatch::separation();
01278                 separateList(v, half0Values);
01279                 separateList(-v, half1Values);
01280             }
01281 
01282             forAll(coupledEdges, i)
01283             {
01284                 const edge& e = coupledEdges[i];
01285 
01286                 label meshEdge0 = meshEdges[e[0]];
01287                 label meshEdge1 = meshEdges[e[1]];
01288 
01289                 cop(edgeValues[meshEdge0], half1Values[i]);
01290                 cop(edgeValues[meshEdge1], half0Values[i]);
01291             }
01292         }
01293     }
01294 
01295     //- Note: hasTransformation is only used for warning messages so
01296     //  reduction not strictly nessecary.
01297     //reduce(hasTransformation, orOp<bool>());
01298 
01299     // Do the multiple shared edges
01300     const globalMeshData& pd = mesh.globalData();
01301 
01302     if (pd.nGlobalEdges() > 0)
01303     {
01304         if (hasTransformation)
01305         {
01306             WarningIn
01307             (
01308                 "syncTools<class T, class CombineOp>::syncEdgeList"
01309                 "(const polyMesh&, UList<T>&, const CombineOp&, const T&"
01310                 ", const bool)"
01311             )   << "There are decomposed cyclics in this mesh with"
01312                 << " transformations." << endl
01313                 << "This is not supported. The result will be incorrect"
01314                 << endl;
01315         }
01316 
01317         // Values on shared edges.
01318         List<T> sharedPts(pd.nGlobalEdges(), nullValue);
01319 
01320         forAll(pd.sharedEdgeLabels(), i)
01321         {
01322             label meshEdgeI = pd.sharedEdgeLabels()[i];
01323 
01324             // Fill my entries in the shared edges
01325             sharedPts[pd.sharedEdgeAddr()[i]] = edgeValues[meshEdgeI];
01326         }
01327 
01328         // Combine on master.
01329         Pstream::listCombineGather(sharedPts, cop);
01330         Pstream::listCombineScatter(sharedPts);
01331 
01332         // Now we will all have the same information. Merge it back with
01333         // my local information.
01334         forAll(pd.sharedEdgeLabels(), i)
01335         {
01336             label meshEdgeI = pd.sharedEdgeLabels()[i];
01337             edgeValues[meshEdgeI] = sharedPts[pd.sharedEdgeAddr()[i]];
01338         }
01339     }
01340 }
01341 
01342 
01343 template <class T, class CombineOp>
01344 void Foam::syncTools::syncBoundaryFaceList
01345 (
01346     const polyMesh& mesh,
01347     UList<T>& faceValues,
01348     const CombineOp& cop,
01349     const bool applySeparation
01350 )
01351 {
01352     const label nBFaces = mesh.nFaces() - mesh.nInternalFaces();
01353 
01354     if (faceValues.size() != nBFaces)
01355     {
01356         FatalErrorIn
01357         (
01358             "syncTools<class T, class CombineOp>::syncBoundaryFaceList"
01359             "(const polyMesh&, UList<T>&, const CombineOp&"
01360             ", const bool)"
01361         )   << "Number of values " << faceValues.size()
01362             << " is not equal to the number of boundary faces in the mesh "
01363             << nBFaces << abort(FatalError);
01364     }
01365 
01366     const polyBoundaryMesh& patches = mesh.boundaryMesh();
01367 
01368     if (!hasCouples(patches))
01369     {
01370         return;
01371     }
01372 
01373 
01374     if (Pstream::parRun())
01375     {
01376         // Send
01377 
01378         forAll(patches, patchI)
01379         {
01380             if
01381             (
01382                 isA<processorPolyPatch>(patches[patchI])
01383              && patches[patchI].size() > 0
01384             )
01385             {
01386                 const processorPolyPatch& procPatch =
01387                     refCast<const processorPolyPatch>(patches[patchI]);
01388 
01389                 label patchStart = procPatch.start()-mesh.nInternalFaces();
01390 
01391                 if (contiguous<T>())
01392                 {
01393                     OPstream::write
01394                     (
01395                         Pstream::blocking,
01396                         procPatch.neighbProcNo(),
01397                         reinterpret_cast<const char*>(&faceValues[patchStart]),
01398                         procPatch.size()*sizeof(T)
01399                     );
01400                 }
01401                 else
01402                 {
01403                     OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo());
01404                     toNbr <<
01405                         SubList<T>(faceValues, procPatch.size(), patchStart);
01406                 }
01407             }
01408         }
01409 
01410 
01411         // Receive and combine.
01412 
01413         forAll(patches, patchI)
01414         {
01415             if
01416             (
01417                 isA<processorPolyPatch>(patches[patchI])
01418              && patches[patchI].size() > 0
01419             )
01420             {
01421                 const processorPolyPatch& procPatch =
01422                     refCast<const processorPolyPatch>(patches[patchI]);
01423 
01424                 List<T> nbrPatchInfo(procPatch.size());
01425 
01426                 if (contiguous<T>())
01427                 {
01428                     IPstream::read
01429                     (
01430                         Pstream::blocking,
01431                         procPatch.neighbProcNo(),
01432                         reinterpret_cast<char*>(nbrPatchInfo.begin()),
01433                         nbrPatchInfo.byteSize()
01434                     );
01435                 }
01436                 else
01437                 {
01438                     IPstream fromNeighb
01439                     (
01440                         Pstream::blocking,
01441                         procPatch.neighbProcNo()
01442                     );
01443                     fromNeighb >> nbrPatchInfo;
01444                 }
01445 
01446                 if (!procPatch.parallel())
01447                 {
01448                     transformList(procPatch.forwardT(), nbrPatchInfo);
01449                 }
01450                 else if (applySeparation && procPatch.separated())
01451                 {
01452                     separateList(-procPatch.separation(), nbrPatchInfo);
01453                 }
01454 
01455 
01456                 label bFaceI = procPatch.start()-mesh.nInternalFaces();
01457 
01458                 forAll(nbrPatchInfo, i)
01459                 {
01460                     cop(faceValues[bFaceI++], nbrPatchInfo[i]);
01461                 }
01462             }
01463         }
01464     }
01465 
01466     // Do the cyclics.
01467     forAll(patches, patchI)
01468     {
01469         if (isA<cyclicPolyPatch>(patches[patchI]))
01470         {
01471             const cyclicPolyPatch& cycPatch =
01472                 refCast<const cyclicPolyPatch>(patches[patchI]);
01473 
01474             label patchStart = cycPatch.start()-mesh.nInternalFaces();
01475 
01476             label half = cycPatch.size()/2;
01477             label half1Start = patchStart+half;
01478 
01479             List<T> half0Values(SubList<T>(faceValues, half, patchStart));
01480             List<T> half1Values(SubList<T>(faceValues, half, half1Start));
01481 
01482             if (!cycPatch.parallel())
01483             {
01484                 transformList(cycPatch.reverseT(), half0Values);
01485                 transformList(cycPatch.forwardT(), half1Values);
01486             }
01487             else if (applySeparation && cycPatch.separated())
01488             {
01489                 const vectorField& v = cycPatch.coupledPolyPatch::separation();
01490                 separateList(v, half0Values);
01491                 separateList(-v, half1Values);
01492             }
01493 
01494             label i0 = patchStart;
01495             forAll(half1Values, i)
01496             {
01497                 cop(faceValues[i0++], half1Values[i]);
01498             }
01499 
01500             label i1 = half1Start;
01501             forAll(half0Values, i)
01502             {
01503                 cop(faceValues[i1++], half0Values[i]);
01504             }
01505         }
01506     }
01507 }
01508 
01509 
01510 template <class T, class CombineOp>
01511 void Foam::syncTools::syncFaceList
01512 (
01513     const polyMesh& mesh,
01514     UList<T>& faceValues,
01515     const CombineOp& cop,
01516     const bool applySeparation
01517 )
01518 {
01519     if (faceValues.size() != mesh.nFaces())
01520     {
01521         FatalErrorIn
01522         (
01523             "syncTools<class T, class CombineOp>::syncFaceList"
01524             "(const polyMesh&, UList<T>&, const CombineOp&"
01525             ", const bool)"
01526         )   << "Number of values " << faceValues.size()
01527             << " is not equal to the number of faces in the mesh "
01528             << mesh.nFaces() << abort(FatalError);
01529     }
01530 
01531     SubList<T> bndValues
01532     (
01533         faceValues,
01534         mesh.nFaces()-mesh.nInternalFaces(),
01535         mesh.nInternalFaces()
01536     );
01537 
01538     syncBoundaryFaceList
01539     (
01540         mesh,
01541         bndValues,
01542         cop,
01543         applySeparation
01544     );
01545 }
01546 
01547 
01548 template <class T>
01549 void Foam::syncTools::swapBoundaryFaceList
01550 (
01551     const polyMesh& mesh,
01552     UList<T>& faceValues,
01553     const bool applySeparation
01554 )
01555 {
01556     syncBoundaryFaceList(mesh, faceValues, eqOp<T>(), applySeparation);
01557 }
01558 
01559 
01560 template <class T>
01561 void Foam::syncTools::swapFaceList
01562 (
01563     const polyMesh& mesh,
01564     UList<T>& faceValues,
01565     const bool applySeparation
01566 )
01567 {
01568     syncFaceList(mesh, faceValues, eqOp<T>(), applySeparation);
01569 }
01570 
01571 
01572 template <unsigned nBits, class CombineOp>
01573 void Foam::syncTools::syncFaceList
01574 (
01575     const polyMesh& mesh,
01576     PackedList<nBits>& faceValues,
01577     const CombineOp& cop
01578 )
01579 {
01580     if (faceValues.size() != mesh.nFaces())
01581     {
01582         FatalErrorIn
01583         (
01584             "syncTools<unsigned nBits, class CombineOp>::syncFaceList"
01585             "(const polyMesh&, PackedList<nBits>&, const CombineOp&)"
01586         )   << "Number of values " << faceValues.size()
01587             << " is not equal to the number of faces in the mesh "
01588             << mesh.nFaces() << abort(FatalError);
01589     }
01590 
01591     const polyBoundaryMesh& patches = mesh.boundaryMesh();
01592 
01593     if (!hasCouples(patches))
01594     {
01595         return;
01596     }
01597 
01598     // Patch data (proc patches only).
01599     List<List<unsigned int> > patchValues(patches.size());
01600 
01601     if (Pstream::parRun())
01602     {
01603         // Send
01604 
01605         forAll(patches, patchI)
01606         {
01607             if
01608             (
01609                 isA<processorPolyPatch>(patches[patchI])
01610              && patches[patchI].size() > 0
01611             )
01612             {
01613                 const processorPolyPatch& procPatch =
01614                     refCast<const processorPolyPatch>(patches[patchI]);
01615 
01616                 patchValues[patchI].setSize(procPatch.size());
01617                 forAll(procPatch, i)
01618                 {
01619                     patchValues[patchI][i] =
01620                         faceValues.get(procPatch.start()+i);
01621                 }
01622 
01623                 OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo());
01624                 toNbr << patchValues[patchI];
01625             }
01626         }
01627 
01628 
01629         // Receive and combine.
01630 
01631         forAll(patches, patchI)
01632         {
01633             if
01634             (
01635                 isA<processorPolyPatch>(patches[patchI])
01636              && patches[patchI].size() > 0
01637             )
01638             {
01639                 const processorPolyPatch& procPatch =
01640                     refCast<const processorPolyPatch>(patches[patchI]);
01641 
01642                 {
01643                     IPstream fromNbr
01644                     (
01645                         Pstream::blocking,
01646                         procPatch.neighbProcNo()
01647                     );
01648                     fromNbr >> patchValues[patchI];
01649                 }
01650 
01651                 // Combine (bitwise)
01652                 forAll(procPatch, i)
01653                 {
01654                     unsigned int patchVal = patchValues[patchI][i];
01655                     label meshFaceI = procPatch.start()+i;
01656                     unsigned int faceVal = faceValues.get(meshFaceI);
01657                     cop(faceVal, patchVal);
01658                     faceValues.set(meshFaceI, faceVal);
01659                 }
01660             }
01661         }
01662     }
01663 
01664     // Do the cyclics.
01665     forAll(patches, patchI)
01666     {
01667         if (isA<cyclicPolyPatch>(patches[patchI]))
01668         {
01669             const cyclicPolyPatch& cycPatch =
01670                 refCast<const cyclicPolyPatch>(patches[patchI]);
01671 
01672             label half = cycPatch.size()/2;
01673 
01674             for (label i = 0; i < half; i++)
01675             {
01676                 label meshFace0 = cycPatch.start()+i;
01677                 unsigned int val0 = faceValues.get(meshFace0);
01678                 label meshFace1 = meshFace0 + half;
01679                 unsigned int val1 = faceValues.get(meshFace1);
01680 
01681                 unsigned int t = val0;
01682                 cop(t, val1);
01683                 faceValues.set(meshFace0, t);
01684 
01685                 cop(val1, val0);
01686                 faceValues.set(meshFace1, val1);
01687             }
01688         }
01689     }
01690 }
01691 
01692 
01693 template <unsigned nBits>
01694 void Foam::syncTools::swapFaceList
01695 (
01696     const polyMesh& mesh,
01697     PackedList<nBits>& faceValues
01698 )
01699 {
01700     syncFaceList(mesh, faceValues, eqOp<unsigned int>());
01701 }
01702 
01703 
01704 template <unsigned nBits, class CombineOp>
01705 void Foam::syncTools::syncPointList
01706 (
01707     const polyMesh& mesh,
01708     PackedList<nBits>& pointValues,
01709     const CombineOp& cop,
01710     const unsigned int nullValue
01711 )
01712 {
01713     if (pointValues.size() != mesh.nPoints())
01714     {
01715         FatalErrorIn
01716         (
01717             "syncTools<unsigned nBits, class CombineOp>::syncPointList"
01718             "(const polyMesh&, PackedList<nBits>&, const CombineOp&"
01719             ", const unsigned int&)"
01720         )   << "Number of values " << pointValues.size()
01721             << " is not equal to the number of points in the mesh "
01722             << mesh.nPoints() << abort(FatalError);
01723     }
01724 
01725     const polyBoundaryMesh& patches = mesh.boundaryMesh();
01726 
01727     if (!hasCouples(patches))
01728     {
01729         return;
01730     }
01731 
01732     // Patch data (proc patches only).
01733     List<List<unsigned int> > patchValues(patches.size());
01734 
01735     if (Pstream::parRun())
01736     {
01737         // Send
01738 
01739         forAll(patches, patchI)
01740         {
01741             if
01742             (
01743                 isA<processorPolyPatch>(patches[patchI])
01744              && patches[patchI].nPoints() > 0
01745             )
01746             {
01747                 const processorPolyPatch& procPatch =
01748                     refCast<const processorPolyPatch>(patches[patchI]);
01749 
01750                 patchValues[patchI].setSize(procPatch.nPoints());
01751                 patchValues[patchI] = nullValue;
01752 
01753                 const labelList& meshPts = procPatch.meshPoints();
01754                 const labelList& nbrPts = procPatch.neighbPoints();
01755 
01756                 forAll(nbrPts, pointI)
01757                 {
01758                     label nbrPointI = nbrPts[pointI];
01759                     if (nbrPointI >= 0 && nbrPointI < procPatch.nPoints())
01760                     {
01761                         patchValues[patchI][nbrPointI] =
01762                             pointValues.get(meshPts[pointI]);
01763                     }
01764                 }
01765 
01766                 OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo());
01767                 toNbr << patchValues[patchI];
01768             }
01769         }
01770 
01771 
01772         // Receive and combine.
01773 
01774         forAll(patches, patchI)
01775         {
01776             if
01777             (
01778                 isA<processorPolyPatch>(patches[patchI])
01779              && patches[patchI].nPoints() > 0
01780             )
01781             {
01782                 const processorPolyPatch& procPatch =
01783                     refCast<const processorPolyPatch>(patches[patchI]);
01784 
01785                 {
01786                     // We do not know the number of points on the other side
01787                     // so cannot use Pstream::read.
01788                     IPstream fromNbr
01789                     (
01790                         Pstream::blocking,
01791                         procPatch.neighbProcNo()
01792                     );
01793                     fromNbr >> patchValues[patchI];
01794                 }
01795 
01796                 // Null any value which is not on neighbouring processor
01797                 patchValues[patchI].setSize(procPatch.nPoints(), nullValue);
01798 
01799                 const labelList& meshPts = procPatch.meshPoints();
01800 
01801                 forAll(meshPts, pointI)
01802                 {
01803                     label meshPointI = meshPts[pointI];
01804                     unsigned int pointVal = pointValues.get(meshPointI);
01805                     cop(pointVal, patchValues[patchI][pointI]);
01806                     pointValues.set(meshPointI, pointVal);
01807                 }
01808             }
01809         }
01810     }
01811 
01812     // Do the cyclics.
01813     forAll(patches, patchI)
01814     {
01815         if (isA<cyclicPolyPatch>(patches[patchI]))
01816         {
01817             const cyclicPolyPatch& cycPatch =
01818                 refCast<const cyclicPolyPatch>(patches[patchI]);
01819 
01820             const edgeList& coupledPoints = cycPatch.coupledPoints();
01821             const labelList& meshPts = cycPatch.meshPoints();
01822 
01823             forAll(coupledPoints, i)
01824             {
01825                 const edge& e = coupledPoints[i];
01826 
01827                 label point0 = meshPts[e[0]];
01828                 label point1 = meshPts[e[1]];
01829 
01830                 unsigned int val0 = pointValues.get(point0);
01831                 unsigned int t = val0;
01832                 unsigned int val1 = pointValues.get(point1);
01833 
01834                 cop(t, val1);
01835                 pointValues.set(point0, t);
01836                 cop(val1, val0);
01837                 pointValues.set(point1, val1);
01838             }
01839         }
01840     }
01841 
01842     // Synchronize multiple shared points.
01843     const globalMeshData& pd = mesh.globalData();
01844 
01845     if (pd.nGlobalPoints() > 0)
01846     {
01847         // Values on shared points. Use unpacked storage for ease!
01848         List<unsigned int> sharedPts(pd.nGlobalPoints(), nullValue);
01849 
01850         forAll(pd.sharedPointLabels(), i)
01851         {
01852             label meshPointI = pd.sharedPointLabels()[i];
01853             // Fill my entries in the shared points
01854             sharedPts[pd.sharedPointAddr()[i]] = pointValues.get(meshPointI);
01855         }
01856 
01857         // Combine on master.
01858         Pstream::listCombineGather(sharedPts, cop);
01859         Pstream::listCombineScatter(sharedPts);
01860 
01861         // Now we will all have the same information. Merge it back with
01862         // my local information.
01863         forAll(pd.sharedPointLabels(), i)
01864         {
01865             label meshPointI = pd.sharedPointLabels()[i];
01866             pointValues.set(meshPointI, sharedPts[pd.sharedPointAddr()[i]]);
01867         }
01868     }
01869 }
01870 
01871 
01872 template <unsigned nBits, class CombineOp>
01873 void Foam::syncTools::syncEdgeList
01874 (
01875     const polyMesh& mesh,
01876     PackedList<nBits>& edgeValues,
01877     const CombineOp& cop,
01878     const unsigned int nullValue
01879 )
01880 {
01881     if (edgeValues.size() != mesh.nEdges())
01882     {
01883         FatalErrorIn
01884         (
01885             "syncTools<unsigned nBits, class CombineOp>::syncEdgeList"
01886             "(const polyMesh&, PackedList<nBits>&, const CombineOp&"
01887             ", const unsigned int&)"
01888         )   << "Number of values " << edgeValues.size()
01889             << " is not equal to the number of edges in the mesh "
01890             << mesh.nEdges() << abort(FatalError);
01891     }
01892 
01893     const polyBoundaryMesh& patches = mesh.boundaryMesh();
01894 
01895     if (!hasCouples(patches))
01896     {
01897         return;
01898     }
01899 
01900     // Patch data (proc patches only).
01901     List<List<unsigned int> > patchValues(patches.size());
01902 
01903     if (Pstream::parRun())
01904     {
01905         // Send
01906 
01907         forAll(patches, patchI)
01908         {
01909             if
01910             (
01911                 isA<processorPolyPatch>(patches[patchI])
01912              && patches[patchI].nEdges() > 0
01913             )
01914             {
01915                 const processorPolyPatch& procPatch =
01916                     refCast<const processorPolyPatch>(patches[patchI]);
01917 
01918                 patchValues[patchI].setSize(procPatch.nEdges(), nullValue);
01919 
01920                 const labelList& meshEdges = procPatch.meshEdges();
01921                 const labelList& neighbEdges = procPatch.neighbEdges();
01922 
01923                 forAll(neighbEdges, edgeI)
01924                 {
01925                     label nbrEdgeI = neighbEdges[edgeI];
01926                     if (nbrEdgeI >= 0 && nbrEdgeI < procPatch.nEdges())
01927                     {
01928                         patchValues[patchI][nbrEdgeI] =
01929                             edgeValues.get(meshEdges[edgeI]);
01930                     }
01931                 }
01932 
01933                 OPstream toNbr(Pstream::blocking, procPatch.neighbProcNo());
01934                 toNbr << patchValues[patchI];
01935             }
01936         }
01937 
01938 
01939         // Receive and combine.
01940 
01941         forAll(patches, patchI)
01942         {
01943             if
01944             (
01945                 isA<processorPolyPatch>(patches[patchI])
01946              && patches[patchI].nEdges() > 0
01947             )
01948             {
01949                 const processorPolyPatch& procPatch =
01950                     refCast<const processorPolyPatch>(patches[patchI]);
01951 
01952                 {
01953                     IPstream fromNeighb
01954                     (
01955                         Pstream::blocking,
01956                         procPatch.neighbProcNo()
01957                     );
01958                     fromNeighb >> patchValues[patchI];
01959                 }
01960 
01961                 patchValues[patchI].setSize(procPatch.nEdges(), nullValue);
01962 
01963                 const labelList& meshEdges = procPatch.meshEdges();
01964 
01965                 forAll(meshEdges, edgeI)
01966                 {
01967                     unsigned int patchVal = patchValues[patchI][edgeI];
01968                     label meshEdgeI = meshEdges[edgeI];
01969                     unsigned int edgeVal = edgeValues.get(meshEdgeI);
01970                     cop(edgeVal, patchVal);
01971                     edgeValues.set(meshEdgeI, edgeVal);
01972                 }
01973             }
01974         }
01975     }
01976 
01977     // Do the cyclics.
01978     forAll(patches, patchI)
01979     {
01980         if (isA<cyclicPolyPatch>(patches[patchI]))
01981         {
01982             const cyclicPolyPatch& cycPatch =
01983                 refCast<const cyclicPolyPatch>(patches[patchI]);
01984 
01985             const edgeList& coupledEdges = cycPatch.coupledEdges();
01986             const labelList& meshEdges = cycPatch.meshEdges();
01987 
01988             forAll(coupledEdges, i)
01989             {
01990                 const edge& e = coupledEdges[i];
01991 
01992                 label edge0 = meshEdges[e[0]];
01993                 label edge1 = meshEdges[e[1]];
01994 
01995                 unsigned int val0 = edgeValues.get(edge0);
01996                 unsigned int t = val0;
01997                 unsigned int val1 = edgeValues.get(edge1);
01998 
01999                 cop(t, val1);
02000                 edgeValues.set(edge0, t);
02001                 cop(val1, val0);
02002                 edgeValues.set(edge1, val1);
02003             }
02004         }
02005     }
02006 
02007     // Synchronize multiple shared edges.
02008     const globalMeshData& pd = mesh.globalData();
02009 
02010     if (pd.nGlobalEdges() > 0)
02011     {
02012         // Values on shared edges. Use unpacked storage for ease!
02013         List<unsigned int> sharedPts(pd.nGlobalEdges(), nullValue);
02014 
02015         forAll(pd.sharedEdgeLabels(), i)
02016         {
02017             label meshEdgeI = pd.sharedEdgeLabels()[i];
02018             // Fill my entries in the shared edges
02019             sharedPts[pd.sharedEdgeAddr()[i]] = edgeValues.get(meshEdgeI);
02020         }
02021 
02022         // Combine on master.
02023         Pstream::listCombineGather(sharedPts, cop);
02024         Pstream::listCombineScatter(sharedPts);
02025 
02026         // Now we will all have the same information. Merge it back with
02027         // my local information.
02028         forAll(pd.sharedEdgeLabels(), i)
02029         {
02030             label meshEdgeI = pd.sharedEdgeLabels()[i];
02031             edgeValues.set(meshEdgeI, sharedPts[pd.sharedEdgeAddr()[i]]);
02032         }
02033     }
02034 }
02035 
02036 
02037 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines