[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)
nested_matrix_type
Stack-1 2 weeks ago
parent 8e02a99a11
commit fd60bb8d7f

@ -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
!-----------------------------------------------------------------

@ -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)`

@ -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

@ -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)

@ -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

Loading…
Cancel
Save