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); }
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 } }