se_class3_vector.hpp 17 KB
Newer Older
incardon's avatar
incardon committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
/*
 * se_class3_vector.hpp
 *
 *  Created on: Feb 11, 2017
 *      Author: i-bird
 */

#ifndef SRC_VECTOR_SE_CLASS3_VECTOR_HPP_
#define SRC_VECTOR_SE_CLASS3_VECTOR_HPP_

#include <iostream>
#include <Space/Shape/Point.hpp>
#include <Vector/map_vector.hpp>
#include <Vector/vector_dist_comm.hpp>
#include <list>

#define SE3_STATUS -2
#define SE3_TYPE -1
incardon's avatar
incardon committed
19
#define SE3_SIZE 2
incardon's avatar
incardon committed
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40

enum statuses
{
	CLEAN,
	DIRTY,
	UNINITIALIZED
};

enum sync
{
	SYNC,
	NOTSYNC
};

enum ptype
{
	HALO,
	GHOST,
	INSIDE
};

incardon's avatar
incardon committed
41 42 43 44 45 46 47 48 49 50 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
// is initialized
template<typename T>
struct is_initialized
{
	static const int init = UNINITIALIZED;
};

// is initialized
template<typename T>
struct is_initialized<openfpm::vector<T>>
{
	static const int init = CLEAN;
};


///////////////////////////////

/*! \brief this class is a functor for "for_each" algorithm
 *
 * This class is a functor for "for_each" algorithm. For each
 * element of the boost::vector the operator() is called.
 * Is mainly used to initialize the properties
 *
 * \tparam encap source
 * \tparam encap dst
 *
 */

template<unsigned int Np, typename vector>
struct init_prop
{
	//! vector for prop initializetion
	size_t (& prp_init)[Np];

	/*! \brief constructor
	 *
	 *
	 * \param src encapsulated object1
	 * \param dst encapsulated object2
	 *
	 */
	inline init_prop(size_t ( & prp_init)[Np])
	:prp_init(prp_init)
	{
	};


	/*!  \brief It call the copy function for each property
	 *
	 * \param t each member
	 *
	 */
	template<typename T>
	inline void operator()(T& t) const
	{
		typedef typename boost::mpl::at<vector,boost::mpl::int_<T::value>>::type tc;

		prp_init[T::value] = is_initialized<tc>::init;
	}
};

incardon's avatar
incardon committed
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211
// Unknown type
template<typename tcheck, bool foundamental>
struct typeCheck
{
	static bool isNan(const tcheck & data)
	{
		return false;
	}

	static bool isInf(const tcheck & data)
	{
		return false;
	}
};

// Unknown type
template<typename tcheck>
struct typeCheck<tcheck,true>
{
	static bool isNan(const tcheck & data)
	{
		return std::isnan(data);
	}

	static bool isInf(const tcheck & data)
	{
		return std::isinf(data);
	}
};

// Array
template<typename tcheck, bool foundamental, unsigned int N1>
struct typeCheck<tcheck[N1], foundamental>
{
	static bool isNan(tcheck (& data)[N1])
	{
		bool nn = false;

		for (size_t i = 0 ; i < N1; i++)
		{
			if (std::isnan(data[i]))
				nn = true;
		}

		return nn;
	}

	static bool isInf(tcheck (& data)[N1])
	{
		bool nn = false;

		for (size_t i = 0 ; i < N1; i++)
		{
			if (std::isinf(data[i]))
				nn = true;
		}

		return nn;
	}
};

// Array2d
template<typename tcheck, bool foundamental, unsigned int N1, unsigned int N2>
struct typeCheck<tcheck[N1][N2], foundamental>
{
	static bool isNan(tcheck (& data)[N1][N2])
	{
		bool nn = false;

		for (size_t i = 0 ; i < N1; i++)
		{
			for (size_t j = 0 ; j < N2; j++)
			{
				if (std::isnan(data[i][j]))
					nn = true;
			}
		}

		return nn;
	}

	static bool isInf(tcheck (& data)[N1][N2])
	{
		bool nn = false;

		for (size_t i = 0 ; i < N1; i++)
		{
			for (size_t j = 0 ; j < N2; j++)
			{
				if (std::isinf(data[i][j]))
					nn = true;
			}
		}

		return nn;
	}
};

/*! \brief this class is a functor for "for_each" algorithm
 *
 * This class is a functor for "for_each" algorithm. For each
 * property it check that there are not NAN properties
 *
 * \param T boost::fusion::vector
 *
 */
