Пример #1
0
/*
 * Evaluate the potential (i.e. the stream function psi) at a particular target location (xt, yt), 
 * given an array of nodes and their expansions 
 */
void evaluate(const Node* nodes, const int node_id, const double *xdata, const double *ydata, const double *mdata,
		const double thetasquared, double * const result, const double xt, const double yt)
{
	// INPUT
	// nodes	array of nodes for the tree of data we're working with
	// node_id	index indicating the node we am considering now (used for recursive call) inside the array of nodes 
	// expansions	array of expansions for these nodes (not needed, we're actually implementing expansion as an attribute of node)
	// xdata	array of x-coordinates of the source-particles (all of them, not just the ones contained in the node. Needed for passing this array down in the recursion)
	// ydata	........ y-coordinates .......................
	// mdata	........ source-values ....................... (vorticities)
	// thetasquared	.
	// xt		x-coordinate of the location of the target
	// yt		y-coordinate .............................
	// OUTPUT
	// result	potential at target location (xt, yt)
	
	
	const Node* const node = nodes + node_id;								// create a pointer to the node we're considering

	if(node->r > -0.5){   													// if this node isn't empty, go on with the evaluation
		if(node->r == 0){ 													// if the node contains only 1 particle 
			const int n_s = node->part_start;								// compute the p2p expansion
			*result += p2p(xdata + n_s, ydata + n_s, mdata + n_s, 1, xt, yt);
			return;
		}
		
		// if the node contains strictly more than one particle, compute the distance between the target and the center of mass of the node 
		double distsquared = ( (node->xcom - xt)*(node->xcom - xt) + (node->ycom - yt)*(node->ycom -yt) ) ; // square of the distance between the target location and the center of mass of the node 

		// recursive algorithm for the evaluation of the potential 			// pseudo-code, cf lecture 4, slide 24
		if( (node->r * node->r) < (distsquared * thetasquared) ){			// if the target and the node are sufficiently far away from each other
																			// return the expansion to particle expression as a potential
			*result += e2p(xt - node->xcom, yt - node->ycom, node->mass, exp_order, node->rxps, node->ixps);
			return;				
																			// and terminate the call to "evaluate"
		} else if(node->child_id == -1){ 									// if they're not sufficiently far away from each other
																			// and if this node is a leaf, 
																			// then we cannot descend deeper into the tree
																			// return the particle-to-particle expansion
			const int n_s = node->part_start;
			const int n_e = node->part_end;
			*result += p2p(xdata + n_s, ydata + n_s, mdata + n_s, n_e - n_s + 1, xt, yt);
			return;
			
		} else {															// in any other case, 
																			// i.e., they are not sufficiently far away from each other, and this node isn't a leaf
																			// continue the descent of the tree
			evaluate(nodes, node->child_id  , xdata, ydata, mdata, thetasquared, result, xt, yt) ;
			evaluate(nodes, node->child_id+1, xdata, ydata, mdata, thetasquared, result, xt, yt) ;
			evaluate(nodes, node->child_id+2, xdata, ydata, mdata, thetasquared, result, xt, yt) ;
			evaluate(nodes, node->child_id+3, xdata, ydata, mdata, thetasquared, result, xt, yt) ;
		}
	}
}
Пример #2
0
 static uint16_type e2p( uint16_type e, uint16_type p )
 {
     return e2p( e,p,boost::mpl::int_<( Order>3 )?1:Order>() );
 }