Function which returns multiple values - fortran

In Fortran, is it possible to define a function which returns multiple values like below?
[a, b] = myfunc(x, y)

That depends... With functions, it is not possible to have two distinct function results. However, you can have an array of length two returned from the function.
function myfunc(x, y)
implicit none
integer, intent(in) :: x,y
integer :: myfunc(2)
myfunc = [ 2*x, 3*y ]
end function
If you need two return values to two distinct variables, use a subroutine instead:
subroutine myfunc(x, y, a, b)
implicit none
integer, intent(in) :: x,y
integer, intent(out):: a,b
a = 2*x
b = 3*y
end subroutine

One possible method is, if you really want to have a single output variable, then you can combine all the outputs of the same data type in an array and return it, although this is not better than the method discussed above.

Related

Procedural pointer in fortran

Let us say I have the following abstract interface to a double precision function of single argument
module abstract
abstract interface
function dp_func (x)
double precision, intent(in) :: x
double precision :: dp_func
end function dp_func
end interface
end module abstract
In a different module I define two functions, a simple one g of the type dp_func and a more complicated one f
module fns
contains
double precision function f(a,b,x)
double precision, intent(in)::a,b,x
f=(a-b)*x
end function f
double precision function g(x)
double precision, intent(in)::x
g=x**2
end function g
end module fns
Now a pointer to g can be created as follows
program main
use abstract,fns
procedure(dp_func), pointer :: p
double precision::x=1.0D0, myA=1.D2, myB=1.D1, y
p => g
y=p(x)
end program main
But how one can create a pointer to f(myA,myB,x), i.e., to f at fixed values of a and b, which can be regarded as a function of just 1 parameter, that is, of the dp_func type?
At the end result I want to be able to write something like
p=>f(myA, myB, )
y=p(x)
Comments below suggest that function closure is not a part of fortran standard and that a wrapper function would be a possible solution to it. However, the wrapper must be initialized and this introduces some chances that end user may forget to call the initializer. How one can do it in a clean and transparent way?
EDIT
After posting this question and googling with "closure and fortran", I found this example
which I present in picture form to emphasize the highlighting. This was presented in an online course. But I doubt such implicit parameter setting is a good programming practice. In fact, dangling variables like z in this example are perfect sources of errors!
You can use internal functions to wrap your functions, e.g.
program main
use abstract
use fns
implicit none
procedure(dp_func), pointer :: p
double precision :: x, myA, myB, y
x = 1.0D0
myA = 1.D2
myB = 1.D1
p => g
y=p(x)
p => f2
y = p(x) ! Calls f(1.D2, 1.D1, x)
myA = 1.D3
myB = 1.D2
y = p(x) ! Calls f(1.D3, 1.D2, x)
contains
double precision function f2(x)
double precision, intent(in) :: x
write(*,*) myA, myB
f2 = f(myA,myB,x)
end function
end program main
An internal function in a given scope can use variables from that scope, so they can act like closures.
The implicit use of myA and myB in the internal function f2 may well be a source of programming error, but, provided the scope of f2 is still in scope, this behaviour is identical to lambda functions in other languages, for example the equivalent python lambda:
f2 = lambda x: f(myA,myB,x)
As pointed out by #vladimirF, once the scope of f2 drops out of scope (e.g. if a pointer to f2 is stored and the procedure where f2 is declared returns) any pointers to f2 will become invalid. This can be seen in this code:
module bad
use abstract
use fns
implicit none
contains
function bad_pointer() result(output)
procedure(dp_func), pointer :: output
double precision :: myA,myB
myA = 1.D2
myB = 1.D1
output => f2
contains
double precision function f2(x)
double precision, intent(in) :: x
write(*,*) myA, myB
f2 = f(myA,myB,x)
end function
end function
end module
program main
use abstract
use fns
use bad
implicit none
procedure(dp_func), pointer :: p
double precision :: y,x
p => bad_pointer()
x = 1.D0
y = p(x)
end program
N.B. the above code may well run fine for this simple case, but it's relying on undefined behaviour so shouldn't be used.
You stated the following:
"...However, the wrapper must be initialized and this introduces some chances that end user may forget to call the initializer. How one can do it in a clean and transparent way?..."
The following might be a solution.
It still needs to be initialized but will throw errors if the user hasn't done so.
I defined a type closure which handles the function pointers.
! file closure.f90
module closure_m
implicit none
type closure
private
procedure(f1), pointer, nopass :: f1ptr => null()
procedure(f3), pointer, nopass :: f3ptr => null()
real :: a, b
contains
generic :: init => closure_init_f1, closure_init_f3
!! this way by calling obj%init one can call either of the two closure_init_fX procedures
procedure :: exec => closure_exec
procedure :: closure_init_f1, closure_init_f3
end type
abstract interface
real function f1(x)
real, intent(in) :: x
end function
real function f3(a, b, x)
real, intent(in) :: a, b, x
end function
end interface
contains
subroutine closure_init_f1(this, f)
class(closure), intent(out) :: this
procedure(f1) :: f
this%f1ptr => f
this%f3ptr => null()
end subroutine
subroutine closure_init_f3(this, f, a, b)
class(closure), intent(out) :: this
procedure(f3) :: f
real, intent(in) :: a, b
this%f1ptr => null()
this%f3ptr => f
this%a = a
this%b = b
end subroutine
real function closure_exec(this, x) result(y)
class(closure), intent(in) :: this
real, intent(in) :: x
if (associated(this%f1ptr)) then
y = this%f1ptr(x)
else if (associated(this%f3ptr)) then
y = this%f3ptr(this%a, this%b, x)
else
error stop "Initialize the object (call init) before computing values (call exec)!"
end if
end function
end module
Concerning the lines class(closure), intent(out) :: this:
This is the standard way of writing initializers for Fortran types.
Note that it is class instead of type which makes this polymorphic as is needed for type-bound procedures.
I slightly adjusted your functions module (changed data types)
! file fns.f90
module fns_m
contains
real function f(a, b, x)
real, intent(in) :: a, b, x
f = (a-b)*x
end function
real function g(x)
real, intent(in) :: x
g = x**2
end function
end module
An example program
! file a.f90
program main
use closure_m
use fns_m
implicit none
type(closure) :: c1, c2
call c1%init(g)
print *, c1%exec(2.0)
call c1%init(f, 1.0, 2.0)
print *, c1%exec(2.0)
call c2%init(f, 1.0, -2.0)
print *, c2%exec(3.0)
end program
Example output
$ gfortran closure.f90 fns.f90 a.f90 && ./a.out
4.00000000
-2.00000000
9.00000000

