358:d89bc21e2f07 | 359:dfbb012c631c |
---|---|
159 int AT; | 159 int AT; |
160 | 160 |
161 qDebug() << "calcWater()"; | 161 qDebug() << "calcWater()"; |
162 | 162 |
163 ui->w1_hardnessEdit->setValue(Utils::Hardness(product->w1_calcium, product->w1_magnesium)); | 163 ui->w1_hardnessEdit->setValue(Utils::Hardness(product->w1_calcium, product->w1_magnesium)); |
164 ui->w1_raEdit->setValue(Utils::RA_ppm(product->w1_total_alkalinity, product->w1_calcium, product->w1_magnesium)); | 164 ui->w1_raEdit->setValue(Utils::ResidualAlkalinity(product->w1_total_alkalinity, product->w1_calcium, product->w1_magnesium)); |
165 | 165 |
166 /* | 166 /* |
167 * If there is a dilute water source, mix the waters. | 167 * If there is a dilute water source, mix the waters. |
168 */ | 168 */ |
169 if (product->w2_name != "") { | 169 if (product->w2_name != "") { |
174 chloride = Utils::mix(product->w1_amount, product->w2_amount, product->w1_chloride, product->w2_chloride); | 174 chloride = Utils::mix(product->w1_amount, product->w2_amount, product->w1_chloride, product->w2_chloride); |
175 sulfate = Utils::mix(product->w1_amount, product->w2_amount, product->w1_sulfate, product->w2_sulfate); | 175 sulfate = Utils::mix(product->w1_amount, product->w2_amount, product->w1_sulfate, product->w2_sulfate); |
176 total_alkalinity = Utils::mix(product->w1_amount, product->w2_amount, product->w1_total_alkalinity, product->w2_total_alkalinity); | 176 total_alkalinity = Utils::mix(product->w1_amount, product->w2_amount, product->w1_total_alkalinity, product->w2_total_alkalinity); |
177 ph = -log10(((pow(10, -product->w1_ph) * product->w1_amount) + (pow(10, -product->w2_ph) * product->w2_amount)) / liters); | 177 ph = -log10(((pow(10, -product->w1_ph) * product->w1_amount) + (pow(10, -product->w2_ph) * product->w2_amount)) / liters); |
178 ui->w2_hardnessEdit->setValue(Utils::Hardness(product->w2_calcium, product->w2_magnesium)); | 178 ui->w2_hardnessEdit->setValue(Utils::Hardness(product->w2_calcium, product->w2_magnesium)); |
179 ui->w2_raEdit->setValue(Utils::RA_ppm(product->w2_total_alkalinity, product->w2_calcium, product->w2_magnesium)); | 179 ui->w2_raEdit->setValue(Utils::ResidualAlkalinity(product->w2_total_alkalinity, product->w2_calcium, product->w2_magnesium)); |
180 } else { | 180 } else { |
181 liters = product->w1_amount; | 181 liters = product->w1_amount; |
182 calcium = product->w1_calcium; | 182 calcium = product->w1_calcium; |
183 magnesium = product->w1_magnesium; | 183 magnesium = product->w1_magnesium; |
184 sodium = product->w1_sodium; | 184 sodium = product->w1_sodium; |
195 product->wg_chloride = round(chloride * 10.0) / 10.0; | 195 product->wg_chloride = round(chloride * 10.0) / 10.0; |
196 product->wg_sulfate = round(sulfate * 10.0) / 10.0; | 196 product->wg_sulfate = round(sulfate * 10.0) / 10.0; |
197 product->wg_total_alkalinity = round(total_alkalinity * 10.0) / 10.0; | 197 product->wg_total_alkalinity = round(total_alkalinity * 10.0) / 10.0; |
198 product->wg_ph = ph; | 198 product->wg_ph = ph; |
199 | 199 |
200 bicarbonate = Utils::Bicarbonate(total_alkalinity, ph); | |
200 ui->wg_volEdit->setValue(liters); | 201 ui->wg_volEdit->setValue(liters); |
201 ui->wg_caEdit->setValue(calcium); | 202 ui->wg_caEdit->setValue(calcium); |
202 ui->wg_mgEdit->setValue(magnesium); | 203 ui->wg_mgEdit->setValue(magnesium); |
203 ui->wg_hco3Edit->setValue(total_alkalinity * 1.22); | 204 ui->wg_hco3Edit->setValue(bicarbonate); |
204 ui->wg_caco3Edit->setValue(total_alkalinity); | 205 ui->wg_caco3Edit->setValue(total_alkalinity); |
205 ui->wg_naEdit->setValue(sodium); | 206 ui->wg_naEdit->setValue(sodium); |
206 ui->wg_clEdit->setValue(chloride); | 207 ui->wg_clEdit->setValue(chloride); |
207 ui->wg_so4Edit->setValue(sulfate); | 208 ui->wg_so4Edit->setValue(sulfate); |
208 ui->wg_phEdit->setValue(ph); | 209 ui->wg_phEdit->setValue(ph); |
209 ui->wg_hardnessEdit->setValue(Utils::Hardness(calcium, magnesium)); | 210 ui->wg_hardnessEdit->setValue(Utils::Hardness(calcium, magnesium)); |
210 ui->wg_raEdit->setValue(Utils::RA_ppm(total_alkalinity, calcium, magnesium)); | 211 ui->wg_raEdit->setValue(Utils::ResidualAlkalinity(total_alkalinity, calcium, magnesium)); |
211 bicarbonate = total_alkalinity * 1.22; | |
212 | 212 |
213 /* Save mixed water ions for later */ | 213 /* Save mixed water ions for later */ |
214 double wg_calcium = calcium; | 214 double wg_calcium = calcium; |
215 double wg_sodium = sodium; | 215 double wg_sodium = sodium; |
216 double wg_total_alkalinity = total_alkalinity; | 216 double wg_total_alkalinity = total_alkalinity; |
263 Acid = protonDeficit / frac; | 263 Acid = protonDeficit / frac; |
264 Acid *= my_acids[AT].MolWt; // mg. | 264 Acid *= my_acids[AT].MolWt; // mg. |
265 Acidmg = Acid; | 265 Acidmg = Acid; |
266 Acid = Acid / my_acids[AT].AcidSG; | 266 Acid = Acid / my_acids[AT].AcidSG; |
267 Acid = round((Acid / (product->wa_acid_perc / 100.0)) * 100.0) / 100.0; | 267 Acid = round((Acid / (product->wa_acid_perc / 100.0)) * 100.0) / 100.0; |
268 qDebug() << " Mash auto Acid final old ml:" << Acid; | |
269 Acid = Acidmg; | |
270 | |
271 double RealSG = round(((my_acids[AT].AcidSG - 1000) * (product->wa_acid_perc / 100)) + 1000); | |
272 Acid /= RealSG; | |
273 Acid /= my_acids[AT].AcidPrc / 100; | |
274 Acid = round(Acid * 100.0) / 100.0; | |
268 qDebug() << " Mash auto Acid final ml:" << Acid; | 275 qDebug() << " Mash auto Acid final ml:" << Acid; |
269 | 276 |
270 QString w = my_acids[AT].name_en + ' ' + my_acids[AT].name_nl; | 277 QString w = my_acids[AT].name_en + ' ' + my_acids[AT].name_nl; |
271 brewing_salt_sub(w, Acid); | 278 brewing_salt_sub(w, Acid, MISC_USES_MASH); |
272 ui->mw_acidvolEdit->setValue(Acid); | 279 ui->mw_acidvolEdit->setValue(Acid); |
273 | 280 |
274 bicarbonate = bicarbonate - protonDeficit * frac / liters; | 281 bicarbonate = bicarbonate - protonDeficit * frac / liters; |
275 total_alkalinity = bicarbonate * 50 / 61; | 282 total_alkalinity = bicarbonate * 50 / 61; |
276 } | 283 } |
280 } else { // Manual | 287 } else { // Manual |
281 /* | 288 /* |
282 * Manual adjust acid, calculate resulting pH. | 289 * Manual adjust acid, calculate resulting pH. |
283 */ | 290 */ |
284 double pHa = ph; // Mixed water pH. | 291 double pHa = ph; // Mixed water pH. |
292 double RealSG = round(((my_acids[AT].AcidSG - 1000) * (product->wa_acid_perc / 100)) + 1000); | |
285 // Then calculate the new pH with added acids and malts | 293 // Then calculate the new pH with added acids and malts |
286 qDebug() << " Mash pH:" << pHa; | 294 qDebug() << " Mash pH:" << pHa; |
287 Acid = my_acids[AT].AcidSG * (product->wa_acid_perc / 100.0); // ml | 295 Acid = RealSG; |
288 Acid *= ui->mw_acidvolEdit->value(); | 296 Acid *= ui->mw_acidvolEdit->value(); |
297 Acid *= my_acids[AT].AcidPrc / 100; | |
289 Acid /= my_acids[AT].MolWt; // mg; | 298 Acid /= my_acids[AT].MolWt; // mg; |
290 Acidmg = Acid; | 299 Acidmg = Acid; |
291 | 300 |
292 //find the pH where the protondeficit = protondeficit by the acid | 301 //find the pH where the protondeficit = protondeficit by the acid |
293 frac = Utils::CalcFrac(pHa, my_acids[AT].pK1, my_acids[AT].pK2, my_acids[AT].pK3); | 302 frac = Utils::CalcFrac(pHa, my_acids[AT].pK1, my_acids[AT].pK2, my_acids[AT].pK3); |
294 protonDeficit = Acid * frac; | 303 protonDeficit = Acid * frac; |
295 //qDebug() << " protonDeficit Acid:" << protonDeficit << "frac:" << frac << "pH:" << pHa; | 304 qDebug() << " Acid:" << Acid << "protonDeficit:" << protonDeficit << "frac:" << frac << "pH:" << pHa; |
296 | 305 |
297 double deltapH = 0.001; | 306 double deltapH = 0.001; |
298 double deltapd = 0.1; | 307 double deltapd = 0.1; |
299 double pd = round(ProtonDeficit(pHa) * 1000000.0) / 1000000.0; | 308 double pd = round(ProtonDeficit(pHa) * 1000000.0) / 1000000.0; |
300 int n = 0; | 309 int n = 0; |
306 pHa += deltapH; | 315 pHa += deltapH; |
307 frac = Utils::CalcFrac(pHa, my_acids[AT].pK1, my_acids[AT].pK2, my_acids[AT].pK3); | 316 frac = Utils::CalcFrac(pHa, my_acids[AT].pK1, my_acids[AT].pK2, my_acids[AT].pK3); |
308 protonDeficit = Acid * frac; | 317 protonDeficit = Acid * frac; |
309 pd = ProtonDeficit(pHa); | 318 pd = ProtonDeficit(pHa); |
310 } | 319 } |
311 //qDebug() << " n:" << n << "pd:" << pd << "protonDeficit:" << protonDeficit << "frac:" << frac << "pHa:" << pHa; | 320 qDebug() << " n:" << n << "pd:" << pd << "protonDeficit:" << protonDeficit << "frac:" << frac << "pHa:" << pHa; |
312 | 321 |
313 bicarbonate = wg_bicarbonate - protonDeficit * frac / liters; | 322 bicarbonate = wg_bicarbonate - protonDeficit * frac / liters; |
314 total_alkalinity = bicarbonate * 50 / 61; | 323 total_alkalinity = bicarbonate * 50 / 61; |
315 ph = pHa; | 324 ph = pHa; |
316 ui->wb_phEdit->setValue(ph); | 325 ui->wb_phEdit->setValue(ph); |
381 ui->wb_caco3Edit->setValue(total_alkalinity); | 390 ui->wb_caco3Edit->setValue(total_alkalinity); |
382 ui->wb_naEdit->setValue(sodium); | 391 ui->wb_naEdit->setValue(sodium); |
383 ui->wb_clEdit->setValue(chloride); | 392 ui->wb_clEdit->setValue(chloride); |
384 ui->wb_so4Edit->setValue(sulfate); | 393 ui->wb_so4Edit->setValue(sulfate); |
385 ui->wb_hardnessEdit->setValue(Utils::Hardness(calcium, magnesium)); | 394 ui->wb_hardnessEdit->setValue(Utils::Hardness(calcium, magnesium)); |
386 ui->wb_raEdit->setValue(Utils::RA_ppm(total_alkalinity, calcium, magnesium)); | 395 ui->wb_raEdit->setValue(Utils::ResidualAlkalinity(total_alkalinity, calcium, magnesium)); |
387 | 396 |
388 ui->wb_caEdit->setStyleSheet((calcium < 40 || calcium > 150) ? "background-color: red":"background-color: green"); | 397 ui->wb_caEdit->setStyleSheet((calcium < 40 || calcium > 150) ? "background-color: red":"background-color: green"); |
389 ui->wb_mgEdit->setStyleSheet((magnesium < 5 || magnesium > 40) ? "background-color: red":"background-color: green"); | 398 ui->wb_mgEdit->setStyleSheet((magnesium < 5 || magnesium > 40) ? "background-color: red":"background-color: green"); |
390 ui->wb_naEdit->setStyleSheet((sodium > 150) ? "background-color: red":"background-color: green"); | 399 ui->wb_naEdit->setStyleSheet((sodium > 150) ? "background-color: red":"background-color: green"); |
391 /* | 400 /* |
418 double Source_pH = product->w1_ph; | 427 double Source_pH = product->w1_ph; |
419 double Source_alkalinity = product->w1_total_alkalinity; | 428 double Source_alkalinity = product->w1_total_alkalinity; |
420 | 429 |
421 qDebug() << "calcSparge()"; | 430 qDebug() << "calcSparge()"; |
422 | 431 |
423 const QSignalBlocker blocker1(ui->sp_sourceEdit); | 432 const QSignalBlocker blocker2(ui->w1_spButton); |
433 const QSignalBlocker blocker3(ui->w2_spButton); | |
434 const QSignalBlocker blocker4(ui->wg_spButton); | |
424 | 435 |
425 // Select watersource or fallback to the first source. | 436 // Select watersource or fallback to the first source. |
426 if (product->sparge_source == 1) { // Source 2 | 437 if (product->sparge_source == 1) { // Source 2 |
427 if (product->w2_ph > 0.0 && product->w2_amount > 0) { | 438 if (product->w2_ph > 0.0 && product->w2_amount > 0) { |
428 Source_pH = product->w2_ph; | 439 Source_pH = product->w2_ph; |
429 Source_alkalinity = product->w2_total_alkalinity; | 440 Source_alkalinity = product->w2_total_alkalinity; |
441 ui->sp_caEdit->setValue(product->w2_calcium); | |
442 ui->sp_mgEdit->setValue(product->w2_magnesium); | |
443 ui->sp_hco3Edit->setValue(Utils::Bicarbonate(product->w2_total_alkalinity, product->w2_ph)); | |
444 ui->sp_caco3Edit->setValue(product->w2_total_alkalinity); | |
445 ui->sp_naEdit->setValue(product->w2_sodium); | |
446 ui->sp_clEdit->setValue(product->w2_chloride); | |
447 ui->sp_so4Edit->setValue(product->w2_sulfate); | |
448 ui->sp_phShow->setValue(product->w2_ph); | |
449 ui->sp_hardnessEdit->setValue(Utils::Hardness(product->w2_calcium, product->w2_magnesium)); | |
450 ui->sp_raEdit->setValue(Utils::ResidualAlkalinity(product->w2_total_alkalinity, product->w2_calcium, product->w2_magnesium)); | |
451 ui->w2_spButton->setChecked(true); | |
430 } else { | 452 } else { |
431 product->sparge_source = 0; // Source 1 | 453 product->sparge_source = 0; // Fallback to source 1 |
432 ui->sp_sourceEdit->setCurrentIndex(0); | 454 ui->w1_spButton->setChecked(true); |
433 } | 455 } |
434 } else if (product->sparge_source == 2) { // Mixed | 456 } else if (product->sparge_source == 2) { // Mixed |
435 if (product->w2_ph > 0.0 && product->w2_amount > 0) { | 457 if (product->w2_ph > 0.0 && product->w2_amount > 0) { |
436 Source_pH = product->wg_ph; | 458 Source_pH = product->wg_ph; |
437 Source_alkalinity = product->wg_total_alkalinity; | 459 Source_alkalinity = product->wg_total_alkalinity; |
460 ui->sp_caEdit->setValue(product->wg_calcium); | |
461 ui->sp_mgEdit->setValue(product->wg_magnesium); | |
462 ui->sp_hco3Edit->setValue(Utils::Bicarbonate(product->wg_total_alkalinity, product->wg_ph)); | |
463 ui->sp_caco3Edit->setValue(product->wg_total_alkalinity); | |
464 ui->sp_naEdit->setValue(product->wg_sodium); | |
465 ui->sp_clEdit->setValue(product->wg_chloride); | |
466 ui->sp_so4Edit->setValue(product->wg_sulfate); | |
467 ui->sp_phShow->setValue(product->wg_ph); | |
468 ui->sp_hardnessEdit->setValue(Utils::Hardness(product->wg_calcium, product->wg_magnesium)); | |
469 ui->sp_raEdit->setValue(Utils::ResidualAlkalinity(product->wg_total_alkalinity, product->wg_calcium, product->wg_magnesium)); | |
470 ui->wg_spButton->setChecked(true); | |
438 } else { | 471 } else { |
439 product->sparge_source = 0; // Source 1 | 472 product->sparge_source = 0; // Fallback to source 1 |
440 ui->sp_sourceEdit->setCurrentIndex(0); | 473 ui->w1_spButton->setChecked(true); |
441 } | 474 } |
442 } | 475 } |
443 | 476 if (product->sparge_source == 0) { |
444 // Step 1: Compute the mole fractions of carbonic (f1o), bicarbonate (f2o) and carbonate(f3o) at the water pH | 477 ui->sp_caEdit->setValue(product->w1_calcium); |
445 double r1 = pow(10, Source_pH - 6.35); | 478 ui->sp_mgEdit->setValue(product->w1_magnesium); |
446 double r2 = pow(10, Source_pH - 10.33); | 479 ui->sp_hco3Edit->setValue(Utils::Bicarbonate(product->w1_total_alkalinity, product->w1_ph)); |
447 double d = 1 + r1 + r1 * r2; | 480 ui->sp_caco3Edit->setValue(product->w1_total_alkalinity); |
448 double f1 = 1 / d; | 481 ui->sp_naEdit->setValue(product->w1_sodium); |
449 double f3 = r1 * r2 / d; | 482 ui->sp_clEdit->setValue(product->w1_chloride); |
450 | 483 ui->sp_so4Edit->setValue(product->w1_sulfate); |
451 // Step 2. Compute the mole fractions at pH = 4.3 (the pH which defines alkalinity) | 484 ui->sp_phShow->setValue(product->w1_ph); |
452 double r143 = pow(10, 4.3 - 6.35); | 485 ui->sp_hardnessEdit->setValue(Utils::Hardness(product->w1_calcium, product->w1_magnesium)); |
453 double r243 = pow(10, 4.3 - 10.33); | 486 ui->sp_raEdit->setValue(Utils::ResidualAlkalinity(product->w1_total_alkalinity, product->w1_calcium, product->w1_magnesium)); |
454 double d43 = 1 + r143 + r143 * r243; | 487 ui->w1_spButton->setChecked(true); |
455 double f143 = 1 / d43; | 488 } |
456 double f343 = r143 * r243 / d43; | 489 // The spargewater is set. |
457 | 490 |
458 // Step 4. Solve | |
459 //double Ct = (Source_alkalinity - 1000 * (pow(10, -4.3) - pow(10, -Source_pH))) / ((f143 - f1) + (f3 - f343)); | |
460 double Ct = Source_alkalinity / 50 / ((f143 - f1) + (f3 - f343)); | |
461 | |
462 // Step 5. Compute mole fractions at desired pH | |
463 double r1g = pow(10, TargetpH - 6.35); | |
464 double r2g = pow(10, TargetpH - 10.33); | |
465 double dg = 1 + r1g + r1g * r2g; | |
466 double f1g = 1 / dg; | |
467 double f3g = r1g * r2g / dg; | |
468 | |
469 // Step 6. Use these to compute the milliequivalents acid required per liter (mEq/L) | |
470 double Acid = Ct * ((f1g - f1) + (f3 - f3g)) + pow(10, -TargetpH) - pow(10, -Source_pH); //mEq/l | |
471 Acid += 0.01; // Add acid that would be required for distilled water. | |
472 | |
473 //Step 8. Get the acid data. | |
474 int AT = product->sparge_acid_type; | 491 int AT = product->sparge_acid_type; |
475 if (AT < 0 || AT >= my_acids.size()) { | 492 if (AT < 0 || AT >= my_acids.size()) { |
476 AT = 0; | 493 AT = 0; |
477 product->sparge_acid_type = 0; | 494 product->sparge_acid_type = 0; |
478 ui->sp_acidtypeEdit->setCurrentIndex(0); | 495 ui->sp_acidtypeEdit->setCurrentIndex(0); |
479 product->sparge_acid_perc = my_acids[0].AcidPrc; | 496 product->sparge_acid_perc = my_acids[0].AcidPrc; |
480 ui->sp_acidpercEdit->setValue(product->sparge_acid_perc); | 497 ui->sp_acidpercEdit->setValue(product->sparge_acid_perc); |
481 } | 498 } |
482 double fract = Utils::CalcFrac(TargetpH, my_acids[AT].pK1, my_acids[AT].pK2, my_acids[AT].pK3); | 499 |
483 | 500 /* |
484 // Step 9. Now divide the mEq required by the "fraction". This is the required number of moles of acid. | 501 * Auto calculate the required acid |
485 Acid /= fract; | 502 */ |
486 | 503 if (product->calc_acid) { |
487 // Step 10. Multiply by molecular weight of the acid | 504 // Step 1: Compute the mole fractions of carbonic (f1o), bicarbonate (f2o) and carbonate(f3o) at the water pH |
488 Acid *= my_acids[AT].MolWt; //mg | 505 double r1 = pow(10, Source_pH - 6.35); |
489 | 506 double r2 = pow(10, Source_pH - 10.33); |
490 // Step 11. Divide by Specific Gravity and Percentage to get the final ml. | 507 double d = 1 + r1 + r1 * r2; |
491 Acid = Acid / my_acids[AT].AcidSG / (product->sparge_acid_perc / 100); //ml | 508 double f1 = 1 / d; |
492 Acid *= product->sparge_volume; //ml acid total | 509 double f3 = r1 * r2 / d; |
493 Acid = round(Acid * 100.0) / 100.0; | 510 |
494 product->sparge_acid_amount = Acid / 1000; | 511 // Step 2. Compute the mole fractions at pH = 4.3 (the pH which defines alkalinity) |
495 ui->sp_acidvolEdit->setValue(Acid); | 512 double r143 = pow(10, 4.3 - 6.35); |
496 | 513 double r243 = pow(10, 4.3 - 10.33); |
514 double d43 = 1 + r143 + r143 * r243; | |
515 double f143 = 1 / d43; | |
516 double f343 = r143 * r243 / d43; | |
517 | |
518 // Step 4. Solve | |
519 double Ct = Source_alkalinity / 50 / ((f143 - f1) + (f3 - f343)); | |
520 | |
521 // Step 5. Compute mole fractions at desired pH | |
522 double r1g = pow(10, TargetpH - 6.35); | |
523 double r2g = pow(10, TargetpH - 10.33); | |
524 double dg = 1 + r1g + r1g * r2g; | |
525 double f1g = 1 / dg; | |
526 double f3g = r1g * r2g / dg; | |
527 | |
528 // Step 6. Use these to compute the milliequivalents acid required per liter (mEq/L) | |
529 double Acid = Ct * ((f1g - f1) + (f3 - f3g)) + pow(10, -TargetpH) - pow(10, -Source_pH); //mEq/l | |
530 Acid += 0.01; // Add acid that would be required for distilled water. | |
531 | |
532 // Step 7. There is no step 7. | |
533 | |
534 // Step 8. Get the acid data. | |
535 double fract = Utils::CalcFrac(TargetpH, my_acids[AT].pK1, my_acids[AT].pK2, my_acids[AT].pK3); | |
536 | |
537 // Step 9. Now divide the mEq required by the "fraction". This is the required number of moles of acid. | |
538 Acid /= fract; | |
539 | |
540 // Step 10. Multiply by molecular weight of the acid | |
541 Acid *= my_acids[AT].MolWt; //mg | |
542 | |
543 // Step 11. Divide by Specific Gravity and Percentage to get the final ml. | |
544 double RealSG = round(((my_acids[AT].AcidSG - 1000) * (product->sparge_acid_perc / 100)) + 1000); | |
545 Acid = Acid / RealSG; //ml | |
546 Acid *= product->sparge_volume; //ml acid total at 100% | |
547 Acid /= my_acids[AT].AcidPrc / 100; //ml acid at supplied strength | |
548 Acid = round(Acid * 100.0) / 100.0; | |
549 product->sparge_acid_amount = Acid / 1000; | |
550 QString w = my_acids[AT].name_en + ' ' + my_acids[AT].name_nl; | |
551 brewing_salt_sub(w, Acid, MISC_USES_SPARGE); // Put it in the miscs table. | |
552 ui->sp_acidvolEdit->setValue(Acid); | |
553 } | |
554 | |
555 ui->sp_phShow->setValue(product->sparge_ph); | |
497 // Finally calculate the estimate preboil pH | 556 // Finally calculate the estimate preboil pH |
498 product->est_preboil_ph = -log10(((pow(10, -product->mash_ph) * product->wg_amount) + (pow(10, -product->sparge_ph) * product->brew_sparge_est)) / | 557 product->est_preboil_ph = -log10(((pow(10, -product->mash_ph) * product->wg_amount) + (pow(10, -product->sparge_ph) * product->brew_sparge_est)) / |
499 (product->wg_amount + product->brew_sparge_est)); | 558 (product->wg_amount + product->brew_sparge_est)); |
500 ui->preboil_phEdit->setValue(product->est_preboil_ph); | 559 ui->preboil_phEdit->setValue(product->est_preboil_ph); |
501 ui->brew_preboilphShow->setValue(product->est_preboil_ph); | 560 ui->brew_preboilphShow->setValue(product->est_preboil_ph); |
502 } | 561 } |
503 | 562 |
504 | 563 |
505 void EditProduct::sp_source_changed(int val) | 564 void EditProduct::sp_group_changed(int val) |
506 { | 565 { |
507 product->sparge_source = val; | 566 if (val != product->sparge_source) { |
508 calcSparge(); | 567 product->sparge_source = val; |
509 is_changed(); | 568 calcSparge(); |
569 is_changed(); | |
570 } | |
510 } | 571 } |
511 | 572 |
512 | 573 |
513 void EditProduct::sp_volume_changed(double val) | 574 void EditProduct::sp_volume_changed(double val) |
514 { | 575 { |
520 | 581 |
521 | 582 |
522 void EditProduct::sp_temp_changed(double val) | 583 void EditProduct::sp_temp_changed(double val) |
523 { | 584 { |
524 product->sparge_temp = val; | 585 product->sparge_temp = val; |
525 ui->brew_spargetempShow->setValue(val); | |
526 calcSparge(); | 586 calcSparge(); |
527 is_changed(); | 587 is_changed(); |
528 } | 588 } |
529 | 589 |
530 | 590 |
531 void EditProduct::sp_type_changed(int val) | 591 void EditProduct::sp_type_changed(int val) |
532 { | 592 { |
593 if (val == product->sparge_acid_type) | |
594 return; | |
595 | |
596 qDebug() << "sp_type_changed" << val << "old" << product->sparge_acid_type; | |
597 /* | |
598 * First remove current acid. | |
599 */ | |
600 QString w = my_acids[product->sparge_acid_type].name_en + ' ' + my_acids[product->sparge_acid_type].name_nl; | |
601 brewing_salt_sub(w, 0, MISC_USES_SPARGE); | |
602 | |
533 product->sparge_acid_type = val; | 603 product->sparge_acid_type = val; |
604 w = my_acids[product->sparge_acid_type].name_en + ' ' + my_acids[product->sparge_acid_type].name_nl; | |
605 | |
534 product->sparge_acid_perc = my_acids[val].AcidPrc; | 606 product->sparge_acid_perc = my_acids[val].AcidPrc; |
535 ui->sp_acidpercEdit->setValue(product->sparge_acid_perc); | 607 ui->sp_acidpercEdit->setValue(product->sparge_acid_perc); |
608 brewing_salt_sub(w, ui->sp_acidvolEdit->value(), MISC_USES_SPARGE); // For now, set old amount. | |
609 | |
536 calcSparge(); | 610 calcSparge(); |
537 is_changed(); | 611 is_changed(); |
538 } | 612 } |
539 | 613 |
540 | 614 |
542 { | 616 { |
543 product->sparge_ph = val; | 617 product->sparge_ph = val; |
544 ui->brew_spargephShow->setValue(product->sparge_ph); | 618 ui->brew_spargephShow->setValue(product->sparge_ph); |
545 calcSparge(); | 619 calcSparge(); |
546 is_changed(); | 620 is_changed(); |
621 } | |
622 | |
623 | |
624 void EditProduct::sp_acid_changed(double val) | |
625 { | |
626 if (product->calc_acid) | |
627 return; | |
628 | |
629 qDebug() << "sp_acid_changed" << val << product->sparge_acid_amount * 1000.0; | |
630 | |
631 double TargetpH = product->sparge_ph; | |
632 double Source_pH = product->w1_ph; | |
633 double Source_alkalinity = product->w1_total_alkalinity; | |
634 | |
635 if (product->sparge_source == 1) { // Source 2 | |
636 if (product->w2_ph > 0.0 && product->w2_amount > 0) { | |
637 Source_pH = product->w2_ph; | |
638 Source_alkalinity = product->w2_total_alkalinity; | |
639 } | |
640 } else if (product->sparge_source == 2) { // Mixed | |
641 if (product->w2_ph > 0.0 && product->w2_amount > 0) { | |
642 Source_pH = product->wg_ph; | |
643 Source_alkalinity = product->wg_total_alkalinity; | |
644 } | |
645 } | |
646 | |
647 int AT = product->sparge_acid_type; | |
648 if (AT < 0 || AT >= my_acids.size()) { | |
649 AT = 0; | |
650 product->sparge_acid_type = 0; | |
651 ui->sp_acidtypeEdit->setCurrentIndex(0); | |
652 product->sparge_acid_perc = my_acids[0].AcidPrc; | |
653 ui->sp_acidpercEdit->setValue(product->sparge_acid_perc); | |
654 } | |
655 | |
656 bool go_up = (val < (product->sparge_acid_amount * 1000.0)); | |
657 bool loop = true; | |
658 | |
659 while (loop) { | |
660 | |
661 if (go_up) | |
662 TargetpH += 0.001; | |
663 else | |
664 TargetpH -= 0.001; | |
665 //qDebug() << " TargetpH" << TargetpH << "up" << go_up; | |
666 | |
667 // Step 1: Compute the mole fractions of carbonic (f1o), bicarbonate (f2o) and carbonate(f3o) at the water pH | |
668 double r1 = pow(10, Source_pH - 6.35); | |
669 double r2 = pow(10, Source_pH - 10.33); | |
670 double d = 1 + r1 + r1 * r2; | |
671 double f1 = 1 / d; | |
672 double f3 = r1 * r2 / d; | |
673 | |
674 // Step 2. Compute the mole fractions at pH = 4.3 (the pH which defines alkalinity) | |
675 double r143 = pow(10, 4.3 - 6.35); | |
676 double r243 = pow(10, 4.3 - 10.33); | |
677 double d43 = 1 + r143 + r143 * r243; | |
678 double f143 = 1 / d43; | |
679 double f343 = r143 * r243 / d43; | |
680 | |
681 // Step 4. Solve | |
682 double Ct = Source_alkalinity / 50 / ((f143 - f1) + (f3 - f343)); | |
683 | |
684 // Step 5. Compute mole fractions at desired pH | |
685 double r1g = pow(10, TargetpH - 6.35); | |
686 double r2g = pow(10, TargetpH - 10.33); | |
687 double dg = 1 + r1g + r1g * r2g; | |
688 double f1g = 1 / dg; | |
689 double f3g = r1g * r2g / dg; | |
690 | |
691 // Step 6. Use these to compute the milliequivalents acid required per liter (mEq/L) | |
692 double Acid = Ct * ((f1g - f1) + (f3 - f3g)) + pow(10, -TargetpH) - pow(10, -Source_pH); //mEq/l | |
693 Acid += 0.01; // Add acid that would be required for distilled water. | |
694 | |
695 // Step 7. There is no step 7. | |
696 | |
697 // Step 8. Get the acid data. | |
698 double fract = Utils::CalcFrac(TargetpH, my_acids[AT].pK1, my_acids[AT].pK2, my_acids[AT].pK3); | |
699 | |
700 // Step 9. Now divide the mEq required by the "fraction". This is the required number of moles of acid. | |
701 Acid /= fract; | |
702 | |
703 // Step 10. Multiply by molecular weight of the acid | |
704 Acid *= my_acids[AT].MolWt; //mg | |
705 | |
706 // Step 11. Divide by Specific Gravity and Percentage to get the final ml. | |
707 double RealSG = round(((my_acids[AT].AcidSG - 1000) * (product->sparge_acid_perc / 100)) + 1000); | |
708 Acid = Acid / RealSG; //ml | |
709 Acid *= product->sparge_volume; //ml acid total at 100% | |
710 Acid /= my_acids[AT].AcidPrc / 100; //ml acid at supplied strength | |
711 Acid = round(Acid * 100.0) / 100.0; | |
712 product->sparge_acid_amount = Acid / 1000; | |
713 //qDebug() << " acid" << product->sparge_acid_amount; | |
714 | |
715 if (go_up && (val > (product->sparge_acid_amount * 1000.0))) | |
716 loop = false; | |
717 else if (! go_up && (val < (product->sparge_acid_amount * 1000.0))) | |
718 loop = false; | |
719 | |
720 //qDebug() << " test" << loop << go_up << val << product->sparge_acid_amount * 1000.0; | |
721 } | |
722 | |
723 const QSignalBlocker blocker1(ui->sp_phEdit); | |
724 product->sparge_ph = round(TargetpH * 100) / 100; | |
725 ui->sp_phEdit->setValue(product->sparge_ph); | |
726 ui->sp_phShow->setValue(product->sparge_ph); | |
727 | |
728 QString w = my_acids[AT].name_en + ' ' + my_acids[AT].name_nl; | |
729 set_brewing_salt(w, val, MISC_USES_SPARGE); | |
730 //qDebug() << " new" << product->sparge_ph << val; | |
547 } | 731 } |
548 | 732 |
549 | 733 |
550 double EditProduct::GetBUGU() | 734 double EditProduct::GetBUGU() |
551 { | 735 { |
573 ui->mw_autoEdit->setChecked(product->calc_acid); | 757 ui->mw_autoEdit->setChecked(product->calc_acid); |
574 ui->mw_phEdit->setReadOnly(! product->calc_acid); | 758 ui->mw_phEdit->setReadOnly(! product->calc_acid); |
575 ui->mw_phEdit->setButtonSymbols(product->calc_acid ? QAbstractSpinBox::UpDownArrows : QAbstractSpinBox::NoButtons); | 759 ui->mw_phEdit->setButtonSymbols(product->calc_acid ? QAbstractSpinBox::UpDownArrows : QAbstractSpinBox::NoButtons); |
576 ui->mw_acidvolEdit->setReadOnly(product->calc_acid); | 760 ui->mw_acidvolEdit->setReadOnly(product->calc_acid); |
577 ui->mw_acidvolEdit->setButtonSymbols(product->calc_acid ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows); | 761 ui->mw_acidvolEdit->setButtonSymbols(product->calc_acid ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows); |
762 ui->sp_phEdit->setReadOnly(! product->calc_acid); | |
763 ui->sp_phEdit->setButtonSymbols(product->calc_acid ? QAbstractSpinBox::UpDownArrows : QAbstractSpinBox::NoButtons); | |
764 ui->sp_acidvolEdit->setReadOnly(product->calc_acid); | |
765 ui->sp_acidvolEdit->setButtonSymbols(product->calc_acid ? QAbstractSpinBox::NoButtons : QAbstractSpinBox::UpDownArrows); | |
578 is_changed(); | 766 is_changed(); |
579 calcWater(); | 767 calcWater(); |
580 } | 768 } |
581 | 769 |
582 | 770 |
599 if (product->calc_acid) | 787 if (product->calc_acid) |
600 return; | 788 return; |
601 | 789 |
602 qDebug() << "on_mw_acid_changed" << val; | 790 qDebug() << "on_mw_acid_changed" << val; |
603 QString w = my_acids[product->wa_acid_name].name_en + ' ' + my_acids[product->wa_acid_name].name_nl; | 791 QString w = my_acids[product->wa_acid_name].name_en + ' ' + my_acids[product->wa_acid_name].name_nl; |
604 set_brewing_salt(w, val); | 792 set_brewing_salt(w, val, MISC_USES_MASH); |
605 } | 793 } |
606 | 794 |
607 | 795 |
608 void EditProduct::mw_type_changed(int val) | 796 void EditProduct::mw_type_changed(int val) |
609 { | 797 { |
613 qDebug() << "on_mw_type_changed" << val << "old" << product->wa_acid_name; | 801 qDebug() << "on_mw_type_changed" << val << "old" << product->wa_acid_name; |
614 /* | 802 /* |
615 * First remove current acid. | 803 * First remove current acid. |
616 */ | 804 */ |
617 QString w = my_acids[product->wa_acid_name].name_en + ' ' + my_acids[product->wa_acid_name].name_nl; | 805 QString w = my_acids[product->wa_acid_name].name_en + ' ' + my_acids[product->wa_acid_name].name_nl; |
618 brewing_salt_sub(w, 0); | 806 brewing_salt_sub(w, 0, MISC_USES_MASH); |
619 | 807 |
620 product->wa_acid_name = val; | 808 product->wa_acid_name = val; |
621 w = my_acids[product->wa_acid_name].name_en + ' ' + my_acids[product->wa_acid_name].name_nl; | 809 w = my_acids[product->wa_acid_name].name_en + ' ' + my_acids[product->wa_acid_name].name_nl; |
622 | 810 |
623 product->wa_acid_perc = my_acids.at(val).AcidPrc; | 811 product->wa_acid_perc = my_acids.at(val).AcidPrc; |
624 ui->mw_acidpercEdit->setValue(my_acids.at(val).AcidPrc); | 812 ui->mw_acidpercEdit->setValue(my_acids.at(val).AcidPrc); |
625 brewing_salt_sub(w, ui->mw_acidvolEdit->value()); // For now, set old amount. | 813 brewing_salt_sub(w, ui->mw_acidvolEdit->value(), MISC_USES_MASH); // For now, set old amount. |
626 | 814 |
627 is_changed(); | 815 is_changed(); |
628 calcWater(); | 816 calcWater(); |
629 } | 817 } |
630 | 818 |
682 if (query.first()) { | 870 if (query.first()) { |
683 if ((query.value("unlimited_stock").toInt() == 0) && (query.value("inventory").toDouble() < product->w2_amount)) { | 871 if ((query.value("unlimited_stock").toInt() == 0) && (query.value("inventory").toDouble() < product->w2_amount)) { |
684 product->waters_ok = false; | 872 product->waters_ok = false; |
685 qDebug() << "w2_amount too low"; | 873 qDebug() << "w2_amount too low"; |
686 } | 874 } |
875 ui->w2_spButton->setEnabled(true); | |
876 ui->wg_spButton->setEnabled(true); | |
687 } | 877 } |
878 } else { | |
879 /* | |
880 * Block selecting sparge water 2 and mixed water. | |
881 */ | |
882 ui->w2_spButton->setEnabled(false); | |
883 ui->wg_spButton->setEnabled(false); | |
884 product->sparge_source = 0; // Only water source 1 | |
688 } | 885 } |
689 } | 886 } |
690 | 887 |
691 | 888 |
692 void EditProduct::w1_name_changed(int val) | 889 void EditProduct::w1_name_changed(int val) |
720 product->w1_sulfate = query.value("sulfate").toDouble(); | 917 product->w1_sulfate = query.value("sulfate").toDouble(); |
721 product->w1_ph = query.value("ph").toDouble(); | 918 product->w1_ph = query.value("ph").toDouble(); |
722 | 919 |
723 ui->w1_caEdit->setValue(product->w1_calcium); | 920 ui->w1_caEdit->setValue(product->w1_calcium); |
724 ui->w1_mgEdit->setValue(product->w1_magnesium); | 921 ui->w1_mgEdit->setValue(product->w1_magnesium); |
725 ui->w1_hco3Edit->setValue(product->w1_total_alkalinity * 1.22); | 922 ui->w1_hco3Edit->setValue(Utils::Bicarbonate(product->w1_total_alkalinity, product->w1_ph)); |
726 ui->w1_caco3Edit->setValue(product->w1_total_alkalinity); | 923 ui->w1_caco3Edit->setValue(product->w1_total_alkalinity); |
727 ui->w1_naEdit->setValue(product->w1_sodium); | 924 ui->w1_naEdit->setValue(product->w1_sodium); |
728 ui->w1_clEdit->setValue(product->w1_chloride); | 925 ui->w1_clEdit->setValue(product->w1_chloride); |
729 ui->w1_so4Edit->setValue(product->w1_sulfate); | 926 ui->w1_so4Edit->setValue(product->w1_sulfate); |
730 ui->w1_phEdit->setValue(product->w1_ph); | 927 ui->w1_phEdit->setValue(product->w1_ph); |
731 ui->w1_hardnessEdit->setValue(Utils::Hardness(product->w1_calcium, product->w1_magnesium)); | 928 ui->w1_hardnessEdit->setValue(Utils::Hardness(product->w1_calcium, product->w1_magnesium)); |
732 ui->w1_raEdit->setValue(Utils::RA_ppm(product->w1_total_alkalinity, product->w1_calcium, product->w1_magnesium)); | 929 ui->w1_raEdit->setValue(Utils::ResidualAlkalinity(product->w1_total_alkalinity, product->w1_calcium, product->w1_magnesium)); |
733 | 930 |
734 check_waters(); | 931 check_waters(); |
735 is_changed(); | 932 is_changed(); |
736 calcWater(); | 933 calcWater(); |
737 } | 934 } |
772 product->w2_sodium = query.value(7).toDouble(); | 969 product->w2_sodium = query.value(7).toDouble(); |
773 product->w2_chloride = query.value(6).toDouble(); | 970 product->w2_chloride = query.value(6).toDouble(); |
774 product->w2_sulfate = query.value(5).toDouble(); | 971 product->w2_sulfate = query.value(5).toDouble(); |
775 product->w2_ph = query.value(9).toDouble(); | 972 product->w2_ph = query.value(9).toDouble(); |
776 hardness = Utils::Hardness(product->w2_calcium, product->w2_magnesium); | 973 hardness = Utils::Hardness(product->w2_calcium, product->w2_magnesium); |
777 ra_ppm = Utils::RA_ppm(product->w2_total_alkalinity, product->w2_calcium, product->w2_magnesium); | 974 ra_ppm = Utils::ResidualAlkalinity(product->w2_total_alkalinity, product->w2_calcium, product->w2_magnesium); |
778 } | 975 } |
779 ui->w1_volEdit->setValue(product->w1_amount); | 976 ui->w1_volEdit->setValue(product->w1_amount); |
780 ui->w2_volEdit->setValue(product->w2_amount); | 977 ui->w2_volEdit->setValue(product->w2_amount); |
781 ui->w2_caEdit->setValue(product->w2_calcium); | 978 ui->w2_caEdit->setValue(product->w2_calcium); |
782 ui->w2_mgEdit->setValue(product->w2_magnesium); | 979 ui->w2_mgEdit->setValue(product->w2_magnesium); |
783 ui->w2_hco3Edit->setValue(product->w2_total_alkalinity * 1.22); | 980 ui->w2_hco3Edit->setValue(Utils::Bicarbonate(product->w2_total_alkalinity, product->w2_ph)); |
784 ui->w2_caco3Edit->setValue(product->w2_total_alkalinity); | 981 ui->w2_caco3Edit->setValue(product->w2_total_alkalinity); |
785 ui->w2_naEdit->setValue(product->w2_sodium); | 982 ui->w2_naEdit->setValue(product->w2_sodium); |
786 ui->w2_clEdit->setValue(product->w2_chloride); | 983 ui->w2_clEdit->setValue(product->w2_chloride); |
787 ui->w2_so4Edit->setValue(product->w2_sulfate); | 984 ui->w2_so4Edit->setValue(product->w2_sulfate); |
788 ui->w2_phEdit->setValue(product->w2_ph); | 985 ui->w2_phEdit->setValue(product->w2_ph); |
823 ui->wt_caco3Edit->setValue(query.value("total_alkalinity").toDouble()); | 1020 ui->wt_caco3Edit->setValue(query.value("total_alkalinity").toDouble()); |
824 ui->wt_naEdit->setValue(query.value("sodium").toDouble()); | 1021 ui->wt_naEdit->setValue(query.value("sodium").toDouble()); |
825 ui->wt_clEdit->setValue(query.value("chloride").toDouble()); | 1022 ui->wt_clEdit->setValue(query.value("chloride").toDouble()); |
826 ui->wt_so4Edit->setValue(query.value("sulfate").toDouble()); | 1023 ui->wt_so4Edit->setValue(query.value("sulfate").toDouble()); |
827 ui->wt_hardnessEdit->setValue(Utils::Hardness(query.value("calcium").toDouble(), query.value("magnesium").toDouble())); | 1024 ui->wt_hardnessEdit->setValue(Utils::Hardness(query.value("calcium").toDouble(), query.value("magnesium").toDouble())); |
828 ui->wt_raEdit->setValue(Utils::RA_ppm(query.value("total_alkalinity").toDouble(), query.value("calcium").toDouble(), query.value("magnesium").toDouble())); | 1025 ui->wt_raEdit->setValue(Utils::ResidualAlkalinity(query.value("total_alkalinity").toDouble(), query.value("calcium").toDouble(), query.value("magnesium").toDouble())); |
829 } | 1026 } |
830 calcWater(); | 1027 calcWater(); |
831 } | 1028 } |
832 | 1029 |
833 | 1030 |
866 product->wg_amount = mash_infuse; | 1063 product->wg_amount = mash_infuse; |
867 ui->wg_volEdit->setValue(mash_infuse); | 1064 ui->wg_volEdit->setValue(mash_infuse); |
868 } | 1065 } |
869 | 1066 |
870 | 1067 |
871 void EditProduct::wb_cacl2_changed(double val) { set_brewing_salt("CaCl2", val); } | 1068 void EditProduct::wb_cacl2_changed(double val) { set_brewing_salt("CaCl2", val, MISC_USES_MASH); } |
872 void EditProduct::wb_caso4_changed(double val) { set_brewing_salt("CaSO4", val); } | 1069 void EditProduct::wb_caso4_changed(double val) { set_brewing_salt("CaSO4", val, MISC_USES_MASH); } |
873 void EditProduct::wb_mgso4_changed(double val) { set_brewing_salt("MgSO4", val); } | 1070 void EditProduct::wb_mgso4_changed(double val) { set_brewing_salt("MgSO4", val, MISC_USES_MASH); } |
874 void EditProduct::wb_nacl_changed(double val) { set_brewing_salt("NaCl", val); } | 1071 void EditProduct::wb_nacl_changed(double val) { set_brewing_salt("NaCl", val, MISC_USES_MASH); } |
875 void EditProduct::wb_mgcl2_changed(double val) { set_brewing_salt("MgCl2", val); } | 1072 void EditProduct::wb_mgcl2_changed(double val) { set_brewing_salt("MgCl2", val, MISC_USES_MASH); } |
876 void EditProduct::wb_nahco3_changed(double val) { set_brewing_salt("NaHCO3", val); } | 1073 void EditProduct::wb_nahco3_changed(double val) { set_brewing_salt("NaHCO3", val, MISC_USES_MASH); } |
877 void EditProduct::wb_caco3_changed(double val) { set_brewing_salt("CaCO3", val); } | 1074 void EditProduct::wb_caco3_changed(double val) { set_brewing_salt("CaCO3", val, MISC_USES_MASH); } |
878 | 1075 void EditProduct::sp_cacl2_changed(double val) { set_brewing_salt("CaCl2", val, MISC_USES_SPARGE); } |
879 | 1076 void EditProduct::sp_caso4_changed(double val) { set_brewing_salt("CaSO4", val, MISC_USES_SPARGE); } |
1077 void EditProduct::sp_mgso4_changed(double val) { set_brewing_salt("MgSO4", val, MISC_USES_SPARGE); } | |
1078 void EditProduct::sp_nacl_changed(double val) { set_brewing_salt("NaCl", val, MISC_USES_SPARGE); } | |
1079 void EditProduct::sp_mgcl2_changed(double val) { set_brewing_salt("MgCl2", val, MISC_USES_SPARGE); } | |
1080 |