From: Jason Lillywhite on
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
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
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
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
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/.