template<typename vector>
struct propCheckNAN
{
	//! Data to check
incardon's avatar
incardon committed
212
	const vector & data;
incardon's avatar
incardon committed
213 214 215 216 217 218 219 220 221

	//! Element to check
	size_t id;

	/*! \brief constructor
	 *
	 * \param
	 *
	 */
incardon's avatar
incardon committed
222
	inline propCheckNAN(const vector & data, size_t id)
incardon's avatar
incardon committed
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260
	:data(data),id(id)
	{};


	/*!  \brief It call the copy function for each property
	 *
	 * \param t each member
	 *
	 */
	template<typename T>
	inline void operator()(T& t) const
	{
		typedef typename boost::mpl::at<typename vector::value_type::type,typename boost::mpl::int_<T::value> >::type type_to_check;

		bool snn = typeCheck<type_to_check,std::is_fundamental<type_to_check>::value>::isNan(data.template getProp<T::value>(id));

		if (snn == true)
		{
			std::cerr << __FILE__ << ":" << __LINE__ << " error detected NAN in property " << T::value  << std::endl;

			ACTION_ON_ERROR(VECTOR_DIST_ERROR_OBJECT);
		}
	}
};


/*! \brief this class is a functor for "for_each" algorithm
 *
 * This class is a functor for "for_each" algorithm. For each
 * property it check that there are not NAN properties
 *
 * \param T boost::fusion::vector
 *
 */
template<typename vector>
struct propCheckINF
{
	//! Data to check
incardon's avatar
incardon committed
261
	const vector & data;
incardon's avatar
incardon committed
262 263 264 265 266 267 268 269 270 271

	//! id
	size_t id;


	/*! \brief constructor
	 *
	 * \param
	 *
	 */
incardon's avatar
incardon committed
272
	inline propCheckINF(const vector & data, size_t id)
incardon's avatar
incardon committed
273 274 275 276 277 278 279 280 281 282 283 284 285 286
	:data(data),id(id)
	{};


	/*!  \brief It call the copy function for each property
	 *
	 * \param t each member
	 *
	 */
	template<typename T>
	inline void operator()(T& t) const
	{
		typedef typename boost::mpl::at<typename vector::value_type::type,boost::mpl::int_<T::value> >::type type_to_check;

incardon's avatar
incardon committed
287
		bool snn = typeCheck<type_to_check,std::is_fundamental<type_to_check>::value>::isInf(data.template getPropNC<T::value>(id));
incardon's avatar
incardon committed
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325

		if (snn == true)
		{
			std::cerr << __FILE__ << ":" << __LINE__ << " error detected INF in property " << T::value << std::endl;
			ACTION_ON_ERROR(VECTOR_DIST_ERROR_OBJECT);
		}
	}
};

/*! \brief Return the type of the particle at string level
 *
 * \param type type of the particle
 *
 */
static inline std::string getParticleTypeString(size_t type)
{
	if (type == INSIDE)
		return std::string("INSIDE");
	else if (type == HALO)
		return std::string("HALO");
	else if (type == GHOST)
		return std::string("GHOST");

	return std::string();
}

/*! \brief This class check for inconsistency access
 *
 * \tparam Np number of properties
 *
 */
template<unsigned int Np, unsigned int dim, typename T, typename Decomposition, typename vector>
class se_class3_vector
{
		//! status of the properties
		int sync[2][Np];

		//! number of real properties + POSITION
incardon's avatar
incardon committed
326
		static const size_t Np_real = Np+SE3_STATUS;
incardon's avatar
incardon committed
327 328 329 330 331 332 333 334 335 336

		//! Domain decomposition object
		Decomposition & dec;

		//! Reference to the distributed object
		vector & vd;

		//! temporal buffer
		openfpm::vector<size_t> non_NP;

incardon's avatar
incardon committed
337 338 339
		//! last write
		size_t l_wrt;

incardon's avatar
incardon committed
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402
		bool isLocalHalo(const Point<dim,T> & p)
		{
			for (size_t i = 0; i < dec.getNLocalSub(); i++)
			{
				size_t Nl = dec.getLocalNIGhost(i);

				for (size_t j = 0; j < Nl; j++)
				{
					Box<dim,T> box = dec.getLocalIGhostBox(i, j);

					if (box.isInside(p) == true)
					{
						return true;
					}
				}
			}

			return false;
		}

