mirror of
				https://github.com/gonum/gonum.git
				synced 2025-10-31 18:42:45 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			84 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			84 lines
		
	
	
		
			1.8 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // Copyright ©2019 The Gonum Authors. All rights reserved.
 | |
| // Use of this source code is governed by a BSD-style
 | |
| // license that can be found in the LICENSE file.
 | |
| 
 | |
| package barneshut_test
 | |
| 
 | |
| 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 Example_galaxy() {
 | |
| 	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.
 | |
| 	}
 | |
| }
 | 
