Page 1 of 1

A variable star (limited) simulation script

Posted: 30.05.2004, 20:46
by Toti
Hello,

This script simulates the size shift of a periodic variable star (48 Aurigae).
It uses a B-Spline to fit the star's radius vs. time data points into a smoother curve.

Unfortunately, star brightness and temperature can't be changed from within LUA, so this aspects weren't modelled.

The visual simulation has been exaggerated 5 times in order to make the effect more visible. Please change FACTOR to 1 in the code below. This will show you the real scale of this phenomenon.
The displayed values for radius are real, though.

Code: Select all

--***************************************************************************
--***************************************************************************
--          An open-uniform B-Spline approximation algorithm
--         Applied to (limited) Variable Star Simulation
--
--               Coded by Toti   
--         
--***************************************************************************
--***************************************************************************

--***************************************************************************
--               Constants
--***************************************************************************
STAR      = "48 Aur"
PERIOD   = 3                  -- period of this star's light curve
DISTANCE   = 12                  -- * mean star's radius

FACTOR   = 5                  -- for a more realistic view, this must be 1
ITERATIONS   = 100

KM_MLY   = 9466411.842
KM_AU      = 149597870.7

TIMESPEED   = 100000
ANGSPEED   = 0.25

UP      = celestia:newvector (0, 1, 0)
OBS      = celestia:getobserver()

ORDER      = 4                  -- order of the curve. Increase for additional smoothness
            
VARIAB   = {   { 0.000,  -310000   ,  0},   -- Control points, in the form (phase, delta Radius, 0)
         { 0.040,   -90000   ,  0},   -- data extracted from http://mb-soft.com/public2/cepheid.html
         { 0.080,   116000   ,  0},   
         { 0.120,   300000   ,  0},   
         { 0.160,   459000   ,  0},
         { 0.200,   589000   ,  0},
         { 0.240,   689000   ,  0},
         { 0.280,   760000   ,  0},   
         { 0.320,   801000   ,  0},
         { 0.360,   814000   ,  0},
         { 0.400,   798000   ,  0},   
         { 0.440,   753000   ,  0},
         { 0.480,   682000   ,  0},
         { 0.520,   582000   ,  0},
         { 0.560,   455000   ,  0},
         { 0.600,   300000   ,  0},
         { 0.640,   121000   ,  0},
         { 0.680,   -80000   ,  0},   
         { 0.720,  -293000   ,  0},
         { 0.760,  -506000   ,  0},
         { 0.800,  -689000   ,  0},   
         { 0.840,  -801000   ,  0},
         { 0.880,  -806000   ,  0},
         { 0.920,  -702000   ,  0},
         { 0.960,  -524000   ,  0},
         { 1.000,  -310000   ,  0}   }


-- *********************************************************
--            B-Spline functions
-- *********************************************************
function buildKnots (ord, size)
-- builds a table of open-uniform knots
   local j
   local K   = {}
   local kn   = size + ord
   local step   = size / (size - ord + 1)
   for j = 1, kn do
      if j <= ord then
         K[j]   = 0
      elseif j > size then
         K[j]   = size
      else
         K[j]   = (j - ord) * step
      end
   end
   return K, size
end

function N (K, i, ord, curr)
-- returns the blending factor for 'curr' position along the curve, using 'K' as knot vector. Uses recursion
   local blend
   if ord == 1 then                              -- definition 1st case
      if K[i] <= curr and curr < K[i+1] then
         blend   = 1
      else
         blend   = 0
      end
   else
      local k1   = i+ord-1
      local k2   = i+ord
      if  K[k1] == K[i] and K[k2] == K[i+1] then            -- be careful with 'division by zero' errors
         blend   = 0
      elseif K[k1] == K[i] then
         blend   = (K[k2] - curr)  / (K[k2] - K[i+1]) * N(K, i+1, ord-1, curr)
      elseif K[k2] == K[i+1] then
         blend   = (curr - K[i]) / (K[k1] - K[i]) * N(K, i, ord-1, curr)
      else                                 -- definition 2nd case
         blend   = (curr - K[i]) / (K[k1] - K[i]) * N(K, i, ord-1, curr) + (K[k2] - curr) / (K[k2] - K[i+1]) *  N(K, i+1, ord-1, curr)
      end
   end
   return blend
end

function buildSpline (K, CP, rows, cols, ord, curr)
-- returns the B-Spline n-tuple value for 'curr' position in knot vector K
   local i, j
   local S   = {}
   for j = 1, cols do
      S[j]   = 0
   end   
   for i = 1, rows do
      local w   = N(K, i, ord, curr)
      for j = 1, cols do
         S[j]   = CP[i][j] * w + S[j]
      end
   end
   return S
