For Programmers: Free Programming Magazines  


Home > Archive > Fortran > March 2008 > Re: Global Data is not Evil (Was: A modern way to solve the "callback









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author Re: Global Data is not Evil (Was: A modern way to solve the "callback
Henrik Holst

2008-03-18, 10:19 pm

On Mar 18, 5:42 pm, "Craig Dedo" <cd...@wi.rr.com> wrote:
> "Henrik Holst" <henrikhols...@gmail.com> wrote in message
>
> news:0762ae68-b666-4ccc-8a95-809d088a0241@b64g2000hsa.googlegroups.com...
>
>
>
>
>
> <snip>
>
>
>
> <snip example>
>
>
>
> <snip #1>
>
>
> <snip #3 - #5>
>
>
> Other posters have suggested a number of ways to solve your problem. I
> would like to address a common misconception.
>
> I would like you to take another look at the issue of the use of global
> data, using an open mind. Global data is not evil. Using global data is
> neutral; it is neither inherently good nor inherently evil.
>
> There are several legitimate reasons to use global data. The most obvious
> is when the data is conceptually a property of the whole program. If this is
> the case, you should use global data and not try to hide the use of global data
> through various subterfuges.
>
> One of the most balanced treatments on the use of global data I have read is
> section 13.3 (pp. 335-343) of Steve McConnell's Code Complete: A Practical
> Handbook of Software Construction, 2nd ed. (ISBN 0-7356-1967-0). This section
> covers the dangers of global data, reasons to use global data, and ways to
> safely use global data.
>
> In Fortran, one of the best ways to use global data is to put it into a
> module that is used in the main program and in all of the procedures where you
> need to use the global data. It also helps to use access procedures to obtain
> values and change the values.


Thats where I am now.

My solution (today) is based on global data in a module.

-

On a unrelated topic - what a good "burn" I got today from my old
friend: assumption.

Let me describe my test case, which did not work:

I started with a "integration routine" in a module:

MODULE ODEFUNC_LIB
REAL :: VE, G, L
CONTAINS
FUNCTION ODEFUNC(T,U) RESULT(Y)
IMPLICIT NONE
REAL, INTENT(IN) :: T, U(2)
REAL Y(2)
REAL, PARAMETER :: PI = 3.141592653589793
REAL :: THETA, OMEGA

THETA = U(1)
OMEGA = U(2)
Y(1) = OMEGA
Y(2) = (1.0/L)*(G + (1.0/VE)*SIN(2.0*PI*T/VE))*SIN(THETA)
END FUNCTION ODEFUNC
END MODULE ODEFUNC_LIB

And my RK11 routine which I was using to solve this ODE:

SUBROUTINE RK11(X, Y, F, H)
INTERFACE
FUNCTION F(X, Y)
USE ODE_LIB_KINDS
REAL(WP), INTENT(IN) :: X, Y(:)
REAL(WP) :: F(SIZE(Y))
END FUNCTION
END INTERFACE
REAL(WP), INTENT(INOUT) :: X, Y(:), H
REAL(WP) :: K(SIZE(Y),1)

K(:,1) = H*F(X, Y)
Y = Y + K(:,1)
X = X + H
END SUBROUTINE RK11

Now here is the burn: ODEFUNC is not compatible with RK11. The X and
Y parameters will be destroyed in the callback!

Instead I had to do this:

MODULE ODEFUNC_LIB_FIXED
REAL :: VE, G, L
CONTAINS
FUNCTION ODEFUNC(T,U) RESULT(Y)
IMPLICIT NONE
REAL, INTENT(IN) :: T, U(:)
REAL Y(SIZE(U))
REAL, PARAMETER :: PI = 3.141592653589793
REAL :: THETA, OMEGA

THETA = U(1)
OMEGA = U(2)
Y(1) = OMEGA
Y(2) = (1.0/L)*(G + (1.0/VE)*SIN(2.0*PI*T/VE))*SIN(THETA)
END FUNCTION ODEFUNC
END MODULE ODEFUNC_LIB_FIXED

And then the parameter passing worked as I hoped. (In the usual
fashion
this makes me very "displeased" with things.)

Since this was so very unexpected (but seems standard: both g95 and
Intel "screwed me") so I am thinking that this too should be done in
another way? Pointers or what else? Remembering to use (:) notation
is just too risky business and failure to do so is hard to detect.

(Recap, for those just joining this thread:
Callback routines and Fortran = bad, mkay? :-))

--
Henrik Holst, Sweden
http://www.nada.kth.se/~holst/contact.shtml

Gary Scott

2008-03-18, 10:19 pm

Henrik Holst wrote:
> On Mar 18, 5:42 pm, "Craig Dedo" <cd...@wi.rr.com> wrote:
>
>
>
> Thats where I am now.
>
> My solution (today) is based on global data in a module.
>
> -
>
> On a unrelated topic - what a good "burn" I got today from my old
> friend: assumption.
>
> Let me describe my test case, which did not work:
>
> I started with a "integration routine" in a module:
>
> MODULE ODEFUNC_LIB
> REAL :: VE, G, L
> CONTAINS
> FUNCTION ODEFUNC(T,U) RESULT(Y)
> IMPLICIT NONE
> REAL, INTENT(IN) :: T, U(2)
> REAL Y(2)
> REAL, PARAMETER :: PI = 3.141592653589793
> REAL :: THETA, OMEGA
>
> THETA = U(1)
> OMEGA = U(2)
> Y(1) = OMEGA
> Y(2) = (1.0/L)*(G + (1.0/VE)*SIN(2.0*PI*T/VE))*SIN(THETA)
> END FUNCTION ODEFUNC
> END MODULE ODEFUNC_LIB
>
> And my RK11 routine which I was using to solve this ODE:
>
> SUBROUTINE RK11(X, Y, F, H)
> INTERFACE
> FUNCTION F(X, Y)
> USE ODE_LIB_KINDS
> REAL(WP), INTENT(IN) :: X, Y(:)
> REAL(WP) :: F(SIZE(Y))
> END FUNCTION
> END INTERFACE
> REAL(WP), INTENT(INOUT) :: X, Y(:), H
> REAL(WP) :: K(SIZE(Y),1)
>
> K(:,1) = H*F(X, Y)
> Y = Y + K(:,1)
> X = X + H
> END SUBROUTINE RK11
>
> Now here is the burn: ODEFUNC is not compatible with RK11. The X and
> Y parameters will be destroyed in the callback!
>
> Instead I had to do this:
>
> MODULE ODEFUNC_LIB_FIXED
> REAL :: VE, G, L
> CONTAINS
> FUNCTION ODEFUNC(T,U) RESULT(Y)
> IMPLICIT NONE
> REAL, INTENT(IN) :: T, U(:)
> REAL Y(SIZE(U))
> REAL, PARAMETER :: PI = 3.141592653589793
> REAL :: THETA, OMEGA
>
> THETA = U(1)
> OMEGA = U(2)
> Y(1) = OMEGA
> Y(2) = (1.0/L)*(G + (1.0/VE)*SIN(2.0*PI*T/VE))*SIN(THETA)
> END FUNCTION ODEFUNC
> END MODULE ODEFUNC_LIB_FIXED
>
> And then the parameter passing worked as I hoped. (In the usual
> fashion
> this makes me very "displeased" with things.)
>
> Since this was so very unexpected (but seems standard: both g95 and
> Intel "screwed me") so I am thinking that this too should be done in
> another way? Pointers or what else? Remembering to use (:) notation
> is just too risky business and failure to do so is hard to detect.
>
> (Recap, for those just joining this thread:
> Callback routines and Fortran = bad, mkay? :-))


