How can I fix the steel moment resisting frame modeling problem in notepad++ (tcl lang. /OpenSEES)? - tcl

I want to model rotational spring for beams in my model in notepad++ (I used tcl lang. in notepad++ editor so I can find lines of errors and open brackets etc., a bit easier) like the picture (MRF) that I add, but without considering RBS. I wrote the code that I paste its lines below but unfortunately, it has an error (warning domain). I did lots of trial and error but I couldn't fix it. Can anyone please help me? (j=floors i=piers)
(because my model is big (10 stories), I want to model it on a programming base)
for {set j 1} {$j <= $nFlrs} {incr j} {
for {set i 1} {$i <= $nBays} {incr i} {
set ID1 [expr 4*1000+($i*10+$j)*10+1]
set nodeR1 [expr ($i*10+$j)*100+5]
set nodeC1 [expr ($i*10+$j)*10+1]
}
for {set i 1} {$i <= $nBays+1} {incr i} {
set ID2 [expr 4*1000+($i*10+$j)*10+2]
set nodeR2 [expr (($i+1)*10+$j)*100+10]
set nodeC2 [expr (($i+1)*10+$j)*10+2]
}
}
uniaxialMaterial Bilin $ID1 $ke $alfah $alfah $my -$my $lambda 0\
0 0 1 0 0 0 $tetap $tetap $tetapc $tetapc 0 0 $tetau $tetau 1 1 $nFactor
uniaxialMaterial Bilin $ID2 $ke $alfah $alfah $my -$my $lambda 0\
0 0 1 0 0 0 $tetap $tetap $tetapc $tetapc 0 0 $tetau $tetau 1 1 $nFactor
# define beam springs
element zeroLength $ID1 $nodeR1 $nodeC1 -mat $ID1 -dir 6
element zeroLength $ID2 $nodeR2 $nodeC2 -mat $ID2 -dir 6
#Constrain the translational DOF with a multi-point constraint
# retained constrained DOF_1 DOF_2 ... DOF_n
equalDOF $nodeR1 $nodeC1 1 2
equalDOF $nodeR2 $nodeC2 1 2
}
incr ID1
incr ID2
warning: WARNING Domain::addElement - In element 4401
no Node 4005 exists in the domain

The big problem you've got is that you are not doing the making of the entities that you'll be simulating in the loops; you loop, but you don't do anything useful with that.
Now, I really don't know OpenSees, but here's a guess as to how you might go about fixing things. Or at least the first step.
for {set j 1} {$j <= $nFlrs} {incr j} {
for {set i 1} {$i <= $nBays} {incr i} {
set ID1 [expr 4*1000+($i*10+$j)*10+1]
set nodeR1 [expr ($i*10+$j)*100+5]
set nodeC1 [expr ($i*10+$j)*10+1]
uniaxialMaterial Bilin $ID1 $ke $alfah $alfah $my -$my $lambda 0\
0 0 1 0 0 0 $tetap $tetap $tetapc $tetapc 0 0 $tetau $tetau 1 1 $nFactor
element zeroLength $ID1 $nodeR1 $nodeC1 -mat $ID1 -dir 6
equalDOF $nodeR1 $nodeC1 1 2
}
for {set i 1} {$i <= $nBays+1} {incr i} {
set ID2 [expr 4*1000+($i*10+$j)*10+2]
set nodeR2 [expr (($i+1)*10+$j)*100+10]
set nodeC2 [expr (($i+1)*10+$j)*10+2]
uniaxialMaterial Bilin $ID2 $ke $alfah $alfah $my -$my $lambda 0\
0 0 1 0 0 0 $tetap $tetap $tetapc $tetapc 0 0 $tetau $tetau 1 1 $nFactor
element zeroLength $ID2 $nodeR2 $nodeC2 -mat $ID2 -dir 6
equalDOF $nodeR2 $nodeC2 1 2
}
}
All I have done here is move code that was after the loops to inside the loops (and deleted a few junk lines). I do not know that what's written now is correct, but it looks much more likely to be so. In particular, the places where the variables are written are next to where they are used, which is probably a good idea.
The next stage of cleaning up this code is to introduce a helper procedure.
# I'm terrible at naming things!
proc makeThing {id nodeR nodeC} {
global ke alfah my lambda tetap tetapc tetau nFactor
uniaxialMaterial Bilin $id $ke $alfah $alfah $my -$my $lambda 0\
0 0 1 0 0 0 $tetap $tetap $tetapc $tetapc 0 0 $tetau $tetau 1 1 $nFactor
element zeroLength $id $nodeR $nodeC -mat $id -dir 6
equalDOF $nodeR $nodeC 1 2
}
for {set j 1} {$j <= $nFlrs} {incr j} {
for {set i 1} {$i <= $nBays} {incr i} {
# I'm also going to put the expressions in braces, for performance
# It gives the expression compiler a chance to do something sensible!
set ID1 [expr { 4*1000+($i*10+$j)*10+1 }]
set nodeR1 [expr { ($i*10+$j)*100+5 }]
set nodeC1 [expr { ($i*10+$j)*10+1 }]
makeThing $ID1 $nodeR1 $nodeC1
}
for {set i 1} {$i <= $nBays+1} {incr i} {
set ID2 [expr { 4*1000+($i*10+$j)*10+2 }]
set nodeR2 [expr { (($i+1)*10+$j)*100+10 }]
set nodeC2 [expr { (($i+1)*10+$j)*10+2 }]
makeThing $ID2 $nodeR2 $nodeC2
}
}
The point of the procedure is that you have one place where you try to do things right (test it until it works) and then you can effectively stamp out all the places where you need that little pattern by just calling the procedure.

Related

how to code inverse of a 3 X 3 matrix in tcl scripting?

I'm finding difficulty in coding for inverse of a 3x3 matrix in tcl. do we really need packages to code for matrix , i need clear explanation for the following parts with minimal simpler coding
1.how to create matrix ?
2.how to find determinant?
3.how to find inverse of it ?
We don't need packages — they're just Tcl code after all — but they do simplify things quite a bit sometimes.
Matrices are represented in Tcl as lists of lists of numbers; it's the natural representation. Think of them being like this (which is row-major form):
set myMatrix {
{ 1.0 -2.0 3.0 }
{-4.0 5.0 -6.0 }
{ 7.0 -8.0 -9.0 }
}
But that can be rewritten like this (it's just a change of whitespace, which isn't significant):
set myMatrix {{1.0 -2.0 3.0} {-4.0 5.0 -6.0} {7.0 -8.0 -9.0}}
The code to invert such a matrix is on the Tcler's Wiki:
puts [Inverse3 $myMatrix]
# {-1.7222222222222223 -0.7777777777777778 -0.05555555555555555} {-1.4444444444444444 -0.5555555555555556 -0.1111111111111111} {-0.05555555555555555 -0.1111111111111111 -0.05555555555555555}
This is the code from the Wiki page, saved here in case the page gets edited away (and using the optimised _Cofactor3).
proc Inverse3 {matrix} {
if {[llength $matrix] != 3 ||
[llength [lindex $matrix 0]] != 3 ||
[llength [lindex $matrix 1]] != 3 ||
[llength [lindex $matrix 2]] != 3} {
error "wrong sized matrix"
}
set inv {{? ? ?} {? ? ?} {? ? ?}}
# Get adjoint matrix : transpose of cofactor matrix
for {set i 0} {$i < 3} {incr i} {
for {set j 0} {$j < 3} {incr j} {
lset inv $i $j [_Cofactor3 $matrix $i $j]
}
}
# Now divide by the determinant
set det [expr {double([lindex $matrix 0 0] * [lindex $inv 0 0]
+ [lindex $matrix 0 1] * [lindex $inv 1 0]
+ [lindex $matrix 0 2] * [lindex $inv 2 0])}]
if {$det == 0} {
error "non-invertable matrix"
}
for {set i 0} {$i < 3} {incr i} {
for {set j 0} {$j < 3} {incr j} {
lset inv $i $j [expr {[lindex $inv $i $j] / $det}]
}
}
return $inv
}
proc _Cofactor3 {matrix i j} {
set COLS {{1 2} {0 2} {0 1}}
lassign [lindex $COLS $j] row1 row2
lassign [lindex $COLS $i] col1 col2
set a [lindex $matrix $row1 $col1]
set b [lindex $matrix $row1 $col2]
set c [lindex $matrix $row2 $col1]
set d [lindex $matrix $row2 $col2]
set det [expr {$a*$d - $b*$c}]
if {($i+$j) & 1} { set det [expr {-$det}]}
return $det
}

How to fix ‘can't read "node_(0)": no such variable’ error in tcl?

