www/includes/formulas.php

Wed, 30 Jan 2019 23:08:05 +0100

author
Michiel Broek <mbroek@mbse.eu>
date
Wed, 30 Jan 2019 23:08:05 +0100
changeset 223
0de4455bd2a1
parent 164
0a5abea575a9
child 231
9881453a49b3
permissions
-rw-r--r--

Fixed spelling area in all programs for caryophyllene. This is still wrong in brouwhulp, we correct it during database import. Also mycrene was spelled myrcene, my fault. The hops grid now uses a popup editor, this is not yet complete. Friendly weight display in the hop grid and added the inventory comlumn.

<?php

define('EURO', chr(128));

define('MMCa', '40.048');
define('MMMg', '24.305');
define('MMNa', '22.98976928');
define('MMCl', '35.453');
define('MMSO4', '96.0626');
define('MMCO3', '60.01684');
define('MMHCO3', '61.01684');
define('MMCaSO4', '172.171');
define('MMCaCl2', '147.015');
define('MMCaCO3', '100.087');
define('MMMgSO4', '246.475');
define('MMNaHCO3', '84.007');
define('MMNa2CO3', '105.996');
define('MMNaCl', '58.443');
define('MMCaOH2', '74.06268');


function ebc_to_srm($ebc)
{
	$srm = -1.32303E-12 * pow($ebc, 4) - 0.00000000291515 * pow($ebc, 3) + 0.00000818515 * pow($ebc, 2) + 0.372038 * $ebc + 0.596351;
	if (($ebc < 0) || ($srm < 0))
		syslog(LOG_NOTICE, "ebc_to_srm(".$ebc.") = ".$srm);
	return $srm;
}



function srm_to_ebc($srm)
{
	// Formule van Adrie Otten. brouwhulp.
	$ebc = round( 0.000000000176506 * pow($srm, 4) + 0.000000154529 * pow($srm, 3) - 0.000159428 * pow($srm, 2) + 2.68837 * $srm - 1.6004 );
	if (($ebc < 0) || ($srm < 0))
		syslog(LOG_NOTICE, "srm_to_ebc(".$srm.") = ".$ebc);
	return $ebc;
}



function ebc_to_color($ebc)
{
	return srm_to_color(ebc_to_srm($ebc));
}



