adjacency_element.F90 Source File


This file depends on

sourcefile~~adjacency_element.f90~~EfferentGraph sourcefile~adjacency_element.f90 adjacency_element.F90 sourcefile~core.f90 core.F90 sourcefile~adjacency_element.f90->sourcefile~core.f90 sourcefile~mesh.f90 mesh.F90 sourcefile~adjacency_element.f90->sourcefile~mesh.f90 sourcefile~allocate.f90 allocate.F90 sourcefile~core.f90->sourcefile~allocate.f90 sourcefile~check_range.f90 check_range.F90 sourcefile~core.f90->sourcefile~check_range.f90 sourcefile~deallocate.f90 deallocate.F90 sourcefile~core.f90->sourcefile~deallocate.f90 sourcefile~error.f90 error.F90 sourcefile~core.f90->sourcefile~error.f90 sourcefile~fortran_utils.f90 fortran_utils.F90 sourcefile~core.f90->sourcefile~fortran_utils.f90 sourcefile~string_utils.f90 string_utils.F90 sourcefile~core.f90->sourcefile~string_utils.f90 sourcefile~types.f90 types.F90 sourcefile~core.f90->sourcefile~types.f90 sourcefile~unique.f90 unique.F90 sourcefile~core.f90->sourcefile~unique.f90 sourcefile~vtk.f90 vtk.F90 sourcefile~core.f90->sourcefile~vtk.f90 sourcefile~vtk_constants.f90 vtk_constants.F90 sourcefile~core.f90->sourcefile~vtk_constants.f90 sourcefile~element.f90 element.F90 sourcefile~mesh.f90->sourcefile~element.f90 sourcefile~mesh_interface.f90 mesh_interface.F90 sourcefile~mesh.f90->sourcefile~mesh_interface.f90 sourcefile~side.f90 side.F90 sourcefile~mesh.f90->sourcefile~side.f90 sourcefile~allocate.f90->sourcefile~error.f90 sourcefile~deallocate.f90->sourcefile~error.f90 sourcefile~element_factory.f90 element_factory.F90 sourcefile~element.f90->sourcefile~element_factory.f90 sourcefile~element_interface.f90 element_interface.F90 sourcefile~element.f90->sourcefile~element_interface.f90 sourcefile~memory_stats_wrapper.f90 memory_stats_wrapper.F90 sourcefile~fortran_utils.f90->sourcefile~memory_stats_wrapper.f90 sourcefile~signal_flag_wrapper.f90 signal_flag_wrapper.F90 sourcefile~fortran_utils.f90->sourcefile~signal_flag_wrapper.f90 sourcefile~system_info_wrapper.f90 system_info_wrapper.F90 sourcefile~fortran_utils.f90->sourcefile~system_info_wrapper.f90 sourcefile~mesh_interface.f90->sourcefile~core.f90 sourcefile~side_factory.f90 side_factory.F90 sourcefile~side.f90->sourcefile~side_factory.f90 sourcefile~side_interface.f90 side_interface.F90 sourcefile~side.f90->sourcefile~side_interface.f90 sourcefile~string_utils.f90->sourcefile~allocate.f90 sourcefile~array.f90 array.F90 sourcefile~types.f90->sourcefile~array.f90 sourcefile~gauss.f90 gauss.F90 sourcefile~types.f90->sourcefile~gauss.f90 sourcefile~matrix.f90 matrix.F90 sourcefile~types.f90->sourcefile~matrix.f90 sourcefile~pointer.f90 pointer.F90 sourcefile~types.f90->sourcefile~pointer.f90 sourcefile~variable.f90 variable.F90 sourcefile~types.f90->sourcefile~variable.f90 sourcefile~vector.f90 vector.F90 sourcefile~types.f90->sourcefile~vector.f90 sourcefile~unique.f90->sourcefile~allocate.f90 sourcefile~vtk.f90->sourcefile~allocate.f90 sourcefile~vtk.f90->sourcefile~deallocate.f90 sourcefile~vtk.f90->sourcefile~types.f90 sourcefile~vtk.f90->sourcefile~unique.f90 sourcefile~vtk.f90->sourcefile~vtk_constants.f90 sourcefile~vtk_wrapper.f90 vtk_wrapper.F90 sourcefile~vtk.f90->sourcefile~vtk_wrapper.f90 sourcefile~vtu_wrapper.f90 vtu_wrapper.F90 sourcefile~vtk.f90->sourcefile~vtu_wrapper.f90 sourcefile~array.f90->sourcefile~allocate.f90 sourcefile~array.f90->sourcefile~deallocate.f90 sourcefile~element_factory.f90->sourcefile~core.f90 sourcefile~element_factory.f90->sourcefile~element_interface.f90 sourcefile~input.f90 input.F90 sourcefile~element_factory.f90->sourcefile~input.f90 sourcefile~element_interface.f90->sourcefile~core.f90 sourcefile~element_interface.f90->sourcefile~mesh_interface.f90 sourcefile~element_interface.f90->sourcefile~input.f90 sourcefile~matrix_coo.f90 matrix_coo.F90 sourcefile~matrix.f90->sourcefile~matrix_coo.f90 sourcefile~matrix_crs.f90 matrix_crs.F90 sourcefile~matrix.f90->sourcefile~matrix_crs.f90 sourcefile~matrix_dense.f90 matrix_dense.F90 sourcefile~matrix.f90->sourcefile~matrix_dense.f90 sourcefile~matrix_interface.f90 matrix_interface.F90 sourcefile~matrix.f90->sourcefile~matrix_interface.f90 sourcefile~c_utils.f90 c_utils.F90 sourcefile~memory_stats_wrapper.f90->sourcefile~c_utils.f90 sourcefile~side_factory.f90->sourcefile~core.f90 sourcefile~side_factory.f90->sourcefile~side_interface.f90 sourcefile~side_factory.f90->sourcefile~input.f90 sourcefile~side_interface.f90->sourcefile~core.f90 sourcefile~side_interface.f90->sourcefile~mesh_interface.f90 sourcefile~side_interface.f90->sourcefile~input.f90 sourcefile~signal_flag.f90 signal_flag.F90 sourcefile~signal_flag_wrapper.f90->sourcefile~signal_flag.f90 sourcefile~system_info_wrapper.f90->sourcefile~c_utils.f90 sourcefile~variable.f90->sourcefile~allocate.f90 sourcefile~c_utils.f90->sourcefile~signal_flag.f90 sourcefile~memory_stats.f90 memory_stats.F90 sourcefile~c_utils.f90->sourcefile~memory_stats.f90 sourcefile~system_info.f90 system_info.F90 sourcefile~c_utils.f90->sourcefile~system_info.f90 sourcefile~input_interface.f90 input_interface.F90 sourcefile~input.f90->sourcefile~input_interface.f90 sourcefile~matrix_coo.f90->sourcefile~allocate.f90 sourcefile~matrix_coo.f90->sourcefile~deallocate.f90 sourcefile~matrix_coo.f90->sourcefile~matrix_interface.f90 sourcefile~matrix_crs.f90->sourcefile~allocate.f90 sourcefile~matrix_crs.f90->sourcefile~deallocate.f90 sourcefile~matrix_crs.f90->sourcefile~matrix_interface.f90 sourcefile~matrix_dense.f90->sourcefile~allocate.f90 sourcefile~matrix_dense.f90->sourcefile~deallocate.f90 sourcefile~matrix_dense.f90->sourcefile~matrix_interface.f90 sourcefile~input_interface.f90->sourcefile~core.f90 sourcefile~project_settings.f90 project_settings.F90 sourcefile~input_interface.f90->sourcefile~project_settings.f90 sourcefile~project_settings.f90->sourcefile~core.f90

