From fd60bb8d7fc05a851575627349fff0628261d87d Mon Sep 17 00:00:00 2001 From: Stack-1 Date: Fri, 12 Jun 2026 20:24:06 +0200 Subject: [PATCH] [UPDATE] User-friendly row queries on the nested matrix Add get_owned_rows(i_field) and get_owned_row_count(i_field) to psb_d_nest_matrix: the list of GLOBAL row indices of a field owned by the calling process (i.e. the rows it is expected to insert through ins) and their count. They replace the descriptor-level idiom field_desc(i)%get_local_rows() / field_desc(i)%l2g(...) in user code, which leaked descriptor jargon into the build loop. The high-level tests (glob, rect, builder) are rewritten on the new queries; the low-level CG test intentionally keeps the descriptor path. README updated with the new queries and an example. Author: Simone Staccone (Stack-1) --- base/modules/tools/psb_d_nest_builder_mod.F90 | 39 +++++++++++++++++++ test/nested/README.md | 20 +++++++++- test/nested/psb_d_nest_builder_test.F90 | 15 ++++--- test/nested/psb_d_nest_glob_test.F90 | 17 ++++---- test/nested/psb_d_nest_rect_test.F90 | 17 ++++---- 5 files changed, 87 insertions(+), 21 deletions(-) diff --git a/base/modules/tools/psb_d_nest_builder_mod.F90 b/base/modules/tools/psb_d_nest_builder_mod.F90 index b54782944..345c8d02a 100644 --- a/base/modules/tools/psb_d_nest_builder_mod.F90 +++ b/base/modules/tools/psb_d_nest_builder_mod.F90 @@ -100,6 +100,10 @@ module psb_d_nest_builder_mod procedure, pass(op) :: ins => psb_d_nest_op_ins procedure, pass(op) :: asb => psb_d_nest_op_asb procedure, pass(op) :: free => psb_d_nest_op_free + ! user-friendly queries on the field row distribution (no descriptor + ! jargon needed: these replace field_desc(i)%get_local_rows() / %l2g(...)) + procedure, pass(op) :: get_owned_rows => psb_d_nest_op_get_owned_rows + procedure, pass(op) :: get_owned_row_count => psb_d_nest_op_get_owned_row_count end type psb_d_nest_matrix private @@ -306,6 +310,41 @@ contains op%assembled = .false. end subroutine psb_d_nest_op_free + ! get_owned_rows: GLOBAL indices (in the field index space, 1..field size) + ! of the rows of field i_field owned by this process. This is the list of + ! rows the process is expected to insert through ins: + ! + ! my_rows = nested_matrix%get_owned_rows(1) + ! do k = 1, size(my_rows) + ! global_row = my_rows(k) + ! ... + ! + ! An empty array is returned for an out-of-range field index. + function psb_d_nest_op_get_owned_rows(op, i_field) result(owned_global_rows) + class(psb_d_nest_matrix), intent(in) :: op + integer(psb_ipk_), intent(in) :: i_field + integer(psb_lpk_), allocatable :: owned_global_rows(:) + + if ((i_field < 1) .or. (i_field > op%n_fields) .or. & + & (.not. allocated(op%field_desc))) then + allocate(owned_global_rows(0)) + return + end if + owned_global_rows = op%field_desc(i_field)%get_global_indices(owned=.true.) + end function psb_d_nest_op_get_owned_rows + + ! get_owned_row_count: how many rows of field i_field this process owns + function psb_d_nest_op_get_owned_row_count(op, i_field) result(owned_row_count) + class(psb_d_nest_matrix), intent(in) :: op + integer(psb_ipk_), intent(in) :: i_field + integer(psb_ipk_) :: owned_row_count + + owned_row_count = 0 + if ((i_field < 1) .or. (i_field > op%n_fields) .or. & + & (.not. allocated(op%field_desc))) return + owned_row_count = op%field_desc(i_field)%get_local_rows() + end function psb_d_nest_op_get_owned_row_count + !----------------------------------------------------------------- ! private helpers: growing triplet buffer !----------------------------------------------------------------- diff --git a/test/nested/README.md b/test/nested/README.md index b8d17bb06..b7c6ced8b 100644 --- a/test/nested/README.md +++ b/test/nested/README.md @@ -82,9 +82,27 @@ use psb_d_nest_mod |--------|---------| | `a_glob` | `type(psb_dspmat_type)` — the assembled global operator; pass it to `psb_spmm`, `psb_krylov`, `prec%build` | | `desc_glob` | `type(psb_desc_type)` — the composed global descriptor; pass it wherever a descriptor is expected | -| `field_desc(i)` | `type(psb_desc_type)` — the descriptor of field `i` (query `%get_local_rows()`, `%l2g(...)` to find the rows owned by this process) | +| `field_desc(i)` | `type(psb_desc_type)` — the descriptor of field `i` (advanced use; for the common queries see `get_owned_rows` below) | | `n_fields` | number of fields | +To know which rows it must insert, a process asks the matrix directly — no +descriptor jargon needed: + +```fortran +integer(psb_lpk_), allocatable :: my_rows(:) + +my_rows = nested_matrix%get_owned_rows(1) ! global rows of field 1 owned here +do k = 1, size(my_rows) + global_row = my_rows(k) + ... ! build the entries of this row +end do +``` + +| Query | Result | +|-------|--------| +| `nested_matrix%get_owned_rows(i_field)` | `integer(psb_lpk_), allocatable (:)` — the GLOBAL indices (in the field index space, 1..field size) of the rows of field `i_field` owned by this process | +| `nested_matrix%get_owned_row_count(i_field)` | `integer(psb_ipk_)` — how many rows of field `i_field` this process owns | + Methods (collective over the communicator unless noted): #### `call nested_matrix%init(ctxt, field_sizes, info)` diff --git a/test/nested/psb_d_nest_builder_test.F90 b/test/nested/psb_d_nest_builder_test.F90 index 9a03aceff..78d0a3907 100644 --- a/test/nested/psb_d_nest_builder_test.F90 +++ b/test/nested/psb_d_nest_builder_test.F90 @@ -64,6 +64,7 @@ program psb_d_nest_builder_test real(psb_dpk_) :: insert_value(1) integer(psb_lpk_), allocatable :: entry_rows(:), entry_cols(:) + integer(psb_lpk_), allocatable :: field1_rows(:), field2_rows(:) real(psb_dpk_), allocatable :: entry_vals(:) real(psb_dpk_) :: stop_tol, final_residual, norm_x_exact, solution_error @@ -87,8 +88,10 @@ program psb_d_nest_builder_test end if ! rows owned by this process in each field - field1_local_rows = nested_matrix%field_desc(1)%get_local_rows() - field2_local_rows = nested_matrix%field_desc(2)%get_local_rows() + field1_rows = nested_matrix%get_owned_rows(1) + field2_rows = nested_matrix%get_owned_rows(2) + field1_local_rows = size(field1_rows) + field2_local_rows = size(field2_rows) !--------------------------------------------------------------- ! 2) insert the values, one block at a time (owned rows only) @@ -96,7 +99,7 @@ program psb_d_nest_builder_test ! block (1,1) = 2I allocate(entry_rows(field1_local_rows), entry_cols(field1_local_rows), entry_vals(field1_local_rows)) do i_local_row = 1, field1_local_rows - call nested_matrix%field_desc(1)%l2g(i_local_row, field1_global_row, info) + field1_global_row = field1_rows(i_local_row) entry_rows(i_local_row)=field1_global_row; entry_cols(i_local_row)=field1_global_row entry_vals(i_local_row)=2.0_psb_dpk_ end do @@ -106,7 +109,7 @@ program psb_d_nest_builder_test ! block (2,2) = 2I allocate(entry_rows(field2_local_rows), entry_cols(field2_local_rows), entry_vals(field2_local_rows)) do i_local_row = 1, field2_local_rows - call nested_matrix%field_desc(2)%l2g(i_local_row, field2_global_row, info) + field2_global_row = field2_rows(i_local_row) entry_rows(i_local_row)=field2_global_row; entry_cols(i_local_row)=field2_global_row entry_vals(i_local_row)=2.0_psb_dpk_ end do @@ -117,7 +120,7 @@ program psb_d_nest_builder_test allocate(entry_rows(2*field1_local_rows), entry_cols(2*field1_local_rows), entry_vals(2*field1_local_rows)) entry_idx = 0 do i_local_row = 1, field1_local_rows - call nested_matrix%field_desc(1)%l2g(i_local_row, field1_global_row, info) + field1_global_row = field1_rows(i_local_row) entry_idx = entry_idx + 1 entry_rows(entry_idx) = field1_global_row entry_cols(entry_idx) = field1_global_row @@ -136,7 +139,7 @@ program psb_d_nest_builder_test allocate(entry_rows(2*field2_local_rows), entry_cols(2*field2_local_rows), entry_vals(2*field2_local_rows)) entry_idx = 0 do i_local_row = 1, field2_local_rows - call nested_matrix%field_desc(2)%l2g(i_local_row, field2_global_row, info) + field2_global_row = field2_rows(i_local_row) entry_idx = entry_idx + 1 entry_rows(entry_idx) = field2_global_row entry_cols(entry_idx) = field2_global_row diff --git a/test/nested/psb_d_nest_glob_test.F90 b/test/nested/psb_d_nest_glob_test.F90 index 2b657e180..f12b3f7d1 100644 --- a/test/nested/psb_d_nest_glob_test.F90 +++ b/test/nested/psb_d_nest_glob_test.F90 @@ -69,6 +69,7 @@ program psb_d_nest_glob_test type(psb_d_vect_type) :: x_vec, y_nested, y_monolithic integer(psb_lpk_), allocatable :: entry_rows(:), entry_cols(:) + integer(psb_lpk_), allocatable :: field1_rows(:), field2_rows(:) real(psb_dpk_), allocatable :: entry_vals(:) real(psb_dpk_) :: insert_value(1) real(psb_dpk_) :: mismatch_norm @@ -86,8 +87,10 @@ program psb_d_nest_glob_test if (info /= psb_success_) then if (my_rank==0) write(*,*) 'FAIL: nested_matrix%init info=', info; goto 9999 end if - field1_local_rows = nested_matrix%field_desc(1)%get_local_rows() - field2_local_rows = nested_matrix%field_desc(2)%get_local_rows() + field1_rows = nested_matrix%get_owned_rows(1) + field2_rows = nested_matrix%get_owned_rows(2) + field1_local_rows = size(field1_rows) + field2_local_rows = size(field2_rows) !--------------------------------------------------------------- ! 2) insert the block values (owned rows only) @@ -97,7 +100,7 @@ program psb_d_nest_glob_test & entry_vals(3*field1_local_rows)) entry_idx = 0 do i_local_row = 1, field1_local_rows - call nested_matrix%field_desc(1)%l2g(i_local_row, global_row, info) + global_row = field1_rows(i_local_row) entry_idx = entry_idx + 1 entry_rows(entry_idx) = global_row entry_cols(entry_idx) = global_row @@ -122,7 +125,7 @@ program psb_d_nest_glob_test allocate(entry_rows(field1_local_rows), entry_cols(field1_local_rows), entry_vals(field1_local_rows)) entry_idx = 0 do i_local_row = 1, field1_local_rows - call nested_matrix%field_desc(1)%l2g(i_local_row, global_row, info) + global_row = field1_rows(i_local_row) entry_idx = entry_idx + 1 entry_rows(entry_idx) = global_row entry_cols(entry_idx) = global_row @@ -135,7 +138,7 @@ program psb_d_nest_glob_test allocate(entry_rows(field2_local_rows), entry_cols(field2_local_rows), entry_vals(field2_local_rows)) entry_idx = 0 do i_local_row = 1, field2_local_rows - call nested_matrix%field_desc(2)%l2g(i_local_row, global_row, info) + global_row = field2_rows(i_local_row) entry_idx = entry_idx + 1 entry_rows(entry_idx) = global_row entry_cols(entry_idx) = global_row @@ -158,7 +161,7 @@ program psb_d_nest_glob_test call psb_spall(monolithic_ref, nested_matrix%desc_glob, info, & & nnz=5*nested_matrix%desc_glob%get_local_rows()) do i_local_row = 1, field1_local_rows ! field-1 rows - call nested_matrix%field_desc(1)%l2g(i_local_row, global_row, info) + global_row = field1_rows(i_local_row) insert_value(1) = 2.0_psb_dpk_ call psb_spins(1,[global_row],[global_row],insert_value,monolithic_ref,nested_matrix%desc_glob,info) if (global_row > 1) then @@ -174,7 +177,7 @@ program psb_d_nest_glob_test call psb_spins(1,[global_row],[global_col],insert_value,monolithic_ref,nested_matrix%desc_glob,info) end do do i_local_row = 1, field2_local_rows ! field-2 rows - call nested_matrix%field_desc(2)%l2g(i_local_row, global_row, info) + global_row = field2_rows(i_local_row) global_col = global_row insert_value(1) = 0.3_psb_dpk_ ! B call psb_spins(1,[field_size+global_row],[global_col],insert_value,monolithic_ref,nested_matrix%desc_glob,info) diff --git a/test/nested/psb_d_nest_rect_test.F90 b/test/nested/psb_d_nest_rect_test.F90 index 58f0fc29f..27e621cf0 100644 --- a/test/nested/psb_d_nest_rect_test.F90 +++ b/test/nested/psb_d_nest_rect_test.F90 @@ -65,6 +65,7 @@ program psb_d_nest_rect_test real(psb_dpk_) :: insert_value(1) integer(psb_lpk_), allocatable :: entry_rows(:), entry_cols(:) + integer(psb_lpk_), allocatable :: v_rows(:), q_rows(:) real(psb_dpk_), allocatable :: entry_vals(:) real(psb_dpk_) :: mismatch_norm real(psb_dpk_), parameter :: tolerance = 1.0e-10_psb_dpk_ @@ -82,8 +83,10 @@ program psb_d_nest_rect_test if (info /= psb_success_) then if (my_rank==0) write(*,*) 'FAIL: nested_matrix%init info=', info; goto 9999 end if - v_local_rows = nested_matrix%field_desc(1)%get_local_rows() - q_local_rows = nested_matrix%field_desc(2)%get_local_rows() + v_rows = nested_matrix%get_owned_rows(1) + q_rows = nested_matrix%get_owned_rows(2) + v_local_rows = size(v_rows) + q_local_rows = size(q_rows) !--------------------------------------------------------------- ! 2) insert the blocks (owned rows only) @@ -92,7 +95,7 @@ program psb_d_nest_rect_test allocate(entry_rows(3*v_local_rows), entry_cols(3*v_local_rows), entry_vals(3*v_local_rows)) entry_idx = 0 do i_local_row = 1, v_local_rows - call nested_matrix%field_desc(1)%l2g(i_local_row, v_global_row, info) + v_global_row = v_rows(i_local_row) entry_idx = entry_idx + 1 entry_rows(entry_idx) = v_global_row entry_cols(entry_idx) = v_global_row @@ -117,7 +120,7 @@ program psb_d_nest_rect_test allocate(entry_rows(v_local_rows), entry_cols(v_local_rows), entry_vals(v_local_rows)) entry_idx = 0 do i_local_row = 1, v_local_rows - call nested_matrix%field_desc(1)%l2g(i_local_row, v_global_row, info) + v_global_row = v_rows(i_local_row) entry_idx = entry_idx + 1 entry_rows(entry_idx) = v_global_row entry_cols(entry_idx) = mod(v_global_row-1_psb_lpk_, q_size)+1 @@ -130,7 +133,7 @@ program psb_d_nest_rect_test allocate(entry_rows(2*q_local_rows), entry_cols(2*q_local_rows), entry_vals(2*q_local_rows)) entry_idx = 0 do i_local_row = 1, q_local_rows - call nested_matrix%field_desc(2)%l2g(i_local_row, q_global_row, info) + q_global_row = q_rows(i_local_row) entry_idx = entry_idx + 1 entry_rows(entry_idx) = q_global_row entry_cols(entry_idx) = q_global_row @@ -156,7 +159,7 @@ program psb_d_nest_rect_test call psb_spall(monolithic_ref, nested_matrix%desc_glob, info, & & nnz=6*nested_matrix%desc_glob%get_local_rows()) do i_local_row = 1, v_local_rows ! V rows - call nested_matrix%field_desc(1)%l2g(i_local_row, v_global_row, info) + v_global_row = v_rows(i_local_row) insert_value(1)=2.0_psb_dpk_ call psb_spins(1,[v_global_row],[v_global_row],insert_value,monolithic_ref,nested_matrix%desc_glob,info) if (v_global_row>1) then @@ -172,7 +175,7 @@ program psb_d_nest_rect_test call psb_spins(1,[v_global_row],[q_col],insert_value,monolithic_ref,nested_matrix%desc_glob,info) end do do i_local_row = 1, q_local_rows ! Q rows - call nested_matrix%field_desc(2)%l2g(i_local_row, q_global_row, info) + q_global_row = q_rows(i_local_row) insert_value(1)=0.3_psb_dpk_ call psb_spins(1,[v_size+q_global_row],[q_global_row], insert_value,monolithic_ref,nested_matrix%desc_glob,info) ! col q call psb_spins(1,[v_size+q_global_row],[q_global_row+q_size],insert_value,monolithic_ref,nested_matrix%desc_glob,info) ! col q+nQ