COOLFluiD  Release kernel
COOLFluiD is a Collaborative Simulation Environment (CSE) focused on complex MultiPhysics simulations.
utest-parallel-commpattern.cpp
Go to the documentation of this file.
1 // Copyright (C) 2010-2013 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 // IMPORTANT:
8 // run it both on 1 and many cores
9 // for example: mpirun -np 4 ./test-parallel-environment --report_level=confirm or --report_level=detailed
10 
11 #define BOOST_TEST_DYN_LINK
12 #define BOOST_TEST_MODULE "Test module for cf3::common 's parallel environment - part of testing the commpattern."
13 
15 
16 #include <boost/test/unit_test.hpp>
17 #include <boost/shared_ptr.hpp>
18 #include <boost/weak_ptr.hpp>
19 
20 #include "common/Log.hpp"
22 #include "common/Component.hpp"
23 #include "common/PE/Comm.hpp"
27 #include "common/PE/debug.hpp"
28 #include "common/Group.hpp"
29 
30 
32 
33 using namespace cf3;
34 using namespace cf3::common;
35 using namespace cf3::common::PE;
36 
38 
40 {
43  {
44  m_argc = boost::unit_test::framework::master_test_suite().argc;
45  m_argv = boost::unit_test::framework::master_test_suite().argv;
46  }
47 
50  {
51  }
52 
54  void setupGidAndRank(std::vector<Uint>& gid, std::vector<Uint>& rank)
55  {
56  // global indices and ranks, ordering: 0 1 2 ... 0 0 1 1 2 2 ... 0 0 0 1 1 1 2 2 2 ...
57  int nproc=PE::Comm::instance().size();
58  int irank=PE::Comm::instance().rank();
59  gid.resize(6*nproc);
60  rank.resize(6*nproc);
61  for (Uint i=0; i<nproc; i++)
62  {
63  rank[0*nproc+1*i+0]=i;
64  gid[ 0*nproc+1*i+0]=(6*nproc-1)-(6*i+0);
65  }
66  for (Uint i=0; i<nproc; i++)
67  {
68  rank[1*nproc+2*i+0]=i;
69  rank[1*nproc+2*i+1]=i;
70  gid[ 1*nproc+2*i+0]=(6*nproc-1)-(6*i+1);
71  gid[ 1*nproc+2*i+1]=(6*nproc-1)-(6*i+2);
72  }
73  for (Uint i=0; i<nproc; i++)
74  {
75  rank[3*nproc+3*i+0]=i;
76  rank[3*nproc+3*i+1]=i;
77  rank[3*nproc+3*i+2]=i;
78  gid[ 3*nproc+3*i+0]=(6*nproc-1)-(6*i+3);
79  gid[ 3*nproc+3*i+1]=(6*nproc-1)-(6*i+4);
80  gid[ 3*nproc+3*i+2]=(6*nproc-1)-(6*i+5);
81  }
82  }
83 
85  int m_argc;
86  char** m_argv;
87 };
88 
90 
91 BOOST_FIXTURE_TEST_SUITE( CommPatternSuite, CommPatternFixture )
92 
93 
96 {
97  PE::Comm::instance().init(m_argc,m_argv);
98  BOOST_CHECK_EQUAL( PE::Comm::instance().is_active() , true );
99  CFinfo.setFilterRankZero(false);
100  PEProcessSortedExecute(-1,CFinfo << "Proccess " << PE::Comm::instance().rank() << "/" << PE::Comm::instance().size() << " reports in." << CFendl;);
101 }
102 
104 
105 BOOST_AUTO_TEST_CASE( data_registration_related )
106 {
107  boost::shared_ptr<CommPattern> pecp_ptr = allocate_component<CommPattern>("CommPattern");
108  CommPattern& pecp = *pecp_ptr;
109  BOOST_CHECK_EQUAL( pecp.isUpToDate() , false );
110 
111  boost::shared_ptr< std::vector<double> > d1( new std::vector<double>(32) );
112  boost::shared_ptr< std::vector<double> > d2( new std::vector<double>(24) );
113 
114  // register data to CommPattern
115  pecp.insert<double>("VectorWeakPtr1",*d1,2,true);
116  pecp.insert<double>("VectorWeakPtr2",*d2,3,true);
117 
118  // these are just dummies to see the selective iteration
119  boost::shared_ptr<Component> dir1 ( allocate_component<Group> ( "dir1" ) );
120  boost::shared_ptr<Component> dir2 ( allocate_component<Group> ( "dir2" ) );
121  pecp.add_component( dir1 );
122  pecp.add_component( dir2 );
123 
124  // count all child
125  BOOST_CHECK_EQUAL( pecp.count_children() , 4u );
126 
127  // count recursively childs but only of type CommWrapper
128  //BOOST_CHECK_EQUAL( find_components_recursively<CommWrapper>(pecp).size() , 2 );
129 
130  // iterate recursively childs but only of type CommWrapper
131  BOOST_FOREACH( CommWrapper& pobj, find_components_recursively<CommWrapper>(pecp) )
132  {
133  BOOST_CHECK_EQUAL( pobj.type_name() , "CommWrapper" );
134  BOOST_CHECK_EQUAL( pobj.size_of() , static_cast<int>(sizeof(double)) );
135  if (pobj.name()=="VectorWeakPtr1"){
136  BOOST_CHECK_EQUAL( pobj.size() , 16 );
137  BOOST_CHECK_EQUAL( pobj.stride() , 2 );
138  }
139  if (pobj.name()=="VectorWeakPtr2"){
140  BOOST_CHECK_EQUAL( pobj.size() , 8 );
141  BOOST_CHECK_EQUAL( pobj.stride() , 3 );
142  }
143  }
144 }
145 
147 
149 //BOOST_AUTO_TEST_CASE( commpattern_cast )
150 //{
151 // CommPattern pecp("CommPattern");
152 // std::vector<Uint> gid(10);
153 // pecp.insert("gid",gid);
154 // CommWrapper globid=pecp.get_child("gid").as_type<CommPattern>();
155 //}
156 
158 
159 BOOST_AUTO_TEST_CASE( commpattern_mainstream )
160 {
161  // general constants in this routine
162  const int nproc=PE::Comm::instance().size();
163  const int irank=PE::Comm::instance().rank();
164 
165  // commpattern
166  boost::shared_ptr<CommPattern> pecp_ptr = allocate_component<CommPattern>("CommPattern");
167  CommPattern& pecp = *pecp_ptr;
168 
169  // setup gid & rank
170  std::vector<Uint> gid;
171  std::vector<Uint> rank;
172  setupGidAndRank(gid,rank);
173  const int stride=1;
174  const bool to_synchronize=false;
175  pecp.insert("gid",gid,stride,to_synchronize);
176 
177  // additional arrays for testing
178  std::vector<int> v1;
179  for(int i=0;i<6*nproc;i++) v1.push_back(-((irank+1)*1000+i+1));
180  pecp.insert("v1",v1,1,true);
181  std::vector<double> v2;
182  for(int i=0;i<12*nproc;i++) v2.push_back((double)((irank+1)*1000+i+1));
183  pecp.insert("v2",v2,2,true);
184 
185  // initial setup
186  pecp.setup(Handle<CommWrapper>(pecp.get_child("gid")),rank);
187 
188  PECheckPoint(100,"Before");
189  PEProcessSortedExecute(-1,PEDebugVector(gid,gid.size()));
190  PEProcessSortedExecute(-1,PEDebugVector(v1,v1.size()));
191  PEProcessSortedExecute(-1,PEDebugVector(v2,v2.size()));
192 
193  // synchronize data
194  pecp.synchronize_all();
195 
196  PECheckPoint(100,"After");
197  PEProcessSortedExecute(-1,PEDebugVector(gid,gid.size()));
198  PEProcessSortedExecute(-1,PEDebugVector(v1,v1.size()));
199  PEProcessSortedExecute(-1,PEDebugVector(v2,v2.size()));
200 
201  // check results
202  Uint idx=0;
203  Uint i;
204  for (i=0; i< nproc; i++, idx++ ) BOOST_CHECK_EQUAL( v1[i], (int)(-((((i-0*nproc)/1)+1)*1000+idx+1)) );
205  for ( ; i<3*nproc; i++, idx++ ) BOOST_CHECK_EQUAL( v1[i], (int)(-((((i-1*nproc)/2)+1)*1000+idx+1)) );
206  for ( ; i<6*nproc; i++, idx++ ) BOOST_CHECK_EQUAL( v1[i], (int)(-((((i-3*nproc)/3)+1)*1000+idx+1)) );
207  idx=0;
208  for (i=0; i< 2*nproc; i++, idx++) BOOST_CHECK_EQUAL( v2[i], (double)((((i-0*nproc)/2)+1)*1000+idx+1) );
209  for ( ; i< 6*nproc; i++, idx++) BOOST_CHECK_EQUAL( v2[i], (double)((((i-2*nproc)/4)+1)*1000+idx+1) );
210  for ( ; i<12*nproc; i++, idx++) BOOST_CHECK_EQUAL( v2[i], (double)((((i-6*nproc)/6)+1)*1000+idx+1) );
211 }
212 
214 
215 BOOST_AUTO_TEST_CASE( commpattern_external_synchronization )
216 {
217 /*
218  // general constants in this routine
219  const int nproc=PE::Comm::instance().size();
220  const int irank=PE::Comm::instance().rank();
221 
222  // commpattern
223  CommPattern pecp("CommPattern");
224 
225  // setup gid & rank
226  std::vector<Uint> pre_gid; // it is used to feed through series of adds
227  std::vector<Uint> gid(0);
228  std::vector<Uint> rank;
229  setupGidAndRank(pre_gid,rank);
230 
231 PECheckPoint(1000,"001");
232  pecp.insert("gid",gid,1,false);
233 PECheckPoint(1000,"002");
234 
235  // additional arrays for testing
236  std::vector<int> v1;
237  for(int i=0;i<6*nproc;i++) v1.push_back(-((irank+1)*1000+i+1));
238  std::vector<double> v2;
239  for(int i=0;i<12*nproc;i++) v2.push_back((double)((irank+1)*1000+i+1));
240 
241  // initial setup
242  for (int i=0; i<gid.size(); i++) pecp.add(pre_gid[i],rank[i]);
243 PECheckPoint(1000,"003");
244 //THIS CRASHES,BECAUSE m_gid IS NOT SET IF THE ZERO ARGUMENT VERSION OF SETUP IS BEING CALLED
245  pecp.setup();
246 PECheckPoint(1000,"004");
247 
248  PECheckPoint(100,"Before");
249  PEProcessSortedExecute(-1,PEDebugVector(gid,gid.size()));
250  PEProcessSortedExecute(-1,PEDebugVector(v1,v1.size()));
251  PEProcessSortedExecute(-1,PEDebugVector(v2,v2.size()));
252 
253  // synchronize data
254 PECheckPoint(1000,"005");
255  pecp.synchronize_all();
256 PECheckPoint(1000,"006");
257 
258  PECheckPoint(100,"After");
259  PEProcessSortedExecute(-1,PEDebugVector(gid,gid.size()));
260  PEProcessSortedExecute(-1,PEDebugVector(v1,v1.size()));
261  PEProcessSortedExecute(-1,PEDebugVector(v2,v2.size()));
262 
263  // check results
264  Uint idx=0;
265  Uint i;
266  for (i=0; i< nproc; i++, idx++ ) BOOST_CHECK_EQUAL( v1[i], (int)(-((((i-0*nproc)/1)+1)*1000+idx+1)) );
267  for ( ; i<3*nproc; i++, idx++ ) BOOST_CHECK_EQUAL( v1[i], (int)(-((((i-1*nproc)/2)+1)*1000+idx+1)) );
268  for ( ; i<6*nproc; i++, idx++ ) BOOST_CHECK_EQUAL( v1[i], (int)(-((((i-3*nproc)/3)+1)*1000+idx+1)) );
269  idx=0;
270  for (i=0; i< 2*nproc; i++, idx++) BOOST_CHECK_EQUAL( v2[i], (double)((((i-0*nproc)/2)+1)*1000+idx+1) );
271  for ( ; i< 6*nproc; i++, idx++) BOOST_CHECK_EQUAL( v2[i], (double)((((i-2*nproc)/4)+1)*1000+idx+1) );
272  for ( ; i<12*nproc; i++, idx++) BOOST_CHECK_EQUAL( v2[i], (double)((((i-6*nproc)/6)+1)*1000+idx+1) );
273 */
274 }
275 
277 
279 {
280  PEProcessSortedExecute(-1,CFinfo << "Proccess " << PE::Comm::instance().rank() << "/" << PE::Comm::instance().size() << " says good bye." << CFendl;);
281  CFinfo.setFilterRankZero(true);
283  BOOST_CHECK_EQUAL( PE::Comm::instance().is_active() , false );
284 }
285 
287 
288 BOOST_AUTO_TEST_SUITE_END()
289 
290 
static std::string type_name()
Get the class name.
#define CFinfo
these are always defined
Definition: Log.hpp:104
~CommPatternFixture()
common tear-down for each test case
CommPatternFixture()
common setup for each test case
Safe pointer to an object. This is the supported method for referring to components.
Definition: Handle.hpp:39
Parallel Communication Pattern. This class provides functionality to collect communication. For efficiency it works such a way that you submit your request via the constructor or the add/remove/move magic triangle and then call setup to modify the commpattern. The data needed to be kept synchronous can be registered via the insert function. The word node here means any kind of "point of storage", in this context it is not directly related with the computational mesh.
const std::string & name() const
Access the name of the component.
Definition: Component.hpp:146
#define CFendl
Definition: Log.hpp:109
Uint rank() const
Return rank, additionally, if is_init==0.
Definition: Comm.cpp:135
Uint size() const
Return the number of processes, or 1 if is_init==0.
Definition: Comm.cpp:145
Holds the Component class, as well as the ComponentIterator class plus some functions related to comp...
Base wrapper class serving as interface.
Definition: CommWrapper.hpp:42
#define PECheckPoint(msec, msg)
Definition: debug.hpp:75
#define PEDebugVector(v, length)
Definition: debug.hpp:107
virtual int stride() const =0
void setupGidAndRank(std::vector< Uint > &gid, std::vector< Uint > &rank)
function for setting up a gid & rank combo (with size of 6*nproc on each process) ...
void init(int argc=0, char **args=0)
Definition: Comm.cpp:80
Top-level namespace for coolfluid.
Definition: Action.cpp:18
unsigned int Uint
typedef for unsigned int
Definition: CF.hpp:90
Classes offering a MPI interface for COOLFluiD.
Definition: all_gather.hpp:39
BOOST_AUTO_TEST_CASE(init)
virtual int size_of() const =0
virtual int size() const =0
static Comm & instance()
Return a reference to the current PE.
Definition: Comm.cpp:44
Most basic kernel library.
Definition: Action.cpp:19
#define PEProcessSortedExecute(irank, expression)
Definition: debug.hpp:43
Send comments to:
COOLFluiD Web Admin