		/*! \brief Given the position it return the particle type
		 *
		 * \param p position of the particle
		 * \param id of the particle (element id in the vector position)
		 * \param vd reference to the vector
		 *
		 * \return the particle type
		 *
		 */
		size_t getParticleType(const Point<dim,T> & p, const size_t & id, vector & vd)
		{
			size_t type;

			// first we distinguish what is this particle

			if (id > vd.size_local())
				type = GHOST;
			else
			{
				// Use cart decomposition to understand if it is in the halo

				const openfpm::vector<size_t> & vp_id = dec.template ghost_processorID<typename Decomposition::lc_processor_id>(p);

				if (vp_id.size() != 0)
					type = HALO;
				else
				{
					// Check if it is in the HALO inner ghost

					if (isLocalHalo(p) == true)
						type = HALO;
					else
						type = INSIDE;
				}
			}

			return type;
		}

		template<unsigned int ... prp> void create_NNP( const size_t (& gg)[sizeof...(prp)+1] )
		{
			non_NP.clear();

incardon's avatar
incardon committed
403
			for (size_t i = 0 ; i < Np_real ; i++)
incardon's avatar
incardon committed
404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422
			{
				bool found = false;
				for (size_t j = 0 ; j < sizeof...(prp) ; j++)
				{
					if (i == gg[j])
					{
						found = true;
						break;
					}
				}

				if (found == false)
					non_NP.add(i);
			}
		}


		std::string getPrpName(size_t i) const
		{
incardon's avatar
incardon committed
423
			if (i == Np_real)
incardon's avatar
incardon committed
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449
				return std::string("POSITION");

			return std::to_string(i);
		}

	public:

		//! Constructor all properties are uninitialized
		se_class3_vector(Decomposition & dec, vector & vd)
		:dec(dec),vd(vd)
		{
		}

		template<unsigned int prp> size_t isGhostSync()
		{
			return sync[GHOST][prp];
		}

		void Initialize()
		{
			auto it = vd.getDomainIterator_no_se3();

			while (it.isNext())
			{
				auto p = it.get();

incardon's avatar
incardon committed
450 451 452
				init_prop<Np_real+1,typename vector::value_type::type> np_r(vd.template getPropNC<Np+SE3_STATUS>(p));

				boost::mpl::for_each_ref< boost::mpl::range_c<int,0,Np_real+1> >(np_r);
incardon's avatar
incardon committed
453

incardon's avatar
incardon committed
454
				vd.template getPropNC<Np+SE3_TYPE>(p) = INSIDE;
incardon's avatar
incardon committed
455 456 457 458 459

				++it;
			}

			for (size_t i = 0 ; i < Np_real ; i++)
incardon's avatar
incardon committed
460
			{
incardon's avatar
incardon committed
461
				sync[GHOST][i] = NOTSYNC;
incardon's avatar
incardon committed
462 463
				sync[HALO][i] = SYNC;
			}
incardon's avatar
incardon committed
464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482
		}

		template <unsigned int ... prp> void ghost_get_pre(size_t opt)
		{
			const size_t gg[sizeof...(prp)+1]  = {prp...};

			create_NNP<prp...>(gg);

			// First check that the ghost are not dirty
			// if they are dirty we are dostroyign information

			auto it = vd.getGhostIterator_no_se3();

			while(it.isNext())
			{
				auto p = it.get();

				for (size_t i = 0 ; i < sizeof...(prp) ; i++)
				{
incardon's avatar
incardon committed
483
					if (vd.template getPropNC<Np+SE3_STATUS>(p)[gg[i]] == DIRTY)
incardon's avatar
incardon committed
484 485 486 487 488 489 490 491 492 493
					{
						std::cerr << __FILE__ << ":" << __LINE__ << " Error the ghost has been written and ghost_get will overwrite your changes" << std::endl;
						ACTION_ON_ERROR(VECTOR_DIST_ERROR_OBJECT);
					}
				}

				if (!(opt & KEEP_PROPERTIES))
				{
					for (size_t i = 0 ; i < non_NP.size() ; i++)
					{
incardon's avatar
incardon committed
494
						if (vd.template getPropNC<Np+SE3_STATUS>(p)[non_NP.get(i)] == DIRTY)
incardon's avatar
incardon committed
495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519
						{
							std::cerr << __FILE__ << ":" << __LINE__ << " Error the it seem that the property=" << getPrpName(non_NP.get(i)) << " has been written and ghost_get will destroy such changes" << std::endl;
							ACTION_ON_ERROR(VECTOR_DIST_ERROR_OBJECT);
						}
					}
				}

				++it;
			}
		}

