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

gatherScatterList.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     Gather data from all processors onto single processor according to some
00026     communication schedule (usually linear-to-master or tree-to-master).
00027     The gathered data will be a list with element procID the data from processor
00028     procID. Before calling every processor should insert its value into
00029     Values[Pstream::myProcNo()].
00030     Note: after gather every processor only knows its own data and that of the
00031     processors below it. Only the 'master' of the communication schedule holds
00032     a fully filled List. Use scatter to distribute the data.
00033 
00034 \*---------------------------------------------------------------------------*/
00035 
00036 #include "IPstream.H"
00037 #include "OPstream.H"
00038 #include <OpenFOAM/contiguous.H>
00039 
00040 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00041 
00042 namespace Foam
00043 {
00044 
00045 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
00046 
00047 template <class T>
00048 void Pstream::gatherList
00049 (
00050     const List<Pstream::commsStruct>& comms,
00051     List<T>& Values
00052 )
00053 {
00054     if (Pstream::parRun())
00055     {
00056         if (Values.size() != Pstream::nProcs())
00057         {
00058             FatalErrorIn
00059             (
00060                 "Pstream::gatherList(const List<Pstream::commsStruct>&"
00061                 ", List<T>)"
00062             )   << "Size of list:" << Values.size()
00063                 << " does not equal the number of processors:"
00064                 << Pstream::nProcs()
00065                 << Foam::abort(FatalError);
00066         }
00067 
00068         // Get my communication order
00069         const commsStruct& myComm = comms[Pstream::myProcNo()];
00070 
00071         // Receive from my downstairs neighbours
00072         forAll(myComm.below(), belowI)
00073         {
00074             label belowID = myComm.below()[belowI];
00075             const labelList& belowLeaves = comms[belowID].allBelow();
00076 
00077             if (contiguous<T>())
00078             {
00079                 List<T> receivedValues(belowLeaves.size() + 1);
00080 
00081                 IPstream::read
00082                 (
00083                     Pstream::scheduled,
00084                     belowID,
00085                     reinterpret_cast<char*>(receivedValues.begin()),
00086                     receivedValues.byteSize()
00087                 );
00088 
00089                 Values[belowID] = receivedValues[0];
00090 
00091                 forAll(belowLeaves, leafI)
00092                 {
00093                     Values[belowLeaves[leafI]] = receivedValues[leafI + 1];
00094                 }
00095             }
00096             else
00097             {
00098                 IPstream fromBelow(Pstream::scheduled, belowID);
00099                 fromBelow >> Values[belowID];
00100 
00101                 if (debug & 2)
00102                 {
00103                     Pout<< " received through "
00104                         << belowID << " data from:" << belowID
00105                         << " data:" << Values[belowID] << endl;
00106                 }
00107 
00108                 // Receive from all other processors below belowID
00109                 forAll(belowLeaves, leafI)
00110                 {
00111                     label leafID = belowLeaves[leafI];
00112                     fromBelow >> Values[leafID];
00113 
00114                     if (debug & 2)
00115                     {
00116                         Pout<< " received through "
00117                             << belowID << " data from:" << leafID
00118                             << " data:" << Values[leafID] << endl;
00119                     }
00120                 }
00121             }
00122         }
00123 
00124         // Send up from Values:
00125         // - my own value first
00126         // - all belowLeaves next
00127         if (myComm.above() != -1)
00128         {
00129             const labelList& belowLeaves = myComm.allBelow();
00130 
00131             if (debug & 2)
00132             {
00133                 Pout<< " sending to " << myComm.above()
00134                     << " data from me:" << Pstream::myProcNo()
00135                     << " data:" << Values[Pstream::myProcNo()] << endl;
00136             }
00137 
00138             if (contiguous<T>())
00139             {
00140                 List<T> sendingValues(belowLeaves.size() + 1);
00141                 sendingValues[0] = Values[Pstream::myProcNo()];
00142 
00143                 forAll(belowLeaves, leafI)
00144                 {
00145                     sendingValues[leafI + 1] = Values[belowLeaves[leafI]];
00146                 }
00147 
00148                 OPstream::write
00149                 (
00150                     Pstream::scheduled,
00151                     myComm.above(),
00152                     reinterpret_cast<const char*>(sendingValues.begin()),
00153                     sendingValues.byteSize()
00154                 );
00155             }
00156             else
00157             {
00158                 OPstream toAbove(Pstream::scheduled, myComm.above());
00159                 toAbove << Values[Pstream::myProcNo()];
00160 
00161                 forAll(belowLeaves, leafI)
00162                 {
00163                     label leafID = belowLeaves[leafI];
00164 
00165                     if (debug & 2)
00166                     {
00167                         Pout<< " sending to "
00168                             << myComm.above() << " data from:" << leafID
00169                             << " data:" << Values[leafID] << endl;
00170                     }
00171                     toAbove << Values[leafID];
00172                 }
00173             }
00174         }
00175     }
00176 }
00177 
00178 
00179 template <class T>
00180 void Pstream::gatherList(List<T>& Values)
00181 {
00182     if (Pstream::nProcs() < Pstream::nProcsSimpleSum)
00183     {
00184         gatherList(Pstream::linearCommunication(), Values);
00185     }
00186     else
00187     {
00188         gatherList(Pstream::treeCommunication(), Values);
00189     }
00190 }
00191 
00192 
00193 template <class T>
00194 void Pstream::scatterList
00195 (
00196     const List<Pstream::commsStruct>& comms,
00197     List<T>& Values
00198 )
00199 {
00200     if (Pstream::parRun())
00201     {
00202         if (Values.size() != Pstream::nProcs())
00203         {
00204             FatalErrorIn
00205             (
00206                 "Pstream::scatterList(const List<Pstream::commsStruct>&"
00207                 ", List<T>)"
00208             )   << "Size of list:" << Values.size()
00209                 << " does not equal the number of processors:"
00210                 << Pstream::nProcs()
00211                 << Foam::abort(FatalError);
00212         }
00213 
00214         // Get my communication order
00215         const commsStruct& myComm = comms[Pstream::myProcNo()];
00216 
00217         // Reveive from up
00218         if (myComm.above() != -1)
00219         {
00220             const labelList& notBelowLeaves = myComm.allNotBelow();
00221 
00222             if (contiguous<T>())
00223             {
00224                 List<T> receivedValues(notBelowLeaves.size());
00225 
00226                 IPstream::read
00227                 (
00228                     Pstream::scheduled,
00229                     myComm.above(),
00230                     reinterpret_cast<char*>(receivedValues.begin()),
00231                     receivedValues.byteSize()
00232                 );
00233 
00234                 forAll(notBelowLeaves, leafI)
00235                 {
00236                     Values[notBelowLeaves[leafI]] = receivedValues[leafI];
00237                 }
00238             }
00239             else
00240             {
00241                 IPstream fromAbove(Pstream::scheduled, myComm.above());
00242 
00243                 forAll(notBelowLeaves, leafI)
00244                 {
00245                     label leafID = notBelowLeaves[leafI];
00246                     fromAbove >> Values[leafID];
00247 
00248                     if (debug)
00249                     {
00250                         Pout<< " received through "
00251                             << myComm.above() << " data for:" << leafID
00252                             << " data:" << Values[leafID] << endl;
00253                     }
00254                 }
00255             }
00256         }
00257 
00258         // Send to my downstairs neighbours
00259         forAll(myComm.below(), belowI)
00260         {
00261             label belowID = myComm.below()[belowI];
00262             const labelList& notBelowLeaves = comms[belowID].allNotBelow();
00263 
00264             if (contiguous<T>())
00265             {
00266                 List<T> sendingValues(notBelowLeaves.size());
00267 
00268                 forAll(notBelowLeaves, leafI)
00269                 {
00270                     sendingValues[leafI] = Values[notBelowLeaves[leafI]];
00271                 }
00272 
00273                 OPstream::write
00274                 (
00275                     Pstream::scheduled,
00276                     belowID,
00277                     reinterpret_cast<const char*>(sendingValues.begin()),
00278                     sendingValues.byteSize()
00279                 );
00280             }
00281             else
00282             {
00283                 OPstream toBelow(Pstream::scheduled, belowID);
00284 
00285                 // Send data destined for all other processors below belowID
00286                 forAll(notBelowLeaves, leafI)
00287                 {
00288                     label leafID = notBelowLeaves[leafI];
00289                     toBelow << Values[leafID];
00290 
00291                     if (debug)
00292                     {
00293                         Pout<< " sent through "
00294                             << belowID << " data for:" << leafID
00295                             << " data:" << Values[leafID] << endl;
00296                     }
00297                 }
00298             }
00299         }
00300     }
00301 }
00302 
00303 
00304 template <class T>
00305 void Pstream::scatterList(List<T>& Values)
00306 {
00307     if (Pstream::nProcs() < Pstream::nProcsSimpleSum)
00308     {
00309         scatterList(Pstream::linearCommunication(), Values);
00310     }
00311     else
00312     {
00313         scatterList(Pstream::treeCommunication(), Values);
00314     }
00315 }
00316 
00317 
00318 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
00319 
00320 } // End namespace Foam
00321 
00322 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines