diff -r 74b442eae07b -r 4bb005694ce7 www/js/prod_edit.js --- a/www/js/prod_edit.js Sun Apr 26 10:36:38 2020 +0200 +++ b/www/js/prod_edit.js Fri May 01 11:56:24 2020 +0200 @@ -1064,25 +1064,25 @@ case 'Melkzuur': $('#wa_acid_name').val(0); $('#wa_acid').val(row.m_amount * 1000); - $('#wa_acid_perc').val(80); + $('#wa_acid_perc').val(AcidTypeData[0].AcidPrc); // TODO: this ignores changed percentages. last_acid = 'Melkzuur'; break; case 'Zoutzuur': $('#wa_acid_name').val(1); $('#wa_acid').val(row.m_amount * 1000); - $('#wa_acid_perc').val(80); + $('#wa_acid_perc').val(AcidTypeData[1].AcidPrc); last_acid = 'Zoutzuur'; break; case 'Fosforzuur': $('#wa_acid_name').val(2); $('#wa_acid').val(row.m_amount * 1000); - $('#wa_acid_perc').val(80); + $('#wa_acid_perc').val(AcidTypeData[2].AcidPrc); last_acid = 'Fosforzuur'; break; case 'Zwavelzuur': $('#wa_acid_name').val(3); $('#wa_acid').val(row.m_amount * 1000); - $('#wa_acid_perc').val(80); + $('#wa_acid_perc').val(AcidTypeData[3].AcidPrc); last_acid = 'Zwavelzuur'; break; case 'NaHCO3': @@ -2794,22 +2794,13 @@ return Z - (Calc / 3.5 + Magn / 7); } - function ProtonDeficit(pHZ) { - - var rows, i, C1, ebc, x, Result = ZRA(pHZ) * parseFloat($('#wg_amount').jqxNumberInput('decimal')); - // proton deficit for the grist - if ((rows = $('#fermentableGrid').jqxGrid('getrows'))) { - for (i = 0; i < rows.length; i++) { - row = rows[i]; - if (row.f_added == 0 && row.f_graintype != 6) { // Added == Mash && graintype != No Malt - // Check if acid is required - C1 = 0; - if ((row.f_di_ph != 5.7) && ((row.f_acid_to_ph_57 < - 0.1) || (row.f_acid_to_ph_57 > 0.1))) { - C1 = row.f_acid_to_ph_57 / (row.f_di_ph - 5.7); - } else { + function BufferCapacity(di_ph, acid_to_ph_57, ebc, graintype) { + C1 = 0; + if ((di_ph != 5.7) && ((acid_to_ph_57 < - 0.1) || (acid_to_ph_57 > 0.1))) { + C1 = acid_to_ph_57 / (di_ph - 5.7); + } else { // If the acid_to_ph_5.7 is unknown from the maltster, guess the required acid. - ebc = row.f_color; - switch (row.f_graintype) { + switch (graintype) { case 0: // Base, Special, Kilned case 3: case 5: C1 = 0.014 * ebc - 34.192; @@ -2821,7 +2812,19 @@ case 4: C1 = -149; // Sour malt break; } - } + } + return C1; + } + + function ProtonDeficit(pHZ) { + + var rows, i, C1, x, Result = ZRA(pHZ) * parseFloat($('#wg_amount').jqxNumberInput('decimal')); + // proton deficit for the grist + if ((rows = $('#fermentableGrid').jqxGrid('getrows'))) { + for (i = 0; i < rows.length; i++) { + row = rows[i]; + if (row.f_added == 0 && row.f_graintype != 6) { // Added == Mash && graintype != No Malt + C1 = BufferCapacity(row.f_di_ph, row.f_acid_to_ph_57, row.f_color, row.f_graintype); x = C1 * (pHZ - row.f_di_ph); // AcidRequired(ZpH) Result += x * row.f_amount; } @@ -2845,24 +2848,11 @@ pH += deltapH; pd = ProtonDeficit(pH); } - pH = Round(pH, 2); + pH = Round(pH, 6); //console.log('MashpH() n: ' + n + ' pH: ' + pH); return pH; } - function GetAcidSpecs(AT) { - switch (AT) { - case 0: // Melkzuur - return { pK1: 3.86, pK2: 20, pK3: 20, MolWt: 90.08, AcidSG: 1214, AcidPrc: 0.88 }; - case 1: // Zoutzuur - return { pK1: -7, pK2: 20, pK3: 20, MolWt: 36.46, AcidSG: 1142, AcidPrc: 0.28 }; - case 2: // Fosforzuur - return { pK1: 2.12, pK2: 7.20, pK3: 12.44, MolWt: 98.00, AcidSG: 1170, AcidPrc: 0.25 }; - case 3: // Zwavelzuur - return { pK1: -1, pK2: 1.92, pK3: 20, MolWt: 98.07, AcidSG: 1700, AcidPrc: 0.93 }; - } - } - function calcWater() { /* Can be called during loading and building the screens */ @@ -2876,7 +2866,6 @@ magnesium = 0, sodium = 0, total_alkalinity = 0, - bicarbonate = 0, chloride = 0, sulfate = 0, ph = 0, @@ -2884,11 +2873,10 @@ frac = 0, TpH = 0, protonDeficit = 0, - AT, BT, result, pK1, pK2, pK3, MolWt, AcidSG, AcidPrc, + AT, BT, r1d, r2d, f1d, f2d, f3d, deltapH, deltapd, pd, n, - Res, - wg_calcium, wg_sodium, wg_total_alkalinity, wg_chloride, wg_sulfate, wg_bicarbonate; + Res; if (dataRecord.w1_name == '') { return; @@ -2914,96 +2902,85 @@ total_alkalinity = dataRecord.w1_total_alkalinity; ph = dataRecord.w1_ph; } + var bicarbonate = total_alkalinity * 1.22; + + /* Save mixed water ions for later */ + var wg_calcium = calcium; + var wg_sodium = sodium; + var wg_total_alkalinity = total_alkalinity; + var wg_chloride = chloride; + var wg_sulfate = sulfate; + var wg_bicarbonate = bicarbonate; + $('#wg_amount').val(liters); - wg_calcium = calcium; - $('#wg_calcium').val(Math.round(calcium * 10) / 10); - //var wg_magnesium = magnesium; - $('#wg_magnesium').val(Math.round(magnesium * 10) / 10); - wg_sodium = sodium; - $('#wg_sodium').val(Math.round(sodium * 10) / 10); - wg_total_alkalinity = total_alkalinity; - $('#wg_total_alkalinity').val(Math.round(total_alkalinity * 10) / 10); - wg_chloride = chloride; - $('#wg_chloride').val(Math.round(chloride * 10) / 10); - wg_sulfate = sulfate; - $('#wg_sulfate').val(Math.round(sulfate * 10) / 10); - // Note: brouwhulp has the malts included here in the result. - //var wg_ph = ph; - var mash_ph = Round(MashpH(), 1); - $('#wg_ph').val(Round(ph, 1)); - $('#wb_ph').val(mash_ph); - $('#est_mash_ph').val(mash_ph); - bicarbonate = total_alkalinity * 1.22; - wg_bicarbonate = bicarbonate; - - // Noot: de volgende berekeningen geven bijna gelijke resultaten in Brun'water. - // Calculate Ca - RA = parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCa / MMCaCl2 + - parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMCa / MMCaSO4; - calcium += 1000 * RA / liters; - - // Calculate Mg - RA = parseFloat($('#wa_mgso4').jqxNumberInput('decimal')) * MMMg / MMMgSO4; - magnesium += 1000 * RA / liters; - - // Calculate Na - RA = parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMNa / MMNaCl + - parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMNa / MMNaHCO3; - sodium += 1000 * RA / liters; - - // Calculate SO4 - RA = parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMSO4 / MMCaSO4 + - parseFloat($('#wa_mgso4').jqxNumberInput('decimal')) * MMSO4 / MMMgSO4; - sulfate += 1000 * RA / liters; - - // Calculate Cl - RA = 2 * parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCl / MMCaCl2 + - parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMCl / MMNaCl; - chloride += 1000 * RA / liters; - // Einde noot. - - if (parseInt($('#wa_acid_name').val()) < 0 || parseInt($('#wa_acid_name').val()) > 3) { + $('#wg_calcium').val(Round(calcium, 1)); + $('#wg_magnesium').val(Round(magnesium, 1)); + $('#wg_sodium').val(Round(sodium, 1)); + $('#wg_total_alkalinity').val(Round(total_alkalinity, 1)); + $('#wg_chloride').val(Round(chloride, 1)); + $('#wg_sulfate').val(Round(sulfate, 1)); + $('#wg_ph').val(Round(ph, 2)); + + var mash_ph = Round(MashpH(), 3); + console.log('Distilled water mash pH: ' + mash_ph); + + /* Calculate Salt additions */ + if (liters > 0) { + calcium += (parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCa / MMCaCl2 * 1000 + + parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMCa / MMCaSO4 * 1000) / liters; + magnesium += (parseFloat($('#wa_mgso4').jqxNumberInput('decimal')) * MMMg / MMMgSO4 * 1000) / liters; + sodium += (parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMNa / MMNaCl * 1000 + + parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMNa / MMNaHCO3 * 1000) / liters; + sulfate += (parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMSO4 / MMCaSO4 * 1000 + + parseFloat($('#wa_mgso4').jqxNumberInput('decimal')) * MMSO4 / MMMgSO4 * 1000) / liters; + chloride += (2 * parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCl / MMCaCl2 * 1000 + + parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMCl / MMNaCl * 1000) / liters; + } + + if (dataRecord.wa_acid_name < 0 || dataRecord,wa_acid_name >= AcidTypeData.length) { $('#wa_acid_name').val(0); dataRecord.wa_acid_name = 0; + dataRecord.wa_acid_perc = AcidTypeData[0].AcidPrc; + $('#wa_acid_perc').val(AcidTypeData[0].AcidPrc); } if (last_acid == '') - last_acid = AcidTypeData[$('#wa_acid_name').val()].nl; - - if (parseInt($('#wa_base_name').val()) < 0 || parseInt($('#wa_base_name').val()) > 3) { + last_acid = AcidTypeData[dataRecord.wa_acid_name].nl; + + if (parseFloat(dataRecord.wa_acid_perc) == 0) { + dataRecord.wa_acid_perc = AcidTypeData[AT].AcidPrc; + $('#wa_acid_perc').val(AcidTypeData[AT].AcidPrc); + } + + if (dataRecord.wa_base_name < 0 || dataRecord.wa_base_name > 3) { $('#wa_base_name').val(0); dataRecord.wa_base_name = 0; } if (last_base == '') - last_base = BaseTypeData[$('#wa_base_name').val()].nl; + last_base = BaseTypeData[dataRecord.wa_base_name].nl; AT = dataRecord.wa_acid_name; BT = dataRecord.wa_base_name; - result = GetAcidSpecs(AT); - pK1 = result.pK1; - pK2 = result.pK2; - pK3 = result.pK3; - MolWt = result.MolWt; - AcidSG = result.AcidSG; - AcidPrc = result.AcidPrc; + /* Note that the next calculations do not correct the pH change by the added salts. + This pH change is at most 0.1 pH and is a minor difference in Acid amount. */ if (dataRecord.calc_acid) { + /* Auto calculate pH */ + $('.c_mashph').show(); TpH = parseFloat(dataRecord.mash_ph); protonDeficit = ProtonDeficit(TpH); //console.log('calc_acid tgt: ' + TpH + ' protonDeficit: ' + protonDeficit); if (protonDeficit > 0) { // Add acid $('#wa_base').val(0); + dataRecord.wa_base = 0; setWaterAgent(last_base, 0); - frac = CalcFrac(TpH, pK1, pK2, pK3); + frac = CalcFrac(TpH, AcidTypeData[AT].pK1, AcidTypeData[AT].pK2, AcidTypeData[AT].pK3); Acid = protonDeficit / frac; - Acid *= MolWt; // mg + Acid *= AcidTypeData[AT].MolWt; // mg Acidmg = Acid; - Acid = Acid / AcidSG; // ml - - if (parseFloat($('#wa_acid_perc').jqxNumberInput('decimal')) == 0) - $('#wa_acid_perc').val(AcidPrc); - Acid = Round(Acid * AcidPrc / (parseFloat($('#wa_acid_perc').jqxNumberInput('decimal')) / 100), 2); // ml - //console.log('Final ml: ' + Acid); + Acid = Acid / AcidTypeData[AT].AcidSG; // ml + Acid = Round(Acid / (parseFloat(dataRecord.wa_acid_perc) / 100), 2); // ml + console.log('Mash auto Acid final ml: ' + Acid); $('#wa_acid').val(Acid); setWaterAgent(AcidTypeData[AT].nl, Acid); @@ -3011,9 +2988,10 @@ total_alkalinity = bicarbonate * 50 / 61; } else if (protonDeficit < 0) { //Add base $('#wa_acid').val(0); + dataRecord.wa_acid = 0; setWaterAgent(last_acid, 0); - r1d = Math.pow(10, (TpH - 6.38)); - r2d = Math.pow(10, (TpH - 10.38)); + r1d = Math.pow(10, (TpH - 6.35)); + r2d = Math.pow(10, (TpH - 10.33)); f1d = 1 / (1 + r1d + r1d * r2d); f2d = f1d * r1d; f3d = f2d * r2d; @@ -3025,13 +3003,11 @@ setWaterAgent('NaHCO3', Round(RA, 2)); if (liters > 0) { // Na - RA = parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMNa / MMNaCl + - parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMNa / MMNaHCO3; - RA = 1000 * RA / liters; + RA = (parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMNa / MMNaCl * 1000 + + parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMNa / MMNaHCO3 * 1000) / liters; sodium = wg_sodium + RA; // HCO3 - RA = parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMHCO3 / MMNaHCO3; - RA = 1000 * RA / liters; + RA = (parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMHCO3 / MMNaHCO3 * 1000) / liters; bicarbonate = wg_bicarbonate + RA; total_alkalinity = bicarbonate * 50 / 61; RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium); @@ -3043,13 +3019,11 @@ $('#wa_base').val(Round(RA, 2)); setWaterAgent('Na2CO3', Round(RA, 2)); if (liters > 0) { - RA = parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMNa / MMNaCl + - parseFloat($('#wa_base').jqxNumberInput('decimal')) * 2 * MMNa / MMNa2CO3; - RA = 1000 * RA / liters; + RA = (parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMNa / MMNaCl * 1000+ + parseFloat($('#wa_base').jqxNumberInput('decimal')) * 2 * MMNa / MMNa2CO3 * 1000) / liters; sodium = wg_sodium + RA; // HCO3 - RA = parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMHCO3 / MMNa2CO3; - RA = 1000 * RA / liters; + RA = (parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMHCO3 / MMNa2CO3 * 1000) / liters; bicarbonate = wg_bicarbonate + RA; total_alkalinity = bicarbonate * 50 / 61; RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium); @@ -3064,15 +3038,13 @@ setWaterAgent('CaCO3', Round(RA, 2)); if (liters > 0) { //Bicarbonate - RA = parseFloat($('#wa_base').jqxNumberInput('decimal')) / 3 * MMHCO3 / MMCaCO3; - RA = 1000 * RA / liters; + RA = (parseFloat($('#wa_base').jqxNumberInput('decimal')) / 3 * MMHCO3 / MMCaCO3 * 1000) / liters; bicarbonate = wg_bicarbonate + RA; total_alkalinity = bicarbonate * 50 / 61; //Ca precipitates out as Ca10(PO4)6(OH)2 - RA = parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCa / MMCaCl2 + - parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMCa / MMCaSO4 + - parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMCa / MMCaCO3; - RA = 1000 * RA / liters; + RA = (parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCa / MMCaCl2 * 1000 + + parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMCa / MMCaSO4 * 1000 + + parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMCa / MMCaCO3 * 1000) / liters; calcium = wg_calcium + RA; RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium); } @@ -3087,10 +3059,9 @@ total_alkalinity = wg_total_alkalinity + RA; bicarbonate = total_alkalinity * 61 / 50; // Calcium - RA = parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCa / MMCaCl2 + - parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMCa / MMCaSO4 + - parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMCa / MMCaOH2; - RA = 1000 * RA / liters; + RA = (parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCa / MMCaCl2 * 1000 + + parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMCa / MMCaSO4 * 1000 + + parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMCa / MMCaOH2 * 1000) / liters; calcium = wg_calcium + RA; RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium); } @@ -3098,98 +3069,86 @@ } } ph = TpH; - $('#wb_ph').val(Round(ph, 1)); - $('#est_mash_ph').val(Round(ph, 1)); - } else { // Manual + $('#wb_ph').val(Round(ph, 2)); + $('#est_mash_ph').val(Round(ph, 2)); + } else { + /* Manual calculate pH */ + $('.c_mashph').hide(); console.log('calc_acid no'); - // First add base salts - if (parseFloat($('#wa_base').jqxNumberInput('decimal')) > 0) { - if (liters > 0) { - switch (BT) { - case 0: // Sodiumbicarbonate, Na - RA = parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMNa / MMNaCl + - parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMNa / MMNaHCO3; - RA = 1000 * RA / liters; - sodium = wg_sodium + RA; - // HCO3 - RA = parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMHCO3 / MMNaHCO3; - RA = 1000 * RA / liters; - bicarbonate = wg_bicarbonate + RA; - total_alkalinity = bicarbonate * 50 / 61; - RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium); - break; - case 1: // Sodiumcarbonate - RA = parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMNa / MMNaCl + - parseFloat($('#wa_base').jqxNumberInput('decimal')) * 2 * MMNa / MMNa2CO3; - RA = 1000 * RA / liters; - sodium = wg_sodium + RA; - // HCO3 - RA = parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMHCO3 / MMNa2CO3; - RA = 1000 * RA / liters; - bicarbonate = wg_bicarbonate + RA; - total_alkalinity = bicarbonate * 50 / 61; - RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium); - break; - case 2: // Calciumcarbonate: Bicarbonate - RA = parseFloat($('#wa_base').jqxNumberInput('decimal')) / 3 * MMHCO3 / MMCaCO3; - RA = 1000 * RA / liters; - bicarbonate = wg_bicarbonate + RA; - total_alkalinity = bicarbonate * 50 / 61; - RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium); - // Ca - RA = parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCa / MMCaCl2 + - parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMCa / MMCaSO4 + - parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMCa / MMCaCO3; - RA = 1000 * RA / liters; - calcium = wg_calcium + RA; - break; - } + if (parseFloat($('#wa_base').jqxNumberInput('decimal')) > 0 && liters > 0) { + /* First add the base salts */ + switch (BT) { + case 0: // Sodiumbicarbonate, Na + RA = (parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMNa / MMNaCl * 1000 + + parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMNa / MMNaHCO3 * 1000) / liters; + sodium = wg_sodium + RA; + // HCO3 + RA = (parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMHCO3 / MMNaHCO3 * 1000) / liters; + bicarbonate = wg_bicarbonate + RA; + total_alkalinity = bicarbonate * 50 / 61; + RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium); + break; + case 1: // Sodiumcarbonate + RA = (parseFloat($('#wa_nacl').jqxNumberInput('decimal')) * MMNa / MMNaCl * 1000 + + parseFloat($('#wa_base').jqxNumberInput('decimal')) * 2 * MMNa / MMNa2CO3 * 1000) / liters; + sodium = wg_sodium + RA; + // HCO3 + RA = (parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMHCO3 / MMNa2CO3 * 1000) / liters; + bicarbonate = wg_bicarbonate + RA; + total_alkalinity = bicarbonate * 50 / 61; + RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium); + break; + case 2: // Calciumcarbonate: Bicarbonate + RA = (parseFloat($('#wa_base').jqxNumberInput('decimal')) / 3 * MMHCO3 * 1000 / MMCaCO3) / liters; + bicarbonate = wg_bicarbonate + RA; + total_alkalinity = bicarbonate * 50 / 61; + RA = ResidualAlkalinity(wb_total_alkalinity, wb_calcium, wb_magnesium); + // Ca + RA = (parseFloat($('#wa_cacl2').jqxNumberInput('decimal')) * MMCa * 1000 / MMCaCl2 + + parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMCa * 1000 / MMCaSO4 + + parseFloat($('#wa_base').jqxNumberInput('decimal')) * MMCa * 1000/ MMCaCO3) / liters; + calcium = wg_calcium + RA; + break; } } - TpH = parseFloat(dataRecord.mash_ph); - pHa = MashpH(); // This one is in demi water, should be in adjusted water??? - // Then calculate the new pH with added acids - if (parseFloat($('#wa_acid').jqxNumberInput('decimal')) > 0) { - console.log('TpH: ' + TpH + ' water: ' + pHa); - Acid = parseFloat($('#wa_acid').jqxNumberInput('decimal')); - if (parseFloat($('#wa_acid_perc').jqxNumberInput('decimal')) == 0) - $('#wa_acid_perc').val(AcidPrc); - Acid = Acid / AcidPrc * (parseFloat($('#wa_acid_perc').jqxNumberInput('decimal')) / 100); // ml - Acid *= AcidSG; // ml - Acid /= MolWt; // mg - Acidmg = Acid; - - //find the pH where the protondeficit = protondeficit by the acid - frac = CalcFrac(pHa, pK1, pK2, pK3); - protonDeficit = Acid * frac; - - deltapH = 0.001; - deltapd = 0.1; - console.log('in calcWater() manual'); - pd = ProtonDeficit(pHa); - n = 0; - while (((pd < (protonDeficit - deltapd)) || (pd > (protonDeficit + deltapd))) && (n < 2000)) { + pHa = Round(ph, 3); // Adjusted water pH + // Then calculate the new pH with added acids and malts + console.log('Mash pH: ' + pHa); + Acid = AcidTypeData[AT].AcidSG * (parseFloat(dataRecord.wa_acid_perc) / 100); // ml + Acid *= parseFloat($('#wa_acid').jqxNumberInput('decimal')); + Acid /= AcidTypeData[AT].MolWt; // mg + Acidmg = Acid; + + //find the pH where the protondeficit = protondeficit by the acid + frac = CalcFrac(pHa, AcidTypeData[AT].pK1, AcidTypeData[AT].pK2, AcidTypeData[AT].pK3); + protonDeficit = Round(Acid * frac, 3); + //console.log('protonDeficit Acid: ' + protonDeficit + ' frac: ' + frac + ' pH: ' + pHa); + + deltapH = 0.001; + deltapd = 0.1; + pd = Round(ProtonDeficit(pHa), 6); + n = 0; + while (((pd < (protonDeficit - deltapd)) || (pd > (protonDeficit + deltapd))) && (n < 4000)) { n++; if (pd < (protonDeficit - deltapd)) pHa -= deltapH; else if (pd > (protonDeficit + deltapd)) pHa += deltapH; - frac = CalcFrac(pHa, pK1, pK2, pK3); + frac = CalcFrac(pHa, AcidTypeData[AT].pK1, AcidTypeData[AT].pK2, AcidTypeData[AT].pK3); protonDeficit = Acid * frac; pd = ProtonDeficit(pHa); - } - console.log('n: ' + n + ' pd: ' + pd + ' protonDeficit: ' + protonDeficit + ' frac: ' + frac + ' pHa: ' + pHa); - RA = wg_bicarbonate - protonDeficit * frac / liters; - bicarbonate = RA; - total_alkalinity = RA * 50 / 61; - ph = pHa; - $('#wb_ph').val(Round(ph, 1)); - $('#est_mash_ph').val(Round(ph, 1)); } + //console.log('n: ' + n + ' pd: ' + pd + ' protonDeficit: ' + protonDeficit + ' frac: ' + frac + ' pHa: ' + pHa); + RA = wg_bicarbonate - protonDeficit * frac / liters; + bicarbonate = RA; + total_alkalinity = RA * 50 / 61; + ph = pHa; + $('#wb_ph').val(Round(ph, 2)); + $('#est_mash_ph').val(Round(ph, 2)); } - if ((AT == 3) && (liters > 0)) { // Sulfuctic / Zwavelzuur + if ((AT == 3) && (liters > 0)) { // Sulfuric / Zwavelzuur RA = parseFloat($('#wa_caso4').jqxNumberInput('decimal')) * MMSO4 / MMCaSO4 + parseFloat($('#wa_mgso4').jqxNumberInput('decimal')) * MMSO4 / MMMgSO4 + Acidmg / 1000 * MMSO4 / (MMSO4 + 2); @@ -3304,13 +3263,10 @@ function calcSparge() { - var TargetpH, Source_pH, Source_alkalinity, r1, r2, d, f1, f3, r143, r243, d43, f143, f343, - alkalinity, Ct, r1g, r2g, dg, f1g, f3g, Acid, AT, result, pK1, pK2, pK3, MolWt, AcidSG, AcidPrc, fract; - - // Code from BrewBuddy/Brouwhulp, who got it from http://www.brewery.org/brewery/library/Acidi0,00fWaterAJD0497.html - TargetpH = dataRecord.sparge_ph; - Source_pH = dataRecord.w1_ph; - Source_alkalinity = dataRecord.w1_total_alkalinity; + /* Based on the work of ajDeLange. */ + var TargetpH = dataRecord.sparge_ph; + var Source_pH = dataRecord.w1_ph; + var Source_alkalinity = dataRecord.w1_total_alkalinity; // Select watersource or fallback to the first source. if (dataRecord.sparge_source == 1) { // Source 2 if (dataRecord.w2_ph > 0.0) { @@ -3322,73 +3278,62 @@ } } else if (dataRecord.sparge_source == 2) { // Mixed if (dataRecord.w2_ph > 0.0) { - Source_pH = parseFloat($('#wg_ph').jqxNumberInput('decimal')); - Source_alkalinity = parseFloat($('#wg_total_alkalinity').jqxNumberInput('decimal')); + Source_pH = parseFloat(dataRecord.wg_ph); + Source_alkalinity = parseFloat(dataRecord.wg_total_alkalinity); } else { dataRecord.sparge_source = 0; $('#sparge_source').val(0); } } - // Step 1: Compute the mole fractions of carbonic (f1o), bicarbonate (f2o) and carbonate(f3o) at the water pH - r1 = Math.pow(10, Source_pH - 6.38); - r2 = Math.pow(10, Source_pH - 10.373); - d = 1 + r1 + r1 * r2; - f1 = 1 / d; - f3 = r1 * r2 / d; + // Step 1: Compute the mole fractions of carbonic (f1) and carbonate(f3) at the source water pH + var r1 = Math.pow(10, Source_pH - 6.35); + var r2 = Math.pow(10, Source_pH - 10.33); + var d = 1 + r1 + r1 * r2; + var f1 = 1 / d; + var f3 = r1 * r2 / d; //Step 2. Compute the mole fractions at pH = 4.3 (the pH which defines alkalinity) - r143 = Math.pow(10, 4.3 - 6.38); - r243 = Math.pow(10, 4.3 - 10.373); - d43 = 1 + r143 + r143 * r243; - f143 = 1 / d43; - f343 = r143 * r243 / d43; - - //Step 3. Convert the water alkalinity to milliequivalents/L - alkalinity = Source_alkalinity / 50; + var r143 = Math.pow(10, 4.3 - 6.35); + var r243 = Math.pow(10, 4.3 - 10.33); + var d43 = 1 + r143 + r143 * r243; + var f143 = 1 / d43; + var f343 = r143 * r243 / d43; //Step 4. Solve - Ct = (alkalinity - 1000 * (Math.pow(10, -4.3) - Math.pow(10, -Source_pH))) / ((f143 - f1) + (f3 - f343)); + var Ct = Source_alkalinity / 50 / ((f143 - f1) + (f3 - f343)); //Step 5. Compute mole fractions at desired pH - r1g = Math.pow(10, TargetpH - 6.38); - r2g = Math.pow(10, TargetpH - 10.373); - dg = 1 + r1g + r1g * r2g; - f1g = 1 / dg; - f3g = r1g * r2g / dg; + var r1g = Math.pow(10, TargetpH - 6.35); + var r2g = Math.pow(10, TargetpH - 10.33); + var dg = 1 + r1g + r1g * r2g; + var f1g = 1 / dg; + var f3g = r1g * r2g / dg; //Step 6. Use these to compute the milliequivalents acid required per liter (mEq/L) - Acid = Ct * ((f1g - f1) + (f3 - f3g)) + Math.pow(10, -TargetpH) - Math.pow(10, -Source_pH); //mEq/l + var Acid = Ct * ((f1g - f1) + (f3 - f3g)) + Math.pow(10, -TargetpH) - Math.pow(10, -Source_pH); //mEq/l Acid += 0.01; // Add acid that would be required for distilled water. - if (dataRecord.sparge_acid_type < 0 || dataRecord.sparge_acid_type > 3) { + + //Step 8. Get the acid data. + var AT = dataRecord.sparge_acid_type; + if (AT < 0 || AT >= AcidTypeData.length) { + AT = 0; dataRecord.sparge_acid_type = 0; $('#sparge_acid_type').val(0); + dataRecord.sparge_acid_perc = AcidTypeData[0].AcidPrc; + $('#sparge_acid_perc').val(dataRecord.sparge_acid_perc); } - - //Step 8. Get the acid data. - AT = dataRecord.sparge_acid_type; - result = GetAcidSpecs(AT); - pK1 = result.pK1; - pK2 = result.pK2; - pK3 = result.pK3; - MolWt = result.MolWt; - AcidSG = result.AcidSG; - AcidPrc = result.AcidPrc; - fract = CalcFrac(TargetpH, pK1, pK2, pK3); + var fract = CalcFrac(TargetpH, AcidTypeData[AT].pK1, AcidTypeData[AT].pK2, AcidTypeData[AT].pK3); //Step 9. Now divide the mEq required by the "fraction". This is the required number of moles of acid. Acid /= fract; //Step 10. Multiply by molecular weight of the acid - Acid *= MolWt; //mg - - Acid = Acid / AcidSG; //ml ; 88% lactic solution - f1 = dataRecord.sparge_acid_perc; - if (f1 <= 0.1) - f1 = AcidPrc; - Acid = Acid * AcidPrc / (f1 / 100); - - Acid *= dataRecord.sparge_volume; //ml lactic acid total + Acid *= AcidTypeData[AT].MolWt; //mg + + //Step 11. Divide by Specific Gravity and Percentage to get the final ml. + Acid = Acid / AcidTypeData[AT].AcidSG / (dataRecord.sparge_acid_perc / 100); //ml + Acid *= dataRecord.sparge_volume; //ml acid total Acid = Round(Acid, 2); dataRecord.sparge_acid_amount = Acid / 1000; $('#sparge_acid_amount').val(Acid); @@ -3923,20 +3868,25 @@ $('#wa_acid_name').on('select', function(event) { if (event.args) { var index = event.args.index; - console.log('wa_acid_name ' + index); + console.log('wa_acid_name ' + index + ' last_acid: ' + last_acid); setWaterAgent(last_acid, 0); last_acid = AcidTypeData[index].nl; + dataRecord.wa_acid_name = index; + dataRecord.wa_acid_perc = AcidTypeData[index].AcidPrc; + $('#wa_acid_perc').val(dataRecord.wa_acid_perc); + calcWater(); setWaterAgent(last_acid, parseFloat($('#wa_acid').jqxNumberInput('decimal'))); - dataRecord.wa_acid_name = index; - calcWater(); } }); $('#wa_acid').on('change', function(event) { - var name = AcidTypeData[$('#wa_acid_name').val()].nl; + var name = AcidTypeData[dataRecord.wa_acid_name].nl; setWaterAgent(name, parseFloat(event.args.value)); calcWater(); }); - $('#wa_acid_perc').on('change', function(event) { calcWater(); }); + $('#wa_acid_perc').on('change', function(event) { + dataRecord.wa_acid_perc = parseFloat(event.args.value); + calcWater(); + }); $('#color_method').on('select', function(event) { dataRecord.color_method = event.args.index; @@ -4034,6 +3984,8 @@ if (event.args) { dataRecord.sparge_acid_type = event.args.index; console.log('new sparge_acid_type: ' + dataRecord.sparge_acid_type); + dataRecord.sparge_acid_perc = AcidTypeData[event.args.index].AcidPrc; + $('#sparge_acid_perc').val(dataRecord.sparge_acid_perc); calcSparge(); } }); @@ -5626,7 +5578,8 @@ calcWater(); } }); - $('#w1_amount,#w1_calcium,#w1_magnesium,#w1_sodium,#w1_total_alkalinity,#w1_chloride,#w1_sulfate,#w1_ph').jqxNumberInput(Show1wat); + $('#w1_amount,#w1_calcium,#w1_magnesium,#w1_sodium,#w1_total_alkalinity,#w1_chloride,#w1_sulfate').jqxNumberInput(Show1wat); + $('#w1_ph').jqxNumberInput(Show2wat); // Water source 2 $('#w2_name').jqxDropDownList({ placeHolder: 'Kies meng water:', @@ -5668,16 +5621,19 @@ inputMode: 'simple', spinMode: 'simple', theme: theme, width: 94, height: 23, min: 0, max: 0, decimalDigits: 1, spinButtons: true, spinButtonsStep: 0.1, readOnly: true }); - $('#w2_calcium,#w2_magnesium,#w2_sodium,#w2_total_alkalinity,#w2_chloride,#w2_sulfate,#w2_ph').jqxNumberInput(Show1wat); + $('#w2_calcium,#w2_magnesium,#w2_sodium,#w2_total_alkalinity,#w2_chloride,#w2_sulfate').jqxNumberInput(Show1wat); + $('#w2_ph').jqxNumberInput(Show2wat); // Water mixed - $('#wg_amount,#wg_calcium,#wg_magnesium,#wg_sodium,#wg_total_alkalinity,#wg_chloride,#wg_sulfate,#wg_ph').jqxNumberInput(Show1wat); + $('#wg_amount,#wg_calcium,#wg_magnesium,#wg_sodium,#wg_total_alkalinity,#wg_chloride,#wg_sulfate').jqxNumberInput(Show1wat); + $('#wg_ph').jqxNumberInput(Show2wat); // Water treated $('#wb_calcium').jqxTooltip({ content: 'De ideale hoeveelheid Calcium is tussen 40 en 150.'}); $('#wb_magnesium').jqxTooltip({ content: 'De ideale hoeveelheid Magnesium is tusse 10 en 30.'}); $('#wb_sodium').jqxTooltip({ content: 'De ideale hoeveelheid Natrium is lager dan 150.'}); $('#wb_chloride').jqxTooltip({ content: 'De ideale hoeveelheid Chloride is tussen 50 en 100.'}); $('#wb_sulfate').jqxTooltip({ content: 'De ideale hoeveelheid Sulfaat is tussen 50 en 350.'}); - $('#wb_calcium,#wb_magnesium,#wb_sodium,#wb_total_alkalinity,#wb_chloride,#wb_sulfate,#wb_ph').jqxNumberInput(Show1wat); + $('#wb_calcium,#wb_magnesium,#wb_sodium,#wb_total_alkalinity,#wb_chloride,#wb_sulfate').jqxNumberInput(Show1wat); + $('#wb_ph').jqxNumberInput(Show2wat); // Water target profile $('#pr_name').jqxDropDownList({ placeHolder: 'Kies doel profiel:', @@ -5790,7 +5746,7 @@ $('#brew_sparge_volume').jqxTooltip({ content: 'Het spoelwater voorraad volume, in te stellen in de Water tab.' }); $('#brew_date_start,#brew_date_end').jqxDateTimeInput(DateTimeopts); $('#brew_date_start,#brew_date_end').on('close', function(event) { calcStage(); }); - $('#est_mash_ph').jqxNumberInput(Show1wat); + $('#est_mash_ph').jqxNumberInput(Show2wat); $('#brew_mash_ph,#brew_preboil_ph,#brew_aboil_ph').jqxNumberInput(SpinpH); $('#brew_mash_sg').on('valueChanged', function() { calcMashEfficiency(); }); $('#brew_preboil_sg').on('valueChanged', function(event) {