Having trouble stopping a loop (or loop de loop de loop)

Having trouble stopping a loop (or loop de loop de loop)

Post by mbwelle » Wed, 27 Aug 2008 11:59:21


Hi again everyone,

Here is my rather clunky code (and I know it is rather inefficient):

------------------------------------------------------------------------------------------------------------------------------
while e_t lt 2 do begin
for x=4e003, 20e003, 4e003 do begin
for c=0.006, 0.01, 0.004 do begin
for o=(50*!pi/180), (70*!pi/180), (10*!pi/180) do begin
v= (a*x)
ind_small = where(file[1,*] lt 2*x,count)
if count eq 0 then te_small=0
if count gt 0 then begin
ext_small = file[*,ind_small]
le_small= ext_small[1,*]
te_small = total(le_small^3)
endif

ind_large = where(file[1,*] ge 2*x,count)
if count eq 0 then te_large=0
if count gt 0 then begin
ext_large = file[*,ind_large]
le_large= ext_large[1,*]
te_large = total(le_large)
endif

kns=(sin(o)*cos(o)/v)
knl=(c*cos(o)*x/a/sin(o))

ens= (kns*c/u)*te_small
enl= knl*te_large
e_t= ens+enl
print,x,c,o,e_t
if e_t ge 0.45 && e_t le 0.9 then openw,1,'g:\Mars_tectonics
\IDL_programs\paper_m_data\alba_eflank.txt',
printf,1,x,c,o,e_t,format='(3f9.3)'
close, 1
endfor
endfor
endfor
endwhile
------------------------------------------------------------------------------------------------------------------------------
I have a few issues here that i could use some advice for:

1.) I'm not sure how to start and more importantly, end this loop. I
chose: while e_t lt 2 do begin to start it. The problem is that this
loop will never be greater than 2 so it will never end and it just
keeps repeating values ad nauseum in the output file.

I don't want it repeating but I'm not certain how to start it and stop
it to allow for no repeated values.

2.) for for c=0.006, 0.01, 0.004 do begin, I watch the output, but I
don't see it change.

3.) i must of screwed something up in this segment:
if e_t ge 0.45 && e_t le 0.9 then openw,1,'g:\Mars_tectonics
\IDL_programs\paper_m_data\alba_eflank.txt',
printf,1,x,c,o,e_t,format='(3f9.3)'

because it worked before, but know I keep getting an error about
unable to close 1, or somesuch thing (just switched to compilation
error).

As always, I appreciate any help that you may provide. After all I
wouldn't be asking this question if it weren't for all your help :)

Thanks,
~Matt
 
 
 

Having trouble stopping a loop (or loop de loop de loop)

Post by mankof » Wed, 27 Aug 2008 12:22:57


It isn't inefficient, it is invalid. Loops must have integer
arguments.

-k.

 
 
 

Having trouble stopping a loop (or loop de loop de loop)

Post by David Fann » Wed, 27 Aug 2008 12:40:09


XXXX@XXXXX.COM writes:


Well, I'll leave the technical details to the experts, but I
would make two general comments. First, I would learn to indent
your code so you can read it more easily. (This may be impossible
and still have it show up properly in a post, but I find non-indented
code so obnoxious I refuse to read it, pretty much, on principle.)

And, second, I don't think in 25+ years of computer programming I have
ever used a floating point loop counter. I didn't even know it was
possible. If it *is* possible, then I envision havoc, simply by
virtue of the way floats can (or, more to the point, cannot) be
represented on computers. (I could easily be wrong about this,
but I'm just saying I've never found a reason for it, so I have
never tried it. There must be a significant difference in how
you and I think about loops.)

I think you might have bigger problems in this code then how
to get out of a loop, although I admit that is a bother. :-)

Cheers,

David
--
David Fanning, Ph.D.
Fanning Software Consulting, Inc.
Coyote's Guide to IDL Programming: http://www.yqcomputer.com/
Sepore ma de ni thui. ("Perhaps thou speakest truth.")
 
 
 

Having trouble stopping a loop (or loop de loop de loop)

Post by Chri » Wed, 27 Aug 2008 14:09:31

Looping floats is perfectly legal - try it if you don't believe it.

- change your 'while e_t lt 2' to 'if e_t lt 2'- then it doesn't loop
(FYI, use BREAK to get out of a loop manually)

- open your file right at the beginning (after if e_t), and close it
right at the end. Also, unless you want the file to be overwritten
each time, use openu (open for updating) instead of openw (open new
for writing). Don't test for anything before opening the file, just
test before writing a new row to it

- you are writing 4 values to file, so format needs to be
format='(4f9.4)' (in human terms, that means 4 Floating point numbers
of 9 characters with 4 characters after the decimal point)


-make sure the line where you open your file doesn't spill onto two
lines like it does on this post.

this will hopefully get you started...
 
 
 

