2012-07-20 78 views
3

我在写一个用于将多种类型(球体,平面,NURBS曲面,stl文件...)的几何图形导入科学Fortran代码的库。这种问题似乎是由OOP制造的,因为它很容易定义type :: geom,然后定义为type,extends(geom) :: analytic等等。我遇到的部分是文件IO。在Fortran中使用多态数据类型的文件IO

我现在的解决方案是编写定义形状的参数,包括一些标志,告诉我它是哪种形状。在阅读时,我实例化了一个class(geom) :: object,(因为我不知道提前知道哪个子类型),但我怎么读它?我不能访问任何子类型的特定组件。我看到这个向下转换是verboten,此外,新的allocate(subtype :: class)似乎没有工作。新的READ(FORMATTED)似乎不被ifort或gfortran实施。即

module geom_mod 
    type :: geom 
    end type 
    type,extends(geom) :: sphere 
    integer :: type 
    real(8) :: center(3),radius 
    contains 
    generic :: READ(FORMATTED)=> read_sphere ! not implemented anywhere 
    end type 
contains 
    subroutine read_geom(object) 
    class(geom),intent(out),pointer :: object  
    integer :: type 

    read(10,*) object%type ! can't access the subtype data yet 

    read(10,*) type 
    backspace(10) 
    if(type==1) then 
     allocate(sphere :: object)! downcast? 
     read(10,*) object   ! doesn't work 
    end if 

    end read_geom 
end module 

我要对所有这一切错了吗?我可以使用除多态之外的其他东西来破解这个,但是在其他地方这看起来更清晰。援助将不胜感激。

编辑:使用IanH的模块

program test 
    use geom_mod 
    implicit none 
    class(geom),allocatable :: object 

    open(10) 
    write(10,*) '1' 
    write(10,*) sphere(center=0,radius=1) 
    rewind(10) 

    call read(object) ! works ! 
end program test 
+0

输入文件需要有(至少)我的示例代码的两条记录 - 第一条记录的类型为整数,第二条记录为球体数据。你真的得到了段错误还是文件结束状态? – IanH 2012-07-20 06:01:52

+0

我在球体类型中添加了一个'integer :: type = 1'行,这只是混淆了这个问题。我不知道为什么这会导致seg错误,但是当我坚持使用模块时,它会起作用。谢谢! – weymouth 2012-07-20 06:08:26

+0

它看起来像seg故障链接到具有默认值的派生类型中的任何变量。所以如果我在类型定义中设置'radius = 1',我会得到seg故障。 – weymouth 2012-07-20 06:18:15

回答

3

电流gfortran和ifort不实现定义的输入/输出样本程序。我还没有看到有证据表明这种情况在不久的将来会改变。但是,除了允许某些语法快捷键之外,该功能实际上并不能为您节省大量工作。

这种情况的一种方法是调用geom扩展的“工厂”,它使用文件中的数据将参数分配给正确的类型,然后切换到类型绑定过程,该过程读​​入特定类型数据。例如:

module geom_mod 
    implicit none 
    integer, parameter :: dp = kind(1.0d0) 
    type, abstract :: geom 
    contains 
    procedure(read_geom), deferred :: read 
    end type geom 

    abstract interface 
    subroutine read_geom(object) 
     import :: geom 
     implicit none 
     class(geom), intent(out) :: object 
    end subroutine read_geom 
    end interface 

    type, extends(geom) :: sphere 
    real(dp) :: center(3), radius 
    contains 
    procedure :: read => read_sphere 
    end type sphere 
contains 
    subroutine read(object) 
    class(geom), intent(out), allocatable :: object 
    integer :: type 
    read (10, *) type 
    ! Create (and set the dynamic type of object) based on type. 
    select case (type) 
    case (1)  ; allocate(sphere :: object) 
    case default ; stop 'Unsupported type index' 
    end select 
    call object%read 
    end subroutine read 

    subroutine read_sphere(object) 
    class(sphere), intent(out) :: object 
    read (10, *) object%center, object%radius 
    end subroutine read_sphere 
end module geom_mod 

当前ifort(12.1.5)的意图(出)多态参数的问题,可能需要变通方法,但一般的方法是一样的。

(注意,子程序读不是一个类型的约束子程序 - 读通用GEOM对象使用“”调用read(对象)“”在传统的子程序引用样式。)