function srm_to_color($srm)
{
	$i = abs($srm * 10);
	if ($i < 0) {
		$i = 0;
	}
	if ($i > 299) {
		$i = 299;
	}

	/* Table copied from Brouwhulp/BrewBuddy */
	$R = array( 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250,	// 0
 		    250, 250, 250, 250, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, 239, 238, 237, 236, 235,	// 2
		    234, 233, 232, 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 218, 217, 216, 215,	// 4
		    214, 213, 212, 211, 210, 209, 208, 207, 206, 205, 204, 203, 202, 201, 200, 200, 199, 199, 198, 198,	// 6
		    197, 197, 196, 196, 195, 195, 194, 194, 193, 193, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,	// 8
		    192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192, 192,	// 10
		    192, 192, 192, 192, 192, 192, 192, 192, 191, 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, 180,	// 12
		    179, 178, 177, 175, 174, 172, 171, 169, 168, 167, 195, 164, 162, 161, 159, 158, 157, 155, 154, 152,	// 14
		    151, 149, 148, 147, 145, 144, 142, 141, 139, 138, 137, 135, 134, 132, 131, 129, 128, 127, 125, 124,	// 16
		    122, 121, 119, 118, 117, 115, 114, 112, 111, 109, 108, 107, 105, 104, 102, 101,  99,  98,  97,  95,	// 18
		     94,  92,  91,  89,  88,  87,  85,  84,  82,  81,  79,  78,  77,  75,  74,  72,  71,  69,  68,  67,	// 20
		     65,  64,  62,  61,  59,  58,  57,  55,  54,  52,  51,  49,  48,  47,  45,  44,  43,  41,  39,  38,	// 22
		     37,  37,  36,  36,  35,  35,  34,  34,  33,  33,  32,  32,  31,  31,  30,  30,  29,  29,  28,  28,	// 24
		     27,  27,  26,  26,  25,  25,  24,  24,  23,  23,  22,  22,  21,  21,  20,  20,  19,  19,  18,  18,	// 26
		     17,  17,  16,  16,  15,  15,  14,  14,  13,  13,  12,  12,  11,  11,  10,  10,   9,   9,   8,   8 );

	$G = array( 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250,
		    250, 250, 250, 250, 250, 250, 249, 248, 247, 246, 245, 244, 242, 240, 238, 236, 234, 232, 230, 228,
		    226, 224, 222, 220, 218, 216, 214, 212, 210, 208, 206, 204, 202, 200, 198, 196, 194, 192, 190, 188,
		    186, 184, 182, 180, 178, 176, 174, 172, 170, 168, 166, 164, 162, 160, 158, 156, 154, 152, 150, 148,
		    146, 144, 142, 141, 140, 139, 139, 138, 137, 136, 136, 135, 134, 133, 133, 132, 131, 130, 130, 129,
		    128, 127, 127, 126, 125, 124, 124, 123, 122, 121, 121, 120, 119, 118, 118, 117, 116, 115, 115, 114,
		    113, 112, 112, 111, 110, 109, 109, 108, 107, 106, 106, 105, 104, 103, 103, 102, 101, 100, 100,  99,
		     98,  97,  97,  96,  95,  94,  94,  93,  92,  91,  91,  90,  89,  88,  88,  87,  86,  85,  85,  84,
		     83,  82,  82,  81,  80,  79,  78,  77,  76,  75,  75,  74,  73,  72,  72,  71,  70,  69,  69,  68,
		     67,  66,  66,  65,  64,  63,  63,  62,  61,  60,  60,  59,  58,  57,  57,  56,  55,  54,  54,  53,
		     52,  51,  51,  50,  49,  48,  48,  47,  46,  45,  45,  44,  43,  42,  42,  41,  40,  39,  39,  38,
		     37,  36,  36,  35,  34,  33,  33,  32,  31,  30,  30,  29,  28,  27,  27,  26,  25,  24,  24,  23,
		     22,  22,  22,  21,  21,  21,  20,  20,  20,  19,  19,  19,  18,  18,  18,  17,  17,  17,  16,  16,
		     16,  15,  15,  15,  14,  14,  14,  13,  13,  13,  12,  12,  12,  11,  11,  11,  10,  10,  10,   9,
		      9,   9,   8,   8,   8,   7,   7,   7,   6,   6,   6,   5,   5,   5,   4,   4,   4,   3,   3,   3 );

	$B = array( 210, 204, 199, 193, 188, 182, 177, 171, 166, 160, 155, 149, 144, 138, 133, 127, 122, 116, 111, 105,
		    100,  94,  89,  83,  78,  72,  67,  61,  56,  50,  45,  45,  45,  46,  46,  46,  46,  47,  47,  47,
		     47,  48,  48,  48,  48,  49,  49,  49,  49,  50,  50,  50,  50,  51,  51,  51,  51,  52,  52,  52,
		     52,  53,  53,  53,  53,  54,  54,  54,  54,  55,  55,  55,  55,  56,  56,  56,  56,  56,  56,  56,
		     56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,
		     56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,
		     56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,  56,
		     56,  56,  56,  55,  55,  55,  55,  54,  54,  54,  54,  53,  53,  53,  53,  52,  52,  52,  52,  51,
		     51,  51,  51,  50,  50,  50,  50,  49,  49,  48,  47,  47,  46,  45,  45,  44,  43,  43,  42,  41,
		     41,  40,  39,  39,  38,  37,  37,  36,  35,  34,  33,  32,  31,  29,  28,  27,  26,  25,  24,  23,
		     21,  20,  19,  18,  17,  16,  15,  13,  12,  11,  10,   9,   8,   9,   9,  10,  10,  11,  11,  12,
		     12,  13,  13,  14,  14,  15,  15,  16,  16,  17,  17,  18,  18,  19,  19,  20,  20,  21,  21,  22,
		     21,  21,  21,  20,  20,  20,  19,  19,  19,  18,  18,  18,  17,  17,  17,  17,  16,  16,  15,  15,
		     15,  14,  14,  14,  13,  13,  13,  12,  12,  12,  11,  11,  11,  10,  10,  10,   9,   9,   9,   8,
		      8,   8,   7,   7,   7,   6,   6,   6,   5,   5,   5,   4,   4,   4,   3,   3,   3,   2,   2,   2 );

	return array($R[$i],$G[$i],$B[$i]);
}



function sg_to_plato($sg) {
	if ($sg > 0.5)
		return 259 - 259 / $sg;
	return 0;
}



function plato_to_sg($plato) {
	if ($plato < 259)
		return 259 / (259 - $plato);
	return 1.000;
}



/*
 * sugars is the total extract weight of sugars.
 */
function estimate_sg($sugars, $batch_size) {
	$plato = 100 * $sugars / $batch_size;
	$sg = plato_to_sg($plato);

	/* Average loops, HansH 5x. Brouwhulp 20x, about 10x is enough so keep 20. */
	for ($i = 0; $i < 20; $i++) {
		if ($sg > 0)
			$plato = 100 * $sugars / ($batch_size * $sg);
		$sg = plato_to_sg($plato);
	}
	return $sg;
}



function estimate_fg($percSugar, $percCara, $WGratio, $TotTme, $Temp, $attenuation, $og) {
	if ($percSugar > 40)
		$percSugar = 0;
	if ($percCara > 50)
		$percCara = 0;
	if (($WGratio > 0) && ($TotTme > 0)) {
		$BD = $WGratio;
		$BD = max(2, min(5.5, $BD));
		$Temp = max(60, min(72, $Temp));
	} else {
		$BD = 3.5;
		$Temp = 67;
		$TotTme = 75;
	}
	if ($attenuation < 30)
		$attenuation = 77;

	$AttBeer = 0.00825 * $attenuation + 0.00817 * $BD - 0.00684 * $Temp + 0.00026 * $TotTme - 0.00356 * $percCara + 0.00553 * $percSugar + 0.547;
	$fg = 1 + (1 - $AttBeer) * ($og - 1);
	return $fg;
}



function abvol($og, $fg) {
	if ((4.749804 - $fg) <> 0)
		return 486.8693 * ($og - $fg) / (4.749804 - $fg);
	return 0;
}


/*
 * Kleurwerking naar SRM
 */
function kw_to_srm($colormethod, $c) {

	if ($colormethod == "Morey")
		return 1.4922 * pow($c, 0.6859);
	if ($colormethod == "Mosher")
		return 0.3 * $c + 4.7;
	if ($colormethod == "Daniels")
		return 0.2 * $c + 8.4;
}



function kw_to_ebc($colormethod, $c) {
	return srm_to_ebc(kw_to_srm($colormethod, $c));
}



