| 1 | /* | 
| 2 |  * staggered_util.hpp | 
| 3 |  * | 
| 4 |  *  Created on: Aug 19, 2015 | 
| 5 |  *      Author: i-bird | 
| 6 |  */ | 
| 7 |  | 
| 8 | #ifndef SRC_GRID_STAGGERED_DIST_GRID_UTIL_HPP_ | 
| 9 | #define SRC_GRID_STAGGERED_DIST_GRID_UTIL_HPP_ | 
| 10 |  | 
| 11 | #include "util/common.hpp" | 
| 12 | #include "VTKWriter/VTKWriter.hpp" | 
| 13 | #include "util/convert.hpp" | 
| 14 |  | 
| 15 |  | 
| 16 | /*! \brief write a property that has attributes | 
| 17 |  * | 
| 18 |  * \tparam ele object we are writing | 
| 19 |  * \tparam vtk vtk writer | 
| 20 |  * \tparam true in case the basic object has attributes | 
| 21 |  * | 
| 22 |  */ | 
| 23 | template<typename ele, typename vtk, bool has_attributes=has_attributes<ele>::value> | 
| 24 | struct vtk_write | 
| 25 | { | 
| 26 | 	/*! \brief Add the grid with attributes name | 
| 27 | 	 * | 
| 28 | 	 * \param vtk_w VTK writer | 
| 29 | 	 * \param output where to write | 
| 30 | 	 * \param i property to write | 
| 31 | 	 * | 
| 32 | 	 */ | 
| 33 | 	vtk_write(vtk vtk_w, const std::string output, const size_t i) | 
| 34 | 	{ | 
| 35 | 		vtk_w.write(output + "_"  + ele::attributes::name[i] + ".vtk" ,ele::attributes::name[i]); | 
| 36 | 	} | 
| 37 | }; | 
| 38 |  | 
| 39 | /*! \brief Add to the vtk writer the key | 
| 40 |  * | 
| 41 |  * \tparam ele object we are writing | 
| 42 |  * \tparam vtk vtk writer | 
| 43 |  * \tparam false in case the basic object has not attributes | 
| 44 |  * | 
| 45 |  */ | 
| 46 | template<typename ele, typename vtk> | 
| 47 | struct vtk_write<ele,vtk,false> | 
| 48 | { | 
| 49 | 	/*! \brief Add the grid with attributes name | 
| 50 | 	 * | 
| 51 | 	 * \param vtk_w VTK writer | 
| 52 | 	 * \param output where to write | 
| 53 | 	 * \param i property to write | 
| 54 | 	 * | 
| 55 | 	 */ | 
| 56 | 	vtk_write(vtk vtk_w, const std::string output, const size_t i) | 
| 57 | 	{ | 
| 58 | 		vtk_w.write(output + "_"  + std::to_string(i) + ".vtk" ,"attr"  + std::to_string(i)); | 
| 59 | 	} | 
| 60 | }; | 
| 61 |  | 
| 62 |  | 
| 63 | /*! \brief Classes to get the number of components of the properties | 
| 64 |  * | 
| 65 |  */ | 
| 66 | template<typename T> | 
| 67 | struct extends | 
| 68 | { | 
| 69 | 	/*! \brief Scalar case | 
| 70 | 	 * | 
| 71 | 	 * \return 1 component | 
| 72 | 	 * | 
| 73 | 	 */ | 
| 74 | 	static inline size_t mul() | 
| 75 | 	{ | 
| 76 | 		return 1; | 
| 77 | 	} | 
| 78 |  | 
| 79 | 	/*! \brief Dimensionality | 
| 80 | 	 * | 
| 81 | 	 * \return 0 | 
| 82 | 	 * | 
| 83 | 	 */ | 
| 84 | 	static inline size_t dim() | 
| 85 | 	{ | 
| 86 | 		return 0; | 
| 87 | 	} | 
| 88 | }; | 
| 89 |  | 
| 90 | //! Partial specialization for N=1 1D-Array | 
| 91 | template<typename T,size_t N1> | 
| 92 | struct extends<T[N1]> | 
| 93 | { | 
| 94 | 	/*! \brief Vector case return N1 component | 
| 95 | 	 * | 
| 96 | 	 * \return N1 | 
| 97 | 	 * | 
| 98 | 	 */ | 
| 99 | 	static inline size_t mul() | 
| 100 | 	{ | 
| 101 | 		return N1; | 
| 102 | 	} | 
| 103 |  | 
| 104 | 	/*! Dimensionality 1 | 
| 105 | 	 * | 
| 106 | 	 * \return 1 | 
| 107 | 	 * | 
| 108 | 	 */ | 
| 109 | 	static inline size_t dim() | 
| 110 | 	{ | 
| 111 | 		return 1; | 
| 112 | 	} | 
| 113 | }; | 
| 114 |  | 
| 115 | //! Partial specialization for N=2 2D-Array | 
| 116 | template<typename T,size_t N1,size_t N2> | 
| 117 | struct extends<T[N1][N2]> | 
| 118 | { | 
| 119 | 	/*! \brief Matrix case return N1*N2 component | 
| 120 | 	 * | 
| 121 | 	 * \return N1*N2 | 
| 122 | 	 * | 
| 123 | 	 */ | 
| 124 | 	static inline size_t mul() | 
| 125 | 	{ | 
| 126 | 		return N1 * N2; | 
| 127 | 	} | 
| 128 |  | 
| 129 | 	/*! Dimensionality 2 | 
| 130 | 	 * | 
| 131 | 	 * \return 2 | 
| 132 | 	 * | 
| 133 | 	 */ | 
| 134 | 	static inline size_t dim() | 
| 135 | 	{ | 
| 136 | 		return 2; | 
| 137 | 	} | 
| 138 | }; | 
| 139 |  | 
| 140 | //! Partial specialization for N=3 | 
| 141 | template<typename T,size_t N1,size_t N2,size_t N3> | 
| 142 | struct extends<T[N1][N2][N3]> | 
| 143 | { | 
| 144 | 	//! number of elements | 
| 145 | 	static inline size_t mul() | 
| 146 | 	{ | 
| 147 | 		return N1 * N2 * N3; | 
| 148 | 	} | 
| 149 |  | 
| 150 | 	/*! number of indexes | 
| 151 | 	 * | 
| 152 | 	 * \return 3 | 
| 153 | 	 * | 
| 154 | 	 */ | 
| 155 | 	static inline size_t dim() | 
| 156 | 	{ | 
| 157 | 		return 3; | 
| 158 | 	} | 
| 159 | }; | 
| 160 |  | 
| 161 | //! Partial specialization for N=4 | 
| 162 | template<typename T,size_t N1,size_t N2,size_t N3,size_t N4> | 
| 163 | struct extends<T[N1][N2][N3][N4]> | 
| 164 | { | 
| 165 | 	//! number of elements | 
| 166 | 	static inline size_t mul() | 
| 167 | 	{ | 
| 168 | 		return N1 * N2 * N3 * N4; | 
| 169 | 	} | 
| 170 |  | 
| 171 | 	/*! number of indexes | 
| 172 | 	 * | 
| 173 | 	 * \return 4 | 
| 174 | 	 * | 
| 175 | 	 */ | 
| 176 | 	static inline size_t dim() | 
| 177 | 	{ | 
| 178 | 		return 4; | 
| 179 | 	} | 
| 180 | }; | 
| 181 |  | 
| 182 | //! Partial specialization for N=5 | 
| 183 | template<typename T,size_t N1,size_t N2,size_t N3,size_t N4,size_t N5> | 
| 184 | struct extends<T[N1][N2][N3][N4][N5]> | 
| 185 | { | 
| 186 | 	//! number of elements | 
| 187 | 	static inline size_t mul() | 
| 188 | 	{ | 
| 189 | 		return N1 * N2 * N3 * N4 * N5; | 
| 190 | 	} | 
| 191 |  | 
| 192 | 	/*! number of indexes | 
| 193 | 	 * | 
| 194 | 	 * \return 5 | 
| 195 | 	 * | 
| 196 | 	 */ | 
| 197 | 	static inline size_t dim() | 
| 198 | 	{ | 
| 199 | 		return 5; | 
| 200 | 	} | 
| 201 | }; | 
| 202 |  | 
| 203 | //! Partial specialization for N=6 | 
| 204 | template<typename T,size_t N1,size_t N2,size_t N3,size_t N4,size_t N5, size_t N6> | 
| 205 | struct extends<T[N1][N2][N3][N4][N5][N6]> | 
| 206 | { | 
| 207 | 	//! number of elements | 
| 208 | 	static inline size_t mul() | 
| 209 | 	{ | 
| 210 | 		return N1 * N2 * N3 * N4 * N5 * N6; | 
| 211 | 	} | 
| 212 |  | 
| 213 | 	/*! number of indexes | 
| 214 | 	 * | 
| 215 | 	 * \return 6 | 
| 216 | 	 * | 
| 217 | 	 */ | 
| 218 | 	static inline size_t dim() | 
| 219 | 	{ | 
| 220 | 		return 6; | 
| 221 | 	} | 
| 222 | }; | 
| 223 |  | 
| 224 | //! Partial specialization for N=7 | 
| 225 | template<typename T,size_t N1,size_t N2,size_t N3,size_t N4,size_t N5, size_t N6, size_t N7> | 
| 226 | struct extends<T[N1][N2][N3][N4][N5][N6][N7]> | 
| 227 | { | 
| 228 | 	//! number of elements | 
| 229 | 	static inline size_t mul() | 
| 230 | 	{ | 
| 231 | 		return N1 * N2 * N3 * N4 * N5 * N6 * N7; | 
| 232 | 	} | 
| 233 |  | 
| 234 | 	/*! number of indexes | 
| 235 | 	 * | 
| 236 | 	 * \return 7 | 
| 237 | 	 * | 
| 238 | 	 */ | 
| 239 | 	static inline size_t dim() | 
| 240 | 	{ | 
| 241 | 		return 7; | 
| 242 | 	} | 
| 243 | }; | 
| 244 |  | 
| 245 | //! Partial specialization for N=8 | 
| 246 | template<typename T,size_t N1,size_t N2,size_t N3,size_t N4,size_t N5, size_t N6, size_t N7, size_t N8> | 
| 247 | struct extends<T[N1][N2][N3][N4][N5][N6][N7][N8]> | 
| 248 | { | 
| 249 | 	/*! number of elements | 
| 250 | 	 * | 
| 251 | 	 * \return the number of elements as N1*N2*N3*......... | 
| 252 | 	 * | 
| 253 | 	 */ | 
| 254 | 	static inline size_t mul() | 
| 255 | 	{ | 
| 256 | 		return N1 * N2 * N3 * N4 * N5 * N6 * N7 * N8; | 
| 257 | 	} | 
| 258 |  | 
| 259 | 	/*! number of indexes | 
| 260 | 	 * | 
| 261 | 	 * \return 8 | 
| 262 | 	 * | 
| 263 | 	 */ | 
| 264 | 	static inline size_t dim() | 
| 265 | 	{ | 
| 266 | 		return 8; | 
| 267 | 	} | 
| 268 | }; | 
| 269 |  | 
| 270 | //! Partial specialization for N=9 | 
| 271 | template<typename T,size_t N1,size_t N2,size_t N3,size_t N4,size_t N5, size_t N6, size_t N7, size_t N8, size_t N9> | 
| 272 | struct extends<T[N1][N2][N3][N4][N5][N6][N7][N8][N9]> | 
| 273 | { | 
| 274 | 	/*! number of elements | 
| 275 | 	 * | 
| 276 | 	 * \return the number of elements as N1*N2*N3*......... | 
| 277 | 	 * | 
| 278 | 	 */ | 
| 279 | 	static inline size_t mul() | 
| 280 | 	{ | 
| 281 | 		return N1 * N2 * N3 * N4 * N5 * N6 * N7 * N8 * N9; | 
| 282 | 	} | 
| 283 |  | 
| 284 | 	/*! number of indexes | 
| 285 | 	 * | 
| 286 | 	 * \return 9 | 
| 287 | 	 * | 
| 288 | 	 */ | 
| 289 | 	static inline size_t dim() | 
| 290 | 	{ | 
| 291 | 		return 9; | 
| 292 | 	} | 
| 293 | }; | 
| 294 |  | 
| 295 | //! Partial specialization for N=10 | 
| 296 | template<typename T,size_t N1,size_t N2,size_t N3,size_t N4,size_t N5, size_t N6, size_t N7, size_t N8, size_t N9, size_t N10> | 
| 297 | struct extends<T[N1][N2][N3][N4][N5][N6][N7][N8][N9][N10]> | 
| 298 | { | 
| 299 | 	/*! number of elements | 
| 300 | 	 * | 
| 301 | 	 * \return the number of elements as N1*N2*N3*......... | 
| 302 | 	 * | 
| 303 | 	 */ | 
| 304 | 	static inline size_t mul() | 
| 305 | 	{ | 
| 306 | 		return N1 * N2 * N3 * N4 * N5 * N6 * N7 * N8 * N9 * N10; | 
| 307 | 	} | 
| 308 |  | 
| 309 | 	/*! number of indexes | 
| 310 | 	 * | 
| 311 | 	 * \return 10 | 
| 312 | 	 * | 
| 313 | 	 */ | 
| 314 | 	static inline size_t dim() | 
| 315 | 	{ | 
| 316 | 		return 10; | 
| 317 | 	} | 
| 318 | }; | 
| 319 |  | 
| 320 | ///////////////////// Copy grid extends | 
| 321 |  | 
| 322 | /*! \brief Classes to copy each component into a grid and add to the VTKWriter the grid | 
| 323 |  * | 
| 324 |  * \param T property to write | 
| 325 |  * \param dim dimansionality | 
| 326 |  * \param St type of space | 
| 327 |  * \param VTK VTK writer | 
| 328 |  * | 
| 329 |  */ | 
| 330 | template<typename T> | 
| 331 | struct write_stag | 
| 332 | { | 
| 333 | 	/*! \brief write the staggered grid | 
| 334 | 	 * | 
| 335 | 	 * \tparam p_val property we are going to write | 
| 336 | 	 * \tparam sg staggered grid type | 
| 337 | 	 * \tparam v_g vector of grids | 
| 338 | 	 * | 
| 339 | 	 * \param st_g staggered grid | 
| 340 | 	 * \param v_g vector of grids | 
| 341 | 	 * \param lg local grid of the staggered grid we are writing | 
| 342 | 	 * | 
| 343 | 	 */ | 
| 344 | 	template<unsigned int p_val, typename sg, typename v_g> static inline void write(sg & st_g, v_g & vg,size_t lg) | 
| 345 | 	{ | 
| 346 | 		// Add a grid; | 
| 347 | 		vg.add(); | 
| 348 | 		size_t k = vg.size() - 1; | 
| 349 |  | 
| 350 | 		// Get the source and destination grid | 
| 351 | 		auto & g_src = st_g.get_loc_grid(lg); | 
| 352 | 		auto & g_dst = vg.get(k); | 
| 353 |  | 
| 354 | 		// Set dimensions and memory | 
| 355 | 		g_dst.resize(g_src.getGrid().getSize()); | 
| 356 |  | 
| 357 | 		// copy | 
| 358 |  | 
| 359 | 		auto it = vg.get(k).getIterator(); | 
| 360 |  | 
| 361 | 		while(it.isNext()) | 
| 362 | 		{ | 
| 363 | 			g_dst.template get<0>(it.get()) = g_src.template get<p_val>(it.get()); | 
| 364 |  | 
| 365 | 			++it; | 
| 366 | 		} | 
| 367 | 	} | 
| 368 | }; | 
| 369 |  | 
| 370 | /*! \brief for each component add a grid fill it, and add to the VTK writer | 
| 371 |  * | 
| 372 |  * \param T Property to copy | 
| 373 |  * \param N1 number of components | 
| 374 |  * | 
| 375 |  */ | 
| 376 | template<typename T,size_t N1> | 
| 377 | struct write_stag<T[N1]> | 
| 378 | { | 
| 379 | 	/*! \brief write the staggered grid | 
| 380 | 	 * | 
| 381 | 	 * \tparam p_val property we are going to write | 
| 382 | 	 * \tparam sg staggered grid type | 
| 383 | 	 * \tparam v_g vector of grids | 
| 384 | 	 * | 
| 385 | 	 * \param st_g staggered grid | 
| 386 | 	 * \param v_g vector of grids | 
| 387 | 	 * \param lg local grid of the staggered grid we are writing | 
| 388 | 	 * | 
| 389 | 	 */ | 
| 390 | 	template<unsigned int p_val, typename sg, typename v_g> static inline void write(sg & st_g, v_g & vg,size_t lg) | 
| 391 | 	{ | 
| 392 | 		for (size_t i = 0 ; i < N1 ; i++) | 
| 393 | 		{ | 
| 394 | 			// Add a grid; | 
| 395 | 			vg.add(); | 
| 396 | 			size_t k = vg.size() - 1; | 
| 397 |  | 
| 398 | 			// Get the source and destination grid | 
| 399 | 			auto & g_src = st_g.get_loc_grid(lg); | 
| 400 | 			auto & g_dst = vg.get(k); | 
| 401 |  | 
| 402 | 			// Set dimensions and memory | 
| 403 | 			g_dst.resize(g_src.getGrid().getSize()); | 
| 404 |  | 
| 405 | 			auto it = vg.get(k).getIterator(); | 
| 406 |  | 
| 407 | 			while(it.isNext()) | 
| 408 | 			{ | 
| 409 | 				g_dst.template get<0>(it.get()) = g_src.template get<p_val>(it.get())[i]; | 
| 410 |  | 
| 411 | 				++it; | 
| 412 | 			} | 
| 413 | 		} | 
| 414 | 	} | 
| 415 | }; | 
| 416 |  | 
| 417 | //! Partial specialization for N=2 2D-Array | 
| 418 | template<typename T,size_t N1,size_t N2> | 
| 419 | struct write_stag<T[N1][N2]> | 
| 420 | { | 
| 421 | 	/*! \brief write the staggered grid | 
| 422 | 	 * | 
| 423 | 	 * \tparam p_val property we are going to write | 
| 424 | 	 * \tparam sg staggered grid type | 
| 425 | 	 * \tparam v_g vector of grids | 
| 426 | 	 * | 
| 427 | 	 * \param st_g staggered grid | 
| 428 | 	 * \param v_g vector of grids | 
| 429 | 	 * \param lg local grid of the staggered grid we are writing | 
| 430 | 	 * | 
| 431 | 	 */ | 
| 432 | 	template<unsigned int p_val, typename sg, typename v_g> static inline void write(sg & st_g, v_g & vg,size_t lg) | 
| 433 | 	{ | 
| 434 | 		for (size_t i = 0 ; i < N1 ; i++) | 
| 435 | 		{ | 
| 436 | 			for (size_t j = 0 ; j < N2 ; j++) | 
| 437 | 			{ | 
| 438 | 				// Add a grid; | 
| 439 | 				vg.add(); | 
| 440 | 				size_t k = vg.size() - 1; | 
| 441 |  | 
| 442 | 				// Set dimensions and memory | 
| 443 | 				vg.get(k).resize(st_g.get_loc_grid(lg).getGrid().getSize()); | 
| 444 |  | 
| 445 | 				// copy | 
| 446 | 				auto & g_src = st_g.get_loc_grid(lg); | 
| 447 | 				auto & g_dst = vg.get(k); | 
| 448 | 				auto it = vg.get(k).getIterator(); | 
| 449 |  | 
| 450 | 				while(it.isNext()) | 
| 451 | 				{ | 
| 452 | 					g_dst.template get<0>(it.get()) = g_src.template get<p_val>(it.get())[i][j]; | 
| 453 |  | 
| 454 | 					++it; | 
| 455 | 				} | 
| 456 | 			} | 
| 457 | 		} | 
| 458 | 	} | 
| 459 | }; | 
| 460 |  | 
| 461 | ///////////////////// Staggered default positioning //////////////////////// | 
| 462 |  | 
| 463 | /*! \brief this class is a functor for "for_each" algorithm | 
| 464 |  * | 
| 465 |  * For each element of the boost::vector the operator() is called. | 
| 466 |  * Is mainly used to produce a default position vector for each | 
| 467 |  * property | 
| 468 |  * | 
| 469 |  * \tparam dim dimensionality | 
| 470 |  * \tparam v boost::fusion::vector of properties | 
| 471 |  * \tparam has_posMask case when v has a position mask | 
| 472 |  * | 
| 473 |  */ | 
| 474 |  | 
| 475 | template<unsigned int dim, typename v, bool has_pM = has_posMask<v>::value> | 
| 476 | class stag_set_position | 
| 477 | { | 
| 478 | 	//! vector containing the position of the properties in the cells (staggered properties are staggered) | 
| 479 | 	// within the cell | 
| 480 | 	openfpm::vector<comb<dim>> (& pos_prp)[boost::fusion::result_of::size<v>::type::value]; | 
| 481 |  | 
| 482 | public: | 
| 483 |  | 
| 484 | 	/*! \brief Constructor | 
| 485 | 	 * | 
| 486 | 	 * \param vector of the staggered position (It is going to be filled by this class) | 
| 487 | 	 * | 
| 488 | 	 */ | 
| 489 | 	stag_set_position( openfpm::vector<comb<dim>> (& pos_prp)[boost::fusion::result_of::size<v>::type::value]) | 
| 490 | 	:pos_prp(pos_prp) | 
| 491 | 	{} | 
| 492 |  | 
| 493 | 	/*! It calculate the staggered position for every property | 
| 494 | 	 * | 
| 495 | 	 * \param t property | 
| 496 | 	 * | 
| 497 | 	 */ | 
| 498 | 	template<typename T> | 
| 499 | 	void operator()(T& t) const | 
| 500 | 	{ | 
| 501 | 		// This is the type of the object we have to copy | 
| 502 | 		typedef typename boost::mpl::at<v,typename boost::mpl::int_<T::value>>::type prop; | 
| 503 |  | 
| 504 | 		bool val = prop::stag_pos_mask[T::value]; | 
| 505 |  | 
| 506 | 		if (val == false) | 
| 507 | 			return; | 
| 508 |  | 
| 509 | 		// Dimension of the object | 
| 510 | 		size_t dim_prp = extends<prop>::dim(); | 
| 511 |  | 
| 512 | 		// It is a scalar | 
| 513 | 		if (dim_prp == 0) | 
| 514 | 		{ | 
| 515 | 			comb<dim> c; | 
| 516 | 			c.zero(); | 
| 517 |  | 
| 518 | 			// It stay in the center | 
| 519 | 			pos_prp[T::value].add(c); | 
| 520 | 		} | 
| 521 | 		else if (dim_prp == 1) | 
| 522 | 		{ | 
| 523 | 			// It stay on the object of dimension dim-1 (Negative part) | 
| 524 | 			for (size_t i = 0 ; i < dim ; i++) | 
| 525 | 			{ | 
| 526 | 				comb<dim> c; | 
| 527 | 				c.zero(); | 
| 528 | 				c.value(i) = -1; | 
| 529 |  | 
| 530 | 				pos_prp[T::value].add(c); | 
| 531 | 			} | 
| 532 | 		} | 
| 533 | 		else if (dim_prp == 2) | 
| 534 | 		{ | 
| 535 | 			// Create an hypercube object | 
| 536 | 			HyperCube<dim> hyp; | 
| 537 |  | 
| 538 | 			// Diagonal part live in | 
| 539 | 			for (size_t i = 0 ; i < dim ; i++) | 
| 540 | 			{ | 
| 541 | 				comb<dim> c1 = pos_prp[T::value-1].get(i); | 
| 542 | 				for (size_t j = 0 ; j < dim ; j++) | 
| 543 | 				{ | 
| 544 | 					comb<dim> c2; | 
| 545 | 					c2.zero(); | 
| 546 | 					c2.value(i) = 1; | 
| 547 |  | 
| 548 | 					comb<dim> c_res = (c1 + c2) & 0x1; | 
| 549 |  | 
| 550 | 					pos_prp[T::value].add(c_res); | 
| 551 | 				} | 
| 552 | 			} | 
| 553 | 		} | 
| 554 | 		else if (dim_prp > 2) | 
| 555 | 		{ | 
| 556 | 			std::cerr << __FILE__ << ":"  << __LINE__ << " Tensor of rank bigger than 2 are not supported" ; | 
| 557 | 		} | 
| 558 | 	} | 
| 559 | }; | 
| 560 |  | 
| 561 | ///////////////////// Staggered default positioning //////////////////////// | 
| 562 |  | 
| 563 | /*! \brief this class is a functor for "for_each" algorithm | 
| 564 |  * | 
| 565 |  * For each element of the boost::vector the operator() is called. | 
| 566 |  * Is mainly used to produce a default position vector for each | 
| 567 |  * property | 
| 568 |  * | 
| 569 |  * \tparam vector of properties | 
| 570 |  * | 
| 571 |  */ | 
| 572 |  | 
| 573 | template<unsigned int dim, typename v> | 
| 574 | class stag_set_position<dim,v,false> | 
| 575 | { | 
| 576 | private: | 
| 577 |  | 
| 578 | 	//! vector containing the position of the properties in the cells (staggered properties are staggered) | 
| 579 | 	// within the cell | 
| 580 | 	openfpm::vector<comb<dim>> (& pos_prp)[boost::fusion::result_of::size<v>::type::value]; | 
| 581 |  | 
| 582 |  | 
| 583 | public: | 
| 584 |  | 
| 585 | 	/*! \brief Constructor | 
| 586 | 	 * | 
| 587 | 	 * \param vector of the staggered position (It is going to be filled by this class) | 
| 588 | 	 * | 
| 589 | 	 */ | 
| 590 | 	stag_set_position( openfpm::vector<comb<dim>> (& pos_prp)[boost::fusion::result_of::size<v>::type::value]) | 
| 591 | 	:pos_prp(pos_prp) | 
| 592 | 	{} | 
| 593 |  | 
| 594 | 	/*! It calculate the staggered position for every property | 
| 595 | 	 * | 
| 596 | 	 * \param t property | 
| 597 | 	 * | 
| 598 | 	 */ | 
| 599 | 	template<typename T> | 
| 600 | 	void operator()(T& t) const | 
| 601 | 	{ | 
| 602 | 		// This is the type of the object we have to copy | 
| 603 | 		typedef typename boost::mpl::at<v,typename boost::mpl::int_<T::value>>::type prop; | 
| 604 |  | 
| 605 | 		// Dimension of the object | 
| 606 | 		size_t dim_prp = extends<prop>::dim(); | 
| 607 |  | 
| 608 | 		// It is a scalar | 
| 609 | 		if (dim_prp == 0) | 
| 610 | 		{ | 
| 611 | 			comb<dim> c; | 
| 612 | 			c.zero(); | 
| 613 |  | 
| 614 | 			// It stay in the center | 
| 615 | 			pos_prp[T::value].add(c); | 
| 616 | 		} | 
| 617 | 		else if (dim_prp == 1) | 
| 618 | 		{ | 
| 619 | 			// It stay on the object of dimension dim-1 (Negative part) | 
| 620 | 			for (size_t i = 0 ; i < dim ; i++) | 
| 621 | 			{ | 
| 622 | 				comb<dim> c; | 
| 623 | 				c.zero(); | 
| 624 | 				c.getComb()[i] = -1; | 
| 625 |  | 
| 626 | 				pos_prp[T::value].add(c); | 
| 627 | 			} | 
| 628 | 		} | 
| 629 | 		else if (dim_prp == 2) | 
| 630 | 		{ | 
| 631 | 			// Diagonal part live in | 
| 632 | 			for (size_t i = 0 ; i < dim ; i++) | 
| 633 | 			{ | 
| 634 | 				comb<dim> c1 = pos_prp[T::value-1].get(i); | 
| 635 | 				for (size_t j = 0 ; j < dim ; j++) | 
| 636 | 				{ | 
| 637 | 					comb<dim> c2; | 
| 638 | 					c2.zero(); | 
| 639 | 					c2.getComb()[j] = 1; | 
| 640 |  | 
| 641 | 					comb<dim> c_res = (c2 + c1).flip(); | 
| 642 |  | 
| 643 | 					pos_prp[T::value].add(c_res); | 
| 644 | 				} | 
| 645 | 			} | 
| 646 | 		} | 
| 647 | 		else if (dim_prp > 2) | 
| 648 | 		{ | 
| 649 | 			std::cerr << __FILE__ << ":"  << __LINE__ << " Tensor of rank bigger than 2 are not supported" ; | 
| 650 | 		} | 
| 651 | 	} | 
| 652 | }; | 
| 653 |  | 
| 654 | /*! \brief It create separated grid for each properties to write them into a file | 
| 655 |  * | 
| 656 |  * \tparam dim dimensionality of the grids | 
| 657 |  * \tparam obj type object to print, must be in OpenFPM format | 
| 658 |  * | 
| 659 |  */ | 
| 660 | template<unsigned int dim, typename st_grid, typename St> | 
| 661 | class stag_create_and_add_grid | 
| 662 | { | 
| 663 |  | 
| 664 | 	size_t p_id; | 
| 665 |  | 
| 666 | 	// staggered grid to write | 
| 667 | 	st_grid & st_g; | 
| 668 |  | 
| 669 | public: | 
| 670 |  | 
| 671 | 	/*! \brief Constructor | 
| 672 | 	 * | 
| 673 | 	 * \param st_g staggered grid | 
| 674 | 	 * \param p_id process id | 
| 675 | 	 * | 
| 676 | 	 */ | 
| 677 | 	stag_create_and_add_grid(st_grid & st_g, size_t p_id) | 
| 678 | 	:p_id(p_id),st_g(st_g) | 
| 679 | 	{} | 
| 680 |  | 
| 681 | 	template<unsigned int p_val> void out_normal() | 
| 682 | 	{ | 
| 683 | 		// property type | 
| 684 | 		typedef typename boost::mpl::at< typename st_grid::value_type::type , typename boost::mpl::int_<p_val> >::type ele; | 
| 685 |  | 
| 686 | 		// create an openfpm format object from the property type | 
| 687 | 		typedef object<typename boost::fusion::vector<ele>> d_object; | 
| 688 |  | 
| 689 | 		VTKWriter<boost::mpl::pair<grid_cpu<dim, d_object >,St>,VECTOR_GRIDS> vtk_w; | 
| 690 |  | 
| 691 | 		// Create a vector of grids | 
| 692 |  | 
| 693 | 		openfpm::vector< grid_cpu<dim, d_object > > vg(st_g.getN_loc_grid()); | 
| 694 |  | 
| 695 | 		// for each domain grid | 
| 696 | 		for (size_t i = 0 ; i < vg.size() ; i++) | 
| 697 | 		{ | 
| 698 | 			// Set dimansions and memory | 
| 699 | 			vg.get(i).resize(st_g.get_loc_grid(i).getGrid().getSize()); | 
| 700 |  | 
| 701 | 			auto & g_src = st_g.get_loc_grid(i); | 
| 702 | 			auto & g_dst = vg.get(i); | 
| 703 |  | 
| 704 | 			auto it = vg.get(i).getIterator(); | 
| 705 |  | 
| 706 | 			while(it.isNext()) | 
| 707 | 			{ | 
| 708 | 				object_si_d< decltype(g_src.get_o(it.get())),decltype(g_dst.get_o(it.get())) ,OBJ_ENCAP,p_val>(g_src.get_o(it.get()),g_dst.get_o(it.get())); | 
| 709 |  | 
| 710 | 				++it; | 
| 711 | 			} | 
| 712 |  | 
| 713 | 			Point<dim,St> offset = st_g.getOffset(i); | 
| 714 | 			Point<dim,St> spacing = st_g.getSpacing(); | 
| 715 | 			Box<dim,size_t> dom = st_g.getDomain(i); | 
| 716 |  | 
| 717 | 			vtk_w.add(g_dst,offset,spacing,dom); | 
| 718 | 		} | 
| 719 |  | 
| 720 | 		vtk_w.write("vtk_grids_st_"  + std::to_string(p_id) + "_"  + std::to_string(p_val) + ".vtk" ); | 
| 721 | 	} | 
| 722 |  | 
| 723 | 	template<unsigned int p_val> void out_staggered() | 
| 724 | 	{ | 
| 725 | 		// property type | 
| 726 | 		typedef typename boost::mpl::at< typename st_grid::value_type::type , typename boost::mpl::int_<p_val> >::type ele; | 
| 727 |  | 
| 728 | 		// Eliminate the extends | 
| 729 | 		typedef typename std::remove_all_extents<ele>::type r_ele; | 
| 730 |  | 
| 731 | 		// create an openfpm format object from the property type | 
| 732 | 		typedef object<typename boost::fusion::vector<r_ele>> d_object; | 
| 733 |  | 
| 734 | 		VTKWriter<boost::mpl::pair<grid_cpu<dim, d_object >,St>,VECTOR_ST_GRIDS> vtk_w; | 
| 735 |  | 
| 736 | 		// Create a vector of grids | 
| 737 | 		openfpm::vector< grid_cpu<dim, d_object > > vg; | 
| 738 | 		vg.reserve(st_g.getN_loc_grid() * extends<ele>::mul()); | 
| 739 |  | 
| 740 | 		size_t k = 0; | 
| 741 |  | 
| 742 | 		// for each domain grid | 
| 743 | 		for (size_t i = 0 ; i < st_g.getN_loc_grid() ; i++) | 
| 744 | 		{ | 
| 745 | 			write_stag<ele>::template write<p_val, st_grid,openfpm::vector< grid_cpu<dim, d_object > > >(st_g,vg,i); | 
| 746 |  | 
| 747 | 			// for each component | 
| 748 | 			for ( ; k < vg.size() ; k++) | 
| 749 | 			{ | 
| 750 | 				Point<dim,St> offset = st_g.getOffset(i); | 
| 751 | 				Point<dim,St> spacing = st_g.getSpacing(); | 
| 752 | 				Box<dim,size_t> dom = st_g.getDomain(i); | 
| 753 |  | 
| 754 | 				vtk_w.add(i,vg.get(k),offset,spacing,dom,st_g.c_prp[p_val].get(k)); | 
| 755 | 			} | 
| 756 |  | 
| 757 | 			k = vg.size(); | 
| 758 | 		} | 
| 759 |  | 
| 760 | 		vtk_write<typename st_grid::value_type,VTKWriter<boost::mpl::pair<grid_cpu<dim, d_object >,St>,VECTOR_ST_GRIDS>> v(vtk_w,"vtk_grids_st_"  + std::to_string(p_id),p_val); | 
| 761 | 	} | 
| 762 |  | 
| 763 | 	//! It call the copy function for each property | 
| 764 | 	template<typename T> | 
| 765 | 	void operator()(T& t) | 
| 766 | 	{ | 
| 767 | 		if (st_g.is_staggered_prop(T::value) == false) | 
| 768 | 			out_normal<T::value>(); | 
| 769 | 		else | 
| 770 | 			out_staggered<T::value>(); | 
| 771 | 	} | 
| 772 | }; | 
| 773 |  | 
| 774 | /*! \brief Check that the size of the iterators match | 
| 775 |  * | 
| 776 |  * It check the the boxes that the sub iterator defines has same dimensions, for example | 
| 777 |  * if the first sub-iterator, iterate from (1,1) to (5,3) and the second from (2,2) to (6,4) | 
| 778 |  * they match (2,2) to (4,6) they do not match | 
| 779 |  * | 
| 780 |  * \tparam Grid_map type of the map grid | 
| 781 |  * \tparam Grid_dst type of the destination grid | 
| 782 |  * | 
| 783 |  * \param it1 Iterator1 | 
| 784 |  * \param it2 Iterator2 | 
| 785 |  * | 
| 786 |  * \return true if they match | 
| 787 |  * | 
| 788 |  */ | 
| 789 | template<typename Eqs_sys, typename it1_type, typename it2_type> bool checkIterator(const it1_type & it1, const it2_type & it2) | 
| 790 | { | 
| 791 | #ifdef SE_CLASS1 | 
| 792 |  | 
| 793 | 	grid_key_dx<Eqs_sys::dims> it1_k = it1.getStop() - it1.getStart(); | 
| 794 | 	grid_key_dx<Eqs_sys::dims> it2_k = it2.getStop() - it2.getStart(); | 
| 795 |  | 
| 796 | 	for (size_t i = 0 ; i < Eqs_sys::dims ; i++) | 
| 797 | 	{ | 
| 798 | 		if (it1_k.get(i) !=  it2_k.get(i)) | 
| 799 | 		{ | 
| 800 | 			std::cerr << __FILE__ << ":"  << __LINE__ << " error src iterator and destination iterator does not match in size\n" ; | 
| 801 | 			return false; | 
| 802 | 		} | 
| 803 | 	} | 
| 804 |  | 
| 805 | 	return true; | 
| 806 | #else | 
| 807 |  | 
| 808 | 	return true; | 
| 809 |  | 
| 810 | #endif | 
| 811 | } | 
| 812 |  | 
| 813 | /*! \brief this class is a functor for "for_each" algorithm | 
| 814 |  * | 
| 815 |  * This class is a functor for "for_each" algorithm. For each | 
| 816 |  * element of the boost::vector the operator() is called. | 
| 817 |  * Is mainly used to calculate the interpolation points for each | 
| 818 |  * property in a staggered grid | 
| 819 |  * | 
| 820 |  * \tparam dim Dimensionality | 
| 821 |  * \tparam v_prp_id vector of properties id | 
| 822 |  * \tparam v_prp_type vector with the properties | 
| 823 |  * | 
| 824 |  */ | 
| 825 | template<unsigned int dim, unsigned int n_prop, typename v_prp_id, typename v_prp_type> | 
| 826 | struct interp_points | 
| 827 | { | 
| 828 | /*#ifdef SE_CLASS3 | 
| 829 |  | 
| 830 | 	// number of properties we are processing | 
| 831 | 	typedef boost::mpl::size<v_prp_id> v_size_old; | 
| 832 |  | 
| 833 | 	typedef boost::mpl::int_<v_size_old::value-3> v_size; | 
| 834 |  | 
| 835 | #else*/ | 
| 836 |  | 
| 837 | 	// number of properties we are processing | 
| 838 | 	typedef boost::mpl::size<v_prp_id> v_size; | 
| 839 |  | 
| 840 | //#endif | 
| 841 |  | 
| 842 | 	// interpolation points for each property | 
| 843 | 	openfpm::vector<std::vector<comb<dim>>> (& interp_pts)[v_size::value]; | 
| 844 |  | 
| 845 | 	// staggered position for each property | 
| 846 | 	const openfpm::vector<comb<dim>> (&stag_pos)[n_prop]; | 
| 847 |  | 
| 848 | 	/*! \brief constructor | 
| 849 | 	 * | 
| 850 | 	 * It define the copy parameters. | 
| 851 | 	 * | 
| 852 | 	 * \param inter_pts array that for each property contain the interpolation points for each components | 
| 853 | 	 * \param staggered position for each property and components | 
| 854 | 	 * | 
| 855 | 	 */ | 
| 856 | 	inline interp_points(openfpm::vector<std::vector<comb<dim>>> (& interp_pts)[v_size::value],const openfpm::vector<comb<dim>> (&stag_pos)[n_prop]) | 
| 857 | 	:interp_pts(interp_pts),stag_pos(stag_pos){}; | 
| 858 |  | 
| 859 | 	//! It call the copy function for each property | 
| 860 | 	template<typename T> | 
| 861 | 	inline void operator()(T& t) | 
| 862 | 	{ | 
| 863 | 		// This is the type of the object we have to copy | 
| 864 | 		typedef typename boost::mpl::at_c<v_prp_type,T::value>::type prp_type; | 
| 865 | 		typedef typename boost::mpl::at<v_prp_id,T>::type p_id; | 
| 866 |  | 
| 867 | 		interp_pts[T::value].resize(stag_pos[p_id::value].size()); | 
| 868 |  | 
| 869 | 		for (size_t i = 0 ; i < stag_pos[p_id::value].size() ; i++) | 
| 870 | 		{ | 
| 871 | 			// Create the interpolation points | 
| 872 | 			interp_pts[T::value].get(i) = SubHyperCube<dim,dim - std::rank<prp_type>::value>::getCombinations_R(stag_pos[p_id::value].get(i),0); | 
| 873 |  | 
| 874 | 			// interp_point are -1,0,1, map the -1 to 0 and 1 to -1 | 
| 875 | 			for (size_t j = 0 ; j < interp_pts[T::value].get(i).size() ; j++) | 
| 876 | 			{ | 
| 877 | 				for (size_t k = 0 ; k < dim ; k++) | 
| 878 | 					interp_pts[T::value].get(i)[j].getComb()[k] = - ((interp_pts[T::value].get(i)[j].getComb()[k] == -1)?0:interp_pts[T::value].get(i)[j].getComb()[k]); | 
| 879 | 			} | 
| 880 | 		} | 
| 881 | 	} | 
| 882 | }; | 
| 883 |  | 
| 884 | #endif /* SRC_GRID_STAGGERED_DIST_GRID_UTIL_HPP_ */ | 
| 885 |  |