		template <unsigned int ... prp> void ghost_get_post(size_t opt)
		{
			const size_t gg[sizeof...(prp)+1]  = {prp...};

			create_NNP<prp...>(gg);

			auto it2 = vd.getGhostIterator_no_se3();

			while(it2.isNext())
			{
				auto p = it2.get();

				for (size_t i = 0 ; i < sizeof...(prp) ; i++)
				{
incardon's avatar
incardon committed
520
					if (vd.template getPropNC<Np+SE3_STATUS>(p)[gg[i]] == DIRTY)
incardon's avatar
incardon committed
521
					{vd.template getPropNC<Np+SE3_STATUS>(p)[gg[i]] = CLEAN;}
incardon's avatar
incardon committed
522 523
				}

incardon's avatar
incardon committed
524 525 526
				if (vd.template getPropNC<Np+SE3_STATUS>(p)[Np_real] == DIRTY)
				{vd.template getPropNC<Np+SE3_STATUS>(p)[Np_real] = CLEAN;}

incardon's avatar
incardon committed
527
				vd.template getPropNC<Np+SE3_TYPE>(p) = GHOST;
incardon's avatar
incardon committed
528 529 530 531 532 533 534

				++it2;
			}

			if (!(opt & KEEP_PROPERTIES))
			{
				for (size_t i = 0 ; i < non_NP.size() ; i++)
incardon's avatar
incardon committed
535
					sync[GHOST][non_NP.get(i)] = NOTSYNC;
incardon's avatar
incardon committed
536 537 538 539 540 541 542 543

				auto it = vd.getGhostIterator_no_se3();

				while (it.isNext() == true)
				{
					auto p = it.get();

					for (size_t i = 0 ; i < non_NP.size() ; i++)
incardon's avatar
incardon committed
544
						vd.template getPropNC<Np+SE3_STATUS>(p)[non_NP.get(i)] = UNINITIALIZED;
incardon's avatar
incardon committed
545 546 547 548 549 550 551 552 553 554 555

					++it;
				}
			}

			// We notify that the ghost are in sync

			for (size_t i = 0 ; i < sizeof...(prp) ; i++)
				sync[GHOST][gg[i]] = SYNC;

			if (!(opt & NO_POSITION))
incardon's avatar
incardon committed
556
			{
incardon's avatar
incardon committed
557
				sync[GHOST][Np_real] = SYNC;
incardon's avatar
incardon committed
558
			}
incardon's avatar
incardon committed
559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 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 609 610 611 612 613 614 615 616 617 618 619 620 621 622

			if (!(opt & KEEP_PROPERTIES))
			{
				for (size_t i = 0 ; i < non_NP.size() ; i++)
					sync[GHOST][non_NP.get(i)] = NOTSYNC;
			}
		}

		template <unsigned int ... prp> void ghost_put()
		{
			const size_t gg[sizeof...(prp)]  = {prp...};

			auto it = vd.getDomainIterator_no_se3();

			while(it.isNext())
			{
				auto p = it.get();

				if (vd.template getProp<Np+SE3_TYPE>(p) == INSIDE)
				{
					++it;
					continue;
				}

				for (size_t i = 0 ; i < sizeof...(prp) ; i++)
				{
					if (vd.template getProp<Np+SE3_STATUS>(p)[gg[i]] == UNINITIALIZED)
					{
						std::cerr << __FILE__ << ":" << __LINE__ << " error it seem that you are sending at least in part uninitialized data with ghost put " << std::endl;
						ACTION_ON_ERROR(VECTOR_DIST_ERROR_OBJECT);
					}
				}

				++it;
			}

			for (size_t i = 0 ; i < sizeof...(prp) ; i++)
			{
				sync[HALO][gg[i]] = SYNC;
				sync[HALO][gg[i]] = CLEAN;
			}

			// Ghost has been merged make ghost clean
			auto it2 = vd.getGhostIterator_no_se3();

			while(it2.isNext())
			{
				auto p = it2.get();

				for (size_t i = 0 ; i < sizeof...(prp) ; i++)
					vd.template getProp<Np+SE3_STATUS>(p)[gg[i]] = CLEAN;

				++it2;
			}
		}

