| 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 |  |