nn_processor.hpp 18.9 KB
Newer Older
incardon's avatar
incardon committed
1 2 3 4 5 6 7 8 9 10 11
/*
 * nn_processor.hpp
 *
 *  Created on: Aug 9, 2015
 *      Author: i-bird
 */

#ifndef SRC_DECOMPOSITION_NN_PROCESSOR_HPP_
#define SRC_DECOMPOSITION_NN_PROCESSOR_HPP_

#include "common.hpp"
12
#include <unordered_map>
incardon's avatar
incardon committed
13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30

/*! \brief This class store the adjacent processors and the adjacent sub_domains
 *
 * \tparam dim is the dimensionality of the physical domain we are going to decompose.
 * \tparam T type of the space we decompose, Real, Integer, Complex ...
 *
 * \see CartDecomposition
 *
 */
template<unsigned int dim, typename T>
class nn_prcs
{
	//! Virtual cluster
	Vcluster & v_cl;

	//! List of adjacent processors
	openfpm::vector<size_t> nn_processors;

31
	//! for each near processor store the sub-domains of the near processors
incardon's avatar
incardon committed
32 33
	std::unordered_map<size_t, N_box<dim,T>> nn_processor_subdomains;

34
	//! when we add new boxes, are added here
35 36
	std::unordered_map<size_t, N_box<dim,T>> nn_processor_subdomains_tmp;

37 38 39
	//! contain the same information as the member boxes with the difference that
	//! instead of the Box itself, it contain the sub-domain id in the list of the
	//! local sub-domains
incardon's avatar
incardon committed
40 41
	openfpm::vector<openfpm::vector<size_t>> proc_adj_box;

42
	//! contain the set of sub-domains sent to the other processors
incardon's avatar
incardon committed
43 44
	openfpm::vector< openfpm::vector< ::SpaceBox<dim,T>> > boxes;

45
	//! Receive counter
incardon's avatar
incardon committed
46 47
	size_t recv_cnt;

48 49 50
	//! applyBC function is suppose to be called only one time
	bool aBC;

Pietro Incardona's avatar
Pietro Incardona committed
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
	/*! \brief It shift a box but it does consistently
	 *
	 * In calculating internal and external ghost boxes, domains are shifted by periodicity.
	 * In particular, consider a box touching with the left bolder the left border of the domain
	 *

	 before shift                              after shift

+-----------------------------+        +------------------------------+
|                             |        |                              |
|      domain                 |        |        domain                |
|                             |        |                              |
|                             |        |                              |
+---------+                   |        |                              +---------+
|         |                   |        |                              |         |
|         |                   |        |                              |         |
|  box    |                   |        |                              |   box   |
|         |                   |        |                              |         |
|         |                   |        |                              |         |
+---------+                   |        |                              +---------+
|                             |        |                              |
|                             |        |                              |
|                             |        |                              |
|                             |        |                              |
|                             |        |                              |
+-----------------------------+        +------------------------------+

	 *
	 *
	 *
	 *
	 *
	 * shifting the box on the right by the size of the domain, we expect to have a box touching with
	 * the left side the right side of the domain. Because of rounding off problem this is not possible
	 * with a simple shift. This function ensure consistency like ensuring the previous condition, with
	 * the assumption that the shift is +/- the domain size
	 *
	 * \param box to shift
	 * \param domain
	 * \param shift
	 *
	 */
	inline void consistent_shift(Box<dim,T> & box, const Box<dim,T> & domain, const Point<dim,T> & shift)
	{
		for (size_t k = 0 ; k < dim ; k++)
		{
			// if it touch on the left and shift on the right
			if (box.getLow(k) == domain.getLow(k) && shift.get(k) > 0)
			{
				box.setLow(k,domain.getHigh(k));
				box.setHigh(k,box.getHigh(k) + shift.get(k));
			}
			else if (box.getLow(k) == domain.getHigh(k) && shift.get(k) < 0)
			{
				box.setLow(k,domain.getLow(k));
				box.setHigh(k,box.getHigh(k) + shift.get(k));
			}
			else if (box.getHigh(k) == domain.getHigh(k) && shift.get(k) < 0)
			{
				box.setHigh(k,domain.getLow(k));
				box.setLow(k,box.getLow(k) + shift.get(k));
			}
			else if (box.getHigh(k) == domain.getLow(k) && shift.get(k) > 0)
			{
				box.setHigh(k,domain.getHigh(k));
				box.setLow(k,box.getLow(k) + shift.get(k));
			}
			else
			{
				box.setHigh(k,box.getHigh(k) + shift.get(k));
				box.setLow(k,box.getLow(k) + shift.get(k));
			}
		}
	}

incardon's avatar
incardon committed
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
	/*! \brief Message allocation
	 *
	 * \param message size required to receive from i
	 * \param total message size to receive from all the processors
	 * \param the total number of processor want to communicate with you
	 * \param i processor id
	 * \param ri request id (it is an id that goes from 0 to total_p, and is unique
	 *           every time message_alloc is called)
	 * \param ptr a pointer to the vector_dist structure
	 *
	 * \return the pointer where to store the message
	 *
	 */
	static void * message_alloc(size_t msg_i ,size_t total_msg, size_t total_p, size_t i, size_t ri, void * ptr)
	{
		// cast the pointer
		nn_prcs<dim,T> * cd = static_cast< nn_prcs<dim,T> *>(ptr);

		cd->nn_processor_subdomains[i].bx.resize(msg_i / sizeof(::Box<dim,T>) );

		// Return the receive pointer
		return cd->nn_processor_subdomains[i].bx.getPointer();
	}

150
	/*! \brief add sub-domains to processor for a near processor i
151
	 *
152 153
	 * \param i near processor
	 * \param r_sub real sub-domain id
154
	 * \param bx Box to add
155
	 * \param c from which sector the sub-domain come from
156 157
	 *
	 */
158
	inline void add_nn_subdomain(size_t i, size_t r_sub, const Box<dim,T> & bx, const comb<dim> & c)
159
	{
160 161 162
		N_box<dim,T> & nnpst = nn_processor_subdomains_tmp[i];
		nnpst.bx.add(bx);
		nnpst.pos.add(c);
163
		nnpst.r_sub.add(r_sub);
164 165
	}

166
	/*! \brief In case of periodic boundary conditions we replicate the sub-domains at the border
167
	 *
168
	 * \param domain Domain
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187
	 * \param boundary boundary conditions
	 * \param ghost ghost part
	 *
	 */
	void add_box_periodic(const Box<dim,T> & domain, const Ghost<dim,T> & ghost, const size_t (&bc)[dim])
	{
		HyperCube<dim> hyp;

		// first we create boxes at the border of the domain used to detect the sub-domain
		// that must be adjusted, each of this boxes define a shift in case of periodic boundary condition
		for (long int i = dim-1 ; i >= 0 ; i--)
		{
			std::vector<comb<dim>> cmbs = hyp.getCombinations_R(i);

			for (size_t j = 0 ; j < cmbs.size() ; j++)
			{
				if (check_valid(cmbs[j],bc) == false)
					continue;

188
				// Calculate the sector box
189 190 191 192 193 194 195 196 197 198
				Box<dim,T> bp;
				Point<dim,T> shift;

				for (size_t k = 0 ; k < dim ; k++)
				{
					switch (cmbs[j][k])
					{
					case 1:
						bp.setLow(k,domain.getHigh(k)+ghost.getLow(k));
						bp.setHigh(k,domain.getHigh(k));
199
						shift.get(k) = -domain.getHigh(k)+domain.getLow(k);
200 201 202 203 204 205 206 207
						break;
					case 0:
						bp.setLow(k,domain.getLow(k));
						bp.setHigh(k,domain.getHigh(k));
						shift.get(k) = 0;
						break;
					case -1:
						bp.setLow(k,domain.getLow(k));
Pietro Incardona's avatar
Pietro Incardona committed
208
						bp.setHigh(k,domain.getLow(k)+ghost.getHigh(k));
209
						shift.get(k) = domain.getHigh(k)-domain.getLow(k);
210 211 212 213 214 215 216 217 218 219
						break;
					}
				}

				// Detect all the sub-domain involved, shift them and add to the list
				// Detection is performed intersecting the sub-domains with the ghost
				// parts near the domain borders
				for (size_t k = 0 ; k < getNNProcessors() ; k++)
				{
					// sub-domains of the near processor
220
					const openfpm::vector< ::Box<dim,T> > & nn_sub = getNearSubdomains(IDtoProc(k));
221 222 223 224 225 226 227 228

					for (size_t l = 0 ; l < nn_sub.size(); l++)
					{
						Box<dim,T> sub = nn_sub.get(l);
						Box<dim,T> b_int;

						if (sub.Intersect(bp,b_int) == true)
						{
Pietro Incardona's avatar
Pietro Incardona committed
229 230 231 232 233 234 235 236
							Box<dim,T> sub2 = sub;
							sub2 += shift;

							// Here we have to be careful of rounding off problems, in particular if any part
							// of the sub-domain touch the border of the domain

							consistent_shift(sub,domain,shift);

237
							add_nn_subdomain(IDtoProc(k),l,sub,cmbs[j]);
238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258
						}
					}
				}
			}
		}

		flush();
	}

