(* =====================================================================
   23_fb_headroom.st - FB_HEADROOM, section 4.4

   Pure calculation.  No control action, no alarms.

   Reference condition, WRPS-PRO-001 7.3 and pass 1 test 14:
     level 4.00 m, inflow 165 L/s, one pump at 120 L/s
       NetInflow   = 45.0 L/s          -> %QW7 = 450
       VolToSpill  = (6.0 - 4.0) * 120 = 240 m3
       TimeToSpill = 240 * 1000 / 45   = 5333.3 s -> %QW5 = 5333
   ===================================================================== *)

FUNCTION_BLOCK FB_HEADROOM
VAR_INPUT
    Level           : REAL;     (* m                                    *)
    Inflow          : REAL;     (* L/s, unfiltered                      *)
    TotalDischarge  : REAL;     (* L/s                                  *)
END_VAR

VAR_OUTPUT
    InflowFilt      : REAL;     (* L/s, 30 s lag                        *)
    NetInflow       : REAL;     (* L/s                                  *)
    VolToSpill      : REAL;     (* m3                                   *)
    VolToLSHH       : REAL;     (* m3                                   *)
    TimeToSpill     : INT;      (* s, 32767 = drawing down              *)
    TimeToLSHH      : INT;      (* s, 32767 = drawing down              *)
END_VAR

VAR CONSTANT
    SCAN_S      : REAL := 0.1;      (* must match TASK INTERVAL         *)
    TAU_S       : REAL := 30.0;     (* inflow filter time constant      *)
    AREA_M2     : REAL := 120.0;
    SPILL_M     : REAL := 6.000;
    LSHH_M      : REAL := 5.500;
    MIN_NET     : REAL := 0.5;      (* L/s, below this the figure is
                                       meaningless - drawing down       *)
    NO_TIME     : INT  := 32767;
    MAX_TIME    : REAL := 32767.0;
END_VAR

VAR
    Primed  : BOOL := FALSE;
    t       : REAL;
END_VAR

(* --- Inflow filter.  First-order lag, 30 s.

   Primed on the first scan rather than ramping from zero: without
   this the reference figure in test 14 would take ~2 minutes to
   settle and would not reproduce exactly on demand. ---------------- *)
IF NOT Primed THEN
    InflowFilt := Inflow;
    Primed     := TRUE;
ELSE
    InflowFilt := InflowFilt + (Inflow - InflowFilt) * SCAN_S / TAU_S;
END_IF;

NetInflow  := InflowFilt - TotalDischarge;

VolToSpill := (SPILL_M - Level) * AREA_M2;
VolToLSHH  := (LSHH_M  - Level) * AREA_M2;
IF VolToSpill < 0.0 THEN
    VolToSpill := 0.0;
END_IF;
IF VolToLSHH < 0.0 THEN
    VolToLSHH := 0.0;
END_IF;

(* --- Time to spill weir ------------------------------------------- *)
IF NetInflow <= MIN_NET THEN
    TimeToSpill := NO_TIME;
ELSE
    t := VolToSpill * 1000.0 / NetInflow;
    IF t >= MAX_TIME THEN
        TimeToSpill := NO_TIME;
    ELSIF t < 0.0 THEN
        TimeToSpill := 0;
    ELSE
        TimeToSpill := REAL_TO_INT(t);
    END_IF;
END_IF;

(* --- Time to LSHH -------------------------------------------------- *)
IF NetInflow <= MIN_NET THEN
    TimeToLSHH := NO_TIME;
ELSE
    t := VolToLSHH * 1000.0 / NetInflow;
    IF t >= MAX_TIME THEN
        TimeToLSHH := NO_TIME;
    ELSIF t < 0.0 THEN
        TimeToLSHH := 0;
    ELSE
        TimeToLSHH := REAL_TO_INT(t);
    END_IF;
END_IF;

END_FUNCTION_BLOCK
