Intel® Fortran Compiler
Build applications that can scale for the future with optimized code designed for Intel® Xeon® and compatible processors.

Procedure Pointer

dundar11
Beginner
951 Views
Hi
I have a problem and I guess the correct approach is procedure pointers.
Here is the problem
I have derived type contains a procedure for optimization. Lets say simplexb.
This function gets a set of numbers -- say coeff-- and needs to call a cost function to optimize.
At this point I want to have a freedom to pick cost function at runtime according to settings.
I have declared a pointer procedure with an interface.
[fortran] type , abstract :: parent_optimizer
   real(8) :: tolerance
   contains
   procedure ( opt_solve) , deferred :: optimizer
 end type parent_optimizer
abstract interface 
 function opt_solve(this,coeff) result ( iostat)
 import :: parent_optimizer
 class(parent_optimizer) :: this
 real(8) , dimension (:),intent(inout) :: coeff
 integer :: iostat
 end function
end interface
!--------------------------------------------------- 
 type , extends(parent_optimizer) :: simplexb_opt
  integer :: iteration
   procedure(cost_func), nopass, pointer :: cost
   contains
   procedure  ::   optimizer => simplexb
 end type
!---------------------------------------------------
interface
 function cost_func(coeff) result ( total_cost)
 real(8) , dimension(:) :: coeff
 real(8) :: total_cost
 end function 
end interface[/fortran]
[fortran]
[/fortran]
ifort compiles this part .
To use this setup I have defined another derived type with a procedure with no pass attribute:
[fortran]module fitdriver_module
use opt_simplexb_module
use parameters_module
use structures_module
  type test_cost
   contains
   procedure ,nopass:: test_cost_function
  end type
 contains

 subroutine fitdriver(structure,parset)
 type(structures) :: structure
 type(parameters) :: parset
 class(*) , allocatable :: optimizer
 type(test_cost),target :: tc
   allocate(simplexb_opt :: optimizer)
  optimizer%cost=> tc%test_cost_function


 end subroutine fitdriver
!-----------------------------------------------------------------------------
function test_cost_function(coeff) result (cost)
real(8) , dimension(:) :: coeff
real(8) :: cost
integer :: ndim
integer :: i
ndim=size(coeff)
cost=0.d0
do i=1,ndim
  cost=cost+(-1)**i*sin(coeff(i))
  end do
end function


end module fitdriver_module[/fortran]
When I compile this I receive following errror:
error #6460: This is not a field name that is defined in the encompassing structure. [COST]
optimizer%cost=> tc%test_cost_function
error #6460: This is not a field name that is defined in the encompassing structure. [COST] optimizer%cost=> tc%test_cost_function
The main aim is to be able to choose cost function at runtime. I don't know if there is a better approach?
0 Kudos
5 Replies
Steven_L_Intel1
Employee
951 Views
Your main problem here is in declaring optimizer to be CLASS(*) - as such, the compiler has no idea what fields it contains unless you are within a SELECT TYPE construct. Either use SELECT TYPE or declare optimizer to be type(simplexb_opt). What did you want the CLASS(*) to do for you?
0 Kudos
dundar11
Beginner
951 Views
I will have different optimizer types for different optimizer algorithms but at the driver stage
they all should be same and user will choose one of them with settings file.
Similarly I will have different cost_function objects but all of them will receive a set of number.
In the runtime code will decide which optimizer algorithm will be used and which cost_function object
will be called. My idea was to put a pointer procedure for cost function to the optimizer object and in the runtimeI can point (associate) this procedure with actual cost function.
Is that doable?
Thanks
0 Kudos
Steven_L_Intel1
Employee
951 Views
You can use procedure pointers for this, but the "selection" part will require an approach other than using CLASS(*). The problem is that you want to decide at run-time, based on some external value, which set of routines to use. The usual way of doing this is to have an array of procedure pointers and select one array element based on the requirement. A complication is that Fortran does not have the concept of an array of pointers, so you have to do it as an array of derived types with a pointer component. When the program starts, it fills the array with the possible values.

Perhaps one of the users here will have another approach to recommend.
0 Kudos
dundar11
Beginner
951 Views
My another and possibly more important problem here is to link optimizer%cost to cost_funct%cost
cost_func is a derived type and has a component procedure function called cost.
On the other hand optimizer%cost is a pointer procedure with an abstract interface.
What will be the correct syntax to assign a derived type's pointer component to another derived types component procedure?
0 Kudos
Steven_L_Intel1
Employee
951 Views
I am not sure what you mean by "component procedure". If you mean that cost_func has a procedure pointer component, then you use pointer assignment just as you did in the code you posted.
0 Kudos
Reply