Salome HOME
4ae9e87652057a7eadd2483652185fe1593caaf3
[tools/medcoupling.git] / src / ParaMEDMEM / ParaSkyLineArray.cxx
1 //
2 // Copyright (C) 2020  CEA/DEN, EDF R&D
3 //
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License, or (at your option) any later version.
8 //
9 // This library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 //
20 // Author : Anthony Geay (EDF R&D)
21
22 #include "ParaSkyLineArray.hxx"
23 #include "ProcessorGroup.hxx"
24 #include "MPIProcessorGroup.hxx"
25 #include "Topology.hxx"
26 #include "BlockTopology.hxx"
27 #include "CommInterface.hxx"
28 #include "MEDCouplingMemArray.hxx"
29
30 #include "mpi.h"
31
32 #include <fstream>
33 #include <sstream>
34 #include <numeric>
35 #include <memory>
36 #include <vector>
37
38 using namespace MEDCoupling;
39
40 ParaSkyLineArray *ParaSkyLineArray::New(MEDCouplingSkyLineArray *ska, DataArrayIdType *globalIds)
41 {
42   return new ParaSkyLineArray(ska,globalIds);
43 }
44
45 MEDCouplingSkyLineArray *ParaSkyLineArray::getSkyLineArray() const
46 {
47   return this->_ska.iAmATrollConstCast();
48 }
49
50 DataArrayIdType *ParaSkyLineArray::getGlobalIdsArray() const
51 {
52   return this->_global_ids.iAmATrollConstCast();
53 }
54
55 ParaSkyLineArray::ParaSkyLineArray(MEDCouplingSkyLineArray *ska, DataArrayIdType *globalIds)
56 {
57   _ska.takeRef(ska);
58   _global_ids.takeRef(globalIds);
59   _ska.checkNotNull();
60   _global_ids.checkNotNull();
61   if(_ska->getNumberOf() != _global_ids->getNumberOfTuples())
62   {
63     std::ostringstream oss; oss << "ParaSkyLineArray constructor : mismatch between # globalIds (" << _global_ids->getNumberOfTuples() << ") and len of indices in SkyLineArray (" << _ska->getNumberOf() << ").";
64     throw INTERP_KERNEL::Exception(oss.str());
65   }
66 }
67
68 std::size_t ParaSkyLineArray::getHeapMemorySizeWithoutChildren() const
69 {
70   return 0;
71 }
72
73 std::vector<const BigMemoryObject *> ParaSkyLineArray::getDirectChildrenWithNull() const
74 {
75   return {_ska,_global_ids};
76 }
77
78 MCAuto<ParaSkyLineArray> ParaSkyLineArray::equiRedistribute(mcIdType nbOfEntities) const
79 {
80   MPI_Comm comm(MPI_COMM_WORLD);
81   CommInterface ci;
82   int size;
83   ci.commSize(comm,&size);
84   std::vector< MCAuto<MEDCouplingSkyLineArray> > skToBeSent(size);
85   std::vector< MCAuto<DataArrayIdType> > idsCaptured(size);
86   for(int curRk = 0 ; curRk < size ; ++curRk)
87   {
88     mcIdType curStart(0),curEnd(0);
89     DataArrayIdType::GetSlice(0,nbOfEntities,1,curRk,size,curStart,curEnd);
90     MCAuto<DataArrayIdType> idsInGlobalIds(_global_ids->findIdsInRange(curStart,curEnd));
91     idsCaptured[curRk] = _global_ids->selectByTupleIdSafe(idsInGlobalIds->begin(),idsInGlobalIds->end());
92     {
93       DataArrayIdType *tmpValues(nullptr),*tmpIndex(nullptr);
94       DataArrayIdType::ExtractFromIndexedArrays(idsInGlobalIds->begin(),idsInGlobalIds->end(),this->_ska->getValuesArray(),this->_ska->getIndexArray(),tmpValues,tmpIndex);
95       MCAuto<DataArrayIdType> tmpValues2(tmpValues),tmpIndex2(tmpIndex);
96       skToBeSent[curRk] = MEDCouplingSkyLineArray::New(tmpIndex,tmpValues);
97     }
98   }
99   // communication : 3 arrays are going to be all2allized : ids, SkyLine index and SyLine values
100   MCAuto<DataArrayIdType> aggregatedIds,indices,values;
101   {
102     std::vector< MCAuto<DataArrayIdType> > myRkIdsCaptured;
103     ci.allToAllArrays(comm,idsCaptured,myRkIdsCaptured);
104     aggregatedIds = DataArrayIdType::Aggregate(FromVecAutoToVecOfConst<DataArrayIdType>(myRkIdsCaptured));
105   }
106   {
107     std::vector< MCAuto<DataArrayIdType> > myRkSkIndex;
108     std::vector< MCAuto<DataArrayIdType> > indexToBeSent(MEDCouplingSkyLineArray::RetrieveVecIndex(skToBeSent));
109     ci.allToAllArrays(comm,indexToBeSent,myRkSkIndex);
110     indices = DataArrayIdType::AggregateIndexes(FromVecAutoToVecOfConst<DataArrayIdType>(myRkSkIndex));
111   }
112   {
113     std::vector< MCAuto<DataArrayIdType> > myRkSkValues;
114     std::vector< MCAuto<DataArrayIdType> > valuesToBeSent(MEDCouplingSkyLineArray::RetrieveVecValues(skToBeSent));
115     ci.allToAllArrays(comm,valuesToBeSent,myRkSkValues);
116     values = DataArrayIdType::Aggregate(FromVecAutoToVecOfConst<DataArrayIdType>(myRkSkValues));
117   }
118   // Reorder results coming from other procs
119   MCAuto<DataArrayIdType> aggregatedIdsSort(aggregatedIds->deepCopy()); aggregatedIdsSort->sort();
120   MCAuto<DataArrayIdType> idsIntoAggregatedIds(DataArrayIdType::FindPermutationFromFirstToSecondDuplicate(aggregatedIdsSort,aggregatedIds));
121   MCAuto<DataArrayIdType> indicesSorted,valuesSorted;
122   {
123     DataArrayIdType *indicesSortedTmp(nullptr),*valuesSortedTmp(nullptr);
124     DataArrayIdType::ExtractFromIndexedArrays(idsIntoAggregatedIds->begin(),idsIntoAggregatedIds->end(),values,indices,valuesSortedTmp,indicesSortedTmp);
125     indicesSorted = indicesSortedTmp; valuesSorted=valuesSortedTmp;
126   }
127   MCAuto<DataArrayIdType> idxOfSameIds(aggregatedIdsSort->indexOfSameConsecutiveValueGroups());
128   //
129   MCAuto<DataArrayIdType> globalIdsOut(aggregatedIdsSort->buildUnique());
130   MCAuto<MEDCouplingSkyLineArray> skOut(MEDCouplingSkyLineArray::New(indicesSorted,valuesSorted));
131   skOut = skOut->groupPacks(idxOfSameIds);//group partial packs coming from different procs
132   skOut = skOut->uniqueNotSortedByPack();//remove duplicates
133   MCAuto<ParaSkyLineArray> ret(ParaSkyLineArray::New(skOut,globalIdsOut));
134   return ret.retn();
135 }
136