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

generic module procedure problem

Li_Dong
Beginner
601 Views
Hi all,

I have written a module which I want to add a new subroutine without disturbing the previous one, so I want to wrap them with an interface, say:

[cpp]subroutine file_io_output_1(label, file_name, folder_name, card_name, buf, nd, dims)
    character(*), intent(in) :: label
    character(*), intent(in) :: file_name
    character(*), intent(in) :: folder_name
    character(*), intent(in) :: card_name
    real, intent(in) :: buf(*)
    integer, intent(in) :: nd
    integer, intent(in) :: dims(*)

subroutine file_io_output_2(label, file_name, card_name, buf, nd, dims)
    character(*), intent(in) :: label
    character(*), intent(in) :: file_name
    character(*), intent(in) :: card_name
    real, intent(in) :: buf(*)
    integer, intent(in) :: nd
    integer, intent(in) :: dims(*)

interface file_io_output
    module procedure file_io_output_1
    module procedure file_io_output_2
end interface file_io_output[/cpp]

When I compiled the program, it complained:

error #6285: There is no matching specific subroutine for this generic subroutine call. [FILE_IO_OUTPUT]

It is more strange that I have two program files calling "file_io_output" with the same pattern of arguments (file_io_output_1), the first one is successfully compiled, but the second one failed. What's wrong?

Thank you for help!

DONG Li
0 Kudos
4 Replies
Steven_L_Intel1
Employee
601 Views
Please show the call that fails and the declarations of all its arguments.
0 Kudos
Li_Dong
Beginner
601 Views
Please show the call that fails and the declarations of all its arguments.

Hi Steve,

The calling that passed the compilation is:

[plain]call file_io_output(trim(label), output_file, module_name, &
    "parcel_"//trim(q_name(i)), q(:,i), 1, (/nq/))

character(20) :: label
character(50) :: output_file
character(50) :: module_name
integer :: nq
character(8) :: q_name(nq)
real :: q(np,nq) ! np is another integer variable[/plain]

The calling that failed the compilation is:

[plain]call file_io_output("constant", output_file, folder_name, &
    "mesh_"//trim(x_name(i)), x(:,:,:,i), 3, num_grid)

character(50) :: output_file
character(50) :: folder_name ! identical to module_name previously
character(8) :: x_name(nd) ! nd is an integer variable
integer :: num_grid(3)
real, allocatable :: x(:,:,:,:) ! The actual dimensions are num_grid(1) X num_grid(2) X num_grid(3) X nd [/plain]

Before I added "file_io_output_2", the compilation is ok. So what is the side effect of interface "file_io_output"?

Thank you for help!

DONG Li
0 Kudos
Hirchert__Kurt_W
New Contributor II
601 Views
Quoting - DONG Li
Before I added "file_io_output_2", the compilation is ok. So what is the side effect of interface "file_io_output"?

I assume that before you added file_io_output_2, you weren't using using a generic interface.

When you invoke a specific name, an assumed size argument like buf can be associated with an actual argument of any rank. Thus, you could associate it with that 3-dimensional subsection of x, even though buf is declared 1-dimensional.

Once you were using a generic interface, rank is one of the attributes used to select the appropriate specific routine, so a 3-dimensional actual argument now requires a 3-dimensional dummy argument. Since your generic interface didn't have one of those, you got an error message. (In the example that worked with the generic interface, you were passing a 1-dimensional subsection of q, so ranks matched.)

If you wanted to make this work, you could add to the generic interface another routine (say "file_io_ouput_1_3d") with the same arguments as file_io_ouput_1 except that buf is buf(:,:,:) instead of buf(*). This routine could then directly call the specific file_io_output_1 to actually do the work. (Because this would be a direct call to the specific, instead of a call to the generic, the rank mismatch would again be allowed.)

-Kurt

If you create these additional "glue" routines with assumed-shape buf arguments to match various dimensionalities, you could create versions with no nd or dims arguments, as these can be recreated with an appropriate constant and shape(buf) respecitively.

I believe I read that Fortran 2008 will have a feature that would allow "assumed-rank" arrays, but since the Fortran 2008 draft has not yet been formally adopted, I expect is will be quite some time before such a feature would make its way into ifort.


0 Kudos
Li_Dong
Beginner
601 Views
Quoting - hirchert

I assume that before you added file_io_output_2, you weren't using using a generic interface.

When you invoke a specific name, an assumed size argument like buf can be associated with an actual argument of any rank. Thus, you could associate it with that 3-dimensional subsection of x, even though buf is declared 1-dimensional.

Once you were using a generic interface, rank is one of the attributes used to select the appropriate specific routine, so a 3-dimensional actual argument now requires a 3-dimensional dummy argument. Since your generic interface didn't have one of those, you got an error message. (In the example that worked with the generic interface, you were passing a 1-dimensional subsection of q, so ranks matched.)

If you wanted to make this work, you could add to the generic interface another routine (say "file_io_ouput_1_3d") with the same arguments as file_io_ouput_1 except that buf is buf(:,:,:) instead of buf(*). This routine could then directly call the specific file_io_output_1 to actually do the work. (Because this would be a direct call to the specific, instead of a call to the generic, the rank mismatch would again be allowed.)

-Kurt

If you create these additional "glue" routines with assumed-shape buf arguments to match various dimensionalities, you could create versions with no nd or dims arguments, as these can be recreated with an appropriate constant and shape(buf) respecitively.

I believe I read that Fortran 2008 will have a feature that would allow "assumed-rank" arrays, but since the Fortran 2008 draft has not yet been formally adopted, I expect is will be quite some time before such a feature would make its way into ifort.



Hi hirchert,

Thank you for your detail explanation!

DONG Li
0 Kudos
Reply