Is it possible to detect the type of a variable?

@CRquantum ,

  1. You may want to again take note there is no such thing as “a naïve question”! As goes the cliche, there can be “stupid answers”! But no need to worry about making inquiries!

  2. You will note there are significant gaps and limitations when it comes to Generics in current standard Fortran (2018 revision) and the language is limiting in terms of what you can do with the situation you describe in the original post. In the "five features for Fortran 202Y thread by @certik, you will thus note enhanced Generics capability in Fortran being requested in several of the posts.

  3. Your inclination, that has been aided by some of the responses here, has been toward employing polymorphism, unlimited polymorphism even (e.g., CLASS(*) dummy argument), to overcome the limitations with Generics in Fortran. I do not recommend this approach at all for a variety of reasons. But to each their own.

  4. Re: “I feel it is a little bit redundant to define basically the same functions twice,” unfortunately however the only other approach I can suggest with current Fortran which does not involve polymorphism and that alleviates to a small extent at least the issues with code duplication is INCLUDE files.

I agree INCLUDE may not be ideal, but that it is what is there in the language and the concept after all is not all that foreign. It became more prevalent in the 1970s and it has persisted with C-like languages to this day.

So the INCLUDE option is something for you to consider i.e., until around year 2040 or 2045 when your Fortran compiler of choice may implement usable Generics assuming they introduced reasonably well in the next revision (Fortran 202Y).

  • Say you author an include source, scatterv1d.i90:
integer :: i,ierror,scounts_default(iproc),displs_default(iproc) 
   integer, optional :: scounts(iproc),displs(iproc) 
   if (.not.(present(scounts).and.present(displs))) then ! here assume no scounts and no displs.     
     call gather(size(rscatter),scounts_default)
     if (myrank()==0) then
       displs_default(1)=0
       do i=2,iproc
         displs_default(i)=displs_default(i-1)+scounts_default(i-1)
       enddo
     endif    
     call mpi_scatterv(r,scounts_default,displs_default,mpir8,rscatter,size(rscatter),mpir8,0, &
                       mpi_comm_world,ierror)
   else
     call mpi_scatterv(r,scounts,displs,mpir8,rscatter,size(rscatter),mpir8,0, &
                       mpi_comm_world,ierror)     
   endif

   return
  • then author your module as
interface scatterv ! scatterv from process 0 to all process, evenly scatter. inverse of gather
   module procedure scattervi1d   
   module procedure scattervr1d
end interface scatterv
..
subroutine scattervi1d(r,rscatter,scounts,displs)
   integer(kind=i4) :: r(:),rscatter(:)
   include "scatterv1d.i90"
end subroutine scattervi1d  

subroutine scattervr1d(r,rscatter,scounts,displs)  
   real(kind=r8) :: r(:),rscatter(:)
   include "scatterv1d.i90"
end subroutine scattervr1d
1 Like