Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

A Runge-Kutta method for Simple pendulum in java

  1. May 13, 2017 #1
    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

    Code (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);
        }


    }
     

    Attached Files:

    Last edited by a moderator: May 13, 2017
  2. jcsd
  3. May 18, 2017 #2
    Thanks for the thread! This is an automated courtesy bump. Sorry you aren't generating responses at the moment. Do you have any further information, come to any new conclusions or is it possible to reword the post? The more details the better.
     
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook

Have something to add?
Draft saved Draft deleted



Similar Discussions: Runge-Kutta method for Simple pendulum in java
  1. A Simple Pendulum (Replies: 6)

  2. Simple Pendulum (Replies: 6)

  3. Simple pendulum (Replies: 1)

Loading...