	/*! \brief Flush the temporal added sub-domain to the processor sub-domain
	 *
	 *
	 */
	void flush()
	{
		for ( auto it = nn_processor_subdomains_tmp.begin(); it != nn_processor_subdomains_tmp.end(); ++it )
		{
			const N_box<dim,T> & nnp_bx = it->second;

			for (size_t i = 0 ; i < nnp_bx.bx.size() ; i++)
			{
259 260 261 262 263
				N_box<dim,T> & nnps = nn_processor_subdomains[it->first];
				const N_box<dim,T> & nnps_tmp = nn_processor_subdomains_tmp[it->first];

				nnps.bx.add(nnps_tmp.bx.get(i));
				nnps.pos.add(nnps_tmp.pos.get(i));
264
				nnps.r_sub.add(nnps_tmp.r_sub.get(i));
265 266
			}
		}
267 268

		nn_processor_subdomains_tmp.clear();
269 270
	}

incardon's avatar
incardon committed
271 272 273
public:

	nn_prcs(Vcluster & v_cl)
274
	:v_cl(v_cl),recv_cnt(0),aBC(false)
275
	{}
incardon's avatar
incardon committed
276

277
	//! Constructor from another nn_prcs
278
	nn_prcs(const nn_prcs<dim,T> & ilg)
279
	:v_cl(ilg.v_cl),recv_cnt(0),aBC(false)
280 281 282 283 284 285
	{
		this->operator=(ilg);
	};

