bool _is_intersecting(tBox& box, const BlockInfo& info) const { Real min_pos[2], max_pos[2]; info.pos(min_pos, 0,0); info.pos(max_pos, B::sizeX-1, B::sizeY-1); const Real intersection[2] = { min(max_pos[0], (Real)(box.center[0] + box.h[0]*0.5)) - max(min_pos[0], (Real)(box.center[0] - box.h[0]*0.5)), min(max_pos[1], (Real)(box.center[1] + box.h[1]*0.5)) - max(min_pos[1], (Real)(box.center[1] - box.h[1]*0.5)) }; return intersection[0]>=0 && intersection[1]>=0; }
inline void operator()(const BlockInfo& info, FluidBlock2D& b) const { map< int, Diagnostic>::iterator it = diagnostics.find(info.blockID); assert(it != diagnostics.end()); Diagnostic& diag = it->second; diag.force[0] = diag.force[1] = 0.0; diag.torque[0] = diag.torque[1] = 0.0; diag.area = 0.0; diag.gridpoints = 0.0; diag.circulation = 0.0; for(int iy=0; iy<FluidBlock2D::sizeY; iy++) for(int ix=0; ix<FluidBlock2D::sizeX; ix++) { Real p[2]; info.pos(p,ix,iy); const Real Xs = b(ix,iy).tmp; diag.force[0] += b(ix,iy).u[0]*Xs; diag.force[1] += b(ix,iy).u[1]*Xs; diag.torque[0] += (p[0]-cor[0]) * (b(ix,iy).u[1]+Uinf[1]) * Xs; diag.torque[1] += -(p[1]-cor[1]) * (b(ix,iy).u[0]+Uinf[0]) * Xs; diag.area += Xs; diag.gridpoints += Xs; diag.circulation += b(ix,iy).omega; } const Real dA = pow(info.h[0], 2); diag.force[0] *= dA*lambda; diag.force[1] *= dA*lambda; diag.torque[0] *= dA*lambda; diag.torque[1] *= dA*lambda; diag.area *= dA; diag.circulation *= dA; diag.force[0] += diag.area*lambda*Uinf[0]; diag.force[1] += diag.area*lambda*Uinf[1]; }
//LOOPC-STYLE: void operator()(blocked_range<int> range) const { for(int iblock=range.begin(); iblock<range.end(); iblock++) { const BlockInfo info = destblocks[iblock]; assert(destblocks[iblock].ptrBlock != NULL); VelocityBlock& my_b = *(VelocityBlock*)destblocks[iblock].ptrBlock; HCFMM::BoxIterator<tBox,tbb::scalable_allocator> it1(rootNode); tBox* current; bool canRemove; //clean velocity field: my_b.clear(); while(it1!=NULL && (it1->nParticles>0)) { canRemove=true; current=it1; const bool is_close = _isclose_box(current, info, _THETA); if(!is_close && current->parent!=NULL) { const bool parent_is_close = _isclose_box(current->parent, info, _THETA); if(parent_is_close) //if we were already well separated from parent, we should skipt this. for(int iy=0; iy<B::sizeY; iy++) for(int ix=0; ix<B::sizeX; ix++) { Real target_pos[2] = {0,0}; info.pos(target_pos, ix, iy); if(current->parent==NULL || !(ws_barnes_hut(current->parent, target_pos, _THETA))) { VelocityRHS rhs; it1->expansions.evaluateExpansions(target_pos, &rhs); my_b.u[0][iy][ix] += rhs.x[0]; my_b.u[1][iy][ix] += rhs.x[1]; measurements.num_indirect_evals[iblock] += 1; } } } else { //treat each point separately for(int iy=0; iy<B::sizeY; iy++) for(int ix=0; ix<B::sizeX; ix++) { Real target_pos[2] = {0,0}; info.pos(target_pos,ix,iy); if(current->parent==NULL || !(ws_barnes_hut(current->parent, target_pos, _THETA))) { //when we were already well separated from the parent, we should not further interact. if (ws_barnes_hut(current, target_pos, _THETA)) { measurements.num_indirect_evals[iblock] += 1; VelocityRHS rhs; it1->expansions.evaluateExpansions(target_pos, &rhs); my_b.u[0][iy][ix] += rhs.x[0]; my_b.u[1][iy][ix] += rhs.x[1]; } else { if(!it1->isleaf) //Case 2: its not a leaf so we further traverse into the tree (summing up the children and bailing out) canRemove=false; else //its close and a leaf ->interactDirectly with particles { Real u[2] = {0,0}; const int nof_sources = current->nParticles; const VelocitySourceParticle * const p = current->vparticles; measurements.num_direct_evals[iblock] += nof_sources; if (_is_intersecting(*current, info)) //tBox current and this block are intersecting for (int i=0;i<nof_sources;++i) { Real r[2] = { target_pos[0] - p[i].x[0], target_pos[1] - p[i].x[1] }; const Real distance_2 = r[0]*r[0] + r[1]*r[1]; if (distance_2==0) continue; const Real factor = 1/distance_2; u[0] -= factor*p[i].w[0]*r[1]; u[1] += factor*p[i].w[0]*r[0]; } else for (int i=0;i<nof_sources;++i) { Real r[2] = { target_pos[0] - p[i].x[0], target_pos[1] - p[i].x[1] }; const Real factor = 1/(r[0]*r[0] + r[1]*r[1]); u[0] -= factor*p[i].w[0]*r[1]; u[1] += factor*p[i].w[0]*r[0]; } assert(!isnan(u[0])); assert(!isnan(u[1])); my_b.u[0][iy][ix] += u[0]; my_b.u[1][iy][ix] += u[1]; } } } } } if(canRemove) it1.advanceRemove(); else it1++; } //multiply by scaling factor { Real * const ue = (Real *)my_b.u[0]; Real * const ve = (Real *)my_b.u[1]; const Real scale = 1./(2.0*M_PI)*inv_scaling; static const int n = FluidBlock2D::sizeY*FluidBlock2D::sizeX; for(int i=0; i<n; i++) { ue[i] *= scale; ve[i] *= scale; } } #ifndef _FMMSILENT printf("Done with %d %d %d l=%d\n", info.index[0], info.index[1], info.index[2], info.level); #endif } }