Comp Sci Velocity Verlet applied to solar system with C++

Click For Summary
SUMMARY

The forum discussion centers on the implementation of the Velocity Verlet algorithm in C++ to simulate the trajectory of Halley's Comet under gravitational influence from the Sun. The user reports that instead of obtaining an elliptical trajectory, the output appears as a straight line, indicating a potential issue with the gravitational calculations or time step size. Key variables include a gravitational constant (G = 6.67e-11), a time step (dt = 3.154e+7 seconds), and the initial conditions for Halley's Comet and the Sun. Suggestions from other users include checking the accuracy of gravitational force calculations and considering smaller time steps for improved simulation fidelity.

PREREQUISITES
  • Understanding of the Velocity Verlet integration algorithm
  • Familiarity with C++ programming and object-oriented principles
  • Knowledge of gravitational physics and celestial mechanics
  • Experience with data visualization in MATLAB
NEXT STEPS
  • Investigate the effects of varying time step sizes on simulation accuracy
  • Learn about gravitational force calculations and their implementation in C++
  • Explore the use of MATLAB for plotting and analyzing trajectory data
  • Study the principles of orbital mechanics to better understand trajectory shapes
USEFUL FOR

Students and developers working on simulations of celestial mechanics, physicists interested in numerical methods for orbital simulations, and anyone looking to enhance their C++ programming skills in the context of scientific computing.

Rebecca1990
Messages
1
Reaction score
0

Homework Statement


Hello, I am attempting to use the velocity Verlet algorithm of integration applied to the solar system in c++. My goal is be able to use the outputted position components in a plot to see if the trajectory of my object is elliptical/parabolic/hyperbolic resulting from the gravitational interaction with the Sun. I have coded it using c++. I then load the output file into MATLAB and plot. I did an example that mimicked a falling object that interacted with Earth, with a dt = 0.1. It worked fine when plotting. I attempted using x and y velocity components I found for Halley's comet using dt = 3.154e+7s (one year). When I load the data, and plot the x and y components of the position, I thought I would get an elliptical shaped object.Instead, I am getting a straight line that is decreasing as x increases. Can someone help me?

Homework Equations

The Attempt at a Solution


C:
[/B]
#include <string>
#include <iostream>
#include <vector>
#include <cmath>
#include <fstream>
#include <cassert>

   const double G = 6.67e-11;  // N*(m/kg)^2
   //double dt = 0.1; // seconds for falling
   double dt = 3.154e+7; // comet
class CelestialObject
{
private:
   std::string m_name;
   double m_mass;
   double m_positionx;
   double m_positiony;
   double m_velocityx;
   double m_velocityy;
public:
   CelestialObject(std::string name, double mass, double* position, double* velocity) // constructor
   {
      m_name = name;
      m_mass = mass;
      m_positionx = position[0];
      m_positiony = position[1];
      m_velocityx = velocity[0];
      m_velocityy = velocity[1];
   }

   // setters and getters

   void setPosition(double* position)
   {
      m_positionx = position[0];
      m_positiony = position[1];
   }
   void setVelocity(double* velocity)
   {
      m_velocityx = velocity[0];
      m_velocityy = velocity[1];
   }
   double getMass() const
   {
      return m_mass;
   }
   double getPositionX() const
   {
      return m_positionx;
   }
   double getPositionY() const
   {
      return m_positiony;
   }
  double getVelocityX() const
   {
      return m_velocityx;
   }
   double getVelocityY() const
   {
      return m_velocityy;
   }
  

