Merge branch 'master' of ssh://git.code.sf.net/p/foam-extend/foam-extend-3.2
[foam-extend-3.2.git] / src / foam / db / IOstreams / Pstreams / gatherScatter.C
blobb26803b6afe545224a0239269b487606c2c425c1
1 /*---------------------------------------------------------------------------*\
2   =========                 |
3   \\      /  F ield         | foam-extend: Open Source CFD
4    \\    /   O peration     | Version:     3.2
5     \\  /    A nd           | Web:         http://www.foam-extend.org
6      \\/     M anipulation  | For copyright notice see file Copyright
7 -------------------------------------------------------------------------------
8 License
9     This file is part of foam-extend.
11     foam-extend is free software: you can redistribute it and/or modify it
12     under the terms of the GNU General Public License as published by the
13     Free Software Foundation, either version 3 of the License, or (at your
14     option) any later version.
16     foam-extend is distributed in the hope that it will be useful, but
17     WITHOUT ANY WARRANTY; without even the implied warranty of
18     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19     General Public License for more details.
21     You should have received a copy of the GNU General Public License
22     along with foam-extend.  If not, see <http://www.gnu.org/licenses/>.
24 Description
25     Gather data from all processors onto single processor according to some
26     communication schedule (usually linear-to-master or tree-to-master).
27     The gathered data will be a single value constructed from the values
28     on individual processors using a user-specified operator.
30 \*---------------------------------------------------------------------------*/
32 #include "OPstream.H"
33 #include "IPstream.H"
34 #include "contiguous.H"
36 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
38 namespace Foam
41 // * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //
43 template <class T, class BinaryOp>
44 void Pstream::gather
46     const List<Pstream::commsStruct>& comms,
47     T& Value,
48     const BinaryOp& bop
51     if (Pstream::parRun())
52     {
53         // Get my communication order
54         const commsStruct& myComm = comms[Pstream::myProcNo()];
56         // Receive from my downstairs neighbours
57         forAll(myComm.below(), belowI)
58         {
59             T value;
61             if (contiguous<T>())
62             {
63                 IPstream::read
64                 (
65                     Pstream::scheduled,
66                     myComm.below()[belowI],
67                     reinterpret_cast<char*>(&value),
68                     sizeof(T)
69                 );
70             }
71             else
72             {
73                 IPstream fromBelow(Pstream::scheduled, myComm.below()[belowI]);
74                 fromBelow >> value;
75             }
77             Value = bop(Value, value);
78         }
80         // Send up Value
81         if (myComm.above() != -1)
82         {
83             if (contiguous<T>())
84             {
85                 OPstream::write
86                 (
87                     Pstream::scheduled,
88                     myComm.above(),
89                     reinterpret_cast<const char*>(&Value),
90                     sizeof(T)
91                 );
92             }
93             else
94             {
95                 OPstream toAbove(Pstream::scheduled, myComm.above());
96                 toAbove << Value;
97             }
98         }
99     }
103 template <class T, class BinaryOp>
104 void Pstream::gather(T& Value, const BinaryOp& bop)
106     if (Pstream::nProcs() < Pstream::nProcsSimpleSum())
107     {
108         gather(Pstream::linearCommunication(), Value, bop);
109     }
110     else
111     {
112         gather(Pstream::treeCommunication(), Value, bop);
113     }
117 template <class T>
118 void Pstream::scatter(const List<Pstream::commsStruct>& comms, T& Value)
120     if (Pstream::parRun())
121     {
122         // Get my communication order
123         const commsStruct& myComm = comms[Pstream::myProcNo()];
125         // Receive from up
126         if (myComm.above() != -1)
127         {
128             if (contiguous<T>())
129             {
130                 IPstream::read
131                 (
132                     Pstream::scheduled,
133                     myComm.above(),
134                     reinterpret_cast<char*>(&Value),
135                     sizeof(T)
136                 );
137             }
138             else
139             {
140                 IPstream fromAbove(Pstream::scheduled, myComm.above());
141                 fromAbove >> Value;
142             }
143         }
145         // Send to my downstairs neighbours
146         forAll(myComm.below(), belowI)
147         {
148             if (contiguous<T>())
149             {
150                 OPstream::write
151                 (
152                     Pstream::scheduled,
153                     myComm.below()[belowI],
154                     reinterpret_cast<const char*>(&Value),
155                     sizeof(T)
156                 );
157             }
158             else
159             {
160                 OPstream toBelow(Pstream::scheduled,myComm.below()[belowI]);
161                 toBelow << Value;
162             }
163         }
164     }
168 template <class T>
169 void Pstream::scatter(T& Value)
171     if (Pstream::nProcs() < Pstream::nProcsSimpleSum())
172     {
173         scatter(Pstream::linearCommunication(), Value);
174     }
175     else
176     {
177         scatter(Pstream::treeCommunication(), Value);
178     }
182 // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
184 } // End namespace Foam
186 // ************************************************************************* //