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

mapDistributeTemplates.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 <OpenFOAM/Pstream.H>
00027 
00028 // * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //
00029 
00030 // Distribute list.
00031 template<class T>
00032 void Foam::mapDistribute::distribute
00033 (
00034     const Pstream::commsTypes commsType,
00035     const List<labelPair>& schedule,
00036     const label constructSize,
00037     const labelListList& subMap,
00038     const labelListList& constructMap,
00039     List<T>& field
00040 )
00041 {
00042     if (commsType == Pstream::blocking)
00043     {
00044         // Since buffered sending can reuse the field to collect the
00045         // received data.
00046 
00047         // Send sub field to neighbour
00048         for (label domain = 0; domain < Pstream::nProcs(); domain++)
00049         {
00050             const labelList& map = subMap[domain];
00051 
00052             if (domain != Pstream::myProcNo() && map.size())
00053             {
00054                 OPstream toNbr(Pstream::blocking, domain);
00055                 toNbr << UIndirectList<T>(field, map);
00056             }
00057         }
00058 
00059         // Subset myself
00060         const labelList& mySubMap = subMap[Pstream::myProcNo()];
00061 
00062         List<T> subField(mySubMap.size());
00063         forAll(mySubMap, i)
00064         {
00065             subField[i] = field[mySubMap[i]];
00066         }
00067 
00068         // Receive sub field from myself (subField)
00069         const labelList& map = constructMap[Pstream::myProcNo()];
00070 
00071         field.setSize(constructSize);
00072 
00073         forAll(map, i)
00074         {
00075             field[map[i]] = subField[i];
00076         }
00077 
00078         // Receive sub field from neighbour
00079         for (label domain = 0; domain < Pstream::nProcs(); domain++)
00080         {
00081             const labelList& map = constructMap[domain];
00082 
00083             if (domain != Pstream::myProcNo() && map.size())
00084             {
00085                 IPstream fromNbr(Pstream::blocking, domain);
00086                 List<T> subField(fromNbr);
00087 
00088                 if (subField.size() != map.size())
00089                 {
00090                     FatalErrorIn
00091                     (
00092                         "template<class T>\n"
00093                         "void mapDistribute::distribute\n"
00094                         "(\n"
00095                         "    const Pstream::commsTypes commsType,\n"
00096                         "    const List<labelPair>& schedule,\n"
00097                         "    const label constructSize,\n"
00098                         "    const labelListList& subMap,\n"
00099                         "    const labelListList& constructMap,\n"
00100                         "    List<T>& field\n"
00101                         ")\n"
00102                     )   << "Expected from processor " << domain
00103                         << " " << map.size() << " but received "
00104                         << subField.size() << " elements."
00105                         << abort(FatalError);
00106                 }
00107 
00108                 forAll(map, i)
00109                 {
00110                     field[map[i]] = subField[i];
00111                 }
00112             }
00113         }
00114     }
00115     else if (commsType == Pstream::scheduled)
00116     {
00117         // Need to make sure I don't overwrite field with received data
00118         // since the data might need to be sent to another processor. So
00119         // allocate a new field for the results.
00120         List<T> newField(constructSize);
00121 
00122         // Subset myself
00123         UIndirectList<T> subField(field, subMap[Pstream::myProcNo()]);
00124 
00125         // Receive sub field from myself (subField)
00126         const labelList& map = constructMap[Pstream::myProcNo()];
00127 
00128         forAll(map, i)
00129         {
00130             newField[map[i]] = subField[i];
00131         }
00132 
00133         // Schedule will already have pruned 0-sized comms
00134         forAll(schedule, i)
00135         {
00136             const labelPair& twoProcs = schedule[i];
00137             label sendProc = twoProcs[0];
00138             label recvProc = twoProcs[1];
00139 
00140             if (Pstream::myProcNo() == sendProc)
00141             {
00142                 // I am sender. Send to recvProc.
00143                 OPstream toNbr(Pstream::scheduled, recvProc);
00144                 toNbr << UIndirectList<T>(field, subMap[recvProc]);
00145             }
00146             else
00147             {
00148                 // I am receiver. Receive from sendProc.
00149                 IPstream fromNbr(Pstream::scheduled, sendProc);
00150                 List<T> subField(fromNbr);
00151 
00152                 const labelList& map = constructMap[sendProc];
00153 
00154                 if (subField.size() != map.size())
00155                 {
00156                     FatalErrorIn
00157                     (
00158                         "template<class T>\n"
00159                         "void mapDistribute::distribute\n"
00160                         "(\n"
00161                         "    const Pstream::commsTypes commsType,\n"
00162                         "    const List<labelPair>& schedule,\n"
00163                         "    const label constructSize,\n"
00164                         "    const labelListList& subMap,\n"
00165                         "    const labelListList& constructMap,\n"
00166                         "    List<T>& field\n"
00167                         ")\n"
00168                     )   << "Expected from processor " << sendProc
00169                         << " " << map.size() << " but received "
00170                         << subField.size() << " elements."
00171                         << abort(FatalError);
00172                 }
00173 
00174                 forAll(map, i)
00175                 {
00176                     newField[map[i]] = subField[i];
00177                 }
00178             }
00179         }
00180         field.transfer(newField);
00181     }
00182     else if (commsType == Pstream::nonBlocking)
00183     {
00184         if (!contiguous<T>())
00185         {
00186             FatalErrorIn
00187             (
00188                 "template<class T>\n"
00189                 "void mapDistribute::distribute\n"
00190                 "(\n"
00191                 "    const Pstream::commsTypes commsType,\n"
00192                 "    const List<labelPair>& schedule,\n"
00193                 "    const label constructSize,\n"
00194                 "    const labelListList& subMap,\n"
00195                 "    const labelListList& constructMap,\n"
00196                 "    List<T>& field\n"
00197                 ")\n"
00198             )   << "Non-blocking only supported for contiguous data."
00199                 << exit(FatalError);
00200         }
00201 
00202         // Set up sends to neighbours
00203 
00204         List<List<T > > sendFields(Pstream::nProcs());
00205 
00206         for (label domain = 0; domain < Pstream::nProcs(); domain++)
00207         {
00208             const labelList& map = subMap[domain];
00209 
00210             if (domain != Pstream::myProcNo() && map.size())
00211             {
00212                 List<T>& subField = sendFields[domain];
00213                 subField.setSize(map.size());
00214                 forAll(map, i)
00215                 {
00216                     subField[i] = field[map[i]];
00217                 }
00218 
00219                 OPstream::write
00220                 (
00221                     Pstream::nonBlocking,
00222                     domain,
00223                     reinterpret_cast<const char*>(subField.begin()),
00224                     subField.size()*sizeof(T)
00225                 );
00226             }
00227         }
00228 
00229         // Set up receives from neighbours
00230 
00231         List<List<T > > recvFields(Pstream::nProcs());
00232 
00233         for (label domain = 0; domain < Pstream::nProcs(); domain++)
00234         {
00235             const labelList& map = constructMap[domain];
00236 
00237             if (domain != Pstream::myProcNo() && map.size())
00238             {
00239                 recvFields[domain].setSize(map.size());
00240                 IPstream::read
00241                 (
00242                     Pstream::nonBlocking,
00243                     domain,
00244                     reinterpret_cast<char*>(recvFields[domain].begin()),
00245                     recvFields[domain].size()*sizeof(T)
00246                 );
00247             }
00248         }
00249 
00250 
00251         // Set up 'send' to myself
00252 
00253         {
00254             const labelList& map = subMap[Pstream::myProcNo()];
00255 
00256             List<T>& subField = sendFields[Pstream::myProcNo()];
00257             subField.setSize(map.size());
00258             forAll(map, i)
00259             {
00260                 subField[i] = field[map[i]];
00261             }
00262         }
00263 
00264 
00265         // Combine bits. Note that can reuse field storage
00266 
00267         field.setSize(constructSize);
00268 
00269 
00270         // Receive sub field from myself (sendFields[Pstream::myProcNo()])
00271         {
00272             const labelList& map = constructMap[Pstream::myProcNo()];
00273             const List<T>& subField = sendFields[Pstream::myProcNo()];
00274 
00275             forAll(map, i)
00276             {
00277                 field[map[i]] = subField[i];
00278             }
00279         }
00280 
00281 
00282         // Wait for all to finish
00283 
00284         OPstream::waitRequests();
00285         IPstream::waitRequests();
00286 
00287         // Collect neighbour fields
00288 
00289         for (label domain = 0; domain < Pstream::nProcs(); domain++)
00290         {
00291             const labelList& map = constructMap[domain];
00292 
00293             if (domain != Pstream::myProcNo() && map.size())
00294             {
00295                 if (recvFields[domain].size() != map.size())
00296                 {
00297                     FatalErrorIn
00298                     (
00299                         "template<class T>\n"
00300                         "void mapDistribute::distribute\n"
00301                         "(\n"
00302                         "    const Pstream::commsTypes commsType,\n"
00303                         "    const List<labelPair>& schedule,\n"
00304                         "    const label constructSize,\n"
00305                         "    const labelListList& subMap,\n"
00306                         "    const labelListList& constructMap,\n"
00307                         "    List<T>& field\n"
00308                         ")\n"
00309                     )   << "Expected from processor " << domain
00310                         << " " << map.size() << " but received "
00311                         << recvFields[domain].size() << " elements."
00312                         << abort(FatalError);
00313                 }
00314 
00315                 forAll(map, i)
00316                 {
00317                     field[map[i]] = recvFields[domain][i];
00318                 }
00319             }
00320         }
00321     }
00322     else
00323     {
00324         FatalErrorIn("mapDistribute::distribute(..)")
00325             << "Unknown communication schedule " << commsType
00326             << abort(FatalError);
00327     }
00328 }
00329 
00330 
00331 // Distribute list.
00332 template<class T, class CombineOp>
00333 void Foam::mapDistribute::distribute
00334 (
00335     const Pstream::commsTypes commsType,
00336     const List<labelPair>& schedule,
00337     const label constructSize,
00338     const labelListList& subMap,
00339     const labelListList& constructMap,
00340     List<T>& field,
00341     const CombineOp& cop,
00342     const T& nullValue
00343 )
00344 {
00345     if (commsType == Pstream::blocking)
00346     {
00347         // Since buffered sending can reuse the field to collect the
00348         // received data.
00349 
00350         // Send sub field to neighbour
00351         for (label domain = 0; domain < Pstream::nProcs(); domain++)
00352         {
00353             const labelList& map = subMap[domain];
00354 
00355             if (domain != Pstream::myProcNo() && map.size())
00356             {
00357                 OPstream toNbr(Pstream::blocking, domain);
00358                 toNbr << UIndirectList<T>(field, map);
00359             }
00360         }
00361 
00362         // Subset myself
00363         const labelList& mySubMap = subMap[Pstream::myProcNo()];
00364 
00365         List<T> subField(mySubMap.size());
00366         forAll(mySubMap, i)
00367         {
00368             subField[i] = field[mySubMap[i]];
00369         }
00370 
00371         // Receive sub field from myself (subField)
00372         const labelList& map = constructMap[Pstream::myProcNo()];
00373 
00374         field.setSize(constructSize);
00375         field = nullValue;
00376 
00377         forAll(map, i)
00378         {
00379             cop(field[map[i]], subField[i]);
00380         }
00381 
00382         // Receive sub field from neighbour
00383         for (label domain = 0; domain < Pstream::nProcs(); domain++)
00384         {
00385             const labelList& map = constructMap[domain];
00386 
00387             if (domain != Pstream::myProcNo() && map.size())
00388             {
00389                 IPstream fromNbr(Pstream::blocking, domain);
00390                 List<T> subField(fromNbr);
00391 
00392                 if (subField.size() != map.size())
00393                 {
00394                     FatalErrorIn
00395                     (
00396                         "template<class T>\n"
00397                         "void mapDistribute::distribute\n"
00398                         "(\n"
00399                         "    const Pstream::commsTypes commsType,\n"
00400                         "    const List<labelPair>& schedule,\n"
00401                         "    const label constructSize,\n"
00402                         "    const labelListList& subMap,\n"
00403                         "    const labelListList& constructMap,\n"
00404                         "    List<T>& field\n"
00405                         ")\n"
00406                     )   << "Expected from processor " << domain
00407                         << " " << map.size() << " but received "
00408                         << subField.size() << " elements."
00409                         << abort(FatalError);
00410                 }
00411 
00412                 forAll(map, i)
00413                 {
00414                     cop(field[map[i]], subField[i]);
00415                 }
00416             }
00417         }
00418     }
00419     else if (commsType == Pstream::scheduled)
00420     {
00421         // Need to make sure I don't overwrite field with received data
00422         // since the data might need to be sent to another processor. So
00423         // allocate a new field for the results.
00424         List<T> newField(constructSize, nullValue);
00425 
00426         // Subset myself
00427         UIndirectList<T> subField(field, subMap[Pstream::myProcNo()]);
00428 
00429         // Receive sub field from myself (subField)
00430         const labelList& map = constructMap[Pstream::myProcNo()];
00431 
00432         forAll(map, i)
00433         {
00434             cop(newField[map[i]], subField[i]);
00435         }
00436 
00437         // Schedule will already have pruned 0-sized comms
00438         forAll(schedule, i)
00439         {
00440             const labelPair& twoProcs = schedule[i];
00441             label sendProc = twoProcs[0];
00442             label recvProc = twoProcs[1];
00443 
00444             if (Pstream::myProcNo() == sendProc)
00445             {
00446                 // I am sender. Send to recvProc.
00447                 OPstream toNbr(Pstream::scheduled, recvProc);
00448                 toNbr << UIndirectList<T>(field, subMap[recvProc]);
00449             }
00450             else
00451             {
00452                 // I am receiver. Receive from sendProc.
00453                 IPstream fromNbr(Pstream::scheduled, sendProc);
00454                 List<T> subField(fromNbr);
00455 
00456                 const labelList& map = constructMap[sendProc];
00457 
00458                 if (subField.size() != map.size())
00459                 {
00460                     FatalErrorIn
00461                     (
00462                         "template<class T>\n"
00463                         "void mapDistribute::distribute\n"
00464                         "(\n"
00465                         "    const Pstream::commsTypes commsType,\n"
00466                         "    const List<labelPair>& schedule,\n"
00467                         "    const label constructSize,\n"
00468                         "    const labelListList& subMap,\n"
00469                         "    const labelListList& constructMap,\n"
00470                         "    List<T>& field\n"
00471                         ")\n"
00472                     )   << "Expected from processor " << sendProc
00473                         << " " << map.size() << " but received "
00474                         << subField.size() << " elements."
00475                         << abort(FatalError);
00476                 }
00477 
00478                 forAll(map, i)
00479                 {
00480                     cop(newField[map[i]], subField[i]);
00481                 }
00482             }
00483         }
00484         field.transfer(newField);
00485     }
00486     else if (commsType == Pstream::nonBlocking)
00487     {
00488         if (!contiguous<T>())
00489         {
00490             FatalErrorIn
00491             (
00492                 "template<class T>\n"
00493                 "void mapDistribute::distribute\n"
00494                 "(\n"
00495                 "    const Pstream::commsTypes commsType,\n"
00496                 "    const List<labelPair>& schedule,\n"
00497                 "    const label constructSize,\n"
00498                 "    const labelListList& subMap,\n"
00499                 "    const labelListList& constructMap,\n"
00500                 "    List<T>& field\n"
00501                 ")\n"
00502             )   << "Non-blocking only supported for contiguous data."
00503                 << exit(FatalError);
00504         }
00505 
00506         // Set up sends to neighbours
00507 
00508         List<List<T > > sendFields(Pstream::nProcs());
00509 
00510         for (label domain = 0; domain < Pstream::nProcs(); domain++)
00511         {
00512             const labelList& map = subMap[domain];
00513 
00514             if (domain != Pstream::myProcNo() && map.size())
00515             {
00516                 List<T>& subField = sendFields[domain];
00517                 subField.setSize(map.size());
00518                 forAll(map, i)
00519                 {
00520                     subField[i] = field[map[i]];
00521                 }
00522 
00523                 OPstream::write
00524                 (
00525                     Pstream::nonBlocking,
00526                     domain,
00527                     reinterpret_cast<const char*>(subField.begin()),
00528                     subField.size()*sizeof(T)
00529                 );
00530             }
00531         }
00532 
00533         // Set up receives from neighbours
00534 
00535         List<List<T > > recvFields(Pstream::nProcs());
00536 
00537         for (label domain = 0; domain < Pstream::nProcs(); domain++)
00538         {
00539             const labelList& map = constructMap[domain];
00540 
00541             if (domain != Pstream::myProcNo() && map.size())
00542             {
00543                 recvFields[domain].setSize(map.size());
00544                 IPstream::read
00545                 (
00546                     Pstream::nonBlocking,
00547                     domain,
00548                     reinterpret_cast<char*>(recvFields[domain].begin()),
00549                     recvFields[domain].size()*sizeof(T)
00550                 );
00551             }
00552         }
00553 
00554         // Set up 'send' to myself
00555 
00556         {
00557             const labelList& map = subMap[Pstream::myProcNo()];
00558 
00559             List<T>& subField = sendFields[Pstream::myProcNo()];
00560             subField.setSize(map.size());
00561             forAll(map, i)
00562             {
00563                 subField[i] = field[map[i]];
00564             }
00565         }
00566 
00567 
00568         // Combine bits. Note that can reuse field storage
00569 
00570         field.setSize(constructSize);
00571         field = nullValue;
00572 
00573         // Receive sub field from myself (subField)
00574         {
00575             const labelList& map = constructMap[Pstream::myProcNo()];
00576             const List<T>& subField = sendFields[Pstream::myProcNo()];
00577 
00578             forAll(map, i)
00579             {
00580                 cop(field[map[i]], subField[i]);
00581             }
00582         }
00583 
00584 
00585         // Wait for all to finish
00586 
00587         OPstream::waitRequests();
00588         IPstream::waitRequests();
00589 
00590         // Collect neighbour fields
00591 
00592         for (label domain = 0; domain < Pstream::nProcs(); domain++)
00593         {
00594             const labelList& map = constructMap[domain];
00595 
00596             if (domain != Pstream::myProcNo() && map.size())
00597             {
00598                 if (recvFields[domain].size() != map.size())
00599                 {
00600                     FatalErrorIn
00601                     (
00602                         "template<class T>\n"
00603                         "void mapDistribute::distribute\n"
00604                         "(\n"
00605                         "    const Pstream::commsTypes commsType,\n"
00606                         "    const List<labelPair>& schedule,\n"
00607                         "    const label constructSize,\n"
00608                         "    const labelListList& subMap,\n"
00609                         "    const labelListList& constructMap,\n"
00610                         "    List<T>& field\n"
00611                         ")\n"
00612                     )   << "Expected from processor " << domain
00613                         << " " << map.size() << " but received "
00614                         << recvFields[domain].size() << " elements."
00615                         << abort(FatalError);
00616                 }
00617 
00618                 forAll(map, i)
00619                 {
00620                     cop(field[map[i]], recvFields[domain][i]);
00621                 }
00622             }
00623         }
00624     }
00625     else
00626     {
00627         FatalErrorIn("mapDistribute::distribute(..)")
00628             << "Unknown communication schedule " << commsType
00629             << abort(FatalError);
00630     }
00631 }
00632 
00633 
00634 // ************************ vim: set sw=4 sts=4 et: ************************ //
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines