268 |
268 |
269 /* |
269 /* |
270 |
270 |
271 Brouwhulp data.pas |
271 Brouwhulp data.pas |
272 |
272 |
273 Function THop.FlavourContribution : double; //in % * concentration in g/l |
|
274 var bt, vol : double; |
|
275 begin |
|
276 bt:= FTime.Value; |
|
277 vol:= 0; |
|
278 if FRecipe <> NIL then vol:= FRecipe.BatchSize.Value; |
|
279 if FUse = huFirstWort then Result:= 0.15 * FAmount.Value * 1000 //assume 15% flavourcontribution for fwh |
|
280 else if bt > 50 then Result:= 0.10 * FAmount.Value * 1000 //assume 10% flavourcontribution as a minimum |
|
281 else |
|
282 begin |
|
283 Result:= 15.25 / (6 * sqrt(2 * PI)) * Exp(-0.5*Power((bt-21)/6, 2)) |
|
284 * FAmount.Value * 1000; |
|
285 if result < 0.10 * FAmount.Value * 1000 then |
|
286 Result:= 0.10 * FAmount.Value * 1000 //assume 10% flavourcontribution as a minimum |
|
287 end; |
|
288 if vol > 0 then Result:= Result / vol; |
|
289 end; |
|
290 |
|
291 Function THop.AromaContribution : double; //in % * concentration in g/l |
|
292 var bt, vol : double; |
|
293 begin |
|
294 bt:= FTime.Value; |
|
295 vol:= 0; |
|
296 if FRecipe <> NIL then vol:= FRecipe.BatchSize.Value; |
|
297 if bt > 20 then Result:= 0 |
|
298 else if bt > 7.5 then |
|
299 Result:= 10.03 / (4 * sqrt(2 * PI)) * Exp(-0.5*Power((bt-7.5)/4, 2)) |
|
300 * FAmount.Value * 1000 |
|
301 else if FUse = huBoil then Result:= FAmount.Value * 1000 |
|
302 else if FUse = huAroma then Result:= 1.2 * FAmount.Value * 1000 |
|
303 else if FUse = huWhirlpool then Result:= 1.2 * FAmount.Value * 1000 |
|
304 else if FUse = huDryHop then Result:= 1.33 * FAmount.Value * 1000; |
|
305 if vol > 0 then Result:= Result / vol; |
|
306 end; |
|
307 |
273 |
308 |
274 |
309 Procedure TFermentable.SetpHParameters(force : boolean); |
275 Procedure TFermentable.SetpHParameters(force : boolean); |
310 var x, ebc : double; |
276 var x, ebc : double; |
311 begin |
277 begin |
437 else |
403 else |
438 Result := 0; |
404 Result := 0; |
439 end; |
405 end; |
440 |
406 |
441 |
407 |
442 Procedure TWater.AddMinerals(Ca, Mg, Na, HCO3, Cl, SO4 : double); |
|
443 begin |
|
444 FCalcium.Add(Ca); |
|
445 FMagnesium.Add(Mg); |
|
446 FSodium.Add(Na); |
|
447 FBicarbonate.Add(HCO3); |
|
448 FChloride.Add(Cl); |
|
449 FSulfate.Add(SO4); |
|
450 end; |
|
451 |
|
452 function TWater.GetResidualAlkalinity: double; |
408 function TWater.GetResidualAlkalinity: double; |
453 begin |
409 begin |
454 //Result in mg/l as CaCO3 |
410 //Result in mg/l as CaCO3 |
455 Result:= FTotalAlkalinity.Value - (FCalcium.Value / 1.4 + FMagnesium.Value / 1.7); |
411 Result:= FTotalAlkalinity.Value - (FCalcium.Value / 1.4 + FMagnesium.Value / 1.7); |
456 end; |
412 end; |
457 |
413 |
458 const |
|
459 Ka1 = 0.0000004445; |
|
460 Ka2 = 0.0000000000468; |
|
461 |
|
462 Function PartCO3(pH : double) : double; |
|
463 var H : double; |
|
464 begin |
|
465 H:= Power(10, -pH); |
|
466 Result:= 100 * Ka1 * Ka2 / (H*H + H * Ka1 + Ka1 * Ka2); |
|
467 end; |
|
468 |
|
469 Function PartHCO3(pH : double) : double; |
|
470 var H : double; |
|
471 begin |
|
472 H:= Power(10, -pH); |
|
473 Result:= 100 * Ka1 * H / (H*H + H * Ka1 + Ka1 * Ka2); |
|
474 end; |
|
475 |
|
476 Function PartH2CO3(pH : double) : double; |
|
477 var H : double; |
|
478 begin |
|
479 H:= Power(10, -pH); |
|
480 Result:= 100 * H * H / (H*H + H * Ka1 + Ka1 * Ka2); |
|
481 end; |
|
482 |
|
483 Function Charge(pH : double) : double; |
|
484 begin |
|
485 Result:= (-2 * PartCO3(pH) - PartHCO3(pH)); |
|
486 end; |
|
487 |
|
488 //Z alkalinity is the amount of acid (in mEq/l) needed to bring water to the target pH (Z pH) |
|
489 Function TWater.ZAlkalinity(pHZ : double) : double; //in mEq/l |
|
490 var CT, DeltaCNaught, DeltaCZ, C43, Cw, Cz : double; |
|
491 begin |
|
492 C43:= Charge(4.3); |
|
493 Cw:= Charge(FpH.Value); |
|
494 Cz:= Charge(pHz); |
|
495 DeltaCNaught:= -C43+Cw; |
|
496 CT:= GetAlkalinity / 50 / DeltaCNaught; |
|
497 DeltaCZ:= -Cz+Cw; |
|
498 Result:= CT * DeltaCZ; |
|
499 end; |
|
500 |
|
501 //Z Residual alkalinity is the amount of acid (in mEq/l) needed to bring the water in the mash to the target pH (Z pH) |
|
502 Function TWater.ZRA(pHZ : double) : double; //in mEq/l |
|
503 var Calc, Magn, Z : double; |
|
504 begin |
|
505 Calc:= FCalcium.Value / (MMCa / 2); |
|
506 Magn:= FMagnesium.Value / (MMMg / 2); |
|
507 Z:= ZAlkalinity(pHZ); |
|
508 Result:= Z - (Calc / 3.5 + Magn / 7); |
|
509 end; |
|
510 |
|
511 Function TWater.ProtonDeficit(pHZ : double) : double; |
|
512 var i : integer; |
|
513 F : TFermentable; |
|
514 x : double; |
|
515 begin |
|
516 Result:= ZRA(pHZ) * FAmount.Value; |
|
517 //proton deficit for the added malts |
|
518 for i:= 0 to FRecipe.NumFermentables - 1 do |
|
519 begin |
|
520 F:= FRecipe.Fermentable[i]; |
|
521 if (F.AddedType = atMash) and (F.GrainType <> gtNone) then |
|
522 begin |
|
523 x:= F.AcidRequired(pHZ) * F.Amount.Value; |
|
524 Result:= Result + x; |
|
525 end; |
|
526 end; |
|
527 end; |
|
528 |
|
529 Function TWater.MashpH : double; |
|
530 var n : integer; |
|
531 pd : double; |
|
532 pH, deltapH, deltapd : double; |
|
533 begin |
|
534 Result:= 0; |
|
535 n:= 0; |
|
536 pH:= 5.4; |
|
537 deltapH:= 0.001; |
|
538 deltapd:= 0.1; |
|
539 pd:= ProtonDeficit(pH); |
|
540 while ((pd < -deltapd) or (pd > deltapd)) and (n < 1000) do |
|
541 begin |
|
542 inc(n); |
|
543 if pd < -deltapd then ph:= ph - deltapH |
|
544 else if pd > deltapd then pH:= pH + deltapH; |
|
545 pd:= ProtonDeficit(pH); |
|
546 end; |
|
547 Result:= pH; |
|
548 end; |
|
549 |
|
550 Function TWater.MashpH2(PrDef : double) : double; |
|
551 var n : integer; |
|
552 pd : double; |
|
553 pH, deltapH, deltapd : double; |
|
554 begin |
|
555 Result:= 0; |
|
556 n:= 0; |
|
557 pH:= 5.4; |
|
558 deltapH:= 0.001; |
|
559 deltapd:= 0.1; |
|
560 pd:= ProtonDeficit(pH); |
|
561 while ((pd < PrDef-deltapd) or (pd > PrDef + deltapd)) and (n < 1000) do |
|
562 begin |
|
563 inc(n); |
|
564 if pd < PrDef-deltapd then ph:= ph - deltapH |
|
565 else if pd > PrDef+deltapd then pH:= pH + deltapH; |
|
566 pd:= ProtonDeficit(pH); |
|
567 end; |
|
568 Result:= pH; |
|
569 end; |
|
570 |
|
571 function TWater.GetAlkalinity: double; |
|
572 begin |
|
573 Result := FBicarbonate.Value / 1.22; //mEq/l |
|
574 end; |
|
575 |
414 |
576 function TWater.GetHardness: double; |
415 function TWater.GetHardness: double; |
577 begin |
416 begin |
578 Result := 0.14 * FCalcium.Value - 0.23 * FMagnesium.Value; |
417 Result := 0.14 * FCalcium.Value - 0.23 * FMagnesium.Value; |
579 end; |
418 end; |
588 begin |
427 begin |
589 pHDemi := FRecipe.pHdemi; |
428 pHDemi := FRecipe.pHdemi; |
590 S := 0.013 * FRecipe.MashThickness + 0.013; |
429 S := 0.013 * FRecipe.MashThickness + 0.013; |
591 Result := pHDemi + ResidualAlkalinity / 50 * S; |
430 Result := pHDemi + ResidualAlkalinity / 50 * S; |
592 end;} |
431 end;} |
593 end; |
|
594 |
|
595 |
|
596 function TBeerStyle.GetBUGUMin: double; |
|
597 var |
|
598 B, G: double; |
|
599 begin |
|
600 Result:= 0; |
|
601 if ((FOGMax.Value + FOGMin.Value) > 0) and ((FIBUMax.Value + FIBUMin.Value) > 0) then |
|
602 begin |
|
603 G := (FOGMax.Value - FOGMin.Value) / ((FOGMax.Value + FOGMin.Value) / 2); |
|
604 B := (FIBUMax.Value - FIBUMin.Value) / ((FIBUMax.Value + FIBUMin.Value) / 2); |
|
605 if G > B then |
|
606 Result := ((FIBUMin.Value + FIBUMax.Value) / 2) / (1000 * (FOGMax.Value - 1)) |
|
607 else |
|
608 Result := FIBUMin.Value / (1000 * (((FOGMax.Value + FOGMin.Value) / 2) - 1)); |
|
609 end; |
|
610 end; |
|
611 |
|
612 function TBeerStyle.GetBUGUMax: double; |
|
613 var |
|
614 B, G: double; |
|
615 begin |
|
616 Result:= 0; |
|
617 if ((FOGMax.Value + FOGMin.Value) > 0) and ((FIBUMax.Value + FIBUMin.Value) > 0) |
|
618 and (FOGMin.Value > 1) then |
|
619 begin |
|
620 G := (FOGMax.Value - FOGMin.Value) / ((FOGMax.Value + FOGMin.Value) / 2); |
|
621 B := (FIBUMax.Value - FIBUMin.Value) / ((FIBUMax.Value + FIBUMin.Value) / 2); |
|
622 if G > B then |
|
623 Result := ((FIBUMin.Value + FIBUMax.Value) / 2) / (1000 * (FOGMin.Value - 1)) |
|
624 else |
|
625 Result := FIBUMax.Value / (1000 * (((FOGMax.Value + FOGMin.Value) / 2) - 1)); |
|
626 end; |
|
627 end; |
|
628 |
|
629 |
|
630 // Get concentration of ions in diluted brewwater (1) and target water (2) in mmol/l |
|
631 Ca1 := W.Calcium.Value / MMCa; |
|
632 Ca2 := W2.Calcium.Value / MMCa; |
|
633 Mg1 := W.Magnesium.Value / MMMg; |
|
634 Mg2 := W2.Magnesium.Value / MMMg; |
|
635 Na1 := W.Sodium.Value / MMNa; |
|
636 Na2 := W2.Sodium.Value / MMNa; |
|
637 |
|
638 CO31 := W.Bicarbonate.Value / MMHCO3; |
|
639 CO32 := W2.Bicarbonate.Value / MMHCO3; |
|
640 SO41 := W.Sulfate.Value / MMSO4; |
|
641 SO42 := W2.Sulfate.Value / MMSO4; |
|
642 Cl1 := W.Sulfate.Value / MMSO4; |
|
643 Cl2 := W2.Sulfate.Value / MMSO4; |
|
644 |
|
645 |
|
646 procedure TRecipe.CalcWaterBalance; |
|
647 var |
|
648 i: integer; |
|
649 F: TFermentable; |
|
650 begin |
|
651 FAbsorbedByGrain := 0; |
|
652 for i := Low(FFermentables) to High(FFermentables) do |
|
653 begin |
|
654 F := TFermentable(FFermentables[i]); |
|
655 if (F.FermentableType = ftGrain) or (F.FermentableType = ftAdjunct) then |
|
656 FAbsorbedByGrain := FAbsorbedByGrain + F.Amount.Value; |
|
657 end; |
|
658 FAbsorbedByGrain := FAbsorbedByGrain * Settings.GrainAbsorption.Value; |
|
659 |
|
660 if FEquipment.CalcBoilVolume.Value then |
|
661 {FBoilSize.Value := FBatchSize.Value / (1 - (FEquipment.EvapRate.Value / 100) * |
|
662 (FBoilTime.Value / 60));} |
|
663 FBoilSize.Value:= FBatchSize.Value + FEquipment.BoilSize.Value |
|
664 * FEquipment.EvapRate.Value / 100 * |
|
665 (FBoilTime.Value / 60); |
|
666 end; |
432 end; |
667 |
433 |
668 |
434 |
669 |
435 |
670 |
436 |