void prepare_recv_buffer(GhostCommunication *gc, int data_parts) { GHOST_TRACE(fprintf(stderr, "%d: prepare receiving from %d\n", this_node, gc->node)); /* reallocate recv buffer */ n_r_buffer = calc_transmit_size(gc, data_parts); if (n_r_buffer > max_r_buffer) { max_r_buffer = n_r_buffer; r_buffer = (char*)realloc(r_buffer, max_r_buffer); } GHOST_TRACE(fprintf(stderr, "%d: will get %d\n", this_node, n_r_buffer)); }
void free_comm(GhostCommunicator *comm) { int n; GHOST_TRACE(fprintf(stderr,"%d: free_comm: %p has %d ghost communications\n",this_node,comm,comm->num)); for (n = 0; n < comm->num; n++) free(comm->comm[n].part_lists); free(comm->comm); }
void cell_cell_transfer(GhostCommunication *gc, int data_parts) { int pl, p, offset; Particle *part1, *part2, *pt1, *pt2; GHOST_TRACE(fprintf(stderr, "%d: local_transfer: type %d data_parts %d\n", this_node,gc->type,data_parts)); /* transfer data */ offset = gc->n_part_lists/2; for (pl = 0; pl < offset; pl++) { Cell *src_list = gc->part_lists[pl]; Cell *dst_list = gc->part_lists[pl + offset]; if (data_parts == GHOSTTRANS_PARTNUM) { prepare_ghost_cell(dst_list, src_list->n); } else { int np = src_list->n; part1 = src_list->part; part2 = dst_list->part; for (p = 0; p < np; p++) { pt1 = &part1[p]; pt2 = &part2[p]; if (data_parts & GHOSTTRANS_PROPRTS) { memcpy(&pt2->p, &pt1->p, sizeof(ParticleProperties)); #ifdef GHOSTS_HAVE_BONDS realloc_intlist(&(pt2->bl), pt2->bl.n = pt1->bl.n); memcpy(&pt2->bl.e, &pt1->bl.e, pt1->bl.n*sizeof(int)); #ifdef EXCLUSIONS realloc_intlist(&(pt2->el), pt2->el.n = pt1->el.n); memcpy(&pt2->el.e, &pt1->el.e, pt1->el.n*sizeof(int)); #endif #endif } if (data_parts & GHOSTTRANS_POSSHFTD) { /* ok, this is not nice, but perhaps fast */ int i; memcpy(&pt2->r, &pt1->r, sizeof(ParticlePosition)); for (i = 0; i < 3; i++) pt2->r.p[i] += gc->shift[i]; } else if (data_parts & GHOSTTRANS_POSITION) memcpy(&pt2->r, &pt1->r, sizeof(ParticlePosition)); if (data_parts & GHOSTTRANS_MOMENTUM) memcpy(&pt2->m, &pt1->m, sizeof(ParticleMomentum)); if (data_parts & GHOSTTRANS_FORCE) add_force(&pt2->f, &pt1->f); #ifdef LB if (data_parts & GHOSTTRANS_COUPLING) memcpy(&pt2->lc, &pt1->lc, sizeof(ParticleLatticeCoupling)); #endif } } } }
void cell_cell_transfer(GhostCommunication *gc, int data_parts) { int pl, p, np, offset; Particle *part1, *part2, *pt1, *pt2; GHOST_TRACE(fprintf(stderr, "%d: local_transfer: type %d data_parts %d\n", this_node,gc->type,data_parts)); /* transfer data */ offset = gc->n_part_lists/2; for (pl = 0; pl < offset; pl++) { np = gc->part_lists[pl]->n; if (data_parts == GHOSTTRANS_PARTNUM) { realloc_particlelist(gc->part_lists[pl + offset], gc->part_lists[pl + offset]->n = gc->part_lists[pl]->n); #ifdef GHOST_FLAG { //init ghost variable int i; for (i=0; i<gc->part_lists[pl + offset]->n; i++) { gc->part_lists[pl + offset]->part[i].l.ghost=1; } } #endif } else { part1 = gc->part_lists[pl]->part; part2 = gc->part_lists[pl + offset]->part; for (p = 0; p < np; p++) { pt1 = &part1[p]; pt2 = &part2[p]; if (data_parts & GHOSTTRANS_PROPRTS) memcpy(&pt2->p, &pt1->p, sizeof(ParticleProperties)); if (data_parts & GHOSTTRANS_POSSHFTD) { /* ok, this is not nice, but perhaps fast */ int i; memcpy(&pt2->r, &pt1->r, sizeof(ParticlePosition)); for (i = 0; i < 3; i++) pt2->r.p[i] += gc->shift[i]; } else if (data_parts & GHOSTTRANS_POSITION) memcpy(&pt2->r, &pt1->r, sizeof(ParticlePosition)); if (data_parts & GHOSTTRANS_MOMENTUM) memcpy(&pt2->m, &pt1->m, sizeof(ParticleMomentum)); if (data_parts & GHOSTTRANS_FORCE) add_force(&pt2->f, &pt1->f); #ifdef LB if (data_parts & GHOSTTRANS_COUPLING) memcpy(&pt2->lc, &pt1->lc, sizeof(ParticleLatticeCoupling)); #endif } } } }
void prepare_comm(GhostCommunicator *comm, int data_parts, int num) { int i; comm->data_parts = data_parts; /* if ghosts should have uptodate velocities, they have to be updated like positions (except for shifting...) */ if (ghosts_have_v && (data_parts & GHOSTTRANS_POSITION)) comm->data_parts |= GHOSTTRANS_MOMENTUM; GHOST_TRACE(fprintf(stderr, "%d: prepare_comm, data_parts = %d\n", this_node, comm->data_parts)); comm->num = num; comm->comm = (GhostCommunication*)malloc(num*sizeof(GhostCommunication)); for(i=0; i<num; i++) { comm->comm[i].shift[0]=comm->comm[i].shift[1]=comm->comm[i].shift[2]=0.0; } }
void ghost_communicator(GhostCommunicator *gc) { MPI_Status status; int n, n2; int data_parts = gc->data_parts; GHOST_TRACE(fprintf(stderr, "%d: ghost_comm %p, data_parts %d\n", this_node, gc, data_parts)); for (n = 0; n < gc->num; n++) { GhostCommunication *gcn = &gc->comm[n]; int comm_type = gcn->type & GHOST_JOBMASK; int prefetch = gcn->type & GHOST_PREFETCH; int poststore = gcn->type & GHOST_PSTSTORE; int node = gcn->node; GHOST_TRACE(fprintf(stderr, "%d: ghost_comm round %d, job %x\n", this_node, n, gc->comm[n].type)); GHOST_TRACE(fprintf(stderr, "%d: ghost_comm shift %f %f %f\n",this_node, gc->comm[n].shift[0], gc->comm[n].shift[1], gc->comm[n].shift[2])); if (comm_type == GHOST_LOCL) cell_cell_transfer(gcn, data_parts); else { /* prepare send buffer if necessary */ if (is_send_op(comm_type, node)) { /* ok, we send this step, prepare send buffer if not yet done */ if (!prefetch) prepare_send_buffer(gcn, data_parts); else { GHOST_TRACE(fprintf(stderr, "%d: ghost_comm using prefetched data for operation %d, sending to %d\n", this_node, n, node)); #ifdef ADDITIONAL_CHECKS if (n_s_buffer != calc_transmit_size(gcn, data_parts)) { fprintf(stderr, "%d: ghost_comm transmission size and current size of cells to transmit do not match\n", this_node); errexit(); } #endif } } else { /* we do not send this time, let's look for a prefetch */ if (prefetch) { /* find next action where we send and which has PREFETCH set */ for (n2 = n+1; n2 < gc->num; n2++) { GhostCommunication *gcn2 = &gc->comm[n2]; int comm_type2 = gcn2->type & GHOST_JOBMASK; int prefetch2 = gcn2->type & GHOST_PREFETCH; int node2 = gcn2->node; if (is_send_op(comm_type2, node2) && prefetch2) { GHOST_TRACE(fprintf(stderr, "%d: ghost_comm prefetch operation %d, is send/bcast to/from %d\n", this_node, n2, node2)); prepare_send_buffer(gcn2, data_parts); break; } } } } /* recv buffer for recv and multinode operations to this node */ if (is_recv_op(comm_type, node)) prepare_recv_buffer(gcn, data_parts); /* transfer data */ switch (comm_type) { case GHOST_RECV: { GHOST_TRACE(fprintf(stderr, "%d: ghost_comm receive from %d (%d bytes)\n", this_node, node, n_r_buffer)); MPI_Recv(r_buffer, n_r_buffer, MPI_BYTE, node, REQ_GHOST_SEND, comm_cart, &status); if (data_parts & GHOSTTRANS_PROPRTS) { int n_bonds = *(int *)(r_buffer + n_r_buffer - sizeof(int)); GHOST_TRACE(fprintf(stderr, "%d: ghost_comm receive from %d (%d bonds)\n", this_node, node, n_bonds)); if (n_bonds) { r_bondbuffer.resize(n_bonds); MPI_Recv(&r_bondbuffer[0], n_bonds, MPI_INT, node, REQ_GHOST_SEND, comm_cart, &status); } } break; } case GHOST_SEND: { GHOST_TRACE(fprintf(stderr, "%d: ghost_comm send to %d (%d bytes)\n", this_node, node, n_s_buffer)); MPI_Send(s_buffer, n_s_buffer, MPI_BYTE, node, REQ_GHOST_SEND, comm_cart); int n_bonds = s_bondbuffer.size(); if (!(data_parts & GHOSTTRANS_PROPRTS) && n_bonds > 0) { fprintf(stderr, "%d: INTERNAL ERROR: not sending properties, but bond buffer not empty\n", this_node); errexit(); } GHOST_TRACE(fprintf(stderr, "%d: ghost_comm send to %d (%d ints)\n", this_node, node, n_bonds)); if (n_bonds) { MPI_Send(&s_bondbuffer[0], n_bonds, MPI_INT, node, REQ_GHOST_SEND, comm_cart); } break; } case GHOST_BCST: GHOST_TRACE(fprintf(stderr, "%d: ghost_comm bcast from %d (%d bytes)\n", this_node, node, (node == this_node) ? n_s_buffer : n_r_buffer)); if (node == this_node) { MPI_Bcast(s_buffer, n_s_buffer, MPI_BYTE, node, comm_cart); int n_bonds = s_bondbuffer.size(); if (!(data_parts & GHOSTTRANS_PROPRTS) && n_bonds > 0) { fprintf(stderr, "%d: INTERNAL ERROR: not sending properties, but bond buffer not empty\n", this_node); errexit(); } if (n_bonds) { MPI_Bcast(&s_bondbuffer[0], n_bonds, MPI_INT, node, comm_cart); } } else { MPI_Bcast(r_buffer, n_r_buffer, MPI_BYTE, node, comm_cart); if (data_parts & GHOSTTRANS_PROPRTS) { int n_bonds = *(int *)(r_buffer + n_r_buffer - sizeof(int)); if (n_bonds) { r_bondbuffer.resize(n_bonds); MPI_Bcast(&r_bondbuffer[0], n_bonds, MPI_INT, node, comm_cart); } } } break; case GHOST_RDCE: GHOST_TRACE(fprintf(stderr, "%d: ghost_comm reduce to %d (%d bytes)\n", this_node, node, n_s_buffer)); if (node == this_node) MPI_Reduce(s_buffer, r_buffer, n_s_buffer, MPI_BYTE, MPI_FORCES_SUM, node, comm_cart); else MPI_Reduce(s_buffer, NULL, n_s_buffer, MPI_BYTE, MPI_FORCES_SUM, node, comm_cart); break; } GHOST_TRACE(MPI_Barrier(comm_cart)); GHOST_TRACE(fprintf(stderr, "%d: ghost_comm done\n", this_node)); /* recv op; write back data directly, if no PSTSTORE delay is requested. */ if (is_recv_op(comm_type, node)) { if (!poststore) { /* forces have to be added, the rest overwritten. Exception is RDCE, where the addition is integrated into the communication. */ if (data_parts == GHOSTTRANS_FORCE && comm_type != GHOST_RDCE) add_forces_from_recv_buffer(gcn); else put_recv_buffer(gcn, data_parts); } else { GHOST_TRACE(fprintf(stderr, "%d: ghost_comm delaying operation %d, recv from %d\n", this_node, n, node)); } } else { /* send op; write back delayed data from last recv, when this was a prefetch send. */ if (poststore) { /* find previous action where we recv and which has PSTSTORE set */ for (n2 = n-1; n2 >= 0; n2--) { GhostCommunication *gcn2 = &gc->comm[n2]; int comm_type2 = gcn2->type & GHOST_JOBMASK; int poststore2 = gcn2->type & GHOST_PSTSTORE; int node2 = gcn2->node; if (is_recv_op(comm_type2, node2) && poststore2) { GHOST_TRACE(fprintf(stderr, "%d: ghost_comm storing delayed recv, operation %d, from %d\n", this_node, n2, node2)); #ifdef ADDITIONAL_CHECKS if (n_r_buffer != calc_transmit_size(gcn2, data_parts)) { fprintf(stderr, "%d: ghost_comm transmission size and current size of cells to transmit do not match\n", this_node); errexit(); } #endif /* as above */ if (data_parts == GHOSTTRANS_FORCE && comm_type != GHOST_RDCE) add_forces_from_recv_buffer(gcn2); else put_recv_buffer(gcn2, data_parts); break; } } } } } } }
void put_recv_buffer(GhostCommunication *gc, int data_parts) { /* put back data */ char *retrieve = r_buffer; std::vector<int>::const_iterator bond_retrieve = r_bondbuffer.begin(); for (int pl = 0; pl < gc->n_part_lists; pl++) { ParticleList *cur_list = gc->part_lists[pl]; if (data_parts == GHOSTTRANS_PARTNUM) { GHOST_TRACE(fprintf(stderr, "%d: reallocating cell %p to size %d, assigned to node %d\n", this_node, cur_list, *(int *)retrieve, gc->node)); prepare_ghost_cell(cur_list, *(int *)retrieve); retrieve += sizeof(int); } else { int np = cur_list->n; Particle *part = cur_list->part; for (int p = 0; p < np; p++) { Particle *pt = &part[p]; if (data_parts & GHOSTTRANS_PROPRTS) { memcpy(&pt->p, retrieve, sizeof(ParticleProperties)); retrieve += sizeof(ParticleProperties); #ifdef GHOSTS_HAVE_BONDS int n_bonds; memcpy(&n_bonds, retrieve, sizeof(int)); retrieve += sizeof(int); if (n_bonds) { realloc_intlist(&pt->bl, pt->bl.n = n_bonds); std::copy(bond_retrieve, bond_retrieve + n_bonds, pt->bl.e); bond_retrieve += n_bonds; } #ifdef EXCLUSIONS memcpy(&n_bonds, retrieve, sizeof(int)); retrieve += sizeof(int); if (n_bonds) { realloc_intlist(&pt->el, pt->el.n = n_bonds); std::copy(bond_retrieve, bond_retrieve + n_bonds, pt->el.e); bond_retrieve += n_bonds; } #endif #endif if (local_particles[pt->p.identity] == NULL) { local_particles[pt->p.identity] = pt; } } if (data_parts & GHOSTTRANS_POSITION) { memcpy(&pt->r, retrieve, sizeof(ParticlePosition)); retrieve += sizeof(ParticlePosition); } if (data_parts & GHOSTTRANS_MOMENTUM) { memcpy(&pt->m, retrieve, sizeof(ParticleMomentum)); retrieve += sizeof(ParticleMomentum); } if (data_parts & GHOSTTRANS_FORCE) { memcpy(&pt->f, retrieve, sizeof(ParticleForce)); retrieve += sizeof(ParticleForce); } #ifdef LB if (data_parts & GHOSTTRANS_COUPLING) { memcpy(&pt->lc, retrieve, sizeof(ParticleLatticeCoupling)); retrieve += sizeof(ParticleLatticeCoupling); } #endif } } } if (data_parts & GHOSTTRANS_PROPRTS) { // skip the final information on bonds to be sent in a second round retrieve += sizeof(int); } if (retrieve - r_buffer != n_r_buffer) { fprintf(stderr, "%d: recv buffer size %d differs " "from what I read out (%ld)\n", this_node, n_r_buffer, retrieve - r_buffer); errexit(); } if (bond_retrieve != r_bondbuffer.end()) { fprintf(stderr, "%d: recv bond buffer was not used up, %ld elements remain\n", this_node, r_bondbuffer.end() - bond_retrieve ); errexit(); } r_bondbuffer.resize(0); }
void prepare_send_buffer(GhostCommunication *gc, int data_parts) { GHOST_TRACE(fprintf(stderr, "%d: prepare sending to/bcast from %d\n", this_node, gc->node)); /* reallocate send buffer */ n_s_buffer = calc_transmit_size(gc, data_parts); if (n_s_buffer > max_s_buffer) { max_s_buffer = n_s_buffer; s_buffer = (char*)realloc(s_buffer, max_s_buffer); } GHOST_TRACE(fprintf(stderr, "%d: will send %d\n", this_node, n_s_buffer)); s_bondbuffer.resize(0); /* put in data */ char *insert = s_buffer; for (int pl = 0; pl < gc->n_part_lists; pl++) { int np = gc->part_lists[pl]->n; if (data_parts == GHOSTTRANS_PARTNUM) { *(int *)insert = np; insert += sizeof(int); GHOST_TRACE(fprintf(stderr, "%d: %d particles assigned\n", this_node, np)); } else { Particle *part = gc->part_lists[pl]->part; for (int p = 0; p < np; p++) { Particle *pt = &part[p]; if (data_parts & GHOSTTRANS_PROPRTS) { memcpy(insert, &pt->p, sizeof(ParticleProperties)); insert += sizeof(ParticleProperties); #ifdef GHOSTS_HAVE_BONDS *(int *)insert = pt->bl.n; insert += sizeof(int); if (pt->bl.n) { s_bondbuffer.insert(s_bondbuffer.end(), pt->bl.e, pt->bl.e + pt->bl.n); } #ifdef EXCLUSIONS *(int *)insert = pt->el.n; insert += sizeof(int); if (pt->el.n) { s_bondbuffer.insert(s_bondbuffer.end(), pt->el.e, pt->el.e + pt->el.n); } #endif #endif } if (data_parts & GHOSTTRANS_POSSHFTD) { /* ok, this is not nice, but perhaps fast */ ParticlePosition *pp = (ParticlePosition *)insert; int i; memcpy(pp, &pt->r, sizeof(ParticlePosition)); //fprintf(stderr,"%d prep_send_buf: ghost %d shift %f,%f,%f\n",this_node,pt->p.identity,gc->shift[0],gc->shift[1],gc->shift[2]); for (i = 0; i < 3; i++) pp->p[i] += gc->shift[i]; insert += sizeof(ParticlePosition); } else if (data_parts & GHOSTTRANS_POSITION) { memcpy(insert, &pt->r, sizeof(ParticlePosition)); insert += sizeof(ParticlePosition); } if (data_parts & GHOSTTRANS_MOMENTUM) { memcpy(insert, &pt->m, sizeof(ParticleMomentum)); insert += sizeof(ParticleMomentum); } if (data_parts & GHOSTTRANS_FORCE) { memcpy(insert, &pt->f, sizeof(ParticleForce)); insert += sizeof(ParticleForce); } #ifdef LB if (data_parts & GHOSTTRANS_COUPLING) { memcpy(insert, &pt->lc, sizeof(ParticleLatticeCoupling)); insert += sizeof(ParticleLatticeCoupling); } #endif } } } if (data_parts & GHOSTTRANS_PROPRTS) { GHOST_TRACE(fprintf(stderr, "%d: bond buffer size is %ld\n", this_node, s_bondbuffer.size())); *(int *)insert = int(s_bondbuffer.size()); insert += sizeof(int); } if (insert - s_buffer != n_s_buffer) { fprintf(stderr, "%d: INTERNAL ERROR: send buffer size %d " "differs from what I put in (%ld)\n", this_node, n_s_buffer, insert - s_buffer); errexit(); } }
void put_recv_buffer(GhostCommunication *gc, int data_parts) { int pl, p, np; Particle *part, *pt; char *retrieve; /* put back data */ retrieve = r_buffer; for (pl = 0; pl < gc->n_part_lists; pl++) { if (data_parts == GHOSTTRANS_PARTNUM) { GHOST_TRACE(fprintf(stderr, "%d: reallocating cell %p to size %d, assigned to node %d\n", this_node, gc->part_lists[pl], *(int *)retrieve, gc->node)); realloc_particlelist(gc->part_lists[pl], gc->part_lists[pl]->n = *(int *)retrieve); #ifdef GHOST_FLAG //init ghost variable int i; for (i=0;i<gc->part_lists[pl]->n;i++){ gc->part_lists[pl]->part[i].l.ghost=1; } #endif retrieve += sizeof(int); } else { np = gc->part_lists[pl]->n; part = gc->part_lists[pl]->part; for (p = 0; p < np; p++) { pt = &part[p]; if (data_parts & GHOSTTRANS_PROPRTS) { memcpy(&pt->p, retrieve, sizeof(ParticleProperties)); retrieve += sizeof(ParticleProperties); /* GHOST_TRACE(fprintf(stderr, "%d: received ghost %d", this_node, pt->p.identity)); */ if (local_particles[pt->p.identity] == NULL) { /* GHOST_TRACE(fprintf(stderr, ", using.\n")); */ local_particles[pt->p.identity] = pt; } /* else { GHOST_TRACE(fprintf(stderr, ", already here.\n")); } */ } if (data_parts & GHOSTTRANS_POSITION) { memcpy(&pt->r, retrieve, sizeof(ParticlePosition)); retrieve += sizeof(ParticlePosition); } if (data_parts & GHOSTTRANS_MOMENTUM) { memcpy(&pt->m, retrieve, sizeof(ParticleMomentum)); retrieve += sizeof(ParticleMomentum); } if (data_parts & GHOSTTRANS_FORCE) { memcpy(&pt->f, retrieve, sizeof(ParticleForce)); retrieve += sizeof(ParticleForce); } #ifdef LB if (data_parts & GHOSTTRANS_COUPLING) { memcpy(&pt->lc, retrieve, sizeof(ParticleLatticeCoupling)); retrieve += sizeof(ParticleLatticeCoupling); } #endif } } } #ifdef ADDITIONAL_CHECKS if (retrieve - r_buffer != n_r_buffer) { fprintf(stderr, "%d: recv buffer size %d differs from what I put in %d\n", this_node, n_r_buffer, retrieve - r_buffer); errexit(); } #endif }
void cell_cell_transfer(GhostCommunication *gc, int data_parts) { int pl, p, offset; Particle *part1, *part2, *pt1, *pt2; GHOST_TRACE(fprintf(stderr, "%d: local_transfer: type %d data_parts %d\n", this_node,gc->type,data_parts)); /* transfer data */ offset = gc->n_part_lists/2; for (pl = 0; pl < offset; pl++) { Cell *src_list = gc->part_lists[pl]; Cell *dst_list = gc->part_lists[pl + offset]; if (data_parts & GHOSTTRANS_PARTNUM) { prepare_ghost_cell(dst_list, src_list->n); } else { int np = src_list->n; part1 = src_list->part; part2 = dst_list->part; for (p = 0; p < np; p++) { pt1 = &part1[p]; pt2 = &part2[p]; if (data_parts & GHOSTTRANS_PROPRTS) { memcpy(&pt2->p, &pt1->p, sizeof(ParticleProperties)); #ifdef GHOSTS_HAVE_BONDS realloc_intlist(&(pt2->bl), pt2->bl.n = pt1->bl.n); memcpy(&pt2->bl.e, &pt1->bl.e, pt1->bl.n*sizeof(int)); #ifdef EXCLUSIONS realloc_intlist(&(pt2->el), pt2->el.n = pt1->el.n); memcpy(&pt2->el.e, &pt1->el.e, pt1->el.n*sizeof(int)); #endif #endif } if (data_parts & GHOSTTRANS_POSSHFTD) { /* ok, this is not nice, but perhaps fast */ int i; memcpy(&pt2->r, &pt1->r, sizeof(ParticlePosition)); for (i = 0; i < 3; i++) pt2->r.p[i] += gc->shift[i]; #ifdef LEES_EDWARDS /* special wrapping conditions for x component of y LE shift */ if( gc->shift[1] != 0.0 ){ /* LE transforms are wrapped */ if( pt2->r.p[0] - (my_left[0] + dst_list->myIndex[0]*dd.cell_size[0]) > 2*dd.cell_size[0] ) pt2->r.p[0]-=box_l[0]; if( pt2->r.p[0] - (my_left[0] + dst_list->myIndex[0]*dd.cell_size[0]) < -2*dd.cell_size[0] ) pt2->r.p[0]+=box_l[0]; } #endif } else if (data_parts & GHOSTTRANS_POSITION) memcpy(&pt2->r, &pt1->r, sizeof(ParticlePosition)); if (data_parts & GHOSTTRANS_MOMENTUM) { memcpy(&pt2->m, &pt1->m, sizeof(ParticleMomentum)); #ifdef LEES_EDWARDS /* special wrapping conditions for x component of y LE shift */ if( gc->shift[1] > 0.0 ) pt2->m.v[0] += lees_edwards_rate; else if( gc->shift[1] < 0.0 ) pt2->m.v[0] -= lees_edwards_rate; #endif } if (data_parts & GHOSTTRANS_FORCE) add_force(&pt2->f, &pt1->f); #ifdef LB if (data_parts & GHOSTTRANS_COUPLING) memcpy(&pt2->lc, &pt1->lc, sizeof(ParticleLatticeCoupling)); #endif #ifdef ENGINE if (data_parts & GHOSTTRANS_SWIMMING) memcpy(&pt2->swim, &pt1->swim, sizeof(ParticleParametersSwimming)); #endif } } } }
void put_recv_buffer(GhostCommunication *gc, int data_parts) { /* put back data */ char *retrieve = r_buffer; std::vector<int>::const_iterator bond_retrieve = r_bondbuffer.begin(); for (int pl = 0; pl < gc->n_part_lists; pl++) { ParticleList *cur_list = gc->part_lists[pl]; if (data_parts & GHOSTTRANS_PARTNUM) { GHOST_TRACE(fprintf(stderr, "%d: reallocating cell %p to size %d, assigned to node %d\n", this_node, cur_list, *(int *)retrieve, gc->node)); prepare_ghost_cell(cur_list, *(int *)retrieve); retrieve += sizeof(int); } else { int np = cur_list->n; Particle *part = cur_list->part; for (int p = 0; p < np; p++) { Particle *pt = &part[p]; if (data_parts & GHOSTTRANS_PROPRTS) { memcpy(&pt->p, retrieve, sizeof(ParticleProperties)); retrieve += sizeof(ParticleProperties); #ifdef GHOSTS_HAVE_BONDS int n_bonds; memcpy(&n_bonds, retrieve, sizeof(int)); retrieve += sizeof(int); if (n_bonds) { realloc_intlist(&pt->bl, pt->bl.n = n_bonds); std::copy(bond_retrieve, bond_retrieve + n_bonds, pt->bl.e); bond_retrieve += n_bonds; } #ifdef EXCLUSIONS memcpy(&n_bonds, retrieve, sizeof(int)); retrieve += sizeof(int); if (n_bonds) { realloc_intlist(&pt->el, pt->el.n = n_bonds); std::copy(bond_retrieve, bond_retrieve + n_bonds, pt->el.e); bond_retrieve += n_bonds; } #endif #endif if (local_particles[pt->p.identity] == NULL) { local_particles[pt->p.identity] = pt; } } if (data_parts & GHOSTTRANS_POSITION) { memcpy(&pt->r, retrieve, sizeof(ParticlePosition)); retrieve += sizeof(ParticlePosition); #ifdef LEES_EDWARDS /* special wrapping conditions for x component of y LE shift */ if( gc->shift[1] != 0.0 ){ /* LE transforms are wrapped ---Using this method because its a shortcut to getting a neat-looking verlet list. */ if( pt->r.p[0] - (my_left[0] + cur_list->myIndex[0]*dd.cell_size[0]) > 2*dd.cell_size[0] ) pt->r.p[0]-=box_l[0]; if( pt->r.p[0] - (my_left[0] + cur_list->myIndex[0]*dd.cell_size[0]) < -2*dd.cell_size[0] ) pt->r.p[0]+=box_l[0]; } #endif } if (data_parts & GHOSTTRANS_MOMENTUM) { memcpy(&pt->m, retrieve, sizeof(ParticleMomentum)); retrieve += sizeof(ParticleMomentum); #ifdef LEES_EDWARDS /* give ghost particles correct velocity for the main * non-ghost LE reference frame */ if( gc->shift[1] > 0.0 ) pt->m.v[0] += lees_edwards_rate; else if( gc->shift[1] < 0.0 ) pt->m.v[0] -= lees_edwards_rate; #endif } if (data_parts & GHOSTTRANS_FORCE) { memcpy(&pt->f, retrieve, sizeof(ParticleForce)); retrieve += sizeof(ParticleForce); } #ifdef LB if (data_parts & GHOSTTRANS_COUPLING) { memcpy(&pt->lc, retrieve, sizeof(ParticleLatticeCoupling)); retrieve += sizeof(ParticleLatticeCoupling); } #endif #ifdef ENGINE if (data_parts & GHOSTTRANS_SWIMMING) { memcpy(&pt->swim, retrieve, sizeof(ParticleParametersSwimming)); retrieve += sizeof(ParticleParametersSwimming); } #endif } } } if (data_parts & GHOSTTRANS_PROPRTS) { // skip the final information on bonds to be sent in a second round retrieve += sizeof(int); } if (retrieve - r_buffer != n_r_buffer) { fprintf(stderr, "%d: recv buffer size %d differs " "from what I read out (%ld)\n", this_node, n_r_buffer, retrieve - r_buffer); errexit(); } if (bond_retrieve != r_bondbuffer.end()) { fprintf(stderr, "%d: recv bond buffer was not used up, %ld elements remain\n", this_node, r_bondbuffer.end() - bond_retrieve ); errexit(); } r_bondbuffer.resize(0); }