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