Calling a subroutine which calls a two-variable function in which one is fixed

I have a main program that can assign values to two variables, x and y. I also have a function subprogram defining, for example, f(x,y) = x*y. I also have a function subprogram that returns the value of the integral of a one-variable function given its delimiters.
I do not want the double integration of f(x,y), I want a simple integration in one of the variables, e.g. y, when I have assigned a fixed value to the other, e.g. x.
So, in the main program, x can have the value 5, and then it calls the function "integral(f, 0, 1)" to integrate f(5,y) = 5*x from y = 0 to y = 1, returning the result as a real variable.
I have these options:
a) create another function defining f(z) = 5*z, and use the integral function to calculate the integral. This is not so good, since I might like to assign another value to x, and this would imply the creation of as many new functions as I might need to attribute a new value to x.
b) I can create a module containing the newer function f(z) sharing the x-value with the main program and the integral function so that I can assign any value to x in the main program, which will be automatically recognized by the function f(z), which in turns will be used as external in the integral function.
c) use the old common statement, that works just like the module in option "b".
My question: Is there any other alternative, maybe a better one?
The option "b" is shown below:
MODULE module_test
IMPLICIT NONE
REAL :: x
CONTAINS
REAL FUNCTION func(z)
REAL :: z, f
func = f(x,z)
END FUNCTION func
END MODULE module_test
PROGRAM main
USE module_test
IMPLICIT NONE
REAL :: y, int_value, integral
x = 5.
int_value = integral(func, 0, 1)
PRINT*, int_value
END PROGRAM main
REAL FUNCTION f(x,y)
IMPLICIT NONE
REAL, INTENT(IN) :: x, y
f = x*y
END FUNCTION f
REAL FUNCTION integral(fun, a, b)
USE module_test
IMPLICIT NONE
REAL, INTENT(IN) :: a, b
REAL, EXTERNAL :: fun
REAL :: t
=== CODE FOR INTEGRATION OF "FUN" FROM "t = a" TO "t = b" HERE ===
END FUNCTION integral

Fortran, passing array using starting index only

In the program below, there are two methods presented for passing an array:
program main
integer, dimension(4) :: x = [9, 8, 7, 6]
call print_x(x(2:3)) ! Method 1
call print_x(x(2)) ! Method 2
end program
subroutine print_x(x)
integer, dimension(2), intent(in) :: x
print *, x
end subroutine
Both methods produce the same result: the numbers 8 and 7 are printed. Personally, I would never code this using Method 2 because it looks like a single value is being passed rather than an array.
Can you give an example of when Method 2 MUST be used instead of Method 1?
Consider the program
implicit none
integer :: x(2,2)=0
call set(x(2,1))
print*, x
contains
subroutine set(y)
integer y(2)
y = [1,2]
end subroutine set
end program
The dummy argument y in this subroutine call is argument associated with the elements x(2,1) and x(1,2). There is no array section of x which consists of exactly these two elements.

Passing additional arguments in Newton’s method in Fortran

