Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix places where we are using old ABV formulae #919

Merged
merged 1 commit into from
Jan 4, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 17 additions & 11 deletions src/Algorithms.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
* Algorithms.cpp is part of Brewtarget, and is copyright the following authors 2009-2023:
* Algorithms.cpp is part of Brewtarget, and is copyright the following authors 2009-2025:
* • Eric Tamme <[email protected]>
* • Matt Young <[email protected]>
* • Philip Greggory Lee <[email protected]>
Expand Down Expand Up @@ -247,7 +247,7 @@ double Polynomial::rootFind( double x0, double x1 ) const {
return newGuess;
}

//╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
//======================================================================================================================

bool Algorithms::isNan(double d) {
// If using IEEE floating points, all comparisons with a NaN
Expand Down Expand Up @@ -475,6 +475,12 @@ double Algorithms::abvFromOgAndFg(double og, double fg) {
// Assert the parameters were supplied in the right order by checking that FG cannot by higher than OG
Q_ASSERT(og >= fg);

//
// Previously, in different places in the code, we either used a very rough rule of thumb:
//
// double calculatedABV_pct = (og - fg) * 130
//
// or we used the FALLBACK METHOD described below.
//
// The current calculation method we use comes from the UK Laboratory of the Government Chemist. It is what HM
// Revenue and Customs (HMRC) encourage UK microbreweries to use to calculate ABV if they have "no or minimal
Expand Down Expand Up @@ -526,7 +532,7 @@ double Algorithms::abvFromOgAndFg(double og, double fg) {
);

//
// OLD METHOD, which is also the fallback
// FALLBACK METHOD
//
// From http://www.brewersfriend.com/2011/06/16/alcohol-by-volume-calculator-updated/:
// "[This] formula, and variations on it, comes from Ritchie Products Ltd, (Zymurgy, Summer 1995, vol. 18, no. 2)
Expand All @@ -536,31 +542,31 @@ double Algorithms::abvFromOgAndFg(double og, double fg) {
// The relationship between the change in gravity, and the change in ABV is not linear. All these equations are
// approximations."
//
double abvByOldMethod = (76.08 * (og - fg) / (1.775 - og)) * (fg / 0.794);
double const abvByFallbackMethod = (76.08 * (og - fg) / (1.775 - og)) * (fg / 0.794);

if (matchingGravityDifferenceRec == gravityDifferenceFactors.cend()) {
qCritical() <<
Q_FUNC_INFO << "Could not find gravity difference record for difference of " <<
(excessGravityDiffx10 / 10.0) << "so using fallback method";
return abvByOldMethod;
return abvByFallbackMethod;
}

double abvByNewMethod = excessGravityDiff * matchingGravityDifferenceRec->factorToUse;
double const abvByHmrcMethod = excessGravityDiff * matchingGravityDifferenceRec->factorToUse;

qDebug() <<
Q_FUNC_INFO << "ABV old method:" << abvByOldMethod << "% , new method:" << abvByNewMethod << "% (used factor" <<
Q_FUNC_INFO << "ABV old method:" << abvByFallbackMethod << "% , new method:" << abvByHmrcMethod << "% (used factor" <<
matchingGravityDifferenceRec->factorToUse << "and should be in range" <<
matchingGravityDifferenceRec->pctAbv_Min << "% -" << matchingGravityDifferenceRec->pctAbv_Max << "%)";

// The tables from UK HMRC have some sanity-check data, so let's use it!
if (abvByNewMethod < matchingGravityDifferenceRec->pctAbv_Min ||
abvByNewMethod > matchingGravityDifferenceRec->pctAbv_Max) {
if (abvByHmrcMethod < matchingGravityDifferenceRec->pctAbv_Min ||
abvByHmrcMethod > matchingGravityDifferenceRec->pctAbv_Max) {
qWarning() <<
Q_FUNC_INFO << "Calculated ABV of" << abvByNewMethod << "% is outside expected range (" <<
Q_FUNC_INFO << "Calculated ABV of" << abvByHmrcMethod << "% is outside expected range (" <<
matchingGravityDifferenceRec->pctAbv_Min << "% -" << matchingGravityDifferenceRec->pctAbv_Max << "%)";
}

return abvByNewMethod;
return abvByHmrcMethod;
}

double Algorithms::correctSgForTemperature(double measuredSg, double readingTempInC, double calibrationTempInC) {
Expand Down
15 changes: 8 additions & 7 deletions src/model/BrewNote.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
* model/BrewNote.cpp is part of Brewtarget, and is copyright the following authors 2009-2024:
* model/BrewNote.cpp is part of Brewtarget, and is copyright the following authors 2009-2025:
* • Brian Rower <[email protected]>
* • Greg Meess <[email protected]>
* • Jonatan Pålsson <[email protected]>
Expand Down Expand Up @@ -563,16 +563,17 @@ double BrewNote::calculateABV_pct() {
// 1 + [(og - 1) * (1.0 - %/100)]
double const estFg = 1 + ((m_og-1.0)*(1.0 - atten_pct/100.0));

double const calculatedABV = (m_og-estFg)*130;
this->setProjABV_pct(calculatedABV);
double const calculatedAbv_pct = Algorithms::abvFromOgAndFg(this->m_og, estFg);

return calculatedABV;
this->setProjABV_pct(calculatedAbv_pct);

return calculatedAbv_pct;
}

double BrewNote::calculateActualABV_pct() {
double const abv = (m_og - m_fg) * 130;
this->setABV(abv);
return abv;
double const abv_pct = Algorithms::abvFromOgAndFg(this->m_og, this->m_fg);
this->setABV(abv_pct);
return abv_pct;
}

double BrewNote::calculateAttenuation_pct() {
Expand Down
17 changes: 9 additions & 8 deletions src/model/Recipe.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
* model/Recipe.cpp is part of Brewtarget, and is copyright the following authors 2009-2024:
* model/Recipe.cpp is part of Brewtarget, and is copyright the following authors 2009-2025:
* • Brian Rower <[email protected]>
* • Greg Greenaae <[email protected]>
* • Greg Meess <[email protected]>
Expand Down Expand Up @@ -1225,16 +1225,11 @@ class Recipe::impl {
return;
}


/**
* Emits changed(ABV_pct). Depends on: m_og, m_fg
*/
void recalcABV_pct() {
// The complex formula, and variations comes from Ritchie Products Ltd, (Zymurgy, Summer 1995, vol. 18, no. 2)
// Michael L. Hall’s article Brew by the Numbers: Add Up What’s in Your Beer, and Designing Great Beers by Daniels.
double calculatedABV_pct =
(76.08 * (this->m_og_fermentable - this->m_fg_fermentable) / (1.775 - this->m_og_fermentable)) *
(this->m_fg_fermentable / 0.794);
double const calculatedABV_pct = Algorithms::abvFromOgAndFg(this->m_og_fermentable, this->m_fg_fermentable);

if (!qFuzzyCompare(calculatedABV_pct, m_ABV_pct)) {
qDebug() <<
Expand Down Expand Up @@ -2657,9 +2652,15 @@ double Recipe::ibuFromHopAddition(RecipeAdditionHop const & hopAddition) {
boilTime_mins = static_cast<int>(equipment->boilTime_min().value_or(Equipment::default_boilTime_mins));
}

// Assume 30 min cool time if boil is not set
double coolTime_mins = 30.0;

auto boil = this->boil();
if (boil) {
boilTime_mins = boil->boilTime_mins();
if (boil->coolTime_mins()) {
coolTime_mins = *boil->coolTime_mins();
}
}

qDebug() <<
Expand All @@ -2674,7 +2675,7 @@ double Recipe::ibuFromHopAddition(RecipeAdditionHop const & hopAddition) {
.postBoilVolume_liters = this->pimpl->m_finalVolumeNoLosses_l,
.wortGravity_sg = m_og,
.timeInBoil_minutes = boilTime_mins, // Seems unlikely in reality that there would be fractions of a minute
.coolTime_minutes = boil->coolTime_mins(),
.coolTime_minutes = coolTime_mins,
};
if (equipment) {
parms.kettleInternalDiameter_cm = equipment->kettleInternalDiameter_cm();
Expand Down
Loading