Files dependent on this one

sourcefile~~adjacency_element.f90~~AfferentGraph sourcefile~adjacency_element.f90 adjacency_element.F90 sourcefile~adjacency.f90 adjacency.F90 sourcefile~adjacency.f90->sourcefile~adjacency_element.f90 sourcefile~multicoloring.f90 multicoloring.F90 sourcefile~multicoloring.f90->sourcefile~adjacency_element.f90 sourcefile~domain.f90 domain.F90 sourcefile~domain.f90->sourcefile~adjacency.f90 sourcefile~domain.f90->sourcefile~multicoloring.f90 sourcefile~domain_manager.f90 domain_manager.F90 sourcefile~domain.f90->sourcefile~domain_manager.f90 sourcefile~domain_manager.f90->sourcefile~adjacency.f90 sourcefile~domain_manager.f90->sourcefile~multicoloring.f90 sourcefile~dsatur.f90 dsatur.F90 sourcefile~dsatur.f90->sourcefile~multicoloring.f90 sourcefile~lfo.f90 lfo.F90 sourcefile~lfo.f90->sourcefile~multicoloring.f90 sourcefile~welch_powell.f90 welch_powell.F90 sourcefile~welch_powell.f90->sourcefile~multicoloring.f90 sourcefile~boundary_interface.f90 boundary_interface.F90 sourcefile~boundary_interface.f90->sourcefile~domain.f90 sourcefile~boundary_manager.f90 boundary_manager.F90 sourcefile~boundary_manager.f90->sourcefile~domain.f90 sourcefile~boundary_manager.f90->sourcefile~boundary_interface.f90 sourcefile~ftdss.f90 ftdss.F90 sourcefile~ftdss.f90->sourcefile~domain.f90 sourcefile~boundary.f90 boundary.F90 sourcefile~ftdss.f90->sourcefile~boundary.f90 sourcefile~hydraulic.f90 hydraulic.F90 sourcefile~ftdss.f90->sourcefile~hydraulic.f90 sourcefile~initial.f90 initial.F90 sourcefile~ftdss.f90->sourcefile~initial.f90 sourcefile~output.f90 output.F90 sourcefile~ftdss.f90->sourcefile~output.f90 sourcefile~thermal.f90 thermal.F90 sourcefile~ftdss.f90->sourcefile~thermal.f90 sourcefile~hydraulic_assemble.f90 hydraulic_assemble.F90 sourcefile~hydraulic_assemble.f90->sourcefile~domain.f90 sourcefile~hydraulic_interface.f90 hydraulic_interface.F90 sourcefile~hydraulic_interface.f90->sourcefile~domain.f90 sourcefile~hydraulic_interface.f90->sourcefile~hydraulic_assemble.f90 sourcefile~hydraulic_interface.f90->sourcefile~boundary.f90 sourcefile~initial_interface.f90 initial_interface.F90 sourcefile~initial_interface.f90->sourcefile~domain.f90 sourcefile~initial_interface.f90->sourcefile~boundary.f90 sourcefile~initial_manager.f90 initial_manager.F90 sourcefile~initial_manager.f90->sourcefile~domain.f90 sourcefile~initial_manager.f90->sourcefile~initial_interface.f90 sourcefile~output_interface.f90 output_interface.F90 sourcefile~output_interface.f90->sourcefile~domain.f90 sourcefile~thermal_interface.f90 thermal_interface.F90 sourcefile~thermal_interface.f90->sourcefile~domain.f90 sourcefile~thermal_interface.f90->sourcefile~boundary.f90 sourcefile~boundary.f90->sourcefile~boundary_interface.f90 sourcefile~boundary.f90->sourcefile~boundary_manager.f90 sourcefile~boundary_adiabatic.f90 boundary_adiabatic.F90 sourcefile~boundary_adiabatic.f90->sourcefile~boundary_interface.f90 sourcefile~boundary_base.f90 boundary_base.F90 sourcefile~boundary_base.f90->sourcefile~boundary_interface.f90 sourcefile~boundary_dirichlet.f90 boundary_dirichlet.F90 sourcefile~boundary_dirichlet.f90->sourcefile~boundary_interface.f90 sourcefile~hydraulic.f90->sourcefile~hydraulic_interface.f90 sourcefile~hydraulic_crs.f90 hydraulic_crs.F90 sourcefile~hydraulic_crs.f90->sourcefile~hydraulic_interface.f90 sourcefile~initial.f90->sourcefile~initial_interface.f90 sourcefile~initial.f90->sourcefile~initial_manager.f90 sourcefile~initial_laplace.f90 initial_laplace.F90 sourcefile~initial_laplace.f90->sourcefile~initial_interface.f90 sourcefile~initial_uniform.f90 initial_uniform.F90 sourcefile~initial_uniform.f90->sourcefile~initial_interface.f90 sourcefile~output.f90->sourcefile~output_interface.f90 sourcefile~output_base.f90 output_base.F90 sourcefile~output_base.f90->sourcefile~output_interface.f90 sourcefile~output_observation.f90 output_observation.F90 sourcefile~output_observation.f90->sourcefile~output_interface.f90 sourcefile~output_overall_base.f90 output_overall_base.F90 sourcefile~output_overall_base.f90->sourcefile~output_interface.f90 sourcefile~output_overall_vtk.f90 output_overall_vtk.F90 sourcefile~output_overall_vtk.f90->sourcefile~output_interface.f90 sourcefile~output_overall_vtu.f90 output_overall_vtu.F90 sourcefile~output_overall_vtu.f90->sourcefile~output_interface.f90 sourcefile~output_system_logger.f90 output_system_logger.F90 sourcefile~output_system_logger.f90->sourcefile~output_interface.f90 sourcefile~thermal.f90->sourcefile~thermal_interface.f90 sourcefile~thermal_crs.f90 thermal_crs.F90 sourcefile~thermal_crs.f90->sourcefile~thermal_interface.f90

