I'm not familiar with Fortran. And here is a generic interface with some subroutines. gfortran 4.8 complains that:
Ambiguous interfaces 'sortic4' and 'sortic' in generic interface 'sorti' at (1)
INTERFACE SORTI
SUBROUTINE SORTIC( N, IND, TBLC )
INTEGER , INTENT(IN ) :: N
INTEGER , INTENT(INOUT) :: IND( N )
CHARACTER*(*), INTENT(IN ) :: TBLC( * )
END SUBROUTINE SORTIC
SUBROUTINE SORTIC4( N, IND, TBLC )
INTEGER , INTENT(IN ) :: N
INTEGER , INTENT(INOUT) :: IND( N )
CHARACTER*(*), INTENT(IN ) :: TBLC( * )
END SUBROUTINE SORTIC4
SUBROUTINE SORTIC8( N, IND, TBLC )
INTEGER(8) , INTENT(IN ) :: N
INTEGER(8) , INTENT(INOUT) :: IND( N )
CHARACTER*(*), INTENT(IN ) :: TBLC( * )
END SUBROUTINE SORTIC8
SUBROUTINE SORTI1( N, IND, TBL1 )
INTEGER, INTENT(IN ) :: N
INTEGER, INTENT(INOUT) :: IND( N )
INTEGER, INTENT(IN ) :: TBL1( * )
END SUBROUTINE SORTI1
....
END INTERFACE
The code comes from the ioapi3.1 library, m3utilio.f: http://www.baronams.com/products/ioapi/index.html
What is wrong?
You first two subroutines (SORTIC and SORTIC4) have exactly the same types, kinds and dimensions (ranks) of dummy arguments. The TKR resolution thus cannot difference between them, they are ambiguous. They must differ in some of these attributes to be usable in generic interface.
The second and the third one differ in their kinds, this is OK. (Default integer and integer(8), kind 8 is not portable, but is most often distinct from the default one.) The first and the second one are the same.
I looked in the source code of the library. I conclude, that this generic interface does not conform to the Fortran 90 and later standards. Therefore I would start with changing it to a regular interface block just for the explicit interface, i.e., delete the name SORTI after the word interface, and call the individual subroutines directly.
Related
I have a module which defines a Type, with its methods, plus some other Type-unrelated methods as well.
module TypeDef
type, public :: T
...
contains
...
procedure type_proc
end type
...
contains !module
subroutine type_proc( this, ... )
class(T), target :: this
...
call gen_proc( arg_1, arg_n-1, this, arg_n+1 )
...
end subroutine type_proc
...
subroutine gen_proc( arg_1, ..., arg_n-1, tv, arg_n+1 )
! this is a general module routine.
! NOT type related
implicit none
...
class(T), pointer, intent(in) :: tv
...
if ( cond ) tv%member = 0
...
end subroutine gen_proc
end module
At a given point, I call, from a variable type(T), public :: var its member method type_proc(), which at its interior calls a general module procedure gen_proc(). In there, for some conditions, I may need to change some member(s) of the ACTUAL object calling the method's tree (i.e. var). To do so, I pass this as a constant pointer to call gen_proc() to have its address passed at the function call, and access its members.
But, I get the error as described.
Same if I pass it by reference and not as a const pointer.
I cannot see if I do something mistakenly. Here Intel Fortran error #6633: The type of the actual argument differs from the type of the dummy argument there's something similar, but there, the call happens in a different program unit.
EDIT 2:
Ok, this compiled and run as expected..
module test
type, public :: T
real, allocatable :: m1(:)
real, allocatable :: m2(:)
integer :: may_change
contains
procedure :: t_proc
procedure :: all_t
end type
private :: all_t
contains
subroutine t_proc( this, n )
implicit none
class(T), target :: this
integer, intent(in) :: n
call this%all_t( n )
call gen_proc( n, this%m1, this%m2, this )
end subroutine t_proc
subroutine all_t( this, n )
implicit none
class(T) :: this
integer, intent(in) :: n
allocate( this%m1( n ) )
allocate( this%m2( n ) )
end subroutine
subroutine gen_proc( n, m1, m2, Tt )
implicit none
integer, intent(in) :: n
real, intent(in) :: m1(n), m2(n)
class(T), intent(in), pointer :: Tt
if ( .true. ) Tt%may_change = 1
print *, ' may change = ', Tt%may_change
end subroutine gen_proc
end module test
module varmod
use test
type(T), public :: var
end module varmod
program main
use varmod, only: var
implicit none
integer, parameter :: n = 2
var%may_change = 0
call var%t_proc( n )
end program main
So, even more than before, I don't know what could be wrong on the actual code...
I am writing a code with a lot of 2D arrays and manipulation of them. I would like the code to be as concise as possible, for that I would like to use as many 'implicit' operation on array as possible but I don't really know how to write them for 2D arrays.
For axample:
DO J=1,N
DO I=1,M
A(I,J)=B(J)*A(I,J)
ENDDO
ENDDO
become easily:
DO J=1,N
A(:,J)=B(J)*A(:,J)
ENDDO
Is there a way to reduce also the loop J?
Thanks
For brevity and clarity, you could wrap these operations in a derived type. I wrote a minimal example which is not so concise because I need to initialise the objects, but once this initialisation is done, manipulating your arrays becomes very concise and elegant.
I stored in arrays_module.f90 a derived type arrays2d_T which can hold the array coefficients, plus useful information (number of rows and columns). This type contains procedures for initialisation, and the operation you are trying to perform.
module arrays_module
implicit none
integer, parameter :: dp = kind(0.d0) !double precision definition
type :: arrays2d_T
real(kind=dp), allocatable :: dat(:,:)
integer :: nRow, nCol
contains
procedure :: kindOfMultiply => array_kindOfMuliply_vec
procedure :: init => initialize_with_an_allocatable
end type
contains
subroutine initialize_with_an_allocatable(self, source_dat, nRow, nCol)
class(arrays2d_t), intent(inOut) :: self
real(kind=dp), allocatable, intent(in) :: source_dat(:,:)
integer, intent(in) :: nRow, nCol
allocate (self%dat(nRow, nCol), source=source_dat)
self%nRow = nRow
self%nCol = nCol
end subroutine
subroutine array_kindOfMuliply_vec(self, vec)
class(arrays2d_t), intent(inOut) :: self
real(kind=dp), allocatable, intent(in) :: vec(:)
integer :: iRow, jCol
do jCol = 1, self%nCol
do iRow = 1, self%nRow
self%dat(iRow, jCol) = vec(jCol)*self%dat(iRow, jCol)
end do
end do
end subroutine
end module arrays_module
Then, in main.f90, I check the behaviour of this multiplication on a simple example:
program main
use arrays_module
implicit none
type(arrays2d_T) :: A
real(kind=dp), allocatable :: B(:)
! auxilliary variables that are only useful for initialization
real(kind=dp), allocatable :: Aux_array(:,:)
integer :: M = 3
integer :: N = 2
! initialise the 2d array
allocate(Aux_array(M,N))
Aux_array(:,1) = [2._dp, -1.4_dp, 0.3_dp]
Aux_array(:,2) = [4._dp, -3.4_dp, 2.3_dp]
call A%init(aux_array, M, N)
! initialise vector
allocate (B(N))
B = [0.3_dp, -2._dp]
! compute the product
call A%kindOfMultiply(B)
print *, A%dat(:,1)
print *, A%dat(:,2)
end program main
Compilation can be as simple as gfortran -c arrays_module.f90 && gfortran -c main.f90 && gfortran -o main.out main.o arrays_module.o
Once this object-oriented machinery exists, call A%kindOfMultiply(B) is much clearer than a FORALL approach (and much less error prone).
No one has mentioned do concurrent construct here, which has the potential to automatically parallelize and speed up your code,
do concurrent(j=1:n); A(:,j)=B(j)*A(:,j); end do
A one-line solution can be achieved by using FORALL:
FORALL(J=1:N) A(:,J) = B(J)*A(:,J)
Note that FORALL is deprecated in the most recent versions of the standard, but as far as I know, that is the only way you can perform that operation as a single line of code.
My IDE is Visual Studio 2010 with integrated Intel Fortran compiler. The version of compiler is: Intel Parallel Studio XE 2011.
I am not experienced programer in Fortran so I need a little help about using optional argument in public procedure from derived type. This is my example code:
MODULE DERIVED_TYPE
TYPE , PUBLIC :: SOME_TYPE
INTEGER , PRIVATE :: V_INT
CONTAINS
PROCEDURE , PUBLIC :: CALL_V_INT => CALL_DATA_V_INT
PROCEDURE , PUBLIC :: TAKE_V_INT => TAKE_DATA_V_INT
END TYPE SOME_TYPE
PRIVATE :: CALL_DATA_V_INT
PRIVATE :: TAKE_DATA_V_INT
CONTAINS
! PUBLIC PROCEDURES
SUBROUTINE CALL_DATA_V_INT( THIS , IA , IB , IC )
CLASS( SOME_TYPE ) :: THIS
INTEGER , INTENT( IN ) :: IA , IC
INTEGER , INTENT( IN ) , OPTIONAL :: IB
IF( .NOT. PRESENT( IB ) ) THEN
THIS%V_INT = IA + IC
ELSE
THIS%V_INT = IA + IB + IC
END IF
END SUBROUTINE CALL_DATA_V_INT
FUNCTION TAKE_DATA_V_INT ( THIS ) RESULT( RES )
CLASS( SOME_TYPE ) :: THIS
INTEGER :: RES
RES = THIS%V_INT
END FUNCTION TAKE_DATA_V_INT
END MODULE DERIVED_TYPE
PROGRAM OPTIONAL_ARG
USE , NON_INTRINSIC :: DERIVED_TYPE
IMPLICIT NONE
INTEGER :: I
INTEGER , PARAMETER :: N = 3
CLASS( SOME_TYPE ) , POINTER :: P_SOME_TYPE
TYPE( SOME_TYPE ) , DIMENSION( N ) , TARGET :: ARR_V_INT
DO I = 1 , N
P_SOME_TYPE => ARR_V_INT( I )
CALL P_SOME_TYPE%CALL_V_INT( I , 5 )
WRITE( * , * ) P_SOME_TYPE%TAKE_V_INT()
END DO
END PROGRAM OPTIONAL_ARG
At the end of compiling proces i got this kind of message in build window:
Missing actual argument for argument 'ic'
What is wrong with this example?
I also try to move optional argument to latest position in argument list and in that case there is no error message.
Can I get detail explanation for optional argument position in argument list?
You should normally try to put optional arguments at the end of the argument list. What happens when you do call such as
subroutine sub (a, b, c)
real :: a, c
real, optional :: b
...
call sub(1.,2.)
is that the compiler must assume that the 1. is for a and the 2. is for b. Then the argument for c is missing.
Instead one can use named arguments after the missing optional one
call sub(1, c=2.)
So in your case you could do
CALL P_SOME_TYPE%CALL_V_INT( I , IC = 5 )
if you don't want to have the optional IB at the end of the argument list.
I am copying a variable of certain class in another of the same class. The compiler happily compiles this but I am worried that at run time the dynamic types may differ. Do I need to test that the two objects are of the same dynamic type to prevent copying rectangle in a square say or may I trust the compiler? What happens if a rectangle is copied in a square accidentally?
What I am trying to do is the following:
type :: simVars
class(stateVars), dimension(:), allocatable :: svars
integer :: count_
contains
procedure :: init => init_simVars
procedure :: destroy => dest_simVars
procedure :: add => add_to_simVars ! adds an observation to the time series
end type simVars
subroutine init_simVars(this,n)
!--> VERSION 1
class(simVars), intent(inout) :: this
integer, intent(in) :: n
allocate( this%svars(n) )
this%count_ = 0
end subroutine init_simVars
subroutine init_simVars(this,n,sVarsIni)
!--> VERSION 2
class(simVars), intent(inout) :: this
integer, intent(in) :: n
class(stateVars), intent(in) :: sVarsIni
allocate( this%svars(n),source=sVarsIni )
this%count_ = 0
end subroutine init_simVars
subroutine add_to_simvars(this,svars)
class(simVars), intent(inout) :: this
class(stateVars), intent(in) :: svars
this%count_ = this%count_+1
this%svars(this%count_) = svars
end subroutine add_to_simvars
subroutine doSimulation(simHist,sVarsIni)
class(simVars), intent(out) :: simHist
class(stateVars), intent(in) :: sVarsIni
!--> dynamic type 'stateVars1'
class(stateVars), allocatable :: sVars ! will be source allocated from 'iniState'
! initialize the state of the economy
allocate( sVars, source=sVarsIni ) ! "copies" 'sVarsIni' in 'sVars'
! initialize 'simHist'
!--> VERSION 1:
call simHist%init(nYears)
!--> VERSION 2:
call simHist%init(nYears,iniState)
! save today's variables
call simHist%add(sVars)
...
end subroutine doSimulation
Compiler (ifort 14) happily compiles both versions but I strongly suspect that VERSION 1 is wrong. In init_simVars this%svars will be allocated to dynamic type stateVars, in add_to_simvars sVars will have dynamic type stateVars1 and a copy in this%sVars (of type stateVars) will be attempted. I am quite surprised that the compiler compiles this even though it cannot determine the dynamic type of sVars in add_to_simvars. What would happen at run time, a seg fault or what?
VERSION 2 I believe is correct however I am somewhat reluctant to trust the compiler here therefore I am thinking I should ASSERT that this%sVars and sVars have the same dynamic type (ASSERT(SAME_TYPE_AS(this%sVars, sVars) ))? Is this a real concern or am I worried too much?
Another question is what happens when I do allocate( this%svars(n),source=sVarsIni ). I want to allocate the array this%sVars to be of size n and dynamic type sVarsIni. However sVarsIni is a scalar. Will it do what I want?
The difference is in these lines
allocate( this%svars(n) )
vs.
allocate( this%svars(n),source=sVarsIni )
where this%svars is class(svars) allocatable array and svarsIni is an class(stateVars) dummy argument.
That indeed changes a lot.
In the first case, it allocates it to the declared type, which is svars, in the other case it allocates to the dynamic type of the dummy argument, which is at least stateVars.
If you do version 1, it should than fail at add_to_simvars, because the dynamic types won't match.
I don't know if you overloaded the assignment in there or not. If you didn't it shouldn't even compile, because of the intrinsic assignment of polymorphic objects.
I'm binding Fortran code with a C dll, and I would like to have a Fortran array inter-operable with C. I currently have the following subroutine to bind the Fortran array with a C double*:
SUBROUTINE Pack_Inputs( Input , In_X )
TYPE( InputType ) , INTENT(INOUT) :: Input
REAL(KIND=C_DOUBLE) , ALLOCATABLE , TARGET , INTENT(INOUT) :: In_X(:)
IF ( .NOT. ALLOCATED(In_X) ) ALLOCATE( In_X (Input%Xlen) )
DO i = 1,Input%C_obj%Xlen
In_X(i) = Input%X(i)
END DO
Input%C_obj%X = C_LOC(In_X)
END SUBROUTINE Pack_Inputs
However, what I don't like about the current code is that I am constantly allocating memory, and having to unpack the array when the C dll is entered (partly driven by my reluctance to use the SAVE attribute on In_X(:)). I would rather much declare In_X once, inside a Fortran derived type. This leads to the motivation for this post. In this derived type:
USE , INSTRINSIC :: ISO_C_BINDING
TYPE , PUBLIC :: InputType
TYPE(InputType_C) :: C_obj
REAL(KIND=C_DOUBLE) , ALLOCATABLE , TARGET :: In_X(:)
REAL , DIMENSION(:) , ALLOCATABLE :: X
REAL , DIMENSION(:) , ALLOCATABLE :: Y
REAL , DIMENSION(:) , ALLOCATABLE :: Z
INTEGER , DIMENSION(:) , ALLOCATABLE :: index
INTEGER :: Xlen
INTEGER :: Ylen
INTEGER :: Zlen
INTEGER :: indexlen
END TYPE InputType
I get the error:
REAL(KIND=C_DOUBLE) , ALLOCATABLE , TARGET :: In_X(:)
1
Error: Attribute at (1) is not allowed in a TYPE definition
Is there a way to eliminate this error?
I have encountered this problem before, and the solution that worked for me was to to declare the component as POINTER instead of ALLOCATABLE, TARGET. I am not sure whether the Fortran standard does not support it, or this feature is just not implemented by the compilers. I was using ifort v12.0.2.137.
Would this be an acceptable solution for you? You would then be able to use it as pointer target.
TYPE , PUBLIC :: InputType
TYPE(InputType_C) :: C_obj
REAL(KIND=C_DOUBLE),DIMENSION(:),POINTER :: In_X => NULL()
REAL , DIMENSION(:) , ALLOCATABLE :: X
REAL , DIMENSION(:) , ALLOCATABLE :: Y
REAL , DIMENSION(:) , ALLOCATABLE :: Z
INTEGER , DIMENSION(:) , ALLOCATABLE :: index
INTEGER :: Xlen
INTEGER :: Ylen
INTEGER :: Zlen
INTEGER :: indexlen
END TYPE InputType
Then, you can associate the In_X pointer with target data:
In_X(1:Input%C_obj%Xlen) => Input%X(1:Input%C_obj%Xlen)
Note that Input%X will need to have a TARGET attribute as well.