COOLFluiD  Release kernel
COOLFluiD is a Collaborative Simulation Environment (CSE) focused on complex MultiPhysics simulations.
utest-mesh-ptscotch.cpp
Go to the documentation of this file.
1 // Copyright (C) 2010-2011 von Karman Institute for Fluid Dynamics, Belgium
2 //
3 // This software is distributed under the terms of the
4 // GNU Lesser General Public License version 3 (LGPLv3).
5 // See doc/lgpl.txt and doc/gpl.txt for the license text.
6 
7 #define BOOST_TEST_DYN_LINK
8 #define BOOST_TEST_MODULE "Test module for cf3::mesh::ptscotch"
9 
10 #include <boost/test/unit_test.hpp>
11 #include <boost/assign/list_of.hpp>
12 
13 #include "common/Core.hpp"
14 #include "common/Foreach.hpp"
15 #include "common/Log.hpp"
16 #include "common/OptionList.hpp"
17 #include "common/StreamHelpers.hpp"
18 
19 #include "common/PE/Comm.hpp"
20 #include "common/PE/debug.hpp"
21 #include "common/Foreach.hpp"
22 
23 #include "math/MatrixTypes.hpp"
24 
25 #include "mesh/Mesh.hpp"
26 #include "mesh/Region.hpp"
27 #include "mesh/Elements.hpp"
28 #include "mesh/MeshReader.hpp"
30 #include "mesh/MeshTransformer.hpp"
31 #include "mesh/MeshPartitioner.hpp"
32 #include "mesh/MeshWriter.hpp"
33 
36 
37 using namespace boost;
38 using namespace cf3;
39 using namespace cf3::mesh;
40 using namespace cf3::common;
41 using namespace boost::assign;
42 
44 
46 {
49  {
50  // uncomment if you want to use arguments to the test executable
51  m_argc = boost::unit_test::framework::master_test_suite().argc;
52  m_argv = boost::unit_test::framework::master_test_suite().argv;
53 
54 
55  baseval=0;
56 
57  }
58 
61  {
62 
63  }
64 
66 
67  SCOTCH_Num* to_ptr(std::vector<SCOTCH_Num>& vec)
68  {
69  if (vec.empty())
70  return NULL;
71  else
72  return &vec[0];
73  }
74 
75 
77  SCOTCH_Dgraph graph;
78 
79  SCOTCH_Num baseval; // first index of an array starts with 0 for c++
80  SCOTCH_Num vertglbnbr; // number of vertices in the total mesh
81  SCOTCH_Num edgeglbnbr; // number of connections in the total mesh
82  SCOTCH_Num procglbnbr; // number of processors
83 
84  SCOTCH_Num vertlocnbr; // number of vertices on this processor
85  SCOTCH_Num vertgstnbr; // number of vertices on this processor, including ghost vertices
86  SCOTCH_Num edgelocnbr; // number of connections to other vertices starting from each local vertex
87 
88  SCOTCH_Num vertlocmax;
89  SCOTCH_Num edgelocsiz;
90  std::vector<SCOTCH_Num> vertloctab;
91  std::vector<SCOTCH_Num> edgeloctab;
92  std::vector<SCOTCH_Num> edgegsttab;
93  std::vector<SCOTCH_Num> partloctab;
94  std::vector<SCOTCH_Num> proccnttab;// number of vertices per processor
95  std::vector<SCOTCH_Num> procvrttab;// start_idx of the vertex for each processor + one extra index greater than vertglbnbr
96 
97 
99  {
100  SCOTCH_dgraphSize(&graph,
101  &vertglbnbr,
102  &vertlocnbr,
103  &edgeglbnbr,
104  &edgelocnbr);
105 
106  proccnttab.resize(common::PE::Comm::instance().size());
107  procvrttab.resize(common::PE::Comm::instance().size()+1);
108 
109  //boost::mpi::communicator world;
110  //boost::mpi::all_gather(world, vertlocnbr, proccnttab);
111  PE::Comm::instance().all_gather(vertlocnbr, proccnttab);
112  Uint cnt=0;
113  for (Uint p=0; p<proccnttab.size(); ++p)
114  {
115  procvrttab[p] = cnt;
116  cnt += proccnttab[p];
117  }
118  procvrttab[common::PE::Comm::instance().size()] = cnt;
119 
120 
121  if (SCOTCH_dgraphGhst(&graph))
122  throw BadValue(FromHere(),"ptscotch error");
123 
124 
125  SCOTCH_dgraphData(&graph,
126  NULL,
127  NULL,
128  NULL,
129  NULL,
130  &vertgstnbr,
131  NULL,
132  NULL,
133  NULL,//&veloloctab,
134  NULL,//&vlblocltab,
135  NULL,
136  NULL,
137  NULL,
138  NULL,
139  NULL,
140  NULL,//&edloloctab,
141  NULL); // &comm
142 
143 
144  }
145 
146  void build_graph()
147  {
148  if (SCOTCH_dgraphInit(&graph, common::PE::Comm::instance().communicator()))
149  throw BadValue(FromHere(),"ptscotch error");
150 
151  if (SCOTCH_dgraphBuild(&graph,
152  baseval,
153  vertlocnbr, // number of local vertices (for creation of proccnttab)
154  vertlocmax, // max number of local vertices to be created (for creation of procvrttab)
155  to_ptr(vertloctab), // local adjacency index array (size = vertlocnbr+1 if vendloctab matches or is null)
156  to_ptr(vertloctab)+1, // (optional) local adjacency end index array
157  NULL, //veloloctab, // (optional) local vertex load array
158  NULL, //vlblocltab, // (optional) local vertex label array (size = vertlocnbr+1)
159  edgelocnbr, // total number of arcs (twice number of edges)
160  edgelocsiz, // minimum size of the edge array required to encompass all used adjacency values (at least equal to the max of vendloctab entries)
161  to_ptr(edgeloctab), // edgeloctab, local adjacency array which stores global indices
162  to_ptr(edgegsttab), // edgegsttab, // (optional) if passed it is assumed an empty array that will be filled by SCOTHC_dgraphGhst if required
163  NULL)) //edloloctab)) // (optional) arc load array of size edgelocsiz
164  throw BadValue(FromHere(),"ptscotch error");
165 
166  gather_global_data();
167 
168  }
169 
170 
172  {
173  if (common::PE::Comm::instance().rank() == 0)
174  {
175  CFinfo << "\n" << CFendl;
176  CFinfo << "global graph info" << CFendl;
177  CFinfo << "-----------------" << CFendl;
178  CFLogVar(vertglbnbr);
179  CFLogVar(edgeglbnbr);
180  CFinfo << "proccnttab = [ ";
181  for (Uint i=0; i<common::PE::Comm::instance().size(); ++i)
182  CFinfo << proccnttab[i] << " ";
183  CFinfo << "]" << CFendl;
184  CFinfo << "procvrttab = [ ";
185  for (Uint i=0; i<common::PE::Comm::instance().size()+1; ++i)
186  CFinfo << procvrttab[i] << " ";
187  CFinfo << "]" << CFendl;
188 
189  CFinfo << CFendl << CFendl;
190  }
191 
192  bool original_filter = CFinfo.getFilterRankZero(LogStream::SCREEN);
193  CFinfo.setFilterRankZero(LogStream::SCREEN,false);
194  for (Uint proc=0; proc<common::PE::Comm::instance().size(); ++proc)
195  {
196  if (common::PE::Comm::instance().rank() == proc)
197  {
198  CFinfo << "proc #"<<proc << CFendl;
199  CFinfo << "-------" << CFendl;
200  CFLogVar(vertlocnbr);
201  CFLogVar(vertlocmax);
202  CFLogVar(vertgstnbr);
203 
204  CFinfo << "vertloctab = [ ";
205  for (int i=0; i<vertlocnbr; ++i)
206  CFinfo << vertloctab[i] << " ";
207  CFinfo << "]" << CFendl;
208 
209  CFLogVar(edgelocnbr);
210  CFinfo << "edgeloctab = [ ";
211  for (int i=0; i<edgelocnbr; ++i)
212  CFinfo << edgeloctab[i] << " ";
213  CFinfo << "]" << CFendl;
214 
215  CFinfo << "edgegsttab = [ ";
216  for (int i=0; i<edgelocnbr; ++i)
217  CFinfo << edgegsttab[i] << " ";
218  CFinfo << "]" << CFendl;
219 
220 
221  CFinfo << CFendl;
222  }
223  common::PE::Comm::instance().barrier();
224  }
225  common::PE::Comm::instance().barrier();
226  CFinfo.setFilterRankZero(LogStream::SCREEN,original_filter);
227  }
228 
229  void partition_graph(const Uint nb_parts)
230  {
231  SCOTCH_Strat stradat;
232  if(SCOTCH_stratInit(&stradat))
233  throw BadValue (FromHere(), "pt-scotch error");
234 
235  partloctab.resize(vertlocmax);
236 
237  if (SCOTCH_dgraphPart(&graph,
238  nb_parts,
239  &stradat,
240  to_ptr(partloctab)))
241  throw BadValue (FromHere(), "pt-scotch error");
242 
243  SCOTCH_stratExit(&stradat);
244  }
245 
247  {
248  bool original_filter = CFinfo.getFilterRankZero(LogStream::SCREEN);
249  CFinfo.setFilterRankZero(LogStream::SCREEN,false);
250  for (Uint proc=0; proc<common::PE::Comm::instance().size(); ++proc)
251  {
252  if (common::PE::Comm::instance().rank() == proc)
253  {
254  CFinfo << "proc #"<<proc << CFendl;
255  CFinfo << "-------" << CFendl;
256  CFLogVar(vertlocnbr);
257  CFLogVar(vertlocmax);
258  CFLogVar(vertgstnbr);
259 
260  for (int i=0; i<vertlocnbr; ++i)
261  CFinfo << procvrttab[proc]+i << " goes to part " << partloctab[i] << CFendl;
262 
263  CFinfo << CFendl;
264  }
265  common::PE::Comm::instance().barrier();
266  }
267  common::PE::Comm::instance().barrier();
268  CFinfo.setFilterRankZero(LogStream::SCREEN,original_filter);
269  CFinfo << CFendl<< CFendl;
270  }
271 
272  int m_argc;
273  char** m_argv;
274 };
275 
277 
278 BOOST_FIXTURE_TEST_SUITE( PTScotchTests_TestSuite, PTScotchTests_Fixture )
279 
280 
283 {
284  common::PE::Comm::instance().init(m_argc,m_argv);
285 }
286 
288 
289 BOOST_AUTO_TEST_CASE( PTSCOTCH_tutorial_construction )
290 {
291 
292  if (common::PE::Comm::instance().size() == 3)
293  {
294 
295  CFinfo << "+++++++++++++++++++ building graph ++++++++++++++++++++ \n" << CFendl;
296 
297  switch (common::PE::Comm::instance().rank())
298  {
299  case 0:
300  {
301  vertloctab = list_of(0)(2)(6)(9) (0);
302  vertlocnbr=vertloctab.size()-2;
303  vertlocmax=vertlocnbr; // no expected growth
304 
305  edgeloctab = list_of(2)(1)(2)(4)(3)(0)(3)(1)(0) (0)(0);
306  edgelocnbr = edgeloctab.size()-2;
307  edgelocsiz = edgeloctab.size();
308  edgegsttab.resize(edgeloctab.size());
309  break;
310  }
311  case 1:
312  {
313  vertloctab = list_of(0)(5)(8) (0);
314  vertlocnbr=vertloctab.size()-2;
315  vertlocmax=vertlocnbr; // no expected growth
316 
317  edgeloctab = list_of(2)(5)(1)(7)(4)(7)(1)(3) (0)(0);
318  edgelocnbr = edgeloctab.size()-2;
319  edgelocsiz = edgeloctab.size();
320  edgegsttab.resize(edgeloctab.size());
321  break;
322  }
323  case 2:
324  {
325  vertloctab = list_of(0)(3)(5)(9) (0);
326  vertlocnbr=vertloctab.size()-2;
327  vertlocmax=vertlocnbr; // no expected growth
328 
329  edgeloctab = list_of(3)(6)(7)(5)(7)(3)(5)(6)(4) (0)(0);
330  edgelocnbr = edgeloctab.size()-2;
331  edgelocsiz = edgeloctab.size();
332  edgegsttab.resize(edgeloctab.size());
333  break;
334  }
335  }
336 
337  build_graph();
338 
339  BOOST_CHECK_EQUAL(SCOTCH_dgraphCheck(&graph),0);
340 
341  CFinfo << "\n\n+++++++++++++++++++ graph info ++++++++++++++++++++ " << CFendl;
342 
343 
344  output_graph_info();
345 
346  BOOST_CHECK(true);
347 
348  CFinfo << "\n\n+++++++++++++++++++ partitioning ++++++++++++++++++++ \n" << CFendl;
349 
350  partition_graph(3);
351 
352  output_graph_partitions();
353  }
354  else
355  {
356  CFinfo << "must run this testcase with 3 processors" << CFendl;
357  }
358 
359 }
360 
361 BOOST_AUTO_TEST_CASE( MeshPartitioner_test )
362 {
363  CFinfo << "MeshPartitioner_test" << CFendl;
364  boost::shared_ptr< MeshReader > meshreader = build_component_abstract_type<MeshReader>("cf3.mesh.neu.Reader","meshreader");
365  meshreader->options().set("read_boundaries",false);
366 
367  // the file to read from
368  URI fp_in ("file:../../resources/quadtriag.neu");
369 
370  // the mesh to store in
371  Mesh& mesh = *Core::instance().root().create_component<Mesh>("mesh");
372  meshreader->read_mesh_into(fp_in,mesh);
374 
375  boost::shared_ptr< MeshTransformer > glb_numbering = build_component_abstract_type<MeshTransformer>("cf3.mesh.actions.GlobalNumbering","glb_numbering");
376  glb_numbering->transform(mesh);
378 
379  boost::shared_ptr< MeshTransformer > glb_connectivity = build_component_abstract_type<MeshTransformer>("cf3.mesh.actions.GlobalConnectivity","glb_connectivity");
380  glb_connectivity->transform(mesh);
382 
383  boost::shared_ptr< MeshWriter > meshwriter = build_component_abstract_type<MeshWriter>("cf3.mesh.gmsh.Writer","meshwriter");
384  URI fp_out_1 ("file:quadtriag.msh");
385  meshwriter->write_from_to(mesh,fp_out_1);
387 
388  boost::shared_ptr< MeshTransformer > partitioner_ptr = build_component_abstract_type<MeshTransformer>("cf3.mesh.ptscotch.Partitioner","partitioner");
389 
390  MeshPartitioner& p = *boost::dynamic_pointer_cast<MeshPartitioner>(partitioner_ptr);
391  BOOST_CHECK_EQUAL(p.name(),"partitioner");
393 
394  //p.set("nb_partitions", (Uint) 2);
395  BOOST_CHECK(true);
396  p.initialize(mesh);
398 
399  BOOST_CHECK(true);
400  p.partition_graph();
402 
403  BOOST_CHECK(true);
404  p.show_changes();
405  BOOST_CHECK(true);
406  p.migrate();
407  BOOST_CHECK(true);
408  URI fp_out_2 ("file:quadtriag_repartitioned.msh");
409  //meshwriter->write_from_to(mesh_ptr,fp_out_2);
410 }
411 
412 
414 
415 BOOST_AUTO_TEST_CASE( finalize_mpi )
416 {
417  common::PE::Comm::instance().finalize();
418 }
419 
421 
422 BOOST_AUTO_TEST_SUITE_END()
423 
424 
#define CFinfo
these are always defined
Definition: Log.hpp:104
external boost library namespace
std::vector< SCOTCH_Num > procvrttab
PTScotchTests_Fixture()
common setup for each test case
#define CFendl
Definition: Log.hpp:109
#define CF3_DEBUG_POINT
Definition of a macro for placing a debug point in the code.
Definition: Log.hpp:125
std::vector< SCOTCH_Num > partloctab
BOOST_AUTO_TEST_CASE(init_mpi)
Basic Classes for Mesh applications used by COOLFluiD.
Top-level namespace for coolfluid.
Definition: Action.cpp:18
std::vector< SCOTCH_Num > proccnttab
std::vector< SCOTCH_Num > edgeloctab
#define CFLogVar(x)
log the value of a variable
Definition: Log.hpp:123
void partition_graph(const Uint nb_parts)
unsigned int Uint
typedef for unsigned int
Definition: CF.hpp:90
std::vector< SCOTCH_Num > edgegsttab
std::vector< SCOTCH_Num > vertloctab
SCOTCH_Num * to_ptr(std::vector< SCOTCH_Num > &vec)
possibly common functions used on the tests below
~PTScotchTests_Fixture()
common tear-down for each test case
SCOTCH_Dgraph graph
common values accessed by all tests goes here
Most basic kernel library.
Definition: Action.cpp:19
#define FromHere()
Send comments to:
COOLFluiD Web Admin