4

我正在编写一个库,用于将多种类型的几何(球体、平面、NURBS 曲面、stl 文件...)导入到科学的 Fortran 代码中。这种问题似乎是为 OOP 量身定做的,因为定义 atype :: geom和 thentype,extends(geom) :: analytic等很简单。我遇到问题的部分是文件 IO。

在这一点上,我的解决方案是编写定义形状的参数,包括一些告诉我它是哪种形状的标志。阅读时,我实例化了一个class(geom) :: object, (因为我事先不知道它将是哪个子类型)但是我该如何阅读它呢?

我无法访问该子类型的任何特定组件。我读到向下转换是禁止的,此外,新的allocate(subtype :: class)似乎不起作用。新的READ(FORMATTED)似乎没有由 ifort 或 gfortran 实现。IE

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
4

1 回答 1

4

当前的 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 对象,请使用传统子例程引用样式中的“调用读取(对象)”。)

于 2012-07-20T03:50:22.730 回答