function calc_IBU($useat, $form, $sg, $volume, $mass, $boiltime, $alpha, $method)
{
	global $my_factor_mashhop;
	global $my_factor_fwh;
	global $my_factor_pellet;
	global $my_factor_plug;

	$fmoment  = 1.0;
	if (($useat == "Dry Hop") || ($useat == "Dry hop") || ($useat == "Whirlpool") || ($useat == "Aroma")) {
		$fmoment = 0.0;
	} else if ($useat == "Mash") {
		$fmoment += $my_factor_mashhop / 100;         // Brouwhulp
	} else if (($useat == "First Wort") || ($useat == "First wort")) {
		$fmoment += $my_factor_fwh / 100;         // Brouwhulp, Louis, Ozzie
	}

	$pfactor  = 1.0;
	if ($form == "Pellet") {
		$pfactor += $my_factor_pellet / 100;
	}
	if ($form == "Plug") {
		$pfactor += $my_factor_plug / 100;
	}

	$ibu = 0;
	if (($method == "Tinseth") || ($method == "Garetz")) {	// For Garetz, we need the $ibu
		$AddedAlphaAcids = (($alpha / 100) * $mass * 1000) / $volume;
		$Bigness_factor = 1.65 * pow( 0.000125, $sg - 1);
		$BoilTime_factor = ((1 - exp(-0.04 * $boiltime)) / 4.15);
		$utiisation = $Bigness_factor * $BoilTime_factor;
		$ibu = (round($utiisation * $AddedAlphaAcids * $fmoment * $pfactor * 10) / 10.0);
	}
	if ($method == "Daniels") {

		if ($form == "Leaf")
			$boilfactor = -(0.0041*$boiltime*$boiltime)+(0.6162*$boiltime)+1.5779;
		else
			$boilfactor = -(0.0051*$boiltime*$boiltime)+(0.7835*$boiltime)+1.9348;
		if ($sg < 1.050)
			$sgfactor = 0;
		else
			$sgfactor = (($sg * 1000) - 1050) / 200;
		$ibu = $fmoment * (($mass * $alpha * $boilfactor * 0.1) / ($volume * (1 + $sgfactor)));
	}
	if ($method == "Rager") {
		$boilfactor = $fmoment * 18.11 + 13.86 * tanh(($boiltime * 31.32) / 18.27);
		if ($sg < 1.050)
			$sgfactor = 0;
		else
			$sgfactor = (($sg * 1000) - 1050) / 200;
		$ibu = ($mass * $alpha * $boilfactor * 0.1) / ($volume * (1 + $sgfactor));
	}
	if ($method == "Garetz") {
		/* Something is wrong, late hops and dryhops give negative results. */
		$boilfactor = $fmoment * 6.03253 + 16.5289 * tanh(($boiltime - 19.17323) / 26.8013);
		$cfactor = $volume / (1.1 * $volume);	// ConcentratieFactor = (Volume na koelen) / (Volume bij Koken)
		$kookdichtheid = ($cfactor * (($sg * 1000) - 1000) / 1000) + 1;
		$sgfactor = ($kookdichtheid - 1.05) / 0.2 + 1;
		$hopratefactor = (($cfactor * $ibu) / 260) + 1;	// $ibu is Tinseth bitterness. Weird.
		$tempfactor = (32.8/550)*0.02+1;
		$ibu = ($boilfactor * $alpha * $mass * 0.1) / ($volume * $sgfactor * $hopratefactor * $tempfactor);
	}
	/* TODO: Noonan and Mosher */

	return $ibu;
}



