Files
sea/tcl/startup/flow_ctrl.tcl

221 lines
6.0 KiB
Tcl

# 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
}
}