# flow control module based on hipadaba namespace eval flow { } proc flow::loop {difget flowget flowset path flowstd flowlim} { $difget $path difmin difmax $flowget $path flowmin flowmax set setval [hvali $path/flowset] set setmin [expr [hvali $path/prop] * $difmin + $flowmin - $setval] set setmax [expr [hvali $path/prop] * $difmax + $flowmax - $setval] hupdate $path/setmin $setmin hupdate $path/setmax $setmax set c [hvali $path/smooth] if {$setmin > $setval} { set setval [expr $setmin * $c + $setval * (1 - $c)] } elseif {$setmax < $setval} { set setval [expr $setmax * $c + $setval * (1 - $c)] } putIntoLimits setval $flowstd $flowlim $flowset $path $setval # the above calculation has the disantvantage, that $path/flowset might be higher # than the flowstd, when the actual flow is very high. We calculate a # more meaningful target just for make the user happy. set flowtarget [expr [hvali $path/prop] * ($difmin + $difmax) * 0.5] #clientput "$flowtarget := [hvali $path/prop] * ($difmin + $difmax) * 0.5" if {$flowtarget < $flowstd && $setval < $flowmin} { set flowtarget [expr $c * $flowstd + (1 - $c) * [hvali $path/flowtarget]] } else { set flowtarget $setval } putIntoLimits flowtarget $flowstd $flowlim set suppress_auto [silent 0 sct suppress_auto] if {$suppress_auto || $flowtarget > ($flowstd + $flowlim) * 0.5} { sct suppress_auto 0 hupdate $path/flowtarget $flowtarget } else { if {$flowtarget < $flowstd + 0.1} { sct suppress_auto 1 } else { hupdate $path/flowtarget $flowtarget } } } proc flow::bufferPut {path name var value} { upvar $var buf set buf [hvali $path/${name}Buf] lappend buf [format %.11g $value] set buf [lrange $buf end-[expr [hvali $path/${name}Size] - 1] end] hupdate $path/${name}Buf $buf } proc flow::difget {path minname maxname} { upvar $minname min upvar $maxname max set t [eval [hvali $path/getTemp]] if {$t eq "NaN"} { set t 0 } set s $t if {[catch { set s [eval [hvali $path/getTset]] hsetprop $path/getTset t_set_undefined 0 }]} { hsetprop $path/getTset t_set_undefined 1 } if {$s eq "NaN"} { set s $t } if {$s < [hvali $path/Tmin]} { set s [hvali $path/Tmin] } #clientput [format {set %.11g ist %.11g} $s $t] flow::bufferPut $path dif buf [expr $t - $s] set last [lindex $buf end] set first [lindex $buf 0] set l [hvali $path/difSize] set slope1 [expr ($last - $first) / $l] set slope2 [expr ([lindex $buf [hvali $path/difRange]] - $first) / $l] #clientput [format {dif %.11g %.11g slope %.11g %.11g} $t $s $slope1 $slope2] if {$slope1 > $slope2} { set max [expr $last + $slope1 * [hvali $path/convTime]] # set min $last set min [expr $last + $slope2 * [hvali $path/convTime]] } else { set min [expr $last + $slope1 * [hvali $path/convTime]] set max [expr $last + $slope2 * [hvali $path/convTime]] } #clientput [format {last %.11g min %.11g max %.11g} $last $min $max] hupdate $path/difmax $max hupdate $path/difmin $min } proc flow::flowget {path flowmin flowmax} { upvar $flowmin min upvar $flowmax max flow::bufferPut $path flow buf [eval [hvali $path/getFlow]] set s [lsort -real $buf] set max [lindex $s end] set min [lindex $s 0] hupdate $path/flowmin $min hupdate $path/flowmax $max } proc flow::flowset {path setval} { set val [format "%.1f" $setval] # if {[hvali $path/flowset] != $val} { # eval "[hvali $path/setFlow] $val" # } hupdate $path/flowset $setval } proc flow::task {path flowstd flowlim} { flow::loop flow::difget flow::flowget flow::flowset $path $flowstd $flowlim } proc flow::pitask {path flowstd flowlim} { set tt [silent 1 result tt tm] set p [silent 0 result tt set/power] set tt [expr $tt - $p] set st $tt if {[catch { set st [eval [hvali $path/getTset]] hsetprop $path/getTset t_set_undefined 0 }]} { hsetprop $path/getTset t_set_undefined 1 } if {$st < [hvali $path/Tmin]} { set st [hvali $path/Tmin] } set y [hvali $path/flowmin] set dif [expr $tt - $st] set now [DoubleTime] set lastim [silent $now hgetpropval $path lastim] hsetprop $path lastim $now set lasdif [silent 0 hgetpropval $path lasdif] hsetprop $path lasdif $dif set dt [expr $now - $lastim] set prop [hvali $path/prop] set convTime [hvali $path/convTime] set y [expr $y + $prop * (($dif - $lasdif) + ($dif - 5 * $p) * $dt / double($convTime))] putIntoLimits y [expr -$flowlim] $flowlim hupdate $path/flowmin $y putIntoLimits y $flowstd $flowlim hupdate $path/flowset $y hupdate $path/flowtarget $y } proc flow::make {{getT flow::tmts} {getS "result tt tr"} {getF "result nv flow"}} { namespace eval ::stdConfig [subst { node suspended par 0 prop enum 1 node prop par 5 node flowstd par 2 node flowlim par 20 node smooth par 0.05 node difSize par 10 node difRange par 7 node flowSize par 10 node convTime par 30 node Tmin par 1.5 node script -text par "flow::task" prop width 24 node getTemp -text par "$getT" prop width 24 node getTset -text par "$getS" prop t_set_undefined 0 prop width 24 node getFlow -text par "$getF" prop width 24 node difBuf -nolog -text upd default "" node flowBuf -nolog -text upd default "" node flowset upd default 2 node flowmin upd node flowmax upd node difmin upd node difmax upd node setmin upd node setmax upd node flowtarget upd }] } proc flow::tmts {} { set tm [silent 1 result tt tm] set ts [silent $tm result tt ts] if {$ts < $tm} { return $ts } else { return $tm } } proc flow::tmts2 {} { set tm [silent 1 result tt tm] # set ts [silent $tm result tt ts] set p [silent 0 result tt set/power] set pr [silent 0 hvali /nv/autoflow/prop] return [expr $tm - $p / $pr] } proc flow::ma15tmts {} { set tm [result te] set ts [result tt] if {$ts < 0} { return $tm } if {$ts < $tm} { return $ts } else { return $tm } }