2012-07-20 75 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(對象)「」在傳統的子程序引用樣式。)