fortran

"wrapping" subroutines in Fortran


I am new to Fortran and am curious about how to correctly 'wrap' subroutines.

E.g. suppose I have a main program that calls some subroutine outer, that checks a flag and then calls some other subroutine, inner_1 or inner_2, depending on the value of flag. It passes arguments along to the inner subroutines.

Naively, I can just create a subroutine outer than checks the flag and calls the inner subroutines. But this requires declaring all variables passed to outer just to pass them along to the inner subroutines. For many arguments, this seems cumbersome.

Is this the standard way to accomplish this, or is there some better way that I don't know about?

I wrote a working example:

program main

    use m_mod,  only : outer

    implicit none

    real    :: a = 1.0
    integer :: b = 1
    integer :: flag

    flag = 1
    call outer(a,b,flag)

    flag = 2
    call outer(a,b,flag)

end program main
module m_mod

    implicit none

    private
    public  :: outer

    contains

    subroutine outer(a,b,flag)

        real, intent(in)    :: a
        integer, intent(in) :: b
        integer, intent(in) :: flag

        if (flag == 1) then
            call inner_1(a,b)
        else
            call inner_2(a,b)
        end if

    end subroutine outer

    subroutine inner_1(a,b)

        real, intent(in)    :: a
        integer, intent(in) :: b

        write(*,*) "inner_1-a", a
        write(*,*) "inner_1-b", b

    end subroutine inner_1

    subroutine inner_2(a,b)

        real, intent(in)    :: a
        integer, intent(in) :: b

        write(*,*) "inner_2-a", a
        write(*,*) "inner_2-b", b

    end subroutine inner_2

end module m_mod 

which outputs

 inner_1-a   1.00000000    
 inner_1-b           1
 inner_2-a   1.00000000    
 inner_2-b           1

as expected. I just want to know if there is a better way to do this!


Solution

  • If you want to keep the inner routines independent (i.e. they can be called from other routines than the wrapping one) there's no obvious other solution. Otherwise you may transform them into contained routines, without having to repeat the argument list:

    module m_mod
    
        implicit none
    
        private
        public  :: outer
    
        contains
    
        subroutine outer(a,b,flag)
    
            real, intent(in)    :: a
            integer, intent(in) :: b
            integer, intent(in) :: flag
    
            if (flag == 1) then
                call inner_1()
            else
                call inner_2()
            end if
        
        CONTAINS
            ! a, b, (and flag), are available to the contained routines
            ! thanks to host association
    
            subroutine inner_1()
    
                write(*,*) "inner_1-a", a
                write(*,*) "inner_1-b", b
    
            end subroutine inner_1
    
            subroutine inner_2()
    
                write(*,*) "inner_2-a", a
                write(*,*) "inner_2-b", b
    
            end subroutine inner_2
    
        end subroutine outer
    
    end module m_mod