end

--***************************************************************************
--               Other functions
--***************************************************************************
function sphe2cart (rad, rho, phi)
-- converts from spherical to cartesian coordinates. Returns a POSITION
   local   r   = rad / KM_MLY
   local x   = - r * math.cos (math.rad (rho)) * math.cos (math.rad (phi))
   local y   = r * math.sin (math.rad (phi))
   local z   = r * math.sin (math.rad (rho)) * math.cos (math.rad (phi))
   return celestia:newposition (x,y,z)
end

--***************************************************************************
--               Main routine
--***************************************************************************
tableSize   = table.getn (VARIAB)
datumSize   = table.getn (VARIAB[1])

Knots      = buildKnots (ORDER, tableSize)      

star      = celestia:find (STAR)
celestia:select (star)

starName   = star:name()
starRadius   = star:radius()
solRadius   = celestia:find ("Sol"):radius()

dist      = DISTANCE * starRadius

startDate   = celestia:gettime()
celestia:settimescale (TIMESPEED)
celestia:settime (startDate)
t1      = 0

for iteration = 0, ITERATIONS do

   repeat

      starPos   = star:getposition()      -- is the star moving?

      t1Rel      = t1 / PERIOD * tableSize

      rad      = buildSpline (Knots, VARIAB, tableSize, datumSize, ORDER, t1Rel)[2]
   
      numberRad   = rad + starRadius      -- radius for numeric display
      visualRad   = rad * FACTOR + starRadius   -- radius for visual display

      -- slow rotation around the star:
      radPos   = dist - visualRad
      phi      = ANGSPEED * celestia:getscripttime()  -- a short way to avoid big numbers unstability
      theta      = -45

      obsPos   = sphe2cart (radPos, phi, theta) + starPos
      OBS:setposition (obsPos)
      OBS:lookat (starPos, UP)
   
      celestia:flash (string.format("%s's radius: \n    %5.3f AU\n    %5.1f RSun\n    %5.1f percent of mean radius ", starName, numberRad/KM_AU, numberRad/solRadius, numberRad/starRadius*100), 5)

      wait()

      t1   = celestia:gettime() - startDate   -- put this here so old computers (like mine) can run the code fine

   until t1 >= PERIOD

   t1      = t1 - PERIOD            -- cut leftovers
   startDate   = startDate + PERIOD

end

celestia:flash ("That was all!", 5)
celestia:settimescale (1)


EDIT: should be numerically stable now

Please report bugs, sugestions and comments here.

Bye :)

Posted: 05.06.2004, 08:02
by don
Been working on other things. Can't wait to get back to some Celestia scripting and trying out all these new scripts!

Posted: 12.06.2004, 06:41
by don
Very nice simulation Toti! :D

To make it even clearer, I edited the Celestia flare.jpg file, set the entire image to black, renamed the original file, and saved the new one as flare.jpg. When Celestia is run, it has the effect of removing the flare. :)

Keep up the great scripting work!

Posted: 12.06.2004, 13:42
by ElPelado
Sorry, but how do I save the script to open it with celestia?

Posted: 13.06.2004, 00:52
by don
* Copy all the text in the "code" section.

* Paste it into a new plain text file.

* Save the file as <filename>.celx, where you create the <filename> yourself.

* Use File / Open Script in Celestia.

Posted: 13.06.2004, 09:11
by ElPelado
Thank you. I didnt know what to put after the ".", now i know its celx :)

EDIT: Sorry, but after saving it, I run it on celestia... but nothing happens.... do I have to press a button to start the srcipt? Or maybe my celestia version is old?(I am still using pre11...)

Posted: 13.06.2004, 17:17
by don
You're welcome El Pelado. Not sure what Celestia version is required. I'm using the current pre-release, 1.3.2 p8 (http://shatters.net/forum/viewtopic.php?t=5072).

Posted: 26.06.2004, 05:36
by Toti
don wrote:Very nice simulation Toti! :D

I am glad that you liked it, Don.
While coding another project (a wind simulator that I expect to finish someday), I had this idea of applying the spline routines that I was writing to variable stars. In the middle of the task I realized that due to the way Celestia is written, changing ambient light (with setambient()) wouldn't have any effect on a star's brightness, so this became a serious limitation. :(

A related note: 48 AUR's radius vs. time data was taken from http://mb-soft.com/public2/cepheid.html (as acknowledged in the script code)

Bye