394 } |
394 } |
395 ui->wb_phEdit->setStyleSheet((ph < 5.2 || ph > 5.6) ? "background-color: red":"background-color: green"); |
395 ui->wb_phEdit->setStyleSheet((ph < 5.2 || ph > 5.6) ? "background-color: red":"background-color: green"); |
396 ui->wb_hco3Edit->setStyleSheet((bicarbonate > 250) ? "background-color: red":"background-color: green"); |
396 ui->wb_hco3Edit->setStyleSheet((bicarbonate > 250) ? "background-color: red":"background-color: green"); |
397 ui->wb_caco3Edit->setStyleSheet((bicarbonate > 250) ? "background-color: red":"background-color: green"); |
397 ui->wb_caco3Edit->setStyleSheet((bicarbonate > 250) ? "background-color: red":"background-color: green"); |
398 |
398 |
399 // calcSparge(); |
399 calcSparge(); |
|
400 } |
|
401 |
|
402 |
|
403 /* |
|
404 * Based on the work of ajDeLange. |
|
405 */ |
|
406 void EditRecipe::calcSparge() |
|
407 { |
|
408 double TargetpH = recipe->sparge_ph; |
|
409 double Source_pH = recipe->w1_ph; |
|
410 double Source_alkalinity = recipe->w1_total_alkalinity; |
|
411 |
|
412 qDebug() << "calcSparge()"; |
|
413 |
|
414 const QSignalBlocker blocker1(ui->sp_sourceEdit); |
|
415 |
|
416 // Select watersource or fallback to the first source. |
|
417 if (recipe->sparge_source == 1) { // Source 2 |
|
418 if (recipe->w2_ph > 0.0 && recipe->w2_amount > 0) { |
|
419 Source_pH = recipe->w2_ph; |
|
420 Source_alkalinity = recipe->w2_total_alkalinity; |
|
421 } else { |
|
422 recipe->sparge_source = 0; // Source 1 |
|
423 ui->sp_sourceEdit->setCurrentIndex(0); |
|
424 } |
|
425 } else if (recipe->sparge_source == 2) { // Mixed |
|
426 if (recipe->w2_ph > 0.0 && recipe->w2_amount > 0) { |
|
427 Source_pH = recipe->wg_ph; |
|
428 Source_alkalinity = recipe->wg_total_alkalinity; |
|
429 } else { |
|
430 recipe->sparge_source = 0; // Source 1 |
|
431 ui->sp_sourceEdit->setCurrentIndex(0); |
|
432 } |
|
433 } |
|
434 |
|
435 // Step 1: Compute the mole fractions of carbonic (f1o), bicarbonate (f2o) and carbonate(f3o) at the water pH |
|
436 double r1 = pow(10, Source_pH - 6.35); |
|
437 double r2 = pow(10, Source_pH - 10.33); |
|
438 double d = 1 + r1 + r1 * r2; |
|
439 double f1 = 1 / d; |
|
440 double f3 = r1 * r2 / d; |
|
441 |
|
442 // Step 2. Compute the mole fractions at pH = 4.3 (the pH which defines alkalinity) |
|
443 double r143 = pow(10, 4.3 - 6.35); |
|
444 double r243 = pow(10, 4.3 - 10.33); |
|
445 double d43 = 1 + r143 + r143 * r243; |
|
446 double f143 = 1 / d43; |
|
447 double f343 = r143 * r243 / d43; |
|
448 |
|
449 // Step 4. Solve |
|
450 //double Ct = (Source_alkalinity - 1000 * (pow(10, -4.3) - pow(10, -Source_pH))) / ((f143 - f1) + (f3 - f343)); |
|
451 double Ct = Source_alkalinity / 50 / ((f143 - f1) + (f3 - f343)); |
|
452 |
|
453 // Step 5. Compute mole fractions at desired pH |
|
454 double r1g = pow(10, TargetpH - 6.35); |
|
455 double r2g = pow(10, TargetpH - 10.33); |
|
456 double dg = 1 + r1g + r1g * r2g; |
|
457 double f1g = 1 / dg; |
|
458 double f3g = r1g * r2g / dg; |
|
459 |
|
460 // Step 6. Use these to compute the milliequivalents acid required per liter (mEq/L) |
|
461 double Acid = Ct * ((f1g - f1) + (f3 - f3g)) + pow(10, -TargetpH) - pow(10, -Source_pH); //mEq/l |
|
462 Acid += 0.01; // Add acid that would be required for distilled water. |
|
463 |
|
464 //Step 8. Get the acid data. |
|
465 int AT = recipe->sparge_acid_type; |
|
466 if (AT < 0 || AT >= my_acids.size()) { |
|
467 AT = 0; |
|
468 recipe->sparge_acid_type = 0; |
|
469 ui->sp_acidtypeEdit->setCurrentIndex(0); |
|
470 recipe->sparge_acid_perc = my_acids[0].AcidPrc; |
|
471 ui->sp_acidpercEdit->setValue(recipe->sparge_acid_perc); |
|
472 } |
|
473 double fract = Utils::CalcFrac(TargetpH, my_acids[AT].pK1, my_acids[AT].pK2, my_acids[AT].pK3); |
|
474 |
|
475 // Step 9. Now divide the mEq required by the "fraction". This is the required number of moles of acid. |
|
476 Acid /= fract; |
|
477 |
|
478 // Step 10. Multiply by molecular weight of the acid |
|
479 Acid *= my_acids[AT].MolWt; //mg |
|
480 |
|
481 // Step 11. Divide by Specific Gravity and Percentage to get the final ml. |
|
482 Acid = Acid / my_acids[AT].AcidSG / (recipe->sparge_acid_perc / 100); //ml |
|
483 Acid *= recipe->sparge_volume; //ml acid total |
|
484 Acid = round(Acid * 100.0) / 100.0; |
|
485 recipe->sparge_acid_amount = Acid / 1000; |
|
486 ui->sp_acidvolEdit->setValue(Acid); |
|
487 } |
|
488 |
|
489 |
|
490 void EditRecipe::sp_source_changed(int val) |
|
491 { |
|
492 recipe->sparge_source = val; |
|
493 calcSparge(); |
|
494 is_changed(); |
|
495 } |
|
496 |
|
497 |
|
498 void EditRecipe::sp_type_changed(int val) |
|
499 { |
|
500 recipe->sparge_acid_type = val; |
|
501 recipe->sparge_acid_perc = my_acids[val].AcidPrc; |
|
502 ui->sp_acidpercEdit->setValue(recipe->sparge_acid_perc); |
|
503 calcSparge(); |
|
504 is_changed(); |
|
505 } |
|
506 |
|
507 |
|
508 void EditRecipe::sp_ph_changed(double val) |
|
509 { |
|
510 recipe->sparge_ph = val; |
|
511 calcSparge(); |
|
512 is_changed(); |
400 } |
513 } |
401 |
514 |
402 |
515 |
403 double EditRecipe::GetBUGU() |
516 double EditRecipe::GetBUGU() |
404 { |
517 { |