The main documentation of the MatVec_ELL_Matrix Procedure contains additional explanation of this code listing.
subroutine MatVec_ELL_Matrix (ELLM, MV_in, MV_out) ! Input variables. ! ELL Matrix to be multiplied. type(ELL_Matrix_type), intent(inout) :: ELLM ! Mathematic Vector to be multiplied. type(Mathematic_Vector_type), intent(inout) :: MV_in ! Output variable. ! Result of dot product. type(Mathematic_Vector_type), intent(inout) :: MV_out ! Internal variables. type(integer) :: i ! Loop counter. type(integer) :: OV_match ! The OV match for ELLM. type(real,2) :: MV_in_Values_Array ! Temp for collected MV_in Values. type(real) :: random_real ! Random temporary. !~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ! Verify requirements. VERIFY(Valid_State(ELLM),5) ! ELLM is valid. VERIFY(Valid_State(MV_in),5) ! MV_in is valid. VERIFY(Valid_State(MV_out),5) ! MV_out is valid. ! MV_in has same Structure as ELLM Column_Structure. VERIFY(ASSOCIATED(ELLM%Column_Structure,MV_in%Structure),5) ! MV_out has same Structure as ELLM Row_Structure. VERIFY(ASSOCIATED(ELLM%Row_Structure,MV_out%Structure),5) VERIFY(Number_of_OVs_in_an_MV==4,5) ! 4 is assumed in this procedure. ! Check to see if Index needs to be updated. if (.not. ELLM%Index_is_Updated) then call Finalize (ELLM%Index) call Initialize (ELLM%Index, ELLM%Column_Structure, & ELLM%Row_Structure, Many_of_One_Array=ELLM%Columns) ELLM%Index_is_Updated = .true. call RANDOM_NUMBER (random_real) ELLM%Index_Match_Number = changetype(integer, random_real*1.e9) end if ! ### SPRONG -- need to step through the logic in this routine, ! ### especially to make sure that MV_in%DV is updated correctly ! ### (and not updated when it shouldn't be). ! Check to see if MV_in already has an Overlapped_Vector for this Matrix. OV_match = 0 do i = 1, Number_of_OVs_in_an_MV if (Initialized(MV_in%OV(i))) then if (ELLM%Index_Match_Number == MV_in%Index_Match_Number(i)) then OV_match = i end if end if end do ! Create MV_in%OV, MV_in%DV if needed. if (OV_match == 0) then ! Determine which slot to put new OV in. do i = 1, Number_of_OVs_in_an_MV if (Initialized(MV_in%OV(i))) then OV_match = i + 1 end if end do if (OV_match == 0 .or. OV_match == 5) then OV_match = 1 end if ! Set up MV_in%DV if necessary. if (.not.Initialized(MV_in%DV)) then call Initialize (MV_in%DV, MV_in%Structure, MV_in%Dimensionality, & MV_in%Name) end if ! Set up MV_in%OV(OV_match). if (Initialized(MV_in%OV(OV_match))) call Finalize (MV_in%OV(OV_match)) MV_in%DV = MV_in%Values call Initialize (MV_in%OV(OV_match), MV_in%DV, ELLM%Index, MV_in%Name) MV_in%Index_Match_Number(OV_match) = ELLM%Index_Match_Number end if ! Update MV_in%DV and MV_in%OV if needed. call Update_DV (MV_in) MV_in%OV(OV_match) = MV_in%DV ! Extract the values from MV_in%OV. call Initialize (MV_in_Values_Array, Length_PE(MV_in%Structure), & ELLM%Max_Nonzeros) MV_in_Values_Array = MV_in%OV(OV_match) ! Calculate the global matrix-vector product. MV_out%Values(:) = SUM(ELLM%Values * MV_in_Values_Array, 2) ! Unset the updated? variables. call Set_Not_Up_to_Date (MV_out) ! Clean up. call Finalize (MV_in_Values_Array) ! Verify guarantees - none. return end subroutine MatVec_ELL_Matrix