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