Van Snyder wrote:
> To avoid this problem, some mathematical software routines are organized
> to allow the package to return to the calling program when access to
> user-supplied code is needed. So using a quadrature routine might
> look like the following:
>
> what = 0 ! initial call
> do
> call quadrature ( a, b, x, what, answer, error_estimate )
> select case ( what )
> case ( 1 ) ! done
> exit
> case ( 2 ) ! Need a function value
> answer = my_function(x, spectroscopic_database)
> case ( 3 ) ! some other feature, e.g. intermediate output ....
> end select
> end do
>
> Inside of the routine, there may be several reasons for needing access
> to user-supplied code. In the case of a quadrature routine, one
> certainly needs access to user-supplied code to compute the function
> being integrated at one of the abscissae of the quadrature formula.
> But what if the procedure has a search method to find discontinuities,
> and break the region of integration thereat? The routine is almost
> certainly needing function values in different places for these two
> purposes. Therefore, at the beginning of the routine, there will
> be a selection process that sends control back to the correct place.
> In my own codes, this is usually a computed-GO TO statement. This
> sort of control structure is almost impossible to organize without
> GO TO.
>
Thanks for rasing this issue. I am writing a library to solve non-linear
programming tasks with user supplied objective functions and have been wondering
for the best way to handle the reverse call mechanism.
I do not like the above flow of control a lot. Also, the routines I use will
usually be handled as ELEMENTAL and/or PURE in HPF, so that such alternate entry
points and GO TO's and such make life difficult to debug and maintain,
especially in parallel codes.
Now, I am really interested in seing what people think the best approach is in
Fortran 95. There must be a way to use modules to somehow encapsulate user
defined routines. But of course the provided user module can not be USEd in my
library modules, since these should be compiled beforehand.
My idea of doing this would be the following: having a dummy rouine that only
accepts one argument (like x in case of quadrature) which in turn calls all the
things the user wants. So have something like:
! This module would be compiled separately and the resulting .mod file available
module Convex_Optimization
...
contains
subroutine MinimizeCost(...,CostFunction)
interface
pure function CostFunction(x) result(f)
real, intent(in) :: x
real:: f
end function CostFunction
end interface
....
end subroutine MinimizeCost
end module Convex_Optimization
! Now this module will be written by the user later on, containing all the
things needed
! for calculating the cost function, such as spectroscopic tables and
interpolations etc.
module Cost_Function
....
contains
pure function MyCostFunction(x) result(f)
real, intent(in) :: x
real :: f
...
end function MyCostFunction
...
end module Cost_Function
! Finally, the user would compile the main program, having access to both
previous .mod files
program main_program_
use Convex_Programming
use Cost_Function
...
call MinimizeCost(...,MyCostFunction)
...
end program main_program_
Is there some problem or improvement to this scheme that I am not seeing.
Providing source codes to any of the files or the .mod files is not a problem
for me. I just want to avoid recompiling something too many times for different
cost functions that we want to use. Any literature reference is also
appreciated.
Thanks for the advice,
Aleksandar
--
_____________________________________________
Aleksandar Donev
[log in to unmask]
http://www.pa.msu.edu/~donev/
Department of Physics and Astronomy
Michigan State University
East Lansing, MI 48825
(517) 432-6770
_____________________________________________
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|