package main import ( "flag" "fmt" "gopkg.in/cheggaaa/pb.v1" "math" "math/rand" "os" "runtime" "time" //"os" ) const ( sigma float64 = 200 f0 float64 = 0.1 G float64 = 4.302e-3 rS float64 = 1e4 ) type star struct { x float64 y float64 z float64 } func rho(x, y, z float64) float64 { r := math.Sqrt(math.Pow(x, 2) + math.Pow(y, 2) + math.Pow(z, 2)) a := (1) / (math.Sqrt(2*math.Pi) * sigma) b := math.Exp(-phi(r) / math.Pow(sigma, 2)) return a * b } func phi(x float64) float64 { if x == 0 { return -4 * math.Pi * f0 * G * math.Pow(rS, 2) } a := -(4 * math.Pi * f0 * G * math.Pow(rS, 3)) / x b := math.Log(1.0 + (x / rS)) return a * b } // generate the given amount of stars and pass them info the stars channel func genStars(threadNr int, amount int, starChannel chan star, galaxyRange float64) { // Define variables var length float64 = galaxyRange // define the range of the galaxy var rangeMin float64 = -length var rangeMax float64 = length var randMin float64 = rho(0, 0, 0) var randMax float64 = rho(length, length, length) var starCounter int = 0 randomSource := rand.New(rand.NewSource(time.Now().UnixNano())) // iterate over the amount of stars for starCounter < amount { // generate random coordinates var x float64 = ((rangeMax - rangeMin) * randomSource.Float64()) + rangeMin var y float64 = ((rangeMax - rangeMin) * randomSource.Float64()) + rangeMin var z float64 = ((rangeMax - rangeMin) * randomSource.Float64()) + rangeMin var randVal = ((randMax - randMin) * randomSource.Float64()) + randMin //fmt.Printf("%-25.15f %-25.15f %-25.15f %-25.15f %-25.15f\n", x, y, z, rho(x, y, z), randVal) if randVal < rho(x, y, z) { //fmt.Printf("[thread %2d] -> | %-20.10f | %-20.10f | %-20.10f | \n", threadNr, x, y, z) var newStar star = star{x, y, z} // write the star to the file starChannel <- newStar starCounter += 1 } } } func main() { // define some variables var amount int var output string hostname, _ := os.Hostname() var pid int = os.Getpid() var outputFileName string = fmt.Sprintf("data/%s_%d_%d.csv", hostname, pid, amount) var threads int = runtime.NumCPU() var galaxyRange float64 // Fill the variables using flags flag.IntVar(&amount, "amount", 40, fmt.Sprintf("%-40s", "Amount of stars to be generated")) flag.StringVar(&output, "output", "data/", fmt.Sprintf("%-40s", "Output File")) flag.IntVar(&threads, "threads", runtime.NumCPU(), fmt.Sprintf("%-40s", "Amount of threads to be used")) flag.Float64Var(&galaxyRange, "range", 1e6, fmt.Sprintf("%-40s", "Spacial size of the galaxy")) flag.Parse() // Calculate some new values var threadAmount int = amount / threads var remainingAmount int = amount - (threadAmount * threads) var starSlice []star var starChannel = make(chan star, 1024) fmt.Printf("Starting %d threads. ", threads) fmt.Printf("Each thread is generating %d stars\n", threadAmount) if remainingAmount > 0 { fmt.Printf("A seperate thread (-1) is generating the remaining %d stars\n\n", remainingAmount) } else { fmt.Printf("\n\n") } startTime := time.Now() // Start all the goroutines for i := 0; i < threads; i++ { go genStars(i, threadAmount, starChannel, galaxyRange) } // generate the missing stars go genStars(-1, remainingAmount, starChannel, galaxyRange) progressBar := pb.New(amount) progressBar.ShowFinalTime = true progressBar.ShowSpeed = true progressBar.Start() // Bundle the stars for j := 0; j < amount; j++ { newStar := <-starChannel starSlice = append(starSlice, newStar) progressBar.Increment() } progressBar.Finish() // Write the stars to a file file, err := os.Create(outputFileName) if err != nil { panic(err) } defer file.Close() for _, starElement := range starSlice { file.WriteString(fmt.Sprintf("%f,%f,%f\n", starElement.x, starElement.y, starElement.z)) } // Stop the timer and print some useful information endTime := time.Now() elapsedTime := endTime.Sub(startTime) fmt.Printf("\nGenerated %d Stars in %v\n", amount, elapsedTime) } /*############################################################ Stats: size: 1e5 amount: 1e6 time: 14m21s size: 1e5 amount 1e4 time: 953.53ms size: 1e6 amount: 1e4 time: 1m46s size: 1e7 amount: 1e4 time: 19m31s ############################################################*/