]> SALOME platform Git repositories - tools/medcoupling.git/blob - src/ParaMEDMEM/CommInterface.cxx
Salome HOME
[EDF21149] : Improvements for // spliter
[tools/medcoupling.git] / src / ParaMEDMEM / CommInterface.cxx
1 // Copyright (C) 2007-2020  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19
20 #include "CommInterface.hxx"
21
22 #include <numeric>
23
24 namespace MEDCoupling
25 {
26   /*! \anchor CommInterface-det
27      \class CommInterface
28
29     The class \a CommInterface is the gateway to the MPI library.
30     It is a wrapper around all MPI calls, thus trying to abstract the rest of the code from using the direct MPI API
31     (but this is not strictly respected overall in practice ...). It is used in all
32     the \ref parallel "DEC related classes".
33
34     It is typically instantiated after the MPI_Init() call in a program and is afterwards passed as a
35     parameter to the constructors of various \ref parallel "parallel objects" so that they access the
36     MPI library via this common interface.
37
38     As an example, the following code excerpt initializes a processor group made of the zero processor.
39
40     \verbatim
41     #include "CommInterface.hxx"
42     #include "ProcessorGroup.hxx"
43
44     int main(int argc, char** argv)
45     {
46     //initialization
47     MPI_Init(&argc, &argv);
48     MEDCoupling::CommInterface comm_interface;
49
50     //setting up a processor group with proc 0
51     set<int> procs;
52     procs.insert(0);
53     MEDCoupling::ProcessorGroup group(procs, comm_interface);
54
55     //cleanup
56     MPI_Finalize();
57     }
58     \endverbatim
59   */
60
61   /*!
62    * Generalized AllGather collective communication.
63    * This method send input \a array to all procs.
64    */
65   void CommInterface::allGatherArrays(MPI_Comm comm, const DataArrayIdType *array, std::unique_ptr<mcIdType[]>& result, std::unique_ptr<mcIdType[]>& resultIndex) const
66   {
67     int size;
68     this->commSize(comm,&size);
69     std::unique_ptr<mcIdType[]> nbOfElems(new mcIdType[size]);
70     mcIdType nbOfCellsRequested(array->getNumberOfTuples());
71     this->allGather(&nbOfCellsRequested,1,MPI_ID_TYPE,nbOfElems.get(),1,MPI_ID_TYPE,comm);
72     mcIdType nbOfCellIdsSum(std::accumulate(nbOfElems.get(),nbOfElems.get()+size,0));
73     result.reset(new mcIdType[nbOfCellIdsSum]);
74     std::unique_ptr<int[]> nbOfElemsInt( CommInterface::ToIntArray<mcIdType>(nbOfElems,size) );
75     std::unique_ptr<int[]> offsetsIn( CommInterface::ComputeOffset(nbOfElemsInt,size) );
76     this->allGatherV(array->begin(),nbOfCellsRequested,MPI_ID_TYPE,result.get(),nbOfElemsInt.get(),offsetsIn.get(),MPI_ID_TYPE,comm);
77     resultIndex = std::move(nbOfElems);
78   }
79
80   /*!
81   * Generalized AllToAll collective communication.
82   */
83   void CommInterface::allToAllArrays(MPI_Comm comm, const std::vector< MCAuto<DataArrayIdType> >& arrays, std::vector< MCAuto<DataArrayIdType> >& arraysOut) const
84   {
85     int size;
86     this->commSize(comm,&size);
87     if( arrays.size() != ToSizeT(size) )
88       throw INTERP_KERNEL::Exception("AllToAllArrays : internal error ! Invalid size of input array.");
89       
90     std::vector< const DataArrayIdType *> arraysBis(FromVecAutoToVecOfConst<DataArrayIdType>(arrays));
91     std::unique_ptr<mcIdType[]> nbOfElems2(new mcIdType[size]),nbOfElems3(new mcIdType[size]);
92     for(int curRk = 0 ; curRk < size ; ++curRk)
93     {
94       nbOfElems3[curRk] = arrays[curRk]->getNumberOfTuples();
95     }
96     this->allToAll(nbOfElems3.get(),1,MPI_ID_TYPE,nbOfElems2.get(),1,MPI_ID_TYPE,comm);
97     mcIdType nbOfCellIdsSum(std::accumulate(nbOfElems2.get(),nbOfElems2.get()+size,0));
98     MCAuto<DataArrayIdType> cellIdsFromProcs(DataArrayIdType::New());
99     cellIdsFromProcs->alloc(nbOfCellIdsSum,1);
100     std::unique_ptr<int[]> nbOfElemsInt( CommInterface::ToIntArray<mcIdType>(nbOfElems3,size) ),nbOfElemsOutInt( CommInterface::ToIntArray<mcIdType>(nbOfElems2,size) );
101     std::unique_ptr<int[]> offsetsIn( CommInterface::ComputeOffset(nbOfElemsInt,size) ), offsetsOut( CommInterface::ComputeOffset(nbOfElemsOutInt,size) );
102     {
103       MCAuto<DataArrayIdType> arraysAcc(DataArrayIdType::Aggregate(arraysBis));
104       this->allToAllV(arraysAcc->begin(),nbOfElemsInt.get(),offsetsIn.get(),MPI_ID_TYPE,
105                       cellIdsFromProcs->getPointer(),nbOfElemsOutInt.get(),offsetsOut.get(),MPI_ID_TYPE,comm);
106     }
107     std::unique_ptr<mcIdType[]> offsetsOutIdType( CommInterface::ComputeOffset(nbOfElems2,size) );
108     // build output arraysOut by spliting cellIdsFromProcs into parts
109     arraysOut.resize(size);
110     for(int curRk = 0 ; curRk < size ; ++curRk)
111     {
112       arraysOut[curRk] = DataArrayIdType::NewFromArray(cellIdsFromProcs->begin()+offsetsOutIdType[curRk],cellIdsFromProcs->begin()+offsetsOutIdType[curRk]+nbOfElems2[curRk]);
113     }
114   }
115 }