Java Runge-Kutta method for Simple pendulum in java

Click For Summary
The discussion revolves around the application of the Runge-Kutta method to simulate a simple pendulum, highlighting a significant discrepancy in energy conservation results. The user reports that their simulation shows a 1% increase in energy per period, while an online simulation indicates only a 0.01% decrease. Possible reasons for this difference include variations in the algorithms used by the online simulation and potential errors in the user's implementation of the Runge-Kutta method. Suggestions for resolving the issue include comparing the user's code with established sources and utilizing software tools like MATLAB to verify calculations and results. This approach could help identify discrepancies and improve the accuracy of the simulation.
sefiroths
Messages
9
Reaction score
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

Last edited by a moderator:
Technology news on Phys.org


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!
 
Learn If you want to write code for Python Machine learning, AI Statistics/data analysis Scientific research Web application servers Some microcontrollers JavaScript/Node JS/TypeScript Web sites Web application servers C# Games (Unity) Consumer applications (Windows) Business applications C++ Games (Unreal Engine) Operating systems, device drivers Microcontrollers/embedded systems Consumer applications (Linux) Some more tips: Do not learn C++ (or any other dialect of C) as a...

Similar threads

  • · Replies 2 ·
Replies
2
Views
4K
  • · Replies 2 ·
Replies
2
Views
3K
  • · Replies 16 ·
Replies
16
Views
3K
Replies
2
Views
2K
  • · Replies 5 ·
Replies
5
Views
2K
  • · Replies 2 ·
Replies
2
Views
2K
Replies
5
Views
41K
  • · Replies 2 ·
Replies
2
Views
7K
  • · Replies 5 ·
Replies
5
Views
11K