src/Utils.cpp

changeset 339
2f3cfb983fcc
parent 337
8133cdb19aa1
child 340
b9af88bfe972
equal deleted inserted replaced
338:473479de8c5b 339:2f3cfb983fcc
377 377
378 /* 378 /*
379 * Formula is from the 'Mash Made Easy' spreadsheet. 379 * Formula is from the 'Mash Made Easy' spreadsheet.
380 * https://mashmadeeasy.yolasite.com/ 380 * https://mashmadeeasy.yolasite.com/
381 * https://www.homebrewtalk.com/threads/a-rather-simplified-whirlpool-hop-ibu-computation-method.701093/ 381 * https://www.homebrewtalk.com/threads/a-rather-simplified-whirlpool-hop-ibu-computation-method.701093/
382 *
383 * Source of the formula Mark G. Malowicki.
382 */ 384 */
383 double Utils::IBU_reduction(double Tc) 385 double Utils::IBU_reduction(double Tc)
384 { 386 {
385 return (2.39 * pow(10, 11) * pow(2.71828182846, - (9773 / (Tc + Kelvin))) ) * 1/1.009231744; 387 /*
386 } 388 * Original formula plus a small correction factor.
387 389 */
388 390 return (2.39 * pow(10, 11) * exp(-(9773 / (Tc + Kelvin))) ) * 1/1.009231743647;
389 double Utils::boilIBU(int Form, double SG, double Volume, double Amount, double Time, double Alpha, int Method) 391 }
390 { 392
391 double ibu = 0.0, sgfactor, boilfactor; 393
392 394 double Utils::TinsethIBU(double SG, double Volume, double Amount, double Time, double Alpha)
395 {
393 double alpha = Alpha / 100.0; 396 double alpha = Alpha / 100.0;
394 double mass = Amount * 1000.0; 397 double mass = Amount * 1000.0;
395 398
396 if (Method == 0) { // Tinseth 399 /*
397 /* http://realbeer.com/hops/research.html */ 400 * Basic Tinseth formula.
398 double AddedAlphaAcids = (alpha * mass * 1000) / Volume; 401 * http://realbeer.com/hops/research.html
399 double Bigness_factor = 1.65 * pow(0.000125, SG - 1); 402 */
400 double BoilTime_factor = ((1 - exp(-0.04 * Time)) / 4.15); 403 double AddedAlphaAcids = (alpha * mass * 1000) / Volume;
401 ibu = Bigness_factor * BoilTime_factor * AddedAlphaAcids; 404 double Bigness_factor = 1.65 * pow(0.000125, SG - 1);
402 } 405 double BoilTime_factor = ((1 - exp(-0.04 * Time)) / 4.15);
403 if (Method == 2) { // Daniels 406 double ibu = Bigness_factor * BoilTime_factor * AddedAlphaAcids;
404 if (Form == 2) // Leaf 407
405 boilfactor = -(0.0041 * Time * Time) + (0.6162 * Time) + 1.5779; 408 qDebug() << "boilIBU" << SG << Volume << Amount << Time << Alpha << "IBU:" << ibu;
406 else
407 boilfactor = -(0.0051 * Time * Time) + (0.7835 * Time) + 1.9348;
408 if (SG < 1.050)
409 sgfactor = 0;
410 else
411 sgfactor = ((SG * 1000) - 1050) / 200;
412 ibu = (mass * (alpha * 100) * boilfactor * 0.1) / (Volume * (1 + sgfactor));
413 }
414 if (Method == 1) { // Rager
415 boilfactor = 18.11 + 13.86 * tanh((Time * 31.32) / 18.27);
416 if (SG < 1.050)
417 sgfactor = 0;
418 else
419 sgfactor = ((SG * 1000) - 1050) / 200;
420 ibu = (mass * (alpha * 100) * boilfactor * 0.1) / (Volume * (1 + sgfactor));
421 }
422
423 //qDebug() << "boilIBU" << Form << SG << Volume << Amount << Time << Alpha << Method << "IBU:" << ibu;
424 return ibu; 409 return ibu;
425 } 410 }
426 411
427 412
428 double Utils::toIBU(int Use, int Form, double SG, double Volume, double Amount, double Boiltime, double Alpha, 413 double Utils::toIBU(int Use, int Form, double SG, double Volume, double Amount, double Boiltime, double Alpha,
429 int Method, double Whirlpool9, double Whirlpool7, double Whirlpool6, double Fulltime) 414 int Method, double Whirlpool9, double Whirlpool7, double Whirlpool6, double Fulltime)
430 { 415 {
416 double loss_boiltemp = 1.0; /* Loss due to the lower boil temperature at higher altitude. */
417
431 double ibu = 0.0, whirlibus = 0.0; 418 double ibu = 0.0, whirlibus = 0.0;
432 double alpha = Alpha / 100.0; 419 double alpha = Alpha / 100.0;
433 double mass = Amount * 1000.0; 420 double mass = Amount * 1000.0;
434 421
435 // Ideas from Zymurgy March-April 2018. These are not exact formulas! 422 // Ideas from Zymurgy March-April 2018. These are not exact formulas!
475 462
476 /* 463 /*
477 * IBU's from hops during Mash, FWH and boil. 464 * IBU's from hops during Mash, FWH and boil.
478 */ 465 */
479 if ((Use == HOP_USEAT_MASH) || (Use == HOP_USEAT_FWH) || (Use == HOP_USEAT_BOIL)) { 466 if ((Use == HOP_USEAT_MASH) || (Use == HOP_USEAT_FWH) || (Use == HOP_USEAT_BOIL)) {
480 ibu = boilIBU(Form, SG, Volume, Amount, Fulltime, Alpha, Method); 467 ibu = TinsethIBU(SG, Volume, Amount, Fulltime, Alpha);
481 /* 468 /*
482 * Corrections for Mash and FWH 469 * Corrections for Mash and FWH
483 */ 470 */
484 if (Use == HOP_USEAT_MASH) { 471 if (Use == HOP_USEAT_MASH) {
485 ibu *= (1 + my_factor_mashhop / 100.0); 472 ibu *= (1 + my_factor_mashhop / 100.0);
500 } else if (Form == HOP_FORMS_CRYO) { 487 } else if (Form == HOP_FORMS_CRYO) {
501 ibu *= (1 + my_factor_cryohop / 100.0); 488 ibu *= (1 + my_factor_cryohop / 100.0);
502 } else if (Form == HOP_FORMS_EXTRACT) { 489 } else if (Form == HOP_FORMS_EXTRACT) {
503 // Nothing for now. 490 // Nothing for now.
504 } 491 }
505 // ibu *= IBU_reduction(boilPoint()); 492
506 // qDebug() << "ibu" << ibu << IBU_reduction(boilPoint()); 493 if (Method > 0) {
494 loss_boiltemp = IBU_reduction(boilPoint());
495 ibu *= loss_boiltemp;
496 qDebug() << "ibu" << ibu << "loss_boiltemp" << loss_boiltemp;
497 }
507 498
508 // } else if (Use == HOP_USEAT_AROMA) { 499 // } else if (Use == HOP_USEAT_AROMA) {
509 /* 500 /*
510 * At flameout. The cooling method is important. 501 * At flameout. The cooling method is important.
511 * Emersion chiller, Counterflow chiller, Au bain marie or natural. 502 * Emersion chiller, Counterflow chiller, Au bain marie or natural.
512 * Assume the hop is removed for all methods except Emersion chilling. 503 * Assume the hop is removed for all methods except Emersion chilling.
513 */ 504 */
514 } else { 505 } else {
515 // qDebug() << "whirlibus" << whirlibus << Use; 506 // qDebug() << "whirlibus" << whirlibus << Use;
516 } 507 }
517
518 508
519 return round((ibu + whirlibus) * 100.0) / 100.0; 509 return round((ibu + whirlibus) * 100.0) / 100.0;
520 } 510 }
521 511
522 512

mercurial