	//! Constructor from temporal ie_loc_ghost
	nn_prcs(nn_prcs<dim,T> && ilg)
286
	:v_cl(ilg.v_cl),recv_cnt(0),aBC(false)
287 288 289 290
	{
		this->operator=(ilg);
	}

291 292 293 294 295 296 297 298
	/*! Check that the compination is valid
	 *
	 * \param cmb combination
	 * \param bc boundary conditions
	 *
	 */
	static bool inline check_valid(comb<dim> cmb,const size_t (& bc)[dim])
	{
299 300 301 302
		// the combination 0 is not valid
		if (cmb.n_zero() == dim)
			return false;

303 304 305 306 307 308 309 310
		for (size_t i = 0 ; i < dim ; i++)
		{
			if (bc[i] == NON_PERIODIC && cmb.getComb()[i] != 0)
				return false;
		}
		return true;
	}

311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340
	/*! \brief Copy the object
	 *
	 * \param nnp object to copy
	 *
	 */
	nn_prcs<dim,T> & operator=(const nn_prcs<dim,T> & nnp)
	{
		nn_processors = nnp.nn_processors;
		nn_processor_subdomains = nnp.nn_processor_subdomains;
		proc_adj_box = nnp.proc_adj_box;
		boxes = nnp.boxes;

		return *this;
	}