Having trouble stopping a loop (or loop de loop de loop)

Post by Spon » Wed, 27 Aug 2008 20:57:55


;;;

; Some sample data
seed = 12L
a = 0.5
u = 1e3
e_t = 1.4
file = randomu(seed, 2, 200) * 1e2

; Open the file at the start as Chris Beaumont suggested
output = 'g:\Mars_tectonics\IDL_programs\paper_m_data\alba_eflank.txt'
openw, lun, /get_lun, output

; Extract the column of data rather than lugging
; around the entire 'file' array. This also
; simplifies indexing in the program
column = file[1,*]

; Use IF rather than WHILE to prevent getting trapped
if e_t lt 2 then begin

; You can vectorise out this loop too,
; but indexing gets messy and it uses
; a LOT of memory on my machine
for n = 1, 5 do begin
x = n*4e3
v = a*x

; You only need one call to WHERE if the
; complement keywords are used
ind_small = where(column lt 2*x, count, $
complement = ind_large, ncomplement = compcount)
if count eq 0 then te_small=0 else begin
le_small = column[ind_small]
te_small = total(le_small^3)
endelse
if compcount eq 0 then te_large=0 else begin
le_large = column[ind_large]
te_large = total(le_large)
endelse

; Vectorisation of inner two FOR loops
o = rebin(50.0*!pi/180.0 + findgen(3) * (10.0*!pi/180.0), 3,2)
c = rebin(transpose([0.06, 0.1]), 3,2)

kns=(sin(o)*cos(o)/v)
knl=(c*cos(o)*x/a/sin(o))

ens= (kns*c/u)*te_small
enl= knl*te_large
; e_t is now a (3*2) array
e_t= ens+enl

; this replaces the simple 'if' statement
; in the original code
ind1 = where(e_t ge 0.45, c1)
ind2 = where(e_t le 0.9, c2)

; Any indices that fulfil our criteria?
if (c1 gt 0) && (c2 gt 0) then begin
ind3 = setintersection(ind1, ind2)
if ind3[0] ge 0 then begin

; If so, write to file
c3 = n_elements(ind3)
; There's got to be a better way of writing
; to file than looping through, but I can't
; get my head around it right now :-)
for i = 0, c3-1 do begin
j = ind3[i]
printf, lun, x, c[j], o[j], e_t[j], format='(4f9.4)'
endfor

endif
endif

endfor
endif

; close the file
free_lun, lun

;;; END

Regards,
Chris
 
 
 

Having trouble stopping a loop (or loop de loop de loop)

Post by Mike » Wed, 27 Aug 2008 23:20:57


Definitely - One way to avoid this representation problem is to use
something like

start = starting value
step = step value
N = number of steps to take
for i = 0L, N-1 do begin
x = start + i*step
;; do stuff with x...
endfor

At least this will keep the loop from misbehaving.

Mike
 
 
 

Having trouble stopping a loop (or loop de loop de loop)

Post by mgallo » Thu, 28 Aug 2008 00:18:39


> endfor

Yep, although I prefer (but I suppose it doesn't matter much since you
are already looping):

start = starting value
step = step value
N = number of steps to take

x = start + findgen(N) * step

for i = 0L, N - 1L do begin
;; do stuff with x[i]
endfor

Mike
www.michaelgalloy.com
Tech-X Corporation
Software Developer II
 
 
 

Having trouble stopping a loop (or loop de loop de loop)

Post by Jean » Thu, 28 Aug 2008 01:46:26

> 1.) I'm not sure how to start and more importantly, end this loop. I

If I understand you right, you want to work with different values of
e_t, but not with the same value twice. In this case, using "if" instead
of "while" will NOT help you, as it will process your code only once, no
matter what is the value of e_t.
So, you can keep your "while" loop, but you must also keep a copy of the
previous e_t value.

e_t_previous = -999 ;(a value you will NEVER get in your code)
e_t = 1.4
...

while e_t lt 2 and e_t_previous ne e_t do ...
e_t_previous= e_t
... ;change e_t
endWhile

Now, with this, you will still have the problem of comparing floats...
which you don't want to. Try
if 0.3+0.6 ne 0.9 then print, 'What??? 0.9 is not 0.9???'
then
print, 0.3+0.6, format = '(F20.10)'
0.9000000358
So basically you would do insteand: e_t - 2 le epsilon, epsilon being
small enough.


Of course it will not.
You INCREASE 0.006, by 0.01, UP to 0.004 ... 0.004<0.006 so this loop is
never executed.


Yes, if e_t does not satisfy this condition, the file will not be
open... but you try to close it after that. You can't close what is not
open.
do a "then begin", end put the "endif" after the "close" statement.


A good way to debug your program is to manually run it (or step by step
if you prefer). Use it with different values and check if it behave as
you have expected. You would have noticed much of the problem in your
code by doing that!

Jean