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

mapDistribute.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 "mapDistribute.H"
00027 #include <OpenFOAM/commSchedule.H>
00028 #include <OpenFOAM/HashSet.H>
00029 #include <OpenFOAM/ListOps.H>
00030 
00031 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00032 
00033 Foam::List<Foam::labelPair> Foam::mapDistribute::schedule
00034 (
00035     const labelListList& subMap,
00036     const labelListList& constructMap
00037 )
00038 {
00039     // Communications: send and receive processor
00040     List<labelPair> allComms;
00041 
00042     {
00043         HashSet<labelPair, labelPair::Hash<> > commsSet(Pstream::nProcs());
00044 
00045         // Find what communication is required
00046         forAll(subMap, procI)
00047         {
00048             if (procI != Pstream::myProcNo())
00049             {
00050                 if (subMap[procI].size())
00051                 {
00052                     // I need to send to procI
00053                     commsSet.insert(labelPair(Pstream::myProcNo(), procI));
00054                 }
00055                 if (constructMap[procI].size())
00056                 {
00057                     // I need to receive from procI
00058                     commsSet.insert(labelPair(procI, Pstream::myProcNo()));
00059                 }
00060             }
00061         }
00062         allComms = commsSet.toc();
00063     }
00064 
00065 
00066     // Reduce
00067     if (Pstream::master())
00068     {
00069         // Receive and merge
00070         for
00071         (
00072             int slave=Pstream::firstSlave();
00073             slave<=Pstream::lastSlave();
00074             slave++
00075         )
00076         {
00077             IPstream fromSlave(Pstream::blocking, slave);
00078             List<labelPair> nbrData(fromSlave);
00079 
00080             forAll(nbrData, i)
00081             {
00082                 if (findIndex(allComms, nbrData[i]) == -1)
00083                 {
00084                     label sz = allComms.size();
00085                     allComms.setSize(sz+1);
00086                     allComms[sz] = nbrData[i];
00087                 }
00088             }
00089         }
00090         // Send back
00091         for
00092         (
00093             int slave=Pstream::firstSlave();
00094             slave<=Pstream::lastSlave();
00095             slave++
00096         )
00097         {
00098             OPstream toSlave(Pstream::blocking, slave);
00099             toSlave << allComms;
00100         }
00101     }
00102     else
00103     {
00104         {
00105             OPstream toMaster(Pstream::blocking, Pstream::masterNo());
00106             toMaster << allComms;
00107         }
00108         {
00109             IPstream fromMaster(Pstream::blocking, Pstream::masterNo());
00110             fromMaster >> allComms;
00111         }
00112     }
00113 
00114 
00115     // Determine my schedule.
00116     labelList mySchedule
00117     (
00118         commSchedule
00119         (
00120             Pstream::nProcs(),
00121             allComms
00122         ).procSchedule()[Pstream::myProcNo()]
00123     );
00124 
00125     // Processors involved in my schedule
00126     return UIndirectList<labelPair>(allComms, mySchedule);
00127 
00128 
00129     //if (debug)
00130     //{
00131     //    Pout<< "I need to:" << endl;
00132     //    const List<labelPair>& comms = schedule();
00133     //    forAll(comms, i)
00134     //    {
00135     //        const labelPair& twoProcs = comms[i];
00136     //        label sendProc = twoProcs[0];
00137     //        label recvProc = twoProcs[1];
00138     //
00139     //        if (recvProc == Pstream::myProcNo())
00140     //        {
00141     //            Pout<< "    receive from " << sendProc << endl;
00142     //        }
00143     //        else
00144     //        {
00145     //            Pout<< "    send to " << recvProc << endl;
00146     //        }
00147     //    }
00148     //}
00149 }
00150 
00151 
00152 const Foam::List<Foam::labelPair>& Foam::mapDistribute::schedule() const
00153 {
00154     if (schedulePtr_.empty())
00155     {
00156         schedulePtr_.reset
00157         (
00158             new List<labelPair>
00159             (
00160                 schedule(subMap_, constructMap_)
00161             )
00162         );
00163     }
00164     return schedulePtr_();
00165 }
00166 
00167 
00168 // * * * * * * * * * * * * * * * * Constructors  * * * * * * * * * * * * * * //
00169 
00170 //- Construct from components
00171 Foam::mapDistribute::mapDistribute
00172 (
00173     const label constructSize,
00174     const labelListList& subMap,
00175     const labelListList& constructMap
00176 )
00177 :
00178     constructSize_(constructSize),
00179     subMap_(subMap),
00180     constructMap_(constructMap),
00181     schedulePtr_()
00182 {}
00183 
00184 
00185 //- (optionally destructively) construct from components
00186 Foam::mapDistribute::mapDistribute
00187 (
00188     const label constructSize,
00189     labelListList& subMap,
00190     labelListList& constructMap,
00191     const bool reUse                // clone or reuse
00192 )
00193 :
00194     constructSize_(constructSize),
00195     subMap_(subMap, reUse),
00196     constructMap_(constructMap, reUse),
00197     schedulePtr_()
00198 {}
00199 
00200 
00201 Foam::mapDistribute::mapDistribute
00202 (
00203     const labelList& sendProcs,
00204     const labelList& recvProcs
00205 )
00206 :
00207     constructSize_(0),
00208     schedulePtr_()
00209 {
00210     if (sendProcs.size() != recvProcs.size())
00211     {
00212         FatalErrorIn
00213         (
00214             "mapDistribute::mapDistribute(const labelList&, const labelList&)"
00215         )   << "The send and receive data is not the same length. sendProcs:"
00216             << sendProcs.size() << " recvProcs:" << recvProcs.size()
00217             << abort(FatalError);
00218     }
00219 
00220     // Per processor the number of samples we have to send/receive.
00221     labelList nSend(Pstream::nProcs(), 0);
00222     labelList nRecv(Pstream::nProcs(), 0);
00223 
00224     forAll(sendProcs, sampleI)
00225     {
00226         label sendProc = sendProcs[sampleI];
00227         label recvProc = recvProcs[sampleI];
00228 
00229         // Note that also need to include local communication (both
00230         // RecvProc and sendProc on local processor)
00231 
00232         if (Pstream::myProcNo() == sendProc)
00233         {
00234             // I am the sender. Count destination processor.
00235             nSend[recvProc]++;
00236         }
00237         if (Pstream::myProcNo() == recvProc)
00238         {
00239             // I am the receiver.
00240             nRecv[sendProc]++;
00241         }
00242     }
00243 
00244     subMap_.setSize(Pstream::nProcs());
00245     constructMap_.setSize(Pstream::nProcs());
00246     forAll(nSend, procI)
00247     {
00248         subMap_[procI].setSize(nSend[procI]);
00249         constructMap_[procI].setSize(nRecv[procI]);
00250     }
00251     nSend = 0;
00252     nRecv = 0;
00253 
00254     forAll(sendProcs, sampleI)
00255     {
00256         label sendProc = sendProcs[sampleI];
00257         label recvProc = recvProcs[sampleI];
00258 
00259         if (Pstream::myProcNo() == sendProc)
00260         {
00261             // I am the sender. Store index I need to send.
00262             subMap_[recvProc][nSend[recvProc]++] = sampleI;
00263         }
00264         if (Pstream::myProcNo() == recvProc)
00265         {
00266             // I am the receiver.
00267             constructMap_[sendProc][nRecv[sendProc]++] = sampleI;
00268             // Largest entry inside constructMap
00269             constructSize_ = sampleI+1;
00270         }
00271     }
00272 }
00273 
00274 
00275 Foam::mapDistribute::mapDistribute(const mapDistribute& map)
00276 :
00277     constructSize_(map.constructSize_),
00278     subMap_(map.subMap_),
00279     constructMap_(map.constructMap_),
00280     schedulePtr_()
00281 {}
00282 
00283 
00284 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00285 
00286 void Foam::mapDistribute::compact(const boolList& elemIsUsed)
00287 {
00288     // 1. send back to sender. Have him delete the corresponding element
00289     //    from the submap and do the same to the constructMap locally
00290     //    (and in same order).
00291 
00292     // Send elemIsUsed field to neighbour. Use nonblocking code from
00293     // mapDistribute but in reverse order.
00294     {
00295         List<boolList> sendFields(Pstream::nProcs());
00296 
00297         for (label domain = 0; domain < Pstream::nProcs(); domain++)
00298         {
00299             const labelList& map = constructMap_[domain];
00300 
00301             if (domain != Pstream::myProcNo() && map.size())
00302             {
00303                 boolList& subField = sendFields[domain];
00304                 subField.setSize(map.size());
00305                 forAll(map, i)
00306                 {
00307                     subField[i] = elemIsUsed[map[i]];
00308                 }
00309 
00310                 OPstream::write
00311                 (
00312                     Pstream::nonBlocking,
00313                     domain,
00314                     reinterpret_cast<const char*>(subField.begin()),
00315                     subField.size()*sizeof(bool)
00316                 );
00317             }
00318         }
00319 
00320         // Set up receives from neighbours
00321 
00322         List<boolList> recvFields(Pstream::nProcs());
00323 
00324         for (label domain = 0; domain < Pstream::nProcs(); domain++)
00325         {
00326             const labelList& map = subMap_[domain];
00327 
00328             if (domain != Pstream::myProcNo() && map.size())
00329             {
00330                 recvFields[domain].setSize(map.size());
00331                 IPstream::read
00332                 (
00333                     Pstream::nonBlocking,
00334                     domain,
00335                     reinterpret_cast<char*>(recvFields[domain].begin()),
00336                     recvFields[domain].size()*sizeof(bool)
00337                 );
00338             }
00339         }
00340 
00341 
00342         // Set up 'send' to myself - write directly into recvFields
00343 
00344         {
00345             const labelList& map = constructMap_[Pstream::myProcNo()];
00346 
00347             recvFields[Pstream::myProcNo()].setSize(map.size());
00348             forAll(map, i)
00349             {
00350                 recvFields[Pstream::myProcNo()][i] = elemIsUsed[map[i]];
00351             }
00352         }
00353 
00354 
00355         // Wait for all to finish
00356 
00357         OPstream::waitRequests();
00358         IPstream::waitRequests();
00359 
00360 
00361         // Compact out all submap entries that are referring to unused elements
00362         for (label domain = 0; domain < Pstream::nProcs(); domain++)
00363         {
00364             const labelList& map = subMap_[domain];
00365 
00366             labelList newMap(map.size());
00367             label newI = 0;
00368 
00369             forAll(map, i)
00370             {
00371                 if (recvFields[domain][i])
00372                 {
00373                     // So element is used on destination side
00374                     newMap[newI++] = map[i];
00375                 }
00376             }
00377             if (newI < map.size())
00378             {
00379                 newMap.setSize(newI);
00380                 subMap_[domain].transfer(newMap);
00381             }
00382         }
00383     }
00384 
00385 
00386     // 2. remove from construct map - since end-result (element in elemIsUsed)
00387     //    not used.
00388 
00389     label maxConstructIndex = -1;
00390 
00391     for (label domain = 0; domain < Pstream::nProcs(); domain++)
00392     {
00393         const labelList& map = constructMap_[domain];
00394 
00395         labelList newMap(map.size());
00396         label newI = 0;
00397 
00398         forAll(map, i)
00399         {
00400             label destinationI = map[i];
00401 
00402             // Is element is used on destination side
00403             if (elemIsUsed[destinationI])
00404             {
00405                 maxConstructIndex = max(maxConstructIndex, destinationI);
00406 
00407                 newMap[newI++] = destinationI;
00408             }
00409         }
00410         if (newI < map.size())
00411         {
00412             newMap.setSize(newI);
00413             constructMap_[domain].transfer(newMap);
00414         }
00415     }
00416 
00417     constructSize_ = maxConstructIndex+1;
00418 
00419     // Clear the schedule (note:not necessary if nothing changed)
00420     schedulePtr_.clear();
00421 }
00422 
00423 
00424 // * * * * * * * * * * * * * * * Member Operators  * * * * * * * * * * * * * //
00425 
00426 void Foam::mapDistribute::operator=(const mapDistribute& rhs)
00427 {
00428     // Check for assignment to self
00429     if (this == &rhs)
00430     {
00431         FatalErrorIn
00432         (
00433             "Foam::mapDistribute::operator=(const Foam::mapDistribute&)"
00434         )   << "Attempted assignment to self"
00435             << abort(FatalError);
00436     }
00437     constructSize_ = rhs.constructSize_;
00438     subMap_ = rhs.subMap_;
00439     constructMap_ = rhs.constructMap_;
00440     schedulePtr_.clear();
00441 }
00442 
00443 
00444 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines