hydraulic_assemble.F90 Source File


This file depends on

sourcefile~~hydraulic_assemble.f90~~EfferentGraph sourcefile~hydraulic_assemble.f90 hydraulic_assemble.F90 sourcefile~calculate.f90 calculate.F90 sourcefile~hydraulic_assemble.f90->sourcefile~calculate.f90 sourcefile~control.f90 control.F90 sourcefile~hydraulic_assemble.f90->sourcefile~control.f90 sourcefile~core.f90 core.F90 sourcefile~hydraulic_assemble.f90->sourcefile~core.f90 sourcefile~domain.f90 domain.F90 sourcefile~hydraulic_assemble.f90->sourcefile~domain.f90 sourcefile~properties.f90 properties.F90 sourcefile~hydraulic_assemble.f90->sourcefile~properties.f90 sourcefile~density_interface.f90 density_interface.F90 sourcefile~calculate.f90->sourcefile~density_interface.f90 sourcefile~gcc_interface.f90 gcc_interface.F90 sourcefile~calculate.f90->sourcefile~gcc_interface.f90 sourcefile~hcf_interface.f90 hcf_interface.F90 sourcefile~calculate.f90->sourcefile~hcf_interface.f90 sourcefile~heat_capacity_interface.f90 heat_capacity_interface.F90 sourcefile~calculate.f90->sourcefile~heat_capacity_interface.f90 sourcefile~linalg.f90 linalg.F90 sourcefile~calculate.f90->sourcefile~linalg.f90 sourcefile~specific_heat_interface.f90 specific_heat_interface.F90 sourcefile~calculate.f90->sourcefile~specific_heat_interface.f90 sourcefile~thermal_conductivity_interface.f90 thermal_conductivity_interface.F90 sourcefile~calculate.f90->sourcefile~thermal_conductivity_interface.f90 sourcefile~control.f90->sourcefile~core.f90 sourcefile~input.f90 input.F90 sourcefile~control.f90->sourcefile~input.f90 sourcefile~iteration.f90 iteration.F90 sourcefile~control.f90->sourcefile~iteration.f90 sourcefile~openmp.f90 openmp.F90 sourcefile~control.f90->sourcefile~openmp.f90 sourcefile~time.f90 time.F90 sourcefile~control.f90->sourcefile~time.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~adjacency.f90 adjacency.F90 sourcefile~domain.f90->sourcefile~adjacency.f90 sourcefile~domain_manager.f90 domain_manager.F90 sourcefile~domain.f90->sourcefile~domain_manager.f90 sourcefile~mesh.f90 mesh.F90 sourcefile~domain.f90->sourcefile~mesh.f90 sourcefile~multicoloring.f90 multicoloring.F90 sourcefile~domain.f90->sourcefile~multicoloring.f90 sourcefile~reordering.f90 reordering.F90 sourcefile~domain.f90->sourcefile~reordering.f90 sourcefile~materials_manager.f90 materials_manager.F90 sourcefile~properties.f90->sourcefile~materials_manager.f90 sourcefile~properties_manager.f90 properties_manager.F90 sourcefile~properties.f90->sourcefile~properties_manager.f90 sourcefile~adjacency_element.f90 adjacency_element.F90 sourcefile~adjacency.f90->sourcefile~adjacency_element.f90 sourcefile~adjacency_node.f90 adjacency_node.F90 sourcefile~adjacency.f90->sourcefile~adjacency_node.f90 sourcefile~adjacency_node_element.f90 adjacency_node_element.F90 sourcefile~adjacency.f90->sourcefile~adjacency_node_element.f90 sourcefile~allocate.f90->sourcefile~error.f90 sourcefile~deallocate.f90->sourcefile~error.f90 sourcefile~density_interface.f90->sourcefile~core.f90 sourcefile~density_interface.f90->sourcefile~input.f90 sourcefile~domain_manager.f90->sourcefile~core.f90 sourcefile~domain_manager.f90->sourcefile~adjacency.f90 sourcefile~domain_manager.f90->sourcefile~input.f90 sourcefile~domain_manager.f90->sourcefile~mesh.f90 sourcefile~domain_manager.f90->sourcefile~multicoloring.f90 sourcefile~domain_manager.f90->sourcefile~reordering.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~gcc_interface.f90->sourcefile~core.f90 sourcefile~gcc_interface.f90->sourcefile~input.f90 sourcefile~hcf_interface.f90->sourcefile~core.f90 sourcefile~hcf_interface.f90->sourcefile~input.f90 sourcefile~heat_capacity_interface.f90->sourcefile~core.f90 sourcefile~heat_capacity_interface.f90->sourcefile~density_interface.f90 sourcefile~input_interface.f90 input_interface.F90 sourcefile~heat_capacity_interface.f90->sourcefile~input_interface.f90 sourcefile~input.f90->sourcefile~input_interface.f90 sourcefile~iteration.f90->sourcefile~calculate.f90 sourcefile~iteration.f90->sourcefile~input.f90 sourcefile~matrix_ops.f90 matrix_ops.F90 sourcefile~linalg.f90->sourcefile~matrix_ops.f90 sourcefile~matvec.f90 matvec.F90 sourcefile~linalg.f90->sourcefile~matvec.f90 sourcefile~vector_ops.f90 vector_ops.F90 sourcefile~linalg.f90->sourcefile~vector_ops.f90 sourcefile~materials_manager.f90->sourcefile~calculate.f90 sourcefile~materials_manager.f90->sourcefile~input.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~multicoloring.f90->sourcefile~core.f90 sourcefile~multicoloring.f90->sourcefile~adjacency_element.f90 sourcefile~openmp.f90->sourcefile~input.f90 sourcefile~properties_manager.f90->sourcefile~calculate.f90 sourcefile~properties_manager.f90->sourcefile~control.f90 sourcefile~properties_manager.f90->sourcefile~core.f90 sourcefile~properties_manager.f90->sourcefile~input.f90 sourcefile~properties_manager.f90->sourcefile~materials_manager.f90 sourcefile~reordering.f90->sourcefile~core.f90 sourcefile~reordering.f90->sourcefile~mesh.f90 sourcefile~reordering.f90->sourcefile~adjacency_node.f90 sourcefile~specific_heat_interface.f90->sourcefile~core.f90 sourcefile~specific_heat_interface.f90->sourcefile~input.f90 sourcefile~string_utils.f90->sourcefile~allocate.f90 sourcefile~thermal_conductivity_interface.f90->sourcefile~core.f90 sourcefile~thermal_conductivity_interface.f90->sourcefile~input.f90 sourcefile~time.f90->sourcefile~core.f90 sourcefile~time.f90->sourcefile~input.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~adjacency_element.f90->sourcefile~core.f90 sourcefile~adjacency_element.f90->sourcefile~mesh.f90 sourcefile~adjacency_node.f90->sourcefile~core.f90 sourcefile~adjacency_node.f90->sourcefile~mesh.f90 sourcefile~adjacency_node_element.f90->sourcefile~mesh.f90 sourcefile~array.f90->sourcefile~allocate.f90 sourcefile~array.f90->sourcefile~deallocate.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~input_interface.f90->sourcefile~core.f90 sourcefile~project_settings.f90 project_settings.F90 sourcefile~input_interface.f90->sourcefile~project_settings.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~matrix_ops.f90->sourcefile~core.f90 sourcefile~matvec.f90->sourcefile~core.f90 sourcefile~c_utils.f90 c_utils.F90 sourcefile~memory_stats_wrapper.f90->sourcefile~c_utils.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~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~element_factory.f90->sourcefile~core.f90 sourcefile~element_factory.f90->sourcefile~input.f90 sourcefile~element_factory.f90->sourcefile~element_interface.f90 sourcefile~element_interface.f90->sourcefile~core.f90 sourcefile~element_interface.f90->sourcefile~input.f90 sourcefile~element_interface.f90->sourcefile~mesh_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~project_settings.f90->sourcefile~core.f90 sourcefile~side_factory.f90->sourcefile~core.f90 sourcefile~side_factory.f90->sourcefile~input.f90 sourcefile~side_factory.f90->sourcefile~side_interface.f90 sourcefile~side_interface.f90->sourcefile~core.f90 sourcefile~side_interface.f90->sourcefile~input.f90 sourcefile~side_interface.f90->sourcefile~mesh_interface.f90

