Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations gkittelson on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Search for nearest value in .dat file 2

Status
Not open for further replies.

anorky

Technical User
Jun 17, 2009
18
NL
Hi all,

I have a tcl/tk programming error. I have some experience in programming tcl/tk but this is very basic.

My problem is the following:

I have a .dat file with varying entries. In general the file looks as follows:

NACA6409 9%
1.00000 0.00000
0.99732 0.00084
0.98930 0.00333
0.97603 0.00737
0.95760 0.01284
0.93423 0.01954
0.90615 0.02724
0.87357 0.03571
0.83690 0.04464
0.79647 0.05378
0.75272 0.06283
0.70608 0.07153
0.65710 0.07961
0.60627 0.08684
0.55413 0.09302
0.50132 0.09796
0.44840 0.10152
0.39590 0.10360
0.34367 0.10352
0.29315 0.10086
0.24502 0.09584
0.19988 0.08874
0.15830 0.07992
0.12080 0.06982
0.08780 0.05889
0.05968 0.04762
0.03677 0.03646
0.01920 0.02581
0.00720 0.01603
0.00080 0.00737
0.00000 0.00000
0.00467 -0.00573
0.01467 -0.00956
0.02973 -0.01157
0.04970 -0.01192
0.07428 -0.01080
0.10317 -0.00844
0.13607 -0.00513
0.17257 -0.00119
0.21235 0.00307
0.25498 0.00729
0.30012 0.01112
0.34730 0.01425
0.39618 0.01639
0.44707 0.01772
0.49868 0.01871
0.55040 0.01925
0.60167 0.01929
0.65193 0.01880
0.70065 0.01780
0.74728 0.01634
0.79130 0.01451
0.83223 0.01241
0.86957 0.01017
0.90288 0.00791
0.93180 0.00576
0.95593 0.00383
0.97503 0.00221
0.98883 0.00101
0.99722 0.00025
1.00000 0.00000

The first column are the x coordinates, the second are z coordinates of an airfoil.

I would like to know at which line(s) the nearest value of x=0.25 can be found.
So for this input file the result should be the line numbers of x=0.24502 and x=0.25498 since these are the closest values to x=0.25.

I suppose this needs to be done in two steps.
The first step, splitting the first column into two parts.
The second to search for both results.

Does anyone of you guys know how to program this in tcl/tk?

If my problem description is not clear, let me know I'll try to be more specific.

Thanks a lot!!!



 
Hi

anorky said:
So for this input file the result should be the line numbers of x=0.24502 and x=0.25498 since these are the closest values to x=0.25.
That looks like you extracted two values for x, both from the first column. Is that your goal ?

I think the logic would be to get the x from the first column and the z from the second. This is what this script does :
Code:
[b]set[/b] find [purple]0.25[/purple]

[b]set[/b] [b]file[/b] [teal][[/teal][b]open[/b] [green][i]"anorky.dat"[/i][/green][teal]][/teal]
[b]gets[/b] [navy]$file[/navy]

[b]set[/b] devx [teal]-[/teal][purple]1[/purple]
[b]set[/b] devz [teal]-[/teal][purple]1[/purple]

[b]while[/b] [teal]{[/teal][teal]![[/teal][b]eof[/b] [navy]$file[/navy][teal]][/teal][teal]}[/teal] [teal]{[/teal]
  [b]set[/b] line [teal][[/teal][b]gets[/b] [navy]$file[/navy][teal]][/teal]
  [b]if[/b] [teal]{[/teal][navy]$line[/navy][teal]==[/teal][teal]{}}[/teal] [teal]{[/teal] [b]continue[/b] [teal]}[/teal]
  [b]set[/b] pair [teal][[/teal][b]split[/b] [navy]$line[/navy][teal]][/teal]
  lassign [navy]$line[/navy] x z

  [b]if[/b] [teal]{[/teal][navy]$devx[/navy][teal]==-[/teal][purple]1[/purple] [teal]||[/teal] [teal][[/teal][b]expr[/b] [navy]$devx[/navy][teal]>[/teal]abs[teal]([/teal][navy]$x[/navy][teal]-[/teal][navy]$find[/navy][teal])][/teal][teal]}[/teal] [teal]{[/teal]
    [b]set[/b] devx abs[teal]([/teal][navy]$x[/navy][teal]-[/teal][navy]$find[/navy][teal])[/teal]
    [b]set[/b] clox [navy]$x[/navy]
  [teal]}[/teal]
  [b]if[/b] [teal]{[/teal][navy]$devz[/navy][teal]==-[/teal][purple]1[/purple] [teal]||[/teal] [teal][[/teal][b]expr[/b] [navy]$devz[/navy][teal]>[/teal]abs[teal]([/teal][navy]$z[/navy][teal]-[/teal][navy]$find[/navy][teal])][/teal][teal]}[/teal] [teal]{[/teal]
    [b]set[/b] devz abs[teal]([/teal][navy]$z[/navy][teal]-[/teal][navy]$find[/navy][teal])[/teal]
    [b]set[/b] cloz [navy]$z[/navy]
  [teal]}[/teal]
[teal]}[/teal]

[b]close[/b] [navy]$file[/navy]

[b]puts[/b] [green][i]"closest x = $clox / z = $cloz"[/i][/green]


Feherke.
 
Hi Feherke,

Thanks for your quick reply!

