Salome HOME
8f2b45cc04e7b3ad1273ca7233a02a6a68b63add
[tools/medcoupling.git] / src / MEDPartitioner / MEDPARTITIONER_PTScotchGraph.cxx
1 // Copyright (C) 2017-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 "MEDPARTITIONER_PTScotchGraph.hxx"
21 #include "MEDPARTITIONER_Utils.hxx"
22
23 #include "MEDCouplingSkyLineArray.hxx"
24 #include "MEDCouplingMemArray.hxx"
25 #include "MCType.hxx"
26
27 #include <cstdio>
28 #include <memory>
29 #include <mpi.h>
30
31 #ifdef MED_ENABLE_PTSCOTCH
32 extern "C"
33 {
34 #define restrict
35 #include "ptscotch.h"
36 }
37 #endif
38
39 using namespace MEDPARTITIONER;
40
41
42 PTSCOTCHGraph::PTSCOTCHGraph(MEDCoupling::MEDCouplingSkyLineArray *graph, int *edgeweight, DataArrayIdType *vlbloctab):Graph(graph,edgeweight),_vlbloctab(vlbloctab)
43 {
44 }
45
46 PTSCOTCHGraph::~PTSCOTCHGraph()
47 {
48 }
49
50 void PTSCOTCHGraph::partGraph(int ndomain, const std::string& options_string, ParaDomainSelector* sel)
51 {
52   if (MyGlobals::_Verbose>10)
53     std::cout << "proc " << MyGlobals::_Rank << " : PTSCOTCHGraph::partGraph" << std::endl;
54   
55   //number of graph vertices
56   int n = FromIdType<int>(_graph->getNumberOf());
57   //graph
58   mcIdType * xadj=const_cast<mcIdType*>(_graph->getIndex());
59   mcIdType * adjncy=const_cast<mcIdType*>(_graph->getValues());
60   //ndomain
61   int nparts=ndomain;
62
63 #if !defined(MED_ENABLE_PTSCOTCH)
64   throw INTERP_KERNEL::Exception("PTSCOTCHGraph::partGraph : PTSCOTCH is not available. Check your products, please.");
65 #else
66   //output parameters
67   std::unique_ptr<mcIdType[]> partition(new mcIdType[n+1]);
68 #ifdef MEDCOUPLING_USE_64BIT_IDS
69   mcIdType *cellWeightPtr(nullptr);
70   std::vector<mcIdType> cellWeightVec;
71   if(_cell_weight)
72   {
73     cellWeightVec.insert(cellWeightVec.end(),_cell_weight,_cell_weight+_graph->getLength());
74     cellWeightPtr = cellWeightVec.data();
75   }
76   mcIdType *edgeWeightPtr(nullptr);
77   std::vector<mcIdType> edgeWeightVec;
78   if(_edge_weight)
79   {
80     edgeWeightVec.insert(edgeWeightVec.end(),_edge_weight,_edge_weight+_graph->getLength());
81     edgeWeightPtr = edgeWeightVec.data();
82   }
83 #else
84   mcIdType *cellWeightPtr(_cell_weight);
85   mcIdType *edgeWeightPtr(_edge_weight);
86 #endif
87   
88   mcIdType *vlbloctab = _vlbloctab?const_cast<mcIdType*>(_vlbloctab->begin()):nullptr;
89
90   SCOTCH_randomReset();
91   SCOTCH_Dgraph scotch_graph;
92   SCOTCH_dgraphInit(&scotch_graph, MPI_COMM_WORLD);
93   SCOTCH_dgraphBuild(&scotch_graph,
94                      0,             // baseval               , base first indice 0
95                      n,             // vertlocnbr            , nb of local graph nodes
96                      n,             // vertlocmax            , should be set to vertlocnbr for graphs without holes
97                      xadj,          // vertloctab[vertnbr+1] , index vertex table
98                      0,             // vendloctab            , index end vertex table if disjoint, set to zero
99                      cellWeightPtr,  // veloloctab            , graph vertices loads, set to zero
100                      vlbloctab,     // vlblocltab            , vertex label array : global vertex index
101                      xadj[n],       // edgelocnbr            , number of edges
102                      xadj[n],       // edgelocsiz            , same as edgelocnbr if edgeloctab is compact
103                      adjncy,        // edgeloctab[edgelocnbr], global indexes of edges
104                      0,             // edgegsttab            , optional, should be computed internally, set to zero
105                      edgeWeightPtr); // edloloctab            , graph edges loads, set to zero
106   
107   SCOTCH_Strat scotch_strategy;
108   SCOTCH_stratInit(&scotch_strategy);
109   
110   //!user-defined options for the strategy
111   if (options_string!="")
112     SCOTCH_stratGraphMap(&scotch_strategy,options_string.c_str());
113
114   if (nparts>1)
115     {
116       if (MyGlobals::_Verbose>10) std::cout << "SCOTCHGraph::graphPart SCOTCH_graphPart" << std::endl;
117       SCOTCH_dgraphPart(&scotch_graph,nparts,&scotch_strategy,partition.get());
118     }
119   else  //partition for 1 subdomain
120     {
121     for (int i=0; i<n+1; i++)
122       partition[i]=0;
123     }
124   
125   SCOTCH_stratExit(&scotch_strategy);
126   SCOTCH_dgraphExit(&scotch_graph);
127
128   std::vector<mcIdType> index(n+1);
129   std::vector<mcIdType> value(n);
130   index[0]=0;
131   for (int i=0; i<n; i++)
132     {
133       index[i+1]=index[i]+1;
134       value[i]=ToIdType(partition[i]);
135     }
136   
137   //creating a skylinearray with no copy of the index and partition array
138   //the fifth argument true specifies that only the pointers are passed 
139   //to the object
140   _partition = MEDCoupling::MEDCouplingSkyLineArray::New(index,value);
141 #endif
142 }