Files dependent on this one

sourcefile~~hydraulic_assemble.f90~~AfferentGraph sourcefile~hydraulic_assemble.f90 hydraulic_assemble.F90 sourcefile~hydraulic_interface.f90 hydraulic_interface.F90 sourcefile~hydraulic_interface.f90->sourcefile~hydraulic_assemble.f90 sourcefile~hydraulic.f90 hydraulic.F90 sourcefile~hydraulic.f90->sourcefile~hydraulic_interface.f90 sourcefile~hydraulic_crs.f90 hydraulic_crs.F90 sourcefile~hydraulic_crs.f90->sourcefile~hydraulic_interface.f90 sourcefile~ftdss.f90 ftdss.F90 sourcefile~ftdss.f90->sourcefile~hydraulic.f90

Source Code

module hydraulic_hydraulic_assemble
    use, intrinsic :: iso_fortran_env, only: int32, real64
!$  use omp_lib
    use :: module_core, only:type_state, type_dp_vector_3d, assignment(=), type_variable, allocate_array, deallocate_array, type_crs, type_dense
    use :: module_domain, only:type_domain, abst_mesh
    use :: module_properties, only:type_properties_manager
    use :: module_calculate, only:gemv, add
    use :: module_control

    implicit none
    private

    public :: abst_assemble_global_hydraulic

    public :: hydraulic_assemble_system_linear_1, hydraulic_assemble_system_linear_1_parallel

    abstract interface
        subroutine abst_assemble_global_hydraulic(J, R, domain, pressure, temperature, ice, porosity, &
                                                  properties, controls, actual_order)
            import :: type_crs, type_domain, type_properties_manager, type_variable, type_controls, int32, real64
            implicit none
            type(type_crs), intent(inout) :: J
            real(real64), intent(inout) :: R(:)
            type(type_domain), intent(inout), target :: domain
            type(type_variable), intent(in) :: pressure
            type(type_variable), intent(in) :: temperature
            type(type_variable), intent(in) :: ice
            type(type_variable), intent(in) :: porosity
            type(type_properties_manager), intent(in) :: properties
            type(type_controls), intent(in) :: controls
            integer(int32), intent(in) :: actual_order
        end subroutine abst_assemble_global_hydraulic
    end interface