I am having trouble in implementing an approach to call Newton's method in a Fortran program.
So I want to use Newton's method to solve an equation following the link
However, my program is slightly different with the example above. In my case, the equation requires some additional information which are produced during runtime.
subroutine solve(f, fp, x0, x, iters, debug)
which means the f is calculated not only based on x, but also a few other variables (but x is the unknown).
I have a solution, which only works for a simple case:
I used a module to include Newton's solver. I also defined a derived data type to hold all the arguments inside the module. It works good now.
My question is: I need to call the Newton's method many times, and each time the arguments are different. How should I design the structure of the modules? Or should I use a different solution?
I provided a simple example below:
module solver
type argu
integer :: m
end type argu
type(argu):: aArgu_test !should I put here?
contains
subroutine solve(f, fp, x0, x, iters, debug)
...
!m is used inside here
end subroutine solve
subroutine set_parameter(m_in)
aArgu%m = m_in
end subroutine set_parameter()
end module solver
And the calling module is:
!only one set of argument, but used many times
module A
use module solver
do i = 1, 4, 1
set_parameter(i)
!call Newtow method
...
enddo
end module A
!can I use an array for argu type if possible?
module B
use module solver
type(argu), dimension(:), allocable :: aArgu ! or should I put here or inside solver module?
end module B
My understanding is that if I put the argu object inside the solver module, then all solver calling will use the same arguments (I can still save all of them inside module A using the above method). In that case, I have to update the arguments during each for loop?
Because the program runs using MPI/OpenMP, I want to make sure there is no overwritten among threads.
Thank you.
There is a common pattern in modern Fortran for the problem you are facing (partial function application). Unlike other languages, Fortran doesn't have function closures, so making a lexical scope for a function is a little "convoluted" and kind of limited.
You should really consider revisiting all the links #VladmirF shared on the comment, most of them apply straightforwardly to your case. I will give you an example of a solution.
This is a solution without using a wrapper type. I will use a feature included in Fortran 2008 standard: passing an internal procedure as an argument. It is compatible with the latest gfortran, Intel and many others.
If you can't access a compiler with this feature or if you prefer a solution with a derived type, you can refer to this answer.
module without_custom_type
use, intrinsic :: iso_fortran_env, only: r8 => real64
use :: solver
contains
subroutine solve_quad(a, b, c, x0, x, iters, debug)
integer, intent(in) :: a, b, c
real(r8), intent(in) :: x0
real(r8), intent(out) :: x
integer, intent(out) :: iters
logical, intent(in) :: debug
call solve(f, fp, x0, x, iters, debug)
contains
real(r8) function f(x)
real(r8),intent(in) :: x
f = a * x * x + b * x + c
end
real(r8) function fp(x)
real(r8),intent(in) :: x
fp = 2 * a * x + b
end
end
end
The rationale of this code is: as f and fp lay inside of the solve_quad procedure, they have access to the arguments a, b and c by host association, without touching those function's signatures. The resulting effect is like changing the arity of the function.
Testing it with gfortran 8.0 and the solver implementation from the link you shared, I got this:
program test
use, intrinsic :: iso_fortran_env, only: r8 => real64
use :: without_custom_type
implicit none
real(r8) :: x, x0
integer :: iters
integer :: a = 1, b = -5, c = 4
x0 = 0
call solve_quad(a, b, c, x0, x, iters, .false.)
print *, x, iters
! output: 1.0000000000000000, 5
x0 = 7
call solve_quad(a, b, c, x0, x, iters, .false.)
print *, x, iters
! output: 4.0000000000000000, 6
end
After discussing with a colleague, I have a solution to my question 2.
If we have only one argument object for the solver module, then all the calling will access the same arguments because they share the same memory space.
To avoid this, we want to pass the argument object as an argument into the solver.
So instead of using the default solver subroutine, we will re-write the Newton's method so it can accept additional argument.
(I used the simplest Newton subroutine earlier because I wanted to keep it untouched.)
In this way, we will define an array of argument objects and pass them during runtime.
Thank you for the comments.

Write array elements based on element type

What I want to accomplish is best explained by an example. In Fortran I have an array a of type mixed that holds a function pointer, an integer variable and a real variable.
type mixed
procedure(), pointer, nopass :: f_ptr
integer :: vi
real :: vr
end type
type(mixed), dimension(10) :: a
The pointer f_ptr should point to an overloaded function that either returns the integer vi or the real vr.
function f_i(i)
implicit none
integer, intent(in) :: i
integer :: f_i
f_i = a(i)%vi
return
end function
function f_r(i)
implicit none
integer, intent(in) :: i
real :: f_r
f_r = a(i)%vr
return
end function
The array is initialized by for example
a(1)%vi = 2
a(1)%f_ptr => f_i
a(2)%vr = 3.14
a(2)%f_ptr => f_r
...
a(10)%vr = 42
a(10)%f_ptr => f_r
In a loop over a variable number of elements then I want to write the array elements vi or vr to an unformatted file via the function that f_ptr is pointing to.
n = 2
write(lununf) (a(j)%f_ptr, j=1,n)
The (readable form) output should be
2 3.14
I tried to implement this but cannot find a solution. Can it be done in some way?