From 0525bc463f53487a7de8409697fabec28471a0bd Mon Sep 17 00:00:00 2001 From: emile Date: Mon, 15 Oct 2018 16:07:22 +0200 Subject: for detailed information about the changes, see https://git.darknebu.la/GalaxySimulator/Source/pulls/1 --- forces/forces.go | 117 +++++++++++++++++++++++++------------------------------ 1 file changed, 54 insertions(+), 63 deletions(-) (limited to 'forces') diff --git a/forces/forces.go b/forces/forces.go index 7763f87..a994334 100644 --- a/forces/forces.go +++ b/forces/forces.go @@ -1,87 +1,81 @@ package forces import ( - "../llog" "../structs" "fmt" + "git.darknebu.la/bit/logplus" "gopkg.in/cheggaaa/pb.v1" "math" ) // forces_acting calculates the force inbetween the two given stars s1 and s2 // The function return the force -func forceActing(s1 structs.Star2D, s2 structs.Star2D) structs.Force { +func accelerationActing(s1 structs.Star2D, s2 structs.Star2D) structs.Vec2 { + // Gravitational constant - var G float64 = 6.674e-11 + var G = 6.674E-11 - // Distance between the stars - var r21 = math.Sqrt(math.Pow(s2.C.X-s1.C.X, 2) + math.Pow(s2.C.Y-s1.C.Y, 2)) + // the vector from star s1 to star s2 + var r12 = s2.C.Subtract(s1.C) - // Unit vector pointing from s1 to s2 - rhat := structs.Force{s2.C.X - s1.C.X, s2.C.Y - s1.C.Y} + // the distance between the stars + var deltaR = r12.GetLength() - // Calculate how strong the star is affected - var FScalar = G * (s1.Mass * s2.Mass) / math.Pow(math.Abs(r21), 2) + // the scalar acceleration of star s1 by star s2 + scalarA := G * (s2.M) / math.Pow(deltaR, 2) - // Calculate the overall force by combining the scalar and the vector - var Fx = FScalar * rhat.X - var Fy = FScalar * rhat.Y + // calculate the direction vector of the vector from s1 to s2 + directionVectorA := r12.GetDirVector() - // Pack the forces in a force structur - F := structs.Force{Fx, Fy} + // the vector acceleration of scalarA + A := directionVectorA.Multiply(scalarA) - return F + return A } -// forces calculates the forces acting in between a given star and all the other stars in a given array. -func forces(stars_arr []structs.Star2D, nr int) structs.Force { +// accelerations calculates the acceleration acting in between a given star and all the other stars in a given array. +func accelerations(stars_arr []structs.Star2D, nr int) structs.Vec2 { - var force structs.Force + var a = /*acceleration*/ structs.Vec2{} // Iterate over all the stars in the stars_arr for index := range stars_arr { // If the current star is not the star itself if index != nr { - // generate a new force and add it to the overall force of the star - fa := forceActing(stars_arr[nr], stars_arr[index]) - stars_arr[nr].F.X += fa.X - stars_arr[nr].F.Y += fa.Y + // calculate the acceleration and add it to the overall acceleration of the star + aa := accelerationActing(stars_arr[nr], stars_arr[index]) + a = a.Add(aa) - force.X += fa.X - force.Y += fa.Y } } - return force + return a } -// forcesThread calculates the forces acting on a given amount of stars in a given range for a given slice of stars +// accelerationThread calculates the acceleration acting on a given amount of stars in a given range for a given slice of stars // as a go-routine -func forcesThread(starSlice []structs.Star2D, localRangeStar2Dt int, localRangeEnd int, channel chan structs.Star2D) { +func accelerationThread(starSlice []structs.Star2D, localRangeStart int, localRangeEnd int, channel chan structs.Star2D) { // iterate over the given range - for index := localRangeStar2Dt; index < localRangeEnd; index++ { + for index := localRangeStart; index < localRangeEnd; index++ { - // Calculate the force acting inbetween the given star and all other stars - var force = forces(starSlice, index) + // Calculate the acceleration acting inbetween the given star and all other stars + var a = accelerations(starSlice, index) // create a new star - newStar2D := structs.Star2D{ - structs.Coord{starSlice[index].C.X, starSlice[index].C.Y}, - structs.Force{force.X, force.Y}, - starSlice[index].Mass, - } + newStar := starSlice[index].Copy() + newStar.AccelerateVelocity(a, 1) - // push the new Star2D into the channel - channel <- newStar2D + // push the new Star into the channel + channel <- newStar } } -// CalcAllForces calculates all the forces acting inbetween all the stars in the given starSlice slice and -// returns a "new" slice contaning the forces -func CalcAllForces(starSlice []structs.Star2D, threads int) []structs.Star2D { - // create a channel for bundling the stars generaten in the go-routines +// CalcAllAccelerations calculates all the accelerations acting in between all the stars in the given starSlice slice and +// returns a "new" slice containing the stars with their new velocities +func CalcAllAccelerations(starSlice []structs.Star2D, threads int) []structs.Star2D { + // create a channel for bundling the stars generated in the go-routines channel := make(chan structs.Star2D, 1000) sliceLength := len(starSlice) @@ -93,43 +87,47 @@ func CalcAllForces(starSlice []structs.Star2D, threads int) []structs.Star2D { // generate a new slice for storing the stars var newSlice []structs.Star2D - llog.Good(fmt.Sprintf("Starting %d workers, each processing %d stars", threads, localRangeLen)) + logplus.LogNeutral(fmt.Sprintf("Starting %d workers, each processing %d stars", threads, localRangeLen)) // start n go threads for i := 0; i < threads; i++ { // define the local range - localRangeStar2Dt := i * localRangeLen + localRangeStart := i * localRangeLen localRangeEnd := (i * localRangeLen) + localRangeLen - // calculate the forces for all the stars in the given slice in the given range and return them using the + // fmt.Printf("starting worker nr. %d, processing %d stars\n", i, localRangeEnd-localRangeStart) + + // calculate the accelerations for all the stars in the given slice in the given range and return them using the // given channel - go forcesThread(starSlice, localRangeStar2Dt, localRangeEnd, channel) + go accelerationThread(starSlice, localRangeStart, localRangeEnd, channel) } // Handle errors (10004 stars, but 1250 stars per thread, so 4 stars are not calculate and block the queue) if sliceLength > localRangeLen { // Calculate the amount of stars and their range - remainingStar2Ds := sliceLength - (localRangeLen * threads) + remainingStars := sliceLength - (localRangeLen * threads) localRangeEnd := ((threads - 1) * localRangeLen) + localRangeLen // Run the Thread - // go forcesThread(starSlice, localRangeEnd, localRangeEnd+remainingStar2Ds, channel) - forcesThread(starSlice, localRangeEnd, localRangeEnd+remainingStar2Ds, channel) + // go accelerationThread(starSlice, localRangeEnd, localRangeEnd+remainingStars, channel) + accelerationThread(starSlice, localRangeEnd, localRangeEnd+remainingStars, channel) } // Initialize a new progress bar - bar := pb.New(len(starSlice)).Prefix("Star2Ds: ") + bar := pb.New(len(starSlice)).Prefix("Stars: ") + + bar.Start() // iterate over the amount of stars for i := 0; i < sliceLength; i++ { // block until a star is finisehd - var newStar2D structs.Star2D = <-channel + var newStar = <-channel // append the star from the channel to the newSlice for returning in the end - newSlice = append(newSlice, newStar2D) + newSlice = append(newSlice, newStar) // increment the progress bar and the counter bar.Increment() @@ -141,26 +139,19 @@ func CalcAllForces(starSlice []structs.Star2D, threads int) []structs.Star2D { } // Calculate the new positions of the stars using the -func NextTimestep(starSlice []structs.Star2D, deltat int) []structs.Star2D { +func NextTimestep(starSlice []structs.Star2D, deltat float64) []structs.Star2D { // create a new slice for storing the "new" stars var newSlice []structs.Star2D // iterate over all the stars in the old slice for index := range starSlice { - // calculate the new position - newX := starSlice[index].C.X + starSlice[index].F.X*float64(deltat) - newY := starSlice[index].C.Y + starSlice[index].F.Y*float64(deltat) - - // assemble the new star - newStar2D := structs.Star2D{ - C: structs.Coord{X: newX, Y: newY}, - F: structs.Force{}, - Mass: starSlice[index].Mass, - } + // move the star with it's velocity for time deltat + newStar := starSlice[index].Copy() + newStar.Move(deltat) // append the new star to the newSlice - newSlice = append(newSlice, newStar2D) + newSlice = append(newSlice, newStar) } return newSlice -- cgit 1.4.1