Actually I am not at all interested in the values. I want to know at which line numbers these values are found. Could it be that herefore a counter has to be included?
Do you understand what I mean?

Regards
 
I would read the entire file into a list:
Code:
set fid [open <filename> r]
set coords [split [read $fid] \n]
close $fid
Next I would assign a variable big enough to ensure that one of your x-coordinates is closer than that number to .25. Then I'd march through the list using a for loop rather than a foreach loop so as to keep track of indices (note that the index should start at 1 to skip your title line):
Code:
set mindist 100
for {set i 1} {$i<[llength $coords]} {incr i} {
  set testx [lindex [lindex $coords $i] 0]
  set distx [expr {$testx-.25}]
  if {$distx<$mindist} {set mindist $distx; set indx $i}
}

_________________
Bob Rashkin
 
Hi

Code:
[b]set[/b] find [purple]0.25[/purple]

[b]set[/b] [b]file[/b] [teal][[/teal][b]open[/b] [green][i]"anorky.dat"[/i][/green][teal]][/teal]
[b]gets[/b] [navy]$file[/navy]

[b]set[/b] devx [teal]-[/teal][purple]1[/purple]
[b]set[/b] devz [teal]-[/teal][purple]1[/purple]

[b]set[/b] nr [purple]1[/purple]
[b]while[/b] [teal]{[/teal][teal]![[/teal][b]eof[/b] [navy]$file[/navy][teal]][/teal][teal]}[/teal] [teal]{[/teal]
  [b]set[/b] line [teal][[/teal][b]gets[/b] [navy]$file[/navy][teal]][/teal]
  [b]incr[/b] nr

  [b]if[/b] [teal]{[/teal][navy]$line[/navy][teal]==[/teal][teal]{}}[/teal] [teal]{[/teal] [b]continue[/b] [teal]}[/teal]
  [b]set[/b] pair [teal][[/teal][b]split[/b] [navy]$line[/navy][teal]][/teal]
  lassign [navy]$line[/navy] x z

  [b]if[/b] [teal]{[/teal][navy]$devx[/navy][teal]==-[/teal][purple]1[/purple] [teal]||[/teal] [teal][[/teal][b]expr[/b] [navy]$devx[/navy][teal]>[/teal]abs[teal]([/teal][navy]$x[/navy][teal]-[/teal][navy]$find[/navy][teal])][/teal][teal]}[/teal] [teal]{[/teal]
    [b]set[/b] devx abs[teal]([/teal][navy]$x[/navy][teal]-[/teal][navy]$find[/navy][teal])[/teal]
    [b]set[/b] clox [navy]$x[/navy]
    [b]set[/b] linx [navy]$nr[/navy]
  [teal]}[/teal]
  [b]if[/b] [teal]{[/teal][navy]$devz[/navy][teal]==-[/teal][purple]1[/purple] [teal]||[/teal] [teal][[/teal][b]expr[/b] [navy]$devz[/navy][teal]>[/teal]abs[teal]([/teal][navy]$z[/navy][teal]-[/teal][navy]$find[/navy][teal])][/teal][teal]}[/teal] [teal]{[/teal]
    [b]set[/b] devz abs[teal]([/teal][navy]$z[/navy][teal]-[/teal][navy]$find[/navy][teal])[/teal]
    [b]set[/b] cloz [navy]$z[/navy]
    [b]set[/b] linz [navy]$nr[/navy]
  [teal]}[/teal]
[teal]}[/teal]

[b]close[/b] [navy]$file[/navy]

[b]puts[/b] [green][i]"closest x = $clox ( line $linx ) / z = $cloz ( line $linz )"[/i][/green]

Feherke.
 
Hi Feherke,

Could it be there is an error in the "lassign" command?

Actually I am using ICEM CFD to run the tcl code since it is part of my script for the mesh generation.

Apparently this in an invalid command name according to ICEM.

Thanks!
 
Hi Bong,

Thanks for your reply!

I am trying to run your code but I don't understand everything happening.
The $testx is empty when I check it. Is that normal?

Entries x=0.24502 and x=0.25498 can be found on lines 22 and 42 respectively, starting counting from 1.

Ideally I would the result as f.e. result1= 22 and result2=42.

However with the code you provided, the result indx is 31.

Is it possible to end up with result1=22 and result2=42?

Or is going wrong when I run it?

Thanks again,

Regards




 
My mistake. You need to use the absolute value.
set distx [expr {[red]abs[/red]($testx-.25)}]

_________________
Bob Rashkin
 
Hi Bong,

Thanks, this solution works.
However I still only recieve the second result.
I think the solution is to split the first column in 2 parts.
The first one would be starting at the first line and end at the line having the values 0.0000 0.0000.
The second part would be the remainder of the entries.
And run the code you provided for both parts.

Is this correct? Or is there another way to do this?

Is it clear for you what I want to achieve?

thanks again!!!
 
Rather than split the data in two, I'd probably make 2 passes. After the first pass, you can remove the found line (a little complicated) or change the value (using lreplace) so that it isn't found again.

_________________
Bob Rashkin
 
Hi Bong,

So there isn't a way to find the two nearest values to 0.25 in one iteration without replacing the value? I use the input file for making the geometry later on, so I rather don't change any values in it...

Any suggestions for this?

Thanks again, your input is helping me a lot!

 
Hi Guys,

Thanks for the replies and help. I figured it out :)

Regards
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top