This commit is contained in:
Tangent Fox 2018-10-01 09:12:32 -07:00
commit de08e7d87d
4 changed files with 296 additions and 0 deletions

112
Fluid.lua Normal file
View File

@ -0,0 +1,112 @@
local Fluid
do
local _class_0
local _base_0 = {
update = function(self, dt)
local leak = 0
local _list_0 = self.breaches
for _index_0 = 1, #_list_0 do
local breach = _list_0[_index_0]
local rate = (self.pressure - breach.pressure) * (breach.size / self.volume) * dt
leak = leak + rate
breach.pressure = breach.pressure + (rate * (self.volume / breach.volume))
if breach.pressure < 0 then
breach.pressure = 0
end
local amount = breach.pressure * breach.volume
local modifier = 1 - self.volume * rate / amount
for item, percentage in pairs(breach.contents) do
breach.contents[item] = percentage * modifier
end
for item, percentage in pairs(self.contents) do
percentage = (self.volume * rate * percentage) / amount
if breach.contents[item] then
breach.contents[item] = breach.contents[item] + percentage
else
breach.contents[item] = percentage
end
end
end
self.pressure = self.pressure - leak
for i = 1, #self.breaches do
if self.breaches[i].pressure > self.pressure then
local other = table.remove(self.breaches, i)
other:breach(self, other.size)
i = i - 1
end
end
end,
amount = function(self, key)
if key then
if self.contents[key] then
return self.volume * self.pressure * self.contents[key]
else
return 0
end
else
return self.volume * self.pressure
end
end,
remove = function(self, key, amount)
if amount == nil then
amount = 1
end
local total = self:amount(key)
if total >= amount then
local percentage = amount / total
self.contents[key] = self.contents[key] - (self.contents[key] * percentage)
percentage = amount / self:amount()
self.pressure = self.pressure - (self.pressure * percentage)
for item, p in pairs(self.contents) do
self.contents[item] = self.contents[item] + (p * percentage)
end
return true
else
return false
end
end,
breach = function(self, other, size)
if other.pressure > self.pressure then
return other:breach(self, size)
else
other.size = size or 1
return table.insert(self.breaches, other)
end
end,
print = function(self)
print("Volume", self.volume, "Pressure", self.pressure, "#", self:amount())
local percentage, amount = 0, 0
for k, v in pairs(self.contents) do
local x = self:amount(k)
print(k, v, x)
percentage = percentage + v
amount = amount + x
end
return print("", "Total:", percentage, amount)
end
}
_base_0.__index = _base_0
_class_0 = setmetatable({
__init = function(self, opts)
if opts == nil then
opts = { }
end
self.volume = opts.volume or 1
self.pressure = opts.pressure or 1
self.contents = opts.contents or { }
self.breaches = { }
end,
__base = _base_0,
__name = "Fluid"
}, {
__index = _base_0,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
Fluid = _class_0
return _class_0
end

77
Fluid.moon Normal file
View File

@ -0,0 +1,77 @@
-- it is up to user to ensure that total breached volume is lower
-- than the total volume
class Fluid
new: (opts={}) =>
@volume = opts.volume or 1
@pressure = opts.pressure or 1
@contents = opts.contents or {}
-- breaches stored on high pressure side of Fluids
@breaches = {}
update: (dt) =>
leak = 0 -- total leak rate (pressure)
for breach in *@breaches
-- difference in pressure * relative size of hole
rate = (@pressure - breach.pressure) * (breach.size / @volume) * dt
leak += rate
breach.pressure += rate * (@volume / breach.volume)
breach.pressure = 0 if breach.pressure < 0
amount = breach.pressure * breach.volume
modifier = 1 - @volume * rate / amount
for item, percentage in pairs breach.contents
breach.contents[item] = percentage * modifier
for item, percentage in pairs @contents
percentage = (@volume * rate * percentage) / amount
if breach.contents[item]
breach.contents[item] += percentage
else
breach.contents[item] = percentage
@pressure -= leak
for i = 1, #@breaches
if @breaches[i].pressure > @pressure
other = table.remove @breaches, i
other\breach(@, other.size)
i -= 1
amount: (key) =>
if key
if @contents[key]
return @volume * @pressure * @contents[key]
else
return 0
else
return @volume * @pressure
remove: (key, amount=1) =>
total = @amount key
if total >= amount
percentage = amount / total
@contents[key] -= @contents[key] * percentage
percentage = amount / @amount!
@pressure -= @pressure * percentage
for item, p in pairs @contents
@contents[item] += p * percentage
return true
else
return false
breach: (other, size) =>
if other.pressure > @pressure
other\breach(@, size)
else
other.size = size or 1
table.insert @breaches, other
print: =>
print "Volume", @volume, "Pressure", @pressure, "#", @amount!
percentage, amount = 0, 0
for k,v in pairs @contents
x = @amount k
print k, v, x
percentage += v
amount += x
print "", "Total:", percentage, amount

65
test.lua Normal file
View File

@ -0,0 +1,65 @@
local Fluid = require("Fluid")
local copy
copy = function(tab)
local new = { }
for k, v in pairs(tab) do
new[k] = v
end
return new
end
local air = {
nitrogen = 0.775,
oxygen = 0.21,
argon = 0.01,
co2 = 0.005
}
local A = Fluid({
volume = 32,
pressure = 12,
contents = copy(air)
})
local B = Fluid({
volume = 1100,
pressure = 2,
contents = {
hydrogen = 0.9,
helium = 0.1
}
})
A:print()
B:print()
A:breach(B, 5)
A:update(1)
B:update(1)
A:print()
B:print()
print("...")
local Air = Fluid({
volume = 1000,
pressure = 1,
contents = copy(air)
})
local Vacuum = Fluid({
volume = math.huge,
pressure = 0
})
Air:breach(Vacuum)
for i = 1, 10 do
Air:print()
Air:update(i)
end
print("...")
Air = Fluid({
volume = 1000,
pressure = 1,
contents = copy(air)
})
Air:print()
local half = Air:amount("oxygen") / 2
print("Removing half the oxygen (" .. tostring(half) .. ").")
Air:remove("oxygen", half)
Air:print()
local full = Air:amount("oxygen")
print("Removing the rest (" .. tostring(full) .. ").")
Air:remove("oxygen", full)
return Air:print()

42
test.moon Normal file
View File

@ -0,0 +1,42 @@
Fluid = require "Fluid"
copy = (tab) ->
new = {}
for k,v in pairs tab
new[k] = v
return new
air = { nitrogen: 0.775, oxygen: 0.21, argon: 0.01, co2: 0.005 }
A = Fluid volume: 32, pressure: 12, contents: copy air
B = Fluid volume: 1100, pressure: 2, contents: { hydrogen: 0.9, helium: 0.1 }
A\print!
B\print!
A\breach(B, 5)
A\update 1
B\update 1
A\print!
B\print!
print "..."
Air = Fluid volume: 1000, pressure: 1, contents: copy air
Vacuum = Fluid volume: math.huge, pressure: 0
Air\breach Vacuum
for i = 1, 10
Air\print!
Air\update i
print "..."
Air = Fluid volume: 1000, pressure: 1, contents: copy air
Air\print!
half = Air\amount("oxygen") / 2
print "Removing half the oxygen (#{half})."
Air\remove "oxygen", half
Air\print!
full = Air\amount "oxygen"
print "Removing the rest (#{full})."
Air\remove "oxygen", full
Air\print!