| 1 | /* |
| 2 | * dec_optimize.hpp |
| 3 | * |
| 4 | * Created on: Jan 16, 2015 |
| 5 | * Author: Pietro Incardona |
| 6 | */ |
| 7 | |
| 8 | #ifndef DEC_OPTIMIZE_HPP_ |
| 9 | #define DEC_OPTIMIZE_HPP_ |
| 10 | |
| 11 | |
| 12 | #include "Graph/CartesianGraphFactory.hpp" |
| 13 | #include "Graph/map_graph.hpp" |
| 14 | #include "Decomposition/Distribution/metis_util.hpp" |
| 15 | #include "dec_optimizer.hpp" |
| 16 | #include "util/SimpleRNG.hpp" |
| 17 | |
| 18 | #undef GS_SIZE |
| 19 | #define GS_SIZE 8 |
| 20 | |
| 21 | BOOST_AUTO_TEST_SUITE( dec_optimizer_test ) |
| 22 | |
| 23 | BOOST_AUTO_TEST_CASE( dec_optimizer_test_use_np) |
| 24 | { |
| 25 | CartesianGraphFactory<3,Graph_CSR<nm_v<3>,nm_e>> g_factory; |
| 26 | CartesianGraphFactory<3,Graph_CSR<nm_part_v,nm_part_e>> g_factory_part; |
| 27 | |
| 28 | // Cartesian grid |
| 29 | size_t sz[3] = {GS_SIZE,GS_SIZE,GS_SIZE}; |
| 30 | |
| 31 | // Box |
| 32 | Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0}); |
| 33 | |
| 34 | // Boundary conditions, non periodic |
| 35 | size_t bc[] = {NON_PERIODIC,NON_PERIODIC,NON_PERIODIC}; |
| 36 | |
| 37 | // Graph to decompose |
| 38 | Graph_CSR<nm_v<3>,nm_e> g = g_factory.construct<nm_e::communication,NO_VERTEX_ID,float,2,0>(sz,box,bc); |
| 39 | |
| 40 | // Processor graph |
| 41 | Graph_CSR<nm_part_v,nm_part_e> gp = g_factory_part.construct<NO_EDGE,NO_VERTEX_ID,float,2>(sz,box,bc); |
| 42 | |
| 43 | // Convert the graph to metis |
| 44 | Metis<Graph_CSR<nm_v<3>,nm_e>> met(g,16); |
| 45 | |
| 46 | // decompose |
| 47 | met.decompose<nm_part_v::id>(gp); |
| 48 | met.decompose<nm_v_id>(); |
| 49 | |
| 50 | // optimize |
| 51 | dec_optimizer<3,Graph_CSR<nm_v<3>,nm_e>> d_o(g,sz); |
| 52 | |
| 53 | Ghost<3,size_t> ghe(1); |
| 54 | |
| 55 | grid_key_dx<3> keyZero(0,0,0); |
| 56 | d_o.optimize<nm_v_sub_id,nm_v_id>(keyZero,g,ghe,bc); |
| 57 | } |
| 58 | |
| 59 | BOOST_AUTO_TEST_CASE( dec_optimizer_test_use_p) |
| 60 | { |
| 61 | CartesianGraphFactory<3,Graph_CSR<nm_v<3>,nm_e>> g_factory; |
| 62 | CartesianGraphFactory<3,Graph_CSR<nm_part_v,nm_part_e>> g_factory_part; |
| 63 | |
| 64 | // Cartesian grid |
| 65 | size_t sz[3] = {GS_SIZE,GS_SIZE,GS_SIZE}; |
| 66 | |
| 67 | //! Grid info |
| 68 | grid_sm<3,void> gs(sz); |
| 69 | |
| 70 | // Box |
| 71 | Box<3,float> box({0.0,0.0,0.0},{1.0,1.0,1.0}); |
| 72 | |
| 73 | // Boundary conditions, non periodic |
| 74 | size_t bc[] = {PERIODIC,PERIODIC,PERIODIC}; |
| 75 | |
| 76 | // Graph to decompose |
| 77 | Graph_CSR<nm_v<3>,nm_e> g = g_factory.construct<nm_e::communication,NO_VERTEX_ID,float,2,0>(sz,box,bc); |
| 78 | |
| 79 | // Processor graph |
| 80 | Graph_CSR<nm_part_v,nm_part_e> gp = g_factory_part.construct<NO_EDGE,NO_VERTEX_ID,float,2>(sz,box,bc); |
| 81 | |
| 82 | bool p[3]; |
| 83 | |
| 84 | // Divide in 8 parts your graph |
| 85 | |
| 86 | // decompose |
| 87 | for (size_t i = 0 ; i < GS_SIZE ; i++) |
| 88 | { |
| 89 | p[0] = (i < GS_SIZE/2)?false:true; |
| 90 | for (size_t j = 0 ; j < GS_SIZE ; j++) |
| 91 | { |
| 92 | p[1] = (j < GS_SIZE/2)?false:true; |
| 93 | for (size_t k = 0 ; k < GS_SIZE ; k++) |
| 94 | { |
| 95 | p[2] = (k < GS_SIZE/2)?false:true; |
| 96 | size_t id = 4*p[2] + 2*p[1] + p[0]; |
| 97 | |
| 98 | grid_key_dx<3> key(i,j,k); |
| 99 | gp.vertex(gs.LinId(key)).get<nm_part_v::id>() = id; |
| 100 | g.vertex(gs.LinId(key)).get<nm_v_id>() = id; |
| 101 | } |
| 102 | } |
| 103 | } |
| 104 | |
| 105 | // optimize |
| 106 | dec_optimizer<3,Graph_CSR<nm_v<3>,nm_e>> d_o(g,sz); |
| 107 | |
| 108 | grid_key_dx<3> keyZero(0,0,0); |
| 109 | |
| 110 | // Set of sub-domain produced by dec-optimizer |
| 111 | openfpm::vector<Box<3,size_t>> dec_o; |
| 112 | |
| 113 | // For each sub-domain check the neighborhood processors |
| 114 | openfpm::vector< openfpm::vector<size_t> > box_nn_processor; |
| 115 | |
| 116 | Ghost<3,size_t> ghe(1); |
| 117 | |
| 118 | // gp,p_id,loc_box,box_nn_processor,bc |
| 119 | d_o.optimize<nm_v_sub_id,nm_v_id>(g,-1,dec_o,box_nn_processor,ghe,bc); |
| 120 | |
| 121 | BOOST_REQUIRE_EQUAL(box_nn_processor.size(),8ul); |
| 122 | |
| 123 | for(size_t i = 0 ; i < box_nn_processor.size() ; i++) |
| 124 | { |
| 125 | BOOST_REQUIRE_EQUAL(box_nn_processor.get(i).size(),8ul); |
| 126 | for (size_t j = 0 ; j < box_nn_processor.get(i).size(); j++) |
| 127 | { |
| 128 | BOOST_REQUIRE(box_nn_processor.get(i).get(j) < 8); |
| 129 | } |
| 130 | } |
| 131 | |
| 132 | // check |
| 133 | } |
| 134 | |
| 135 | BOOST_AUTO_TEST_CASE( dec_optimizer_disconnected_subdomains_np) |
| 136 | { |
| 137 | // Vcluster |
| 138 | Vcluster<> & vcl = create_vcluster(); |
| 139 | |
| 140 | // Test for only 3 processors |
| 141 | if (vcl.getProcessingUnits() != 3) |
| 142 | return; |
| 143 | |
| 144 | CartesianGraphFactory<2,Graph_CSR<nm_v<2>,nm_e>> g_factory; |
| 145 | |
| 146 | // Cartesian grid |
| 147 | size_t sz[2] = {GS_SIZE,GS_SIZE}; |
| 148 | |
| 149 | // Box |
| 150 | Box<2,float> box({0.0,0.0},{1.0,1.0}); |
| 151 | |
| 152 | // Boundary conditions, non periodic |
| 153 | size_t bc[] = {NON_PERIODIC,NON_PERIODIC}; |
| 154 | |
| 155 | // Graph to decompose |
| 156 | Graph_CSR<nm_v<2>,nm_e> g = g_factory.construct<nm_e::communication,NO_VERTEX_ID,float,1,0>(sz,box,bc); |
| 157 | |
| 158 | SimpleRNG rng; |
| 159 | |
| 160 | auto vit = g.getVertexIterator(); |
| 161 | |
| 162 | while (vit.isNext()) |
| 163 | { |
| 164 | auto vk = vit.get(); |
| 165 | |
| 166 | g.vertex_p<nm_v_proc_id>(vk) = rng.GetUniform() * 2.9999; |
| 167 | g.vertex_p<nm_v_sub_id>(vk) = 100; |
| 168 | |
| 169 | ++vit; |
| 170 | } |
| 171 | |
| 172 | // optimize |
| 173 | dec_optimizer<2,Graph_CSR<nm_v<2>,nm_e>> d_o(g,sz); |
| 174 | |
| 175 | // set of Boxes produced by the decomposition optimizer |
| 176 | openfpm::vector<::Box<2, size_t>> loc_box; |
| 177 | |
| 178 | //! for each sub-domain, contain the list of the neighborhood processors |
| 179 | openfpm::vector<openfpm::vector<long unsigned int> > box_nn_processor; |
| 180 | |
| 181 | Ghost<2,size_t> ghe(1); |
| 182 | d_o.optimize<nm_v_sub_id, nm_v_proc_id>(g, vcl.getProcessUnitID(), loc_box, box_nn_processor,ghe,bc); |
| 183 | |
| 184 | std::stringstream str_g; |
| 185 | str_g << "dec_optimizer_disc_graph" << vcl.getProcessUnitID() << ".vtk" ; |
| 186 | std::stringstream str_gt; |
| 187 | str_gt << "src/Decomposition/Distribution/test_data/dec_optimizer_disc_graph" << vcl.getProcessUnitID() << "_test.vtk" ; |
| 188 | |
| 189 | std::stringstream str_s; |
| 190 | str_s << "dec_optimizer_disc_sub" << vcl.getProcessUnitID() << ".vtk" ; |
| 191 | std::stringstream str_st; |
| 192 | str_st << "src/Decomposition/Distribution/test_data/dec_optimizer_disc_sub" << vcl.getProcessUnitID() << "_test.vtk" ; |
| 193 | |
| 194 | VTKWriter<Graph_CSR<nm_v<2>,nm_e>,VTK_GRAPH> wrt(g); |
| 195 | wrt.write("dec_optimizer_disc_graph" + std::to_string(vcl.getProcessUnitID()) + ".vtk" ); |
| 196 | |
| 197 | VTKWriter<openfpm::vector<::Box<2, size_t>>, VECTOR_BOX> vtk_box1; |
| 198 | vtk_box1.add(loc_box); |
| 199 | vtk_box1.write("dec_optimizer_disc_sub" + std::to_string(vcl.getProcessUnitID()) + std::string(".vtk" )); |
| 200 | |
| 201 | bool test = compare(str_g.str(), str_gt.str()); |
| 202 | BOOST_REQUIRE_EQUAL(true,test); |
| 203 | |
| 204 | test = compare(str_s.str(),str_st.str()); |
| 205 | BOOST_REQUIRE_EQUAL(true,test); |
| 206 | } |
| 207 | |
| 208 | BOOST_AUTO_TEST_SUITE_END() |
| 209 | |
| 210 | |
| 211 | #endif /* DEC_OPTIMIZE_HPP_ */ |
| 212 | |