From: Jason Lillywhite on 28 May 2010 11:20 Here is my attempt at Newton's second law in Ruby: #c is the drag coefficent #m is mass #t is total time elapsed #dt is time increment #vi is the starting velocity G = 9.8 def velocity(c, m, t, dt, vi) vel = [] t += dt steps = t/dt steps.times do v = vi vi = v + ( G - c/m*v) * dt vel << v end return vel end Is there a better way to do write this function? It seems pretty straight forward to me so I guess that might be a sign that it is fine the way it is...? What if I needed more speed but still wanted it in Ruby? Thank you! -- Posted via http://www.ruby-forum.com/.
From: Robert Klemme on 28 May 2010 14:01 On 28.05.2010 17:20, Jason Lillywhite wrote: > def velocity(c, m, t, dt, vi) > vel = [] > t += dt > steps = t/dt > > steps.times do > v = vi > vi = v + ( G - c/m*v) * dt > vel<< v > end > return vel > end > Just a slight improvement def velocity(c, m, t, dt, vi) vel = [] (t/dt + 1).times do vel << vi vi += ( G - c/m*v) * dt end vel end You could also do def velocity(c, m, t, dt, vi) (t/dt + 1).times do yield vi vi += ( G - c/m*v) * dt end end and use it with a block. Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/
From: Caleb Clausen on 28 May 2010 14:39 On 5/28/10, Jason Lillywhite <jason.lillywhite(a)gmail.com> wrote: > Here is my attempt at Newton's second law in Ruby: > > #c is the drag coefficent > #m is mass > #t is total time elapsed > #dt is time increment > #vi is the starting velocity > > G = 9.8 > > def velocity(c, m, t, dt, vi) > vel = [] > t += dt > steps = t/dt > > steps.times do > v = vi > vi = v + ( G - c/m*v) * dt > vel << v > end > return vel > end > > Is there a better way to do write this function? It seems pretty > straight forward to me so I guess that might be a sign that it is fine > the way it is...? > > What if I needed more speed but still wanted it in Ruby? A couple small speedups. c/m never changes while the loop is running, so compute it once when the loop starts, then reuse the value. And you could replace the times loop by a while loop for another small speedup.... but this is never going to be fast in ruby. If you want fast, use C.
From: Joel VanderWerf on 28 May 2010 16:08 Jason Lillywhite wrote: > What if I needed more speed but still wanted it in Ruby? Not quite pure ruby, but if it's acceptable to have a C backend, then you can use redshift. On my computer, if I create 20K of the objects below, they run (concurrently) at about "real" time, i.e. 1 sec process time per 1 sec simulation time. Also, it is more accurate than your integration algorithm, since it uses a higher-order Runge-Kutta integrator. Plus, there are other features suitable for discrete/continuous multi-agent simulation (algebraic equations, discrete state transitions, event synchronization, queues with pattern-matching like Erlang, dataflow ports like Simulink, link variables, delay flows, differentiation, interactive shell and debuggers, ...). If you want to try this, unpack this tarball: http://path.berkeley.edu/~vjoel/redshift/redshift-1.3.14.tgz and put the lib dir on your RUBYLIB. Some of the examples expect gnuplot to be installed, but otherwise there are no deps. However, you must be able to build extensions, i.e, have a working C compiler that is binary compatible with your ruby (gcc, msvc, and solaris work for me), so that redshift can translate the equations into C and compile them into ruby extensions. If native gems build on your system, you should be ok. Note that the first time you run a particular redshift program, there is a delay while this build happens (the build goes into a tmp dir under the current dir). ----- require 'redshift' class Thing < RedShift::Component continuous :v, :x constant :m, :c, :G # per-instance constants flow do # "differential" means Runge-Kutta 4th order integration; if # you replace that word with "euler", it uses forward Euler # integration, which gives exactly the same results as the # original poster's example. Usually, RK4 is significantly # more accurate than Euler. differential " v' = G - c/m * v " # just for fun, let's keep track of distance traveled differential " x' = v " end end world = RedShift::World.new world.time_step = 0.1 thing = world.create Thing thing.m = 10 thing.c = 0.01 thing.v = 0 thing.x = 0 thing.G = 9.8 p thing world.evolve 5.0 do p thing end __END__ Output: <<Thing 0>: Enter; G = 9.8, c = 0.01, m = 10.0; v = 0.0, x = 0.0> <<Thing 0>: Enter; G = 9.8, c = 0.01, m = 10.0; v = 0.979951001633293, x = 0.0489983667075> <<Thing 0>: Enter; G = 9.8, c = 0.01, m = 10.0; v = 1.95980401306601, x = 0.195986933986642> ... ... <<Thing 0>: Enter; G = 9.8, c = 0.01, m = 10.0; v = 47.9025429248678, x = 117.457075132208> <<Thing 0>: Enter; G = 9.8, c = 0.01, m = 10.0; v = 48.8777039117133, x = 122.296088286671>
From: Jason Lillywhite on 2 Jun 2010 14:40
Joel VanderWerf wrote: >snip Thank you Joel. is this redshift you introduced to me the same thing as http://sourceforge.net/projects/redshift/ ?? -- Posted via http://www.ruby-forum.com/. |