Beispiel #1
0
bool moving_objects::fill_collisions			(moving_object *object, const Fvector &object_position, const float &time_to_check)
{
	possible_actions			action;
	int							i = 0;
	NEAREST_MOVING::const_iterator	I = m_nearest_moving.begin();
	NEAREST_MOVING::const_iterator	E = m_nearest_moving.end();
	for ( ; I != E; ++I) {
		++i;
		bool					break_cycle = false;

		bool					priority = ::priority::predicate(object,*I);
		if (priority) {
			if (!collided_dynamic(object, object_position, (*I), (*I)->predict_position(time_to_check), action))
				continue;

			if (action == possible_action_1_can_wait_2)
				break_cycle		= true;
			else
				VERIFY			(action == possible_action_2_can_wait_1);
		}
		else {
			if (!collided_dynamic((*I), (*I)->predict_position(time_to_check), object, object_position, action))
				continue;

			if (action == possible_action_2_can_wait_1)
				break_cycle		= true;
			else
				VERIFY			(action == possible_action_1_can_wait_2);
		}

		m_collisions.push_back	(
			std::make_pair(
				time_to_check,
				std::make_pair(
					action,
					std::make_pair(
						priority ? object : (*I),
						!priority ? object : (*I)
					)
				)
			)
		);

		if (break_cycle)
			return				(false);
	}

	{
		u32							collision_count = m_collisions.size();
		COLLISION_TIME				*collisions = (COLLISION_TIME*)_alloca(collision_count*sizeof(COLLISION_TIME));
		std::copy					(m_collisions.begin(), m_collisions.end(), collisions);
		COLLISION_TIME				*I = collisions;
		COLLISION_TIME				*E = collisions + collision_count;
		for ( ; I != E; ++I) {
			moving_object			*test;
			if ((*I).second.first == possible_action_1_can_wait_2)
				test				= (*I).second.second.first;
			else {
				VERIFY				((*I).second.first == possible_action_2_can_wait_1);
				test				= (*I).second.second.second;
			}

			bool					priority = ::priority::predicate(object,test);
			if (priority) {
				if (!collided_dynamic(object, object_position, test, test->position()))
					continue;
			}
			else {
				if (!collided_dynamic(test, test->position(), object, object_position))
					continue;
			}

			m_collisions.push_back	(
				std::make_pair(
					time_to_check,
					std::make_pair(
						priority ? possible_action_2_can_wait_1 : possible_action_1_can_wait_2,
						std::make_pair(
							priority ? object : test,
							!priority ? object : test
						)
					)
				)
			);
		}

		VERIFY					(m_collisions.size() >= collision_count);
		COLLISIONS::iterator	b = m_collisions.begin() + collision_count, i = b;
		COLLISIONS::iterator	e = m_collisions.end();
		for ( ; i != e; ++i) {
			if ((*i).second.second.first == object) {
				if (exchange_all((*i).second.second.second, object, collision_count))
					continue;

				(*i).second.second.first	= 0;
				continue;
			}

			VERIFY				((*i).second.second.second == object);
			if (!exchange_all((*i).second.second.first, object, collision_count))
				(*i).second.second.first	= 0;
		}

		struct remove {
			static	IC	bool	predicate	(const COLLISION_TIME &collision)
			{
				return			(!collision.second.second.first);
			}
		};

		m_collisions.erase		(
			std::remove_if(
				b,
				e,
				&remove::predicate
			),
			e
		);
	}

	return						(true);
}
Beispiel #2
0
void Comm::exchange(Atom &atom)
{
  if(do_safeexchange)
    return exchange_all(atom);

  int i, m, n, idim, nsend, nrecv, nrecv1, nrecv2, nlocal;
  MMD_float lo, hi, value;
  MMD_float** x;

  MPI_Request request;
  MPI_Status status;

  /* enforce PBC */

  atom.pbc();

  /* loop over dimensions */
  int tid = omp_get_thread_num();

  for(idim = 0; idim < 3; idim++) {

    /* only exchange if more than one proc in this dimension */

    if(procgrid[idim] == 1) continue;

    /* fill buffer with atoms leaving my box
       when atom is deleted, fill it in with last atom */

    i = nsend = 0;

    if(idim == 0) {
      lo = atom.box.xlo;
      hi = atom.box.xhi;
    } else if(idim == 1) {
      lo = atom.box.ylo;
      hi = atom.box.yhi;
    } else {
      lo = atom.box.zlo;
      hi = atom.box.zhi;
    }

    x = atom.x;

    nlocal = atom.nlocal;

    #pragma omp master
    {
      if(nlocal > maxnlocal) {
        send_flag = new int[nlocal];
        maxnlocal = nlocal;
      }

      if(maxthreads < threads->omp_num_threads) {
        maxthreads = threads->omp_num_threads;
        nsend_thread = new int [maxthreads];
        nrecv_thread = new int [maxthreads];
        nholes_thread = new int [maxthreads];
        maxsend_thread = new int [maxthreads];
        exc_sendlist_thread = new int*[maxthreads];

        for(int i = 0; i < maxthreads; i++) {
          maxsend_thread[i] = maxsend;
          exc_sendlist_thread[i] = (int*) malloc(maxsend * sizeof(int));
        }
      }
    }

    #pragma omp barrier

    nsend = 0;
    #pragma omp for

    for(int i = 0; i < threads->omp_num_threads; i++) {
      nsend_thread[i] = 0;
      nholes_thread[i] = 0;
    }

    #pragma omp for

    for(int i = 0; i < nlocal; i++) {
      if(x[i][idim] < lo || x[i][idim] >= hi) {
        if(nsend >= maxsend_thread[tid])  {
          maxsend_thread[tid] = nsend + 100;
          exc_sendlist_thread[tid] = (int*) realloc(exc_sendlist_thread[tid], (nsend + 100) * sizeof(int));
        }

        exc_sendlist_thread[tid][nsend++] = i;
        send_flag[i] = 0;
      } else
        send_flag[i] = 1;
    }

    nsend_thread[tid] = nsend;

    #pragma omp barrier

    #pragma omp master
    {
      int total_nsend = 0;

      for(int i = 0; i < threads->omp_num_threads; i++) {
        total_nsend += nsend_thread[i];
        nsend_thread[i] = total_nsend;
      }

      if(total_nsend * 6 > maxsend) growsend(total_nsend * 6);
    }
    #pragma omp barrier

    int total_nsend = nsend_thread[threads->omp_num_threads - 1];
    int nholes = 0;

    for(int i = 0; i < nsend; i++)
      if(exc_sendlist_thread[tid][i] < nlocal - total_nsend)
        nholes++;

    nholes_thread[tid] = nholes;
    #pragma omp barrier

    #pragma omp master
    {
      int total_nholes = 0;

      for(int i = 0; i < threads->omp_num_threads; i++) {
        total_nholes += nholes_thread[i];
        nholes_thread[i] = total_nholes;
      }
    }
    #pragma omp barrier

    int j = nlocal;
    int holes = 0;

    while(holes < nholes_thread[tid]) {
      j--;

      if(send_flag[j]) holes++;

    }


    for(int k = 0; k < nsend; k++) {
      atom.pack_exchange(exc_sendlist_thread[tid][k], &buf_send[(k + nsend_thread[tid] - nsend) * 6]);

      if(exc_sendlist_thread[tid][k] < nlocal - total_nsend) {
        while(!send_flag[j]) j++;

        atom.copy(j++, exc_sendlist_thread[tid][k]);
      }
    }

    nsend *= 6;
    #pragma omp barrier
    #pragma omp master
    {
      atom.nlocal = nlocal - total_nsend;
      nsend = total_nsend * 6;

      /* send/recv atoms in both directions
         only if neighboring procs are different */

      MPI_Send(&nsend, 1, MPI_INT, procneigh[idim][0], 0, MPI_COMM_WORLD);
      MPI_Recv(&nrecv1, 1, MPI_INT, procneigh[idim][1], 0, MPI_COMM_WORLD, &status);
      nrecv = nrecv1;

      if(procgrid[idim] > 2) {
        MPI_Send(&nsend, 1, MPI_INT, procneigh[idim][1], 0, MPI_COMM_WORLD);
        MPI_Recv(&nrecv2, 1, MPI_INT, procneigh[idim][0], 0, MPI_COMM_WORLD, &status);
        nrecv += nrecv2;
      }

      if(nrecv > maxrecv) growrecv(nrecv);

      if(sizeof(MMD_float) == 4) {
        MPI_Irecv(buf_recv, nrecv1, MPI_FLOAT, procneigh[idim][1], 0,
                  MPI_COMM_WORLD, &request);
        MPI_Send(buf_send, nsend, MPI_FLOAT, procneigh[idim][0], 0, MPI_COMM_WORLD);
      } else {
        MPI_Irecv(buf_recv, nrecv1, MPI_DOUBLE, procneigh[idim][1], 0,
                  MPI_COMM_WORLD, &request);
        MPI_Send(buf_send, nsend, MPI_DOUBLE, procneigh[idim][0], 0, MPI_COMM_WORLD);
      }

      MPI_Wait(&request, &status);

      if(procgrid[idim] > 2) {
        if(sizeof(MMD_float) == 4) {
          MPI_Irecv(&buf_recv[nrecv1], nrecv2, MPI_FLOAT, procneigh[idim][0], 0,
                    MPI_COMM_WORLD, &request);
          MPI_Send(buf_send, nsend, MPI_FLOAT, procneigh[idim][1], 0, MPI_COMM_WORLD);
        } else {
          MPI_Irecv(&buf_recv[nrecv1], nrecv2, MPI_DOUBLE, procneigh[idim][0], 0,
                    MPI_COMM_WORLD, &request);
          MPI_Send(buf_send, nsend, MPI_DOUBLE, procneigh[idim][1], 0, MPI_COMM_WORLD);
        }

        MPI_Wait(&request, &status);
      }

      nrecv_atoms = nrecv / 6;

      for(int i = 0; i < threads->omp_num_threads; i++)
        nrecv_thread[i] = 0;

    }
    /* check incoming atoms to see if they are in my box
       if they are, add to my list */

    #pragma omp barrier

    nrecv = 0;

    #pragma omp for

    for(int i = 0; i < nrecv_atoms; i++) {
      value = buf_recv[i * 6 + idim];

      if(value >= lo && value < hi)
        nrecv++;
    }

    nrecv_thread[tid] = nrecv;
    nlocal = atom.nlocal;
    #pragma omp barrier

    #pragma omp master
    {
      int total_nrecv = 0;

      for(int i = 0; i < threads->omp_num_threads; i++) {
        total_nrecv += nrecv_thread[i];
        nrecv_thread[i] = total_nrecv;
      }

      atom.nlocal += total_nrecv;
    }
    #pragma omp barrier

    int copyinpos = nlocal + nrecv_thread[tid] - nrecv;
    #pragma omp for

    for(int i = 0; i < nrecv_atoms; i++) {
      value = buf_recv[i * 6 + idim];

      if(value >= lo && value < hi)
        atom.unpack_exchange(copyinpos++, &buf_recv[i * 6]);
    }

    #pragma omp barrier

  }
}