plot3d_operator.f90 Source File


Files dependent on this one

sourcefile~~plot3d_operator.f90~~AfferentGraph sourcefile~plot3d_operator.f90 plot3d_operator.f90 sourcefile~cube2usg.f90 CUBE2USG.f90 sourcefile~cube2usg.f90->sourcefile~plot3d_operator.f90

Contents

Source Code


Source Code

!>CUBE出力ファイル形式:Plot3Dを取り扱うためのモジュール
module plot3d_operator
    implicit none
    private

    !>エリア構造体
    type area_t
        real, dimension(3) :: min, max  !最小座標と最大座標
    end type

    !>cube(Plot3D形式における立方体)構造体
    type cube_inP3D
        real, allocatable :: nodes(:,:,:,:)
            !!節点座標配列(i,j,k, xyz)

        real, allocatable :: f(:,:,:,:) 
            !!保存量配列(i,j,k, f)

        type(area_t) area
        contains
        procedure, public :: isIncluded
        procedure areaOfCube, nearest_nodeID!, nearer_nodeID
    end type

    !>節点情報構造体
    type, public :: plot3dNodeInfo  
        integer cubeID, nodeID(3)   !節点が属するcubeID、そのcube内の節点ID(i,j,kそれぞれのIDを指定するので要素数3)
    end type

    !>Plot3Dメッシュクラス
    type, public :: Plot3dMesh  
        private
        type(cube_inP3D), allocatable :: cubes(:)
            !!cube配列

        contains
        procedure areaOfMesh
        procedure, public :: read_plot3d_function, get_numCube, get_velocity, get_cubeShape
        procedure, public :: get_cubeID_contains, nearestNodeInfo
    end type

    public :: read_plot3d_multigrid !Plot3Dメッシュクラスの事実上コンストラクタ
    
    contains

    !>メッシュファイル(.g)を読み込んでメッシュクラスを返す関数
    function read_plot3d_multigrid(fName) result(mesh)
        character(*), intent(in) :: fName
        type(Plot3dMesh) mesh
        integer n_unit, i,j,k, i_cube, num_cube, xyz
        integer, allocatable :: ni(:), nj(:), nk(:)

        print*, 'READ_multigrid:', fName

        open(newunit=n_unit , form='unformatted', file=fName, status='old', action='read')

            read(n_unit) num_cube   ;print*, 'num_cube=', num_cube
            allocate(mesh%cubes(num_cube))
            allocate(ni(num_cube), nj(num_cube), nk(num_cube))

            read(n_unit) (ni(i_cube), nj(i_cube), nk(i_cube), i_cube=1,num_cube)

            print*, 'ni=', minval(ni(:)), maxval(ni(:))
            print*, 'nj=', minval(nj(:)), maxval(ni(:))
            print*, 'nk=', minval(nk(:)), maxval(ni(:))

            do i_cube = 1, num_cube
                allocate(mesh%cubes(i_cube)%nodes(ni(i_cube), nj(i_cube), nk(i_cube), 3))
            end do

            do i_cube = 1, num_cube
                read(n_unit) ((((   mesh%cubes(i_cube)%nodes(i,j,k, xyz), &
                    i = 1, ni(i_cube) ), j = 1, nj(i_cube) ), k = 1, nk(i_cube) ), xyz = 1,3)
                    ! (((iblank(i,j,k,i_cube), i = 1, ni(i_cube) ), j = 1, nj(i_cube) ), k = 1, nk(i_cube) )

                mesh%cubes(i_cube)%area = mesh%cubes(i_cube)%areaOfCube()
            end do

        close(n_unit)

        block
            type(area_t) area

            area = mesh%areaOfMesh()
            print*, 'min_cdn =', area%min
            print*, 'max_cdn =', area%max
        end block

    end function

    !>メッシュのエリアを構造体で返す関数
    type(area_t) function areaOfMesh(self)
        class(Plot3dMesh), intent(in) :: self
        integer i_cube, num_cube

        num_cube = size(self%cubes)

        areaOfMesh%min(:) = 1.e9
        areaOfMesh%max(:) = -1.e9

        do i_cube = 1, num_cube
            areaOfMesh%min(1) = min(areaOfMesh%min(1), self%cubes(i_cube)%area%min(1))
            areaOfMesh%min(2) = min(areaOfMesh%min(2), self%cubes(i_cube)%area%min(2))
            areaOfMesh%min(3) = min(areaOfMesh%min(3), self%cubes(i_cube)%area%min(3))
            areaOfMesh%max(1) = max(areaOfMesh%max(1), self%cubes(i_cube)%area%max(1))
            areaOfMesh%max(2) = max(areaOfMesh%max(2), self%cubes(i_cube)%area%max(2))
            areaOfMesh%max(3) = max(areaOfMesh%max(3), self%cubes(i_cube)%area%max(3))
        end do

    end function

    !>cubeのエリアを構造体で返す関数
    type(area_t) function areaOfCube(self)
        class(cube_inP3D), intent(in) :: self

        areaOfCube%min(1) = minval(self%nodes(:,:,:,1))
        areaOfCube%min(2) = minval(self%nodes(:,:,:,2))
        areaOfCube%min(3) = minval(self%nodes(:,:,:,3))
        areaOfCube%max(1) = maxval(self%nodes(:,:,:,1))
        areaOfCube%max(2) = maxval(self%nodes(:,:,:,2))
        areaOfCube%max(3) = maxval(self%nodes(:,:,:,3))

    end function

    !>cubeのエリア内に任意座標(引数)が含まれているかを返す関数
    logical function isIncluded(self, cdn)
        class(cube_inP3D), intent(in) :: self
        real, intent(in) :: cdn(3)

        isIncluded = .false.

        if ((cdn(1) >= self%area%min(1)).and.(cdn(2) >= self%area%min(2)).and.(cdn(3) >= self%area%min(3))) then

            if  ((cdn(1) <= self%area%max(1)).and.(cdn(2) <= self%area%max(2)).and.(cdn(3) <= self%area%max(3)))then

                isIncluded = .true.

            end if

        end if

    end function

    !>任意座標(引数)を含むcubeをメッシュの中から探してそのIDを返す関数
    integer function get_cubeID_contains(self, cdn)
        class(Plot3dMesh), intent(in) :: self
        real, intent(in) :: cdn(3)
        integer i_cube, num_cube

        get_cubeID_contains = 0
        num_cube = self%get_numCube()

        do i_cube = 1, num_cube
            if(self%cubes(i_cube)%isIncluded(cdn)) then
                get_cubeID_contains = i_cube
                return
            end if
        end do

        print*, 'ERROR : The Point is Out of Area.', cdn
        error stop

    end function

    !>任意座標(引数)に最近傍な節点を探してそのIDを返す関数
    function nearest_nodeID(self, cdn) result(nodeID)
        class(cube_inP3D), intent(in) :: self
        real, intent(in) :: cdn(3)
        integer nodeID(3)
        integer i,j,k, cubeShape(4)
        real relation(3)
        real, allocatable :: distance(:,:,:)

        cubeShape = shape(self%nodes)
        allocate(distance(cubeShape(1), cubeShape(2), cubeShape(3)), source=1.e9)
        !!$OMP parallel private(relation)
        !!$OMP do collapse(3)
        do k = 1, cubeShape(3)
            do j = 1, cubeShape(2)
                do i = 1, cubeShape(1)
                    relation(:) = cdn(:) - self%nodes(i,j,k, :)
                    distance(i,j,k) = norm2(relation(:))
                end do
            end do
        end do
        !!$OMP end do
        !!$OMP end parallel

        nodeID = minloc(distance)

    end function

    ! function nearer_nodeID(self, cdn, inodeID) result(rnodeID)
    !     class(cube_inP3D), intent(in) :: self
    !     real, intent(in) :: cdn(3)
    !     integer, intent(in) :: inodeID(3)
    !     integer nodeID(3), rnodeID(3), i, maxID
    !     real distance_min, relation(3)
    !     integer,parameter :: diff(3,6) &
    !                         = reshape([1,0,0, -1,0,0, 0,1,0, 0,-1,0, 0,0,1, 0,0,-1], shape(diff))
    !     logical update
    !     type(cube_inP3D) cube_
    !     type(node_inCUBE) node_

    !     node_ = self%nodes(inodeID(1), inodeID(2), inodeID(3))
    !     relation(1) = cdn(1) - node_%x
    !     relation(2) = cdn(2) - node_%y
    !     relation(3) = cdn(3) - node_%z
    !     distance_min = norm2(relation(:))
    !     rnodeID = inodeID
    !     update = .true.

    !     maxID = size(cube_%nodes(:,:,:), dim=1)

    !     do while(update)
    !         update = .false.

    !         check : do i = 1, 6

    !             nodeID(:) = rnodeID(:) + diff(:,i)

    !             if((minval(nodeID) < 1).or.(maxval(nodeID) > maxID)) cycle check

    !             node_ = cube_%nodes(nodeID(1), nodeID(2), nodeID(3))
    !             relation(1) = cdn(1) - node_%x
    !             relation(2) = cdn(2) - node_%y
    !             relation(3) = cdn(3) - node_%z

    !             if(norm2(relation(:)) < distance_min) then
    !                 distance_min = norm2(relation(:))
    !                 rnodeID = nodeID
    !                 update = .true.
    !             end if

    !         end do check

    !     end do

    ! end function

    !>任意座標(引数)に最近傍な節点を探し、その情報(cubeID,nodeID)を返す関数
    type(plot3dNodeInfo) function nearestNodeInfo(self, cdn)
        class(Plot3dMesh), intent(in) :: self
        real, intent(in) :: cdn(3)
        integer cubeID!, nodeID(3)

        cubeID = self%get_cubeID_contains(cdn)
        
        nearestNodeInfo%cubeID = cubeID
        nearestNodeInfo%nodeID(:) = self%cubes(cubeID)%nearest_nodeID(cdn)

        ! nodeID = self%cubes(cubeID)%nearest_nodeID(cdn, 4)
        ! nearestNodeInfo%nodeID(:) = self%cubes(cubeID)%nearer_nodeID(cdn, nodeID)

    end function

    ! subroutine write_plot3d_multigrid(mesh_in, fName)
    !     type(cube_inP3D), intent(in) :: mesh_in(:)
    !     character(*), intent(in) :: fName
    !     integer n_unit, i,j,k, i_cube, num_cube
    !     integer, allocatable :: ni(:), nj(:), nk(:)

    !     num_cube = size(mesh_in)

    !     allocate(ni(num_cube), nj(num_cube), nk(num_cube))

    !     do i_cube = 1, num_cube
    !         ni(i_cube) = size(mesh_in(i_cube)%nodes(:,:,:), dim=1)
    !         nj(i_cube) = size(mesh_in(i_cube)%nodes(:,:,:), dim=2)
    !         nk(i_cube) = size(mesh_in(i_cube)%nodes(:,:,:), dim=3)
    !     end do

    !     open(newunit=n_unit , form='unformatted', file=fName, status='replace')

    !         write(n_unit) num_cube

    !         write(n_unit) (ni(i_cube), nj(i_cube), nk(i_cube), i_cube=1,num_cube)

    !         do i_cube = 1, num_cube
    !             write(n_unit) &
    !                 ((( mesh_in(i_cube)%nodes(i,j,k)%x, &
    !                     i = 1, ni(i_cube) ), j = 1, nj(i_cube) ), k = 1, nk(i_cube) ), &
    !                 ((( mesh_in(i_cube)%nodes(i,j,k)%y, &
    !                     i = 1, ni(i_cube) ), j = 1, nj(i_cube) ), k = 1, nk(i_cube) ), &
    !                 ((( mesh_in(i_cube)%nodes(i,j,k)%z, &
    !                     i = 1, ni(i_cube) ), j = 1, nj(i_cube) ), k = 1, nk(i_cube) )

    !                 ! (((iblank(i,j,k,i_cube), i = 1, ni(i_cube) ), j = 1, nj(i_cube) ), k = 1, nk(i_cube) )
    !         end do

    !     close(n_unit)
    ! end subroutine

    ! subroutine write_plot3d_f(mesh_in, fName)
    !     type(cube_inP3D), intent(in) :: mesh_in(:)
    !     character(*), intent(in) :: fName
    !     integer n_unit, i,j,k,l, i_cube, num_cube
    !     integer, allocatable :: ni(:), nj(:), nk(:), nf(:)

    !     num_cube = size(mesh_in)

    !     allocate(ni(num_cube), nj(num_cube), nk(num_cube), nf(num_cube))

    !     do i_cube = 1, num_cube
    !         ni(i_cube) = size(mesh_in(i_cube)%nodes(:,:,:), dim=1)
    !         nj(i_cube) = size(mesh_in(i_cube)%nodes(:,:,:), dim=2)
    !         nk(i_cube) = size(mesh_in(i_cube)%nodes(:,:,:), dim=3)
    !     end do

    !     do i_cube = 1, num_cube
    !         nf(i_cube) = size(mesh_in(i_cube)%nodes(1,1,1)%f(:), dim=1)
    !     end do

    !     open(newunit=n_unit , form='unformatted', file=fName, status='replace')

    !         write(n_unit) num_cube

    !         write(n_unit) (ni(i_cube), nj(i_cube), nk(i_cube), nf(i_cube), i_cube=1,num_cube)

    !         do i_cube = 1, num_cube
    !             write(n_unit) &
    !             (((( mesh_in(i_cube)%nodes(i,j,k)%f(l), &
    !             i = 1, ni(i_cube) ), j = 1, nj(i_cube) ), k = 1, nk(i_cube) ), &
    !             l = 1, nf(i_cube))
    !         end do

    !     close(n_unit)
    ! end subroutine

    ! subroutine write_plot3d_asVTK(mesh_in, fName, n_cell)   !ひとつのcubeをひとつの節点とみなしてVTK出力
    !     type(cube_inP3D), intent(in) :: mesh_in(:)
    !     character(*), intent(in) :: fName
    !     integer, intent(in) :: n_cell    !CUBE一辺当たりのセル数
    !     integer n_unit, i_cube, num_cube, i,j,k, num_func, i_node, num_nodes, num_cells, i_cell
    !     integer i_max, j_max, k_max, delta_i, delta_j, delta_k, i1,i2,i3,i4, i_n
    !     real :: cdn(3), velocity(3)

    !     num_cube = size(mesh_in)
    !     num_nodes = num_cube*((n_cell + 1)**3)
    !     num_cells = num_cube*(n_cell**3)

    !     print*, 'VTK informations:'
    !     print*, 'nodes =', num_nodes
    !     print*, 'cells=', num_cells

    !     open(newunit=n_unit , form='formatted', file=fName, status='replace')

    !         write(n_unit, '(A)') '# vtk DataFile Version 2.0'
    !         write(n_unit, '(A)') 'Header'
    !         write(n_unit, '(A)') 'ASCII'
    !         write(n_unit, '(A)') 'DATASET UNSTRUCTURED_GRID'

    !         write(n_unit, *) 'POINTS', num_nodes, 'float'
    !         do i_cube = 1, num_cube
    !             i_max = size(mesh_in(i_cube)%nodes(:,:,:), dim=1)
    !             j_max = size(mesh_in(i_cube)%nodes(:,:,:), dim=2)
    !             k_max = size(mesh_in(i_cube)%nodes(:,:,:), dim=3)
    !             delta_i = (i_max - 1) / n_cell
    !             delta_j = (j_max - 1) / n_cell
    !             delta_k = (k_max - 1) / n_cell
    !             do k = 1, k_max, delta_k
    !                 do j = 1, j_max, delta_j
    !                     do i = 1, i_max, delta_i
    !                         cdn(1) = mesh_in(i_cube)%nodes(i,j,k)%x
    !                         cdn(2) = mesh_in(i_cube)%nodes(i,j,k)%y
    !                         cdn(3) = mesh_in(i_cube)%nodes(i,j,k)%z
    !                         write(n_unit, '(3(E15.8e2,2X))') cdn(:)
    !                     end do
    !                 end do
    !             end do
    !         end do

    !         write(n_unit, *) 'CELLS ', num_cells, num_cells*9
    !         do i_cube = 1, num_cube
    !             i_node =  (i_cube - 1)*((n_cell + 1)**3)    !CUBEの基準点ID
    !             i_n = 0
    !             do i_cell = 1, n_cell**3
    !                 i1 = i_node + i_n    !セルの基準点ID
    !                 i2 = i1 + n_cell + 1
    !                 i3 = i1 + (n_cell + 1)**2
    !                 i4 = i3 + n_cell + 1
    !                 write(n_unit, *)  8, i1, i1+1, i2, i2+1, i3, i3+1, i4, i4+1
    !                 i_n = i_n + 1
    !                 if(mod(i_n +1, n_cell +1) == 0) i_n = i_n + 1
    !                 if(mod(i_n +1 +n_cell, (n_cell +1)**2)==0) i_n = i_n + (n_cell + 1)
    !             end do
    !         end do
    !         write(n_unit, *) 'CELL_TYPES', num_cells
    !         do i_cell = 1, num_cells
    !             write(n_unit, *) 11 !11:直方体
    !         end do

    !         num_func = size(mesh_in(1)%nodes(1,1,1)%f(:))
    !         write(n_unit, *) 'POINT_DATA', num_nodes

    !         write(n_unit, '(A)') 'SCALARS density float'
    !         write(n_unit, '(A)') 'LOOKUP_TABLE default'
    !         do i_cube = 1, num_cube
    !             i_max = size(mesh_in(i_cube)%nodes(:,:,:), dim=1)
    !             j_max = size(mesh_in(i_cube)%nodes(:,:,:), dim=2)
    !             k_max = size(mesh_in(i_cube)%nodes(:,:,:), dim=3)
    !             delta_i = (i_max - 1) / n_cell
    !             delta_j = (j_max - 1) / n_cell
    !             delta_k = (k_max - 1) / n_cell
    !             do k = 1, k_max, delta_k
    !                 do j = 1, j_max, delta_j
    !                     do i = 1, i_max, delta_i
    !                         write(n_unit, '(E15.8e2)') mesh_in(i_cube)%nodes(i,j,k)%f(1)
    !                     end do
    !                 end do
    !             end do
    !         end do

    !         write(n_unit, '(A)') 'VECTORS velocity float'
    !         do i_cube = 1, num_cube
    !             i_max = size(mesh_in(i_cube)%nodes(:,:,:), dim=1)
    !             j_max = size(mesh_in(i_cube)%nodes(:,:,:), dim=2)
    !             k_max = size(mesh_in(i_cube)%nodes(:,:,:), dim=3)
    !             delta_i = (i_max - 1) / n_cell
    !             delta_j = (j_max - 1) / n_cell
    !             delta_k = (k_max - 1) / n_cell
    !             do k = 1, k_max, delta_k
    !                 do j = 1, j_max, delta_j
    !                     do i = 1, i_max, delta_i
    !                         velocity(:) = mesh_in(i_cube)%nodes(i,j,k)%f(2:4) / mesh_in(i_cube)%nodes(i,j,k)%f(1)
    !                         write(n_unit, '(3(E15.8e2,2X))') velocity(:)                                
    !                     end do
    !                 end do
    !             end do
    !         end do

    !     close(n_unit)
    ! end subroutine

    !>メッシュクラスメソッド
    !>保存量ファイル(.f)を読み込み、メッシュクラスに格納する
    subroutine read_plot3d_function(self, fName)
        class(Plot3dMesh) self
        character(*), intent(in) :: fName
        integer num_cube
        integer n_unit, i,j,k,l, i_cube
        real, allocatable :: min_f(:), max_f(:)
        integer, allocatable :: ni(:), nj(:), nk(:), nf(:)

        print*, 'READ_function:', fName

        open(newunit=n_unit , form='unformatted', file=fName, status='old', action='read')

            read(n_unit) num_cube   ;print*, 'num_cube=', num_cube
            if(num_cube /= size(self%cubes)) then
                print*, 'ERROR:the number of cube is not macth', num_cube, size(self%cubes)
                error stop
            end if

            allocate(ni(num_cube), nj(num_cube), nk(num_cube), nf(num_cube))

            read(n_unit) (ni(i_cube),nj(i_cube),nk(i_cube),nf(i_cube), i_cube=1,num_cube)

            print*, 'nf=', minval(nf(:)), maxval(nf(:))

            if(.not.allocated(self%cubes(1)%f)) then
                do i_cube = 1, num_cube
                    allocate(self%cubes(i_cube)%f(ni(i_cube), nj(i_cube), nk(i_cube), nf(i_cube)))
                end do
            end if

            do i_cube = 1, num_cube
                read(n_unit) &
                    ((((self%cubes(i_cube)%f(i,j,k,l), &
                        i = 1, ni(i_cube)), j = 1, nj(i_cube)), k = 1, nk(i_cube)), l = 1, nf(i_cube))
            end do

            allocate(min_f(maxval(nf(:))), source=1.e9)
            allocate(max_f(maxval(nf(:))), source=-1.e9)

            do i_cube = 1, num_cube
                do l = 1, nf(i_cube)
                    min_f(l) = min(min_f(l), minval(self%cubes(i_cube)%f(:,:,:,l)))
                    max_f(l) = max(max_f(l), maxval(self%cubes(i_cube)%f(:,:,:,l)))
                end do
            end do

            print*, min_f
            print*, max_f

        close(n_unit)

    end subroutine

    ! function extract_cube(mesh_in, min_cdn, max_cdn) result(mesh_extracted)
    !     type(cube_inP3D), intent(in) :: mesh_in(:)
    !     type(cube_inP3D), allocatable :: mesh_extracted(:)
    !     real, intent(in) :: min_cdn(3), max_cdn(3)
    !     real :: center(3)
    !     integer i_cube, l, cube_cnt, num_cube
    !     logical extract
    !     integer :: original_ID(size(mesh_in))

    !     num_cube = size(mesh_in)

    !     cube_cnt = 0
         
    !     do i_cube = 1, num_cube
    !         extract = .false.

    !         center(:) = get_center_position(mesh_in(i_cube)%nodes)

    !         do l = 1, 3
    !             if(center(l) < min_cdn(l)) extract = .true.
    !             if(center(l) > max_cdn(l)) extract = .true.
    !         end do

    !         if(extract) cycle

    !         cube_cnt = cube_cnt +1
    !         original_ID(cube_cnt) = i_cube

    !     end do

    !     print*, 'cube_count=', cube_cnt

    !     allocate(mesh_extracted(cube_cnt))

    !     do i_cube = 1, cube_cnt
    !         mesh_extracted(i_cube) = mesh_in(original_ID(i_cube))
    !     end do

    ! end function

    ! function change_resolution(mesh_in, resolution) result(mesh_changed)
    !     type(cube_inP3D), intent(in) :: mesh_in(:)
    !     type(cube_inP3D) :: mesh_changed(size(mesh_in))
    !     integer, intent(in) :: resolution   !一辺当たりのセル数
    !     integer i_cube, i,j,k, num_cube, i_max, j_max, k_max, delta_i, delta_j, delta_k
    !     integer ii,jj,kk

    !     num_cube = size(mesh_in)

    !     do i_cube = 1, num_cube
    !         allocate(mesh_changed(i_cube)%nodes(resolution+1, resolution+1, resolution+1))
    !         ! do k = 1, resolution+1
    !         !     do j = 1, resolution+1
    !         !         do i = 1, resolution+1
    !         !             nf = size(mesh_in(i_cube)%nodes(i,j,k)%f(:))
    !         !             allocate(mesh_changed(i_cube)%nodes(i,j,k)%f(nf))
    !         !         end do
    !         !     end do
    !         ! end do
    !     end do

    !     do i_cube = 1, num_cube
    !         i_max = size(mesh_in(i_cube)%nodes(:,:,:), dim=1)
    !         j_max = size(mesh_in(i_cube)%nodes(:,:,:), dim=2)
    !         k_max = size(mesh_in(i_cube)%nodes(:,:,:), dim=3)
    !         delta_i = (i_max - 1) / resolution
    !         delta_j = (j_max - 1) / resolution
    !         delta_k = (k_max - 1) / resolution
    !         kk = 1
    !         do k = 1, k_max, delta_k
    !             jj = 1
    !             do j = 1, j_max, delta_j
    !                 ii = 1
    !                 do i = 1, i_max, delta_i
    !                     mesh_changed(i_cube)%nodes(ii,jj,kk) = mesh_in(i_cube)%nodes(i,j,k)
    !                     ii = ii + 1
    !                 end do
    !                 jj = jj + 1
    !             end do
    !             kk = kk + 1
    !         end do
    !     end do

    ! end function

    ! function extract_function(mesh_in, nf) result(mesh_extracted)
    !     type(cube_inP3D), intent(in) :: mesh_in(:)
    !     type(cube_inP3D) :: mesh_extracted(size(mesh_in))
    !     integer, intent(in) :: nf   !関数の数
    !     integer i_cube, i,j,k, num_cube, i_max, j_max, k_max

    !     num_cube = size(mesh_in)

    !     do i_cube = 1, num_cube
    !         i_max = size(mesh_in(i_cube)%nodes(:,:,:), dim=1)
    !         j_max = size(mesh_in(i_cube)%nodes(:,:,:), dim=2)
    !         k_max = size(mesh_in(i_cube)%nodes(:,:,:), dim=3)
    !         allocate(mesh_extracted(i_cube)%nodes(i_max, j_max, k_max))
    !         do k = 1, k_max
    !             do j = 1, j_max
    !                 do i = 1, i_max
    !                     allocate(mesh_extracted(i_cube)%nodes(i,j,k)%f(nf))
    !                     mesh_extracted(i_cube)%nodes(i,j,k)%f(:) = mesh_in(i_cube)%nodes(i,j,k)%f(:nf)
    !                 end do
    !             end do
    !         end do
    !     end do

    ! end function

    ! function get_center_position(nodes) result(center)
    !     type(node_inCUBE) :: nodes(:,:,:)
    !     real :: center(3)
    !     integer ni,nj,nk,num_nodes

    !     ni = size(nodes(:,:,:), dim=1)
    !     nj = size(nodes(:,:,:), dim=2)
    !     nk = size(nodes(:,:,:), dim=3)

    !     num_nodes = ni * nj * nk
    !     center(1) = sum(nodes(:,:,:)%x)
    !     center(2) = sum(nodes(:,:,:)%y) 
    !     center(3) = sum(nodes(:,:,:)%z)
    !     center(:) = center(:) / num_nodes

    ! end function

    ! real function mean_value(nodes, n_func)
    !     type(node_inCUBE) :: nodes(:,:,:)
    !     integer, intent(in) :: n_func
    !     integer ni,nj,nk,num_nodes, i,j,k

    !     ni = size(nodes(:,:,:), dim=1)
    !     nj = size(nodes(:,:,:), dim=2)
    !     nk = size(nodes(:,:,:), dim=3)

    !     num_nodes = ni * nj * nk

    !     mean_value = 0.0
    !     do k = 1, nk
    !         do j = 1, nj
    !             do i = 1, ni
    !                 mean_value = mean_value+ nodes(i,j,k)%f(n_func)
    !             end do
    !         end do
    !     end do

    !     mean_value = mean_value / num_nodes

    ! end function

    !>メッシュを構成するcube数を返す関数
    integer function get_numCube(self)
        class(Plot3dMesh), intent(in) :: self

        get_numCube = size(self%cubes)

    end function

    !>cubeの形状(i,j,k節点数)を返す関数
    function get_cubeShape(self) result(cubeShape)
        class(Plot3dMesh), intent(in) :: self
        integer shapeArray(4), cubeShape(3)

        shapeArray = shape(self%cubes(1)%nodes)
        cubeShape = shapeArray(1:3)

    end function

    !>任意節点(引数)における流速を返す関数
    function get_velocity(self, node) result(velocity)
        class(Plot3dMesh) self
        type(plot3dNodeInfo), intent(in) :: node
            !!節点
        
        type(cube_inP3D) cube
        real velocity(3)

        cube = self%cubes(node%cubeID)

        !質量流束(第2〜第4成分)を密度(第1成分)で割ることで流速を取得する
        velocity(:) = cube%f(node%nodeID(1),node%nodeID(2),node%nodeID(3), 2:4) &
                        / cube%f(node%nodeID(1),node%nodeID(2),node%nodeID(3), 1)

    end function

end module plot3d_operator