require 'matrix'
#Functions to calculate water/sugar solution density.
#Code ported from IGOR to Ruby
#Original code provided by ajdelange: https://www.homebrewtalk.com/showthread.php?t=531216&page=2
def water(t)
#Bettin & Spieweck equation (*1000):
return (0.99984+t*(6.7715e-05-t*(+9.0735e-06-t*(1.015e-07-t*(+1.3356e-09-t*(1.4421e-11-t*(+1.0896e-13-t*(4.9038e-16-9.7531e-19*t))))))))*1000.0
#ICUMSA equation:
#return (((((-281.03006e-12*t +105.84601e-9)*t-46.241757e-6)*t-7.9905127e-3)*t+16.952577)*t +999.83952)/(1+16.887236e-3*t)
end
=begin
################################################################################
# Generate the sugar matrices from ajdelange's code #
################################################################################
m = [0,0,0,0]
m[0] = [385.85074,-45.9244,60.198,-51.1,19.86,-13.03435,7.5699,-13.008,15.8,0,-3.6663,6.2667,-4.907,0.0,0,0,0,0,0,0]
m[1] = [382.9716,-55.1502,75.5366,-44.059,0,-23.0838,19.0140,-30.9314,0,0,0.1218,4.2741,0,0,0,-0.7704,0,0,0,4]
m[2] = [390.5399,-74.4141,81.7245,-77.138,32.396,-22.1864,15.5436,-44.6412,42.824,0,-0.0829,5.3744,4.9248,0,0,-1.7937,0,0,0,0]
m[3] = [386.7294,-64.7839,78.6570,-60.676,16.241,-22.9485,17.6392,-37.8841,21.588,0,1.7684,4.2073,2.5197,0,0,-2.3475,0,0,0,0]
for i in 0..3
m[i] = [m[i][ 0..4 ],
m[i][ 5..9 ],
m[i][10..14],
m[i][15..19]].transpose
print "c_suc = "
print m[i]
puts
end
## RESULTS:
c_suc = [[385.85074, -13.03435, -3.6663, 0], [-45.9244, 7.5699, 6.2667, 0], [60.198, -13.008, -4.907, 0], [-51.1, 15.8, 0.0, 0], [19.86, 0, 0, 0]]
c_suc = [[382.9716, -23.0838, 0.1218, -0.7704], [-55.1502, 19.014, 4.2741, 0], [75.5366, -30.9314, 0, 0], [-44.059, 0, 0, 0], [0, 0, 0, 4]]
c_suc = [[390.5399, -22.1864, -0.0829, -1.7937], [-74.4141, 15.5436, 5.3744, 0], [81.7245, -44.6412, 4.9248, 0], [-77.138, 42.824, 0, 0], [32.396, 0, 0, 0]]
c_suc = [[386.7294, -22.9485, 1.7684, -2.3475], [-64.7839, 17.6392, 4.2073, 0], [78.657, -37.8841, 2.5197, 0], [-60.676, 21.588, 0, 0], [16.241, 0, 0, 0]]
################################################################################
=end
def suc_c(c, t, mode=0, sugar=0) #default mode is density and sugar is sucrose
# m = mode
# 0 density
# 1 apparent SG t/t
# 2 true SG t/t
# 3 wt 1 cc in air
#
# sugar = the type of sugar
# 0 sucrose
# 1 glucose
# 2 fructose
# 3 invert sugar
wts = 8000
air = 1.201
case sugar
when 0
c_suc = Matrix[[385.85074, -13.03435, -3.6663, 0],
[-45.9244, 7.5699, 6.2667, 0],
[60.198, -13.008, -4.907, 0],
[-51.1, 15.8, 0.0, 0],
[19.86, 0, 0, 0]]
when 1
c_suc = Matrix[[382.9716, -23.0838, 0.1218, -0.7704],
[-55.1502, 19.014, 4.2741, 0],
[75.5366, -30.9314, 0, 0],
[-44.059, 0, 0, 0],
[0, 0, 0, 4]]
when 2
c_suc = Matrix[[390.5399, -22.1864, -0.0829, -1.7937],
[-74.4141, 15.5436, 5.3744, 0],
[81.7245, -44.6412, 4.9248, 0],
[-77.138, 42.824, 0, 0],
[32.396, 0, 0, 0]]
when 3
c_suc = Matrix[[386.7294, -22.9485, 1.7684, -2.3475],
[-64.7839, 17.6392, 4.2073, 0],
[78.657, -37.8841, 2.5197, 0],
[-60.676, 21.588, 0, 0],
[16.241, 0, 0, 0]]
end
mf = [c.to_f, 0.0, 0.0, 0.0]
for j in 1...4
mf[j] = mf[j-1]*c.to_f
end
mf = Matrix[mf].t
tau = (t.to_f-20.0)/100.0
ta = [1.0, 0.0, 0.0, 0.0, 0.0]
for j in 1...5
ta[j] = ta[j-1]*tau
end
ta = Matrix[ta]
m_product = (ta * c_suc * mf)[0,0]
acc = water(t) + m_product
case mode
when 0
return acc/1000.0
when 1
return (acc -air)/(water(t) -air)
when 2
return acc/water(t)
when 3
return acc/((1.0 + (air/wts)*(wts -acc)/(acc-air)))/1000.0
end
end
#w = percent sugar
#t = temp celsius (F-32)/1.8
def DensA(w, t, mode=0, sugar=0) #default mode density and sugar is sucrose
c1 = 0.0
c2 = 1.44009
cb = acc = 0.0
f1 = f2 = fb = dc = 0.0
tolerance = 1E-9
w += 1E-15
j = 0
#check that there is a solution between sg1 and sg2
f1 = suc_c(c1,20.0,0,sugar)*w/100.0-c1
f2 = suc_c(c2,20.0,0,sugar)*w/100.0-c2
if f1*f2 > 0
return -1
else
dc = c2 - c1
begin
cb = c1 +dc/2.0
fb = suc_c(cb,20.0,0,sugar)*w/100.0 -cb
if (f1*fb < 0) #root is between sg1 and sgb
c2 = cb
else #root is betweeb sgb abd sg2
c1 = cb
end
dc = c2 - c1
j += 1
end while ( (dc.abs > tolerance) or (j < 35) )
acc = suc_c(cb,t,mode,sugar)
return acc
end
end
puts
puts
puts (DensA(0,(70-32)/1.8)/DensA(0,(150-32)/1.8)).round(5)
puts (DensA(10,(70-32)/1.8)/DensA(10,(150-32)/1.8)).round(5)
puts (DensA(20,(70-32)/1.8)/DensA(20,(150-32)/1.8)).round(5)
puts
puts
puts (DensA(10,(150-32.0)/1.8,0,0)).round(5)
puts (DensA(10,(150-32.0)/1.8,0,1)).round(5)
puts (DensA(10,(150-32.0)/1.8,0,2)).round(5)
puts (DensA(10,(150-32.0)/1.8,0,3)).round(5)
puts
puts