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

combineGatherScatter.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 Description
00025     Variant of gather, scatter.
00026     Normal gather uses:
00027     - construct null and read (>>) from Istream
00028     - binary operator and assignment operator to combine values
00029 
00030     combineGather uses:
00031     - construct from Istream
00032     - modify operator which modifies its lhs
00033 
00034 \*---------------------------------------------------------------------------*/
00035 
00036 #include "OPstream.H"
00037 #include "IPstream.H"
00038 #include <OpenFOAM/IOstreams.H>
00039 #include <OpenFOAM/contiguous.H>
00040 
00041 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00042 
00043 namespace Foam
00044 {
00045 
00046 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00047 
00048 template <class T, class CombineOp>
00049 void Pstream::combineGather
00050 (
00051     const List<Pstream::commsStruct>& comms,
00052     T& Value,
00053     const CombineOp& cop
00054 )
00055 {
00056     if (Pstream::parRun())
00057     {
00058         // Get my communication order
00059         const commsStruct& myComm = comms[Pstream::myProcNo()];
00060 
00061         // Receive from my downstairs neighbours
00062         forAll(myComm.below(), belowI)
00063         {
00064             label belowID = myComm.below()[belowI];
00065 
00066             if (contiguous<T>())
00067             {
00068                 T value;
00069                 IPstream::read
00070                 (
00071                     Pstream::scheduled,
00072                     belowID,
00073                     reinterpret_cast<char*>(&value),
00074                     sizeof(T)
00075                 );
00076 
00077                 if (debug & 2)
00078                 {
00079                     Pout<< " received from "
00080                         << belowID << " data:" << value << endl;
00081                 }
00082 
00083                 cop(Value, value);
00084             }
00085             else
00086             {
00087                 IPstream fromBelow(Pstream::scheduled, belowID);
00088                 T value(fromBelow);
00089 
00090                 if (debug & 2)
00091                 {
00092                     Pout<< " received from "
00093                         << belowID << " data:" << value << endl;
00094                 }
00095 
00096                 cop(Value, value);
00097             }
00098         }
00099 
00100         // Send up Value
00101         if (myComm.above() != -1)
00102         {
00103             if (debug & 2)
00104             {
00105                 Pout<< " sending to " << myComm.above()
00106                     << " data:" << Value << endl;
00107             }
00108 
00109             if (contiguous<T>())
00110             {
00111                 OPstream::write
00112                 (
00113                     Pstream::scheduled,
00114                     myComm.above(),
00115                     reinterpret_cast<const char*>(&Value),
00116                     sizeof(T)
00117                 );
00118             }
00119             else
00120             {
00121                 OPstream toAbove(Pstream::scheduled, myComm.above());
00122                 toAbove << Value;
00123             }
00124         }
00125     }
00126 }
00127 
00128 
00129 template <class T, class CombineOp>
00130 void Pstream::combineGather(T& Value, const CombineOp& cop)
00131 {
00132     if (Pstream::nProcs() < Pstream::nProcsSimpleSum)
00133     {
00134         combineGather(Pstream::linearCommunication(), Value, cop);
00135     }
00136     else
00137     {
00138         combineGather(Pstream::treeCommunication(), Value, cop);
00139     }
00140 }
00141 
00142 
00143 template <class T>
00144 void Pstream::combineScatter(const List<Pstream::commsStruct>& comms, T& Value)
00145 {
00146     if (Pstream::parRun())
00147     {
00148         // Get my communication order
00149         const Pstream::commsStruct& myComm = comms[Pstream::myProcNo()];
00150 
00151         // Reveive from up
00152         if (myComm.above() != -1)
00153         {
00154             if (contiguous<T>())
00155             {
00156                 IPstream::read
00157                 (
00158                     Pstream::scheduled,
00159                     myComm.above(),
00160                     reinterpret_cast<char*>(&Value),
00161                     sizeof(T)
00162                 );
00163             }
00164             else
00165             {
00166                 IPstream fromAbove(Pstream::scheduled, myComm.above());
00167                 Value = T(fromAbove);
00168             }
00169 
00170             if (debug & 2)
00171             {
00172                 Pout<< " received from "
00173                     << myComm.above() << " data:" << Value << endl;
00174             }
00175         }
00176 
00177         // Send to my downstairs neighbours
00178         forAll(myComm.below(), belowI)
00179         {
00180             label belowID = myComm.below()[belowI];
00181 
00182             if (debug & 2)
00183             {
00184                 Pout<< " sending to " << belowID << " data:" << Value << endl;
00185             }
00186 
00187             if (contiguous<T>())
00188             {
00189                 OPstream::write
00190                 (
00191                     Pstream::scheduled,
00192                     belowID,
00193                     reinterpret_cast<const char*>(&Value),
00194                     sizeof(T)
00195                 );
00196             }
00197             else
00198             {
00199                 OPstream toBelow(Pstream::scheduled, belowID);
00200                 toBelow << Value;
00201             }
00202         }
00203     }
00204 }
00205 
00206 
00207 template <class T>
00208 void Pstream::combineScatter(T& Value)
00209 {
00210     if (Pstream::nProcs() < Pstream::nProcsSimpleSum)
00211     {
00212         combineScatter(Pstream::linearCommunication(), Value);
00213     }
00214     else
00215     {
00216         combineScatter(Pstream::treeCommunication(), Value);
00217     }
00218 }
00219 
00220 
00221 // Same thing but for whole list at a time
00222 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00223 
00224 
00225 template <class T, class CombineOp>
00226 void Pstream::listCombineGather
00227 (
00228     const List<Pstream::commsStruct>& comms,
00229     List<T>& Values,
00230     const CombineOp& cop
00231 )
00232 {
00233     if (Pstream::parRun())
00234     {
00235         // Get my communication order
00236         const commsStruct& myComm = comms[Pstream::myProcNo()];
00237 
00238         // Receive from my downstairs neighbours
00239         forAll(myComm.below(), belowI)
00240         {
00241             label belowID = myComm.below()[belowI];
00242 
00243             if (contiguous<T>())
00244             {
00245                 List<T> receivedValues(Values.size());
00246 
00247                 IPstream::read
00248                 (
00249                     Pstream::scheduled,
00250                     belowID,
00251                     reinterpret_cast<char*>(receivedValues.begin()),
00252                     receivedValues.byteSize()
00253                 );
00254 
00255                 if (debug & 2)
00256                 {
00257                     Pout<< " received from "
00258                         << belowID << " data:" << receivedValues << endl;
00259                 }
00260 
00261                 forAll(Values, i)
00262                 {
00263                     cop(Values[i], receivedValues[i]);
00264                 }
00265             }
00266             else
00267             {
00268                 IPstream fromBelow(Pstream::scheduled, belowID);
00269                 List<T> receivedValues(fromBelow);
00270 
00271                 if (debug & 2)
00272                 {
00273                     Pout<< " received from "
00274                         << belowID << " data:" << receivedValues << endl;
00275                 }
00276 
00277                 forAll(Values, i)
00278                 {
00279                     cop(Values[i], receivedValues[i]);
00280                 }
00281             }
00282         }
00283 
00284         // Send up Value
00285         if (myComm.above() != -1)
00286         {
00287             if (debug & 2)
00288             {
00289                 Pout<< " sending to " << myComm.above()
00290                     << " data:" << Values << endl;
00291             }
00292 
00293             if (contiguous<T>())
00294             {
00295                 OPstream::write
00296                 (
00297                     Pstream::scheduled,
00298                     myComm.above(),
00299                     reinterpret_cast<const char*>(Values.begin()),
00300                     Values.byteSize()
00301                 );
00302             }
00303             else
00304             {
00305                 OPstream toAbove(Pstream::scheduled, myComm.above());
00306                 toAbove << Values;
00307             }
00308         }
00309     }
00310 }
00311 
00312 
00313 template <class T, class CombineOp>
00314 void Pstream::listCombineGather(List<T>& Values, const CombineOp& cop)
00315 {
00316     if (Pstream::nProcs() < Pstream::nProcsSimpleSum)
00317     {
00318         listCombineGather(Pstream::linearCommunication(), Values, cop);
00319     }
00320     else
00321     {
00322         listCombineGather(Pstream::treeCommunication(), Values, cop);
00323     }
00324 }
00325 
00326 
00327 template <class T>
00328 void Pstream::listCombineScatter
00329 (
00330     const List<Pstream::commsStruct>& comms,
00331     List<T>& Values
00332 )
00333 {
00334     if (Pstream::parRun())
00335     {
00336         // Get my communication order
00337         const Pstream::commsStruct& myComm = comms[Pstream::myProcNo()];
00338 
00339         // Reveive from up
00340         if (myComm.above() != -1)
00341         {
00342             if (contiguous<T>())
00343             {
00344                 IPstream::read
00345                 (
00346                     Pstream::scheduled,
00347                     myComm.above(),
00348                     reinterpret_cast<char*>(Values.begin()),
00349                     Values.byteSize()
00350                 );
00351             }
00352             else
00353             {
00354                 IPstream fromAbove(Pstream::scheduled, myComm.above());
00355                 fromAbove >> Values;
00356             }
00357 
00358             if (debug & 2)
00359             {
00360                 Pout<< " received from "
00361                     << myComm.above() << " data:" << Values << endl;
00362             }
00363         }
00364 
00365         // Send to my downstairs neighbours
00366         forAll(myComm.below(), belowI)
00367         {
00368             label belowID = myComm.below()[belowI];
00369 
00370             if (debug & 2)
00371             {
00372                 Pout<< " sending to " << belowID << " data:" << Values << endl;
00373             }
00374 
00375             if (contiguous<T>())
00376             {
00377                 OPstream::write
00378                 (
00379                     Pstream::scheduled,
00380                     belowID,
00381                     reinterpret_cast<const char*>(Values.begin()),
00382                     Values.byteSize()
00383                 );
00384             }
00385             else
00386             {
00387                 OPstream toBelow(Pstream::scheduled, belowID);
00388                 toBelow << Values;
00389             }
00390         }
00391     }
00392 }
00393 
00394 
00395 template <class T>
00396 void Pstream::listCombineScatter(List<T>& Values)
00397 {
00398     if (Pstream::nProcs() < Pstream::nProcsSimpleSum)
00399     {
00400         listCombineScatter(Pstream::linearCommunication(), Values);
00401     }
00402     else
00403     {
00404         listCombineScatter(Pstream::treeCommunication(), Values);
00405     }
00406 }
00407 
00408 
00409 
00410 
00411 // Same thing but for sparse list (map)
00412 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
00413 
00414 
00415 template <class Container, class CombineOp>
00416 void Pstream::mapCombineGather
00417 (
00418     const List<Pstream::commsStruct>& comms,
00419     Container& Values,
00420     const CombineOp& cop
00421 )
00422 {
00423     if (Pstream::parRun())
00424     {
00425         // Get my communication order
00426         const commsStruct& myComm = comms[Pstream::myProcNo()];
00427 
00428         // Receive from my downstairs neighbours
00429         forAll(myComm.below(), belowI)
00430         {
00431             label belowID = myComm.below()[belowI];
00432 
00433             IPstream fromBelow(Pstream::scheduled, belowID);
00434             Container receivedValues(fromBelow);
00435 
00436             if (debug & 2)
00437             {
00438                 Pout<< " received from "
00439                     << belowID << " data:" << receivedValues << endl;
00440             }
00441 
00442             for
00443             (
00444                 typename Container::const_iterator slaveIter =
00445                     receivedValues.begin();
00446                 slaveIter != receivedValues.end();
00447                 ++slaveIter
00448             )
00449             {
00450                 typename Container::iterator
00451                     masterIter = Values.find(slaveIter.key());
00452 
00453                 if (masterIter != Values.end())
00454                 {
00455                     cop(masterIter(), slaveIter());
00456                 }
00457                 else
00458                 {
00459                     Values.insert(slaveIter.key(), slaveIter());
00460                 }
00461             }
00462         }
00463 
00464         // Send up Value
00465         if (myComm.above() != -1)
00466         {
00467             if (debug & 2)
00468             {
00469                 Pout<< " sending to " << myComm.above()
00470                     << " data:" << Values << endl;
00471             }
00472 
00473             OPstream toAbove(Pstream::scheduled, myComm.above());
00474             toAbove << Values;
00475         }
00476     }
00477 }
00478 
00479 
00480 template <class Container, class CombineOp>
00481 void Pstream::mapCombineGather(Container& Values, const CombineOp& cop)
00482 {
00483     if (Pstream::nProcs() < Pstream::nProcsSimpleSum)
00484     {
00485         mapCombineGather(Pstream::linearCommunication(), Values, cop);
00486     }
00487     else
00488     {
00489         mapCombineGather(Pstream::treeCommunication(), Values, cop);
00490     }
00491 }
00492 
00493 
00494 template <class Container>
00495 void Pstream::mapCombineScatter
00496 (
00497     const List<Pstream::commsStruct>& comms,
00498     Container& Values
00499 )
00500 {
00501     if (Pstream::parRun())
00502     {
00503         // Get my communication order
00504         const Pstream::commsStruct& myComm = comms[Pstream::myProcNo()];
00505 
00506         // Reveive from up
00507         if (myComm.above() != -1)
00508         {
00509             IPstream fromAbove(Pstream::scheduled, myComm.above());
00510             fromAbove >> Values;
00511 
00512             if (debug & 2)
00513             {
00514                 Pout<< " received from "
00515                     << myComm.above() << " data:" << Values << endl;
00516             }
00517         }
00518 
00519         // Send to my downstairs neighbours
00520         forAll(myComm.below(), belowI)
00521         {
00522             label belowID = myComm.below()[belowI];
00523 
00524             if (debug & 2)
00525             {
00526                 Pout<< " sending to " << belowID << " data:" << Values << endl;
00527             }
00528 
00529             OPstream toBelow(Pstream::scheduled, belowID);
00530             toBelow << Values;
00531         }
00532     }
00533 }
00534 
00535 
00536 template <class Container>
00537 void Pstream::mapCombineScatter(Container& Values)
00538 {
00539     if (Pstream::nProcs() < Pstream::nProcsSimpleSum)
00540     {
00541         mapCombineScatter(Pstream::linearCommunication(), Values);
00542     }
00543     else
00544     {
00545         mapCombineScatter(Pstream::treeCommunication(), Values);
00546     }
00547 }
00548 
00549 
00550 
00551 
00552 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00553 
00554 } // End namespace Foam
00555 
00556 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines