본문으로 바로가기

zaskateam 님이 제공해 주신 팁입니다.


반복계산하는 프로그램의 수렴성을 테스트하기 위해서는 error rate를 텍스트로 출력해서 볼 수도 있지만, 그림으로 보면 더 명확해집니다. 이를 위해 간단한 팁을 올려 드립니다.

For 문으로 iteration 되는 프로그램에서 200 step마다 residue를 계산하여 residues.txt에 저장하려고 합니다. 반복이 되면서 쌓이는 데이터 중에 2000 step의 데이터만 plotting 하려 합니다. 저는 blt::stripchart를 사용했습니다. blt::graph에는 없는 기능들이 더 있습니다. 사용방법은 비슷합니다. 특히 -autorange, -shiftby를 사용하면 원하는 데이터만 plotting 할 수 있습니다.

제가 구현한 방법은 아래와 같습니다. 다른 분들은 아마 더 쉽게 할 수도 있을 것 같아요^^; Run을 클릭하면 아래의 cal_run을 호출합니다.

proc cal_run {} {
set pushd [pwd]
cd ju

...
set cmd "./win.exe"
blt::bgexec execstatus \
        -onoutput ::StdoutMessage \
        -keepnewline true \
        $cmd &
...
cd $pushd
}

btl::bgexec에서 -onoutput 을 사용하면 콘솔에 stdout으로 나오는 데이터를 얻어올 수 있습니다. 저는 tkcon을 삽입해서 그 msg를 바로 뿌려주고, 거기에서 residue를 plotting 하는 함수를 콜 하도록 했습니다. 데이터가 파일로 출력되는 시간을 고려해 sleep을 좀 줬습니다. 그리고 see_residue가 1이면 실행되는 동안 plotting 하도록 했습니다. see_residue는 별것 아니고, 메뉴바에서 체크가 되면 1이 되도록 해서 필요하면 볼 수 있게 했습니다. 저는 defalut로 1을 줬습니다.

proc StdoutMessage {msg} {
        global point_value
        global xrange_value
        global xshift_value
        global see_residue
        puts $msg

        sleep 500

        if {$see_residue == 1} {
                graph_residue
        }

# 200번마다 데이터가 출력되고 있음.
# 최종 2000번의 데이터만 출력하기 위해 shiftby값을 추가시킴

        set xshift_value [expr $xshift_value + 200]
}

proc sleep {time} {
      after $time set end 1
      vwait end
}

그리고 중요한 blt::stripchart를 이용해 plotting하는 소스입니다.

proc graph_residue {} {
        namespace import blt::*
        namespace import -force blt::tile::*
        global xrange_value
        global xshift_value

        global show_residue fr19

        option add *bufferElements no
        option add *bufferGraph yes
        option add *Axis.lineWidth 1
        option add *Axis*Rotate 90
        option add *pixels 1.25m
        option add *Stripchart.width 6i

        if [winfo exist .show_residue] {
                raise .show_residue
        } else {
                toplevel .show_residue
        }
        wm title .show_residue "Residues of Plasma Parameters"

        if [winfo exist .show_residue.fr19] {
                destroy .show_residue.fr19
        }

        set fr19 [frame .show_residue.fr19]
        pack $fr19 -fill x

        set rgraph [blt::stripchart $fr19.graph -title "Residues"]
        pack $rgraph

        # For 문으로 iteration 되는 프로그램에서
        # 200 step마다 residue를 계산하여 residues.txt에 저장한다.
        # 반복이 되면서 쌓이는 데이터 중에 2000 step의 데이터만 plotting 하려 한다.
        # -autorange 2000
        # -shiftby 는 초기값을 0으로 주고 데이터가 추가 될 때마다 그 증가량 만큼 증가시킴
        # 그러면 나중에 나오는 데이터 2000 step만 plotting 된다.

        $rgraph axis configure x -autorange 2000
        $rgraph axis configure x -shiftby $xshift_value

        # 축에 라벨 표시
        $rgraph xaxis configure -title "Iteration (#)"
        $rgraph yaxis configure -title "Residues"

        # Grid 표시
        $rgraph grid on

        # Output 파일 갯수를 얻어온다
        set outdata "./residues.txt"
        set file [open $outdata r]
        set i 1
        while { [gets $file line] != -1 } {
                incr i 1
        }
        close $file

        # 배열에 할당함
        set arr_num [expr $i-1]
        vector x($arr_num) y0($arr_num) y1($arr_num) y2($arr_num)
        set outdata "./residues.txt"
        set file [open $outdata r]
        set i 1
        while { [gets $file line] != -1 } {
                scan $line "%f %f %f %f %f" iter ni ne nN Te
                set x($i-1) $iter
                set y0($i-1) $ne
                set y1($i-1) $nN
                set y2($i-1) $Te
                incr i 1
        }
        close $file

        $rgraph element create ne -symbol square \
                -color red \
                -xdata x -ydata y0
       
        $rgraph element create nN -symbol triangle \
                -color green \
                -xdata x -ydata y1
       
        $rgraph element create Te -symbol cross \
                -color blue \
                -xdata x -ydata y2

        $rgraph axis configure y -min {} -max {}
       
        # 로그 스케일
        $rgraph axis configure x -logscale yes
        $rgraph axis configure y -logscale yes
}

마지막으로 아주 중요한 tip알려드립니다. 제가 이것 때문에 아주 고생했습니다.

win.exe 파일을 ./ju/win.exe에 두었습니다. 그래서 ./ju 폴더로 디렉터리를 변경한 후에 win.exe를 실행하도록 했습니다. 그리고 residues.txt파일도 ./ju/residue.txt에 출력되게 했습니다. 그러면 run을 눌러 win.exe가 실행되는 동안에는 ./ju 폴더로 이동한 상태죠. 따라서 plotting할 때, 데이터의 위치는 ./ju/residues.txt이 아닌 그냥 ./residues.txt이 됩니다. 이것 때문에 정말 삽질했습니다.

그럼 많은 도움이 되었으면 좋겠습니다.