	/*! \brief Copy the object
	 *
	 * \param nnp object to copy
	 *
	 */
	nn_prcs<dim,T> & operator=(nn_prcs<dim,T> && nnp)
	{
		nn_processors.swap(nnp.nn_processors);
		nn_processor_subdomains.swap(nnp.nn_processor_subdomains);
		proc_adj_box.swap(nnp.proc_adj_box);
		boxes = nnp.boxes;

		return *this;
	}

incardon's avatar
incardon committed
341 342 343 344 345 346 347
	/*! \brief Create the list of adjacent processors and the list of adjacent sub-domains
	 *
	 * \param box_nn_processors
	 *
	 */
	void create(const openfpm::vector<openfpm::vector<long unsigned int> > & box_nn_processor, const openfpm::vector<SpaceBox<dim,T>> & sub_domains)
	{
348
		// produce the list of the adjacent processor (nn_processors) list
incardon's avatar
incardon committed
349 350 351 352 353 354 355 356
		for (size_t i = 0 ;  i < box_nn_processor.size() ; i++)
		{
			for (size_t j = 0 ; j < box_nn_processor.get(i).size() ; j++)
			{
				nn_processors.add(box_nn_processor.get(i).get(j));
			}
		}

357
		// make the list of the processor sort and unique
incardon's avatar
incardon committed
358 359 360 361
	    std::sort(nn_processors.begin(), nn_processors.end());
	    auto last = std::unique(nn_processors.begin(), nn_processors.end());
	    nn_processors.erase(last, nn_processors.end());

362 363 364
        // link nn_processor_subdomains to nn_processors
	    // it is used to quickly convert the Processor rank to the position in the list of the
	    // near processors
365 366 367 368
        for (size_t i = 0 ;  i < box_nn_processor.size() ; i++)
        {
                for (size_t j = 0 ; j < box_nn_processor.get(i).size() ; j++)
                {
369
                        // processor id adjacent to this sub-domain
370 371 372 373 374 375 376 377 378 379 380
                        size_t proc_id = box_nn_processor.get(i).get(j);

                        size_t k = 0;
                        // search inside near processor list
                        for (k = 0 ; k < nn_processors.size() ; k++)
                                if (nn_processors.get(k) == proc_id)    break;

                        nn_processor_subdomains[proc_id].id = k;
                }
        }

381 382
		// create a buffer with the sub-domains that can have an intersection with
        // the near processors
incardon's avatar
incardon committed
383
		proc_adj_box.resize(getNNProcessors());
384
		boxes.resize(getNNProcessors());
incardon's avatar
incardon committed
385 386 387 388 389 390 391 392 393

		for (size_t b = 0 ; b < box_nn_processor.size() ; b++)
		{
			for (size_t p = 0 ; p < box_nn_processor.get(b).size() ; p++)
			{
				size_t prc = box_nn_processor.get(b).get(p);

				// id of the processor in the processor list
				// [value between 0 and the number of the near processors]
394
				size_t id = ProctoID(prc);
incardon's avatar
incardon committed
395 396 397 398 399 400

				boxes.get(id).add(sub_domains.get(b));
				proc_adj_box.get(id).add(b);
			}
		}

401
		nn_processor_subdomains.reserve(nn_processors.size());
incardon's avatar
incardon committed
402 403 404 405

		// Get the sub-domains of the near processors
		v_cl.sendrecvMultipleMessagesNBX(nn_processors,boxes,nn_prcs<dim,T>::message_alloc, this ,NEED_ALL_SIZE);

406 407 408 409 410 411 412 413 414 415 416
		// Add to all the received sub-domains the information that they live in the central sector
		for ( auto it = nn_processor_subdomains.begin(); it != nn_processor_subdomains.end(); ++it )
		{
			const N_box<dim,T> & nnp_bx = it->second;

			for (size_t i = 0 ; i < nnp_bx.bx.size() ; i++)
			{
				comb<dim> c;
				c.zero();

				N_box<dim,T> & nnps = nn_processor_subdomains[it->first];
incardon's avatar
incardon committed
417

418
				nnps.pos.add(c);
419 420
				nnps.r_sub.add(i);
				nnps.n_real_sub = nnps.bx.size();
421 422
			}
		}
incardon's avatar
incardon committed
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441
	}

	/*! \brief Get the number of Near processors
	 *
	 * \return the number of near processors
	 *
	 */
	inline size_t getNNProcessors() const
	{
		return nn_processors.size();
	}

	/*! \brief Return the processor id of the near processor list at place id
	 *
	 * \param id
	 *
	 * \return return the processor rank
	 *
	 */
incardon's avatar
incardon committed
442
	inline size_t IDtoProc(size_t id) const
incardon's avatar
incardon committed
443 444 445 446
	{
		return nn_processors.get(id);
	}

447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467
	/*! \brief Get the real-id of the sub-domains of a near processor
	 *
	 * \param p_id near processor rank
	 *
	 * \return the sub-domains real id
	 *
	 */
	inline const openfpm::vector< size_t > & getNearSubdomainsRealId(size_t p_id) const
	{
		auto key = nn_processor_subdomains.find(p_id);
#ifdef SE_CLASS1
		if (key == nn_processor_subdomains.end())
		{
			std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " error this process rank is not adjacent to the local processor";
		}
#endif

		return key->second.r_sub;
	}

