Runge-Kutta method for Simple pendulum in java

In summary, the conversation is about using the Runge-Kutta method to study and apply it on a simple pendulum. The person is using a timestep of 0.1 and noticing that the pendulum increases energy by 1% every period, while on a website it decreases by 0.01%. They are wondering what they are doing wrong and if there is a software available to compare their calculated values. The program shown is a simulation of the pendulum's movement using the Runge-Kutta method.
  • #1
sefiroths
9
0
Hi, I'm trying to study Runge-Kutta method and apply on a simple pendulum.
Using a timestep dt=0.1 (h=0.1) the pendulum increses energy of 1% every period...
while in this site:
https://www.myphysicslab.com/pendulum/pendulum/pendulum-en.html
decreses energy about 0.01%

What am I doing wrong?
There is a software where can I compare my camculated values?
thanks

Java:
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Point2D;
import java.util.ArrayList;

import javax.swing.JFrame;
import javax.swing.JPanel;class Sistema{
    double g=10;//9.81;
    double m1 = 1;
    double th1 = Math.PI/2;
    double w1=0;
    double L1=1;

    double dt=0.001;

    final int N = 2;

    double energiaIniziale, yPotenziale0;

    ArrayList<Point2D.Double> tracciato = new ArrayList<Point2D.Double>();

    public Sistema(){
        double y0 = getY();

        yPotenziale0 = m1*L1;
        energiaIniziale = energiaCinetica()+energiaPotenziale();

        System.out.println("y0:"+y0);
        System.out.println("y:"+yPotenziale0 + " Tot."+energiaIniziale+" = C:"+energiaCinetica()+" P:"+energiaPotenziale());

    }

    synchronized ArrayList<Point2D.Double> getTracciato(){
        return tracciato;
    }

    synchronized double energiaCinetica(){
        return m1*L1*L1*w1*w1/2;
    }

    synchronized double energiaPotenziale(){
        return m1*g*yPotenziale0+g*m1*getY();
    }

    synchronized double getX(){
        double x1 = L1*Math.sin(th1);
        return x1;
    }

    synchronized double getY(){
        double y1 = -L1*Math.cos(th1);
        return y1;
    }
    void simulate(){
      
        synchronized(this){
            double yin[] = new double[N];
            yin[0] = th1;
            yin[1] = w1;
            double yout[] = runge_kutta(0, yin, dt);
            this.th1 = yout[0];
            this.w1 = yout[1];
          
            //System.out.println(""+Math.toDegrees(th1)+" "+w1);

            tracciato.add(new Point2D.Double(getX(), getY()));
        }
    }

    double[] derivs(double xin, double yin[])
    {
        /*
            yin[0] = th1[i];
            yin[1] = w1[i];
            yin[2] = th2[i];
            yin[3] = w2[i];
         */

        double dydx[] = new double[N];
        /* function to fill array of derivatives dydx at xin */

        dydx[0] = yin[1];
        dydx[1] = -g/L1*Math.sin(th1);

        return dydx;

    }

    double[] runge_kutta(double xin, double yin[], double h)
    {
        double yout[] = new double[N];
        /* fourth order Runge-Kutta - see e.g. Numerical Recipes */

        int i;
        double hh, xh;
        double dydx[] = new double[N];
        double dydxt[] = new double[N];
        double yt[] = new double[N];
        double k1[] = new double[N];
        double k2[] = new double[N];
        double k3[] = new double[N];
        double k4[] = new double[N];

        hh = 0.5*h;
        xh = xin + hh;

        dydx = derivs(xin, yin); /* first step */
//        System.out.print("a:");
        for (i = 0; i < N; i++)
        {
            k1[i] = h*dydx[i];
            yt[i] = yin[i] + 0.5*k1[i];
//            System.out.printf(" %5.2f ",k1[i]);
        }

        dydxt = derivs(xh, yt); /* second step */
//        System.out.print("\nb:");
        for (i = 0; i < N; i++)
        {
            k2[i] = h*dydxt[i];
            yt[i] = yin[i] + 0.5*k2[i];
//            System.out.printf(" %5.2f ",k2[i]);
        } 

        dydxt = derivs(xh, yt); /* third step */
//        System.out.print("\nc:");
        for (i = 0; i < N; i++)
        {
            k3[i] = h*dydxt[i];
            yt[i] = yin[i] + k3[i];
//            System.out.printf(" %5.2f ",k3[i]);
        }

        dydxt = derivs(xin + h, yt); /* fourth step */
//        System.out.print("\nd:");
        for (i = 0; i < N; i++)
        {
            k4[i] = h*dydxt[i];
            yout[i] = yin[i] + k1[i]/6. + k2[i]/3. + k3[i]/3. + k4[i]/6.;
//            System.out.printf(" %5.2f ",k4[i]);
        }
//        System.out.println();
        return yout;

    }
}