It seems no worse to me than callback routines in any language. It's
just a fundamentally bad way to program. The thing I hate most about
Win32 is the horrid callback design.

>
> --
> Henrik Holst, Sweden
> http://www.nada.kth.se/~holst/contact.shtml
>



--

Gary Scott
mailto:garylscott@sbcglobal dot net

Fortran Library: http://www.fortranlib.com

Support the Original G95 Project: http://www.g95.org
-OR-
Support the GNU GFortran Project: http://gcc.gnu.org/fortran/index.html

If you want to do the impossible, don't hire an expert because he knows
it can't be done.

-- Henry Ford
Jan Vorbrüggen

2008-03-26, 8:15 am

> FUNCTION ODEFUNC(T,U) RESULT(Y)
> IMPLICIT NONE
> REAL, INTENT(IN) :: T, U(2)
> REAL Y(2)
>
> And my RK11 routine which I was using to solve this ODE:
>
> FUNCTION F(X, Y)
> USE ODE_LIB_KINDS
> REAL(WP), INTENT(IN) :: X, Y(:)
> REAL(WP) :: F(SIZE(Y))
> END FUNCTION
>
> Now here is the burn: ODEFUNC is not compatible with RK11. The X and
> Y parameters will be destroyed in the callback!


What else did you expect? You lied to the compiler about the actual
interface: in one case you are passing an explicit-length array and
returning such, in the other case an assumed-length one.

If, in the interface definition, you had used Y(*), all should be well.

Jan
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com