Flow123d  release_3.0.0-973-g92f55e826
partitioning.cc
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file partitioning.cc
15  * @brief
16  */
17 
18 #include "mesh/partitioning.hh"
19 #include "la/sparse_graph.hh"
20 #include "la/distribution.hh"
21 #include "mesh/side_impl.hh"
22 #include "mesh/long_idx.hh"
23 #include "mesh/mesh.h"
24 #include "mesh/accessors.hh"
25 #include "mesh/range_wrapper.hh"
26 #include "mesh/neighbours.h"
27 
28 #include "petscao.h"
29 
30 
31 namespace IT = Input::Type;
33  return IT::Selection("GraphType",
34  "Different algorithms to make the sparse graph with weighted edges\n"
35  "from the multidimensional mesh. Main difference is dealing with \n"
36  "neighboring of elements of different dimension.")
37  .add_value(any_neighboring, "any_neighboring", "Add an edge for any pair of neighboring elements.")
38  .add_value(any_weight_lower_dim_cuts, "any_weight_lower_dim_cuts", "Same as before and assign higher weight to cuts of lower dimension in order to make them stick to one face.")
39  .add_value(same_dimension_neighboring, "same_dimension_neighboring", "Add an edge for any pair of neighboring elements of the same dimension (bad for matrix multiply).")
40  .close();
41 }
42 
44  return IT::Selection("PartTool", "Select the partitioning tool to use.")
45  .add_value(PETSc, "PETSc", "Use PETSc interface to various partitioning tools.")
46  .add_value(METIS, "METIS", "Use direct interface to Metis.")
47  .close();
48 }
49 
51  static IT::Record input_type = IT::Record("Partition","Setting for various types of mesh partitioning." )
52  .declare_key("tool", Partitioning::get_tool_sel(), IT::Default("\"METIS\""), "Software package used for partitioning. See corresponding selection.")
53  .declare_key("graph_type", Partitioning::get_graph_type_sel(), IT::Default("\"any_neighboring\""), "Algorithm for generating graph and its weights from a multidimensional mesh.")
54  .allow_auto_conversion("graph_type") // mainly in order to allow Default value for the whole record Partition
55  .close();
56  input_type.finish();
57 
58  return input_type;
59 }
60 
61 
63 : mesh_(mesh), in_(in), graph_(NULL), loc_part_(NULL), init_el_ds_(NULL)
64 {
66 }
67 
68 
69 
71  if (loc_part_) delete [] loc_part_;
72  loc_part_ = NULL;
73  if (init_el_ds_) delete init_el_ds_;
74  init_el_ds_ = NULL;
75  if (graph_) delete graph_;
76  graph_ = NULL;
77 }
78 
80  OLD_ASSERT(init_el_ds_, "NULL initial distribution.");
81  return init_el_ds_;
82 }
83 
84 
85 
87  OLD_ASSERT(loc_part_, "NULL local partitioning.");
88  return loc_part_;
89 }
90 
91 
92 
94 
95  Distribution edistr = graph_->get_distr();
96 
97  const Edge *edg;
98  int e_idx;
99  unsigned int i_neigh;
100  int i_s, n_s;
101 
102  // Add nigbouring edges only for "any_*" graph types
103  bool neigh_on = ( in_.val<PartitionGraphType>("graph_type") != same_dimension_neighboring );
104 
105  for (auto ele : mesh_->elements_range()) {
106  // skip non-local elements
107  if ( !edistr.is_local( ele.idx() ) )
108  continue;
109 
110  // for all connected elements
111  for (unsigned int si=0; si<ele->n_sides(); si++) {
112  edg = ele.side(si)->edge();
113 
114  for (unsigned int li=0; li<edg->n_sides; li++) {
115  ASSERT(edg->side(li)->valid()).error("NULL side of edge.");
116  e_idx = edg->side(li)->element().idx();
117 
118  // for elements of connected elements, excluding element itself
119  if ( e_idx != ele.idx() ) {
120  graph_->set_edge( ele.idx(), e_idx );
121  }
122  }
123  }
124 
125  // include connections from lower dim. edge
126  // to the higher dimension
127  if (neigh_on) {
128  for (i_neigh = 0; i_neigh < ele->n_neighs_vb(); i_neigh++) {
129  n_s = ele->neigh_vb[i_neigh]->edge()->n_sides;
130  for (i_s = 0; i_s < n_s; i_s++) {
131  e_idx = ele->neigh_vb[i_neigh]->edge()->side(i_s)->element().idx();
132  graph_->set_edge( ele.idx(), e_idx );
133  graph_->set_edge( e_idx, ele.idx() );
134  }
135  }
136  }
137  }
138  graph_->finalize();
139 }
140 
141 
142 
144 
145 
146  // prepare dual graph
147  switch ( in_.val<PartitionTool>("tool")) {
148  case PETSc:
149  init_el_ds_ = new Distribution(DistributionBlock(), mesh_->n_elements(), mesh_->get_comm() ); // initial distr.
151 
152  break;
153  case METIS:
154  init_el_ds_ = new Distribution(DistributionLocalized(), mesh_->n_elements(), mesh_->get_comm() ); // initial distr.
156  break;
157  }
158  int mesh_size = mesh_->n_elements();
159  int num_of_procs = init_el_ds_->np();
160  if (mesh_size < num_of_procs) { // check if decomposing is possible
161  THROW( ExcDecomposeMesh() << EI_NElems( mesh_size ) << EI_NProcs( num_of_procs ) );
162  }
163 
165 
166  // compute partitioning
169  delete graph_; graph_ = NULL;
170 }
171 
172 
173 
174 
175 /**
176  * Old UGLY, PETSC dependent method for getting new numbering after partitioning.
177  *
178  * n_ids - given maximal ID used in id_4_old
179  * id_4_old - given array of size init_el_ds_.size() - assign ID to an old index
180  *
181  * new_ds - new distribution of elements according to current distributed partitioning loc_part_
182  * id_4_loc - IDs for local elements in new distribution, has size new_ds->lsize()
183  * new_4_id - for given ID, the new index, -1 for unknown IDs
184  *
185  */
186 void Partitioning::id_maps(int n_ids, LongIdx *id_4_old,
187  const Distribution &old_ds, LongIdx *loc_part,
188  Distribution * &new_ds, LongIdx * &id_4_loc, LongIdx * &new_4_id) {
189 
190  IS part, new_numbering;
191  unsigned int size = old_ds.size(); // whole size of distr. array
192  int new_counts[old_ds.np()];
193  AO new_old_ao;
194  int *old_4_new;
195  int i_loc;
196 
197  // make distribution and numbering
198  ISCreateGeneral(PETSC_COMM_WORLD, old_ds.lsize(), loc_part, PETSC_COPY_VALUES, &part); // global IS part.
199  ISPartitioningCount(part, old_ds.np(), new_counts); // new size of each proc
200 
201  new_ds = new Distribution((unsigned int *) new_counts, PETSC_COMM_WORLD); // new distribution
202  ISPartitioningToNumbering(part, &new_numbering); // new numbering
203  ISDestroy(&part);
204 
205  old_4_new = new int [size];
206  id_4_loc = new LongIdx [ new_ds->lsize() ];
207  new_4_id = new LongIdx [ n_ids + 1 ];
208 
209  // create whole new->old mapping on each proc
210  AOCreateBasicIS(new_numbering, PETSC_NULL, &new_old_ao); // app ordering= new; petsc ordering = old
211  ISDestroy(&new_numbering);
212  for (unsigned int i = 0; i < size; i++)
213  old_4_new[i] = i;
214  AOApplicationToPetsc(new_old_ao, size, old_4_new);
215  AODestroy(&(new_old_ao));
216 
217  // compute id_4_loc
218  i_loc = 0;
219 
220  for (unsigned int i_new = new_ds->begin(); i_new < new_ds->end(); i_new++) {
221  id_4_loc[i_loc++] = id_4_old[old_4_new[i_new]];
222  }
223  // compute row_4_id
224  for (i_loc = 0; i_loc <= n_ids; i_loc++)
225  new_4_id[i_loc] = -1; // ensure that all ids are initialized
226  for (unsigned int i_new = 0; i_new < size; i_new++)
227  new_4_id[id_4_old[old_4_new[i_new]]] = i_new;
228 
229  delete [] old_4_new;
230 }
231 
232 
233 void Partitioning::id_maps(int n_ids, LongIdx *id_4_old, Distribution * &new_ds, LongIdx * &id_4_loc, LongIdx * &new_4_id) {
234  Partitioning::id_maps(n_ids, id_4_old, *init_el_ds_, loc_part_, new_ds, id_4_loc, new_4_id);
235 }
236 
237 
238 
239 shared_ptr< vector<int> > Partitioning::subdomain_id_field_data() {
240  OLD_ASSERT(loc_part_, "Partition is not yet computed.\n");
241  if (!seq_part_) {
242  unsigned int seq_size=(init_el_ds_->myp() == 0) ? init_el_ds_->size() : 1;
243  //seq_part_.resize(seq_size);
244  seq_part_ = make_shared< vector<int> >(seq_size);
245  std::vector<int> &vec = *( seq_part_.get() );
246 
248  &vec[0],
249  (int *)(init_el_ds_->get_lsizes_array()),
250  (int *)(init_el_ds_->get_starts_array()),
251  MPI_INT, 0,init_el_ds_->get_comm() );
252 
253  }
254  return seq_part_;
255 
256 }
SparseGraph::set_edge
void set_edge(const int a, const int b, int weight=1)
Definition: sparse_graph.cc:66
Distribution::np
unsigned int np() const
get num of processors
Definition: distribution.hh:105
Partitioning::Partitioning
Partitioning(Mesh *mesh, Input::Record in)
Definition: partitioning.cc:62
Partitioning::make_partition
void make_partition()
Definition: partitioning.cc:143
sparse_graph.hh
Distributed sparse graphs, partitioning.
Partitioning::in_
Input::Record in_
Input Record accessor.
Definition: partitioning.hh:121
Distribution::lsize
unsigned int lsize(int proc) const
get local size
Definition: distribution.hh:115
neighbours.h
Partitioning::METIS
@ METIS
Use direct interface to Metis.
Definition: partitioning.hh:106
Distribution::myp
unsigned int myp() const
get my processor
Definition: distribution.hh:107
ASSERT
#define ASSERT(expr)
Allow use shorter versions of macro names if these names is not used with external library.
Definition: asserts.hh:346
LongIdx
int LongIdx
Define type that represents indices of large arrays (elements, nodes, dofs etc.)
Definition: long_idx.hh:22
Mesh::elements_range
virtual Range< ElementAccessor< 3 > > elements_range() const
Returns range of bulk elements.
Definition: mesh.cc:1116
distribution.hh
Support classes for parallel programing.
DistributionLocalized
Definition: distribution.hh:37
Input::Record::val
const Ret val(const string &key) const
Definition: accessors_impl.hh:31
Partitioning::subdomain_id_field_data
shared_ptr< vector< int > > subdomain_id_field_data()
Definition: partitioning.cc:239
Input::Type::Selection::close
const Selection & close() const
Close the Selection, no more values can be added.
Definition: type_selection.cc:65
Partitioning::mesh_
Mesh * mesh_
The input mesh.
Definition: partitioning.hh:119
Partitioning::~Partitioning
~Partitioning()
Destructor.
Definition: partitioning.cc:70
Partitioning::loc_part_
LongIdx * loc_part_
Partition numbers for local elements in original distribution of elements given be init_el_ds_.
Definition: partitioning.hh:126
THROW
#define THROW(whole_exception_expr)
Wrapper for throw. Saves the throwing point.
Definition: exceptions.hh:53
std::vector< int >
Side::edge
const Edge * edge() const
Definition: side_impl.hh:66
Distribution::size
unsigned int size() const
get global size
Definition: distribution.hh:118
MPI_Gatherv
#define MPI_Gatherv(sendbuf, sendcount, sendtype, recvbuf, recvcounts, displs, recvtype, root, comm)
Definition: mpi.h:549
Partitioning::get_loc_part
const LongIdx * get_loc_part() const
Definition: partitioning.cc:86
Partitioning::get_graph_type_sel
static const Input::Type::Selection & get_graph_type_sel()
Input specification objects.
Definition: partitioning.cc:32
SparseGraphPETSC
Definition: sparse_graph.hh:172
Partitioning::graph_
SparseGraph * graph_
Graph used to partitioning the mesh.
Definition: partitioning.hh:124
Input::Type::Default
Class Input::Type::Default specifies default value of keys of a Input::Type::Record.
Definition: type_record.hh:61
Distribution
Definition: distribution.hh:50
accessors.hh
Partitioning::init_el_ds_
Distribution * init_el_ds_
Original distribution of elements. Depends on type of partitioner.
Definition: partitioning.hh:128
Input::Record
Accessor to the data with type Type::Record.
Definition: accessors.hh:291
Partitioning::get_tool_sel
static const Input::Type::Selection & get_tool_sel()
Definition: partitioning.cc:43
Side::valid
bool valid() const
Definition: side_impl.hh:92
Edge::n_sides
int n_sides
Definition: edges.h:36
Edge::side
SideIter side(const unsigned int i) const
Definition: edges.h:31
Partitioning::PartitionTool
PartitionTool
Definition: partitioning.hh:104
Input::Type::Record::allow_auto_conversion
virtual Record & allow_auto_conversion(const string &from_key)
Allows shorter input of the Record providing only value of the from_key given as the parameter.
Definition: type_record.cc:132
Partitioning::any_neighboring
@ any_neighboring
Add edge for any pair of neighboring elements.
Definition: partitioning.hh:113
Distribution::get_lsizes_array
const unsigned int * get_lsizes_array()
get local sizes array
Definition: distribution.cc:155
SparseGraph::finalize
void finalize()
Make sparse graph structures: rows, adj.
Definition: sparse_graph.cc:98
Input::Type::Record::declare_key
Record & declare_key(const string &key, std::shared_ptr< TypeBase > type, const Default &default_value, const string &description, TypeBase::attribute_map key_attributes=TypeBase::attribute_map())
Declares a new key of the Record.
Definition: type_record.cc:501
SparseGraph::partition
virtual void partition(int *loc_part)=0
Side::element
ElementAccessor< 3 > element() const
Definition: side_impl.hh:53
MPI_INT
#define MPI_INT
Definition: mpi.h:160
Partitioning::same_dimension_neighboring
@ same_dimension_neighboring
Add edge for any pair of neighboring elements of same dimension (bad for matrix multiply)
Definition: partitioning.hh:115
mesh.h
Input::Type::Selection
Template for classes storing finite set of named values.
Definition: type_selection.hh:65
Input::Type::Record::close
Record & close() const
Close the Record for further declarations of keys.
Definition: type_record.cc:303
Mesh::get_comm
MPI_Comm get_comm() const
Definition: mesh.h:189
Partitioning::PartitionGraphType
PartitionGraphType
Definition: partitioning.hh:112
Input::Type
Definition: balance.hh:38
partitioning.hh
Partitioning::get_input_type
static const Input::Type::Record & get_input_type()
Definition: partitioning.cc:50
Input::Type::Record
Record type proxy class.
Definition: type_record.hh:182
Distribution::get_starts_array
const unsigned int * get_starts_array() const
get local starts array
Definition: distribution.cc:167
Mesh
Definition: mesh.h:80
OLD_ASSERT
#define OLD_ASSERT(...)
Definition: global_defs.h:131
Edge
Definition: edges.h:26
Input::Type::Record::finish
FinishStatus finish(FinishStatus finish_type=FinishStatus::regular_) override
Finish declaration of the Record type.
Definition: type_record.cc:242
DistributionBlock
Definition: distribution.hh:33
side_impl.hh
SparseGraph::get_distr
Distribution get_distr()
Definition: sparse_graph.hh:120
Partitioning::get_init_distr
const Distribution * get_init_distr() const
Definition: partitioning.cc:79
ElementAccessor::idx
unsigned int idx() const
Return local idx of element in boundary / bulk part of element vector.
Definition: accessors.hh:111
Partitioning::seq_part_
shared_ptr< vector< int > > seq_part_
Sequential partitioning for output.
Definition: partitioning.hh:130
long_idx.hh
Partitioning::id_maps
void id_maps(int n_ids, LongIdx *id_4_old, Distribution *&new_ds, LongIdx *&id_4_loc, LongIdx *&new_4_id)
Definition: partitioning.cc:233
Partitioning::make_element_connection_graph
void make_element_connection_graph()
Definition: partitioning.cc:93
Partitioning::PETSc
@ PETSc
Use PETSc interface to various partitioing tools.
Definition: partitioning.hh:105
Partitioning::any_weight_lower_dim_cuts
@ any_weight_lower_dim_cuts
Same as before and assign higher weight to cuts of lower dimension in order to make them stick to one...
Definition: partitioning.hh:114
Mesh::n_elements
virtual unsigned int n_elements(bool boundary=false) const
Returns count of boundary or bulk elements.
Definition: mesh.h:355
Input::Type::Selection::add_value
Selection & add_value(const int value, const std::string &key, const std::string &description="", TypeBase::attribute_map attributes=TypeBase::attribute_map())
Adds one new value with name given by key to the Selection.
Definition: type_selection.cc:50
SparseGraphMETIS
Definition: sparse_graph.hh:207
Distribution::get_comm
MPI_Comm get_comm() const
Returns communicator.
Definition: distribution.hh:129
Distribution::is_local
bool is_local(unsigned int idx) const
identify local index
Definition: distribution.hh:120
range_wrapper.hh
Implementation of range helper class.
Distribution::begin
unsigned int begin(int proc) const
get starting local index
Definition: distribution.hh:109