class Pannello extends JPanel implements Runnable, MouseMotionListener{

    double x[];
    double y[];
    int offX, offY;
    double scale;
    final int DIM_BARRA_EN = 400;

    Sistema sistema;

    public Pannello(Sistema sistema){
        this.sistema=sistema;
        x = new double[2];
        y = new double[2];
    }

    @Override
    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        int raggioPallina=20;
        offX=this.getWidth()/2;
        offY=this.getHeight()/2;
        scale=(getHeight()-100)/sistema.L1/2;
        ArrayList<Point2D.Double> tracciato;
        synchronized(sistema){

            x[0]=sistema.getX()*scale;
            y[0]=-sistema.getY()*scale;
            tracciato = sistema.getTracciato();
        }        Graphics2D g2 = (Graphics2D)g;      
        g2.setStroke(new BasicStroke(3.0f));

        for(int i=0; i<tracciato.size()-1; i++){
            int x1 = (int) (tracciato.get(i).x*scale+offX);
            int y1 = (int) (-tracciato.get(i).y*scale+offY);
            int x2 = (int) (tracciato.get(i+1).x*scale+offX);
            int y2 = (int) (-tracciato.get(i+1).y*scale+offY);
            int c = (int) (255.0/tracciato.size()*i);
            //            System.out.println("i: "+i+" colore: "+c+" n."+sistema.tracciato.size()*i);
            g2.setPaint(new Color(c, 0, 0));
            g.drawLine(x1,y1,x2,y2);
        }

        g2.setPaint(new Color(0, 0, 0));
        g2.setStroke(new BasicStroke(2.0f));

        //bracci e palline
        g.drawLine(offX,offY, (int)x[0]+offX,(int)y[0]+offY);
        g.fillOval((int)x[0]-raggioPallina/2+offX, (int)y[0]-raggioPallina/2+offY, raggioPallina, raggioPallina);

        //energia
        g2.setStroke(new BasicStroke(1.0f));
        g2.setPaint(new Color(0.5f, 0.5f, 0.5f));
        g.fillRect(10,10,DIM_BARRA_EN,10);//tot
        g2.setPaint(new Color(0f, 1f, 0f));

        double e = sistema.energiaCinetica();
        double v = sistema.energiaPotenziale();
        double m = sistema.energiaIniziale;
        g.fillRect(10,20,(int)(e/sistema.energiaIniziale*DIM_BARRA_EN),10);//cinetica
        g2.setPaint(new Color(1f, 0f, 0f));
        g.fillRect(10+(int)(e/sistema.energiaIniziale*DIM_BARRA_EN),20,
                (int)(v/sistema.energiaIniziale*DIM_BARRA_EN),10);//potenziale    }

    @Override
    public void mouseDragged(MouseEvent arg0) {
        // TODO Auto-generated method stub

    }
    @Override
    public void mouseMoved(MouseEvent arg0) {

        x[0]=(double)arg0.getX()-offX;
        y[0]=(double)arg0.getY()-offY;

    }

