# # Wavefront & Shack-Hartmann Simulator # # Air bubbles & phase delays hypothesis # # Image (from original standalone program have been suppressed) # because plugin does not support binary extensions # # 1995/1996 by Laurent Demailly # # Thanks to Olivier Lai, Jean-Pierre Veran and Eric Gendron for physics hints # # note this was a quick hack primarly to create some # figures for my thesis, the coding style is not not representative # of my usual habits ! # Some TclX builtins replacements: (too slow...) proc loop {var start end body} { upvar $var v; for {set v $start} {$v<$end} {incr v} { uplevel $body; } } # tcl-usage' faq random : proc random {args} { global RNG_seed; set max 259200; set argcnt [llength $args]; if { $argcnt < 1 || $argcnt > 2 } { error "wrong # args: random limit | seed ?seedval?" } if ![string compare [lindex $args 0] seed] { if { $argcnt == 2 } { set RNG_seed [lindex $args 1] } else { set RNG_seed [clock clicks] ; # poor... } return; } if ![info exists RNG_seed] { set RNG_seed [clock clicks] ; # poor... } set RNG_seed [expr ($RNG_seed*7141+54773) % $max] return [expr int(double($RNG_seed)*[lindex $args 0]/$max)] } proc lassign {list args} { set i 0; foreach vname $args { uplevel [list set $vname [lindex $list $i]]; incr i; } lrange $list $i end } ######### start of the program (french comments!) ######### # nombre de sous pupilles set nb_pup 5 # nombre de point d'echantillons par sous pupilles set nb_ptspup 3 ; # 9 # soit nombre de points : # +---+---+---+ # 123412341234X <- nb_pup 4 , nb_ptspup 5 # 12345 # espace entre les points set echx 20 ; # 10 # 'vitesse' dans milieu global (pas d'echantillonage en y) set v0 20; # vitesse lente dans bulle froide set vlow 18; # vitesse rapide dans bulle chaude set vhigh 22; # nombre de bulles set nb_bulles 5 ; # 15 # sous echantillonage affichage: (affiche 1/$skipy calculs) set skipy 1; set offy 20; # hauteur de la zone turbulente set ty 220; # generatoire aleatoire random seed 45679; # rayon minimal des bulles set minr 10; # ecart aleatoire maximum (maxr=minr+randr) set randrstart 60 ; # genere une nouvelle bulle proc bulle {} { global tx ty minr randr offy vlow vhigh; # distribution 'kolmogorov' des tailles set r [expr int($minr+pow([random [expr int(pow($randr,3))]],.333333))]; set x [expr [random [expr $tx+2*($r-1)]]-$r+1]; set y [expr $offy+$r+[random [expr $ty-(2*$r)]]]; set v [expr [random 2]?$vlow:$vhigh]; list $x $y $r $v; } # est-ce que la bulle (x,y,r) intercepte une bulle deja existante ? proc isin {x y r} { global blist; foreach bul $blist { lassign $bul xb yb rb vb; set dx [expr $xb-$x]; set dy [expr $yb-$y]; set dist [expr $dx*$dx+$dy*$dy]; if {$dist<($r+$rb)*($r+$rb)} { return 1 } } return 0; } # vitesse du milieu au point (x,y) proc getv {x y} { global blist v0; foreach bul $blist { lassign $bul xb yb rb vb; set dx [expr $xb-$x]; set dy [expr $yb-$y]; if {($dx*$dx+$dy*$dy)<=($rb*$rb)} {return $vb} } return $v0; } # nom du canvas de dessin frame .tc pack .tc -side bottom -fill both -expand 1 -side right ; set c ".tc.c" # # Construction de l'interface utilisateur # permettant de changer les parametres, lancer et arretter la simu,... # frame .fl -relief groove -borderwidth 3; label .fl.l1 -text "WF Simulation (toy)" ; label .fl.l2 -text "Laurent Demailly" button .pr -text "Start simulation" -command "do" pack .fl .fl.l1 .fl.l2 -pady 1m -padx .5m; # variables controlables et nom: # with current tk_plugin, no toplevel so we have to fix # dimensions... # {nb_ptspup "Number of Samples per aperture"} # {echx "X Scale"} # {nb_pup "Number of Apertures"} # {skipy "Skip"} # {offy "Offy"} # {ty "Turbulence layer height"} set lst { {nb_bulles "Number of Bubbles"} {v0 "Nominal Speed"} {vlow "Speed in cold bubbles"} {vhigh "Speed in hot (red) bubbles"} {minr "Minimal bubble radius"} {randrstart "Aditional random radius"} } frame .fv; pack .fv -padx .5m -pady .5m -fill x -expand 1; # could be replaced by newer & nice grid manager... [this is old code of mine] foreach el $lst { lassign $el nvar label; set f .fv.f$nvar; frame $f; label $f.l$nvar -text "$label :" -anchor w; entry $f.e$nvar -width 4 -textvariable $nvar -relief sunken ; pack $f.l$nvar -fill x -expand y -side left; pack $f.e$nvar -fill x -side left; pack $f -padx .5m -pady .5m -fill x -expand 1; } pack .pr -pady .5m -padx .5m; set font "-*-helvetica-medium-r-normal--8-*" set fontmap($font) [list "Helvetica-Bold" 8]; set colormap(red) "1 .3 .3 setrgbcolor" set colormap(blue) "0 0 .4 setrgbcolor" # etat de base (simu arrete'e) proc reset {} { .pr configure -state normal catch {destroy .ps} catch {destroy .lrem} } # proc mk_canvas {} { uplevel #0 { set nb_pt [expr ($nb_ptspup*$nb_pup)+1] set tx [expr $echx*($nb_pt-1)]; set toty [expr 3*$offy+$ty+150]; set totx [expr $tx+1]; catch {destroy $c} canvas $c -width $totx -height $toty; pack $c -fill y -expand 1; $c create rectangle 0 0 $totx $toty -fill white -outline white; # limites de la couche turbulente $c create line 0 $offy $totx $offy -fill green -width 2; $c create line 0 [expr $offy+$ty] $totx [expr $offy+$ty] -fill green -width 2; } } mk_canvas; # # Proc do: lance effectivement la simu # proc do {} { uplevel #0 { set stop 0; .pr configure -state disabled set status "Init..."; label .lrem -textvariable status; pack .lrem -padx .5m -pady .5m; button .ps -text Stop -command "set stop 1" pack .ps -padx .5m -pady .5m; update; mk_canvas; # # # # # Generation des bulles # set blist {}; set randr $randrstart; loop i 0 $nb_bulles { set status "Remaining [expr $nb_bulles-$i] bubble to place..."; set j 0; while 1 { set bul [bulle]; lassign $bul x y r v; set b [$c create oval [expr $x-$r] [expr $y-$r] [expr $x+$r] [expr $y+$r] -width 3 -outline pink]; if {$stop} {reset;return;} if {![isin $x $y $r]} break; update $c delete $b; incr j; if {($j>3) && ($randr>5)} {incr randr -1} } if {$v>$v0} {set col red} else {set col blue}; $c itemconfig $b -outline $col; lappend blist $bul; update; } set status "Generating plane wavefront..." update; #puts "working on $nb_pt points"; set ptlist {}; # starting point loop i 0 $nb_pt { lappend ptlist [list [expr $echx*$i] $v0]; } eval $c create line [join $ptlist " "]; # set i 0; # Y du plan des pupilles set yp [expr 3*$offy+$ty]; set status "Propagating WF "; # # de'placement du front d'onde : # while 1 { incr i; set newlist {}; set ymin 9999; foreach pt $ptlist { lassign $pt x y; set ny [expr $y+[getv $x $y]]; if {$ny<$ymin} {set ymin $ny} lappend newlist "$x $ny"; } if {$stop} {reset;return;} set ptlist $newlist; if {$i%$skipy==0} { eval $c create line [join $ptlist " "]; append status "."; update; if {$ymin>=$yp} break; } } #puts "done $i iters"; set status "WF analysis & correction..."; update; # dessine les micro lentilles : set szpup [expr $echx*$nb_ptspup]; set szpup2 [expr $szpup/2]; set cx 0; set dy 6; set yp1 [expr $yp-$dy] set yp2 [expr $yp+$dy] $c create rectangle 0 $yp $totx $toty -fill white -outline white; lassign [lindex $ptlist 0] x0 y0; set mlist {} loop i 0 $nb_pup { $c create oval $cx $yp1 [expr $cx+$szpup] $yp2 -width 2 -outline brown -fill white; $c create line $cx [expr $yp+100] $cx [expr $yp-$offy/2] -fill brown; set cx2 [expr $cx+$szpup2]; set p1 [lindex $ptlist [expr $i*$nb_ptspup]]; set p2 [lindex $ptlist [expr ($i+1)*$nb_ptspup]]; # puts "$p1 $p2"; lassign $p1 x1 y1; lassign $p2 x2 y2; # calcul du miroir segmente' lappend mlist "$x1 [expr ($y1-$y0)/2.]" lappend mlist "$x2 [expr ($y2-$y0)/2.]" # vecteur normal ( $y1-$y2 , $x2-$x1 ) $c create line $cx2 $yp [expr $cx2+.5*($y1-$y2)] [expr $yp+.5*($x2-$x1)]; incr cx $szpup; } $c create line $cx [expr $yp+100] $cx [expr $yp-$offy/2] -fill brown; update lassign [correct $nb_pup $nb_ptspup $ptlist] nptlist ptcorr; set n [eval $c create line [join $mlist " "] -fill black -width 2]; $c move $n 0 [expr $yp+140]; set n [eval $c create polygon [join $mlist " "] $cx $offy 0 $offy -fill orange1]; $c move $n 0 [expr $yp+140]; set n [eval $c create line [join $nptlist " "] -fill darkgreen]; $c move $n 0 [expr $yp+100]; set n [eval $c create line [join $ptcorr " "] -fill gold]; $c move $n 0 [expr $yp+100]; catch {$c create text [expr $totx-20] [expr $toty-5] -font $font -text "(c)DL"} } reset } # en cas d'erreur... #proc tkerror {info} { #reset; #tkerror.tk $info; #} set lscale 20.; set lambda 0.5; # # "corrige" le front d'onde : mirroir segmenté. # et retire un pseudo piston (moyenne des extremitées) de pt source proc correct {nb_pup nb_ptspup ptlist} { set ptlr {}; set ptloc {}; set n0 0; set n1 $nb_ptspup; lassign [lindex $ptlist 0] x0 y0; lassign [lindex $ptlist [expr $nb_pup*$nb_ptspup]] xn yn; set cor [expr ($y0+$yn)/2]; loop i 0 $nb_pup { lassign [lindex $ptlist $n0] x1 y1; lassign [lindex $ptlist $n1] x2 y2; lappend ptlr "$x1 0." lappend ptloc "$x1 [expr $y1-$cor]"; set pente [expr 1.*($y2-$y1)/($x2-$x1)] loop j 1 $nb_ptspup { lassign [lindex $ptlist [expr $n0+$j]] x y; lappend ptlr "$x [expr $y-$y1-($x-$x1)*$pente]" lappend ptloc "$x [expr $y-$cor]"; } incr n0 $nb_ptspup; incr n1 $nb_ptspup; } lappend ptlr "$x2 0."; lappend ptloc "$x2 [expr $y2-$cor]"; list $ptloc $ptlr; }