	/*! \brief Get the sub-domains of a near processor
incardon's avatar
incardon committed
468
	 *
469
	 * \param p_id near processor rank
incardon's avatar
incardon committed
470 471 472 473
	 *
	 * \return the sub-domains
	 *
	 */
474
	inline const openfpm::vector< ::Box<dim,T> > & getNearSubdomains(size_t p_id) const
incardon's avatar
incardon committed
475
	{
incardon's avatar
incardon committed
476
		auto key = nn_processor_subdomains.find(p_id);
incardon's avatar
incardon committed
477
#ifdef SE_CLASS1
incardon's avatar
incardon committed
478 479 480 481 482
		if (key == nn_processor_subdomains.end())
		{
			std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " error this process rank is not adjacent to the local processor";
		}
#endif
483

incardon's avatar
incardon committed
484
		return key->second.bx;
incardon's avatar
incardon committed
485 486
	}

487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509
	/*! \brief Get the number of real sub-domains of a near processor
	 *
	 * \note the real sub-domain are the subdomain in the central sector, or any sub-domain that has not been create because of boundary conditions
	 *
	 * \param p_id near processor rank
	 *
	 * \return the number of real sub-domains
	 *
	 */
	inline size_t getNRealSubdomains(size_t p_id) const
	{
		auto key = nn_processor_subdomains.find(p_id);
#ifdef SE_CLASS1
		if (key == nn_processor_subdomains.end())
		{
			std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " error this process rank is not adjacent to the local processor";
		}
#endif

		return key->second.n_real_sub;
	}

	/*! \brief Get the sub-domains sector position of a near processor
incardon's avatar
incardon committed
510
	 *
511
	 * \param p_id near processor rank
incardon's avatar
incardon committed
512
	 *
513
	 * \return the sub-domains positions
incardon's avatar
incardon committed
514 515
	 *
	 */
516
	inline const openfpm::vector< comb<dim> > & getNearSubdomainsPos(size_t p_id) const
incardon's avatar
incardon committed
517
	{
incardon's avatar
incardon committed
518
		auto key = nn_processor_subdomains.find(p_id);
incardon's avatar
incardon committed
519
#ifdef SE_CLASS1
incardon's avatar
incardon committed
520 521 522 523 524
		if (key == nn_processor_subdomains.end())
		{
			std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " error this process rank is not adjacent to the local processor";
		}
#endif
525
		return key->second.pos;
incardon's avatar
incardon committed
526 527
	}

528
	/*! \brief Get the near processor id
incardon's avatar
incardon committed
529
	 *
530
	 * \param p_id adjacent processor rank
incardon's avatar
incardon committed
531
	 *
532
	 * \return the processor rank
incardon's avatar
incardon committed
533 534
	 *
	 */
535
	inline size_t getNearProcessor(size_t p_id) const
incardon's avatar
incardon committed
536 537
	{
		auto key = nn_processor_subdomains.find(p_id);
incardon's avatar
incardon committed
538
#ifdef SE_CLASS1
incardon's avatar
incardon committed
539 540 541 542 543
		if (key == nn_processor_subdomains.end())
		{
			std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " error this process rank is not adjacent to the local processor";
		}
#endif
544 545 546 547 548 549 550 551 552 553 554 555 556 557 558
		return key->second.id;
	}


	/*! \brief For each near processor it give a vector with the id
	 *         of the local sub-domain sent to that processor
	 *
	 * \param p_id adjacent processor (id from 0 to getNNProcessors())
	 *
	 * \return a vector of sub-domains id
	 *
	 */
	inline const openfpm::vector<size_t> & getSentSubdomains(size_t p_id) const
	{
		return proc_adj_box.get(p_id);
incardon's avatar
incardon committed
559 560
	}

incardon's avatar
incardon committed
561 562 563 564 565 566 567
	/*! \brief Convert the processor rank to the id in the list
	 *
	 * \param p processor rank
	 *
	 * \return the id
	 *
	 */
incardon's avatar
incardon committed
568
	inline size_t ProctoID(size_t p) const
incardon's avatar
incardon committed
569
	{
incardon's avatar
incardon committed
570
		auto key = nn_processor_subdomains.find(p);
incardon's avatar
incardon committed
571
#ifdef SE_CLASS1
incardon's avatar
incardon committed
572 573 574 575 576 577 578
		if (key == nn_processor_subdomains.end())
		{
			std::cerr << "Error " << __FILE__ << ":" << __LINE__ << " error this process rank is not adjacent to the local processor";
		}
#endif

		return key->second.id;
incardon's avatar
incardon committed
579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608
	}