contains

    ! subroutine process_element_hydraulic_linear_1(J, R, element, pressure, temperature, ice, porosity, &
    !                                               properties, controls, actual_order)
    !     implicit none
    !     ! --- 引数 ---
    !     type(type_crs), intent(inout) :: J
    !     real(real64), intent(inout) :: R(:)
    !     class(abst_element), intent(in), pointer :: element
    !     type(type_variable), intent(in) :: pressure
    !     type(type_variable), intent(in) :: temperature
    !     type(type_variable), intent(in) :: ice
    !     type(type_variable), intent(in) :: porosity
    !     type(type_properties_manager), intent(in) :: properties
    !     type(type_controls), intent(in) :: controls
    !     integer(int32), intent(in) :: actual_order

    !     ! --- ローカル変数 ---
    !     integer(int32) :: index, num_nodes, num_gauss, material_id, il, jl, iG, iO
    !     real(real64) :: weight, detJ
    !     real(real64) :: dNdx_i, dNdy_i, dNdx_j, dNdy_j
    !     real(real64) :: val, zeta
    !     real(real64) :: dt

    !     ! --- スタック上のワークスペース (自動配列) ---
    !     real(real64) :: CH_e(element%get_num_nodes(), element%get_num_nodes())
    !     real(real64) :: KH_e(element%get_num_nodes(), element%get_num_nodes())
    !     real(real64) :: J_e(element%get_num_nodes(), element%get_num_nodes())
    !     real(real64) :: R_e(element%get_num_nodes())

    !     ! --- ガウスポイントでの物理量 (自動配列) ---
    !     type(type_state) :: state(element%get_num_gauss())
    !     real(real64) :: kflh(element%get_num_gauss())
    !     real(real64) :: dot_ice(element%get_num_gauss())

    !     !---------------------------------------------------------------------------------------------------------------------------
    !     ! STEP 0: 初期化とサイズの取得
    !     !---------------------------------------------------------------------------------------------------------------------------
    !     num_nodes   = element%get_num_nodes() !&
    !     num_gauss   = element%get_num_gauss() !&
    !     material_id = element%get_group() !&
    !     if (.not. controls%is_target(calc_hydraulic, material_id)) return

    !     CH_e(:, :) = 0.0d0
    !     KH_e(:, :) = 0.0d0

    !     !---------------------------------------------------------------------------------------------------------------------------
    !     ! STEP 1: 全ガウスポイントの物理量を一括計算
    !     !---------------------------------------------------------------------------------------------------------------------------
    !     do iG = 1, num_gauss
    !         state(iG)%temperature = element%lerp(gauss(iG), temperature%pre) !&
    !         state(iG)%pressure    = element%lerp(gauss(iG), pressure%pre) !&
    !         state(iG)%porosity    = element%lerp(gauss(iG), porosity%pre) !&
    !     end do
    !     call properties%calc_hydraulic(material_id, state, kflh)

    !     dt = controls%time%get_dt()
    !     dot_ice(:) = 0.0d0
    !     do il = 1, num_nodes
    !         dot_ice(il) = ice%dif(p_conn(il)) / dt
    !     end do

    !     !---------------------------------------------------------------------------------------------------------------------------
    !     ! STEP 2: 要素行列 CH_e と KH_e を計算
    !     !---------------------------------------------------------------------------------------------------------------------------
    !     do iG = 1, num_gauss
    !         weight = element%weight(iG)
    !         detJ = element%jacobian_det(gauss(iG))
    !         zeta = state(iG)%density_ice / state(iG)%density_water - 1.0d0
    !         do il = 1, num_nodes
    !             dNdx_i = ( element%jacobian(2, 2,p_gauss(iG)) * element%dpsi (il,1,p_gauss(iG)) - & !&
    !                        element%jacobian(2, 1,p_gauss(iG)) * element%dpsi(il,2,p_gauss(iG))) / detJ !&
    !             dNdy_i = (-element%jacobian(1, 2,p_gauss(iG)) * element%dpsi (il,1,p_gauss(iG)) + & !&
    !                        element%jacobian(1, 1,p_gauss(iG)) * element%dpsi(il,2,p_gauss(iG))) / detJ !&
    !             do jl = 1, num_nodes
    !                 dNdx_j = ( element%jacobian(2, 2,p_gauss(iG)) * element%dpsi (jl,1,p_gauss(iG)) - & !&
    !                            element%jacobian(2, 1,p_gauss(iG)) * element%dpsi(jl,2,p_gauss(iG))) / detJ !&
    !                 dNdy_j = (-element%jacobian(1, 2,p_gauss(iG)) * element%dpsi (jl,1,p_gauss(iG)) + & !&
    !                            element%jacobian(1, 1,p_gauss(iG)) * element%dpsi(jl,2,p_gauss(iG))) / detJ !&

    !                 CH_e(il, jl) = CH_e(il, jl) + element%psi(il,p_gauss(iG)) * & !&
    !                                               element%psi(jl,p_gauss(iG)) * zeta * weight * detJ
    !                 KH_e(il, jl) = KH_e(il, jl) + (dNdx_i * dNdx_j + dNdy_i * dNdy_j) * kflh(iG) * weight * detJ
    !             end do
    !         end do
    !     end do

    !     !---------------------------------------------------------------------------------------------------------------------------
    !     ! STEP 3: 最終的な LHS(J_e) と RHS(R_e) を構築
    !     !---------------------------------------------------------------------------------------------------------------------------
    !     ! --- 3a. LHS行列 J_e の構築 (物理的に正しい式) ---
    !     J_e(:, :) = 0.0d0
    !     do jl = 1, num_nodes
    !         do il = 1, num_nodes
    !             J_e(il, jl) = KH_e(il, jl)
    !         end do
    !     end do

    !     do il = 1, num_nodes
    !         val = 0.0d0
    !         do jl = 1, num_nodes
    !             val = val + CH_e(il, jl) * dot_ice(jl)
    !         end do
    !         R_e(il) = -val
    !     end do

    !     !---------------------------------------------------------------------------------------------------------------------------
    !     ! STEP 4: 全体行列・ベクトルへのアセンブル (数学的に正しい標準手順)
    !     !---------------------------------------------------------------------------------------------------------------------------
    !     do il = 1, num_nodes
    !         R(p_conn(il)) = R(p_conn(il)) + R_e(il)
    !         do jl = 1, num_nodes
    !             call J%add(p_conn(il), p_conn(jl), J_e(il, jl))
    !         end do
    !     end do

    ! end subroutine process_element_hydraulic_linear_1

    subroutine process_element_hydraulic_linear_1(J, R, element, pressure, temperature, ice, porosity, &
                                                  properties, controls, actual_order)
        implicit none
        ! --- arguments ---
        type(type_crs), intent(inout) :: J
        real(real64), intent(inout) :: R(:)
        class(abst_mesh), intent(in), pointer :: element
        type(type_variable), intent(in) :: pressure
        type(type_variable), intent(in) :: temperature
        type(type_variable), intent(in) :: ice
        type(type_variable), intent(in) :: porosity
        type(type_properties_manager), intent(in) :: properties
        type(type_controls), intent(in) :: controls
        integer(int32), intent(in) :: actual_order

        ! --- Local variables ---
        integer(int32) :: index, num_nodes, num_gauss, material_id, il, jl, iG, iO
        real(real64) :: weight, detJ
        real(real64) :: dNdx_i, dNdy_i, dNdx_j, dNdy_j
        real(real64) :: val, zeta
        real(real64) :: dt

        ! --- Workspace variables ---
        type(type_dense) :: CH_e
        type(type_dense) :: KH_e
        type(type_dense) :: J_e
        real(real64), allocatable :: R_e(:)

        ! --- Physical quantities at Gauss points ---
        type(type_state), allocatable :: state(:)
        real(real64), dimension(:), pointer :: p_weight => null()
        type(type_dp_vector_3d), dimension(:), pointer :: p_gauss => null()
        real(real64), allocatable :: kflh(:)
        real(real64), allocatable :: dot_ice(:)
        integer(int32), dimension(:), pointer :: p_conn => null()

        !---------------------------------------------------------------------------------------------------------------------------
        ! STEP 0: Initialize and obtain sizes
        !---------------------------------------------------------------------------------------------------------------------------
        num_nodes   = element%get_num_nodes() !&
        num_gauss   = element%get_num_gauss() !&
        material_id = element%get_group() !&
        if (.not. controls%is_target(calc_hydraulic, material_id)) return

        call CH_e%initialize_local(num_nodes)
        call KH_e%initialize_local(num_nodes)
        call J_e%initialize_local(num_nodes)
        call allocate_array(R_e, num_nodes)
        allocate (state(num_gauss))
        call allocate_array(kflh, num_gauss)
        call allocate_array(dot_ice, num_nodes)

        dt = controls%time%get_dt()
        p_weight => element%get_weight()
        p_gauss => element%get_gauss()
        p_conn => element%get_connectivity()

        !---------------------------------------------------------------------------------------------------------------------------
        ! STEP 1: Compute the physical quantities at all Gauss points
        !---------------------------------------------------------------------------------------------------------------------------
        do iG = 1, num_gauss
            state(iG)%temperature = element%lerp(p_gauss(iG), temperature%pre) !&
            state(iG)%pressure    = element%lerp(p_gauss(iG), pressure%pre) !&
            state(iG)%porosity    = element%lerp(p_gauss(iG), porosity%pre) !&
        end do
        call properties%calc_hydraulic(material_id, state, kflh)

        do il = 1, num_nodes
            dot_ice(il) = ice%dif(p_conn(il)) / dt
        end do

        !---------------------------------------------------------------------------------------------------------------------------
        ! STEP 2: Compute the element matrices CH_e and KH_e
        !---------------------------------------------------------------------------------------------------------------------------
        do iG = 1, num_gauss
            weight = p_weight(iG) !&
            detJ   = element%jacobian_det(p_gauss(iG)) !&
            zeta   = state(iG)%density_ice / state(iG)%density_water - 1.0d0 !&
            do il = 1, num_nodes
                dNdx_i = ( element%jacobian(2, 2, p_gauss(iG)) * element%dpsi(il, 1, p_gauss(iG)) - & !&
                           element%jacobian(2, 1, p_gauss(iG)) * element%dpsi(il, 2, p_gauss(iG))) / detJ !&
                dNdy_i = (-element%jacobian(1, 2, p_gauss(iG)) * element%dpsi(il, 1, p_gauss(iG)) + & !&
                           element%jacobian(1, 1, p_gauss(iG)) * element%dpsi(il, 2, p_gauss(iG))) / detJ !&
                do jl = 1, num_nodes
                    dNdx_j = ( element%jacobian(2, 2, p_gauss(iG)) * element%dpsi(jl, 1, p_gauss(iG)) - & !&
                               element%jacobian(2, 1, p_gauss(iG)) * element%dpsi(jl, 2, p_gauss(iG))) / detJ !&
                    dNdy_j = (-element%jacobian(1, 2, p_gauss(iG)) * element%dpsi(jl, 1, p_gauss(iG)) + & !&
                               element%jacobian(1, 1, p_gauss(iG)) * element%dpsi(jl, 2, p_gauss(iG))) / detJ !&

                    val = element%psi(il, p_gauss(iG)) * element%psi(jl, p_gauss(iG)) * zeta * weight * detJ
                    call CH_e%add(il, jl, val)
                    val = (dNdx_i * dNdx_j + dNdy_i * dNdy_j) * kflh(iG) * weight * detJ
                    call KH_e%add(il, jl, val)
                end do
            end do
        end do

        !---------------------------------------------------------------------------------------------------------------------------
        ! STEP 3: Build the final local matrix (J_e) and vector (R_e)
        !---------------------------------------------------------------------------------------------------------------------------
        call add(0.0d0, KH_e, CH_e, J_e)
        call gemv(-1.0d0, CH_e, dot_ice, 0.0d0, R_e)

        !---------------------------------------------------------------------------------------------------------------------------
        ! STEP 4: Assemble the global matrix and vector
        !---------------------------------------------------------------------------------------------------------------------------
        do il = 1, num_nodes
            R(p_conn(il)) = R(p_conn(il)) + R_e(il)
            do jl = 1, num_nodes
                call J%add(p_conn(il), p_conn(jl), J_e%val(il, jl))
            end do
        end do

        !---------------------------------------------------------------------------------------------------------------------------
        ! STEP 5: Finalization
        !---------------------------------------------------------------------------------------------------------------------------
        call deallocate_array(kflh)
        call deallocate_array(R_e)
        call J_e%destroy()
        call KH_e%destroy()
        call CH_e%destroy()
        deallocate (state)

    end subroutine process_element_hydraulic_linear_1

    subroutine hydraulic_assemble_system_linear_1(J, R, domain, pressure, temperature, porosity, ice, &
                                                  properties, controls, actual_order)
        implicit none
        type(type_crs), intent(inout) :: J
        real(real64), intent(inout) :: R(:)
        type(type_domain), intent(inout), target :: domain
        type(type_variable), intent(in) :: pressure
        type(type_variable), intent(in) :: temperature
        type(type_variable), intent(in) :: ice
        type(type_variable), intent(in) :: porosity
        type(type_properties_manager), intent(in) :: properties
        type(type_controls), intent(in) :: controls
        integer(int32), intent(in) :: actual_order

        class(abst_mesh), pointer :: element
        integer(int32) :: iE, num_elements

        num_elements = domain%get_num_elements()
        call J%set_all(0.0d0)
        R(:) = 0.0d0

        do iE = 1, num_elements
            element => domain%elements(iE)%e
            call process_element_hydraulic_linear_1(J, R, element, pressure, temperature, porosity, ice, &
                                                    properties, controls, actual_order)
        end do
    end subroutine hydraulic_assemble_system_linear_1

    subroutine hydraulic_assemble_system_linear_1_parallel(J, R, domain, pressure, temperature, porosity, ice, &
                                                           properties, controls, actual_order)
        implicit none
        type(type_crs), intent(inout) :: J
        real(real64), intent(inout) :: R(:)
        type(type_domain), intent(inout), target :: domain
        type(type_variable), intent(in) :: pressure
        type(type_variable), intent(in) :: temperature
        type(type_variable), intent(in) :: ice
        type(type_variable), intent(in) :: porosity
        type(type_properties_manager), intent(in) :: properties
        type(type_controls), intent(in) :: controls
        integer(int32), intent(in) :: actual_order

        integer(int32) :: c, ie_idx
        class(abst_mesh), pointer :: element

        call J%set_all(0.0d0)
        R(:) = 0.0d0

        !$omp parallel private(c, ie_idx, element)
        do c = 1, domain%colors%num_colors
            !$omp do
            do ie_idx = 1, domain%colors%colored(c)%num_elements
                element => domain%elements(domain%colors%colored(c)%elements(ie_idx))%e
                call process_element_hydraulic_linear_1(J, R, element, pressure, temperature, porosity, ice, &
                                                        properties, controls, actual_order)
            end do
            !$omp end do
        end do
        !$omp end parallel
    end subroutine hydraulic_assemble_system_linear_1_parallel
end module hydraulic_hydraulic_assemble