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
|
|
|
|
|