/*! This routine finds all neighbours `j' that can interact with * \f$ r_{ij} < h_i \f$ OR if \f$ r_{ij} < h_j \f$. */ int subfind_ngb_treefind_linkpairs(MyDouble searchcenter[3], double hsml, int target, int *startnode, int mode, double *hmax, int *nexport, int *nsend_local) { int numngb, i, no, p, task, nexport_save, exported = 0; struct NODE *current; double dx, dy, dz, dist, r2; #ifdef PERIODIC MyDouble xtmp; #endif nexport_save = *nexport; *hmax = 0; numngb = 0; no = *startnode; while(no >= 0) { if(no < All.MaxPart) /* single particle */ { p = no; no = Nextnode[no]; #ifdef DENSITY_SPLIT_BY_TYPE if(!((1 << P[p].Type) & (DENSITY_SPLIT_BY_TYPE))) #else if(!((1 << P[p].Type) & (FOF_PRIMARY_LINK_TYPES))) #endif continue; dist = DMAX(P[p].DM_Hsml, hsml); dx = NGB_PERIODIC_LONG_X(P[p].Pos[0] - searchcenter[0]); if(dx > dist) continue; dy = NGB_PERIODIC_LONG_Y(P[p].Pos[1] - searchcenter[1]); if(dy > dist) continue; dz = NGB_PERIODIC_LONG_Z(P[p].Pos[2] - searchcenter[2]); if(dz > dist) continue; if((r2 = (dx * dx + dy * dy + dz * dz)) > dist * dist) continue; Dist2list[numngb] = r2; Ngblist[numngb++] = p; } else { if(no >= All.MaxPart + MaxNodes) /* pseudo particle */ { if(mode == 1) endrun(12312); if(target >= 0) /* if no target is given, export will not occur */ { exported = 1; if(Exportflag[task = DomainTask[no - (All.MaxPart + MaxNodes)]] != target) { Exportflag[task] = target; Exportnodecount[task] = NODELISTLENGTH; } if(Exportnodecount[task] == NODELISTLENGTH) { if(*nexport >= All.BunchSize) { *nexport = nexport_save; if(nexport_save == 0) endrun(13004); /* in this case, the buffer is too small to process even a single particle */ for(task = 0; task < NTask; task++) nsend_local[task] = 0; for(no = 0; no < nexport_save; no++) nsend_local[DataIndexTable[no].Task]++; return -1; } Exportnodecount[task] = 0; Exportindex[task] = *nexport; DataIndexTable[*nexport].Task = task; DataIndexTable[*nexport].Index = target; DataIndexTable[*nexport].IndexGet = *nexport; *nexport = *nexport + 1; nsend_local[task]++; } DataNodeList[Exportindex[task]].NodeList[Exportnodecount[task]++] = DomainNodeIndex[no - (All.MaxPart + MaxNodes)]; if(Exportnodecount[task] < NODELISTLENGTH) DataNodeList[Exportindex[task]].NodeList[Exportnodecount[task]] = -1; } no = Nextnode[no - MaxNodes]; continue; } current = &Nodes[no]; if(mode == 1) { if(current->u.d.bitflags & (1 << BITFLAG_TOPLEVEL)) /* we reached a top-level node again, which means that we are done with the branch */ { *startnode = -1; return numngb; } } dist = DMAX(Extnodes[no].hmax, hsml) + 0.5 * current->len; no = current->u.d.sibling; /* in case the node can be discarded */ dx = NGB_PERIODIC_LONG_X(current->center[0] - searchcenter[0]); if(dx > dist) continue; dy = NGB_PERIODIC_LONG_Y(current->center[1] - searchcenter[1]); if(dy > dist) continue; dz = NGB_PERIODIC_LONG_Z(current->center[2] - searchcenter[2]); if(dz > dist) continue; /* now test against the minimal sphere enclosing everything */ dist += FACT1 * current->len; if(dx * dx + dy * dy + dz * dz > dist * dist) continue; no = current->u.d.nextnode; /* ok, we need to open the node */ } } if(mode == 0) /* local particle */ if(exported == 0) /* completely local */ if(numngb >= All.DesNumNgb) { R2list = mymalloc(" R2list", sizeof(struct r2data) * numngb); for(i = 0; i < numngb; i++) { R2list[i].index = Ngblist[i]; R2list[i].r2 = Dist2list[i]; } #ifdef OMP_SORT omp_qsort(R2list, numngb, sizeof(struct r2data), subfind_ngb_compare_dist); #else qsort(R2list, numngb, sizeof(struct r2data), subfind_ngb_compare_dist); #endif *hmax = sqrt(R2list[All.DesNumNgb - 1].r2); numngb = All.DesNumNgb; for(i = 0; i < numngb; i++) { Ngblist[i] = R2list[i].index; Dist2list[i] = R2list[i].r2; } myfree(R2list); } *startnode = -1; return numngb; }
int subfind_contamination_treefind(MyDouble searchcenter[3], MyFloat hsml, int target, int *startnode, int mode, int *nexport, int *nsend_local, double *Mass) { int no, p, task, nexport_save; struct NODE *current; double mass; int count; MyDouble dx, dy, dz, dist, r2; #ifdef PERIODIC MyDouble xtmp; #endif nexport_save = *nexport; mass = 0; count = 0; no = *startnode; while(no >= 0) { if(no < All.MaxPart) /* single particle */ { p = no; no = Nextnode[no]; dist = hsml; dx = NGB_PERIODIC_LONG_X(P[p].Pos[0] - searchcenter[0]); if(dx > dist) continue; dy = NGB_PERIODIC_LONG_Y(P[p].Pos[1] - searchcenter[1]); if(dy > dist) continue; dz = NGB_PERIODIC_LONG_Z(P[p].Pos[2] - searchcenter[2]); if(dz > dist) continue; if(dx * dx + dy * dy + dz * dz > dist * dist) continue; mass += P[p].Mass; count++; } else { if(no >= All.MaxPart + MaxNodes) /* pseudo particle */ { if(mode == 1) endrun(12312); if(mode == 0) { if(Exportflag[task = DomainTask[no - (All.MaxPart + MaxNodes)]] != target) { Exportflag[task] = target; Exportnodecount[task] = NODELISTLENGTH; } if(Exportnodecount[task] == NODELISTLENGTH) { if(*nexport >= All.BunchSize) { *nexport = nexport_save; if(nexport_save == 0) endrun(13005); /* in this case, the buffer is too small to process even a single particle */ for(task = 0; task < NTask; task++) nsend_local[task] = 0; for(no = 0; no < nexport_save; no++) nsend_local[DataIndexTable[no].Task]++; return -1; } Exportnodecount[task] = 0; Exportindex[task] = *nexport; DataIndexTable[*nexport].Task = task; DataIndexTable[*nexport].Index = target; DataIndexTable[*nexport].IndexGet = *nexport; *nexport = *nexport + 1; nsend_local[task]++; } DataNodeList[Exportindex[task]].NodeList[Exportnodecount[task]++] = DomainNodeIndex[no - (All.MaxPart + MaxNodes)]; if(Exportnodecount[task] < NODELISTLENGTH) DataNodeList[Exportindex[task]].NodeList[Exportnodecount[task]] = -1; } no = Nextnode[no - MaxNodes]; continue; } current = &Nodes[no]; if(mode == 1) { if(current->u.d.bitflags & (1 << BITFLAG_TOPLEVEL)) /* we reached a top-level node again, which means that we are done with the branch */ { *startnode = -1; *Mass = mass; return count; } } no = current->u.d.sibling; /* in case the node can be discarded */ dist = hsml + 0.5 * current->len;; dx = NGB_PERIODIC_LONG_X(current->center[0] - searchcenter[0]); if(dx > dist) continue; dy = NGB_PERIODIC_LONG_Y(current->center[1] - searchcenter[1]); if(dy > dist) continue; dz = NGB_PERIODIC_LONG_Z(current->center[2] - searchcenter[2]); if(dz > dist) continue; /* now test against the minimal sphere enclosing everything */ dist += FACT1 * current->len; if((r2 = (dx * dx + dy * dy + dz * dz)) > dist * dist) continue; no = current->u.d.nextnode; /* ok, we need to open the node */ } } *startnode = -1; *Mass = mass; return count; }