diff options
Diffstat (limited to 'main.go')
-rw-r--r-- | main.go | 189 |
1 files changed, 189 insertions, 0 deletions
diff --git a/main.go b/main.go index 7905807..e39e8e5 100644 --- a/main.go +++ b/main.go @@ -1,5 +1,194 @@ package main +import ( + "encoding/csv" + "fmt" + "io" + "io/ioutil" + "log" + "math" + "strconv" + "strings" + "time" +) + +var ( + amountOfStars int +) + func main() { + var tests = []int64{ + 1000, + 2000, + 4000, + 8000, + 16000, + 32000, + 64000, + 128000, + } + data := ReadData("data/200000.csv") + + for _, element := range tests { + data = data[:element] + var processedStars []Star + var cores = 8 + amountOfStars = len(data) + processedChannel := make(chan Star, 1) + + var starsPerCore = amountOfStars / cores + overallStartTime := time.Now() + + // start n threads processing stars + for i := 0; i < cores; i++ { + //fmt.Printf("Core %d processing #%d-#%d\n", i, i*starsPerCore, (i*starsPerCore)+(starsPerCore-1)) + + var begin = i * starsPerCore + var end = (i * starsPerCore) + (starsPerCore) + + go ProcessStar(data, begin, end, processedChannel) + } + + processedChannel <- Star{} + + doneStartingThreads := time.Now() + + // get the results through the processedChannel + for i := 0; i < amountOfStars+1; i++ { + newStar := <-processedChannel + processedStars = append(processedStars, newStar) + } + + doneGettingResults := time.Now() + + threadStartTime := doneStartingThreads.Sub(overallStartTime) + calculationTime := doneGettingResults.Sub(overallStartTime) + + fmt.Printf("--------------------------------------------------------------------------------") + fmt.Printf("Amount of Stars: %d\n", amountOfStars) + fmt.Printf("Amount of Threads: %d\n", cores) + fmt.Printf("Amount of stars per thread: %d\n", starsPerCore) + fmt.Printf("Thread start time: %f sec.\n", threadStartTime.Seconds()) + fmt.Printf("Calculation time: %f sec.\n", calculationTime.Seconds()) + fmt.Printf("Calculation time per star: %f sec.\n", calculationTime.Seconds()/float64(amountOfStars)) + fmt.Printf("Calculation per second: %f sec.\n", calculationTime.Seconds()/float64(amountOfStars)) + } + +} + +type Star struct { + C, V Vec3 + M float64 +} + +type Vec3 struct { + X, Y, Z float64 +} + +func check(e error) { + if e != nil { + panic(e) + } +} + +func ReadData(filepath string) []Star { + // open the .csv + dat, err := ioutil.ReadFile(filepath) + check(err) + + // create a new csv reader + r := csv.NewReader(strings.NewReader(string(dat))) + + var arrayOfStars []Star + + for { + record, err := r.Read() + if err == io.EOF { + break + } + if err != nil { + log.Fatal(err) + } + + // parse the values + x, parseErr := strconv.ParseFloat(record[0], 64) + y, parseErr := strconv.ParseFloat(record[0], 64) + z, parseErr := strconv.ParseFloat(record[0], 64) + check(parseErr) + + // define a star + var localStar = Star{Vec3{x, y, z}, Vec3{0, 0, 0}, 2e30} + + // append the star to the list of stars + arrayOfStars = append(arrayOfStars, localStar) + } + + return arrayOfStars +} + +// CalcForce calculates the force exerted on s1 by s2 and returns a vector representing that force +func CalcForce(s1 Star, s2 Star) Vec3 { + G := 6.6726 * math.Pow(10, -11) + + // calculate the force acting + var combinedMass = s1.M * s2.M + var distance = math.Sqrt(math.Pow(math.Abs(s1.C.X-s2.C.X), 2) + math.Pow(math.Abs(s1.C.Y-s2.C.Y), 2)) + + var scalar = G * ((combinedMass) / math.Pow(distance, 2)) + + // define a unit vector pointing from s1 to s2 + var vector = Vec3{s2.C.X - s1.C.X, s2.C.Y - s1.C.Y, s2.C.Z - s1.C.Z} + var UnitVector = Vec3{vector.X / distance, vector.Y / distance, vector.Z / distance} + + // multiply the vector with the force to get a vector representing the force acting + var force = UnitVector.Multiply(scalar) + + // return the force exerted on s1 by s2 + return force +} + +// Multiply returns the product of the vector and a scalar s +func (v *Vec3) Multiply(s float64) Vec3 { + return Vec3{v.X * s, v.Y * s, v.Z * s} +} + +func ProcessStar(data []Star, begin int, end int, returnChannel chan Star) { + + // iterate over the given range of data + for i := begin; i < end; i++ { + localStar := data[i] + var Force Vec3 + + // iterate over all the other stars + for index := range data { + if index != i { + + // calculate the force acting on the star + force := CalcForce(localStar, data[index]) + + // add the force onto the overall force + Force.X += force.X + Force.Y += force.Y + Force.Z += force.Z + } + } + + newStar := Star{ + C: Vec3{ + X: data[i].C.X, + Y: data[i].C.Y, + Z: data[i].C.Z, + }, + V: Vec3{ + X: Force.X / float64(amountOfStars), + Y: Force.Y / float64(amountOfStars), + Z: Force.Z / float64(amountOfStars), + }, + M: data[i].M, + } + + returnChannel <- newStar + } + return } |