	/*! \brief Write the decomposition as VTK file
	 *
	 * The function generate several files
	 *
	 * 1) subdomains_adjacent_X.vtk sub-domains adjacent to the local processor (X)
	 *
	 * where X is the local processor rank
	 *
	 * \param output directory where to write the files
	 * \param p_id id of the local processor
	 *
	 */
	bool write(std::string output) const
	{
		//! subdomains_adjacent_X.vtk sub-domains adjacent to the local processor (X)
		VTKWriter<openfpm::vector<::Box<dim,T>>,VECTOR_BOX> vtk_box2;
		for (size_t p = 0 ; p < nn_processors.size() ; p++)
		{
			size_t prc = nn_processors.get(p);
			auto it = nn_processor_subdomains.find(prc);
			if (it != nn_processor_subdomains.end())
				vtk_box2.add(nn_processor_subdomains.at(prc).bx);
		}
		vtk_box2.write(output + std::string("subdomains_adjacent_") + std::to_string(v_cl.getProcessUnitID()) + std::string(".vtk"));

		return true;
	}

609 610 611 612 613 614 615 616 617 618 619
	/*! \brief Apply boundary conditions
	 *
	 * \param domain The simulation domain
	 * \param ghost ghost part
	 * \param bc Boundary conditions
	 *
	 */
	void applyBC(const Box<dim,T> & domain, const Ghost<dim,T> & ghost, const size_t (&bc)[dim])
	{
		if (aBC == true)
		{
620
			std::cerr << "Warning " << __FILE__ << ":" << __LINE__ << " apply BC is suppose to be called only one time\n";
621 622 623 624 625
			return;
		}

		aBC=true;

incardon's avatar
incardon committed
626
		add_box_periodic(domain,ghost,bc);
627 628
	}

incardon's avatar
incardon committed
629 630 631 632 633 634 635 636 637 638 639 640
	/*! \brief Check if the nn_prcs contain the same information
	 *
	 * \param ele Element to check
	 *
	 */
	bool is_equal(nn_prcs<dim,T> & np)
	{
		if (np.getNNProcessors() != getNNProcessors())
			return false;

		for (size_t p = 0 ; p < getNNProcessors() ; p++)
		{
641
			if (getNearSubdomains(IDtoProc(p)) != np.getNearSubdomains(IDtoProc(p)))
incardon's avatar
incardon committed
642
				return false;
643
			if (getNearProcessor(IDtoProc(p)) != np.getNearProcessor(IDtoProc(p)))
incardon's avatar
incardon committed
644
				return false;
645
			if (getSentSubdomains(p) != np.getSentSubdomains(p))
incardon's avatar
incardon committed
646 647 648 649 650
				return false;
		}

		return true;
	}
651

652 653 654 655 656 657 658 659 660 661 662 663 664 665
	/*! \brief Reset the nn_prcs structure
	 *
	 */
	void reset()
	{
		nn_processors.clear();
		nn_processor_subdomains.clear();
		nn_processor_subdomains_tmp.clear();
		proc_adj_box.clear();
		boxes.clear();
		recv_cnt = 0;
		aBC = false;
	}

666 667 668 669 670 671 672 673 674 675 676
	//! Used for testing porpose do not use
	std::unordered_map<size_t, N_box<dim,T>> & get_nn_processor_subdomains()
	{
		return nn_processor_subdomains;
	}

	//! Used for testing porpose do not use
	openfpm::vector<size_t> & get_nn_processors()
	{
		return nn_processors;
	}
incardon's avatar
incardon committed
677 678 679 680
};


#endif /* SRC_DECOMPOSITION_NN_PROCESSOR_HPP_ */