Ray_Trace_Adaptively(int my_node) { int i,outx,outy,yindex,xindex; int num_xqueue,num_yqueue,num_queue,lnum_xblocks,lnum_yblocks,lnum_blocks; int xstart,xstop,ystart,ystop,local_node,work; itest = 0; num_xqueue = ROUNDUP((float)image_len[X]/(float)image_section[X]); num_yqueue = ROUNDUP((float)image_len[Y]/(float)image_section[Y]); num_queue = num_xqueue * num_yqueue; lnum_xblocks = ROUNDUP((float)num_xqueue/(float)block_xlen); lnum_yblocks = ROUNDUP((float)num_yqueue/(float)block_ylen); lnum_blocks = lnum_xblocks * lnum_yblocks; local_node = my_node; Global->Queue[local_node][0] = 0; while (Global->Queue[num_nodes][0] > 0) { xstart = (local_node % image_section[X]) * num_xqueue; xstart = ROUNDUP((float)xstart/(float)highest_sampling_boxlen); xstart = xstart * highest_sampling_boxlen; xstop = MIN(xstart+num_xqueue,image_len[X]); ystart = (local_node / image_section[X]) * num_yqueue; ystart = ROUNDUP((float)ystart/(float)highest_sampling_boxlen); ystart = ystart * highest_sampling_boxlen; ystop = MIN(ystart+num_yqueue,image_len[Y]); ALOCK(Global->QLock,local_node); work = Global->Queue[local_node][0]; Global->Queue[local_node][0] += 1; AULOCK(Global->QLock,local_node); while (work < lnum_blocks) { xindex = xstart + (work%lnum_xblocks)*block_xlen; yindex = ystart + (work/lnum_xblocks)*block_ylen; for (outy=yindex; outy<yindex+block_ylen && outy<ystop; outy+=highest_sampling_boxlen) { for (outx=xindex; outx<xindex+block_xlen && outx<xstop; outx+=highest_sampling_boxlen) { /* Trace rays within square box of highest sampling size */ /* whose lower-left corner is current image space location. */ Ray_Trace_Adaptive_Box(outx,outy,highest_sampling_boxlen); } } ALOCK(Global->QLock,local_node); work = Global->Queue[local_node][0]; Global->Queue[local_node][0] += 1; AULOCK(Global->QLock,local_node); } if (my_node == local_node) { ALOCK(Global->QLock,num_nodes); Global->Queue[num_nodes][0]--; AULOCK(Global->QLock,num_nodes); } local_node = (local_node+1)%num_nodes; while (Global->Queue[local_node][0] >= lnum_blocks && Global->Queue[num_nodes][0] > 0) local_node = (local_node+1)%num_nodes; } }
long RemoveBoxFromGrid (box *b, box *pb) { long success; if (pb == NULL) { LOCK(G_Memory->single_lock); if (Grid == b) { Grid = NULL; success = TRUE; } else success = FALSE; UNLOCK(G_Memory->single_lock); } else { ALOCK(G_Memory->lock_array, pb->particle_lock_index); if (pb->children[b->child_num] == b) { pb->children[b->child_num] = NULL; b->parent = NULL; pb->num_children -= 1; success = TRUE; } else success = FALSE; AULOCK(G_Memory->lock_array, pb->particle_lock_index); } return success; }
long InsertBoxInGrid (long my_id, box *b, box *pb) { long success; if (pb == NULL) { LOCK(G_Memory->single_lock); if (Grid == NULL) { Grid = b; success = TRUE; } else success = FALSE; UNLOCK(G_Memory->single_lock); } else { ALOCK(G_Memory->lock_array, pb->particle_lock_index); if (pb->children[b->child_num] == NULL) { pb->children[b->child_num] = b; pb->num_children += 1; b->parent = pb; success = TRUE; } else success = FALSE; AULOCK(G_Memory->lock_array, pb->particle_lock_index); } if (success == TRUE) InsertSubtreeInPartition(my_id, b); return success; }
void INTERF(long DEST, double *VIR, long ProcID) { /* This routine gets called both from main() and from mdmain(). When called from main(), it is used to estimate the initial accelerations by computing intermolecular forces. When called from mdmain(), it is used to compute intermolecular forces. The parameter DEST specifies whether results go into the accelerations or the forces. Uses routine UPDATE_FORCES in this file, and routine CSHIFT in file cshift.U */ /* .....this routine calculates inter-molecular interaction forces the distances are arranged in the order M-M, M-H1, M-H3, H1-M, H3-M, H1-H3, H1-H1, H3-H1, H3-H3, O-O, O-H1, O-H3, H1-O, H3-O, where the M are "centers" of the molecules. */ long mol, comp, dir, icomp; long comp_last, half_mol; long KC, K; double YL[15], XL[15], ZL[15], RS[15], FF[15], RL[15]; /* per- interaction arrays that hold some computed distances */ double FTEMP; double LVIR = 0.0; double *temp_p; { /* initialize PFORCES array */ long ct1,ct2,ct3; for (ct1 = 0; ct1<NMOL; ct1++) for (ct2 = 0; ct2<NDIR; ct2++) for (ct3 = 0; ct3<NATOM; ct3++) PFORCES[ProcID][ct1][ct2][ct3] = 0; } half_mol = NMOL/2; for (mol = StartMol[ProcID]; mol < StartMol[ProcID+1]; mol++) { comp_last = mol + half_mol; if (NMOL%2 == 0) { if ((half_mol <= mol) && (mol%2 == 0)) { comp_last--; } if ((mol < half_mol) && (comp_last%2 == 1)) { comp_last--; } } for (icomp = mol+1; icomp <= comp_last; icomp++) { comp = icomp; if (comp > NMOL1) comp = comp%NMOL; /* compute some intermolecular distances */ CSHIFT(VAR[mol].F[DISP][XDIR],VAR[comp].F[DISP][XDIR], VAR[mol].VM[XDIR],VAR[comp].VM[XDIR],XL,BOXH,BOXL); CSHIFT(VAR[mol].F[DISP][YDIR],VAR[comp].F[DISP][YDIR], VAR[mol].VM[YDIR],VAR[comp].VM[YDIR],YL,BOXH,BOXL); CSHIFT(VAR[mol].F[DISP][ZDIR],VAR[comp].F[DISP][ZDIR], VAR[mol].VM[ZDIR],VAR[comp].VM[ZDIR],ZL,BOXH,BOXL); KC=0; for (K = 0; K < 9; K++) { RS[K]=XL[K]*XL[K]+YL[K]*YL[K]+ZL[K]*ZL[K]; if (RS[K] > CUT2) KC++; } /* for K */ if (KC != 9) { for (K = 0; K < 14; K++) FF[K]=0.0; if (RS[0] < CUT2) { FF[0]=QQ4/(RS[0]*sqrt(RS[0]))+REF4; LVIR = LVIR + FF[0]*RS[0]; } /* if */ for (K = 1; K < 5; K++) { if (RS[K] < CUT2) { FF[K]= -QQ2/(RS[K]*sqrt(RS[K]))-REF2; LVIR = LVIR + FF[K]*RS[K]; } /* if */ if (RS[K+4] <= CUT2) { RL[K+4]=sqrt(RS[K+4]); FF[K+4]=QQ/(RS[K+4]*RL[K+4])+REF1; LVIR = LVIR + FF[K+4]*RS[K+4]; } /* if */ } /* for K */ if (KC == 0) { RS[9]=XL[9]*XL[9]+YL[9]*YL[9]+ZL[9]*ZL[9]; RL[9]=sqrt(RS[9]); FF[9]=AB1*exp(-B1*RL[9])/RL[9]; LVIR = LVIR + FF[9]*RS[9]; for (K = 10; K < 14; K++) { FTEMP=AB2*exp(-B2*RL[K-5])/RL[K-5]; FF[K-5]=FF[K-5]+FTEMP; LVIR= LVIR+FTEMP*RS[K-5]; RS[K]=XL[K]*XL[K]+YL[K]*YL[K]+ZL[K]*ZL[K]; RL[K]=sqrt(RS[K]); FF[K]=(AB3*exp(-B3*RL[K])-AB4*exp(-B4*RL[K]))/RL[K]; LVIR = LVIR + FF[K]*RS[K]; } /* for K */ } /* if KC == 0 */ UPDATE_FORCES(mol, comp, XL, YL, ZL, FF, ProcID); } /* if KC != 9 */ } /* for comp */ } /* for mol */ /* accumulate the running sum from private per-interaction partial sums */ LOCK(gl->InterfVirLock); *VIR = *VIR + LVIR; UNLOCK(gl->InterfVirLock); /* at the end of the above force-computation, comp_last */ /* contains the number of the last molecule (no modulo) */ /* that this process touched */ if (comp_last > NMOL1) { for (mol = StartMol[ProcID]; mol < NMOL; mol++) { ALOCK(gl->MolLock, mol % MAXLCKS); for ( dir = XDIR; dir <= ZDIR; dir++) { temp_p = VAR[mol].F[DEST][dir]; temp_p[H1] += PFORCES[ProcID][mol][dir][H1]; temp_p[O] += PFORCES[ProcID][mol][dir][O]; temp_p[H2] += PFORCES[ProcID][mol][dir][H2]; } AULOCK(gl->MolLock, mol % MAXLCKS); } comp = comp_last % NMOL; for (mol = 0; ((mol <= comp) && (mol < StartMol[ProcID])); mol++) { ALOCK(gl->MolLock, mol % MAXLCKS); for ( dir = XDIR; dir <= ZDIR; dir++) { temp_p = VAR[mol].F[DEST][dir]; temp_p[H1] += PFORCES[ProcID][mol][dir][H1]; temp_p[O] += PFORCES[ProcID][mol][dir][O]; temp_p[H2] += PFORCES[ProcID][mol][dir][H2]; } AULOCK(gl->MolLock, mol % MAXLCKS); } } else{ for (mol = StartMol[ProcID]; mol <= comp_last; mol++) { ALOCK(gl->MolLock, mol % MAXLCKS); for ( dir = XDIR; dir <= ZDIR; dir++) { temp_p = VAR[mol].F[DEST][dir]; temp_p[H1] += PFORCES[ProcID][mol][dir][H1]; temp_p[O] += PFORCES[ProcID][mol][dir][O]; temp_p[H2] += PFORCES[ProcID][mol][dir][H2]; } AULOCK(gl->MolLock, mol % MAXLCKS); } } /* wait till all forces are updated */ BARRIER(gl->InterfBar, NumProcs); /* divide final forces by masses */ for (mol = StartMol[ProcID]; mol < StartMol[ProcID+1]; mol++) { for ( dir = XDIR; dir <= ZDIR; dir++) { temp_p = VAR[mol].F[DEST][dir]; temp_p[H1] = temp_p[H1] * FHM; temp_p[O] = temp_p[O] * FOM; temp_p[H2] = temp_p[H2] * FHM; } /* for dir */ } /* for mol */ }/* end of subroutine INTERF */