Code: from numpy import * from imsl.math.linLsqLinConstraints import linLsqLinConstraints from imsl.math.writeMatrix import writeMatrix from imsl.math.vectorNorm import vectorNorm #Replace the values in base_water with your water profile base_water = [26.0, 3.6, 13.2, 28.0, 12.2, 68] #################Values taken from ProMash################ burton_on_trent = [268., 62., 30., 638., 36., 141.] calistoga_mineral = [11.1, 62., 30., 638., 36., 141.] distilled_water = [0.,0.,0.,0.,0.,0.] dortmund = [260.,23.,69.,240.,206.,270.] dublin = [118., 4., 12., 54., 19., 319.] edinburgh = [140., 36., 92., 231., 60., 270.] london = [90., 4., 24., 58., 18., 123.] marin_county_ca = [12., 10., 15., 17., 13., 74.] munich = [76., 18., 1., 10., 2., 152.] pilsen = [7., 3., 3.2, 5.8, 5., 9.] vienna = [200., 60., 8., 125., 12., 120.] yorkshire = [105., 17., 23., 66., 30., 153.] ########################################################### target = burton_on_trent #Salt contents (PPM / (grams per gallon)) caso4 = [61.5, 0.0, 0.0, 147.4, 0.0, 0.0] mgso4 = [0.0, 26.1, 0.0, 103.0, 0.0, 0.0] nacl = [0.0, 0.0, 103.9, 0.0, 160.3, 0.0] nahco3 = [0.0, 0.0, 72.0, 0.0, 0.0, 189.0] cacl2 = [72.0, 0.0, 0.0, 0.0, 127.4, 0.0] caco3 = [105.8, 0.0, 0.0, 0.0, 0.0, 158.4] # The overall goal here is to find x ST: # Ax =~ b # x >= 0 a = transpose([caso4, mgso4, nacl, nahco3, cacl2, caco3]) b = array(target) - array(base_water) xlb = [0.] * 6 xub = [-1.0e30] * 6 c = [] con_type = [] bu = [] bl = [] residual = [] x = linLsqLinConstraints(a, b, c, bl, bu, con_type, xlb, xub, residual=residual) ion_labels = ['', 'Ca', 'Mg', 'Na', 'SO4', 'Cl', 'HCO3'] salt_labels = ['', 'CaSO4', 'MgSO4', 'NaCl', 'NaHCO3', 'CaCl2', 'CaCO3'] writeMatrix("Salt amounts to add

(Grams per Gallon)", x, colLabels=salt_labels) writeMatrix("Target Profile

(PPM)", target, colLabels=ion_labels) writeMatrix("Base Water + Recomended Salt Additions

(PPM)", dot(a,x) + array(base_water), colLabels=ion_labels) writeMatrix("Residuals

(PPM)", residual, colLabels=ion_labels) print ("

Norm of residual = %f" % (vectorNorm(residual)))

Code: [email protected]:~/Desktop$ python water.py Salt amounts to add (Grams per Gallon) CaSO4 MgSO4 NaCl NaHCO3 CaCl2 CaCO3 2.888 1.817 0.106 0.000 0.083 0.489 Target Profile (PPM) Ca Mg Na SO4 Cl HCO3 268 62 30 638 36 141 Base Water + Recomended Salt Additions (PPM) Ca Mg Na SO4 Cl HCO3 261.3 51.0 24.2 640.8 39.8 145.5 Residuals (PPM) Ca Mg Na SO4 Cl HCO3 -6.67 -10.98 -5.81 2.78 3.77 4.45 Norm of residual = 15.513117

I wrote this script to calculate the optimal amount of brewing salts to add to your water profile to end up with a target profile. I grabbed most of my numbers from ProMash, and so far this seems to be working well for me.It is a python script, so you'll need the python interpreter with numpy, and the PyIMSL numerical libraries (freely available here: http://www.imslaps.com/products/imsl/pyimsl/ Here's a run calculating additions from my water to Burton on Trent. Plugging these numbers back into ProMash I get these exact totals.Hope somebody finds this useful!