   friend std::eek:stream& operator<<(std::eek:stream& out, const CelestialObject& object)
   {
      return out << object.getPositionX() << '\t' << object.getPositionY() << '\t' << object.getVelocityX() << '\t' << object.getVelocityY() << std::endl;
   }
};

   // returns square of distance between objects
   double distanceSquared(const CelestialObject &a, const CelestialObject &b)
   {
      // distance squared is (dy^2 + dx^2)
      double rSquared = pow(a.getPositionY()-b.getPositionY(),2) + pow(a.getPositionX()-b.getPositionX(),2);
      return rSquared;
   }
   // returns distance between objects
   double distance(const CelestialObject &a, const CelestialObject &b)
   {
      // distance is (dy^2 + dx^2)^(1/2)
      double r = sqrt(pow(a.getPositionY()-b.getPositionY(),2) + pow(a.getPositionX()-b.getPositionX(),2));
      return r;
   }

   // returns magnitude of the force between the objects
   double force(const CelestialObject &a, const CelestialObject &b)
   {
      //  F=(G * m1 * m1)/(r^2) in the direction a->b and b->a
      double forceGrav = G*a.getMass()*b.getMass()/distanceSquared(a, b);
      return forceGrav;
   }

   // returns the angle from a to b
   double angle(const CelestialObject &a, const CelestialObject &b)
   {
      double angle = atan2f(b.getPositionY()-a.getPositionY(),b.getPositionX()-a.getPositionX());
      return angle;
   }

   // Velocity Verlet algorithm

   void updatePosition(CelestialObject &a, CelestialObject &b )
   {
      double F = force(a,b);
      double theta = angle(a,b);
      double accelerationA = F/a.getMass();
      double accelerationB = -F/b.getMass();

   // now that we have the acceleration of both objects, update positions
   // x = x +v *dt + a*dt*dt/2 = x + dt * (v + a*dt/2)
   double newPositionA[2] = {a.getPositionX() + dt * (a.getVelocityX() + accelerationA*((b.getPositionX() - a.getPositionX())/distance(a,b))*dt/2), a.getPositionY() + dt * (a.getVelocityY() + accelerationA*((b.getPositionY() - a.getPositionY())/distance(a,b))*dt/2)};
   a.setPosition(newPositionA);
   double newPositionB[2] = {b.getPositionX() + dt * (b.getVelocityX() + accelerationB*((b.getPositionX() - a.getPositionX())/distance(a,b))*dt/2), b.getPositionY() + dt * (b.getVelocityY() + accelerationB*((b.getPositionY() - a.getPositionY())/distance(a,b))*dt/2)};
   b.setPosition(newPositionB);

   // get new acceleration a'
   F = force(a,b);
   double thetaNew = angle(a,b);
   double newAccelerationA = F/a.getMass();
   double newAccelerationB = -F/b.getMass();
  
   // update velocities
   // v = v + (a + a')*dt/2
   double newVelocityA[2] = {a.getVelocityX() + (accelerationA*((b.getPositionX() - a.getPositionX())/distance(a,b)) + newAccelerationA*((b.getPositionX() - a.getPositionX())/distance(a,b)))*dt/2, a.getVelocityY() + (accelerationA*((b.getPositionY() - a.getPositionY())/distance(a,b)) + newAccelerationA*((b.getPositionY() - a.getPositionY())/distance(a,b)))*dt/2};
   a.setVelocity(newVelocityA);
   double newVelocityB[2] = {b.getVelocityX() + (accelerationB*((b.getPositionX() - a.getPositionX())/distance(a,b)) + newAccelerationB*((b.getPositionX() - a.getPositionX())/distance(a,b)))*dt/2, b.getVelocityY() + (accelerationB*((b.getPositionY() - a.getPositionY())/distance(a,b)) + newAccelerationB*((b.getPositionY() - a.getPositionY())/distance(a,b)))*dt/2};
   b.setVelocity(newVelocityB);
   }int main()
{
   // example of halley's comet
   double positionHalley[2] = {48696201283, -6.8734238e+10};
   double positionSun[2] = {5.6378e7,5.6378e7}; // in metres, take origin at centre so equal component on both axes
   double velocityHalley[2] = {-9.096111, -6.916686};
   double velocitySun[2] = {0,0}; // may have to switch
   CelestialObject halley("halley", 2.2e+14, positionHalley, velocityHalley);
   CelestialObject sun("sun", 1.99e+30, positionSun, velocitySun);
   std::count << "Initial values:\n" << sun << halley;
  
   std::eek:fstream write_output("halley2.txt");
   assert (write_output.is_open());

   int t;
   for (t=0; t < 80; t++)
   {
      write_output << dt*t << '\t' << halley;
      updatePosition(sun, halley);
   }
   std::count << "Final values at t = " << dt*t << " seconds:\n";
   std::count << "Sun: " << sun << "\n";
   std::count << "Halley: "<< halley << "\n";
   write_output.close();
/*
   // example of mass falling off building file output
   double positionMass[2] = {0, 370};
   double positionEarth[2] = {0, -6.378e6};
   double velocityMass[2] = {0, 0};
   double velocityEarth[2] = {0,0};
   CelestialObject mass("mass", 70, positionMass, velocityMass);
   CelestialObject earth("earth", 5.97e+24, positionEarth, velocityEarth);

   std::eek:fstream write_output("falling.txt");
   assert (write_output.is_open());

   int t;
   for (t=0; mass.getPositionY() > 0; t++)
   {
      write_output << dt*t << '\t' << mass;
      updatePosition(mass, earth);
   }
   std::count << "Final values at t = " << dt*t << " seconds:\n";
   std::count << "Earth: " << Earth << "\n";
   std::count << "Mass: "<< mass << "\n";
*/
   return 0;
}
[/B]
 
Last edited by a moderator:
Physics news on Phys.org
Did you try smaller steps?
Did you check the size of all the relevant numbers? A straight line could mean you underestimate the strength of gravity.
 

Similar threads

  • · Replies 2 ·
Replies
2
Views
2K
  • · Replies 2 ·
Replies
2
Views
3K
  • · Replies 2 ·
Replies
2
Views
5K
  • · Replies 1 ·
Replies
1
Views
1K
  • · Replies 1 ·
Replies
1
Views
2K
  • · Replies 15 ·
Replies
15
Views
3K
  • · Replies 5 ·
Replies
5
Views
2K
  • · Replies 10 ·
Replies
10
Views
2K
  • · Replies 3 ·
Replies
3
Views
2K
  • · Replies 15 ·
Replies
15
Views
2K