I'm setting up a net environment that there are n nodes surrounded by a circle with DSR protocol. However, when I fixed most of the errors, the most confused error that I couldn't solve like the title. How to fix 'can't read "node_(0)": no such variable' error? Didn't I already define it in the for loop at line 86?
I can't find a solution to this problem and when I changed
set node_($i) [$ns node]
to
set node_($i) [$ns_ node]
Here's the full code.
set val(chan) Channel/WirelessChannel
set val(prop) Propagation/TwoRayGround
set val(netif) Phy/WirelessPhy
set val(mac) Mac/802_11
set val(ifq) CMUPriQueue
set val(ll) LL
set val(ant) Antenna/OmniAntenna
set val(ifqlan) 50
set val(nn) 0
set val(rp) DSR
set val(x) 1000
set val(y) 1000
set val(r) 400
proc usage {} \
{
global argv0
puts "\nusage: $argv0 \[-nn node\] \[-r r\] \[-x x\] \[-y y\]\n"
puts "note: \[-nn nodes\] is essential, and the others are optional.\n"
}
proc getval {argc argv} \
{
global val
lappend vallist nn r x y z
for {set i 0} {$i < $argc} {incr i} {
set arg [lindex $argv $i]
if {[string range $arg 0 0] != "-"} continue
set name [string range $arg 1 end]
set val($name) [lindex $argv[expr $i+1]]
}
}
getval $argc $argv
if {$val(nn) == 0} {
usage
exit
}
set ns [new Simulator]
set tracefd [open circle.tr w]
$ns trace-all $tracefd
set namtracefd [open circle.nam w]
$ns namtrace-all-wireless $namtracefd $val(x) $val(y)
proc finish {} \
{
global ns tracefd namtracefd
$ns flush-trace
#close the trace file
close $tracefd
close $namtracefd
#execute nam on the trace file
exec nam circle.nam &
exit 0
}
set topo [new Topography]
$topo load_flatgrid $val(x) $val(y)
create-god $val(nn)
$ns node-config -addressType def\
-adhocRouting $val(rp)\
-llType $val(ll)\
-macType $val(mac)\
-ifqType $val(ifq)\
-ifqLan $val(ifqlan)\
-antType $val(ant)\
-propType $val(prop)\
-phyType $val(netif)\
-channelType $val(chan)\
-topoInstance $topo\
-agenttrace ON\
-routertrace ON\
-mactrace OFF\
-movementtrace OFF
##################################
for {set i 0} {$i < $val(nn)} {incr i} {
set node_($i) [$ns node]
$node_($i) random-motion 0
$node_($i) set X_ [expr $val(r) * cos($i * 2 * 3.14159 / $val(nn))]
$node_($i) set Y_ [expr $val(r) * sin($i * 2 * 3.14159 / $val(nn))]
$node_($i) set Z_ 0
$ns initial_node_pos $node_($i) [expr $val(x) / 10]
}
##################################
set tcp [new Agent/UDP]
$ns attach-agent $node_(0) $tcp
set null [new Agent/Null]
$ns attach-agent $node_([expr $val(nn) / 2]) $null
set cbr [new Application/Traffic/CBR]
$cbr set packetSize_ 5000
$cbr set interval_ 0.05
$cbr attach-agent $tcp
$ns connect $tcp $null
$ns at 0.1 "$cbr start"
$ns at 3.0 "$cbr stop"
$ns at 5.0 "finish"
$ns run
When i type ns circle.tcl -nn 12, I expect the output:
num_node is set 12
warning: Please use -channel as shown in tcl/ex/wireless-mitf.tcl
INITIALIZE THE LIST xListHead
channel.cc:sendUp - Calc highestAntennaZ_and distCST_
SORTING LISTS ...DONE!
Please help me, I've been stuck for a long time.
That error will be produced whenever val(nn) is not greater than zero, as then the loop that creates the nodes:
for {set i 0} {$i < $val(nn)} {incr i} {
set node_($i) [$ns node]
$node_($i) random-motion 0
$node_($i) set X_ [expr $val(r) * cos($i * 2 * 3.14159 / $val(nn))]
$node_($i) set Y_ [expr $val(r) * sin($i * 2 * 3.14159 / $val(nn))]
$node_($i) set Z_ 0
$ns initial_node_pos $node_($i) [expr $val(x) / 10]
}
will simply decide that it has nothing to do and not execute the body of the loop even once. What might cause that? Well, if we look at the argument parsing procedure:
proc getval {argc argv} \
{
global val
lappend vallist nn r x y z
for {set i 0} {$i < $argc} {incr i} {
set arg [lindex $argv $i]
if {[string range $arg 0 0] != "-"} continue
set name [string range $arg 1 end]
set val($name) [lindex $argv[expr $i+1]]
}
}
we can see a number of problems, of which the biggest is this (on the line with set val($name):
lindex $argv[expr $i+1]
The problem here is the lack of a space between $argv and the expression evaluation; that concatenates the two strings before feeding the result into lindex as a single argument! (lindex with a single argument just returns that argument, using the principle of “do nothing, gracefully”.) That's not even syntactically correct in all cases, but probably was in the cases you tried and resulted in val(nn) being set to something like the string -nn 101. Now, the < operator (in the node generation loop) will use ASCII ordering whenever either side looks non-numeric and that string has extra garbage in it so it is definitely non-numeric. Oh dear. (- is ASCII character code 45 and 0 is ASCII character code 48, so - comes before 0.) This isn't what you wanted!
Here's a fixed version of the argument parser:
proc getval {argc argv} {
global val
for {set i 0} {$i < $argc} {incr i} {
set arg [lindex $argv $i]
if {[string index $arg 0] eq "-"} {
set val([string range $arg 1 end]) [lindex $argv [incr i]]
}
}
}
Remember, in Tcl the spaces are important!
Add four lines, and the simulation can be run.
set val(ifqlen) 50 ;# added (Line 7)
set val(nn) 10 ;# added (Line 10)
.
-movementtrace OFF \
-ifqLen $val(ifqlen) ;# added (Line 85)
.
for {set i 0} {$i < [expr $val(nn)]} {incr i} {
set node_($i) [$ns node] ;# added (Line 89)
Reason for set val(nn) 10 : I didn't get the [$argv]'s to work. ( $ ns file.tcl -nn 10 or $ ns file.tcl nn 10 )
Link to the edited file : https://www.dropbox.com/s/m7zsnga6wf29r95/2Ezio-Auditore-DSR.tcl?dl=0
All ~3500 ns2 simulations ex https://drive.google.com/drive/folders/0B7S255p3kFXNSmRYb2lGcDRUdWs?usp=sharing
EDIT : The 'argument parser' by #Donal Fellows was added, can now run with $ ns file.tcl -nn 12. New example https://www.dropbox.com/s/br6qaeg5kj73k14/4-circle-Ezio-Auditore.tar.gz?dl=0
ns2 analyzing scripts https://drive.google.com/drive/folders/1rU_MFAEl1GCLMTJPLR3zbxPxkQQHkQ7T?usp=sharing

Reference Arrays and Variables after proc tcl

I am in the process of creating a wireless sensor network using NS2. 20 Wireless Nodes are distributed randomly across an x-y plane, and using a distance calculation, the neighbors are found (the ones that a broadcast can reach). From the neighbors, I create clusters for each node starting with Node 0.
For example, starting with Node 0 as clusterhead, we would get an output like:
Cluster for Node 0 contains:
1
3
8
From there, move to the next node NOT contained in there so:
Cluster for Node 2 contains:
5
6
7
Using lists in TCL, I am having trouble referencing the cluster array changed in the proc neighbors. I am able to add elements to the list for Node 0 cluster. However, I can only do it inside the process and the loops create a 'reprinting' issue. I have tried different combinations of global cluster and upvar. How do I reference my cluster list AFTER the process?
Below is my current code with the output and reprint issue (the neighbors are correct, I am able to verify that in the simulator).
set cluster {}
set bool 0
proc neighbors {n1 n2 nd1 nd2} {
global bool cluster
set x1 [expr int([$n1 set X_])]
set y1 [expr int([$n1 set Y_])]
set x2 [expr int([$n2 set X_])]
set y2 [expr int([$n2 set Y_])]
set d [expr int(sqrt(pow(($x2-$x1),2)+pow(($y2-$y1),2)))]
if {$d<40} {
if {$nd1!=$nd2} {
set bool 1
if {$bool ==1} {
puts "$nd1 AND $nd2"
if {$nd1 == 0} {
lappend cluster $nd2
}
}
}
}
for {set i 0} {$i < [llength $::cluster]} {incr i} {
puts "${i}=[lindex $::cluster $i]"
}
}
for {set i 0} {$i < $val(nn)} {incr i} {
for {set j 0} {$j < $val(nn)} {incr j} {
$ns at 0.0 "neighbors $node($i) $node($j) $i $j"
}
}
Small section of Output (it repeats for every nd1 and nd2 combo) - For Node 0, the the 0-7 identifier is referencing the correct neighbor.
0 AND 19
0=2
1=4
2=5
3=6
4=10
5=13
6=15
7=19
0=2
1=4
2=5
3=6
4=10
5=13
6=15
7=19
0=2
1=4
2=5
3=6
4=10
5=13
6=15
7=19
Now, if I move the cluster index OUTSIDE the proc. I get no output referring to the cluster list.
set cluster {}
set bool 0
proc neighbors {n1 n2 nd1 nd2} {
global bool cluster
set x1 [expr int([$n1 set X_])]
set y1 [expr int([$n1 set Y_])]
set x2 [expr int([$n2 set X_])]
set y2 [expr int([$n2 set Y_])]
set d [expr int(sqrt(pow(($x2-$x1),2)+pow(($y2-$y1),2)))]
if {$d<40 && $nd1!=$nd2} {
puts "$nd1 AND $nd2"
if {$nd1 == 0} {
lappend cluster $nd2
}
}
}
for {set i 0} {$i < $val(nn)} {incr i} {
for {set j 0} {$j < $val(nn)} {incr j} {
puts "$i, $j"
$ns at 0.0 "neighbors $node($i) $node($j) $i $j"
}
}
for {set i 0} {$i < [llength $::cluster]} {incr i} {
puts "${i}=[lindex $::cluster $i]"
}
Output (just for Node 0):
0, 0
0, 1
0, 2
0, 3
...
0 AND 4
0 AND 6
0 AND 8
0 AND 9
0 AND 11
0 AND 12
0 AND 15
0 AND 16
0 AND 19
Although I would expect/want something like
...
0 AND 15
Cluster for Node 0:
0=8
1=12
2=15
How do I reference this array/list properly? Also, I feel like I will need to use the bool == 1 later as well. In simple tests, I cannot reference it's change outside the proc as well.
Thank you
I figured out the solution. The I THINK the problems lies in the fact that the simulator must run all process in the code - not the actual TCL compiler. Either way, adding a new proc printCluster gives you a single output of your cluster along with the neighbors.
set ::cluster {}
set bool 0
proc neighbors {n1 n2 nd1 nd2} {
global bool ::cluster {}
set x1 [expr int([$n1 set X_])]
set y1 [expr int([$n1 set Y_])]
set x2 [expr int([$n2 set X_])]
set y2 [expr int([$n2 set Y_])]
set d [expr int(sqrt(pow(($x2-$x1),2)+pow(($y2-$y1),2)))]
if {$d<40 && $nd1!=$nd2} {
puts "$nd1 AND $nd2"
if {$nd1 == 0} {
lappend ::cluster $nd2
}
}
proc printCluster {} {
puts "Node 0 Cluster:"
for {set i 0} {$i < [llength $::cluster]} {incr i} {
puts "[lindex $::cluster $i]"
}
}
}
for {set i 0} {$i < $val(nn)} {incr i} {
for {set j 0} {$j < $val(nn)} {incr j} {
$ns at 0.0 "neighbors $node($i) $node($j) $i $j"
}
}
$ns at 0.0 "printCluster"
Output:
...
Node 0 Cluster:
1
2
6
15
18

How to extract the required lines from a file using TCL?

My file looks like this below. I want to extract only id, pos and type from file so that I can use it further. Should I need to treat this data as a list and use lindex syntax to retrieve.
{particles {id pos type v f}
{0 442.3601602032813 775.8494355067412 339.7428247245854 0 -1.0649468656691174 0.3118359585805807 0.7974629587243917 -7.856415738784473 120.82920096524781 80.7680149353967}
{1 75.78431491144367 187.28007812237516 279.3569202413006 0 0.3317344469183915 3.0716559473604916 -1.679965732986453 2.573367640795655 -11.46026754809828 125.75306472245369}
{2 44.167251258358164 371.8839725825084 80.32709197838003 0 -0.6260768510694417 0.9493261445672099 0.9445444874655268 -98.8132600015945 -80.10617403827258 43.578514821777155}
{3 289.0168944249348 193.4364952458922 96.30251497465443 0 -0.5327035586676473 1.028492567403681 4.364969924730662 139.09290151549465 75.46717320097427 -29.955066397359094}
{4 324.94257366360085 404.9215380451672 799.3481016151578 0 -1.2801842708841038 -4.320355658821216 2.9394195915181567 -109.72971491904342 -44.06068452005151 118.2802261191011}
{5 598.4521733790556 447.74320547029174 750.4399422142899 0 1.740414834859398 -0.5926143788565617 1.5937397085063156 -155.08309023301794 186.08101953841978 177.1804659692657}
}
This is the code I have used below. Can anyone tel me the code which I used is correct or not.
set num_part 6
set mol1 0.1666
set mol2 0.8333
set num_conf 2
for {set i 0} {$i < $num_conf} {incr i} {
set f [open "config_$i" "r"]
set part [while { [blockfile $f read auto] != "eof" } {} ]
set g [open "positions" "w"]
blockfile $g write particles {id pos type}
close $f
close $g
set g [open "positions" "r"]
set data [read $g]
close $g
set num0 0
for {set j 0} {$j < [expr { $num_part + 1 }]} {incr j} {
set type [lindex $data 0 $j 4]
if { $type == 0 } {
set tlist [expr $i]
set x0 [lindex $data 0 $j 1]
set y0 [lindex $data 0 $j 2]
set z0 [lindex $data 0 $j 3]
set total1 [ expr { sqrt(($x0 * $x0) + ($y0 * $y0)+ ($z0 * $z0)) }]+0]
incr num0
puts " $i :: $num0 "
set dum 0
for {set k 0} {$k < [expr { $num_part + 1 }]} {incr k} {
set type [lindex $data 0 $k 4]
if { $type == 1 } {
set tlist [expr $i]
set x1 [lindex $data 0 $k 1]
set y1 [lindex $data 0 $k 2]
set z1 [lindex $data 0 $k 3]
set total2 [ expr { sqrt(($x1 * $x1) + ($y1 * $y1)+ ($z1 * $z1)) }]+0]
incr dum
puts " $i :: $dum "
}
}
}
}
}
set h [open "dist12" "w"]
set dist12 [ expr {($mol1 * $total1)-($mol2 * $total2)}]
puts "Distance between cross particles $dist12"
puts $h "\# t $dist12 "
foreach t $tlist dist" $dist12 { puts $h "$t $dist_12" }
close $h
You've a few lines that look suspicious.
1:
set part [while { [blockfile $f read auto] != "eof" } {} ]
The result of while is an empty string, so the above code probably isn't doing what you hope. Not quite sure how to fix it though; blockfile isn't a standard Tcl command.
2:
for {set j 0} {$j < [expr { $num_part + 1 }]} {incr j} {
Not really a correctness issue, but that could be written as:
for {set j 0} {$j < $num_part + 1} {incr j} {
The bytecode generated will be virtually identical, but it's shorter and easier to read.
3:
set tlist [expr $i]
This looks unnecessary and suspcious. We know i is a numeric variable (in fact it contains an integer), so there's no need to pretend it is an expression. It slows things down for no benefit.
You've two occurrences of this.
4:
set total1 [ expr { sqrt(($x0 * $x0) + ($y0 * $y0)+ ($z0 * $z0)) }]+0]
This line is definitely wrong. The number of ] characters doesn't match the number of [ characters, so what you get will be “unexpected”, and that +0 is either useless or harmful. It's probably best to write a procedure to help you with this. Put the procedure at the top of the script.
proc length {x y z} {
expr { sqrt($x*$x + $y*$y + $z*$z) }
}
Then just call it later on:
set total1 [length $x0 $y0 $z0]
The same applies to the calculation of total2 later.
5:
foreach t $tlist dist" $dist12 { puts $h "$t $dist_12" }
Looks like this has a typo: dist" instead of dist. The failure to use dist inside the loop also looks odd; I think you're going wrong here, and should take another look and think about what you actually want to do.

Any filter we can use in tcl script?

I have a question about the for loop,
for {{set loop 0} {$loop < 100} {incr loop}} {
#do someting here
}
loop goes from 0 to 99, and I do something for each value of loop, but if the loop is 3, I will skip it, so, is there any filter in tcl to achieve it or we should write it as:
for {{set loop 0} {$loop < 100} {incr loop}} {
if {loop != 3} {
#do someting here
}
}
You can use the "continue" command. For example:
for {set loop 0} {$loop < 100} {incr loop} {
if {$loop == 3} continue
# do something here
}
% proc xiter {varName "over" a z "excluding" filter body} {
upvar 1 $varName i
set excl [lsort $filter]
for {set i $a} {$i < $z} {incr i} {
if {[lsearch -exact -sorted $excl $i] < 0} {
uplevel 1 $body
}
}
}
% xiter loop over 0 10 excluding {5 3 8} {
puts $loop
}
0
1
2
4
6
7
9
The first, third and fourth arguments to for can be arbitrary scripts, so you could do this:
for {set i 0} {$i < 100} {incr i [expr {$i == 2 ? 2 : 1}]} {
do stuff with $i ...
}