Ejemplo n.º 1
0
// compute repulsion field at interpolation point x, y and update v
func (f *RepulsionField) ComputeFieldRecursive(x, y float64, q *quadtree.Quadtree, coord quadtree.Coord, v *float64) {

	Trace.Printf("ComputeFieldRecursive at %e %e, quadtree %p, coord %s, input v = %e\n", x, y, q, coord.String(), *v)

	var body quadtree.Body
	body.X = x
	body.Y = y

	// compute the node box size
	level := coord.Level()
	boxSize := 1.0 / math.Pow(2.0, float64(level)) // if level = 0, this is 1.0

	node := &(q.Nodes[coord])
	distToNode := getModuloDistanceBetweenBodies(&body, &(node.Body))

	// avoid node with zero mass
	if node.M == 0 {
		return
	}

	// check if the COM of the node can be used
	if (boxSize / distToNode) < BN_THETA {

		*v += getRepulsionField(&body, &(node.Body))

	} else {
		if level < 8 {
			// parse sub nodes
			Trace.Printf("ComputeFieldRecursive go down at node %#v\n", node.Coord())

			coordNW, coordNE, coordSW, coordSE := quadtree.NodesBelow(coord)
			f.ComputeFieldRecursive(x, y, q, coordNW, v)
			f.ComputeFieldRecursive(x, y, q, coordNE, v)
			f.ComputeFieldRecursive(x, y, q, coordSW, v)
			f.ComputeFieldRecursive(x, y, q, coordSE, v)
		} else {

			// parse bodies of the node
			rank := 0
			rankOfBody := -1
			for b := node.First(); b != nil; b = b.Next() {
				if *b != body {

					dist := getModuloDistanceBetweenBodies(&body, b)

					if dist == 0.0 {
						var t testing.T
						q.CheckIntegrity(&t)

						// c1 := body.Coord()
						// c2 := b.Coord()
						Error.Printf("Problem at rank %d for body of rank %d on node %#v ",
							rank, rankOfBody, *node)
					}

					// if distance is inferior to cutoff, return
					if dist < f.cutoff {
						*v = 0.0
						return

					} else {
						*v += getRepulsionField(&body, b)

					}

					rank++
					Trace.Printf("ComputeFieldRecursive at leaf %#v rank %d x %9.3f y %9.3f\n", b.Coord(), rank, x, y)
				} else {
					rankOfBody = rank
				}
			}
		}
	}
	return
}