gonum: gonum.org/v1/gonum/spatial/barneshut Index | Examples | Files

package barneshut

import "gonum.org/v1/gonum/spatial/barneshut"

Package barneshut provides routines for calculating n-body force approximations using the Barnes-Hut algorithm.

See https://en.wikipedia.org/wiki/Barnes–Hut_simulation, http://arborjs.org/docs/barnes-hut and https://jheer.github.io/barnes-hut/ for details.

Code:

package main

import (
    "log"

    "golang.org/x/exp/rand"

    "gonum.org/v1/gonum/spatial/barneshut"
    "gonum.org/v1/gonum/spatial/r2"
)

type mass struct {
    d   r2.Vec
    v   r2.Vec
    m   float64
}

func (m *mass) Coord2() r2.Vec { return m.d }
func (m *mass) Mass() float64  { return m.m }
func (m *mass) move(f r2.Vec) {
    m.v = m.v.Add(f.Scale(1 / m.m))
    m.d = m.d.Add(m.v)
}

func main() {
    rnd := rand.New(rand.NewSource(1))

    // Make 1000 stars in random locations.
    stars := make([]*mass, 1000)
    p := make([]barneshut.Particle2, len(stars))
    for i := range stars {
        s := &mass{
            d: r2.Vec{
                X:  100 * rnd.Float64(),
                Y:  100 * rnd.Float64(),
            },
            v: r2.Vec{
                X:  rnd.NormFloat64(),
                Y:  rnd.NormFloat64(),
            },
            m:  10 * rnd.Float64(),
        }
        stars[i] = s
        p[i] = s
    }
    vectors := make([]r2.Vec, len(stars))

    // Make a plane to calculate approximate forces
    plane := barneshut.Plane{Particles: p}

    // Run a simulation for 100 updates.
    for i := 0; i < 1000; i++ {
        // Build the data structure. For small systems
        // this step may be omitted and ForceOn will
        // perform the naive quadratic calculation
        // without building the data structure.
        err := plane.Reset()
        if err != nil {
            log.Fatal(err)
        }

        // Calculate the force vectors using the theta
        // parameter...
        const theta = 0.5
        // and an imaginary gravitational constant.
        const G = 10
        for j, s := range stars {
            vectors[j] = plane.ForceOn(s, theta, barneshut.Gravity2).Scale(G)
        }

        // Update positions.
        for j, s := range stars {
            s.move(vectors[j])
        }

        // Rendering stars is left as an exercise for
        // the reader.
    }
}

Index

Examples

Package Files

barneshut2.go barneshut3.go doc.go no_bounds.go

func Gravity2 Uses

func Gravity2(_, _ Particle2, m1, m2 float64, v r2.Vec) r2.Vec

Gravity2 returns a vector force on m1 by m2, equal to (m1⋅m2)/‖v‖² in the directions of v. Gravity2 ignores the identity of the interacting particles and returns a zero vector when the two particles are coincident, but performs no other sanity checks.

func Gravity3 Uses

func Gravity3(_, _ Particle3, m1, m2 float64, v r3.Vec) r3.Vec

Gravity3 returns a vector force on m1 by m2, equal to (m1⋅m2)/‖v‖² in the directions of v. Gravity3 ignores the identity of the interacting particles and returns a zero vector when the two particles are coincident, but performs no other sanity checks.

type Force2 Uses

type Force2 func(p1, p2 Particle2, m1, m2 float64, v r2.Vec) r2.Vec

Force2 is a force modeling function for interactions between p1 and p2, m1 is the mass of p1 and m2 of p2. The vector v is the vector from p1 to p2. The returned value is the force vector acting on p1.

In models where the identity of particles must be known, p1 and p2 may be compared. Force2 may be passed nil for p2 when the Barnes-Hut approximation is being used. A nil p2 indicates that the second mass center is an aggregate.

type Force3 Uses

type Force3 func(p1, p2 Particle3, m1, m2 float64, v r3.Vec) r3.Vec

Force3 is a force modeling function for interactions between p1 and p2, m1 is the mass of p1 and m2 of p2. The vector v is the vector from p1 to p2. The returned value is the force vector acting on p1.

In models where the identity of particles must be known, p1 and p2 may be compared. Force3 may be passed nil for p2 when the Barnes-Hut approximation is being used. A nil p2 indicates that the second mass center is an aggregate.

type Particle2 Uses

type Particle2 interface {
    Coord2() r2.Vec
    Mass() float64
}

Particle2 is a particle in a plane.

type Particle3 Uses

type Particle3 interface {
    Coord3() r3.Vec
    Mass() float64
}

Particle3 is a particle in a volume.

type Plane Uses

type Plane struct {
    Particles []Particle2
    // contains filtered or unexported fields
}

Plane implements Barnes-Hut force approximation calculations.

func NewPlane Uses

func NewPlane(p []Particle2) (*Plane, error)

NewPlane returns a new Plane. If the plane is too large to allow particle coordinates to be distinguished due to floating point precision limits, NewPlane will return a non-nil error.

func (*Plane) ForceOn Uses

func (q *Plane) ForceOn(p Particle2, theta float64, f Force2) (force r2.Vec)

ForceOn returns a force vector on p given p's mass and the force function, f, using the Barnes-Hut theta approximation parameter.

Calls to f will include p in the p1 position and a non-nil p2 if the force interaction is with a non-aggregate mass center, otherwise p2 will be nil.

It is safe to call ForceOn concurrently.

func (*Plane) Reset Uses

func (q *Plane) Reset() (err error)

Reset reconstructs the Barnes-Hut tree. Reset must be called if the Particles field or elements of Particles have been altered, unless ForceOn is called with theta=0 or no data structures have been previously built. If the plane is too large to allow particle coordinates to be distinguished due to floating point precision limits, Reset will return a non-nil error.

type Volume Uses

type Volume struct {
    Particles []Particle3
    // contains filtered or unexported fields
}

Volume implements Barnes-Hut force approximation calculations.

func NewVolume Uses

func NewVolume(p []Particle3) (*Volume, error)

NewVolume returns a new Volume. If the volume is too large to allow particle coordinates to be distinguished due to floating point precision limits, NewVolume will return a non-nil error.

func (*Volume) ForceOn Uses

func (q *Volume) ForceOn(p Particle3, theta float64, f Force3) (force r3.Vec)

ForceOn returns a force vector on p given p's mass and the force function, f, using the Barnes-Hut theta approximation parameter.

Calls to f will include p in the p1 position and a non-nil p2 if the force interaction is with a non-aggregate mass center, otherwise p2 will be nil.

It is safe to call ForceOn concurrently.

func (*Volume) Reset Uses

func (q *Volume) Reset() (err error)

Reset reconstructs the Barnes-Hut tree. Reset must be called if the Particles field or elements of Particles have been altered, unless ForceOn is called with theta=0 or no data structures have been previously built. If the volume is too large to allow particle coordinates to be distinguished due to floating point precision limits, Reset will return a non-nil error.

Package barneshut imports 5 packages (graph) and is imported by 2 packages. Updated 2019-11-10. Refresh now. Tools for package owners.