    @Override
    public void run() {
        // TODO Auto-generated method stub
        while(true){
            sistema.simulate();

            System.out.format("EnIni:%8.2f Tot.%8.2f = C: %8.2f P: %8.2f\n",
                    sistema.energiaIniziale,
                    sistema.energiaCinetica()+sistema.energiaPotenziale(),
                    sistema.energiaCinetica(),sistema.energiaPotenziale());

            repaint();
            try {
                Thread.sleep((long) (sistema.dt*1000));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}public class Pendolo {    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(600, 600);
        frame.setLayout(null);

        Sistema s = new Sistema();

        Pannello p = new Pannello(s);
        p.setBounds(0,0,600,600);
        frame.add(p);
        p.addMouseMotionListener(p);
        new Thread(p).start();

        s.simulate();

        frame.setVisible(true);
    }}
 

Attachments

  • Pendolo.txt
    6.2 KB · Views: 415
Last edited by a moderator:
Technology news on Phys.org
  • #2


Hi there,

Thank you for your question. It seems like you are experiencing a discrepancy between the results of your Runge-Kutta method and the results from the online pendulum simulation. There could be a few factors contributing to this difference.

Firstly, it is important to note that the online simulation may be using a different algorithm or method to simulate the pendulum. This could result in different results even with the same input values.

Additionally, it is possible that there may be a mistake in your implementation of the Runge-Kutta method. It may be helpful to compare your code with other sources or to use a software tool to check your calculations.

One potential software tool that you could use to compare your calculated values is MATLAB. It has built-in functions for solving differential equations, including the Runge-Kutta method. You could input your values into the MATLAB function and compare the results to your own.

I hope this helps and good luck with your studies!
 

1. What is the Runge-Kutta method for a Simple Pendulum in Java?

The Runge-Kutta method is a numerical algorithm used to solve ordinary differential equations, such as the equations of motion for a simple pendulum. In Java, the method can be implemented using a set of mathematical formulas and programming code to simulate the motion of a pendulum.

2. How does the Runge-Kutta method work for a Simple Pendulum in Java?

The Runge-Kutta method works by breaking the differential equations into a series of smaller steps and using a weighted average of these steps to approximate the solution. In the case of a simple pendulum, the method calculates the position and velocity of the pendulum at each time step based on its current state.

3. What are the advantages of using the Runge-Kutta method for a Simple Pendulum in Java?

The Runge-Kutta method is a more accurate and efficient way of solving differential equations compared to other numerical methods. It also allows for a higher number of time steps, resulting in a more precise simulation of the pendulum's motion.

4. What are the limitations of using the Runge-Kutta method for a Simple Pendulum in Java?

One limitation of the Runge-Kutta method is that it can only approximate solutions and may not always provide an exact solution. Additionally, the accuracy of the method may decrease if the pendulum's motion becomes chaotic or if the time steps are too large.

5. Are there any other methods for simulating a Simple Pendulum in Java?

Yes, there are other methods for simulating a simple pendulum in Java, such as the Euler method or the Verlet algorithm. However, the Runge-Kutta method is generally considered to be the most accurate and efficient method for solving differential equations.

Similar threads

  • Programming and Computer Science
Replies
2
Views
3K
  • Programming and Computer Science
Replies
2
Views
2K
  • Programming and Computer Science
Replies
16
Views
2K
  • Programming and Computer Science
Replies
5
Views
2K
  • Programming and Computer Science
Replies
2
Views
2K
  • Engineering and Comp Sci Homework Help
Replies
2
Views
2K
  • Engineering and Comp Sci Homework Help
Replies
1
Views
2K
  • Programming and Computer Science
Replies
2
Views
2K
  • Programming and Computer Science
Replies
5
Views
41K
Replies
1
Views
2K
Back
Top