Skip to content

User-defined callback routines #117

Open
@ivan-pi

Description

@ivan-pi

Before we dive into the implementation of root-solvers, optimization routines, and quadrature routines (see #87 and #112 ) I think it is worth discussing the "standard" way of defining callback routines (or in other words user-defined functions) which are potentially parametrized by some variables.

Some of the possibilities are described at https://www.fortran90.org/src/best-practices.html#callbacks

The NAG library uses a very low level approach, where the user function carries along both integer and real user workspaces:

Function f(x, iuser, ruser)
Real (Kind=nag_wp)	:: 	f
Integer, Intent (Inout)	:: 	iuser(*)
Real (Kind=nag_wp), Intent (In)	:: 	x
Real (Kind=nag_wp), Intent (Inout)	:: 	ruser(*)

Do we want to support a high level API were the users extend a base class (see related issue #27 ) that carries an evaluate method, as suggested already in the comment by @rweed #87 (comment)?

In the ideal case, the n-D root finding routines, the optimization routines, and quadrature routines could share the same callback interface.

What should we do for routines that require both the function value and its derivative? Should we write multiple functions, as in

real function quad(x)
  real, intent(in) :: x
  quad = 2.0*x**2 + 3.0
end function
real function dquad(x)
  real, intent(in) :: x
  dquad = 4.0*x
end function

or would a subroutine interface `like

subroutine quadd(f,df,x)
  real, intent(in) :: x
  real, intent(out) :: f
  real, intent(out), optional :: df
  f = 2.0*x**2 + 3.0
  if (present(df)) df = 4.0*x
end subroutine

be preferable?

The downside of such a subroutine interface is that it cannot be nested in other expressions.I know that personally, from performance reasons, I sometimes use the second approach, as typically the function and the derivative share some common sub-expressions that can be reused, potentially saving a few CPU operations.

It is of course possible to support several interfaces using "adaptor" routines, but this introduces extra calls, de-referencing issues, and just makes things more complicated.

Metadata

Metadata

Assignees

No one assigned

    Labels

    APIDiscussion on a specific API for a proposal (exploratory)metaRelated to this repository

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions