Пример #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
}
Пример #2
0
// given a body and a node in the quadtree, compute the repulsive force
func (r *Run) computeAccelationWithNodeRecursive(idx int, coord quadtree.Coord) float64 {

	minInterbodyDistance := 2.0

	body := (*r.bodies)[idx]
	acc := &((*r.bodiesAccel)[idx])

	// 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 := &(r.q.Nodes[coord])
	distToNode := getModuloDistanceBetweenBodies(&body, &(node.Body))

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

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

		x, y := getRepulsionVector(&body, &(node.Body))

		acc.X += x
		acc.Y += y

		// fmt.Printf("computeAccelationWithNodeRecursive at node %#v x %9.3f y %9.3f\n", node.Coord(), x, y)

	} else {
		if level < 8 {
			// parse sub nodes
			// fmt.Printf("computeAccelationWithNodeRecursive go down at node %#v\n", node.Coord())
			coordNW, coordNE, coordSW, coordSE := quadtree.NodesBelow(coord)
			dist := 2.0
			dist = r.computeAccelationWithNodeRecursive(idx, coordNW)
			if dist < minInterbodyDistance {
				minInterbodyDistance = dist
			}

			dist = r.computeAccelationWithNodeRecursive(idx, coordNE)
			if dist < minInterbodyDistance {
				minInterbodyDistance = dist
			}

			dist = r.computeAccelationWithNodeRecursive(idx, coordSW)
			if dist < minInterbodyDistance {
				minInterbodyDistance = dist
			}

			dist = r.computeAccelationWithNodeRecursive(idx, coordSE)
			if dist < minInterbodyDistance {
				minInterbodyDistance = dist
			}

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

					// update the neighbour
					r.bodiesNeighbours.Insert(idx, b, dist)

					if dist == 0.0 {
						var t testing.T
						r.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)
						// logMessage := fmt.Sprintf("distance is 0.0 between \n%#v\n%s and \n%#v\n%s\n", body, c1.String(), b, c2.String())

						// log.Fatal( logMessage)
					}
					if dist < minInterbodyDistance {
						minInterbodyDistance = dist
					}

					x, y := getRepulsionVector(&body, b)

					acc.X += x
					acc.Y += y
					rank++
					// fmt.Printf("computeAccelationWithNodeRecursive at leaf %#v rank %d x %9.3f y %9.3f\n", b.Coord(), rank, x, y)
				} else {
					rankOfBody = rank
				}
			}
		}
	}
	return minInterbodyDistance
}