# HG changeset patch # User Michiel Broek # Date 1658313842 -7200 # Node ID 4bc746c656508e3a5ad6ed87b4135d9cf1636cad # Parent 1efe29f64551135add90e4180e84dab3ffc0dd5e Added sparge water salt additions. Adjust sparge acid amount if manual calculations and the water volume is changed. diff -r 1efe29f64551 -r 4bc746c65650 src/EditProduct.cpp --- a/src/EditProduct.cpp Tue Jul 19 16:00:52 2022 +0200 +++ b/src/EditProduct.cpp Wed Jul 20 12:44:02 2022 +0200 @@ -460,7 +460,6 @@ ui->sp_phEdit->setValue(product->sparge_ph); ui->sp_acidtypeEdit->setCurrentIndex(product->sparge_acid_type); ui->sp_acidpercEdit->setValue(product->sparge_acid_perc); - ui->sp_acidvolEdit->setValue(product->sparge_acid_amount); check_waters(); // Tab brewday. diff -r 1efe29f64551 -r 4bc746c65650 src/EditProductTab8.cpp --- a/src/EditProductTab8.cpp Tue Jul 19 16:00:52 2022 +0200 +++ b/src/EditProductTab8.cpp Wed Jul 20 12:44:02 2022 +0200 @@ -470,52 +470,58 @@ void EditProduct::calcSparge() { double TargetpH = product->sparge_ph; - double Source_pH = product->w1_ph; - double Source_alkalinity = product->w1_total_alkalinity; + double Source_pH = 7.0; qDebug() << "calcSparge()"; - setButtons(product->stage > PROD_STAGE_BREW); if (product->sparge_source == 1 && product->w2_ph > 0.0) { + product->ws_calcium = product->w2_calcium; + product->ws_magnesium = product->w2_magnesium; + product->ws_total_alkalinity = product->w2_total_alkalinity; + product->ws_sodium = product->w2_sodium; + product->ws_chloride = product->w2_chloride; + product->ws_sulfate = product->w2_sulfate; Source_pH = product->w2_ph; - Source_alkalinity = product->w2_total_alkalinity; - ui->sp_caEdit->setValue(product->w2_calcium); - ui->sp_mgEdit->setValue(product->w2_magnesium); - ui->sp_hco3Edit->setValue(Utils::Bicarbonate(product->w2_total_alkalinity, product->w2_ph)); - ui->sp_caco3Edit->setValue(product->w2_total_alkalinity); - ui->sp_naEdit->setValue(product->w2_sodium); - ui->sp_clEdit->setValue(product->w2_chloride); - ui->sp_so4Edit->setValue(product->w2_sulfate); - ui->sp_phShow->setValue(product->w2_ph); - ui->sp_hardnessEdit->setValue(Utils::Hardness(product->w2_calcium, product->w2_magnesium)); - ui->sp_raEdit->setValue(Utils::ResidualAlkalinity(product->w2_total_alkalinity, product->w2_calcium, product->w2_magnesium)); } else if (product->sparge_source == 2 && product->w2_ph > 0.0) { + product->ws_calcium = product->wg_calcium; + product->ws_magnesium = product->wg_magnesium; + product->ws_total_alkalinity = product->wg_total_alkalinity; + product->ws_sodium = product->wg_sodium; + product->ws_chloride = product->wg_chloride; + product->ws_sulfate = product->wg_sulfate; Source_pH = product->wg_ph; - Source_alkalinity = product->wg_total_alkalinity; - ui->sp_caEdit->setValue(product->wg_calcium); - ui->sp_mgEdit->setValue(product->wg_magnesium); - ui->sp_hco3Edit->setValue(Utils::Bicarbonate(product->wg_total_alkalinity, product->wg_ph)); - ui->sp_caco3Edit->setValue(product->wg_total_alkalinity); - ui->sp_naEdit->setValue(product->wg_sodium); - ui->sp_clEdit->setValue(product->wg_chloride); - ui->sp_so4Edit->setValue(product->wg_sulfate); - ui->sp_phShow->setValue(product->wg_ph); - ui->sp_hardnessEdit->setValue(Utils::Hardness(product->wg_calcium, product->wg_magnesium)); - ui->sp_raEdit->setValue(Utils::ResidualAlkalinity(product->wg_total_alkalinity, product->wg_calcium, product->wg_magnesium)); } else { - ui->sp_caEdit->setValue(product->w1_calcium); - ui->sp_mgEdit->setValue(product->w1_magnesium); - ui->sp_hco3Edit->setValue(Utils::Bicarbonate(product->w1_total_alkalinity, product->w1_ph)); - ui->sp_caco3Edit->setValue(product->w1_total_alkalinity); - ui->sp_naEdit->setValue(product->w1_sodium); - ui->sp_clEdit->setValue(product->w1_chloride); - ui->sp_so4Edit->setValue(product->w1_sulfate); - ui->sp_phShow->setValue(product->w1_ph); - ui->sp_hardnessEdit->setValue(Utils::Hardness(product->w1_calcium, product->w1_magnesium)); - ui->sp_raEdit->setValue(Utils::ResidualAlkalinity(product->w1_total_alkalinity, product->w1_calcium, product->w1_magnesium)); + product->ws_calcium = product->w1_calcium; + product->ws_magnesium = product->w1_magnesium; + product->ws_total_alkalinity = product->w1_total_alkalinity; + product->ws_sodium = product->w1_sodium; + product->ws_chloride = product->w1_chloride; + product->ws_sulfate = product->w1_sulfate; + Source_pH = product->w1_ph; } - // The spargewater is set. + + /* Calculate Salt additions */ + if (product->sparge_volume > 0) { + product->ws_calcium += ( ui->ss_cacl2Edit->value() * MMCa / MMCaCl2 * 1000 + ui->ss_caso4Edit->value() * MMCa / MMCaSO4 * 1000) / product->sparge_volume; + product->ws_magnesium += (ui->ss_mgso4Edit->value() * MMMg / MMMgSO4 * 1000 + ui->ss_mgcl2Edit->value() * MMMg / MMMgCl2 * 1000) / product->sparge_volume; + product->ws_sodium += (ui->ss_naclEdit->value() * MMNa / MMNaCl * 1000) / product->sparge_volume; + product->ws_sulfate += (ui->ss_caso4Edit->value() * MMSO4 / MMCaSO4 * 1000 + ui->ss_mgso4Edit->value() * MMSO4 / MMMgSO4 * 1000) / product->sparge_volume; + product->ws_chloride += (2 * ui->ss_cacl2Edit->value() * MMCl / MMCaCl2 * 1000 + ui->ss_naclEdit->value() * MMCl / MMNaCl * 1000 + + ui->ss_mgcl2Edit->value() * MMCl / MMMgCl2 * 1000) / product->sparge_volume; + } + + /* Show the spargewater with salt additions. */ + ui->sp_caEdit->setValue(product->ws_calcium); + ui->sp_mgEdit->setValue(product->ws_magnesium); + ui->sp_hco3Edit->setValue(Utils::Bicarbonate(product->ws_total_alkalinity, Source_pH)); + ui->sp_caco3Edit->setValue(product->ws_total_alkalinity); + ui->sp_naEdit->setValue(product->ws_sodium); + ui->sp_clEdit->setValue(product->ws_chloride); + ui->sp_so4Edit->setValue(product->ws_sulfate); + ui->sp_phShow->setValue(product->sparge_ph); + ui->sp_hardnessEdit->setValue(Utils::Hardness(product->ws_calcium, product->ws_magnesium)); + ui->sp_raEdit->setValue(Utils::ResidualAlkalinity(product->ws_total_alkalinity, product->ws_calcium, product->ws_magnesium)); int AT = product->sparge_acid_type; if (AT < 0 || AT >= my_acids.size()) { @@ -545,7 +551,7 @@ double f343 = r143 * r243 / d43; // Step 4. Solve - double Ct = Source_alkalinity / 50 / ((f143 - f1) + (f3 - f343)); + double Ct = product->ws_total_alkalinity / 50 / ((f143 - f1) + (f3 - f343)); // Step 5. Compute mole fractions at desired pH double r1g = pow(10, TargetpH - 6.35); @@ -581,7 +587,7 @@ ui->sp_acidvolEdit->setValue(Acid); } - ui->sp_phShow->setValue(product->sparge_ph); +// ui->sp_phShow->setValue(product->sparge_ph); // Finally calculate the estimate preboil pH product->est_preboil_ph = -log10(((pow(10, -product->mash_ph) * product->wg_amount) + (pow(10, -product->sparge_ph) * product->brew_sparge_est)) / (product->wg_amount + product->brew_sparge_est)); @@ -602,6 +608,12 @@ void EditProduct::sp_volume_changed(double val) { + if (! product->calc_acid) { + product->sparge_acid_amount *= val / product->sparge_volume; + const QSignalBlocker blocker1(ui->sp_acidvolEdit); + ui->sp_acidvolEdit->setValue(product->sparge_acid_amount * 1000.0); + } + product->sparge_volume = val; ui->brew_spargevolShow->setValue(val); calcSparge(); diff -r 1efe29f64551 -r 4bc746c65650 src/EditRecipe.cpp --- a/src/EditRecipe.cpp Tue Jul 19 16:00:52 2022 +0200 +++ b/src/EditRecipe.cpp Wed Jul 20 12:44:02 2022 +0200 @@ -341,7 +341,6 @@ ui->sp_phEdit->setValue(recipe->sparge_ph); ui->sp_acidtypeEdit->setCurrentIndex(recipe->sparge_acid_type); ui->sp_acidpercEdit->setValue(recipe->sparge_acid_perc); - ui->sp_acidvolEdit->setValue(recipe->sparge_acid_amount); // All signals from tab "Generic" connect(ui->lockedEdit, &QCheckBox::stateChanged, this, &EditRecipe::is_changed); @@ -410,6 +409,7 @@ connect(ui->spargeGroup, SIGNAL(buttonClicked(int)), this, SLOT(sp_group_changed(int))); connect(ui->sp_acidtypeEdit, QOverload::of(&QComboBox::currentIndexChanged), this, &EditRecipe::sp_type_changed); connect(ui->sp_phEdit, QOverload::of(&QDoubleSpinBox::valueChanged), this, &EditRecipe::sp_ph_changed); + connect(ui->sp_volEdit, QOverload::of(&QDoubleSpinBox::valueChanged), this, &EditRecipe::sp_vol_changed); connect(ui->sp_acidvolEdit, QOverload::of(&QDoubleSpinBox::valueChanged), this, &EditRecipe::sp_acid_changed); setLocked(recipe->locked); diff -r 1efe29f64551 -r 4bc746c65650 src/EditRecipe.h --- a/src/EditRecipe.h Tue Jul 19 16:00:52 2022 +0200 +++ b/src/EditRecipe.h Wed Jul 20 12:44:02 2022 +0200 @@ -120,6 +120,7 @@ void sp_group_changed(int val); void sp_type_changed(int val); void sp_ph_changed(double val); + void sp_vol_changed(double val); void sp_acid_changed(double val); void step_name_changed(QString val); void step_type_changed(int val); diff -r 1efe29f64551 -r 4bc746c65650 src/EditRecipeTab7.cpp --- a/src/EditRecipeTab7.cpp Tue Jul 19 16:00:52 2022 +0200 +++ b/src/EditRecipeTab7.cpp Wed Jul 20 12:44:02 2022 +0200 @@ -470,51 +470,58 @@ void EditRecipe::calcSparge() { double TargetpH = recipe->sparge_ph; - double Source_pH = recipe->w1_ph; - double Source_alkalinity = recipe->w1_total_alkalinity; + double Source_pH = 7.0; qDebug() << "calcSparge()"; setButtons(recipe->locked); if (recipe->sparge_source == 1 && recipe->w2_ph > 0.0) { - Source_pH = recipe->w2_ph; - Source_alkalinity = recipe->w2_total_alkalinity; - ui->sp_caEdit->setValue(recipe->w2_calcium); - ui->sp_mgEdit->setValue(recipe->w2_magnesium); - ui->sp_hco3Edit->setValue(Utils::Bicarbonate(recipe->w2_total_alkalinity, recipe->w2_ph)); - ui->sp_caco3Edit->setValue(recipe->w2_total_alkalinity); - ui->sp_naEdit->setValue(recipe->w2_sodium); - ui->sp_clEdit->setValue(recipe->w2_chloride); - ui->sp_so4Edit->setValue(recipe->w2_sulfate); - ui->sp_phShow->setValue(recipe->w2_ph); - ui->sp_hardnessEdit->setValue(Utils::Hardness(recipe->w2_calcium, recipe->w2_magnesium)); - ui->sp_raEdit->setValue(Utils::ResidualAlkalinity(recipe->w2_total_alkalinity, recipe->w2_calcium, recipe->w2_magnesium)); + recipe->ws_calcium = recipe->w2_calcium; + recipe->ws_magnesium = recipe->w2_magnesium; + recipe->ws_total_alkalinity = recipe->w2_total_alkalinity; + recipe->ws_sodium = recipe->w2_sodium; + recipe->ws_chloride = recipe->w2_chloride; + recipe->ws_sulfate = recipe->w2_sulfate; + Source_pH = recipe->w2_ph; } else if (recipe->sparge_source == 2 && recipe->w2_ph > 0.0) { - Source_pH = recipe->wg_ph; - Source_alkalinity = recipe->wg_total_alkalinity; - ui->sp_caEdit->setValue(recipe->wg_calcium); - ui->sp_mgEdit->setValue(recipe->wg_magnesium); - ui->sp_hco3Edit->setValue(Utils::Bicarbonate(recipe->wg_total_alkalinity, recipe->wg_ph)); - ui->sp_caco3Edit->setValue(recipe->wg_total_alkalinity); - ui->sp_naEdit->setValue(recipe->wg_sodium); - ui->sp_clEdit->setValue(recipe->wg_chloride); - ui->sp_so4Edit->setValue(recipe->wg_sulfate); - ui->sp_phShow->setValue(recipe->wg_ph); - ui->sp_hardnessEdit->setValue(Utils::Hardness(recipe->wg_calcium, recipe->wg_magnesium)); - ui->sp_raEdit->setValue(Utils::ResidualAlkalinity(recipe->wg_total_alkalinity, recipe->wg_calcium, recipe->wg_magnesium)); + recipe->ws_calcium = recipe->wg_calcium; + recipe->ws_magnesium = recipe->wg_magnesium; + recipe->ws_total_alkalinity = recipe->wg_total_alkalinity; + recipe->ws_sodium = recipe->wg_sodium; + recipe->ws_chloride = recipe->wg_chloride; + recipe->ws_sulfate = recipe->wg_sulfate; + Source_pH = recipe->wg_ph; } else { - ui->sp_caEdit->setValue(recipe->w1_calcium); - ui->sp_mgEdit->setValue(recipe->w1_magnesium); - ui->sp_hco3Edit->setValue(Utils::Bicarbonate(recipe->w1_total_alkalinity, recipe->w1_ph)); - ui->sp_caco3Edit->setValue(recipe->w1_total_alkalinity); - ui->sp_naEdit->setValue(recipe->w1_sodium); - ui->sp_clEdit->setValue(recipe->w1_chloride); - ui->sp_so4Edit->setValue(recipe->w1_sulfate); - ui->sp_phShow->setValue(recipe->w1_ph); - ui->sp_hardnessEdit->setValue(Utils::Hardness(recipe->w1_calcium, recipe->w1_magnesium)); - ui->sp_raEdit->setValue(Utils::ResidualAlkalinity(recipe->w1_total_alkalinity, recipe->w1_calcium, recipe->w1_magnesium)); + recipe->ws_calcium = recipe->w1_calcium; + recipe->ws_magnesium = recipe->w1_magnesium; + recipe->ws_total_alkalinity = recipe->w1_total_alkalinity; + recipe->ws_sodium = recipe->w1_sodium; + recipe->ws_chloride = recipe->w1_chloride; + recipe->ws_sulfate = recipe->w1_sulfate; + Source_pH = recipe->w1_ph; } - // The spargewater is set. + + /* Calculate Salt additions */ + if (recipe->sparge_volume > 0) { + recipe->ws_calcium += ( ui->ss_cacl2Edit->value() * MMCa / MMCaCl2 * 1000 + ui->ss_caso4Edit->value() * MMCa / MMCaSO4 * 1000) / recipe->sparge_volume; + recipe->ws_magnesium += (ui->ss_mgso4Edit->value() * MMMg / MMMgSO4 * 1000 + ui->ss_mgcl2Edit->value() * MMMg / MMMgCl2 * 1000) / recipe->sparge_volume; + recipe->ws_sodium += (ui->ss_naclEdit->value() * MMNa / MMNaCl * 1000) / recipe->sparge_volume; + recipe->ws_sulfate += (ui->ss_caso4Edit->value() * MMSO4 / MMCaSO4 * 1000 + ui->ss_mgso4Edit->value() * MMSO4 / MMMgSO4 * 1000) / recipe->sparge_volume; + recipe->ws_chloride += (2 * ui->ss_cacl2Edit->value() * MMCl / MMCaCl2 * 1000 + ui->ss_naclEdit->value() * MMCl / MMNaCl * 1000 + + ui->ss_mgcl2Edit->value() * MMCl / MMMgCl2 * 1000) / recipe->sparge_volume; + } + + /* Show the spargewater with salt additions. */ + ui->sp_caEdit->setValue(recipe->ws_calcium); + ui->sp_mgEdit->setValue(recipe->ws_magnesium); + ui->sp_hco3Edit->setValue(Utils::Bicarbonate(recipe->ws_total_alkalinity, Source_pH)); + ui->sp_caco3Edit->setValue(recipe->ws_total_alkalinity); + ui->sp_naEdit->setValue(recipe->ws_sodium); + ui->sp_clEdit->setValue(recipe->ws_chloride); + ui->sp_so4Edit->setValue(recipe->ws_sulfate); + ui->sp_phShow->setValue(recipe->sparge_ph); + ui->sp_hardnessEdit->setValue(Utils::Hardness(recipe->ws_calcium, recipe->ws_magnesium)); + ui->sp_raEdit->setValue(Utils::ResidualAlkalinity(recipe->ws_total_alkalinity, recipe->ws_calcium, recipe->ws_magnesium)); int AT = recipe->sparge_acid_type; if (AT < 0 || AT >= my_acids.size()) { @@ -544,7 +551,7 @@ double f343 = r143 * r243 / d43; // Step 4. Solve - double Ct = Source_alkalinity / 50 / ((f143 - f1) + (f3 - f343)); + double Ct = recipe->ws_total_alkalinity / 50 / ((f143 - f1) + (f3 - f343)); // Step 5. Compute mole fractions at desired pH double r1g = pow(10, TargetpH - 6.35); @@ -578,7 +585,6 @@ ui->sp_acidvolEdit->setValue(Acid); } - ui->sp_phShow->setValue(recipe->sparge_ph); // Finally calculate the estimate preboil pH recipe->preboil_ph = -log10(((pow(10, -recipe->mash_ph) * recipe->wg_amount) + (pow(10, -recipe->sparge_ph) * recipe->sparge_volume)) / (recipe->wg_amount + recipe->sparge_volume)); @@ -629,6 +635,20 @@ } +void EditRecipe::sp_vol_changed(double val) +{ + if (! recipe->calc_acid) { + recipe->sparge_acid_amount *= val / recipe->sparge_volume; + const QSignalBlocker blocker1(ui->sp_acidvolEdit); + ui->sp_acidvolEdit->setValue(recipe->sparge_acid_amount * 1000.0); + } + + recipe->sparge_volume = val; + calcSparge(); + is_changed(); +} + + void EditRecipe::sp_acid_changed(double val) { if (recipe->calc_acid) diff -r 1efe29f64551 -r 4bc746c65650 src/global.h --- a/src/global.h Tue Jul 19 16:00:52 2022 +0200 +++ b/src/global.h Wed Jul 20 12:44:02 2022 +0200 @@ -399,6 +399,12 @@ int mashs_time; ///< Total mash time. double preboil_sg; double preboil_ph; + double ws_calcium; ///< Sparge water calculated. + double ws_sulfate; + double ws_chloride; + double ws_sodium; + double ws_magnesium; + double ws_total_alkalinity; }; @@ -651,12 +657,18 @@ double est_mash_sg; double est_preboil_ph; double preboil_sg; - double final_abv; /// ABV after dilution/infusion. + double final_abv; ///< ABV after dilution/infusion. double bottle_abv; double bottle_bar; double keg_abv; double keg_bar; - QList splits; /// Used during building a split batch + QList splits; ///< Used during building a split batch + double ws_calcium; ///< Sparge water calculated. + double ws_sulfate; + double ws_chloride; + double ws_sodium; + double ws_magnesium; + double ws_total_alkalinity; };