Hi.
I have a piece of code that has several libraries sharing a common code base. The libraries are compiled from this common base plus their own bits of unique code.
One piece of data that all the libraries share is a "Phase Type", a derived type containing several common pieces of data. However each library needs to extend this out for their own extra data. We'd created the datatype to hold another extendable datatype that could hold this extra information. The idea was that the other libraries would contain code that would extend the type and set the data themselves. The set routines would also call teh base routines in the common code to set the common variables.
BUT. passing the extended type back into the common code is poving tricker than we hoped.
The problem seems to be that we can't pass the extended type back to the base routine that expects the original abstract base type.
Here's an example of what we're trying, with the compiler output below that. Does anyone have any suggestions on how to get this working please? (or alternatives that would acieve the same thing
Cheers.
Duncan
!------------------------------------
module phase_mod
implicit none
save
type, abstract :: PHASEINFO_TYPE
integer(kind=4) :: TYPE_ID
end type PHASEINFO_TYPE
type :: Phase_tp
integer(kind=4) :: nghosts
class (PHASEINFO_TYPE), pointer :: phaseinfo => null()
end type Phase_tp
! This bit is unique to one of the libraries
type, extends(PHASEINFO_TYPE) :: Ext_Phase_tp
integer(kind=4) :: keySetID ! KeySet associated with this
integer(kind=4) :: ghostsMin ! Default Ghost layer range
integer(kind=4) :: ghostsMax ! Default Ghost layer range
end type Ext_Phase_tp
type(Phase_tp), target :: iPhase
type(Ext_Phase_tp), pointer :: PhaseInfo=>null()
contains
! sets up a base Phase type. Calling program must pass in the phaseinfo type
integer function addBasePhase(nghosts, aPhaseInfo)
integer, intent(in) :: nghosts
class (PHASEINFO_TYPE), pointer, optional :: aPhaseInfo ! intent(in)
iPhase%nghosts = nghosts
iPhase%phaseinfo => aPhaseInfo
addBasePhase = 0
return
end function addBasePhase
! The unique library will call this routine to set up the phase info type and pass it back
integer function addPhase(nghosts, keysetid, gmin, gmax)
integer, intent(in) :: nghosts
integer, intent(in) :: keysetid
integer, intent(in) :: gmin
integer, intent(in) :: gmax
integer :: irc
allocate(PhaseInfo)
PhaseInfo%KeysetID = keysetid
PhaseInfo%ghostsMin = gmin
PhaseInfo%ghostsMax = gmax
! Two ways we tried this bit:
irc=addBasePhase(nghosts,PhaseInfo)
! irc=addBasePhase(nghosts,PhaseInfo%PHASEINFO_TYPE)
addPhase = 0
return
end function addPhase
! Trying to see if what we had worked!
integer function getPhase(phase, phaseInfo)
type(Phase_tp), pointer :: phase
type(Ext_Phase_tp), pointer :: phaseInfo
phase => iPhase
select type (p=>iPhase%phaseinfo)
type is (Ext_Phase_tp)
print*,"Type found!"
phaseInfo=>p
class is (PHASEINFO_TYPE)
print*,"Error! Type is wrong!"
class default
print *,"Error! Type not found"
end select
getPhase = 0
return
end function getPhase
end module phase_mod
program extend
use phase_mod
implicit none
integer :: irc
integer :: ID
type(Phase_tp), pointer :: myphase
type(Ext_Phase_tp), pointer :: myphaseInfo
irc = addPhase(3,1,0,3)
irc = getPhase(myphase, myphaseInfo)
print*,myphaseInfo%KeysetID
print*,myphaseInfo%ghostsMin
print*,myphaseInfo%ghostsMax
end program extend
!------------------------
With the intel compiler we get:
using: irc=addBasePhase(nghosts,PhaseInfo)
ifort extend.f90
extend.f90(XX): error #6633: The type of the actual argument differs from the type of the dummy argument. [PHASEINFO]
irc=addBasePhase(nghosts,PhaseInfo)
-----------------------------^
Using irc=addBasePhase(nghosts,PhaseInfo%PHASEINFO_TYPE)
!
! ifort extend.f90
!
! extend.f90(XX): error #8307: If the rightmost part-name is of abstract type, data-ref shall be polymorphic [PHASEINFO_TYPE]
! irc=addBasePhase(nghosts,PhaseInfo%PHASEINFO_TYPE)
! ---------------------------------------^
! extend.f90(XX): error #8292: If a dummy argument is allocatable or a pointer, the associated actual argument shall be polymorphic if and only if the dummy argument is polymorphic. [PHASEINFO_TYPE]
! irc=addBasePhase(nghosts,PhaseInfo%PHASEINFO_TYPE)
! ---------------------------------------^
! extend.f90(47): error #6691: A pointer dummy argument may only be argument associated with a pointer. [PHASEINFO_TYPE]
! irc=addBasePhase(nghosts,PhaseInfo%PHASEINFO_TYPE)
! ---------------------------------------^
!
I have a piece of code that has several libraries sharing a common code base. The libraries are compiled from this common base plus their own bits of unique code.
One piece of data that all the libraries share is a "Phase Type", a derived type containing several common pieces of data. However each library needs to extend this out for their own extra data. We'd created the datatype to hold another extendable datatype that could hold this extra information. The idea was that the other libraries would contain code that would extend the type and set the data themselves. The set routines would also call teh base routines in the common code to set the common variables.
BUT. passing the extended type back into the common code is poving tricker than we hoped.
The problem seems to be that we can't pass the extended type back to the base routine that expects the original abstract base type.
Here's an example of what we're trying, with the compiler output below that. Does anyone have any suggestions on how to get this working please? (or alternatives that would acieve the same thing
Cheers.
Duncan
!------------------------------------
module phase_mod
implicit none
save
type, abstract :: PHASEINFO_TYPE
integer(kind=4) :: TYPE_ID
end type PHASEINFO_TYPE
type :: Phase_tp
integer(kind=4) :: nghosts
class (PHASEINFO_TYPE), pointer :: phaseinfo => null()
end type Phase_tp
! This bit is unique to one of the libraries
type, extends(PHASEINFO_TYPE) :: Ext_Phase_tp
integer(kind=4) :: keySetID ! KeySet associated with this
integer(kind=4) :: ghostsMin ! Default Ghost layer range
integer(kind=4) :: ghostsMax ! Default Ghost layer range
end type Ext_Phase_tp
type(Phase_tp), target :: iPhase
type(Ext_Phase_tp), pointer :: PhaseInfo=>null()
contains
! sets up a base Phase type. Calling program must pass in the phaseinfo type
integer function addBasePhase(nghosts, aPhaseInfo)
integer, intent(in) :: nghosts
class (PHASEINFO_TYPE), pointer, optional :: aPhaseInfo ! intent(in)
iPhase%nghosts = nghosts
iPhase%phaseinfo => aPhaseInfo
addBasePhase = 0
return
end function addBasePhase
! The unique library will call this routine to set up the phase info type and pass it back
integer function addPhase(nghosts, keysetid, gmin, gmax)
integer, intent(in) :: nghosts
integer, intent(in) :: keysetid
integer, intent(in) :: gmin
integer, intent(in) :: gmax
integer :: irc
allocate(PhaseInfo)
PhaseInfo%KeysetID = keysetid
PhaseInfo%ghostsMin = gmin
PhaseInfo%ghostsMax = gmax
! Two ways we tried this bit:
irc=addBasePhase(nghosts,PhaseInfo)
! irc=addBasePhase(nghosts,PhaseInfo%PHASEINFO_TYPE)
addPhase = 0
return
end function addPhase
! Trying to see if what we had worked!
integer function getPhase(phase, phaseInfo)
type(Phase_tp), pointer :: phase
type(Ext_Phase_tp), pointer :: phaseInfo
phase => iPhase
select type (p=>iPhase%phaseinfo)
type is (Ext_Phase_tp)
print*,"Type found!"
phaseInfo=>p
class is (PHASEINFO_TYPE)
print*,"Error! Type is wrong!"
class default
print *,"Error! Type not found"
end select
getPhase = 0
return
end function getPhase
end module phase_mod
program extend
use phase_mod
implicit none
integer :: irc
integer :: ID
type(Phase_tp), pointer :: myphase
type(Ext_Phase_tp), pointer :: myphaseInfo
irc = addPhase(3,1,0,3)
irc = getPhase(myphase, myphaseInfo)
print*,myphaseInfo%KeysetID
print*,myphaseInfo%ghostsMin
print*,myphaseInfo%ghostsMax
end program extend
!------------------------
With the intel compiler we get:
using: irc=addBasePhase(nghosts,PhaseInfo)
ifort extend.f90
extend.f90(XX): error #6633: The type of the actual argument differs from the type of the dummy argument. [PHASEINFO]
irc=addBasePhase(nghosts,PhaseInfo)
-----------------------------^
Using irc=addBasePhase(nghosts,PhaseInfo%PHASEINFO_TYPE)
!
! ifort extend.f90
!
! extend.f90(XX): error #8307: If the rightmost part-name is of abstract type, data-ref shall be polymorphic [PHASEINFO_TYPE]
! irc=addBasePhase(nghosts,PhaseInfo%PHASEINFO_TYPE)
! ---------------------------------------^
! extend.f90(XX): error #8292: If a dummy argument is allocatable or a pointer, the associated actual argument shall be polymorphic if and only if the dummy argument is polymorphic. [PHASEINFO_TYPE]
! irc=addBasePhase(nghosts,PhaseInfo%PHASEINFO_TYPE)
! ---------------------------------------^
! extend.f90(47): error #6691: A pointer dummy argument may only be argument associated with a pointer. [PHASEINFO_TYPE]
! irc=addBasePhase(nghosts,PhaseInfo%PHASEINFO_TYPE)
! ---------------------------------------^
!