Source Code

module domain_adjacency_adjacency_element
    use, intrinsic :: iso_fortran_env, only: int32
    use :: module_core, only:allocate_array, deallocate_array
    use :: module_mesh, only:abst_element, holder_elements
    implicit none
    private

    public :: type_crs_adjacency_element

    !============================================================
    ! CRS形式の隣接行列を格納する型
    !============================================================
    type :: type_crs_adjacency_element
        private
        integer(int32) :: nnz = 0
        integer(int32) :: num_row = 0
        integer(int32), allocatable :: ptr(:)
        integer(int32), allocatable :: ind(:)
    contains
        procedure, pass(self), public :: initialize => initialize_crs_adjacency
        procedure, pass(self), public :: get_num_elements => get_num_elements_impl
        procedure, pass(self), public :: get_degree => get_degree_impl
        procedure, pass(self), public :: get_neighbors => get_neighbors_impl
    end type type_crs_adjacency_element

contains

    !============================================================
    ! メインの初期化サブルーチン
    !============================================================
    subroutine initialize_crs_adjacency(self, elements)
        class(type_crs_adjacency_element), intent(inout) :: self
        type(holder_elements), intent(in) :: elements(:)

        integer(int32) :: num_elements
        integer(int32) :: i, j
        integer(int32) :: pair_count, capacity
        integer(int32), allocatable :: coo_row(:), coo_col(:), temp_row(:), temp_col(:)

        num_elements = size(elements)
        self%num_row = num_elements
        if (num_elements <= 1) return

        ! --- Step 1 & 2: 隣接ペアを全探索で探し、一時的なCOO形式で格納 ---
        pair_count = 0
        capacity = num_elements * 5
        call allocate_array(coo_row, length=capacity)
        call allocate_array(coo_col, length=capacity)

        do i = 1, num_elements
            do j = i + 1, num_elements
                if (are_elements_adjacent(elements(i)%e, elements(j)%e)) then
                    if ((pair_count + 2) > capacity) then
                        capacity = capacity * 2
                        call allocate_array(temp_row, length=capacity)
                        call allocate_array(temp_col, length=capacity)
                        temp_row(1:pair_count) = coo_row(1:pair_count)
                        temp_col(1:pair_count) = coo_col(1:pair_count)

                        call deallocate_array(coo_row)
                        call deallocate_array(coo_col)

                        call move_alloc(temp_row, coo_row)
                        call move_alloc(temp_col, coo_col)
                    end if

                    pair_count = pair_count + 1
                    coo_row(pair_count) = i
                    coo_col(pair_count) = j

                    pair_count = pair_count + 1
                    coo_row(pair_count) = j
                    coo_col(pair_count) = i
                end if
            end do
        end do

        self%nnz = pair_count

        ! --- Step 3: COO形式からCRS形式へ変換 ---
        call allocate_array(self%ptr, length=self%num_row + 1_int32)
        call allocate_array(self%ind, length=self%nnz)
        self%ptr = 0

        ! Pass 1: 各行の非ゼロ要素数(次数)をカウント
        do i = 1, self%nnz
            self%ptr(coo_row(i) + 1) = self%ptr(coo_row(i) + 1) + 1
        end do

        ! Pass 2: 累積和を計算して、ptr配列を完成させる
        self%ptr(1) = 1
        do i = 2, self%num_row + 1
            self%ptr(i) = self%ptr(i) + self%ptr(i - 1)
        end do

        ! Pass 3: ind配列を構築する
        call allocate_array(temp_row, length=self%num_row)
        temp_row(:) = self%ptr(1:self%num_row)

        do i = 1, self%nnz
            j = temp_row(coo_row(i))
            self%ind(j) = coo_col(i)
            temp_row(coo_row(i)) = j + 1
        end do

        call deallocate_array(temp_row)

        call deallocate_array(coo_row)
        call deallocate_array(coo_col)

    end subroutine initialize_crs_adjacency

    !============================================================
    ! 2つの要素が隣接しているか判定する private logical 関数
    ! (この関数は変更なし)
    !============================================================
    function are_elements_adjacent(elem1, elem2) result(is_adjacent)
        class(abst_element), intent(in) :: elem1, elem2
        logical :: is_adjacent
        integer(int32) :: i, j
        integer(int32) :: num_nodes1, num_nodes2
        integer(int32), dimension(:), pointer :: ptr_conn1 => null()
        integer(int32), dimension(:), pointer :: ptr_conn2 => null()

        is_adjacent = .false.
        num_nodes1 = elem1%get_num_nodes()
        num_nodes2 = elem2%get_num_nodes()

        ptr_conn1 => elem1%get_connectivity()
        ptr_conn2 => elem2%get_connectivity()

        do i = 1, num_nodes1
            do j = 1, num_nodes2
                if (ptr_conn1(i) == ptr_conn2(j)) then
                    is_adjacent = .true.
                    return
                end if
            end do
        end do
    end function are_elements_adjacent

    !============================================================
    ! Getter: 要素数を返す
    !============================================================
    function get_num_elements_impl(self) result(num_row)
        implicit none
        class(type_crs_adjacency_element), intent(in) :: self
        integer(int32) :: num_row

        num_row = self%num_row
    end function get_num_elements_impl

    !============================================================
    ! Getter: 指定した要素の次数を返す
    !============================================================
    function get_degree_impl(self, i) result(degree)
        implicit none
        class(type_crs_adjacency_element), intent(in) :: self
        integer(int32), intent(in) :: i
        integer(int32) :: degree

        if (i < 1 .or. i > self%num_row) then
            degree = 0
        else
            degree = self%ptr(i + 1) - self%ptr(i)
        end if
    end function get_degree_impl

    !============================================================
    ! ★★★ Getter: 指定した要素の隣接要素リストを返す (新規追加) ★★★
    !============================================================
    function get_neighbors_impl(self, i) result(neighbors)
        implicit none
        class(type_crs_adjacency_element), intent(in) :: self
        integer(int32), intent(in) :: i
        integer(int32), allocatable :: neighbors(:)

        integer(int32) :: start_p, end_p, num_neighbors

        if (i < 1 .or. i > self%num_row) then
            ! 範囲外の場合はサイズ0の配列を返す
            call allocate_array(neighbors, length=0_int32)
            return
        end if

        start_p = self%ptr(i)
        end_p = self%ptr(i + 1) - 1
        num_neighbors = end_p - start_p + 1

        if (num_neighbors > 0) then
            call allocate_array(neighbors, length=num_neighbors)
            neighbors = self%ind(start_p:end_p)
        else
            call allocate_array(neighbors, length=0_int32)
        end if
    end function get_neighbors_impl

end module domain_adjacency_adjacency_element