double System::boundPotentialEnergy(double limit) const { Distance d; double energy = 0.0; arma::Col<double> position1, position2, center(3); for (int i = 0 ; i < numberOfObject ; ++i) { for (int j = 0 ; j < numberOfObject ; ++j) { if (i!=j) { Object movingObject = objectlist[i]; Object otherObject = objectlist[j]; position1 = movingObject.getPosition(); position2 = otherObject.getPosition(); if (d.twoObjects(center, position1)<limit) { double R = d.twoObjects(position1, position2); energy += -( 4 * PI * PI * otherObject.getMass() * movingObject.getMass() /R); } } } } return energy; }
void System::acceleration(Object &mainObject, int i, double time, std::string dimension) { arma::Col<double> tempAcceleration(3); arma::Col<double> acceleration(3); acceleration.zeros(); for (int j = 0; j < numberOfObject; ++j) { if (j!=i) { const Object tempObject = objectlist[j]; Distance d; arma::Col<double> position1, position2; position1 = mainObject.getPosition(); position2 = tempObject.getPosition()+ time*tempObject.getVelocity(); double R = d.twoObjects(position1, position2); if (dimension == "ly") { tempAcceleration = -(tempObject.getMass()* (mainObject.getPosition()-tempObject.getPosition())/ (R*(R*R+epsilon_*epsilon_)));// ly/yr] } else if(dimension == "AU") { tempAcceleration = -4*PI*PI*tempObject.getMass()* (mainObject.getPosition()-tempObject.getPosition())/ (R*(R*R+epsilon_*epsilon_));// ly/yr] } else { std::cout << "dimension must be AU or ly"<< std::endl; } acceleration += tempAcceleration; } //end if } //end for mainObject.setAcceleration(acceleration); }
double System::boundKineticEnergi(double limit) const { double energy = 0; arma::Col<double> center(3), position(3); center.zeros(); Distance d; for (int i = 0 ; i < numberOfObject ; ++i) { Object movingObject = objectlist[i]; position = movingObject.getPosition(); if (d.twoObjects(center, position)<limit) { energy += 0.5 * movingObject.getMass() * arma::dot(movingObject.getVelocity(), movingObject.getVelocity()) ; } } return energy; }
double System::potentialEnergy() const { Distance d; double energy = 0.0; for (int i = 0 ; i < numberOfObject ; ++i) { for (int j = 0 ; j < numberOfObject ; ++j) { if (i!=j) { const Object movingObject = objectlist[i]; const Object otherObject = objectlist[j]; const double R = d.twoObjects(movingObject.getPosition(), otherObject.getPosition()); energy += -( 4 * PI * PI * otherObject.getMass() * movingObject.getMass()/R); } } } return energy; }
double System::maxTimestep(int i) { Distance d; const Object mainObject = objectlist[i]; int k; if (i == 0) { k=1; } else { k=0; } Object tempObject = objectlist[k]; arma::Col<double> position1(3), position2(3); arma::Col<double> mainVel = mainObject.getVelocity(); position1 = mainObject.getPosition(); position2 = tempObject.getPosition(); double R = d.twoObjects(position1, position2); arma::Col<double> tempVel = tempObject.getVelocity()-mainVel; double V = std::sqrt(arma::dot(tempVel,tempVel)); double maxTime; if (V>1e-16) { maxTime = R/V; } else { maxTime = R/1e-16; } double temptime; for (int j = 1; j < numberOfObject; ++j) { if (j!=i) { tempObject = objectlist[j]; position2 = tempObject.getPosition(); R = d.twoObjects(position1, position2); tempVel = tempObject.getVelocity()-mainVel; V = std::sqrt(arma::dot(tempVel,tempVel)); if (V>1e-16) { maxTime = R/V; } else { maxTime = R/1e-16; } temptime = R/V; if (temptime<maxTime) { maxTime = temptime; } } //end if } //end for return maxTime; }
int SolveStep::solve(double timestep, double time, std::string name, std::string method, std::string dimension) { /* Solves given system with given parametres using * given method * timestep: size of timestep * time: total simulation time * name: name of files where the position of the * particles are saved at some timesteps * method: verlet or RK4 * dimension: ly or AU * * Ditterent timers have not been used at the * same time.*/ clock_t start, finish; Distance d; //declaration and intialisation omp_set_num_threads(8); //parallelisation double limit = 60; //definition of bound system arma::Col<double> center(3), position(3); center.zeros(); double t = 0.; System newsystem = mysolarsystem_; int n = time/timestep; //file to store energy of the system std::ofstream energy("energy.m"); energy << "A = ["; //file to store energy of the bound system std::ofstream bound("BoundEnergy.m"); bound << "A = ["; //update the objects initial acceleration for (int i = 0 ; i < size() ; ++i) { Object &mainbody = newsystem.objectlist[i]; newsystem.acceleration(mainbody, i, 0.0,dimension); } // start = clock(); //start timer //start simulation for (int k = 0 ; k < n ; ++k) { t += timestep; //file to store position of particles name.append("t"); std::string filename = name; filename.append(".m"); std::ofstream fout(filename.c_str()); fout << "t = " << t << "\n A = ["; //variable needed for calculating intermediate steps double addtime = 0.0; //simulate all particles for one timestep #pragma omp parallel for private(i) for (int i = 0 ; i < size() ; ++i) { Object &mainbody = newsystem.objectlist[i]; System tempSystem = mysolarsystem_; double dt = timestep; int j = 0; double maxTimestep; //chose the smallest timestep if (mainbody.maxTimestep() < tempSystem.maxTimestep(i)) { maxTimestep = mainbody.maxTimestep(); } else { maxTimestep = tempSystem.maxTimestep(i); } //make sure to use small endough timesteps while(dt > maxTimestep) { dt = dt/2.0; j += 1; } //simulate timesteps for (int kk = 0 ; kk < std::pow(2,j); ++kk) { if (method == "rk4") { start = clock(); //start timer rk4Step(dt, i, mainbody, tempSystem, addtime, dimension); finish = clock(); //stop timer std::cout << "time one rk4 step: " << static_cast<double>(finish - start)/ static_cast<double>(CLOCKS_PER_SEC ) << " s" << std::endl; // mainbody.addToFile(name); addtime += dt; } else if(method == "verlet") { start = clock(); //start timer verlet(dt, i, mainbody, tempSystem, addtime, dimension); finish = clock(); //stop timer std::cout << "time one verlet step: " << static_cast<double>(finish - start)/ static_cast<double>(CLOCKS_PER_SEC ) << " s" << std::endl; // mainbody.addToFile(name); addtime += dt; } else { std::cout << "method must be 'verlet' or 'rk4'" << std::endl; } } mysolarsystem_ = newsystem; //save position to file for (int i = 0 ; i < size() ; ++i) { Object &mainbody = mysolarsystem_.objectlist[i]; position = mainbody.getPosition(); double dist = d.twoObjects(position,center) ; if(dist < limit) { fout << mainbody.getPosition()(0) << "\t\t" << mainbody.getPosition()(1) << "\t\t" << mainbody.getPosition()(2) << "\n"; } // else // { // mysolarsystem_.removeObject(i); // i-=1; // } } fout << "]; \n"; fout << "plot3(A(:,1), A(:,2),A(:,3), 'o')\n"; fout << "t = " << t ; fout.close(); } //write energy of the system to file bound << t << "\t\t" << mysolarsystem_.boundPotentialEnergy(limit) << "\t\t" << mysolarsystem_.boundKineticEnergi(limit) << "\n"; energy << t << "\t\t" << mysolarsystem_.potentialEnergy() << "\t\t" << mysolarsystem_.kineticEnergi() << "\n"; if (k % 100 == 0) { std::cout << t << std::endl; } } // finish = clock(); //stop timer // std::cout << "time: " << // static_cast<double>(finish - start)/ // static_cast<double>(CLOCKS_PER_SEC ) << " s" << std::endl; energy << "]; \n"; energy.close(); bound << "]; \n"; bound.close(); for (int i = 0 ; i < size() ; ++i) { Object &mainbody = mysolarsystem_.objectlist[i]; mysolarsystem_.acceleration(mainbody, i, 0.0,dimension); } //write final postition to file std::ofstream fout("end.m"); fout << "A = ["; for (int i = 0 ; i < size() ; ++i) { Object &mainbody = mysolarsystem_.objectlist[i]; fout << mainbody.getPosition()(0) << "\t\t" << mainbody.getPosition()(1) << "\t\t" << mainbody.getPosition()(2) << "\n"; } fout << "] \n"; fout.close(); return 0; }