Auto-suggest helps you quickly narrow down your search results by suggesting possible matches as you type.

Showing results for

- Intel Community
- Software Development Tools (Compilers, Debuggers, Profilers & Analyzers)
- Intel® Fortran Compiler
- EXTERNAL subprogram as an argument to a subroutine in the CONTAINS section of a module

- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Mute
- Printer Friendly Page

Highlighted
##

avinashs

New Contributor I

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

06-17-2020
06:02 AM

12 Views

EXTERNAL subprogram as an argument to a subroutine in the CONTAINS section of a module

I have a module that contains an internal subroutine (say S) which has an external function (say F) as a dummy argument. The internal subroutine S is then called by other internal subroutines (S1, S2 etc.) in the module with functions having the same interface as the external argument (F1, F2 etc.). However, this generates an error since the calls to the S cannot "find" F1, F2. Of course, this is a standard practice if the subprograms were not in a module and defined as standalone subprograms in one or more files.

My questions are:

1. Is this an error because it does not conform to the Fortran standard?

2. Is there a way around this?

I am attaching a sample program that explains the situation and generates the error.

As further background ... The reason for using the internal subprogram S in this way is that it was previously a standalone subprogram that I want to simply insert into the module without having to make any modifications.

module test_internal_subroutine_with_external_function implicit none contains subroutine stats(n, x, a, s, func) external :: func ! OK: no compilation error integer :: n real :: a, s, x(n) ! calculates average and standard deviation of ! function values defined by EXTERNAL routine func ! evaluated at the n components of vector x integer :: i real :: f(n) do i = 1,n f(i) = func(x(i)) ! error #6404: This name does not have a type, and must have an explicit type. [FUNC] end do a = sum(f)/n s = sqrt(sum((f - a)**2)/(n - 1)) end subroutine stats function func1(x) result(r) real :: x, r r = sin(x) end function func1 function func2(x) result(r) real :: x, r r = cos(x) end function func2 subroutine evaluate() external :: func1, func2 ! OK: no compilation error integer :: n real :: a1, s1, a2, s2 real, allocatable :: x(:) ! evaluate statistics for two functions n = 100 allocate(x(n)) call random_number(x) call stats(n, x, a1, s1, func1) ! OK: no compilation error call stats(n, x, a2, s2, func2) ! OK: no compilation error print *, 'sin(x)', a1, s1 print *, 'cos(x)', a2, s2 read * deallocate(x) end subroutine evaluate end module test_internal_subroutine_with_external_function

4 Replies

Highlighted
##

Andreas_Z_

Beginner

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

06-17-2020
06:39 AM

12 Views

The error message you show on

On line 8, try: real, external :: func.

Highlighted
##

andrew_4619

Valued Contributor II

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

06-17-2020
07:14 AM

12 Views

if "evaluate" has been told

if "evaluate" has been told to use func1 and func2 that are external. That is fine but they must exist in some other source that is not in a module or you will get a link error for not found.

If you want to use the func1 and func2 that are in the module than these have already been defined fully and are fully visible to evaluate by default. You should not declare them again as the compiler will then ignore the existing local definitions.

Highlighted
##

FortranFan

Valued Contributor III

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

06-17-2020
07:22 AM

12 Views

With your current approach

With your current approach with classic but limited FORTRAN approach with EXTERNAL, you would need to declare the type of the function result e.g., REAL FUNC in your STATS subprogram.

But now that you're using MODULEs and moving away from standalone subprograms, you may want to consider using more modern facilities with explicit interfaces including ABSTRACT ones like so for your code which will give you considerable safety with procedure arguments and type,kind,rank checking, etc.:

module test_internal_subroutine_with_external_function implicit none abstract interface function Ifunc(x) result(r) real :: x, r end function Ifunc end interface contains subroutine stats(n, x, a, s, func) integer :: n real :: a, s, x(n) procedure(Ifunc) :: func ! calculates average and standard deviation of ! function values defined by EXTERNAL routine func ! evaluated at the n components of vector x integer :: i real :: f(n) do i = 1,n f(i) = func(x(i)) ! error #6404: This name does not have a type, and must have an explicit type. [FUNC] end do a = sum(f)/n s = sqrt(sum((f - a)**2)/(n - 1)) end subroutine stats function func1(x) result(r) real :: x, r r = sin(x) end function func1 function func2(x) result(r) real :: x, r r = cos(x) end function func2 subroutine evaluate() procedure(Ifunc) :: func1, func2 integer :: n real :: a1, s1, a2, s2 real, allocatable :: x(:) ! evaluate statistics for two functions n = 100 allocate(x(n)) call random_number(x) call stats(n, x, a1, s1, func1) ! OK: no compilation error call stats(n, x, a2, s2, func2) ! OK: no compilation error print *, 'sin(x)', a1, s1 print *, 'cos(x)', a2, s2 read * deallocate(x) end subroutine evaluate end module test_internal_subroutine_with_external_function

Highlighted
##

Thanks for all the helpful responses. The use of interfaces instead of EXTERNAL statements is the only solution which means that I can reuse the standalone subroutines in the modules only after replacing the EXTERNAL statements with PROCEDURE statements referencing the correct interface blocks. I implemented this approach and it works correctly without any errors.

avinashs

New Contributor I

- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content

06-17-2020
08:36 PM

12 Views

Thanks for all the helpful