-
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!
-
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.
-
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. -
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