		void getIterator() const
		{
			auto it = vd.getDomainIterator_no_se3();

			while(it.isNext())
			{
				auto p = it.get();

incardon's avatar
incardon committed
623
				for (size_t j = 0 ; j < Np_real + 1 ; j++)
incardon's avatar
incardon committed
624
				{
incardon's avatar
incardon committed
625 626
					if (vd.template getPropNC<Np+SE3_STATUS>(p)[j] == DIRTY)
						vd.template getPropNC<Np+SE3_STATUS>(p)[j] = CLEAN;
incardon's avatar
incardon committed
627 628 629 630 631 632 633 634 635 636 637 638 639 640
				}

				++it;
			}
		}

		void map_pre()
		{
			auto it = vd.getGhostIterator_no_se3();

			while (it.isNext() == true)
			{
				auto p = it.get();

incardon's avatar
incardon committed
641
				for (size_t j = 0 ; j < Np_real + 1 ; j++)
incardon's avatar
incardon committed
642
				{
incardon's avatar
incardon committed
643
					if (vd.template getPropNC<Np+SE3_STATUS>(p)[j] == DIRTY)
incardon's avatar
incardon committed
644 645 646 647 648 649 650 651 652 653 654
					{
						std::cerr << __FILE__ << ":" << __LINE__ << " error it seem that ghost has been filled with information that we are going to destroy with the map call " << std::endl;
					}
				}

				++it;
			}
		}

		void map_post()
		{
incardon's avatar
incardon committed
655
			for (size_t j = 0 ; j < Np_real + 1 ; j++)
incardon's avatar
incardon committed
656 657 658 659 660 661 662 663 664 665 666
			{

				sync[GHOST][j] = NOTSYNC;
			}

			auto it = vd.getDomainIterator_no_se3();

			while (it.isNext() == true)
			{
				auto p = it.get();

incardon's avatar
incardon committed
667
				Point<vector::dims,typename vector::stype> xp = vd.getPosNC(p);
incardon's avatar
incardon committed
668

incardon's avatar
incardon committed
669
				vd.template getPropNC<Np+SE3_TYPE>(p) = getParticleType(xp,p.getKey(),vd);
incardon's avatar
incardon committed
670 671 672 673 674 675 676

				++it;
			}
		}

		template<unsigned int prp> void read(const vector & vd, size_t p) const
		{
incardon's avatar
incardon committed
677
			if (vd.template getPropNC<Np+SE3_STATUS>(p)[prp] == UNINITIALIZED)
incardon's avatar
incardon committed
678 679
			{
				std::stringstream str;
incardon's avatar
incardon committed
680
				std::string type_str = getParticleTypeString(vd.template getPropNC<Np+SE3_TYPE>(p));
incardon's avatar
incardon committed
681 682 683 684 685 686 687

				if (prp == Np_real)
					str << __FILE__ << ":" << __LINE__ << " Error you are reading the particle " << p << " of type " << type_str << " the position. But it result to be uninitialized" << std::endl;
				else
					str << __FILE__ << ":" << __LINE__ << " Error you are reading from the particle " << p << " of type " << type_str << " the property=" << getPrpName(prp) << ". But it result to be uninitialized" << std::endl;

				// It is an error read from an uninitialized property
incardon's avatar
incardon committed
688
				std::cerr << str.str() << std::endl;
incardon's avatar
incardon committed
689 690 691
				ACTION_ON_ERROR(VECTOR_DIST_ERROR_OBJECT);
			}

incardon's avatar
incardon committed
692
			if (vd.template getPropNC<Np+SE3_STATUS>(p)[prp] == DIRTY && p != l_wrt)
incardon's avatar
incardon committed
693
			{
incardon's avatar
incardon committed
694
				std::cerr << __FILE__ << ":" << __LINE__ << " Warning you are reading from a particle that has been changed already in the same cycle" << std::endl;
incardon's avatar
incardon committed
695 696 697
				ACTION_ON_ERROR(VECTOR_DIST_ERROR_OBJECT);
			}

incardon's avatar
incardon committed
698
			if (vd.template getPropNC<Np+SE3_TYPE>(p) == GHOST)
incardon's avatar
incardon committed
699 700
			{
				// if we read from the ghost we have to ensure that the ghost is in
incardon's avatar
incardon committed
701
				// sync in particular that the state of the halo is CLEAN
incardon's avatar
incardon committed
702

incardon's avatar
incardon committed
703
				if (sync[vd.template getPropNC<Np+SE3_TYPE>(p)][prp] != SYNC)
incardon's avatar
incardon committed
704 705 706 707 708
				{
					std::cerr << __FILE__ << ":" << __LINE__ << " Error it seem that you are reading from a ghost the property=" << getPrpName(prp) << " but it seem it is changed from the last ghost_get. It seems that is missing a ghost_get" << std::endl;
					ACTION_ON_ERROR(VECTOR_DIST_ERROR_OBJECT);
				}
			}
incardon's avatar
incardon committed
709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749

#ifdef CHECK_FOR_POSINF

			if ( std::isinf(vd.getPosNC(p)[0]) || std::isinf(vd.getPosNC(p)[1]) || std::isinf(vd.getPosNC(p)[2]) )
			{
				std::cerr << __FILE__ << ":" << __LINE__ << " error detected INF in position for particle p=" << p << " of type=" << getParticleTypeString(vd.template getPropNC<Np+SE3_TYPE>(p)) << std::endl;
				ACTION_ON_ERROR(VECTOR_DIST_ERROR_OBJECT);
			}

#endif

#ifdef CHECKFOR_POSNAN

			if ( std::isnan(vd.getPosNC(p)[0]) || std::isnan(vd.getPosNC(p)[1]) || std::isnan(vd.getPosNC(p)[2]) )
			{
				std::cerr << __FILE__ << ":" << __LINE__ << " error detected NAN in position for particle p=" << p << " of type=" << getParticleTypeString(vd.template getPropNC<Np+SE3_TYPE>(p)) << std::endl;
				ACTION_ON_ERROR(VECTOR_DIST_ERROR_OBJECT);
			}

#endif

#ifdef CHECKFOR_PROPINF

			{
				propCheckINF<vector> checker(vd,p);

				boost::mpl::for_each_ref< boost::mpl::range_c<int,0, Np_real > > (checker);
			}

#endif

#ifdef CHECKFOR_PROPNAN

			{
				propCheckNAN<vector> checker(vd,p);

				boost::mpl::for_each_ref< boost::mpl::range_c<int,0, Np_real > >(checker);
			}

#endif

incardon's avatar
incardon committed
750 751 752 753
		}

