improved
This commit is contained in:
parent
a9bf59c08f
commit
5ff3c2f57b
156
src/main.moon
156
src/main.moon
@ -23,104 +23,112 @@ class Isotopes
|
||||
return @randoms[i]
|
||||
generate: (z, n) =>
|
||||
@[z] = {} unless @[z]
|
||||
isotope = {}
|
||||
isotope = { :z, :n }
|
||||
|
||||
-- isotopes only exist in this range
|
||||
if n/z > 0.9 and n/z < 1.2
|
||||
v = 2 / math.abs(n - z) -- base stability is proximity to n == z
|
||||
-- v /= @rng\randomNormal 0.25, 1 -- a slight random variation
|
||||
v /= @normal(z, n)
|
||||
local odd_even -- based on statistics from real isotopes
|
||||
if z % 2 == 0
|
||||
if n % 2 == 0
|
||||
odd_even = 0.6
|
||||
else
|
||||
odd_even = 0.205
|
||||
else
|
||||
if n % 2 == 0
|
||||
odd_even = 0.18
|
||||
else
|
||||
odd_even = 0.015
|
||||
-- if @rng\random! <= v * odd_even -- more random variation based on stats
|
||||
if @random(z, n) <= v * odd_even
|
||||
v *= odd_even
|
||||
if v > 1 -- maximum stability should be close to 1
|
||||
v = 1.05
|
||||
v -= z / 1000 -- lighter elements should have a higher stability
|
||||
isotope.stability = v
|
||||
if n/z > 0.88 and n/z < 1.15
|
||||
lower_const = 16.5 -- aiming for 1e-16 (0.1 femtoseconds) minimum half life
|
||||
upper_const = 1e18 -- aiming for 1e17 (3 billion years) maximum half life (besides pure stability)
|
||||
v = math.abs(z - n)^lower_const / upper_const
|
||||
v = math.abs v / @normal(z, n)
|
||||
odd_even = { [0]: { [0]: 0.6, 0.205 }, { [0]: 0.18, 0.015 } }
|
||||
c = odd_even[z % 2][n % 2]
|
||||
if @random(z, n) <= v * c
|
||||
v *= c
|
||||
v = math.abs v - z / 1e17
|
||||
if @random(z, n) < 0.5
|
||||
v *= 2
|
||||
-- if v < 1 and @normal(z, n) < z / 200
|
||||
-- v = v^0.001
|
||||
if v < 1 and z + n > @normal(z, n) * 280
|
||||
v = v^0.3
|
||||
-- if v < 1 and z + n > @normal(n, z) * 400
|
||||
-- v = v^0.1
|
||||
isotope.decay = v
|
||||
else
|
||||
isotope.stability = 0 -- this isotope cannot exist
|
||||
isotope.decay = math.huge
|
||||
|
||||
if isotope.stability < 1
|
||||
isotope.half_life = 0.69314718056 / (1 - isotope.stability)
|
||||
-- isotope.half_life = 0.69314718056 / isotope.stability
|
||||
if isotope.decay < math.huge
|
||||
isotope.half_life = 0.69314718056 / isotope.decay
|
||||
-- print isotope.half_life
|
||||
else
|
||||
isotope.half_life = math.huge
|
||||
isotope.half_life = 0
|
||||
|
||||
m = z + n
|
||||
e = 14 - 13 / m^(1/3) - 0.585 * z^2 / m^(4/3) - 19.3 * (n - z)^2 / m^2
|
||||
if z % 2 != 0 and n % 2 != 0
|
||||
e -= 33 / m^(7/4)
|
||||
else
|
||||
e += 33 / m^(7/4)
|
||||
|
||||
isotope.binding_energy = math.abs e
|
||||
-- verified "accuracy"
|
||||
-- if isotope.half_life > 1 and m < 10
|
||||
-- print math.floor(e * 100)/100, m, z, n
|
||||
|
||||
@[z][n] = isotope
|
||||
|
||||
-- Z > 82 -> unstable
|
||||
-- Z <= 20 -> stable n/p is nearly 1 (0.775 - 1.29)
|
||||
-- Z > 20 & Z <= 82 -> stable n/p between 1:1 and 1.5:1
|
||||
-- Z > 92 -> spontaneous fission
|
||||
-- Z > 52 -> alpha rays possible
|
||||
-- Can induce fission by neutron bombardment.
|
||||
|
||||
-- Decay types
|
||||
-- Spontaneous: Splits in half + extra neutrons, Z > 92
|
||||
-- Too many neutrons -> beta decay, neutron emission
|
||||
-- Too few neutrons -> electron capture, positron emission, proton emission
|
||||
-- Alpha: Emits 2Z-2N
|
||||
-- Beta: Emits e, 1N -> 1Z
|
||||
-- Beta: Emits e-, 1N -> 1Z
|
||||
-- Electron capture & Positron emission: Emits e+, 1Z -> 1N
|
||||
-- (difference: positron emission uses its own electron, electron capture steals one)
|
||||
|
||||
export showUnstable = true
|
||||
w, h = love.graphics.getDimensions!
|
||||
scale = 6
|
||||
|
||||
isotopes = Isotopes!
|
||||
|
||||
love.load = ->
|
||||
above_0 = 0
|
||||
above_1 = 0
|
||||
min_half_life = math.huge
|
||||
max_half_life = 0
|
||||
min_z, min_n = 0, 0
|
||||
max_z, max_n = 0, 0
|
||||
min_s = 0
|
||||
max_s = 0
|
||||
for z = 1, w
|
||||
for n = 0, h
|
||||
shortest = { half_life: math.huge }
|
||||
longest = { half_life: -math.huge }
|
||||
heaviest = { z: 0, n: 0 }
|
||||
for z = 1, w / scale
|
||||
for n = 0, h / scale
|
||||
isotope = isotopes\get z, n
|
||||
if isotope.stability > 0
|
||||
above_0 += 1
|
||||
if isotope.half_life < min_half_life
|
||||
min_half_life = isotope.half_life
|
||||
min_z = z
|
||||
min_n = n
|
||||
min_s = isotope.stability
|
||||
if isotope.stability < 1
|
||||
if isotope.half_life > max_half_life
|
||||
max_half_life = isotope.half_life
|
||||
max_z = z
|
||||
max_n = n
|
||||
max_s = isotope.stability
|
||||
else
|
||||
above_1 += 1
|
||||
print "#{above_0} isotopes", "#{above_1} stable isotopes"
|
||||
print "Shortest half life:", "#{min_half_life}", "#{min_z}P#{min_n}N", min_s
|
||||
print "Longest half life:", "#{max_half_life}", "#{max_z}P#{max_n}N", max_s
|
||||
|
||||
-- decay constant (probability of decay per second): 1 - stability
|
||||
-- half life: 0.69314718056 / decay constant
|
||||
-- I have redefined stability to equal the decay constant
|
||||
if isotope.half_life > 1e15 and isotope.z + isotope.n > heaviest.z + heaviest.n
|
||||
heaviest = isotope
|
||||
if isotope.half_life < shortest.half_life and isotope.half_life != 0
|
||||
shortest = isotope
|
||||
elseif isotope.half_life > longest.half_life and isotope.half_life != math.huge
|
||||
longest = isotope
|
||||
print "Shortest half life: #{shortest.half_life}", "#{shortest.z}P#{shortest.n}N", "Decay: #{shortest.decay}"
|
||||
print "Longest half life: #{longest.half_life}", "#{longest.z}P#{longest.n}N", "Decay: #{longest.decay}"
|
||||
print "Heaviest stable: #{heaviest.z}P#{heaviest.n}N", "#{heaviest.z + heaviest.n}"
|
||||
|
||||
love.draw = ->
|
||||
scale = 3
|
||||
for z = 1, w
|
||||
for n = 0, h
|
||||
for z = 1, w / scale
|
||||
for n = 0, h / scale
|
||||
isotope = isotopes\get z, n
|
||||
s = isotope.stability
|
||||
if s >= 1 or showUnstable
|
||||
-- c = 1 - s -- side effect -> stable isotopes are now invisible
|
||||
love.graphics.setColor s, s, s, 1
|
||||
love.graphics.rectangle "fill", (z - 1) * scale, (h / scale - n - 1) * scale, scale, scale
|
||||
-- s = math.log 1 / isotope.decay
|
||||
-- love.graphics.setColor s, s, s, 1
|
||||
colors = {
|
||||
{0, {0, 0, 0, 1}}, -- non-existent, black
|
||||
{0.01, {0.1, 0.1, 0.1, 1}}, -- hundredth and less, dark grey
|
||||
{1, {0, 0, 1, 1}}, -- hundredth to second, blue
|
||||
{60, {0, 1, 1, 1}}, -- second to minute, teal
|
||||
{60*60, {0, 0.5, 0, 1}}, -- minute to hour, dark green
|
||||
{60*60*24, {0.2, 1, 0.2, 1}}, -- hour to day, light green
|
||||
{60*60*24*7, {1, 1, 0, 1}}, -- day to week, yellow
|
||||
{60*60*24*30, {1, 0.5, 0, 1}}, -- week to month, orange
|
||||
{60*60*24*365, {1, 0, 0, 1}}, -- month to year, red
|
||||
{60*60*24*365*100, {1, 0.5, 0.5, 1}}, -- year to century, pink
|
||||
{1e15, {0.8, 0.8, 0.8, 1}} -- century to 31 million years, light grey
|
||||
{math.huge, {1, 1, 1, 1}} -- purely stable, white
|
||||
}
|
||||
for color in *colors
|
||||
if isotope.half_life <= color[1]
|
||||
love.graphics.setColor color[2]
|
||||
break
|
||||
-- if z == n -- NOTE temp
|
||||
-- love.graphics.setColor 1, 0, 0, 1
|
||||
love.graphics.rectangle "fill", (z - 1) * scale, (h / scale - n - 1) * scale, scale, scale
|
||||
|
||||
love.keypressed = (key) ->
|
||||
love.event.quit! if key == "escape"
|
||||
|
Loading…
Reference in New Issue
Block a user