src/Utils.cpp

changeset 440
349c0c5bd512
parent 380
8f5c03ed4321
child 442
d8c110d91b1f
--- a/src/Utils.cpp	Wed Nov 16 17:26:27 2022 +0100
+++ b/src/Utils.cpp	Thu Nov 17 17:23:54 2022 +0100
@@ -419,9 +419,10 @@
 
 double Utils::toIBU(int Use, int Form, double preSG, double postSG, double Volume, double Amount, double Boiltime, double Alpha,
 		    int Method, double Whirlpool9, double Whirlpool7, double Whirlpool6, double Fulltime,
-		    int Cooltype, double Coolparm1, double Coolparm2, double Utilisation, double BU_factor)
+		    int Cooltype, double CoolTo79, double CoolLPM, double Utilisation, double BU_factor)
 {
     double ibu = 0.0;
+    double bp = boilPoint();
 
     if (Use == HOP_USEAT_MASH) {
 	/*
@@ -453,19 +454,59 @@
 	}
 
 	if (Method > 0) {
+	    /*
+	     * Extra IBU's during flameout, chilling, hopstands for hops added during boil or first wort.
+	     */
 	    double nibu = ibu;
-	    nibu *= IBU_reduction(boilPoint());
+	    if (Use == HOP_USEAT_BOIL)	/* Correct for brewery height above sealevel */
+	    	nibu *= IBU_reduction(bp);
 
 	    /*
 	     * Flameout, currently fixed 1 minute.
 	     */
 	    double flameout_time = 1;
 	    double fibu = TinsethIBU(Form, postSG, Volume, Amount, boil_time, boil_time + flameout_time, Alpha, Utilisation, BU_factor);
-	    fibu *= IBU_reduction(98.0);
-	    //qDebug() << "during flameout" << fibu;
+	    fibu *= IBU_reduction(bp - 0.5);	/* Boilpoint minus 0.5 degree */
+	    //qDebug() << "during flameout" << fibu << bp;
 	    nibu += fibu;
 
-	    // Add this hop during cooling
+	    if ((Cooltype == CHILLER_TYPE_IMMERSION || Cooltype == CHILLER_TYPE_AUBAINMARIE || Cooltype == CHILLER_TYPE_NOCHILL) && CoolTo79 > 0) {
+		/*
+		 * Direct wort chilling, calculate the IBU's when chilling down to 79 degrees.
+		 */
+		double cibu = 0, tibu;
+		for (int i = 1; i < int(CoolTo79); i++) {
+		    tibu = TinsethIBU(Form, postSG, Volume, Amount, boil_time + flameout_time + i, boil_time + flameout_time + i + 1, Alpha, Utilisation, BU_factor);
+		    tibu *= IBU_reduction((bp - 1) - (i * ((bp - 80) / CoolTo79)));
+		    //qDebug() << "  chill" << i << "time" << boil_time + flameout_time + i << "temp" << (bp - 1) - (i * ((bp - 80) / CoolTo79)) << "ibu" << tibu;
+		    cibu += tibu;
+		}
+		//qDebug() << "  immersion" << cibu;
+		nibu += cibu;
+	    }
+
+	    if (Cooltype == CHILLER_TYPE_COUNTERFLOW && CoolLPM > 0) {
+		/*
+		 * Counterflow chilling, calculate the IBU's isomerized in the kettle during transfer the hot wort to the chiller.
+		 */
+		double cibu = 0, tibu, V, A;
+		int steps = trunc(Volume / CoolLPM);
+		for (int i = 1; i <= steps; i++) {
+		    V = Volume - (i * CoolLPM);
+		    A = Amount - (i * (Amount / steps));
+		    tibu = TinsethIBU(Form, postSG, V, A, boil_time + flameout_time + i, boil_time + flameout_time + i + 1, Alpha, Utilisation, BU_factor);
+		    /*
+		     * Correction for the natural cooling of the wort in the kettle.
+		     * Asume 0.1 degree per minute.
+		     */
+		    tibu *= IBU_reduction((bp - 1) - (i * 0.1));
+		    //qDebug() << "  chill" << i << steps << "left" << V << A << "time" << boil_time + flameout_time + i << "ibu" << tibu;
+		    cibu += tibu;
+		}
+		//qDebug() << "  counterflow" << cibu;
+                nibu += cibu;
+	    }
+
 	    /*
 	     * Hopstands, this boil hop adds some IBU's too.
 	     */
@@ -497,7 +538,45 @@
 	 */
 	double flameout_time = 1;
         ibu = TinsethIBU(Form, postSG, Volume, Amount, 0, flameout_time, Alpha, Utilisation, BU_factor);
-        ibu *= IBU_reduction(98.0);
+        ibu *= IBU_reduction(bp - 0.5);
+
+	if ((Cooltype == CHILLER_TYPE_IMMERSION || Cooltype == CHILLER_TYPE_AUBAINMARIE || Cooltype == CHILLER_TYPE_NOCHILL) && CoolTo79 > 0) {
+	    /*
+	     * Direct wort chilling, calculate the IBU's when chilling down to 79 degrees.
+	     */
+	    double cibu = 0, tibu;
+	    for (int i = 1; i < int(CoolTo79); i++) {
+		tibu = TinsethIBU(Form, postSG, Volume, Amount, flameout_time + i, flameout_time + i + 1, Alpha, Utilisation, BU_factor);
+		tibu *= IBU_reduction((bp - 1) - (i * ((bp - 80) / CoolTo79)));
+		//qDebug() << "  chill" << i << "time" << flameout_time + i << "temp" << (bp - 1) - (i * ((bp - 80) / CoolTo79)) << "ibu" << tibu;
+		cibu += tibu;
+	    }
+	    //qDebug() << "  immersion" << cibu;
+	    ibu += cibu;
+	}
+
+	if (Cooltype == CHILLER_TYPE_COUNTERFLOW && CoolLPM > 0) {
+	    /*
+	     * Counterflow chilling, calculate the IBU's isomerized in the kettle during transfer the hot wort to the chiller.
+	     */
+	    double cibu = 0, tibu, V, A;
+	    int steps = trunc(Volume / CoolLPM);
+	    for (int i = 1; i <= steps; i++) {
+		V = Volume - (i * CoolLPM);
+		A = Amount - (i * (Amount / steps));
+		tibu = TinsethIBU(Form, postSG, V, A, flameout_time + i, flameout_time + i + 1, Alpha, Utilisation, BU_factor);
+		/*
+		 * Correction for the natural cooling of the wort in the kettle.
+		 * Asume 0.1 degree per minute.
+		 */
+		tibu *= IBU_reduction((bp - 1) - (i * 0.1));
+		//qDebug() << "  chill" << i << steps << "left" << V << A << "time" << flameout_time + i << "ibu" << tibu;
+		cibu += tibu;
+	    }
+	    //qDebug() << "  counterflow" << cibu;
+	    ibu += cibu;
+	}
+
 	/*
          * Hopstands, this flameout hop adds some IBU's too.
          */
@@ -559,7 +638,7 @@
 
     double rc = round(ibu * 1000.0) / 1000.0;
 
-    qDebug() << "toIBU" << Use << Form << preSG << postSG << Volume << Amount << Boiltime << Alpha << Method << Whirlpool9 << Whirlpool7 << Whirlpool6 << Fulltime << Cooltype << Coolparm1 << Coolparm2 << Utilisation << BU_factor << "rc:" << rc;
+    qDebug() << "toIBU" << Use << Form << preSG << postSG << Volume << Amount << Boiltime << Alpha << Method << Whirlpool9 << Whirlpool7 << Whirlpool6 << Fulltime << Cooltype << CoolTo79 << CoolLPM << Utilisation << BU_factor << "rc:" << rc;
     return rc;
 }
 

mercurial