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

1D simulator (Ruby)

  1. Jun 29, 2008 #1
    I have just started programming (started on C but currently using Ruby). This is literally my first proper program and I wanted some help and opinions. The problem is I am completely self taught using various random tutorials to learn the language and my own logic for the actual programs, so until I start my engineering degree at Oxford in October I have to work it out myself.

    Anyway I just wanted to use some simple mechanics to simulate an object being given an impulse and the resulting motion through a medium on a surface. The basics were to work out acceleration based on resultant force and use the kinematic equations to calculate the result of that interval. I wanted the simulation to occur in real time on the screen and text files to be created so the data can be used in excel or something.

    Code (Text):
    class Ball
     
      def initialize(massOfBall, coOfFriction)
        @mass = massOfBall
        @coef = coOfFriction
        @d = 0
        @v = 0
        @a = 0
        @area = 1
        @rho = 0
        @drag = 0
      end
     
      def density ro
        @rho = ro
      end
     
      def area a
        @area = a
      end
     
      def drag dragco
        @drag = dragco
      end
     
      def origin
        @d = 0
        @v = 0
        puts 'Back to origin'
      end
     
      def impulse mag
        @v = mag.to_f/@mass.to_f
        #puts 'impulse ran'
        run
      end
     
      private
     
      def run
        #puts 'run ran'
        n = 1
        while File.exists?(('distance_'+n.to_s+'.txt').to_s)
          n = n + 1
        end
        distancef = File.new(('distance_'+n.to_s+'.txt').to_s, 'w+')
        speedf = File.new(('speed_'+n.to_s+'.txt').to_s, 'w+')
        timef = File.new(('time_'+n.to_s+'.txt').to_s, 'w+')
        t2 = 0
        t1 = 0
        t = 0
        time = Time.now
        lw = 25
        distancef.puts(@d.to_s)
        timef.puts(t.to_s)
        speedf.puts(@v.to_s)
        puts (@d.to_s+'m').ljust(lw) + (t.to_s+' secs').center(lw) + (@v.to_s+'m/s').rjust(lw)
        while (@v > 0.05) or (@v < -0.05)
          int = t2 - t1
          t1 = Time.now
          @a = (-1*@coef*9.8) - (0.5*@rho*@v*@v*@drag*@area/@mass)
          #look into this more!
          if (0.5*@a*int**2).abs > (@v*int).abs
            return
          elsif @v < 0
            @d = @d + (@v*int) - (0.5*@a*int**2)
            @v = @v - (@a*int)
          else
            @d = @d + (@v*int) + (0.5*@a*int**2)
            @v = @v + (@a*int)
          end
          t = t + int
          unless int == 0
            distancef.puts(@d.to_s)
            timef.puts(t.to_s)
            speedf.puts(@v.to_s)
            puts (@d.to_s+'m').ljust(lw) + (t.to_s+' secs').center(lw) + (@v.to_s+'m/s').rjust(lw)
          end
          t2 = Time.now
         
        end
        distancef.close
        timef.close
        speedf.close
        puts 'run finished. started at ' + time.to_s + ' and finished at ' + Time.now.to_s
      end
     
    end

    puts 'Enter mass (kg):'
    mass = gets.chomp.to_f
    puts 'Enter coefficient of friction:'
    co = gets.chomp.to_f
    ball = Ball.new(mass, co)
    while true
      str = gets.chomp.downcase
      if str == 'area'
        puts 'New frontal cross sectional area (m^2):'
        area = gets.chomp.to_f
        ball.area(area)
      elsif str == 'density'
        puts 'New density of fluid medium (e.g. water = 1000, air = 1.2) (kg/m^3):'
        dens = gets.chomp.to_f
        ball.density(dens)
      elsif str == 'drag'
        puts 'New drag coefficient of object (e.g. smooth sphere = 0.1, rough sphere = 0.4):'
        coef = gets.chomp.to_f
        ball.drag(coef)
      elsif str == 'push'
        puts 'Size of impulse:'
        magnitude = gets.chomp.to_f
        ball.impulse(magnitude)
      elsif str == 'return'
      ball.origin
      elsif str == 'help'
        puts 'Commands: area, density, drag, push, return, exit'
      elsif str == 'exit'
        exit
      end
    end
     
    Thats the full program...it should be easy to understand without much knowledge of Ruby. I just wanted some help with mainly the logic.

    At the moment it works well, but slightly slower than realtime (i.e if it takes 6 seconds to run the motion is only for about 4 seconds) and the simulation for the total distance i found to be about 15% less than what it should (well according to my calculations at least).

    Originally I had it runnying in realtime but that was because i just made it continually output the data even if no change had occurred, but when I wanted to create files for excel it would have tens of thousands of lines of data, so was too much (not to mention inefficient) so i added the "unless int == 0" line, which solves the problem but makes it run slower :S

    Also if you put too much impulse or use a too dense medium (e.g. water) then the initial acceleration is worked out to be very negative (as the drag force is a function of v^2) and velocity of the first sample would be negative (obviously not what would happen) so i had to just cut the simulation as if it wouldnt move in that case (otherwise it would start to move. The problem here is the sample time is too big. It seems the minimum difference between Time that Ruby can show is about 32ms...is there anyway to get that smaller?
    Also how can i improve the accuracy (the 15% loss in distance) and get it running in realtime?

    And if there are any other comments they would be much appreciated as i need some help going further with programming!
     
    Last edited: Jun 29, 2008
  2. jcsd
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook

Can you help with the solution or looking for help too?
Draft saved Draft deleted



Similar Discussions: 1D simulator (Ruby)
  1. Learning Ruby (Replies: 0)

Loading...