/*

Brouwhulp data.pas



Procedure TFermentable.SetpHParameters(force : boolean);
var x, ebc : double;
begin
  if Between(FDIpH.Value, -0.01, 0.01) or Between(FAcidTo57.Value, -0.1, 0.1) or force then
  begin
    ebc:= SRMtoEBC(FColor.Value);
    case FGrainType of
    gtBase, gtKilned:
    begin
      FDIpH.Value:= -0.0132 * ebc + 5.7605;
      x:= 0.4278 * ebc - 1.8106;
      FAcidTo57.Value:= x;
    end;
    gtRoast:
    begin
      FDIpH.Value:= 0.00018 * ebc + 4.558;
      FAcidTo57.Value:= -0.0176 * ebc + 60.04;
    end;
    gtCrystal:
    begin
      FDIpH.Value:= -0.0019 * ebc + 5.2175;
      FAcidTo57.Value:= 0.132 * ebc + 14.277;
    end;
    gtSour:
    begin
      FDIpH.Value:= 3.44;
      FAcidTo57.Value:= 337;
    end;
    gtSpecial: //this could be anything. Assume for now it is a non-acidulated base or kilned malt
    begin
      FDIpH.Value:= -0.0132 * ebc + 5.7605;
      FAcidTo57.Value:= 0.4278 * ebc - 1.8106;
    end;
    end;
  end;
  //known parameters should be filled in here
  if FSupplier.Value = 'Weyermann' then
  begin
    if FName.Value = 'Vienna mout' then
    begin
      FDIpH.Value:= 5.65;
      FAcidTo57.Value:= 1.6;
    end;
    if FName.Value = 'Münchner I' then
    begin
      FDIpH.Value:= 5.44;
      FAcidTo57.Value:= 8.4;
    end;
    if FName.Value = 'Münchner II' then
    begin
      FDIpH.Value:= 5.54;
      FAcidTo57.Value:= 5.6;
    end;
    if FName.Value = 'Caramunich I' then
    begin
      FDIpH.Value:= 5.1;
      FAcidTo57.Value:= 22.4;
    end;
    if FName.Value = 'Caramunich II' then
    begin
      FDIpH.Value:= 4.71;
      FAcidTo57.Value:= 49;
    end;
    if FName.Value = 'Caramunich III' then
    begin
      FDIpH.Value:= 4.92;
      FAcidTo57.Value:= 31.2;
    end;
    if FName.Value = 'Cara-aroma' then
    begin
      FDIpH.Value:= 4.48;
      FAcidTo57.Value:= 74.4;
    end;
    if FName.Value = 'Carafa I' then
    begin
      FDIpH.Value:= 4.71;
      FAcidTo57.Value:= 42;
    end;
    if FName.Value = 'Carafa III' then
    begin
      FDIpH.Value:= 4.81;
      FAcidTo57.Value:= 35.4;
    end;
    if FName.Value = 'Carafa II' then
    begin
      FDIpH.Value:= 4.76;
      FAcidTo57.Value:= 38.7;
    end;
    if FName.Value = 'Carafa Special I' then
    begin
      FDIpH.Value:= 4.73;
      FAcidTo57.Value:= 46.4;
    end;
    if FName.Value = 'Carafa Special II' then
    begin
      FDIpH.Value:= 4.78;
      FAcidTo57.Value:= 42.9;
    end;
    if FName.Value = 'Carafa Special III' then
    begin
      FDIpH.Value:= 4.83;
      FAcidTo57.Value:= 38.9;
    end;
    if IsInString(FName.Value, 'Zuurmout') then
    begin
      FDIpH.Value:= 3.44;
      FAcidTo57.Value:= 358.2;
    end;
  end;
end;


function TFermentable.GetExtract: double;
begin
  Result := 0;
  if FRecipe <> nil then
  begin
    Result := FAmount.Value * FYield.Value / 100 * (1 - FMoisture.Value / 100);
    if FAdded = atMash then
      Result := Result * FRecipe.Efficiency / 100;
  end;
end;


function TFermentable.GetKolbachIndex: double;
begin
  if FProtein.Value > 0 then
    Result := FDissolvedProtein.Value / FProtein.Value
  else
    Result := 0;
end;


function TWater.GetResidualAlkalinity: double;
begin
  //Result in mg/l as CaCO3
  Result:= FTotalAlkalinity.Value - (FCalcium.Value / 1.4 + FMagnesium.Value / 1.7);
end;


function TWater.GetHardness: double;
begin
  Result := 0.14 * FCalcium.Value - 0.23 * FMagnesium.Value;
end;

function TWater.GetEstPhMash: double;
{var
  pHdemi, S: double;}
begin
  Result:= MashpH;
{  Result := 0;
  if FRecipe <> nil then
  begin
    pHDemi := FRecipe.pHdemi;
    S := 0.013 * FRecipe.MashThickness + 0.013;
    Result := pHDemi + ResidualAlkalinity / 50 * S;
  end;}
end;





Procedure TRecipe.CalcCalories;
var sug, alc, org, fig : double;
begin
  if FOGFermenter.Value > 1.001 then org:= FOGFermenter.Value
  else if FOG.Value > 1.001 then org:= FOG.Value
  else org:= 0;
  if FFG.Value > 0.999 then fig:= FFG.Value
  else if FEstFG.Value > 1.000 then fig:= FEstFG.Value
  else if FEstFG2.Value > 1.000 then fig:= FEstFG2.Value
  else fig:= 0;
  if (org > 0) and (fig > 0) then
  begin
    alc:= 1881.22 * fig * (org - fig) / (1.775 - org);
    sug:= 3550 * fig * (0.1808 * org + 0.8192 * fig - 1.0004);
    FCalories.Value:= (alc + sug) / (12 * 0.0295735296);
  end
  else FCalories.Value:= 0;
end;




*/

?>

mercurial