SCTfile_reader.f90 Source File


Files dependent on this one

sourcefile~~sctfile_reader.f90~~AfferentGraph sourcefile~sctfile_reader.f90 SCTfile_reader.f90 sourcefile~unstructuredgrid.f90 unstructuredGrid.f90 sourcefile~unstructuredgrid.f90->sourcefile~sctfile_reader.f90 sourcefile~boxflowfield.f90 boxFlowField.f90 sourcefile~boxflowfield.f90->sourcefile~unstructuredgrid.f90 sourcefile~cellcentercalc_test.f90 cellCenterCalc_test.f90 sourcefile~cellcentercalc_test.f90->sourcefile~unstructuredgrid.f90 sourcefile~dropletmotionsimulation.f90 dropletMotionSimulation.f90 sourcefile~dropletmotionsimulation.f90->sourcefile~unstructuredgrid.f90 sourcefile~flow_field.f90 flow_field.f90 sourcefile~dropletmotionsimulation.f90->sourcefile~flow_field.f90 sourcefile~flow_field.f90->sourcefile~unstructuredgrid.f90 sourcefile~kdtree_test.f90 kdTree_test.f90 sourcefile~kdtree_test.f90->sourcefile~unstructuredgrid.f90 sourcefile~main.f90 MAIN.f90 sourcefile~main.f90->sourcefile~dropletmotionsimulation.f90

Contents

Source Code


Source Code

module SCT_file_reader_m
    !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    !!version: 2.5.2
    !!author: T.Ikeda, Y.Ida
    !!summary:
    !!- SC/TETRA 出力のファイルを読み取り,データを取り出す.  
    !!- 今までのconverterと異なり, 本モジュールで独立して扱えるようになっている. 
    !!- 並列化には対応していない. 
    !!
    !!@note
    !!
    !!- セルの節点の並び順はwedge以外はvtkのものと同じ.
    !!- SC/TETRAでは,セル番号および節点番号は0スタートなので, fortran運用のためインデックス+1. 
    !!- 頂点配列(NDNO)はセルタイプ毎に並んでいない. 
    !!- cell2verticesのrank 1には最大で8つ(hexahedron), face2verticesには4つの値が入るが, 
    !!  値が入っていない箇所は全て-1に統一されている. 
    !!
    !!@endnote
    !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    implicit none
    private

    integer(4) LCORD
        !!座標番号(=0固定): 多分不要

    integer,parameter :: LengthOfSubRecord = 4194304
        !!サブレコード1行あたりの長さの上限. 必要はないがメモとして

    !面の定義. [頂点数, ローカル節点番号の並び].ローカル節点番号は1~最大8.  
    integer, private, target :: SCTTetraFaces_(3+1,4)   = reshape( &
                                                    [3, 4,3,2, &
                                                     3, 4,1,3, &
                                                     3, 4,2,1, &
                                                     3, 1,2,3], shape(SCTTetraFaces_))
    integer, private, target :: SCTPyramidFaces_(4+1,5) = reshape( &
                                                    [3, 1,5,2,-1, &
                                                     3, 2,5,3,-1, &
                                                     3, 3,5,4,-1, &
                                                     3, 4,5,1,-1, &
                                                     4, 1,2,3,4], shape(SCTPyramidFaces_))
    integer, private, target :: SCTPrismFaces_(4+1,5)   = reshape( &
                                                    [4, 1,4,5,2, &
                                                     4, 2,5,6,3, &
                                                     4, 3,6,4,1, &
                                                     3, 1,2,3,-1, &
                                                     3, 6,5,4,-1], shape(SCTPrismFaces_))        
    integer, private, target :: SCTHexahedronFaces_(4+1,6)   = reshape( &
                                                    [4, 1,5,6,2, &
                                                     4, 2,6,7,3, &
                                                     4, 3,7,8,4, &
                                                     4, 4,8,5,1, &
                                                     4, 1,2,3,4, &
                                                     4, 8,7,6,5], shape(SCTHexahedronFaces_))

    real(8),parameter,public :: MissingValueSize = 1.0d20
        !! SC/TETRAで規定された欠測値の大きさ. 

    character(10),parameter :: LS_Scalar_HeadName = "LS_Scalar:"
    character(10),parameter :: LS_Vector_HeadName = "LS_Vector:"
    character(32),parameter :: OverLapEndLabel = "OverlapEnd"

    integer,parameter :: LS_Scalar_DataSize = 30
        !!.fldに含まれるスカラーデータの個数上限. 
    integer,parameter :: LS_Vector_DataSize = 30
        !!.fldに含まれるベクトルデータの個数上限. 

    type,private :: LS_Scalar_t
        character(:),allocatable :: name
        character(:),allocatable :: abbreviated_name
        integer(4) ndata
        real(8),allocatable :: data(:)
    end type

    type,private :: LS_Vector_t
        character(:),allocatable :: name
        character(:),allocatable :: abbreviated_name
        integer(4) ndata
        real(8),allocatable :: x(:), y(:), z(:)
    end type
    type,private :: sctregion_t
        integer(4) NE
        character(:),allocatable :: LRGN
        integer(4),allocatable :: IE(:)
            !!領域を構成する要素番号
        integer(4),allocatable :: IFA(:)
            !!領域を構成するローカル面番号. 
        contains
        procedure,private :: get_data => get_sctregion_data_
        procedure,private :: extract_region_surface_
    end type sctregion_t

    type sct_data_name_list_t
        !! スカラーorベクトルデータの名前だけを取り出す. 構造体の配列にして使用する.
        !! region用に使うことも出来る. その場合abbreviatedは使わない.
        !! 異なる文字長の配列が実装できなかったのでこれで代用する.  
        character(:),allocatable :: name
        character(:),allocatable :: abbreviated_name
    end type

    type sct_grid_t
        !! SC/TETRA メッシュクラス. 
        !! 必要最低限の変数のみ保持. 変数名はフォーマットに準拠.  
        !! メッシュそのものを取り扱うのでメモリ圧迫する可能性大. 
        !! ソルバ内で使う場合はサブルーチンのローカル変数として扱う方が無難(自動開放されるはず)
        logical,private :: is_FLD
        logical,private :: includes_topo
        ! integer,private :: error_code

        integer(4),private ::  NELEM = 0
            !!要素数
        integer(4),private ::  NTTE = 0
            !!1要素あたりの節点数の合計

        integer(4),allocatable,private :: IETYP(:)
            !! 要素タイプ. 
            !! 34:tetrahedron, 35:pyramid, 36:wedge, 38:hexahedron
        integer(4),allocatable,private :: NDNO(:)
            !! 節点番号

        integer(4),allocatable,private :: GRP(:)
            !! グループ番号

        integer(4),allocatable,private :: MAT(:)
            !! 物性番号
            !! 多分使えないけど念のため...

        integer(4),private :: NNODS = 0
            !! 節点の総数
        real(8),allocatable,private :: CDN_X(:), CDN_Y(:), CDN_Z(:)
            !! 節点座標

        integer(4),private ::  NDATA = 0
            !! 場の変数のデータ数(=NNODS)

        ! SctRegion用変数
        integer(4),private :: NRGN = 0
            !! NRGN: 領域の個数, 配列regionの次元
        integer(4),private :: NLEN = 0
            !! NLEN: 領域名LRGNのバイト数 

        type(sctregion_t),allocatable,private :: region(:)
        
        !test 2021/10/12
        !連結リストの方が良い?
        integer,private :: scalar_data_count = 0
        integer,private :: vector_data_count = 0
        type(LS_Scalar_t),allocatable,private :: scalars(:)
        type(LS_Vector_t),allocatable,private :: vectors(:)

        integer,private :: tetra_count_ = 0
        integer,private :: pyramid_count_ = 0
        integer,private :: wedge_count_ = 0
        integer,private :: hexa_count_ = 0

        contains

        procedure,public :: includes_topology
        procedure,public :: is_fld_file

        procedure,public :: print_self

        procedure,public :: read_SCT_file

        procedure,public :: extract_original_cell_vertices
        procedure,public :: extract_cell_vertices
        procedure,public :: extract_ordered_cell_vertices

        procedure,public :: get_2d_array_of_point_coords
        ! procedure get_2d_array_of_point_velocity !データをsearch_vector_dataで探す方針なので削除. 

        procedure,public :: get_cell_types

        procedure,public :: get_element_count
        procedure,public :: get_vertex_count

        procedure,public :: get_tetrahedron_count
        procedure,public :: get_wedge_count
        procedure,public :: get_pyramid_count
        procedure,public :: get_hexahedron_count

        procedure,public :: get_region_count
        procedure,public :: get_region_namelist
        procedure,public :: extract_face2vertices_on_region

        procedure,public :: search_scalar_data
        procedure,public :: search_vector_data
        procedure,public :: get_data_titles

        final destructor

    end type

    interface get_data_array_
        module procedure get_data_array_int32_
        module procedure get_data_array_float64_
    end interface get_data_array_


    public sct_grid_t, sct_data_name_list_t, get_cell_data_from_cellvertices
contains

    !==========================================================================
    ! PUBLIC : subroutine
    !==========================================================================


    subroutine get_cell_data_from_cellvertices(cell_data, cell2vertices, point_data)
        !! 各セル毎の頂点配列に関連する節点中心データからセル中心データを構築する. 
        !! 値はセルを構成する節点データの算術平均として計算する. 
        
        implicit none
        integer,intent(inout) :: cell_data(:)
            !!出力されるセル中心データ. 
        integer,intent(in) :: cell2vertices(:,:)
            !!頂点配列. 
        integer,intent(in) :: point_data(:)
            !!任意の節点データ. 

        integer cell, node_count
        
        node_count = ubound(cell2vertices,dim=1)

        do cell = 1, size(cell2vertices,dim=2)
            cell_data(cell) = sum(point_data(cell2vertices(1:node_count,cell))) / node_count
        end do
        
    end subroutine

    !==========================================================================
    ! type bounded procedure : sct_grid_t
    !==========================================================================
    logical function includes_topology(this)
        !! 格子ファイルがトポロジを含むか. 
        implicit none
        class(sct_grid_t),intent(in) :: this

        includes_topology = this%includes_topo
    
    end function

    logical function is_fld_file(this)
        !!ファイルがFLDか.
        implicit none
        class(sct_grid_t),intent(in) :: this

        is_fld_file = this%is_FLD

    end function

    subroutine print_self(this,unit)
        implicit none
        class(sct_grid_t),intent(in) :: this
        integer,intent(in) :: unit
        integer i, nrg

        write(unit,"('sct grid information ')",advance="no") 
        if(this%includes_topo) then
            write(unit, "(A)") "from "//merge("fld file", "pre file",this%is_FLD)
            write(unit, "(' cell      :: ', i0)") this%NELEM
            write(unit, "(' - tetra   :: ', i0)") this%tetra_count_
            write(unit, "(' - pyramid :: ', i0)") this%pyramid_count_
            write(unit, "(' - wedge   :: ', i0)") this%wedge_count_
            write(unit, "(' - hexa    :: ', i0)") this%hexa_count_
            write(unit, "(' node      :: ', i0)") this%NNODS

            if(allocated(this%region)) then
                write(unit, "(' region info ')")
                do nrg = 1, this%NRGN
                    write(unit, "(2x,A,1x,A)") trim(this%region(nrg)%LRGN), merge("(vol )", "(surf)", all(this%region(nrg)%IFA==0))
                end do
            endif

        else
            write(unit, "('topology information not found.')")
        endif

        if(this%is_FLD) then
            write(unit, "(' scalar data  :: ', i0)") this%scalar_data_count
            write(unit, "(A,' = ',A)") (this%scalars(i)%abbreviated_name, this%scalars(i)%name, i = 1, this%scalar_data_count)
            write(unit, "(' vector data  :: ', i0)") this%vector_data_count
            write(unit, "(A,' = ',A)") (this%vectors(i)%abbreviated_name, this%vectors(i)%name, i = 1, this%vector_data_count)
        endif

    end subroutine

    subroutine read_SCT_file(this, filename)
        !! SCTファイルを開き,データを取得する. 事実上のコンストラクタ. 
        !! 既に別のファイルを開いていた場合,そのデータを破棄して開く. 
        implicit none
        class(sct_grid_t),intent(inout) :: this
        character(*),intent(in) :: filename
        
        ! character(256) :: errmsg

        integer unit

        !割り付けされている物があれば解放する. 
        call destructor(this)


        if(.not. open_binary_sequential_(unit, filename)) then
            return 
        endif

        select case(get_extension_(filename))

        case(".pre")
            ! メッシュファイルの場合
            this%is_FLD = .false.
            this%includes_topo = .true.
            call readPRE_Header_data_(unit)
            call readPRE_Main_data_(unit, this%NELEM, this%IETYP, this%NTTE, this%NDNO, this%GRP, this%MAT, this%NNODS, &
                                   this%CDN_X, this%CDN_Y, this%CDN_Z, this%region, this%NRGN, this%NLEN)

        case(".fld")
            ! fldファイルの場合
            ! fldの初期ファイルでないとトポロジー情報が入手できないらしい. 
            this%is_FLD = .true.
            call readFLD_Header_data_(unit)
            !call readFLD_Main_data_(unit, this%NELEM, this%IETYP, this%NTTE, this%NDNO, this%MAT, this%NNODS, &
            !                       this%CDN_X, this%CDN_Y, this%CDN_Z, this%NDATA, this%VEL_X, this%VEL_Y, this%VEL_Z, this%PRES)
        
            call readFLD_Main_data_2(unit, this%NELEM, this%IETYP, this%NTTE, this%NDNO, this%MAT, this%NNODS, &
                                     this%CDN_X, this%CDN_Y, this%CDN_Z, this%scalars, this%vectors,           &
                                     this%scalar_data_count, this%vector_data_count, this%includes_topo)
        case default
            print "(A,' is not supported. STOP')", trim(filename)
            return
        end  select

        !各セル数. 
        if ( this%includes_topo  ) then
            this%tetra_count_ = count(this%IETYP==34)
            this%pyramid_count_ = count(this%IETYP==35)
            this%wedge_count_ = count(this%IETYP==36)
            this%hexa_count_ = count(this%IETYP==38)
        end if
    
        close(unit)

        ! if(this%error_code == -3) stop "invalid data format. "
    end subroutine 

    subroutine extract_original_cell_vertices(this, cell2vertices)
        !!Sc/Tetraで出力されたセル-頂点関係の配列をそのまま出力する. 
        !!セルの種類毎に並んでいないのが特徴.  頂点番号は1から始まる.
        implicit none
        class(sct_grid_t),intent(in) :: this
        integer,allocatable,intent(inout) :: cell2vertices(:,:)
            !!頂点配列. 1st arg: vertex count, 2nd arg: cell number

        integer II
        integer offset
        integer nc
        integer KK_beg, KK_end

        if(.not. this%includes_topo) return

        if(.not. allocated(cell2vertices)) allocate(cell2vertices(1:8,1:this%NELEM),source = -1)

        nc = 1
        KK_beg = 1
        do II = 1, this%NELEM

            offset = this%IETYP(II) - 30
            KK_end = KK_beg + offset - 1

            cell2vertices(1:offset,nc) =this%NDNO(KK_beg:KK_end)
            nc = nc + 1
           
            KK_beg = KK_end + 1

        end do


    end subroutine


    subroutine extract_cell_vertices(this, tetras, pyramids, wedges, hexas)
        !!afdet solver との互換性のため, セルタイプごとの頂点配列を出力する. 
        !!頂点配列にはセル毎の頂点のインデックスが格納される. 頂点番号は1から始まる. 
        implicit none
        class(sct_grid_t),intent(in) :: this
        integer,allocatable,intent(inout),optional :: tetras(:,:), pyramids(:,:), wedges(:,:), hexas(:,:)

        if(.not. this%includes_topo) return

        if(present(tetras)) call extract_primitives_(this, tetras, "tetra")
        if(present(pyramids)) call extract_primitives_(this, pyramids, "pyramid")
        if(present(wedges)) call extract_primitives_(this, wedges, "wedge")
        if(present(hexas)) call extract_primitives_(this, hexas, "hexa")

    end subroutine


    subroutine extract_ordered_cell_vertices(this, cell2vertices)
        !!セルの種類毎に並んだ格子全体の頂点配列を作成する. 
        !!セルはtetra→pyramid→wedge→hexaの順に並べられる. 頂点番号は1から始まる.
        implicit none
        class(sct_grid_t),intent(in) :: this
        integer,allocatable,intent(inout) :: cell2vertices(:,:)

        integer,allocatable :: tmp(:,:)
        integer :: celltypes(4) = [34,35,36,38]
        character(5),dimension(4) :: typename = ["tetra", "pyram", "wedge", "hexah"] 
            !gfortranだと文字数が同じでないとerrorになるため無理矢理揃えた.  
            !ifortなら問題ないのだが...
        integer i, cell_beg, cell_end
       
        if(.not. this%includes_topo) return
        if(.not. allocated(cell2vertices)) allocate(cell2vertices(1:8,1:this%NELEM))

        cell_beg = 1
        do i = 1, 4
            if(count(this%IETYP==celltypes(i)) > 0) then

                call extract_primitives_(this, tmp, typename(i))

                cell_end = cell_beg + size(tmp, dim=2) - 1

                cell2vertices(1:size(tmp, dim=1), cell_beg:cell_end) = tmp(:,:)

                cell_beg = cell_end + 1

                deallocate(tmp)
            
            end if
        end do    
    
    end subroutine


    subroutine get_2d_array_of_point_coords(this, xyz)
        !! 節点座標を2次元配列で出力する. 
        implicit none
        class(sct_grid_t),intent(in) :: this
        real(8),allocatable,intent(inout) :: xyz(:,:)

        if(.not. this%includes_topo) return
        call packing_vector_into_2Darray_(xyz, this%CDN_X, this%CDN_Y, this%CDN_Z)
    
    end subroutine 


    ! subroutine get_2d_array_of_point_velocity(this, velocity)
    !     !! 節点流速データを2次元配列で出力する. 
    !     implicit none
    !     class(sct_grid_t),intent(in) :: this
    !     real(8),allocatable,intent(inout) :: velocity(:,:)

    !     if(this%error_code /= 0) return
    !     call packing_vector_into_2Darray_(velocity, this%VEL_X, this%VEL_Y, this%VEL_Z)
    
    ! end subroutine 

    subroutine get_cell_types(this, celltypes,conversion)
        !!セルタイプ配列を出力する. 
        !!extract_original_cell_verticesで出力したセル-節点配列に対して有効. 
        implicit none
        class(sct_grid_t),intent(in) :: this
        integer,allocatable,intent(inout) :: celltypes(:)
            !!セルタイプ配列
        character(*),intent(in),optional :: conversion
            !!セルタイプ番号をvtk, xdmfいずれかに変換する. 

        if(.not. this%includes_topo) return

        allocate(celltypes, source = this%IETYP)

        if(.not.present(conversion)) return

        select case(trim(conversion))
            case("vtk","VTK")
                where(celltypes == 34)
                    celltypes = 10
                elsewhere(celltypes == 35)
                    celltypes = 14
                elsewhere(celltypes == 36)
                    celltypes = 13
                elsewhere(celltypes == 38)
                    celltypes = 12
                endwhere
            case("xdmf","XDMF")
                where(celltypes == 34)
                    celltypes = 6
                elsewhere(celltypes == 35)
                    celltypes = 7
                elsewhere(celltypes == 36)
                    celltypes = 8
                elsewhere(celltypes == 38)
                    celltypes = 9
                endwhere
            case default
                print*, trim(conversion), " is not implemented. "
                return
        end select
    
    end subroutine 



    integer function get_element_count(this)
        !!要素数を取得する. 
        implicit none
        class(sct_grid_t),intent(in) :: this

        if(this%includes_topo) get_element_count = this%NELEM
    
    end function


    integer function get_vertex_count(this)
        !!節点数を取得する. 
        implicit none
        class(sct_grid_t),intent(in) :: this

        if(this%includes_topo) get_vertex_count = this%NNODS

    end function

    integer function get_tetrahedron_count(this)
        !!格子に含まれるテトラ格子数を取得する. 
        implicit none
        class(sct_grid_t),intent(in) :: this

        if(this%includes_topo) get_tetrahedron_count = this%tetra_count_
    end function

    integer function get_pyramid_count(this)
        !!格子に含まれるピラミッド格子数を取得する. 
        implicit none
        class(sct_grid_t),intent(in) :: this

        if(this%includes_topo) get_pyramid_count = this%pyramid_count_
    end function

    integer function get_wedge_count(this)
        !!格子に含まれるプリズム格子数を取得する. 
        implicit none
        class(sct_grid_t),intent(in) :: this

        if(this%includes_topo) get_wedge_count = this%wedge_count_
    end function

    integer function get_hexahedron_count(this)
        !!格子に含まれるヘキサ格子数を取得する. 
        implicit none
        class(sct_grid_t),intent(in) :: this

        if(this%includes_topo) get_hexahedron_count = this%hexa_count_
    end function

    integer function get_region_count(this)
        !!領域の個数. 
        implicit none
        class(sct_grid_t),intent(in) :: this

        get_region_count = this%NRGN

    end function

    subroutine get_region_namelist(this, name_list)
        implicit none
        class(sct_grid_t),intent(in) :: this
        type(sct_data_name_list_t),allocatable,intent(inout) :: name_list(:)

        integer nrg

        allocate(name_list(1:this%NRGN))
        do nrg = 1, this%NRGN
            name_list(nrg)%name = this%region(nrg)%LRGN
        enddo

    end subroutine


    subroutine extract_face2vertices_on_region(this, region_num, cell2vertices, face2vertices)
        !!任意のregionを構成する頂点配列を取得する. 体積領域は無視する. 
        !!cell2verticesはoriginalの物でなければならない. 
        implicit none
        class(sct_grid_t),intent(in) :: this
        integer,intent(in) :: region_num
            !!region番号. 
        integer,allocatable,intent(in) :: cell2vertices(:,:)
            !!並べ替えのされていないセル-頂点配列. 
        integer,allocatable,intent(inout) :: face2vertices(:,:)
            !!regionを構成する面-頂点配列. 

        ! integer nrg
        if(.not. this%includes_topo) return
        if(region_num > this%NRGN) then
            print*, "error(sct_grid_t) :: region_num must be less than ",this%NRGN
            return
        endif

        call this%region(region_num)%extract_region_surface_(this%IETYP, cell2vertices, face2vertices)
    end subroutine



    subroutine search_scalar_data(this, key, scalar)
        !! .fldに含まれるスカラー場データを取得する.
        !! keyにタイトル名を入れて検索する. 該当しない場合含まれるデータ一覧を表示.  
        implicit none
        class(sct_grid_t),intent(in) :: this
        character(*),intent(in) :: key
            !!取り出したいデータのSC/TETRAでの名称. 
        real(8),allocatable,intent(inout) :: scalar(:)

        integer i

        if(.not. this%is_FLD) return !FLDファイルなら場のデータは含まれると判断. 

        do i = 1, size(this%scalars)
            if ( trim(this%scalars(i)%abbreviated_name) == trim(key) ) then
                if ( .not. allocated(scalar) ) then
                    allocate(scalar, source = this%scalars(i)%data)
                else
                    scalar(:) = this%scalars(i)%data(:)
                end if
                return
            end if
        end do

        print "(A,' does not exists.')", key
        print "('Existing Scalar data are listed below:')"
        do i = 1, this%scalar_data_count
            print "(A,1x,':',A)", this%scalars(i)%name, this%scalars(i)%abbreviated_name
        end do

         
    end subroutine

    subroutine search_vector_data(this, key, vector)
        !! .fldに含まれるベクトル場データを取得する.
        !! keyにタイトル名を入れて検索する. 該当しない場合含まれるデータ一覧を表示. 
        implicit none
        class(sct_grid_t),intent(in) :: this
        character(*),intent(in) :: key
            !!取り出したいデータのSC/TETRAでの名称.
        real(8),allocatable,intent(inout) :: vector(:,:)

        integer i

        if(.not. this%is_FLD) return

        do i = 1, size(this%vectors)
            if ( trim(this%vectors(i)%abbreviated_name) == trim(key) ) then
                call packing_vector_into_2Darray_(vector, this%vectors(i)%x, this%vectors(i)%y, this%vectors(i)%z)
                return
            end if
        end do

        print "(A,' does not exists.')", key
        print "('Existing Vector data are listed below:')"
        do i = 1, this%vector_data_count
            print "(A,1x,':',A)", this%vectors(i)%name, this%vectors(i)%abbreviated_name
        end do

    end subroutine

    subroutine get_data_titles(this, titles, data_type)
        !! .fldに含まれるデータのタイトルを取得する. 
        implicit none
        class(sct_grid_t), intent(in) :: this
        type(sct_data_name_list_t),allocatable,intent(inout) :: titles(:)
        character(*), intent(in) :: data_type

        integer i

        if(.not. this%is_FLD) return

        select case(data_type)

            case("scalar")
                allocate(titles(this%scalar_data_count))
                do i = 1, this%scalar_data_count
                    titles(i)%abbreviated_name = this%scalars(i)%abbreviated_name
                    titles(i)%name = this%scalars(i)%name
                end do
            case("vector")
                allocate(titles(this%vector_data_count))
                do i = 1, this%vector_data_count
                    titles(i)%abbreviated_name = this%vectors(i)%abbreviated_name
                    titles(i)%name = this%vectors(i)%name
                end do
            case default
        
        end select

    end subroutine

    subroutine destructor(this)
        implicit none
        type(sct_grid_t),intent(inout) :: this

        ! integer i
    
        if (allocated(this%IETYP)) deallocate(this%IETYP)
        if (allocated(this%MAT)) deallocate(this%MAT)
        if (allocated(this%NDNO)) deallocate(this%NDNO)
        if (allocated(this%GRP)) deallocate(this%GRP)
        if (allocated(this%CDN_X)) deallocate(this%CDN_X)
        if (allocated(this%CDN_Y)) deallocate(this%CDN_Y)
        if (allocated(this%CDN_Z)) deallocate(this%CDN_Z)
        ! if (allocated(this%VEL_X)) deallocate(this%VEL_X)
        ! if (allocated(this%VEL_Y)) deallocate(this%VEL_Y)
        ! if (allocated(this%VEL_Z)) deallocate(this%VEL_Z)
        if (allocated(this%region)) deallocate(this%region)
        if(allocated(this%scalars)) deallocate(this%scalars)
        if(allocated(this%vectors)) deallocate(this%vectors)

        this%NELEM = 0
        this%NNODS = 0
        this%NDATA = 0
        this%NTTE = 0
        this%NLEN = 0
        this%NRGN = 0
        this%tetra_count_ = 0
        this%pyramid_count_ = 0
        this%wedge_count_ = 0
        this%hexa_count_ = 0
        this%scalar_data_count = 0
        this%vector_data_count = 0
    end subroutine

    !==========================================================================
    ! PRIVATE : extraction
    !==========================================================================

    subroutine extract_primitives_(sct_grid, primitive, cell_type)
        !!格子からセルタイプ毎の頂点配列を抜き出す. 
        implicit none
        type(sct_grid_t),intent(in) :: sct_grid
        integer,allocatable,intent(inout) :: primitive(:,:)
            !!セルタイプ毎の頂点配列. 1st arg: local node number, 2nd arg: cell number
            !!頂点インデックスが格納される. インデックスは1スタートになっている. 
        character(*),intent(in) :: cell_type
            !!セルの種類. 
            !!"tetra(or tetrahedron)", "prizm(or wedge)", "pyramid", "hexa(or hexahedron)"

        integer(4) :: nc, offset
        integer(4) :: II, node_of_cell
        integer(4) :: KK_beg, KK_end
        integer a_err
        character(512) msg

        nc = 1
        
        select case(trim(cell_type))
            case("tetra","tetrahedron")
                node_of_cell = 4
            case("prizm","wedge")
                node_of_cell = 6
            case("pyramid","pyram")
                node_of_cell = 5
            case("hexa","hexahedron","hexah")
                node_of_cell = 8
            case default
                print "('Unclassifiable cell type was detected. choose cell type below:')"
                print "('tetra or tetrahedron')"
                print "('prizm or wedge      ')"
                print "('pyramid             ')"
                print "('hexa  or hexahedron ')"
                stop
        end select

        if ( count(sct_grid%IETYP==30+node_of_cell) == 0 ) then
            print "('error: cell_type ', A, ' possibly does not exists on your mesh file...')", cell_type
            ! return
        end if

        !仮に対応するセルタイプが存在しなくても割り付けは出来るが,その場合は以下の処理も自動的にスルーされる
        allocate(primitive(1:node_of_cell,count(sct_grid%IETYP==30+node_of_cell)),source = -1, &
                 stat = a_err, errmsg = msg)

        if ( a_err /= 0 ) then
            print "(i0,1x,A)", a_err, msg
            return
        end if

        KK_beg = 1
        do II = 1, size(sct_grid%IETYP)

            offset = sct_grid%IETYP(II) - 30
            KK_end = KK_beg + offset - 1

            if ( sct_grid%IETYP(II) == 30 + node_of_cell ) then
                primitive(1:node_of_cell,nc) = sct_grid%NDNO(KK_beg:KK_end)
                nc = nc + 1
            end if

            KK_beg = KK_end + 1

        end do

    end subroutine extract_primitives_

    ! subroutine get_cell_data_from_point_data_(cell_data, cell_types, node_numbers, point_data)
    !     !! 節点中心データからセル中心データを取り出す
    !     !! セルの値はセルを構成する節点データの平均として扱われる
    !     !!~~~ CAUTION :: THIS IS DEPRICATED METHOD ~~~
    !     !! REASON) 作ってみたが,あとでセルタイプ毎に並び替えるためこの方法では矛盾する. 
    !     !!         セル中心データへの補間は外部で行うとする方が都合が良い. 
    !     !!~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    !     implicit none
    !     integer,allocatable,intent(inout) :: cell_data(:)
    !     integer,intent(in) :: cell_types(:)
    !     integer,intent(in) :: node_numbers(:)
    !     integer,intent(in) :: point_data(:)

    !     integer cell, node_beg, node_end, node_count

    !     allocate(cell_data(size(cell_types)))

    !     node_beg = 1
    !     do cell = 1, size(cell_types)
    !         node_count = cell_types(cell) - 30
    !         node_end = node_beg + node_count - 1

    !         cell_data(cell) = sum(point_data(node_numbers(node_beg:node_end))) / node_count

    !         node_beg = node_end + 1
            
    !     end do


    ! end subroutine 
    
    !==========================================================================
    ! PRIVATE : utility
    !==========================================================================

    logical function open_binary_sequential_(unit, filename) result(is_opened)
        !! バイナリファイルをシーケンシャル形式で開く. 開けない場合.false.
        integer, intent(inout) :: unit
            !! 装置番号. 
        character(*), intent(in) :: filename
             
        character(256) iomessage
        integer iostatus

        open(newunit = unit, file = filename, iostat = iostatus, iomsg = iomessage, &
             form = 'unformatted', access = 'sequential', status = 'old', convert = 'big_endian')

        if ( iostatus == 0 ) then
            is_opened = .true.
        else
            is_opened = .false.
            print "('error:',i0,1x,A)", iostatus, trim(iomessage)
        end if
    end function

    function get_extension_(filename) result(extension_name)
        !! ファイル名の拡張子を取得する. 
        !! e.g.) hoge.f90なら".f90"が返される. "."が2つ以上ある場合は保証しない. 
        character(*),intent(in) :: filename

        character(:),allocatable :: extension_name

        integer extension_start

        extension_start = index(filename, ".", back = .true.)
        extension_name = filename(extension_start:len_trim(filename))

    end function

    subroutine packing_vector_into_2Darray_(array, x, y, z)
        !! 実数のベクトル配列を2次元配列に詰め直す
        implicit none
        real(8), allocatable, intent(out) :: array(:,:)
        real(8), intent(in) :: x(:), y(:), z(:)

        integer size_of_array

        size_of_array = size(x)
        
        if(size_of_array /= size(y) .or. size_of_array /= size(z)) then
            print "('ERROR(SCTfile_reader, packing_): size of x is different from y or z')"
            return
        end if
        if(.not. allocated(array)) allocate(array(3, size_of_array))

        array(1,:) = x(:)
        array(2,:) = y(:)
        array(3,:) = z(:)
    end subroutine
    
    !==========================================================================
    ! PRIVATE: reading header
    !==========================================================================


    subroutine readPRE_Header_data_(unit)
        !!preファイルのヘッダ部分を読み取る
        implicit none
        integer,intent(in) :: unit

        integer(4)  header_num
        character(8)  header_text
        character(32) title_text
    
        read(unit) header_text
        read(unit) header_num
        ! 序文データの読み取り
        ! おそらくvtk化するためには不要なので
        ! 無限ループでHeaderDataEndを検出した時点でexit
        
        do 
            read(unit) title_text
            if(trim(title_text)=='HeaderDataEnd') exit
            read(unit)
            read(unit)
            read(unit)
        end do
    end subroutine 

    subroutine readFLD_Header_data_(unit)
        implicit none
        integer,intent(in) :: unit
        integer(4)  header_num, NNAMS, n
        character(8)  header_text
        character(32) title_text
    
        read(unit) header_text
        read(unit) header_num
        ! 序文データの読み取り
        ! おそらくvtk化するためには不要なので
        ! 無限ループでHeaderDataEndを検出した時点でexit
        
        do 
            read(unit) title_text
            if(trim(title_text)=='HeaderDataEnd') then
                exit
            elseif((trim(title_text)=='Cycle').or.(trim(title_text)=='Unused')) then
                read(unit)
                read(unit)
    
            elseif(trim(title_text)=='Unit:$TEMP') then
                read(unit)
                read(unit)
                read(unit)
                read(unit)
                read(unit) NNAMS
                do n = 1, NNAMS
                    read(unit)
                end do
                read(unit)
                cycle
            end if
    
            read(unit)
            read(unit)
            read(unit)
    
        end do
    end subroutine


    !==========================================================================
    ! PRIVATE: reading main data
    !==========================================================================


    !> 本文データの読み取り.とにかく全て読み取るようにしている
    subroutine readPRE_Main_data_(unit, NELEM, IETYP, NTTE, NDNO, GRP, MAT, NNODS, CDN_X, CDN_Y, CDN_Z, region, NRGN, NLEN)
        implicit none
        integer,intent(in) :: unit
        integer,intent(inout) :: NELEM
        integer,intent(inout) :: NTTE
        integer,allocatable,intent(inout) :: IETYP(:)
        integer,allocatable,intent(inout) :: NDNO(:)
        integer,allocatable,intent(inout) :: GRP(:)
        integer,allocatable,intent(inout) :: MAT(:)
        integer,intent(inout) :: NNODS
        real(8),allocatable,intent(inout) :: CDN_X(:), CDN_Y(:), CDN_Z(:)
        integer,intent(inout) :: NRGN
        integer,intent(inout) :: NLEN
        type(sctregion_t), allocatable, intent(inout) :: region(:)

        integer(4) nrg
        character(32) main_data_title
        character(32) TITLE

        !> OVerlapStart_nの読み取り
        read(unit) main_data_title
        !本文データの読み取り
        ! irecn == 1 なら タイトル内のサブレコードは1つ
        ! iretn == 1 なら サブレコード内のデータは1つ
        ! ibyte == 4:int32, 8:real64, 1:char(32 or 80 or 1)
        ! 本文データにて ibyte = 1となることはなさそう 

        !> LS_CoordinateSystem
        read(unit) TITLE
        read(unit) !4, 1, 1
        read(unit) !LNX
        call get_data_int32_(unit, LCORD)
        read(unit) !0, 0, 0

        !> LS_Elements
        read(unit) TITLE 
        read(unit) !4, 1, 1
        read(unit) !LNX
        call get_data_int32_(unit, NELEM) 
       
        call get_data_array_(unit, IETYP, NELEM) 
        
        call get_data_int32_(unit, NTTE)
        
        call get_data_array_(unit, NDNO, NTTE)
        !NDNOは0スタートのため, 都合+1する. 
        NDNO(1:NTTE) = NDNO(1:NTTE) + 1  
        read(unit) !0, 0, 0

        !> LS_GrpOfElements
        read(unit) TITLE 
        read(unit) !4, 1, 1
        read(unit) !LNX
        call get_data_int32_(unit, NELEM)
        call get_data_array_(unit, GRP, NELEM)
        read(unit)

        !> LS_MatOfElements
        read(unit) TITLE 
        read(unit) !4, 1, 1
        read(unit) !LNX
        call get_data_int32_(unit, NELEM)
        call get_data_array_(unit, MAT, NELEM)
        read(unit)

        !> LS_Nodes
        read(unit) TITLE 
        read(unit) !4, 1, 1
        read(unit) !LNX
        call get_data_int32_(unit, NNODS)
        call get_data_array_(unit, CDN_X, NNODS)
        call get_data_array_(unit, CDN_Y, NNODS)
        call get_data_array_(unit, CDN_Z, NNODS)
        read(unit)

        !> OverlapEndならそのまま終了
        !> そうで無い場合,任意データLS_SctRegionsが存在しうるが
        !> vtk化のためには不要と思われるので現状は素通り
        !> 追記:2021/05/30 境界面の指定番号なのでIFACE.DATへ利用可能かも
        read(unit) TITLE 
        if(trim(TITLE)=='OverlapEnd') then
            print *, 'SctRegion is not included in this file. '
        else
            print *, 'SctRegions is included.'
            read(unit) !4, 1, 1
            read(unit) !LNX
            call get_data_int32_(unit, NRGN)

            allocate(region(NRGN))

            call get_data_int32_(unit, NLEN)
            do nrg = 1, NRGN
                call region(nrg)%get_data(unit, NLEN)
            end do
            
            read(unit)
        end if

    end subroutine

    subroutine readFLD_Main_data_(unit,NELEM, IETYP, NTTE, NDNO, MAT, &
                                      NNODS, CDN_X, CDN_Y, CDN_Z,    &
                                      NDATA, VEL_X, VEL_Y, VEL_Z,    &
                                      PRES)
        implicit none
        integer,intent(in) :: unit
        integer,intent(inout) :: NELEM
        integer,intent(inout) :: NTTE
        integer,allocatable,intent(inout) :: IETYP(:)
        integer,allocatable,intent(inout) :: NDNO(:)
        integer,allocatable,intent(inout) :: MAT(:)
        integer,intent(inout) :: NNODS
        real(8),allocatable,intent(inout) :: CDN_X(:), CDN_Y(:), CDN_Z(:)
        integer,intent(inout) :: NDATA
        real(8),allocatable,intent(inout) :: VEL_X(:), VEL_Y(:), VEL_Z(:)
        real(8),allocatable,intent(inout) :: PRES(:)

        integer(4) N, NTRY
        character(32) main_data_title
        character(32) TITLE
    
        !> OVerlapStart_nの読み取り
        read(unit) main_data_title
        !本文データの読み取り
        ! irecn == 1 なら タイトル内のサブレコードは1つ
        ! iretn == 1 なら サブレコード内のデータは1つ
        ! ibyte == 4:int32, 8:real64, 1:char(32 or 80 or 1)
        ! 本文データにて ibyte = 1となることはなさそう
    
        do
    
        read(unit) TITLE ; print *, TITLE
        
        select case (trim(TITLE))
            case('LS_CoordinateSystem')
                read(unit) !4, 1, 1
                read(unit) !LNX
                call get_data_int32_(unit, LCORD)
                read(unit) !0, 0, 0
    
            case('LS_SurfaceGeometryArray')
                call ignore_data_(unit) !LNX
                call ignore_data_(unit) !NGFAX
                call ignore_data_(unit) !LLEN
                call ignore_data_(unit) !LRGNS
                call ignore_data_(unit) !NBNNS
                call ignore_data_(unit) !IPTYP
                call ignore_data_(unit) !IPMAT
                call ignore_data_(unit) !NTTSS
                call ignore_data_(unit) !NDFA
                read(unit) !0, 0, 0
    
            case('LS_Elements')
                read(unit) !4, 1, 1
                read(unit) !LNX
                call get_data_int32_(unit, NELEM) 
                call get_data_array_(unit, IETYP, NELEM) 
                call get_data_int32_(unit, NTTE)
                call get_data_array_(unit, NDNO, NTTE)  
                !NDNOは0スタートのため, 都合+1する. 
                NDNO(1:NTTE) = NDNO(1:NTTE) + 1
                read(unit) !0, 0, 0
    
            case('LS_MatOfElements')
                read(unit) !4, 1, 1
                read(unit) !LNX
                call get_data_int32_(unit, NELEM)
                call get_data_array_(unit, MAT, NELEM)
                read(unit)
    
            case('LS_Nodes')
                read(unit) !4, 1, 1
                read(unit) !LNX
                call get_data_int32_(unit, NNODS)
                call get_data_array_(unit, CDN_X, NNODS)
                call get_data_array_(unit, CDN_Y, NNODS)
                call get_data_array_(unit, CDN_Z, NNODS)
                read(unit)
    
            case('LS_VolumeGeometryArray')
                call ignore_data_(unit) !LNX
                call ignore_data_(unit) !NVORG
                call ignore_data_(unit) !LLEN
                call ignore_data_(unit) !LRGNS
                call ignore_data_(unit) !NELES
                call ignore_data_(unit) !IELE
                read(unit)
    
            case('LS_RegionName&Type')
                call ignore_data_(unit) !LNX
                call get_data_int32_(unit, NTRY)
                call ignore_data_(unit) !NLEN
                do N = 1, NTRY
                    call ignore_data_(unit) !ITRY
                    call ignore_data_(unit) !MRGN
                end do
                read(unit)
    
            case('LS_SFile')
                call ignore_data_(unit) !LNX
                call ignore_data_(unit) !NLEN
                call ignore_data_(unit) !TEXT
                read(unit)
    
            !ここを切り分ける. scalar dataは要求するデータのみ探索し, 後は捨てる
            !一致するもののみよみとり,あとはignoreする. 
            case('LS_Scalar:PRES')
                call ignore_data_(unit) !LNX
                call ignore_data_(unit) !LNAM
                call get_data_int32_(unit, NDATA) !NDATA
                call get_data_array_(unit, PRES, NDATA) !VAR
                read(unit)
    
            case('LS_Scalar:TEMP')
                call ignore_data_(unit) !LNX
                call ignore_data_(unit) !LNAM
                call ignore_data_(unit) !NDATA
                call ignore_data_(unit) !VAR
                read(unit)
    
            case('LS_Scalar:TURK')
                call ignore_data_(unit) !LNX
                call ignore_data_(unit) !LNAM
                call ignore_data_(unit) !NDATA
                call ignore_data_(unit) !VAR
                read(unit)
            
            case('LS_Scalar:TEPS')
                call ignore_data_(unit) !LNX
                call ignore_data_(unit) !LNAM
                call ignore_data_(unit) !NDATA
                call ignore_data_(unit) !VAR
                read(unit)
    
            case('LS_Scalar:EVIS')
                call ignore_data_(unit) !LNX
                call ignore_data_(unit) !LNAM
                call ignore_data_(unit) !NDATA
                call ignore_data_(unit) !VAR
                read(unit)
    
            case('LS_Scalar:YPLS')
                call ignore_data_(unit) !LNX
                call ignore_data_(unit) !LNAM
                call ignore_data_(unit) !NDATA
                call ignore_data_(unit) !VAR
                read(unit)
    
            case('LS_Scalar:HTRC')
                call ignore_data_(unit) !LNX
                call ignore_data_(unit) !LNAM
                call ignore_data_(unit) !NDATA
                call ignore_data_(unit) !VAR
                read(unit)
    
            case('LS_Scalar:USTR')
                call ignore_data_(unit) !LNX
                call ignore_data_(unit) !LNAM
                call ignore_data_(unit) !NDATA
                call ignore_data_(unit) !VAR
                read(unit)
    
            case('LS_Vector:VEL')
                call ignore_data_(unit) !LNX
                call ignore_data_(unit) !LVCT
                call ignore_data_(unit) !LNAM
                call get_data_int32_(unit, NDATA) !NDATA
                call get_data_array_(unit, VEL_X, NDATA)
                call get_data_array_(unit, VEL_Y, NDATA)
                call get_data_array_(unit, VEL_Z, NDATA)
                read(unit)
    
            case('LS_Vector:HVEC')
                call ignore_data_(unit) !LNX
                call ignore_data_(unit) !LVCT
                call ignore_data_(unit) !LNAM
                call ignore_data_(unit) !NDATA
                call ignore_data_(unit) !VAR
                call ignore_data_(unit) !VAR
                call ignore_data_(unit) !VAR
                read(unit)
    
            case('OverlapEnd')
                exit
    
            case default
                print*, 'TITLE_ERROR:', TITLE
                stop
    
        end select
    
        end do
    
    end subroutine

    subroutine readFLD_Main_data_2(unit,NELEM, IETYP, NTTE, NDNO, MAT, &
        NNODS, CDN_X, CDN_Y, CDN_Z,    &
        scalars, vectors, scalar_cnt, vector_cnt, topo_included)
        !!FLDのメインデータ部分を読み取る. 
        !
        !fldが解析スタートファイルでない場合,toporogy情報が含まれない可能性が高い. 
        !したがって, 初期ファイル以外のものを最初に読み取るとトポロジ情報が入手できない.
        !
        implicit none
        integer,intent(in) :: unit
        integer,intent(inout) :: NELEM
        integer,intent(inout) :: NTTE
        integer,allocatable,intent(inout) :: IETYP(:)
        integer,allocatable,intent(inout) :: NDNO(:)
        integer,allocatable,intent(inout) :: MAT(:)
        integer,intent(inout) :: NNODS
        real(8),allocatable,intent(inout) :: CDN_X(:), CDN_Y(:), CDN_Z(:)
        type(LS_Scalar_t),allocatable,intent(inout) :: scalars(:)
        type(LS_Vector_t),allocatable,intent(inout) :: vectors(:)
        integer,intent(inout) :: scalar_cnt
        integer,intent(inout) ::  vector_cnt
        logical,intent(inout) ::  topo_included
            

        integer(4) N, NTRY
        character(32) main_data_title
        character(32) TITLE

        !> OVerlapStart_nの読み取り
        read(unit) main_data_title
        !本文データの読み取り
        ! irecn == 1 なら タイトル内のサブレコードは1つ
        ! iretn == 1 なら サブレコード内のデータは1つ
        ! ibyte == 4:int32, 8:real64, 1:char(32 or 80 or 1)
        ! 本文データにて ibyte = 1となることはなさそう

        topo_included = .false.
        !TITLEは以下の順に並んでいると仮定する. 
        do

            read(unit) TITLE
        
            if( trim(TITLE) == 'LS_CoordinateSystem') then
                read(unit) !4, 1, 1
                read(unit) !LNX
                call get_data_int32_(unit, LCORD)
                read(unit) !0, 0, 0

            else if ( trim(TITLE) == 'LS_SurfaceGeometryArray') then
                call ignore_data_(unit) !LNX
                call ignore_data_(unit) !NGFAX
                call ignore_data_(unit) !LLEN
                call ignore_data_(unit) !LRGNS
                call ignore_data_(unit) !NBNNS
                call ignore_data_(unit) !IPTYP
                call ignore_data_(unit) !IPMAT
                call ignore_data_(unit) !NTTSS
                call ignore_data_(unit) !NDFA
                read(unit) !0, 0, 0

            else if ( trim(TITLE) == 'LS_Elements') then
                read(unit) !4, 1, 1
                read(unit) !LNX
                call get_data_int32_(unit, NELEM) 
                call get_data_array_(unit, IETYP, NELEM) 
                call get_data_int32_(unit, NTTE)
                call get_data_array_(unit, NDNO, NTTE)  
                !NDNOは0スタートのため, 都合+1する. 
                NDNO(1:NTTE) = NDNO(1:NTTE) + 1
                read(unit) !0, 0, 0

            else if ( trim(TITLE) == 'LS_MatOfElements') then
                read(unit) !4, 1, 1
                read(unit) !LNX
                call get_data_int32_(unit, NELEM)
                call get_data_array_(unit, MAT, NELEM)
                read(unit)

            else if( trim(TITLE) == 'LS_Nodes') then
                read(unit) !4, 1, 1
                read(unit) !LNX
                call get_data_int32_(unit, NNODS)
                call get_data_array_(unit, CDN_X, NNODS)
                call get_data_array_(unit, CDN_Y, NNODS)
                call get_data_array_(unit, CDN_Z, NNODS)
                read(unit)

                !順番的にこれがトポロジー情報の最後とみる. 
                topo_included = .true.

                !ここでループ抜けすると,LS_Scalar以外の物が前に残っている可能性があるのでNG. 
                ! exit

            else if( trim(TITLE) == 'LS_VolumeGeometryArray') then
                call ignore_data_(unit) !LNX
                call ignore_data_(unit) !NVORG
                call ignore_data_(unit) !LLEN
                call ignore_data_(unit) !LRGNS
                call ignore_data_(unit) !NELES
                call ignore_data_(unit) !IELE
                read(unit)

            else if ( trim(TITLE) == 'LS_RegionName&Type') then
                call ignore_data_(unit) !LNX
                call get_data_int32_(unit, NTRY)
                call ignore_data_(unit) !NLEN
                do N = 1, NTRY
                    call ignore_data_(unit) !ITRY
                    call ignore_data_(unit) !MRGN
                end do
                read(unit)

            else if( trim(TITLE) == 'LS_SFile') then
                call ignore_data_(unit) !LNX
                call ignore_data_(unit) !NLEN
                call ignore_data_(unit) !TEXT
                read(unit)
                !必須データでないらしい. 確実にここでループ抜け出来るとは限らない. 
                ! exit

            else if( TITLE(1:10) == "LS_Scalar:") then
                !LS_Scalar:以下はループ外で処理するので,1行前に戻ってループ抜けする. 
                backspace(unit)
                exit
                !もしLS_elementsなどを介せずここに来た場合, トポロジは含まれないと判断. 
                 
            else
                print*, "(error) readFLD_main_data_2 :: UnKnown title data was detected. ", trim(TITLE)
                return
            end if

        end do

        !LS_scalar, LS_vector
        if(.not.allocated(scalars)) allocate(scalars(LS_Scalar_DataSize))
        if(.not.allocated(vectors)) allocate(vectors(LS_Vector_DataSize))
        datas_reader:block
            logical EOR
            integer s_cnt, v_cnt, i

            EOR = .false.
            s_cnt = 0
            do while(.not.EOR)
                s_cnt = s_cnt + 1
                call LS_Scalar_reader(scalars(s_cnt), unit, EOR)
            end do
            scalar_cnt = s_cnt - 1

            EOR = .false.
            v_cnt = 0
            do while(.not.EOR)
                v_cnt = v_cnt + 1
                call LS_Vector_reader(vectors(v_cnt), unit, EOR)
            end do
            vector_cnt = v_cnt - 1

            do i = s_cnt, size(scalars)
                scalars(i)%name = "NONE"
            enddo

            do i = v_cnt, size(vectors)
                vectors(i)%name = "NONE"
            enddo

            ! do i = 1, size(scalars)
            !     print *, scalars(i)%name
            !     print *, scalars(i)%abbreviated_name
            ! enddo
    
            ! do i = 1, size(vectors)
            !     print *, vectors(i)%name
            !     print *, scalars(i)%abbreviated_name
            ! enddo
    
        end block datas_reader

    end subroutine

    !==========================================================================
    ! LS_Scalar_t
    !==========================================================================

    subroutine LS_Scalar_reader(ls_scalar, unit, is_ended)
        !!LS_Scalar:で始まる行のデータ読み取り. 
        implicit none
        type(LS_Scalar_t),intent(inout) :: ls_scalar
            !!LS_Scalar_t 構造体
        integer(4),intent(in) :: unit
            !!装置番号
        logical,intent(out) :: is_ended
            !!LS_Scalarの終端かどうか. 
        ! character(:),allocatable,intent(inout) :: LNAME
        ! integer(4),intent(inout) :: NDATA
        ! real(8),allocatable,intent(inout) :: VAR(:)
        
        character(32) title
       
        is_ended = .false.
        read(unit) title
        select case(title(1:10))
            case(LS_Scalar_HeadName)
                ls_scalar%abbreviated_name = title(11:14)
                call ignore_data_(unit)
                call get_data_char_(unit, 32, ls_scalar%name)
                call get_data_int32_(unit, ls_scalar%ndata)
                call get_data_array_(unit, ls_scalar%data, ls_scalar%ndata)
                read(unit)
            case(LS_Vector_HeadName)
                backspace(unit)
                is_ended = .true.
                return
            case(OverLapEndLabel)
                is_ended = .true.
                return
            case default
                print "('something is wrong. ')", trim(title(1:10))
                error stop
        end select
       
    end subroutine

    subroutine LS_Vector_reader(ls_vector, unit, is_ended)
        implicit none
        
        type(LS_Vector_t),intent(inout) :: ls_vector
        integer(4),intent(in) :: unit
        logical,intent(inout) :: is_ended
        ! character(:),allocatable,intent(inout) :: LNAME
        ! integer(4),intent(inout) :: NDATA
        ! real(8),allocatable,intent(inout) :: VAR(:)
        
        character(32) title
       
        is_ended = .false.
        read(unit) title
        select case(title(1:10))
            case(LS_Vector_HeadName)
                ls_vector%abbreviated_name = title(11:14)
                call ignore_data_(unit)
                call ignore_data_(unit)
                call get_data_char_(unit, 32, ls_vector%name)
                call get_data_int32_(unit, ls_vector%ndata)
                call get_data_array_(unit, ls_vector%x, ls_vector%ndata)
                call get_data_array_(unit, ls_vector%y, ls_vector%ndata)
                call get_data_array_(unit, ls_vector%z, ls_vector%ndata)
                read(unit)
            case(OverLapEndLabel)
                is_ended = .true.
                return
            case default
                print "('something is wrong. ')", trim(title(1:10))
                error stop
        end select

    end subroutine
    !==========================================================================
    ! sctregion_t
    !==========================================================================

    !> sctregion_tクラスのメソッド
    subroutine get_sctregion_data_(this, unit, n_length)
        implicit none
        class(sctregion_t),intent(inout) :: this
        integer(4),intent(in) :: unit, n_length

        call get_data_char_(unit, n_length, this%LRGN)
        call get_data_int32_(unit, this%NE)
        call get_data_array_(unit, this%IE, this%NE)
        call get_data_array_(unit, this%IFA, this%NE)

        !要素番号, ローカル面番号は全て1スタートに揃える. 従って体積領域は0番. 
        this%IE(1:this%NE) = this%IE(1:this%NE) + 1
        this%IFA(1:this%NE) = this%IFA(1:this%NE) + 1

    end subroutine 

    subroutine extract_region_surface_(this,celltypes, cell2vertices, face2vert_on_region)
        !! regionを構成する頂点番号の抜き出し. 体積領域はスルー. 
        !! したがってregionの面-頂点関係が取得できる. 
        implicit none
        class(sctregion_t),intent(in) :: this
        integer,intent(in) :: celltypes(:)
        integer,intent(in) :: cell2vertices(:,:)
            !!セル-頂点関係の配列. オリジナルのものでなければならない. 
        integer,allocatable,intent(inout) :: face2vert_on_region(:,:)

        integer i, nv, cell, face
        integer,dimension(:,:),pointer :: SCTElementFacesDef

        if(all(this%IFA == 0)) then
            print*, "this region :"//trim(this%LRGN)//" is not a surface region."
            return
        endif

        if(allocated(face2vert_on_region)) deallocate(face2vert_on_region)
        allocate(face2vert_on_region(1:8,this%NE),source = -1)
        
        do i = 1, this%NE
            cell = this%IE(i)
            face = this%IFA(i)

            select case(celltypes(cell))

                case(34)
                    SCTElementFacesDef => SCTTetraFaces_
                case(35)
                    SCTElementFacesDef => SCTPyramidFaces_
                case(36)
                    SCTElementFacesDef => SCTPrismFaces_
                case(38)
                    SCTElementFacesDef => SCTHexahedronFaces_
                case default
                    print*, "sctregion_t :: not implemented celltype.",celltypes(cell)
                    error stop
            end select

            nv = SCTElementFacesDef(1,face)
            face2vert_on_region(1:nv,i) = cell2vertices(SCTElementFacesDef(2:nv+1,face),cell)
        end do

    end subroutine
    !==========================================================================
    ! data_reader
    !==========================================================================

    !> 整数型データを読みこみ格納
    subroutine get_data_int32_(unit,retval)
        implicit none
        integer(4),intent(in) :: unit
        integer(4),intent(out):: retval
        integer(4) ibyte, iretn, irecn 

        read(unit) ibyte, iretn, irecn
        read(unit) retval 
        
    end subroutine

    !> 整数型配列の読み込み
    subroutine get_data_array_int32_(unit, ret_array, ret_array_size)
        implicit none
        integer(4),intent(in) :: unit
        integer(4),allocatable,intent(out) :: ret_array(:)
        integer(4),intent(in) :: ret_array_size
        integer(4) ibyte, iretn, irecn
        integer(4) irec, L, ios
        integer(4) subrecn

        read(unit) ibyte, iretn, irecn

        subrecn = irecn - 1

        if(.not. allocated(ret_array)) allocate(ret_array(ret_array_size))

        if(subrecn == 0) then
            read(unit,iostat=ios) (ret_array(L), L=1, irecn*iretn)
            return
        else
            do irec = 1, subrecn
                read(unit,iostat=ios) (ret_array(L), L=1+(irec-1)*iretn, irec*iretn)
                if ( ios /= 0 ) then
                    ! print*,'iostat: ', ios, 'at L=', L
                    exit
                end if
            end do
        
            read(unit) (ret_array(L), L=1+(irecn-1)*iretn, ret_array_size)
        endif

    end subroutine

    !> 倍精度実数型配列の読み込み
    subroutine get_data_array_float64_(unit, ret_array, ret_array_size)
        implicit none
        integer(4),intent(in) :: unit
        real(8),allocatable,intent(out) :: ret_array(:)
        integer(4),intent(in) :: ret_array_size
        integer(4) ibyte, iretn, irecn
        integer(4) irec, L, ios
        integer(4) subrecn

        read(unit) ibyte, iretn, irecn

        subrecn = irecn - 1
        
        if(.not. allocated(ret_array)) allocate(ret_array(ret_array_size))

        if(subrecn == 0) then
            read(unit,iostat=ios) (ret_array(L), L=1, irecn*iretn)
            return
        else
            do irec = 1, subrecn
                read(unit,iostat=ios) (ret_array(L), L=1+(irec-1)*iretn, irec*iretn)
                if ( ios /= 0 ) then
                    ! print*,'iostat: ', ios, 'at L=', L
                    exit
                end if
            end do
        
            read(unit) (ret_array(L), L=1+(irecn-1)*iretn, ret_array_size)
        endif

    end subroutine

    !> データを読み飛ばす処理
    subroutine ignore_data_(unit)
        implicit none
        integer(4),intent(in) :: unit
        integer(4) ibyte, iretn, irecn
        integer(4) irec

        read(unit) ibyte, iretn, irecn
        do irec = 1, irecn
            read(unit)
        end do

    end subroutine

    !> 文字列(バイト数指定)
    subroutine get_data_char_(unit, byte, ret_char)
        implicit none
        integer(4), intent(in) :: unit
        integer(4), intent(in) :: byte
        character(:),allocatable,intent(inout) :: ret_char

        if(.not. allocated(ret_char)) allocate(character(byte) :: ret_char)
        read(unit) 
        read(unit) ret_char

    end subroutine

end module SCT_file_reader_m