		template<unsigned int prp> void write(vector & vd, size_t p)
		{
incardon's avatar
incardon committed
754
			vd.template getPropNC<Np+SE3_STATUS>(p)[prp] = DIRTY;
incardon's avatar
incardon committed
755 756 757 758
			if (p >= vd.size_local())
				vd.get_se_class3().template setHaloOutSync<prp>();
			else
			{
incardon's avatar
incardon committed
759
				if (vd.template getPropNC<Np+SE3_TYPE>(p) == HALO)
incardon's avatar
incardon committed
760 761 762
					vd.get_se_class3().template setGhostOutSync<prp>();
			}

incardon's avatar
incardon committed
763
			l_wrt = p;
incardon's avatar
incardon committed
764 765 766 767 768
		}

		//! Copy operator
		se_class3_vector<Np,dim,T,Decomposition,vector> & operator=(const se_class3_vector<Np,dim,T,Decomposition,vector> & se3)
		{
incardon's avatar
incardon committed
769
			for (size_t i = 0 ; i < Np_real + 1 ; i++)
incardon's avatar
incardon committed
770 771 772 773 774 775 776 777 778 779
			{
				sync[0][i] = se3.sync[0][i];
				sync[1][i] = se3.sync[1][i];
			}

			return *this;
		}

		template<unsigned int prp> void setHaloOutSync()
		{
incardon's avatar
incardon committed
780
			sync[HALO][prp] = NOTSYNC;
incardon's avatar
incardon committed
781 782 783 784
		}

		template<unsigned int prp> void setGhostOutSync()
		{
incardon's avatar
incardon committed
785
			sync[GHOST][prp] = NOTSYNC;
incardon's avatar
incardon committed
786 787 788 789 790 791 792 793 794 795 796 797 798 799
		}

		void getNN()
		{
			if (sync[GHOST][Np_real] == NOTSYNC)
			{
				std::cerr << __FILE__ << ":" << __LINE__ << " Error you are trying to get a Cell-list or Verlet-list without having the ghost synchronized in position please use ghost_get before" << std::endl;
				ACTION_ON_ERROR(VECTOR_DIST_ERROR_OBJECT);
			}
		}
};


#endif /* SRC_VECTOR_SE_CLASS3_VECTOR_HPP_ */