v1
This commit is contained in:
commit
de08e7d87d
112
Fluid.lua
Normal file
112
Fluid.lua
Normal 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
77
Fluid.moon
Normal 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
65
test.lua
Normal 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
42
test.moon
Normal 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!
|
Loading…
Reference in New Issue
Block a user